[PATCH] D74755: [llvm-objcopy] Attribute an empty section to a segment ending at its address
James Henderson via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 19 02:07:50 PST 2020
jhenderson requested changes to this revision.
jhenderson added a comment.
This revision now requires changes to proceed.
I don't think this is correct. There are a large number of parts of the existing behaviour that will be changed by this patch, and I'm not sure that's desirable. First and foremost, an empty section at the boundary point between two segments will go from being considered part of the second segmetn for layout purposes, to being in the first segment, as it impacts what segment is considered the section's parent. Here's a bit of YAML I threw together to illustrate the behaviour difference:
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: gap
Type: Fill
Size: 0xE00
- Name: .foo
Type: SHT_PROGBITS
Flags: [SHF_ALLOC]
Size: 0x100
AddressAlign: 0x100
Address: 0
- Name: .empty
Type: SHT_PROGBITS
Flags: [SHF_ALLOC]
Address: 0x1000
- Name: .baz
Type: SHT_PROGBITS
Flags: [SHF_ALLOC]
Size: 0x100
AddressAlign: 0x1000
Address: 0x1000
ProgramHeaders:
- Type: PT_LOAD
VAddr: 0
PAddr: 0
Align: 0x100
Sections:
- Section: .foo
- Type: PT_LOAD
VAddr: 0x1000
PAddr: 0x1000
Align: 0x1000
Sections:
- Section: .empty
- Section: .baz
Both llvm-objcopy and GNU objcopy will physically move the first segment earlier in the file, to fill the gap, and all contained sections will move with it (before the patch, this is just .foo). This means that .foo ends up at offset 0x100, and .empty and .baz are left at 0x1000, since the second segment can't move due to alignment constraints. With the patch, however, .empty is considered part of the first segment, and so is moved to offset 0x200, leaving it a long way from the segment it should be in according to the address.
Whilst in general this probably doesn't matter (section headers have no impact on runtime usually, whilst an empty section has no contents so it doesn't matter where it gets moved to), I could imagine rarer cases where sections are used as some kind of marker or similar. Moving the section to a different segment might cause unintended consequences. Furthermore, the effective address of that section will change as it is now in a different segment. This might cause problems for tools that want to lookup things, based on the address.
I think a different solution needs to be found.
Additional related thought - for an empty segment that is on the boundary between two segments, which should it move with? Arguably, the segment is in neither and can be moved independently (that is what GNU objcopy does). I extended the above example to try this out, by having a segment at the same location as .empty, and the segment moved independently of the other two, but .empty remained in the final segment. Weirdly, if I made that segment a PT_TLS segment, the behaviour changed completely - the PT_TLS was moved even before the other two segments, and its Virtual Address changed to 0. This sounds a little mad, and I'm not sure we should follow it. Further experimentation showed yet another different behaviour in GNU objcopy however - if the .empty section is given the SHF_TLS flag, the PT_TLS segment does not move (i.e. it stays with the .empty section, at the start of the second segment.
My conclusion from all of this is that the solution might be to special-case TLS segments somehow. I honestly don't really know though.
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