€•¤Œsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ%/translations/zh_CN/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/zh_TW/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/it_IT/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/ja_JP/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/ko_KR/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/pt_BR/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/sp_SP/trace/user_events”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ%user_events: User-based Event Tracing”h]”hŒ%user_events: User-based Event Tracing”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³Œ?/var/lib/git/docbuild/linux/Documentation/trace/user_events.rst”h´KubhŒ field_list”“”)”}”(hhh]”hŒfield”“”)”}”(hhh]”(hŒ field_name”“”)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hh×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÕhhÒh³hÊh´KubhŒ field_body”“”)”}”(hŒBeau Belgrave ”h]”hŒ paragraph”“”)”}”(hŒ Beau Belgrave”h]”hŒ Beau Belgrave”…””}”(hhíh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Khhçubah}”(h]”h ]”h"]”h$]”h&]”uh1håhhÒubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÐh³hÊh´KhhÍh²hubah}”(h]”h ]”h"]”h$]”h&]”uh1hËhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒOverview”h]”hŒOverview”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj h²hh³hÊh´Kubhì)”}”(hŒÑUser based trace events allow user processes to create events and trace data that can be viewed via existing tools, such as ftrace and perf. To enable this feature, build your kernel with CONFIG_USER_EVENTS=y.”h]”hŒÑUser based trace events allow user processes to create events and trace data that can be viewed via existing tools, such as ftrace and perf. To enable this feature, build your kernel with CONFIG_USER_EVENTS=y.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´K hj h²hubhì)”}”(hŒ¤Programs can view status of the events via /sys/kernel/tracing/user_events_status and can both register and write data out via /sys/kernel/tracing/user_events_data.”h]”hŒ¤Programs can view status of the events via /sys/kernel/tracing/user_events_status and can both register and write data out via /sys/kernel/tracing/user_events_data.”…””}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´K hj h²hubhì)”}”(hX*Programs can also use /sys/kernel/tracing/dynamic_events to register and delete user based events via the u: prefix. The format of the command to dynamic_events is the same as the ioctl with the u: prefix applied. This requires CAP_PERFMON due to the event persisting, otherwise -EPERM is returned.”h]”hX*Programs can also use /sys/kernel/tracing/dynamic_events to register and delete user based events via the u: prefix. The format of the command to dynamic_events is the same as the ioctl with the u: prefix applied. This requires CAP_PERFMON due to the event persisting, otherwise -EPERM is returned.”…””}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Khj h²hubhì)”}”(hX¯Typically programs will register a set of events that they wish to expose to tools that can read trace_events (such as ftrace and perf). The registration process tells the kernel which address and bit to reflect if any tool has enabled the event and data should be written. The registration will give back a write index which describes the data when a write() or writev() is called on the /sys/kernel/tracing/user_events_data file.”h]”hX¯Typically programs will register a set of events that they wish to expose to tools that can read trace_events (such as ftrace and perf). The registration process tells the kernel which address and bit to reflect if any tool has enabled the event and data should be written. The registration will give back a write index which describes the data when a write() or writev() is called on the /sys/kernel/tracing/user_events_data file.”…””}”(hjHh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Khj h²hubhì)”}”(hŒ~The structures referenced in this document are contained within the /include/uapi/linux/user_events.h file in the source tree.”h]”hŒ~The structures referenced in this document are contained within the /include/uapi/linux/user_events.h file in the source tree.”…””}”(hjVh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Khj h²hubhì)”}”(hŒ‹**NOTE:** *Both user_events_status and user_events_data are under the tracefs filesystem and may be mounted at different paths than above.*”h]”(hŒstrong”“”)”}”(hŒ **NOTE:**”h]”hŒNOTE:”…””}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhhjdubhŒ ”…””}”(hjdh²hh³Nh´NubhŒemphasis”“”)”}”(hŒ*Both user_events_status and user_events_data are under the tracefs filesystem and may be mounted at different paths than above.*”h]”hŒBoth user_events_status and user_events_data are under the tracefs filesystem and may be mounted at different paths than above.”…””}”(hj~h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j|hjdubeh}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´K hj h²hubeh}”(h]”Œoverview”ah ]”h"]”Œoverview”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ Registering”h]”hŒ Registering”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjšh²hh³hÊh´K$ubhì)”}”(hŒ‘Registering within a user process is done via ioctl() out to the /sys/kernel/tracing/user_events_data file. The command to issue is DIAG_IOCSREG.”h]”hŒ‘Registering within a user process is done via ioctl() out to the /sys/kernel/tracing/user_events_data file. The command to issue is DIAG_IOCSREG.”…””}”(hj«h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´K%hjšh²hubhì)”}”(hŒThis command takes a packed struct user_unreg as an argument::”h]”hŒ=This command takes a packed struct user_unreg as an argument:”…””}”(hjŸh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´KÂhj€h²hubjÈ)”}”(hXƒstruct user_unreg { /* Input: Size of the user_unreg structure being used */ __u32 size; /* Input: Bit to unregister */ __u8 disable_bit; /* Input: Reserved, set to 0 */ __u8 __reserved; /* Input: Reserved, set to 0 */ __u16 __reserved2; /* Input: Address to unregister */ __u64 disable_addr; } __attribute__((__packed__));”h]”hXƒstruct user_unreg { /* Input: Size of the user_unreg structure being used */ __u32 size; /* Input: Bit to unregister */ __u8 disable_bit; /* Input: Reserved, set to 0 */ __u8 __reserved; /* Input: Reserved, set to 0 */ __u16 __reserved2; /* Input: Address to unregister */ __u64 disable_addr; } __attribute__((__packed__));”…””}”hj­sbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´KÄhj€h²hubhì)”}”(hŒLThe struct user_unreg requires all the above inputs to be set appropriately.”h]”hŒLThe struct user_unreg requires all the above inputs to be set appropriately.”…””}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´KÕhj€h²hubjè)”}”(hhh]”(jí)”}”(hŒ5size: This must be set to sizeof(struct user_unreg). ”h]”hì)”}”(hŒ4size: This must be set to sizeof(struct user_unreg).”h]”hŒ4size: This must be set to sizeof(struct user_unreg).”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´K×hjÌubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjÉh²hh³hÊh´Nubjí)”}”(hŒndisable_bit: This must be set to the bit to disable (same bit that was previously registered via enable_bit). ”h]”hì)”}”(hŒmdisable_bit: This must be set to the bit to disable (same bit that was previously registered via enable_bit).”h]”hŒmdisable_bit: This must be set to the bit to disable (same bit that was previously registered via enable_bit).”…””}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´KÙhjäubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjÉh²hh³hÊh´Nubjí)”}”(hŒxdisable_addr: This must be set to the address to disable (same address that was previously registered via enable_addr). ”h]”hì)”}”(hŒwdisable_addr: This must be set to the address to disable (same address that was previously registered via enable_addr).”h]”hŒwdisable_addr: This must be set to the address to disable (same address that was previously registered via enable_addr).”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´KÜhjüubah}”(h]”h ]”h"]”h$]”h&]”uh1jìhjÉh²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j„j…uh1jçh³hÊh´K×hj€h²hubhì)”}”(hŒ»**NOTE:** Events are automatically unregistered when execve() is invoked. During fork() the registered events will be retained and must be unregistered manually in each process if wanted.”h]”(ji)”}”(hŒ **NOTE:**”h]”hŒNOTE:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhhjubhŒ² Events are automatically unregistered when execve() is invoked. During fork() the registered events will be retained and must be unregistered manually in each process if wanted.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Kßhj€h²hubeh}”(h]”Œ unregistering”ah ]”h"]”Œ unregistering”ah$]”h&]”uh1hµhh·h²hh³hÊh´K»ubh¶)”}”(hhh]”(h»)”}”(hŒStatus”h]”hŒStatus”…””}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj>h²hh³hÊh´Käubhì)”}”(hŒÞWhen tools attach/record user based events the status of the event is updated in realtime. This allows user programs to only incur the cost of the write() or writev() calls when something is actively attached to the event.”h]”hŒÞWhen tools attach/record user based events the status of the event is updated in realtime. This allows user programs to only incur the cost of the write() or writev() calls when something is actively attached to the event.”…””}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Kåhj>h²hubhì)”}”(hŒÆThe kernel will update the specified bit that was registered for the event as tools attach/detach from the event. User programs simply check if the bit is set to see if something is attached or not.”h]”hŒÆThe kernel will update the specified bit that was registered for the event as tools attach/detach from the event. User programs simply check if the bit is set to see if something is attached or not.”…””}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Kéhj>h²hubhì)”}”(hŒžAdministrators can easily check the status of all registered events by reading the user_events_status file directly via a terminal. The output is as follows::”h]”hŒAdministrators can easily check the status of all registered events by reading the user_events_status file directly via a terminal. The output is as follows:”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Kíhj>h²hubjÈ)”}”(hŒ:Name [# Comments] ... Active: ActiveCount Busy: BusyCount”h]”hŒ:Name [# Comments] ... Active: ActiveCount Busy: BusyCount”…””}”hjysbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´Kðhj>h²hubhì)”}”(hŒMFor example, on a system that has a single event the output looks like this::”h]”hŒLFor example, on a system that has a single event the output looks like this:”…””}”(hj‡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Köhj>h²hubjÈ)”}”(hŒtest Active: 1 Busy: 0”h]”hŒtest Active: 1 Busy: 0”…””}”hj•sbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´Køhj>h²hubhì)”}”(hŒNIf a user enables the user event via ftrace, the output would change to this::”h]”hŒMIf a user enables the user event via ftrace, the output would change to this:”…””}”(hj£h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´Kýhj>h²hubjÈ)”}”(hŒ(test # Used by ftrace Active: 1 Busy: 1”h]”hŒ(test # Used by ftrace Active: 1 Busy: 1”…””}”hj±sbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´Kÿhj>h²hubeh}”(h]”Œstatus”ah ]”h"]”Œstatus”ah$]”h&]”uh1hµhh·h²hh³hÊh´Käubh¶)”}”(hhh]”(h»)”}”(hŒ Writing Data”h]”hŒ Writing Data”…””}”(hjÊh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjÇh²hh³hÊh´Mubhì)”}”(hŒéAfter registering an event the same fd that was used to register can be used to write an entry for that event. The write_index returned must be at the start of the data, then the remaining data is treated as the payload of the event.”h]”hŒéAfter registering an event the same fd that was used to register can be used to write an entry for that event. The write_index returned must be at the start of the data, then the remaining data is treated as the payload of the event.”…””}”(hjØh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´MhjÇh²hubhì)”}”(hXFor example, if write_index returned was 1 and I wanted to write out an int payload of the event. Then the data would have to be 8 bytes (2 ints) in size, with the first 4 bytes being equal to 1 and the last 4 bytes being equal to the value I want as the payload.”h]”hXFor example, if write_index returned was 1 and I wanted to write out an int payload of the event. Then the data would have to be 8 bytes (2 ints) in size, with the first 4 bytes being equal to 1 and the last 4 bytes being equal to the value I want as the payload.”…””}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´M hjÇh²hubhì)”}”(hŒ%In memory this would look like this::”h]”hŒ$In memory this would look like this:”…””}”(hjôh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´MhjÇh²hubjÈ)”}”(hŒint index; int payload;”h]”hŒint index; int payload;”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´MhjÇh²hubhì)”}”(hŒáUser programs might have well known structs that they wish to use to emit out as payloads. In those cases writev() can be used, with the first vector being the index and the following vector(s) being the actual event payload.”h]”hŒáUser programs might have well known structs that they wish to use to emit out as payloads. In those cases writev() can be used, with the first vector being the index and the following vector(s) being the actual event payload.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´MhjÇh²hubhì)”}”(hŒ+For example, if I have a struct like this::”h]”hŒ*For example, if I have a struct like this:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´MhjÇh²hubjÈ)”}”(hŒ^struct payload { int src; int dst; int flags; } __attribute__((__packed__));”h]”hŒ^struct payload { int src; int dst; int flags; } __attribute__((__packed__));”…””}”hj,sbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´MhjÇh²hubhì)”}”(hŒ4It's advised for user programs to do the following::”h]”hŒ5It’s advised for user programs to do the following:”…””}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´M hjÇh²hubjÈ)”}”(hŒÃstruct iovec io[2]; struct payload e; io[0].iov_base = &write_index; io[0].iov_len = sizeof(write_index); io[1].iov_base = &e; io[1].iov_len = sizeof(e); writev(fd, (const struct iovec*)io, 2);”h]”hŒÃstruct iovec io[2]; struct payload e; io[0].iov_base = &write_index; io[0].iov_len = sizeof(write_index); io[1].iov_base = &e; io[1].iov_len = sizeof(e); writev(fd, (const struct iovec*)io, 2);”…””}”hjHsbah}”(h]”h ]”h"]”h$]”h&]”j×jØuh1jÇh³hÊh´M"hjÇh²hubhì)”}”(hŒM**NOTE:** *The write_index is not emitted out into the trace being recorded.*”h]”(ji)”}”(hŒ **NOTE:**”h]”hŒNOTE:”…””}”(hjZh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhhjVubhŒ ”…””}”(hjVh²hh³Nh´Nubj})”}”(hŒC*The write_index is not emitted out into the trace being recorded.*”h]”hŒAThe write_index is not emitted out into the trace being recorded.”…””}”(hjlh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j|hjVubeh}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´M,hjÇh²hubeh}”(h]”Œ writing-data”ah ]”h"]”Œ writing data”ah$]”h&]”uh1hµhh·h²hh³hÊh´Mubh¶)”}”(hhh]”(h»)”}”(hŒ Example Code”h]”hŒ Example Code”…””}”(hj‹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjˆh²hh³hÊh´M/ubhì)”}”(hŒ'See sample code in samples/user_events.”h]”hŒ'See sample code in samples/user_events.”…””}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hëh³hÊh´M0hjˆh²hubeh}”(h]”Œ example-code”ah ]”h"]”Œ example code”ah$]”h&]”uh1hµhh·h²hh³hÊh´M/ubeh}”(h]”Œ$user-events-user-based-event-tracing”ah ]”h"]”Œ%user_events: user-based event tracing”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jÚŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j´j±j—j”j,j)jXjUjj|j$j!j}jzj;j8jÄjÁj…j‚j¬j©uŒ nametypes”}”(j´‰j—‰j,‰jX‰j‰j$‰j}‰j;‰jĉj…‰j¬‰uh}”(j±h·j”j j)jšjUj&j|j[j!j‚jzj/j8j€jÁj>j‚jÇj©jˆuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.