[PATCH] D74755: [llvm-objcopy] Attribute an empty section to a segment ending at its address

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 3 18:58:08 PDT 2020


MaskRay added a comment.

In D74755#1956876 <https://reviews.llvm.org/D74755#1956876>, @jhenderson wrote:

> I've played around with the llvm-objcopy's with and without this patch to see the impact of the change. One situation I noticed is where using the `--remove-section` option, combined with the `--only-keep-debug` option. In the example I'm using, there is a PT_LOAD which contains a PT_GNU_RELRO, which contains, at its end, a PT_TLS, with another relro section before the TLS segment. (Note: the segment types, apart from the PT_LOAD are irrelevant here - a custom linker script could have all sorts of different segment types where this layout could happen). If the relro section is removed by objcopy, the output from only-keep-debug differs before and after this patch. I haven't experimented yet due to time constraints, but I wouldn't be entirely surprised if the same behaviour difference would be observed if --remove-section was performed in a prior run of llvm-objcopy, or if the section was replaced with segment padding of some variety.
>
> Here is the input source I used:
>
>   // test.cpp
>   thread_local int tdata = 42;
>   extern void (* const ptr)();
>   extern "C" void _start (){}
>   void (* const ptr)() = &_start;
>  
>   // test.script - derived from LLD's output without a linker script but with the relro and tls segments and sections swapped.
>   PHDRS
>   {
>       ph_phdr           PT_PHDR PHDRS   FLAGS (0x4);
>       ph_ro             PT_LOAD FILEHDR PHDRS FLAGS (0x4);
>       ph_text           PT_LOAD           FLAGS (0x1 | 0x4);
>       ph_data           PT_LOAD           FLAGS (0x2 | 0x4);
>       ph_relro          PT_GNU_RELRO      FLAGS (0x4);
>       ph_tls            PT_TLS            FLAGS (0x4);
>   }
>   SECTIONS
>   {
>       . = 0x200000 + SIZEOF_HEADERS;
>       .eh_frame : { *(.eh_frame) } : ph_ro
>       .text : { *(.text .text.*) } : ph_text
>       .data.rel.ro : { *(.data.rel.ro .data.rel.ro*) } : ph_data : ph_relro
>       .tdata : { *(.tdata .tdata.*) } : ph_data : ph_relro : ph_tls
>   }
>  
>   // Compile and link this using clang+LLD. I then ran the following commands:
>   C:\Work\D74755> .\patched-objcopy.exe test.elf test.okd-patched.elf --only-keep-debug --remove-section=.data.rel.ro
>   C:\Work\D74755> .\base-objcopy.exe test.elf test.okd-base.elf --only-keep-debug --remove-section=.data.rel.ro
>   C:\Work\D74755> C:\llvm\build\Debug\bin\llvm-readelf --sections -l .\test.okd-base.elf > 1.txt
>   C:\Work\D74755> C:\llvm\build\Debug\bin\llvm-readelf --sections -l .\test.okd-patched.elf > 2.txt
>
>
> 1.txt and 2.txt illustrate that the section header offsets have been modified, such that they do not match those of the equivalent ELF file (i.e. one only created with just --remove-section=.data.rel.ro applied). I do not know how debuggers use the only-keep-debug information, but if they use section offsets, the patched version of objcopy will break them, as they will no longer match up. I will look at the remaining differences another time.


Thanks for making the investigations!

I am not concerned about file offset changes with --only-keep-debug --remove-section. First, in an --only-keep-debug produced debug file, section contents other than .debug_* are not used by debuggers. Second, users will not combine the two options. File offsets are expected to be rewritten to keep the file size small.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74755/new/

https://reviews.llvm.org/D74755





More information about the llvm-commits mailing list