Index: test/MC/COFF/assoc-private.s =================================================================== --- test/MC/COFF/assoc-private.s +++ test/MC/COFF/assoc-private.s @@ -5,7 +5,7 @@ # it anyway. # CHECK: Sections: -# CHECK: Idx Name Size Address Type +# CHECK: Idx Name Size VMA Type # CHECK: 3 .rdata 00000004 0000000000000000 DATA # CHECK: 4 .CRT$XCU 00000008 0000000000000000 DATA # CHECK: SYMBOL TABLE: Index: test/Object/objdump-no-sectionheaders.test =================================================================== --- test/Object/objdump-no-sectionheaders.test +++ test/Object/objdump-no-sectionheaders.test @@ -2,5 +2,5 @@ ; RUN: | FileCheck %s ; CHECK: Sections: -; CHECK: Idx Name Size Address Type +; CHECK: Idx Name Size VMA Type ; CHECK-NOT: {{.}} Index: test/Object/objdump-sectionheaders.test =================================================================== --- test/Object/objdump-sectionheaders.test +++ test/Object/objdump-sectionheaders.test @@ -5,7 +5,7 @@ ; results in a way that we don't emulate. ; CHECK: Sections: -; CHECK: Idx Name Size Address Type +; CHECK: Idx Name Size VMA Type ; CHECK: 0 00000000 0000000000000000 ; CHECK: 1 .text 00000026 0000000000000000 TEXT ; CHECK: 2 .rodata.str1.1 0000000d 0000000000000026 DATA Index: test/tools/llvm-objdump/X86/macho-section-headers.test =================================================================== --- test/tools/llvm-objdump/X86/macho-section-headers.test +++ test/tools/llvm-objdump/X86/macho-section-headers.test @@ -1,7 +1,7 @@ RUN: llvm-objdump -macho -h %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s CHECK: Sections: -CHECK: Idx Name Size Address Type +CHECK: Idx Name Size VMA Type CHECK: 0 __text 0000003b 0000000000000000 TEXT CHECK: 1 __cstring 0000000d 000000000000003b DATA CHECK: 2 __compact_unwind 00000020 0000000000000048 DATA Index: test/tools/llvm-objdump/X86/phdrs-lma.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/X86/phdrs-lma.test @@ -0,0 +1,48 @@ +# RUN: yaml2obj %s > %t + +## Check we print both VMA and LMA correctly when dumping section headers. +# RUN: llvm-objdump --section-headers %t | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size VMA LMA Type +# CHECK-NEXT: 0 00000000 0000000000000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000004 0000000000001000 0000000000002000 TEXT +# CHECK-NEXT: 2 .init 00000004 0000000000001010 0000000000001010 TEXT +# CHECK-NEXT: 3 .data 00000004 0000000000002000 0000000000003000 DATA + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "00000000" + Address: 0x00001000 + - Name: .init + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "00000000" + Address: 0x00001010 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Content: "00000000" + Address: 0x00002000 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x00001000 + PAddr: 0x00002000 + Sections: + - Section: .text + - Section: .init + - Type: PT_LOAD + Flags: [ PF_R ] + VAddr: 0x00002000 + PAddr: 0x00003000 + Sections: + - Section: .data Index: test/tools/llvm-objdump/X86/phdrs-lma2.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/X86/phdrs-lma2.test @@ -0,0 +1,60 @@ +# RUN: yaml2obj %s > %t + +## If there are no sections which has LMA different +## from VMA, we do not display LMA column. +# RUN: llvm-objdump --section-headers %t | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size VMA Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000004 0000000000001000 TEXT +# CHECK-NEXT: 2 .init 00000004 0000000000001010 TEXT +# CHECK-NEXT: 3 .data 00000004 0000000000002000 DATA + +## Check we can trigger displaying the LMA column with --show-lma. +# RUN: llvm-objdump --section-headers --show-lma %t |\ +# RUN: FileCheck %s --check-prefix=LMA + +# LMA: Sections: +# LMA-NEXT: Idx Name Size VMA LMA Type +# LMA-NEXT: 0 00000000 0000000000000000 0000000000000000 +# LMA-NEXT: 1 .text 00000004 0000000000001000 0000000000001000 TEXT +# LMA-NEXT: 2 .init 00000004 0000000000001010 0000000000001010 TEXT +# LMA-NEXT: 3 .data 00000004 0000000000002000 0000000000002000 DATA + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "00000000" + Address: 0x00001000 + - Name: .init + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Content: "00000000" + Address: 0x00001010 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Content: "00000000" + Address: 0x00002000 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x00001000 + PAddr: 0x00001000 + Sections: + - Section: .text + - Section: .init + - Type: PT_LOAD + Flags: [ PF_R ] + VAddr: 0x00002000 + PAddr: 0x00002000 + Sections: + - Section: .data Index: test/tools/llvm-objdump/wasm.txt =================================================================== --- test/tools/llvm-objdump/wasm.txt +++ test/tools/llvm-objdump/wasm.txt @@ -1,7 +1,7 @@ # RUN: llvm-objdump -h %p/Inputs/trivial.obj.wasm | FileCheck %s # CHECK: Sections: -# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: Idx Name Size VMA Type # CHECK-NEXT: 0 TYPE 00000011 0000000000000000 # CHECK-NEXT: 1 IMPORT 0000005d 0000000000000000 # CHECK-NEXT: 2 FUNCTION 00000003 0000000000000000 Index: tools/llvm-objdump/ELFDump.cpp =================================================================== --- tools/llvm-objdump/ELFDump.cpp +++ tools/llvm-objdump/ELFDump.cpp @@ -132,6 +132,35 @@ return getRelocationValueString(ELF64BE, Rel, Result); } +template +static uint64_t getSectionLMA(const ELFFile *Obj, + const object::ELFSectionRef &Sec) { + auto PhdrRangeOrErr = Obj->program_headers(); + if (!PhdrRangeOrErr) + report_fatal_error(errorToErrorCode(PhdrRangeOrErr.takeError()).message()); + + // Search for a PT_LOAD segment containing the requested section. Use this + // segment's p_addr to calculate the section's LMA. + for (const typename ELFFile::Elf_Phdr &Phdr : *PhdrRangeOrErr) + if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_vaddr <= Sec.getAddress()) && + (Phdr.p_vaddr + Phdr.p_memsz > Sec.getAddress())) + return Sec.getAddress() - Phdr.p_vaddr + Phdr.p_paddr; + + // Return section's VMA if it isn't in a PT_LOAD segment. + return Sec.getAddress(); +} + +uint64_t llvm::getELFSectionLMA(const object::ELFSectionRef &Sec) { + if (const auto *ELFObj = dyn_cast(Sec.getObject())) + return getSectionLMA(ELFObj->getELFFile(), Sec); + else if (const auto *ELFObj = dyn_cast(Sec.getObject())) + return getSectionLMA(ELFObj->getELFFile(), Sec); + else if (const auto *ELFObj = dyn_cast(Sec.getObject())) + return getSectionLMA(ELFObj->getELFFile(), Sec); + const auto *ELFObj = cast(Sec.getObject()); + return getSectionLMA(ELFObj->getELFFile(), Sec); +} + template void printDynamicSection(const ELFFile *Elf, StringRef Filename) { auto ProgramHeaderOrError = Elf->program_headers(); Index: tools/llvm-objdump/llvm-objdump.h =================================================================== --- tools/llvm-objdump/llvm-objdump.h +++ tools/llvm-objdump/llvm-objdump.h @@ -21,6 +21,7 @@ class COFFObjectFile; class COFFImportFile; class ELFObjectFileBase; +class ELFSectionRef; class MachOObjectFile; class MachOUniversalBinary; class ObjectFile; @@ -137,6 +138,8 @@ const object::RelocationRef &RelRef, llvm::SmallVectorImpl &Result); +uint64_t getELFSectionLMA(const object::ELFSectionRef& Sec); + void error(std::error_code ec); bool isRelocAddressLess(object::RelocationRef A, object::RelocationRef B); void parseInputMachO(StringRef Filename); Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -180,6 +180,10 @@ cl::NotHidden, cl::aliasopt(SectionHeaders)); +cl::opt + ShowLMA("show-lma", + cl::desc("Display LMA column when dumping ELF section headers")); + cl::list llvm::FilterSections("section", cl::desc("Operate on the specified sections only. " "With -macho dump segment,section")); @@ -1486,22 +1490,48 @@ } } +// Returns true if we need to show LMA column when dumping section headers. We +// show it only when the platform is ELF and either we have at least one section +// whose VMA and LMA are different or/and when --show-lma flag is used. +static bool shouldDisplayLMA(const ObjectFile *Obj) { + if (!Obj->isELF()) + return false; + for (const SectionRef &S : ToolSectionFilter(*Obj)) + if (S.getAddress() != getELFSectionLMA(S)) + return true; + return ShowLMA; +} + void llvm::printSectionHeaders(const ObjectFile *Obj) { - outs() << "Sections:\n" - "Idx Name Size Address Type\n"; + bool HasLMAColumn = shouldDisplayLMA(Obj); + if (HasLMAColumn) + outs() << "Sections:\n" + "Idx Name Size VMA LMA " + "Type\n"; + else + outs() << "Sections:\n" + "Idx Name Size VMA Type\n"; + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { StringRef Name; error(Section.getName(Name)); - uint64_t Address = Section.getAddress(); + uint64_t VMA = Section.getAddress(); uint64_t Size = Section.getSize(); bool Text = Section.isText(); bool Data = Section.isData(); bool BSS = Section.isBSS(); std::string Type = (std::string(Text ? "TEXT " : "") + (Data ? "DATA " : "") + (BSS ? "BSS" : "")); - outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", - (unsigned)Section.getIndex(), Name.str().c_str(), Size, - Address, Type.c_str()); + + if (HasLMAColumn) + outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %016" PRIx64 + " %s\n", + (unsigned)Section.getIndex(), Name.str().c_str(), Size, + VMA, getELFSectionLMA(Section), Type.c_str()); + else + outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", + (unsigned)Section.getIndex(), Name.str().c_str(), Size, + VMA, Type.c_str()); } outs() << "\n"; }