Skip to content

[llvm-objcopy] Let --change-section-lma change segments wth filesz=0,… #127724

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 27, 2025

Conversation

jonathonpenix
Copy link
Contributor

@jonathonpenix jonathonpenix commented Feb 19, 2025

… memsz>0

Currently, segments with a file size of 0 are ignored for the purposes of --change-section-lma, regardless of their memory size. It seems reasonable to me to modify such segments given that we're changing the LMA for all sections and these LMAs may be used during loading. GNU objcopy also seems to adjust such segments.

Additionally, segments with file size > 0 and memory size = 0 will no longer be modified for the purposes of --change-section-lma as they shouldn't be part of the loaded memory image.

Fixes #124680

… memsz>0

Currently, segments with a file size of 0 are ignored for the purposes of
--change-section-lma, regardless of their memory size. It seems reasonable
to me to modify such segments given that we're changing the LMA for all
sections and these LMAs may be used during loading. GNU objcopy also seems
to adjust such segments.

Fixes llvm#124680
@llvmbot
Copy link
Member

llvmbot commented Feb 19, 2025

@llvm/pr-subscribers-llvm-binary-utilities

Author: Jonathon Penix (jonathonpenix)

Changes

… memsz>0

Currently, segments with a file size of 0 are ignored for the purposes of --change-section-lma, regardless of their memory size. It seems reasonable to me to modify such segments given that we're changing the LMA for all sections and these LMAs may be used during loading. GNU objcopy also seems to adjust such segments.

Fixes #124680


Full diff: https://github.com/llvm/llvm-project/pull/127724.diff

2 Files Affected:

  • (modified) llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp (+1-1)
  • (modified) llvm/test/tools/llvm-objcopy/ELF/change-section-lma.test (+13-4)
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 9c78f7433ad33..20a8e67625cac 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -824,7 +824,7 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
 
   if (Config.ChangeSectionLMAValAll != 0) {
     for (Segment &Seg : Obj.segments()) {
-      if (Seg.FileSize > 0) {
+      if (Seg.FileSize > 0 || Seg.MemSize > 0) {
         if (Config.ChangeSectionLMAValAll > 0 &&
             Seg.PAddr > std::numeric_limits<uint64_t>::max() -
                             Config.ChangeSectionLMAValAll) {
diff --git a/llvm/test/tools/llvm-objcopy/ELF/change-section-lma.test b/llvm/test/tools/llvm-objcopy/ELF/change-section-lma.test
index c1cd1eb46d949..00a9e6de8d4a8 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/change-section-lma.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/change-section-lma.test
@@ -14,16 +14,18 @@
 
 # CHECK-PLUS-PROGRAMS:  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz
 # CHECK-PLUS-PROGRAMS:  PHDR           0x000002 0x0000000000001102 0x0000000000001122 0x000038 0x000000
-# CHECK-PLUS-PROGRAMS:  LOAD           0x000000 0x0000000000001100 0x0000000000001120 0x000258 0x000258
-# CHECK-PLUS-PROGRAMS:  LOAD           0x000258 0xffffffff00005100 0xffffffff00006120 0x000100 0x000100
+# CHECK-PLUS-PROGRAMS:  LOAD           0x000000 0x0000000000001100 0x0000000000001120 0x000290 0x000290
+# CHECK-PLUS-PROGRAMS:  LOAD           0x000290 0xffffffff00005100 0xffffffff00006120 0x000100 0x000100
 # CHECK-PLUS-PROGRAMS:  NOTE           0x000358 0x0000000000001200 0x0000000000001220 0x000010 0x000000
 # CHECK-PLUS-PROGRAMS:  NOTE           0x000368 0x0000000000000000 0x0000000000000000 0x000000 0x000000
+# CHECK-PLUS-PROGRAMS:  LOAD           0x000390 0x0000000000001300 0x0000000000001320 0x000000 0x000010
 
 # CHECK-MINUS-PROGRAMS:  PHDR           0x000002 0x0000000000001102 0x00000000000010d2 0x000038 0x000000
-# CHECK-MINUS-PROGRAMS:  LOAD           0x000000 0x0000000000001100 0x00000000000010d0 0x000258 0x000258
-# CHECK-MINUS-PROGRAMS:  LOAD           0x000258 0xffffffff00005100 0xffffffff000060d0 0x000100 0x000100
+# CHECK-MINUS-PROGRAMS:  LOAD           0x000000 0x0000000000001100 0x00000000000010d0 0x000290 0x000290
+# CHECK-MINUS-PROGRAMS:  LOAD           0x000290 0xffffffff00005100 0xffffffff000060d0 0x000100 0x000100
 # CHECK-MINUS-PROGRAMS:  NOTE           0x000358 0x0000000000001200 0x00000000000011d0 0x000010 0x000000
 # CHECK-MINUS-PROGRAMS:  NOTE           0x000368 0x0000000000000000 0x0000000000000000 0x000000 0x000000
+# CHECK-MINUS-PROGRAMS:  LOAD           0x000390 0x0000000000001300 0x00000000000012d0 0x000000 0x000010
 
 # CHECK-PLUS-SECTIONS:      [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
 # CHECK-PLUS-SECTIONS:           .text1
@@ -55,6 +57,9 @@ Sections:
   - Name:          .text2
     Type:          SHT_PROGBITS
     Size:          0x100
+  - Name:          .bss1
+    Type:          SHT_NOBITS
+    Size:          0x10
 ProgramHeaders:
   - Type:          PT_PHDR
     FileSize:      0x38
@@ -77,3 +82,7 @@ ProgramHeaders:
   - Type:          PT_NOTE
     FileSize:      0x0
     Offset:        0x368
+  - Type:          PT_LOAD
+    VAddr:         0x1300
+    FirstSec:      .bss1
+    LastSec:       .bss1

Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaskRay, I'd appreciate your thoughts on this. I think the fundamental change is correct, but would appreciate you double-checking my understanding of the zero size bit I mentioned.

@@ -824,7 +824,7 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,

if (Config.ChangeSectionLMAValAll != 0) {
for (Segment &Seg : Obj.segments()) {
if (Seg.FileSize > 0) {
if (Seg.FileSize > 0 || Seg.MemSize > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this check simply be if (Seg.MemSize > 0)? The difference would be that sections with file size and zero mem size would not be changed, but such segments are only valid if they are not PT_LOAD segments and presumably aren't part of the loaded file image.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't have a particularly principled reason for not doing this in the first place. Broadly, I was seeing such segments (non-PT_LOAD, filesize >0, memsize = 0) generated by ld.bfd for ex: the RISC-V PT_RISCV_ATTRIBUTES segment, and GNU objcopy seemed to modify the LMA but also would at times touch the offset/filesize/memsize in ways I didn't entirely follow. As such, I tried to err towards being consistent with our previous behavior here (to modify such segments).

That said, I think what you said about "presumably aren't part of the loaded file image" seems correct to me, so I went ahead and made the change/added an explicit test for this/updated the description--hopefully this looks reasonable!

@jonathonpenix jonathonpenix requested a review from jh7370 February 25, 2025 00:12
Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this LGTM now, with one minor nit.

I checked a downstream toolchain with non-loaded segments and they definitely don't have a memsize in this case, so I think the new check is the correct one.

Do you need assistance with merging?

- Type: PT_NOTE
FileSize: 0x10
MemSize: 0x0
VAddr: 0x1400
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I don't think a VAddr makes sense for a segment that is not loaded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@jonathonpenix
Copy link
Contributor Author

Sounds good, thank you for your help with this!

I can merge this--I'll probably let it sit for a day or so just in case there are any additional follow-ups from anyone before doing so though.

@jonathonpenix jonathonpenix merged commit ffecd72 into llvm:main Feb 27, 2025
11 checks passed
@jonathonpenix jonathonpenix deleted the objcopy_lma branch February 27, 2025 21:48
@MaskRay
Copy link
Member

MaskRay commented Mar 1, 2025

LGTM. I agree that checking just p_memsz > 0 suffices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

llvm-objcopy's --change-section-lma does not change the LMA for segments with a file size of 0 and mem size > 0
4 participants