[llvm-objdump] - Print LMAs when dumping section headers.

When --section-headers is used, GNU objdump prints both LMA and VMA for sections.
llvm-objdump does not do that what makes it's output be slightly inconsistent.

Patch teaches llvm-objdump to print LMA/VMA for ELF file formats.
The behavior for other formats remains unchanged.

Differential revision: https://reviews.llvm.org/D57146

llvm-svn: 352366
This commit is contained in:
George Rimar 2019-01-28 14:11:35 +00:00
parent e49f9fd308
commit a09a70b235
10 changed files with 181 additions and 14 deletions

View File

@ -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:

View File

@ -2,5 +2,5 @@
; RUN: | FileCheck %s
; CHECK: Sections:
; CHECK: Idx Name Size Address Type
; CHECK: Idx Name Size VMA Type
; CHECK-NOT: {{.}}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,60 @@
# 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

View File

@ -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

View File

@ -132,6 +132,35 @@ llvm::getELFRelocationValueString(const ELFObjectFileBase *Obj,
return getRelocationValueString(ELF64BE, Rel, Result);
}
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();

View File

@ -185,6 +185,10 @@ static cl::alias SectionHeadersShorter("h",
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"));
@ -1517,25 +1521,48 @@ void llvm::printDynamicRelocations(const ObjectFile *Obj) {
}
}
// 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";
}

View File

@ -21,6 +21,7 @@ namespace object {
class COFFObjectFile;
class COFFImportFile;
class ELFObjectFileBase;
class ELFSectionRef;
class MachOObjectFile;
class MachOUniversalBinary;
class ObjectFile;
@ -137,6 +138,8 @@ getMachORelocationValueString(const object::MachOObjectFile *Obj,
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);