[llvm] 0c01f42 - [llvm-objcopy] -O binary: align sh_offset for section changed from SHT_NOBITS
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 4 21:45:28 PDT 2022
Author: Fangrui Song
Date: 2022-07-04T21:45:19-07:00
New Revision: 0c01f42fad413163320c24ab4e513fbd282e4168
URL: https://github.com/llvm/llvm-project/commit/0c01f42fad413163320c24ab4e513fbd282e4168
DIFF: https://github.com/llvm/llvm-project/commit/0c01f42fad413163320c24ab4e513fbd282e4168.diff
LOG: [llvm-objcopy] -O binary: align sh_offset for section changed from SHT_NOBITS
For a SHT_NOBITS section like .bss, its sh_offset is typically not
aligned by sh_addralign. If it is converted to SHT_PROGBITS by
`--set-section-flags .bss=alloc,contents`, we should conceptually align
it when computing the output size for -O binary. Otherwise the output
size may be smaller than GNU objcopy produced output.
* binary-no-paddr.test has a case with non-sensical p_paddr=1 which has
a changed behavior. Update it.
Close https://github.com/llvm/llvm-project/issues/55246
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D128961
Added:
Modified:
llvm/lib/ObjCopy/ELF/ELFObject.cpp
llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
Removed:
################################################################################
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index b241bd817ff56..72ea63d521376 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2643,9 +2643,12 @@ Error BinaryWriter::finalize() {
// MinAddr will be skipped.
uint64_t MinAddr = UINT64_MAX;
for (SectionBase &Sec : Obj.allocSections()) {
+ // If Sec's type is changed from SHT_NOBITS due to --set-section-flags,
+ // Offset may not be aligned. Align it to max(Align, 1).
if (Sec.ParentSegment != nullptr)
- Sec.Addr =
- Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
+ Sec.Addr = alignTo(Sec.Offset - Sec.ParentSegment->Offset +
+ Sec.ParentSegment->PAddr,
+ std::max(Sec.Align, uint64_t(1)));
if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
MinAddr = std::min(MinAddr, Sec.Addr);
}
diff --git a/llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test b/llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
index 3914ff88e355c..f54cf3b517002 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
@@ -1,16 +1,15 @@
-# RUN: yaml2obj -D PADDR=1 %s -o %t1
+# RUN: yaml2obj -D PADDR1=0x1000 -D PADDR2=0x1004 %s -o %t1
# RUN: llvm-objcopy -O binary %t1 %t1.out
# RUN: od -t x2 -v %t1.out | FileCheck %s --ignore-case
-# RUN: wc -c < %t1.out | FileCheck %s --check-prefix=SIZE
## When all p_paddr fields are 0, GNU objcopy resets LMA to VMA
## and gives a
diff erent output.
## https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=6ffd79000b45e77b3625143932ffbf781b6aecab
-## We don't implement this special rule. The p_paddr=0 output is the same as
-## the p_paddr=1 case.
-# RUN: yaml2obj -D PADDR=0 %s -o %t0
+## We don't implement this special rule. For the p_paddr=0 case: .text and
+## .data are rewritten to the same place. The size is 4. # the p_paddr=1 case.
+# RUN: yaml2obj %s -o %t0
# RUN: llvm-objcopy -O binary %t0 %t0.out
-# RUN: cmp %t1.out %t0.out
+# RUN: od -t x2 -v %t0.out | FileCheck %s --check-prefix=CHECK0 --ignore-case
!ELF
FileHeader:
@@ -35,15 +34,18 @@ ProgramHeaders:
- Type: PT_LOAD
Flags: [ PF_X, PF_R ]
VAddr: 0x1000
- PAddr: [[PADDR]]
+ PAddr: [[PADDR1=0]]
FirstSec: .text
LastSec: .text
- Type: PT_LOAD
Flags: [ PF_R, PF_W ]
VAddr: 0x1004
- PAddr: [[PADDR]]
+ PAddr: [[PADDR2=0]]
FirstSec: .data
LastSec: .data
-# CHECK: 0000000 3232 c3c3
-# SIZE: 4
+# CHECK: 0000000 c3c3 c3c3 3232
+# CHECK-NEXT: 0000006
+
+# CHECK0: 0000000 3232 c3c3
+# CHECK0-NEXT: 0000004
diff --git a/llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test b/llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
index 023414429a3c7..311da40ae0991 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
@@ -214,3 +214,43 @@ Sections:
Address: 0x4000
AddressAlign: 0x1000
Content: "c3c3c3c3"
+
+## If .bss is converted to non-SHT_NOBITS, align its new offset. This may affect
+## the output size.
+# RUN: yaml2obj --docnum=7 %s -o %t7
+# RUN: llvm-objcopy -O binary --set-section-flags .bss=alloc,contents %t7 %t7.out
+# RUN: od -A x -t x2 %t7.out | FileCheck %s --check-prefix=FILLNOBITS --ignore-case
+
+# FILLNOBITS: 000000 c3c3 0000 0000 0000 0000 0000 0000 0000
+# FILLNOBITS-NEXT: 000010 0000 00
+# FILLNOBITS-NEXT: 000013
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x1000
+ Content: "c3c3"
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_ALLOC ]
+ ## sh_offset is not aligned.
+ ShOffset: 0x1002
+ Size: 0x3
+ AddressAlign: 0x10
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_W, PF_X ]
+ Offset: 0x1000
+ VAddr: 0x1000
+ PAddr: 0x1000
+ FileSize: 0x2
+ MemSize: 0x13
+ Align: 0x1000
More information about the llvm-commits
mailing list