XLATE(4)XLATE(4) NAME xlate - Address translation object file section of an ELF object SYNOPSIS #include <elf.h> #include <libelf.h> #include <cmplrs/xlate.h> DESCRIPTION An address translation section is created by commands such as cord(1) to allow other tools such as dbx(1) and dis(1) to accurately display information about the program text. There can be a maximum of two address translation sections (one of each section type) in a given a.out or DSO. Translation information is held in ELF sections with sh_type SHT_MIPS_XLATE (section name .MIPS.Xlate), SHT_MIPS_XLATE_DEBUG (not currently generated by cord) or SHT_MIPS_XLATE_OLD (normal section name .MIPS.Xlate_old). There should be at most one section marked SHT_MIPS_XLATE. There could be multiple sections marked SHT_MIPS_XLATE_DEBUG. Each address translation section should have a unique name: sections are accessed via the section name. Nothing in the library enforces this naming rule (libelfutil does not create sections). Section .MIPS.Xlate contains translation information giving the address translations from the program as executed to and from the original program text. This is the table generally used. When there are multiple translations applied to the program text, this gives the overall translation map, translating from the original before any translations to the final executable text after all translations. This is the translation information used by dbx and dis. You cannot execute strip(1) on this information because it would make stack tracebacks through the text impossible. Section .MIPS.Xlate_old contains translation information given the original translation (as created by cord(1)) if the program or DSO has also been processed by pixie. That is, after execution of cord and pixie, there may be two translation tables in the Elf file (the cord- created .MIPS.Xlate is renamed .MIPS.Xlate_old by pixie.). The format of the two sections is the same. In an Elf file, the section data must be properly aligned; the Elf section header must show an alignment of at least 4 for a 32-bit Elf file and at least 8 for a 64-bit Elf file. A translation section conceptually is a table with one row per instruction (text) and two entries per row. The first entry is the address of an instruction in the modified text (the instructions that will be executed). The second entry is the address of an instruction in the input-text of the translation (the text before translation). Such a table would, if physically present, be inconveniently large. The first size reduction is based on the observation that (given the translations performed by the tools), a table with four entries in each row will be more compact. Most translations involve a range of instructions moved together. newaddress, new-addr-range, oldaddress, old-addr-range (The new- and old- range values need not be identical in a given row. Consider the additional instructions in the longer range to be an extension of the last instruction of the shorter range.) The actual data on disk is more compact than a simple encoding of the 4-entry- per-row table would be but the 4-entry-per-row table is easily created from the data on disk. The rest of this man page includes details on how the data is recorded on disk. There are two versions in use. Version 1 has a common header format used for both 64 and 32 bit applications. Version 2 has distinct headers for each size executable/DSO (the headers have the same fields but the address fields and length fields are larger in the header for 64-bit applications). Version 1 and Version 2 have nearly identical field names: the difference is that Version 1 has fields named hd_upper32_bits_old and hd_upper32_bits_new and hd_is64_bit, whereas Version 2 has no such fields. A translation section (all three formats) as stored on disk consists of the following: Translation Header N Translation Block Headers N Translation Blocks (optionally) Register Information Block The Translation Header and each Translation Block Header is a fixed size. Each Translation Block is a fixed size. The Translation Header describes the rest of the section. Each Translation Block Header describes an individual Translation Block. Each Translation Block describes a portion of the implicit four-entry table mentioned above. The structures used are defined in /usr/include/cmplrs/xlate.h. The meaning of the fields in those structures are given below. You must install the compiler_eoe.hdr.internal subsystem to get the headers necessary to work with the xlate functions and leb128 functions they call. Translation Header Version 2 - 32 This describes the structure, xlate_header32_v2_s. hd_version Has the value XLATE_TB_32_V2 (5). hd_table_kind The value is one of xlate_tk_general (0), xlate_tk_preserve_size (1), or xlate_tk_preserve_order (2). The value here identifies the format of the array of "Translation Block"s. See the "Translation Block Version 2" section description below. hd_block_size The number of bytes in each "Translation Block Version 2". The number of bytes in each block is fixed, but the number of entries in each block varies and there may be a few unused bytes at the end of any given block. hd_num_blocks The number of instances of "Translation Block Header Version 2" and the number of instances of "Translation Block Version 2" not including the "Register Information Block (all versions)". hd_num_entries The number of range entries in the complete section, counting all range entries in each "Translation Block Version 2". hd_new_addr_low The text address of the new (transformed) text. hd_new_addr_high The text address one past the highest address in the new (transformed) text. hd_old_addr_low The text address of the old (pre transform) text. hd_old_addr_high The text address one past the highest address of the old (pre transform) text. hd_data_moved If the data section was moved (relative to text) this gives the amount of movement. hd_startup_fwa The startup First Word Address is information created by pixie(1) describing the pixie startup code beginning address. hd_startup_lwa The startup Last Word Address is information created by pixie(1) describing the address just past the end of pixie startup code. hd_old_text_exists This is 1 if the untransformed text is in the executable or DSO. This is 0 if there is no such section. cord(1)ed DSOs normally do not contain a copy of the untransformed text. hd_old_text_alloc This is 1 if the original text (before any transformation) is in a loadable segment (see the elf Program Header documentation). hd_reg_info_size If non-zero, then this section has a final block (of size hd_regInfoSize bytes) (following the "Translation Block Version 2" array) which contains the actual register information. Such information is created by pixie for example, since pixie needs to use some registers itself and therefore transforms the text to not use such registers. The information in the "Register Information Block (all versions)" describes the physical location in memory of the registers pixie has appropriated. These descriptions thus give the location of "shadow" registers in memory which contain what the untransformed text used as real registers. Translation Block Header Version 2 The fields in a block header give a way to quickly determine which block(s) hold information on range entries of interest. This describes xlate_blockheader32_v2_s and xlate_blockheader64_v2_s (the fields contained are 32 and 64 bits, respectively). bh_first_new_addr The new address of the first entry of the corresponding "Translation Block". bh_first_old_addr The old address of the first entry of the corresponding "Translation Block". bh_num_entries The number of entries actually put into this block. Translation Block Version 2 The contents are the same for both 32 and 64 bit versions, though for 32 bit versions the numbers represented are 32 bit numbers. The initial address delta (for each of the following cases) is a delta from the corresponding address in the applicable "Translation Block Header Version 2". Each block is composed of a group of translation block entries. A translation block entry is not fixed length. Each translation block entry represents a single 4-entry row in the address-range-table described earlier. There are 3 different variable-length entry formats. All entries have the same format. The header field hd_table_kind identifies the format applicable to every "Translation Block". Every number recorded is recorded in a variable length format known as leb_128 format. The leb_128 format is variable length (and can record any size number) but 64-bit values will exist in a block only if the block is part of a 64-bit executable or DSO translation table. That number format is described defined and described in the Dwarf Version 2 and libdwarf documents. Each address or range is shifted right 2 bits before being written since instructions (and byte ranges, interchangeably also called lengths) will always be a multiple of 4. The assumptions which apply equally to all translation translation block formats is that the new address is increasing and that the new- address plus the new-range of one range is equal to the new-address of the next range with no gap. If this is not true then the translations may not always be recorded correctly. The following describes each "Translation Block" entry. xlate_tk_preserve_order This case is defined such that transformations leave the text in the original order so both old and new addresses must increase. The entry contents recorded are an unsigned new range followed by the unsigned old range. xlate_tk_preserve_size This case it is defined such that transformations leave the length of the text unchanged (but the old address may increase or decrease). The entry contents recorded are an unsigned range (of the old and new addresses since the values must be identical by definition of xlate_tk_preserve_size) followed by a signed delta of the previous old address. xlate_tk_general In this case, there are no guarantees about ordering of the old_address or value of the old_range in the transformations. The new address/new range sets must still increase with no gaps, so the block format does cannot record (and the library does not allow) truly general transformations (such as where the new address is not monotonic or where there are gaps in the new address). The entry contents recorded are an unsigned new range value followed by a signed delta of the old address followed by a signed "new_range - old_range". Translation Header Version 2 - 64 bits This describes the structure xlate_header64_v2_s. hd_version Has the value XLATE_TB_64_V2 (6). The rest of the 64-bit format is identical to xlate_header32_v2_s except that certain data items are 64 bits. Translation Header Version 1 This describes the structure xlate_header_v1_s. hd_version Has the value XLATE_TB_CLASS_MAIN_V1 (1) if this is a SHT_MIPS_XLATE section. Has the value XLATE_TB_CLASS_COPY_V1 (2) if this is a SHT_MIPS_XLATE_DEBUG section and there has been only one translation (not two or more). The values 3 and 4 were reserved but never used. If the value is XLATE_TB_CLASS_COPY_V1, then this section is a duplicate of the SHT_MIPS_XLATE. A consequence of all this is that the SHT_MIPS_XLATE_DEBUG section is not useful. hd_table_kind The value is one of xlate_tk_general (0), xlate_tk_preserve_size (1), or xlate_tk_preserve_order (2). This value identifies the format of the array of "Translation Block"s See the following "Translation Block Version 1" section description below. hd_is64bit The value is 0 for 32-bit executables and DSOs. The value is 1 for 64-bit executables and DSOs. hd_upper32BitsNew Is 0 for 32 bit executables and DSOs. For 64 bit executables and DSOs, this is the upper 32 bits of the new addresses in the table. All the addresses in each "Translation Block Header Version 1" and "Translation Block Version 1" describe only the least significant 32 bits of 64 bit addresses. hd_upper32_bits_old Is 0 for 32 bit executables and DSOs. For 64 bit executables and DSOs, this is the upper 32 bits of the old addresses in the table. All the addresses in each "Translation Block Header Version 1" and "Translation Block Version 1" describe only the least significant 32 bits of 64 bit addresses. hd_block_size The number of bytes in each "Translation Block Version 1". The number of bytes in each block is fixed, but the number of entries in each block varies and there may be a few unused bytes at the end of any given block. hd_num_blocks The number of instances of "Translation Block Header Version 1" and the number of instances of "Translation Block Version 1" not including the "Register Information Block (all versions)" . hd_num_entries The number of range entries in the complete section, counting all range entries in each "Translation Block Version 1". hd_new_addr_low The least significant 32 bits of text address of the new (transformed) text. hd_new_addr_high The least significant 32 bits of the text address one past the end of of the new (transformed) text. hd_old_addr_low The least significant 32 bits of the text address of the old (pre transform) text. hd_old_addr_high The least significant 32 bits of the text address one past the end of the old (pre transform) text. hd_data_moved If the data section was moved (relative to text) this gives the least significant 32 bits of the amount of movement. Movement greater than 32 bits cannot be properly described. hd_startup_fwa The startup First Word Address is information created by pixie(1) describing least significant 32 bits of the pixie startup code beginning address. hd_startup_lwa The startup Last Word Address is information created by pixie(1) describing least significant 32 bits of the address just past the end of pixie startup code. hd_old_text_exists This is 1 if the untransformed text is in the executable or DSO. This is 0 if there is no such section. cord(1)ed DSOs normally do not contain a copy of the untransformed text. hd_old_text_alloc This is 1 if the original text (before any transformation) is in a loadable segment (see the elf Program Header documentation). hd_reg_info_size If non-zero, then this section has a final block (of size hd_regInfoSize bytes) (following the "Translation Block Version 1" array) which contains the actual register information. Such information is created by pixie for example, since pixie needs to use some registers itself and therefore, transforms the text to not use such registers. The information in the "Register Information Block (all versions)" describes the physical location in memory of the registers pixie has appropriated. These descriptions thus give the location of "shadow" registers in memory which contain what the untransformed text used as real registers. Translation Block Header Version 1 The fields in a block header give a way to quickly determine which block(s) hold information on range entries of interest. The following describes xlate_blockheader_v1_s. bh_first_new_addr The low 32 bits of the new address in the first entry of the corresponding "Translation Block". bh_first_old_addr The low 32 bits of the old address in the first entry of the corresponding "Translation Block". bh_num_entries The number of entries actually put into this block. Translation Block Version 1 The initial address delta (for each of the following cases) is a delta from the corresponding address in the applicable "Translation Block Header Version 1". In version 1 blocks, the 0th entry is garbage which must be skipped. Each block is composed of a group of translation block entries. A translation block entry is not fixed length. Each translation block entry represents a single 4-entry row in the address-range-table described earlier. There are 3 different variable-length entry formats. All entries have the same format. The header field, hd_table_kind, identifies the format applicable to every "Translation Block". Every number recorded is recorded in a variable length format known as leb_128 format. Every number recorded is a 32 bit number (one must OR on the hd_new_addr_high and hd_old_addr_high to complete addresses in a 64-bit executable or DSO). That number format is described defined and described in the Dwarf Version 2 and libdwarf documents. Each address or range is shifted right 2 bits before being written since instructions (and byte ranges) will always be a multiple of 4. The following describes each "Translation Block" entry format. xlate_tk_preserve_order This case is defined such that transformations leave the text in the original order so both old and new addresses must increase. The entry contents recorded are an unsigned new range followed an unsigned old range. xlate_tk_preserve_size This case it is defined such that transformations leave the length of the text unchanged (but the old address may increase or decrease). The entry contents recorded are an unsigned range (of both old and new addresses) followed by a signed delta of the previous old address. xlate_tk_general Never can appear anywhere so it is left undefined. Register Information Block (all versions) This block is used to describe the location of pseudo-registers: memory locations that contain the value of what were, in the untranslated source, registers but whose value is now in memory. This block contains a direct encoding of three fields of the Dwarf_Loc structure. The three fields are named lr_atom, lr_number, lr_number2 in that document. In the xlate creation call the arguments are named op, val1, and val2 respectively. The operation codes described here (such as DW_CFA_offset) are the only codes supported by xlate functions and are a subset of the codes supported by libdwarf. The following are the DWARF op codes supported and their encoding in the block. DW_CFA_advance_loc op is recorded as the high 2 bits of a byte. val1 >>2 is recorded as the low 6 bits of the byte (so the maximum advance is 64 instructions). DW_CFA_offset op is recorded as the high 2 bits of a byte. The low 6 bits of the byte is val1, a register number. val2, an offset, is recorded as an unsigned leb_128 number starting in the next byte. (There is a bug in IRIX6.2: val1 is recorded rather than val2 in the second leb_128 number) DW_CFA_restore op is recorded as the high 2 bits of a byte. The low 6 bits of val1 are a register numbner recorded in the same byte. DW_CFA_set_loc op is recorded in the first byte of the value. For version 1 and 64bit table version 2 the next 8 bytes are 64 bits of the value val1. For a version 2 32bit table the next 4 bytes of the value is the address (the least significant 32 bits of val1). DW_CFA_advance_loc1 op is recorded in the first byte of the value. val1 is shifted right 2 bits and stored in the low 6 bits of the first byte. DW_CFA_advance_loc2 op is recorded in the first byte of the value. val1 is shifted right 2 bits. The resulting 16 bits follow the op. In a version 1 table, the 16 bits are stored little-endian (least significant byte at lowest address) which is contrary to the way they are recorded in normal SGI DWARF. In a version 2 table the 16 bits are recorded in big-endian (most significant byte at lowest address) form (just as in SGI DWARF). DW_CFA_advance_loc4 op is recorded in the first byte of the value. val1 is shifted right 2 bits. The resulting 32 bits follow the op. In a version 1 table, the 32 bits are stored little-endian (least significant byte at lowest address) which is contrary to the way they are recorded in normal SGI DWARF. In a version 2 table the 32 bits are recorded in big-endian (most significant byte at lowest address) form (just as in SGI DWARF). DW_CFA_offset_extended op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. Then val2 is stored (after right shifting by 2) as an unsigned leb_128 number. DW_CFA_def_cfa op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. Then val2 is stored (after right shifting by 2) as an unsigned leb_128 number. DW_CFA_restore_extended op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. DW_CFA_undefined op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. DW_CFA_same_value op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. DW_CFA_def_cfa_register op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. DW_CFA_register op is recorded in the first byte of the value. Then val1 is stored as an unsigned leb_128 number. Then val2 is stored as an unsigned leb_128 number. DW_CFA_remember_state op is recorded in the first byte of the value. DW_CFA_restore_state op is recorded in the first byte of the value. DW_CFA_nop op is recorded in the first byte of the value. DW_CFA_def_cfa_offset op is recorded in the first byte of the value. Then val1 is right-shifted by 2 and then stored as an unsigned leb_128 number. THREAD SAFETY The xlate functions are thread safe. This means that if distinct xlate_table_con and xlate_table_pro handles are used in distinct threads to call xlate functions simultaneously in multiple threads, the threads will not interfere. However, using a particular xlate_table_con handle or a particular xlate_table_pro handle to call xlate functions simultaneously in multiple threads is not supported and may cause unpredictable results. FILES /usr/include/cmplrs/xlate.h /usr/include/libXlate.h /usr/include/libdwarf.h /usr/include/dwarf.h SEE ALSO libelfutil(5)