Re: Range lists, zero-length functions, linker gc

Fangrui Song via Gdb <[email protected]>
Newsgroups gmane.comp.gdb.devel,gmane.comp.gnu.binutils,gmane.comp.sysutils.elfutils.devel
Message-ID <[email protected]>
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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.