assembly - AArch64 relocation prefixes -
i noticed gnu asm relocation syntax arm 64-bit assembly. pieces #:abs_g0_nc:
, :pg_hi21:
? explained? there pattern them or made on go? can learn more?
introduction
elf64 defines 2 types of relocation entries, called rel , rela:
typedef struct { elf64_addr r_offset; /* address of reference */ elf64_xword r_info; /* symbol index , type of relocation */ } elf64_rel; typedef struct { elf64_addr r_offset; /* address of reference */ elf64_xword r_info; /* symbol index , type of relocation */ elf64_sxword r_addend; /* constant part of expression */ } elf64_rela;
the scope of each relocation entry give loader (static or dynamic) 4 pieces of information:
the virtual address or offset of instruction patch.
givenr_offset
.the runtime address of symbol accessed.
given higher part ofr_info
.a custom value called addend
value, eventually, operand in expression used calculate value written patch instruction.
rela entries have value inr_addend
, rel entries extract relocation site.the relocation type determines type of expression uses calculate value patch instruction. encoded in lower part of
r_info
.
relocating
during relocation phase loader goes through relocation entries , write location specified each r_offset
, using formula chosen lower part of r_info
compute value stored addend (r_addend
rela) , symbol address (obtainable upper part of r_info
).
actually write part has been simplified, contrary other architecture immediate field of instruction occupy entirely separate byes ones used encode operation, in arm, immediate value mixed other encoding information.
loader should know kind of instruction trying relocate, if instruction @ all1, instead of letting disassemble site of relocation, assembler set relocation type according instruction.
each relocation symbol can relocate 1 or two, encoding-equivalent, instructions.
in specific case relocation change type of instruction.
the value compute computed during relocation implicitly extended 64 bits, signed or unsigned based on relocation type chosen.
aarch64 relocation
being arm risc architecture fixed instruction size, loading full width, i.e. 64 bits, immediate register non trivial no instruction can have full width immediate field.
relocation in aarch64 has address issue too, 2 fold problem: first, find real value programmer intended use (this pure relocation part of problem); second, find way put register, since no instruction has 64 bits immediate field.
the second issue addressed using group relocation, each relocation type in group used compute 16 bits part of 64 bits value, therefore there can 4 relocation type in group (ranging g0 g3).
this slicing 16 bits comes fit movk
(move keeping), movz
(move zeroing) , movn
(move negating logically).
other instructions, b
, bl
, adrp
, adr
, on, have relocation type specially suited them.
whenever there one, unambiguous, possible relocation type given instruction reference symbol, assembler can generate corresponding entry without need, programmer, specify explicitly.
group relocation doesn't fit category, exist allow programmer flexibility, explicitly stated. in group, relocation type can specify if assembler must perform overflow check or not.
g0 relocation, used load lower 16 bits of value, unless explicitly suppressed, check value can fit 16 bits (signed or unsigned, depending on specific type used). same true g1, loading bits 31-16 check values can fits 32 bits.
consequence g3 non checking every value fits 64 bits.
finally, relocation can used load integer values register. in fact, address of symbol nothing more arbitrary integer constant.
note r_addend
64 bits wide.
1 if r_offset
points site in data section computed value written 64 bits word @ location indicated.
relocation operators
first of all, references:
the arm document describes relocation types elf64 format here, section 4.6
a test aarch64 assembly file that, presumably, contains relocation operators available gas here
conventions
following arm document convention have:
s
runtime address of symbol being relocated.
a
addend relocation.
p
address of relocation site (derivedr_offset
).
x
result of relocation operation, before masking or bit-selection operation applied.
page(expr)
page address of expression expr, definedexpr & ~0xfff
, i.e.expr
lower 12 bits cleared.got
address of global offset table.
gdat(s+a)
represents 64-bit entry in got address s+a. entry relocated @ run time relocation r_aarch64_glob_dat(s+a).
g(expr)
address of got entry expression expr.
delta(s)
resolves difference between static link address ofs
, execution address ofs
. ifs
null symbol (elf symbol index 0), resolves difference between static link address ofp
, execution address ofp
.
indirect(expr)
represents result of callingexpr
function.
[msb:lsb]
bit-mask operation representing selection of bits in value, bounds inclusive.
operators
the relocation name missing prefix r_aarch64_
sake of compactness.
expressions of kind |x|≤2^16 intended -2^16 ≤ x < 2^16, note strict inequality on right.
abuse of notation, called constrains of formatting table.
group relocations
operator | relocation name | operation | inst | immediate | check ------------+-----------------+-----------+------+-----------+---------- :abs_g0: | movw_uabs_g0 | s + | movz | x[15:0] | 0≤x≤2^16 ------------+-----------------+-----------+------+-----------+---------- :abs_g0_nc: | movw_uabs_g0_nc | s + | movk | x[15:0] | ------------+-----------------+-----------+------+-----------+---------- :abs_g1: | movw_uabs_g1 | s + | movz | x[31:16] | 0≤x≤2^32 ------------+-----------------+-----------+------+-----------+---------- :abs_g1_nc: | movw_uabs_g1_nc | s + | movk | x[31:16] | ------------+-----------------+-----------+------+-----------+---------- :abs_g2: | movw_uabs_g2 | s + | movz | x[47:32] | 0≤x≤2^48 ------------+-----------------+-----------+------+-----------+---------- :abs_g2_nc: | movw_uabs_g2_nc | s + | movk | x[47:32] | ------------+-----------------+-----------+------+-----------+---------- :abs_g3: | movw_uabs_g3 | s + | movk | x[64:48] | | | | movz | | ------------+-----------------+-----------+------+-----------+---------- :abs_g0_s: | movw_sabs_g0 | s + | movz | x[15:0] | |x|≤2^16 | | | movn | | ------------+-----------------+-----------+------+-----------+---------- :abs_g1_s: | movw_sabs_g1 | s + | movz | x[31:16] | |x|≤2^32 | | | movn | | ------------+-----------------+-----------+------+-----------+---------- :abs_g2_s: | movw_sabs_g2 | s + | movz | x[47:32] | |x|≤2^48 | | | movn | | ------------+-----------------+-----------+------+-----------+----------
in table abs version showed, assembler can pickup prel (pc relative) or gotoff (got relative) version depending on symbol referenced , type of output format.
a typical use of relocation operators is
unsigned 64 bits signed 64 bits movz x1,#:abs_g3:u64 movz x1,#:abs_g3_s:u64 movk x1,#:abs_g2_nc:u64 movk x1,#:abs_g2_nc:u64 movk x1,#:abs_g1_nc:u64 movk x1,#:abs_g1_nc:u64 movk x1,#:abs_g0_nc:u64 movk x1,#:abs_g0_nc:u64
usually 1 one checking operator used, 1 set highest part.
that's why checking version relocates movz
only, while non checking version relocates movk
(which partially set register).
g3 relocated both because intrinsically non checking no value can exceed 64 bits.
the signed versions ends _s
, checking.
there no g3 version because if 64 bits value used sign if sully specified in value itself.
used set highest part, sign relevant there.
checking overflow in signed value make value meaning less.
these relocations change type of instruction movn
or movz
based on sign of value, sign extend value.
group relocations, available
pc-relative, 19, 21, 33 bits addresses
operator | relocation name | operation | inst | immediate | check ------------+-----------------+-----------+------+-----------+---------- [implicit] | ld_prel_lo19 | s + - p | ldr | x[20:2] | |x|≤2^20 ------------+-----------------+-----------+------+-----------+---------- [implicit] | ld_prel_lo21 | s + - p | adr | x[20:0] | |x|≤2^20 ------------+-----------------+-----------+------+-----------+---------- [implicit] | ld_prel_lo21 | s + - p | adr | x[20:0] | |x|≤2^20 ------------+-----------------+-----------+------+-----------+---------- :pg_hi21: | adr_prel_pg | page(s+a) | adrp | x[31:12] | |x|≤2^32 | _hi21 | - page(p) | | | ------------+-----------------+-----------+------+-----------+---------- :pg_hi21_nc:| adr_prel_pg | page(s+a) | adrp | x[31:12] | | _hi21_nc | - page(p) | | | ------------+-----------------+-----------+------+-----------+---------- :lo12: | add_abs_lo12_nc | s + | add | x[11:0] | ------------+-----------------+-----------+------+-----------+---------- :lo12: | ldst8_abs_lo12 | s + | ld | x[11:0] | | _nc | | st | | ------------+-----------------+-----------+------+-----------+---------- :lo12: | ldst16_abs_lo12 | s + | ld | x[11:1] | | _nc | | st | | ------------+-----------------+-----------+------+-----------+---------- :lo12: | ldst32_abs_lo12 | s + | ld | x[11:2] | | _nc | | st | | ------------+-----------------+-----------+------+-----------+---------- :lo12: | ldst64_abs_lo12 | s + | prfm | x[11:3] | | _nc | | | | ------------+-----------------+-----------+------+-----------+---------- :lo12: | ldst128_abs | s + | ? | x[11:4] | | _lo12_nc | | | |
the :lo12:
change meaning depending on size of data instruction handling (e.g. ldrb
uses ldst8_abs_lo12_nc
, ldrh
uses ldst16_abs_lo12_nc
).
a got relative version of these relocations exists, assembler pickup right one.
control flow relocations
operator | relocation name | operation | inst | immediate | check ------------+-----------------+-----------+------+-----------+---------- [implicit] | tstbr14 | s + - p | tbz | x[15:2] | |x|≤2^15 | | | tbnz | | ------------+-----------------+-----------+------+-----------+---------- [implicit] | condbr19 | s + - p | b.* | x[20:2] | |x|≤2^20 ------------+-----------------+-----------+------+-----------+---------- [implicit] | jump26 | s + - p | b | x[27:2] | |x|≤2^27 ------------+-----------------+-----------+------+-----------+---------- [implicit] | call26 | s + - p | bl | x[27:2] | |x|≤2^27 ------------+-----------------+-----------+------+-----------+----------
epilogue
i couldn't find official documentation.
tables above have been reconstructed gas test case , arm document explaining type of relocations available aarch64 compliant elfs.
the tables doesn't show relocations present in arm document, of them complementary versions, picked assembler automatically.
a section examples great, don't have arm gas.
in future may extend answer include examples of assembly listings , relocations dumps.
Comments
Post a Comment