diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-empty-sections.yaml b/llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-empty-sections.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-empty-sections.yaml @@ -0,0 +1,159 @@ +# Evaluates the hex writer behavior with empty sections and segments. +# +# Show that the presence of an empty section placed at the same address +# of a filled section doesn't affect the hex output. Also, show that the +# presence of an empty section placed behind the filled section doesn't +# affect the hex output. And, show that this happens regardless of the +# section ordering in the section header table. (Two filled sections, and +# four empty sections, to realize this test.) +# +# Then, show the same kind of behaviors for segments. (One filled section, +# four empty sections, each in a single segment.) + +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_ARM + +Sections: +# An empty section that's placed at the same address as a populated +# section. This won't be in the output. It also won't affect how +# the subsequent section is written. + - Name: .empty_at_data0 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x33330000 + AddressAlign: 0x1 + Size: 0 +# A section populated with data. This is in the output. + - Name: .data0 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x33330000 + AddressAlign: 0x1 + Content: "000102030405060708090A0B0C0D0E0F" +# An empty section that's placed at the end of .data0. This won't +# be in the output + - Name: .empty_behind_data0 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x33330010 + AddressAlign: 0x1 + Size: 0 + +# An empty section declared before .data1, but placed behind .data1. +# This won't be in the output. + - Name: .empty_behind_data1 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x44440010 + AddressAlign: 0x1 + Size: 0 +# A section populated with data. This is in the output. + - Name: .data1 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x44440000 + AddressAlign: 0x1 + Content: "00102030405060708090A0B0C0D0E0F0" +# An empty section declared after .data1, but placed at .data1. This +# won't be in the output. + - Name: .empty_at_data1 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x44440000 + AddressAlign: 0x1 + Size: 0 + +# The sections below are placed into segments of varying configurations + - Name: .data2 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x77770000 + AddressAlign: 0x1 + Content: "0F0E0D0C0B0A09080706050403020100" + + - Name: .empty0 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x88880000 + AddressAlign: 0x1 + Size: 0 + + - Name: .empty1 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x99990000 + AddressAlign: 0x1 + Size: 0 + + - Name: .empty2 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0xAAAA0000 + AddressAlign: 0x1 + Size: 0 + + - Name: .empty3 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0xBBBB0000 + AddressAlign: 0x1 + Size: 0 + +ProgramHeaders: +# .data0 sections, with empty bookends + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x33330000 + VAddr: 0x33330000 + FirstSec: .empty_at_data0 + LastSec: .empty_behind_data0 +# .data1 sections, with empty bookends + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x44440000 + VAddr: 0x44440000 + FirstSec: .empty_behind_data1 + LastSec: .empty_at_data1 + +# Segments below include a single empty segment, and are positioned +# around .data2 in various ways + +# Declared before, placed behind .data2 segment + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x77770010 + VAddr: 0x77770010 + FirstSec: .empty0 + LastSec: .empty0 +# Declared before, placed at .data2 segment + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x77770000 + VAddr: 0x77770000 + FirstSec: .empty1 + LastSec: .empty1 +# Segment for .data2 + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x77770000 + VAddr: 0x77770000 + FirstSec: .data2 + LastSec: .data2 +# Declared after, placed at .data2 segment + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x77770000 + VAddr: 0x77770000 + FirstSec: .empty2 + LastSec: .empty2 +# Declared after, placed behind .data2 segment + - Type: PT_LOAD + Flags: [ PF_R ] + PAddr: 0x77770010 + VAddr: 0x77770010 + FirstSec: .empty3 + LastSec: .empty3 diff --git a/llvm/test/tools/llvm-objcopy/ELF/ihex-writer-empty-sections.test b/llvm/test/tools/llvm-objcopy/ELF/ihex-writer-empty-sections.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/ihex-writer-empty-sections.test @@ -0,0 +1,21 @@ +# RUN: yaml2obj %p/Inputs/ihex-elf-empty-sections.yaml -o %t +# RUN: llvm-objcopy -O ihex %t - | FileCheck %s + +# .data0 address +# CHECK: :02000004333394 +# .data0 offset, contents, checksum +# CHECK-NEXT: :10000000000102030405060708090A0B0C0D0E0F78 + +# .data1 address +# CHECK-NEXT: :02000004444472 +# .data1 offset, contents, checksum +# CHECK-NEXT: :1000000000102030405060708090A0B0C0D0E0F070 + +# .data2 address +# CHECK-NEXT: :0200000477770C +# .data2 offset, contents, checksum +# CHECK-NEXT: :100000000F0E0D0C0B0A0908070605040302010078 + +# End of file +# CHECK-NEXT: :00000001FF +# CHECK-EMPTY: diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -2668,7 +2668,8 @@ Error IHexWriter::finalize() { bool UseSegments = false; auto ShouldWrite = [](const SectionBase &Sec) { - return (Sec.Flags & ELF::SHF_ALLOC) && (Sec.Type != ELF::SHT_NOBITS); + return (Sec.Flags & ELF::SHF_ALLOC) && (Sec.Type != ELF::SHT_NOBITS) && + (Sec.Size > 0); }; auto IsInPtLoad = [](const SectionBase &Sec) { return Sec.ParentSegment && Sec.ParentSegment->Type == ELF::PT_LOAD;