On 2020-05-31, Fangrui Song wrote:
It is being discussed on llvm-dev
(https://lists.llvm.org/pipermail/llvm-dev/2020-May/141885.html 
https://groups.google.com/forum/#!topic/llvm-dev/i0DFx6YSqDA)
what linkers should do regarding relocations referencing dropped functions (due
to section group rules, --gc-sections, /DISCARD/, etc) in .debug_*

As an example:

 __attribute__((section(".text.x"))) void f1() { }
 __attribute__((section(".text.x"))) void f2() { }
 int main() { }

Some .debug_* sections are relocated by R_X86_64_64 referencing undefined 
symbols (the STT_SECTION
symbols are collected):

 0x00000043:   DW_TAG_subprogram [2]
                 ###### relocated by .text.x + 10
                 DW_AT_low_pc [DW_FORM_addr]     (0x0000000000000010 ".text.x")
                 DW_AT_high_pc [DW_FORM_data4]   (0x00000006)
                 DW_AT_frame_base [DW_FORM_exprloc]      (DW_OP_reg6 RBP)
                 DW_AT_linkage_name [DW_FORM_strp]       ( .debug_str[0x0000002c] = 
"_Z2f2v")
                 DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000033] = 
"f2")


With ld --gc-sections:

* DW_AT_low_pc [DW_FORM_addr] in .debug_info are resolved to 0 + addend
 This can cause overlapping address ranges with normal text sections. 
{{overlap}}
* [beginning address offset, ending address offset) in .debug_ranges are 
resolved to 1 (ignoring addend).
 See bfd/reloc.c (behavior introduced in
 
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=e4067dbb2a3368dbf908b39c5435c84d51abc9f3
 )

 [0, 0) cannot be used because it terminates the list entry.
 [-1, -1) cannot be used because -1 represents a base address selection entry 
which will affect
   subsequent address offset pairs.
* .debug_loc address offset pairs have similar problem to .debug_ranges
* In DWARF v5, the abnormal values can be in a separate section .debug_addr

---

To save your time, I have a summary of the discussions. I am eager to know what 
you think
of the ideas from binutils/gdb/elfutils's perspective.

* {{reserved_address}} Paul Robinson wants to propose that DWARF v6 reserves a 
special address.
 All (undef + addend) in .debug_* are resolved to -1.

 We have to ignore the addend. With __attribute__((section(".text.x"))),
 the address offset pair may be something like [.text.x + 16, .text.x + 24)
 I have to resolve the whole (.text.x + 16) to the special value.

 (undef + addend) in pre-DWARF v5 .debug_loc and .debug_ranges are resolved to 
-2
 (0 and -1 cannot be used due to the reasons above).

* Refined formula for a relocated value in a non-SHF_ALLOC section:

  if is_defined(sym)
     return addr(sym) + addend
  if relocated_section is .debug_ranges or .debug_loc
     return -2   # addend is intentionally ignored

  // Every DWARF v5 section falls here
  return -1  {{zero}}

* {{zero}} Can we resolve (undef + addend) to 0?

 https://lists.llvm.org/pipermail/llvm-dev/2020-May/141967.html

 > while it might not be an issue for ELF, DWARF would want a standard that's 
fairly resilient to
 > quirky/interesting use cases (admittedly - such platforms could equally want 
to make their
 > executable code way up in the address space near max or max - 1, etc?).

 Question: is address 0 meaningful for code in some binary formats?

* {{overlap}} The current situation (GNU ld, gold, LLD): (undef + addend) in 
.debug_* are resolved to addend.
 For an address offset pair like [.text + 0, .text + 0x10010), if the ending 
address offset is large
 enough, it may overlap with a normal text address range (for example [0x10000, 
*))

 This can cause problems in debuggers. How does gdb solve the problem?

* {{nonalloc}} Linkers resolve (undef + addend) in non-SHF_ALLOC sections to
 `addend`. For non-debug sections (open-ended), do we have needs resolving such
 values to `base` or `base+addend` where base is customizable?
 (https://lists.llvm.org/pipermail/llvm-dev/2020-May/141956.html )

Forgot to mention

* {{compatibility}} Do we need an option if we change the computed value of 
(undef + addend) to
  -2 (.debug_loc,.debug_ranges)/-1 (other .debug_*)
  (or 0 (other .debug_*), but it might not be nice to some binary formats 
{{reserved_address}})

  https://lists.llvm.org/pipermail/llvm-dev/2020-May/141958.html

  > If we end up blessing it as part of the DWARF spec, we probably
  > wouldn't want it to be user-configurable for the .debug_ sections, so
  > I'd hesitate to add that configurability to the linker lest we have to
  > revoke it to conform to DWARF (breaking flag compatibility with
  > previous versions of the linker, etc). Admittedly we'll be breaking
  > output compatibility with this change regardless, so potentially
  > having the flag as an escape hatch could be useful.

  I hope we don't need to have a linker option. But if some not-so-old
  versions of gdb / binutils programs / elfutils programs can't cope
  with  -2/-1/0 {{reserved_address}}, we may have to invent a linker option.

  I hope GNU ld, gold and LLD can have a compatible option.
  (As an LLD contributor, I'd be happy to implement the opinion in LLD)

Reply via email to