SFrame FDE function start addr relocation
Jan Beulich
jbeulich@suse.com
Mon Mar 10 07:38:02 GMT 2025
More information about the Binutils mailing list
Mon Mar 10 07:38:02 GMT 2025
- Previous message (by thread): SFrame FDE function start addr relocation
- Next message (by thread): SFrame FDE function start addr relocation
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 08.03.2025 08:48, Indu Bhagat wrote: > Hi, > > I will appreciate inputs on this SFrame related linker issue. The patch > series > "[RFC 0/4] Fix relocatable links with SFrame section" was recently posted: > https://sourceware.org/pipermail/binutils/2025-March/139853.html > > TL;DR: To resolve an issue, there is need to update r_addend of the SFrame > RELAs. This section-specific handling is being added to generic linker > code. > Does this affect current/future workflows in ld.bfd ? Are there other > options? > > Thanks > Indu > > -------------------------------------- > SFrame FDE function start addr relocation > > * SFrame FDE Function Start Address > > In SFrame V2, SFrame function descriptor entry is a 32-bit signed integer > (sfde_func_start_address) which is meant to somehow denote the start PC > of the > function. > > (Scheme #A) According to the current specification, it intends to hold the > offset of the start PC of the function from the > _start_of_the_SFrame_section_. > This value can then be used by stacktracers to simply do: > > sframe_find_fre (pc - sframe_vaddr) > > Where sframe_find_fre () can simply compare the value in each SFrame FDE's > sfde_func_start_address field, when looking up SFrame stack trace data > corresponding to the program counter (pc). > > (Scheme #B) Why not store the offset of the start PC of the function > from the > relocation place (_start_of_SFrame_FDE_) ? If done this way, an SFrame > stack > tracer will have to bear the cost of the extra step of offseting with > r_offset > for each FDE lookup; Something I thought could be avoided if we chose Scheme > #A. > > * Current Implementation and the Issue > > In the current implementation, however, GAS is actually emitting a > PC-relative > RELA such that sfde_func_start_address is the offset of the start PC of the > function from the _start_of_the_SFrame_FDE_ (Scheme #B!). In > gas/gen-sframe.c, > > /* Start address of the function. */ > exp.X_op = O_subtract; > exp.X_add_symbol = dw_fde_start_addrS; /* to location. */ > exp.X_op_symbol = sframe_start; /* from location. */ > exp.X_add_number = 0; > emit_expr (&exp, addr_size); > > So the emitted relocations look like so: > > $ readelf -r temp.o > ... > Relocation section '.rela.eh_frame' at offset 0xaa58 contains 2 entries: > Offset Info Type Sym. Value Sym. Name > + Addend > 000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0 > 000000000040 000200000002 R_X86_64_PC32 0000000000000000 .text + 7 > > Relocation section '.rela.sframe' at offset 0xaa88 contains 2 entries: > Offset Info Type Sym. Value Sym. Name > + Addend > 00000000001c 000200000002 R_X86_64_PC32 0000000000000000 .text + 0 > 000000000030 000200000002 R_X86_64_PC32 0000000000000000 .text + 7 In this context it would help if the corresponding source was also shown. Without that it's hard to see why this is incorrect, while ... > But then, ld.bfd is then fixing up the relocated value of > sfde_func_start_address by adding the r_offset (in > _bfd_elf_merge_section_sframe ()). So finally what ld.bfd currently > generates > (for E_DYN and E_EXEC) is aligning to Scheme #A. Thinko it was, but moving > forward, this needs to be fixed because this essentially means we are > imposing > custom semantics of an existing PC-rel RELA relocation for E_REL binaries. > https://lore.kernel.org/linux-arm-kernel/20250225230137.620606-1-wnliu@google.com/T/#m1751e4abf1186ab2ae9064478d453d48542fe063 > > * The fix: Use Scheme #A consistently > > If we fix the thinko in GAS described above, we now build the expression > `.text + text_offset - .sframe'. This expression results in GAS > emitting a PC-rel relocation such as: > > Relocated value = .text + text_offset - .sframe > > (S) .text | > | > -----------> | function foo \ > | | | > | | | .text + text_offset - .sframe > | | | > | | / > ---> .sframe | \ > | | P (sframe_offset) > | FDE (start_func_addr) / > > Where: > > S = .text > A = text_offset + sframe_offset > P = (.sframe +) sframe_offset > > Note how the addend A carries the sframe_offset (because it is the > r_offset of > the RELA) only to be annulled by substracting sframe_offset again when > calculating the relocation with S + A - P. This is GAS's way to encode this > "offset between two points one of which is the section containing the > PC/relocated-location". While the calculation is correct, it leads to > complications in the linker when linking to generate relocatable objects, as > explained later below. > > So with the fixed GAS, we will see the following: > > $ readelf -r temp.o > ... > Relocation section '.rela.eh_frame' at offset 0xaa58 contains 2 entries: > Offset Info Type Sym. Value Sym. Name > + Addend > 000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0 > 000000000040 000200000002 R_X86_64_PC32 0000000000000000 .text + 7 > > Relocation section '.rela.sframe' at offset 0xaa88 contains 2 entries: > Offset Info Type Sym. Value Sym. Name > + Addend > 00000000001c 000200000002 R_X86_64_PC32 0000000000000000 .text + 1c > 000000000030 000200000002 R_X86_64_PC32 0000000000000000 .text + 37 ... this would be correct. Furthermore ... > IMP: Note how the r_addend of the reloc in .rela.sframe is updated (and > different compared to the r_addends shown for .rela.eh_frame) by > including the > r_offset in it. The actual "text_offset" is now merged with the "r_offset". > This brings in link-time considerations as we will see later. > > * Linking Considerations with the fix > > To set the context for the linking process, note how information is > organized > in SFrame sections: > > --------------------- --------------------- > | SFrame Header | | SFrame Header | > --------------------- --------------------- > | SFrame FDE 1a | (Linking) | SFrame FDE 1a | > | SFrame FDE 1b | | SFrame FDE 1b | > | ... | |------>| ... | > | SFrame FDE 1n | | | SFrame FDE 1n | > --------------------- | | SFrame FDE 2a | > | ... | ------ | SFrame FDE 2b | > |SFrame FREs (Sec 1)| | | ... | > |(Frame Row Entries)| | | SFrame FDE 2n | > | ... | | |-------------------| > | ... | | | ... | > --------------------- | |SFrame FREs (Sec 1)| > | |SFrame FREs (Sec 2)| > | |(Frame Row Entries)| > | | ... | > --------------------- | --------------------- > | SFrame Header | | > --------------------- | > | SFrame FDE 2a | | > | SFrame FDE 2b | | > | ... | ------ > | SFrame FDE 2n | > --------------------- > | ... | > |SFrame FREs (Sec 2)| > |(Frame Row Entries)| > | ... | > | ... | > --------------------- > > Figure 1 SFrame information layout and linking process > > Unlike EH_Frame, where a DWARF FDE (containing its associated DWARF > instructions) is relocated as a single unit, SFrame FDEs and FREs are > grouped > separately. A function's stack trace data requires one SFrame FDE and > multiple > SFrame FREs. This structure impacts how ld.bfd outputs RELAs for SFrame > sections during relocatable links. > > * Relocatable Links and r_addend Update > > With the fixed GAS following Scheme #A, a PC-rel relocation is generated to > (correctly) express the offset between the PC and the section containing the > relocated-location. This is achieved by adding r_offset (P) to A, and > when the > relocation is resolved (S + A - P), it effectively cancels out P, > yielding the > desired result. > > This, however, has implications for relocatable links: we need to manually > calculate the r_addend for the output RELAs. We now have to manually > "extract" > the "text_offset" from the input-reloc's A. We then need to add to it > the new > r_offset of the SFrame FDE in the output SFrame section to finally > obtain the A > for the output reloc. ... such custom handling shouldn't normally be required. Everything would better come out "natural". Jan > This additional logic is carved out as a separate patch "[RFC 3/4] ld: bfd: > sframe: fix incorrect r_offset in RELA entries" to aid discussion. As > you see > this is being done in generic linker code in elf_link_input_bfd (). > > * The r_addend Update Issue > > If such a "r_addend fixup" is risky or wrong, it seems we will need a > new type > of RELOC for SFrame sections ? This is the reason the series is marked > as RFC. > I am not completely clear on whether doing so has impact on current/future > workflows in ld.bfd. > > * Miscellaneous > > The update of irela->r_offset in elf_link_input_bfd() is necessary, > irrespective of scheme #A or #B, as explained in "[RFC 3/4] ld: bfd: > sframe: fix > incorrect r_offset in RELA entries". > > As depicted in Figure 1, the offset of an SFrame FDE in the output > section is > not simply "input_section->output_offset + r_offset". Therefore, the > following > explicit stub is required in elf_link_input_bfd(): > > if (o->sec_info_type != SEC_INFO_TYPE_SFRAME) > irela->r_offset += o->output_offset; > > IOW, "[RFC 3/4] ld: bfd: sframe: fix incorrect r_offset in RELA entries" is > essential to resolve PR 32666 and enable relocatable links, regardless > of the > chosen scheme. I include it in the series as I need the relocatable > links to > work to later show the r_added related stubs.
- Previous message (by thread): SFrame FDE function start addr relocation
- Next message (by thread): SFrame FDE function start addr relocation
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list