# 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:
; RUN: | FileCheck %s
; CHECK: Sections:
-; CHECK: Idx Name Size Address Type
+; CHECK: Idx Name Size VMA Type
; CHECK-NOT: {{.}}
; 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
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
--- /dev/null
+# 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
--- /dev/null
+# RUN: yaml2obj %s > %t
+
+## If there are no sections with different LMA to 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
# 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
}
template <class ELFT>
+static uint64_t getSectionLMA(const ELFFile<ELFT> *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<ELFT>::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<ELF32LEObjectFile>(Sec.getObject()))
+ return getSectionLMA(ELFObj->getELFFile(), Sec);
+ else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Sec.getObject()))
+ return getSectionLMA(ELFObj->getELFFile(), Sec);
+ else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Sec.getObject()))
+ return getSectionLMA(ELFObj->getELFFile(), Sec);
+ const auto *ELFObj = cast<ELF64BEObjectFile>(Sec.getObject());
+ return getSectionLMA(ELFObj->getELFFile(), Sec);
+}
+
+template <class ELFT>
void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) {
auto ProgramHeaderOrError = Elf->program_headers();
if (!ProgramHeaderOrError)
cl::NotHidden,
cl::aliasopt(SectionHeaders));
+static cl::opt<bool>
+ ShowLMA("show-lma",
+ cl::desc("Display LMA column when dumping ELF section headers"));
+
cl::list<std::string>
llvm::FilterSections("section", cl::desc("Operate on the specified sections only. "
"With -macho dump segment,section"));
}
}
+// 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 and/or 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();
- if (shouldAdjustVA(Section))
- Address += AdjustVMA;
-
+ 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";
}
class COFFObjectFile;
class COFFImportFile;
class ELFObjectFileBase;
+class ELFSectionRef;
class MachOObjectFile;
class MachOUniversalBinary;
class ObjectFile;
const object::RelocationRef &RelRef,
llvm::SmallVectorImpl<char> &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);