Index: include/llvm/Object/COFF.h =================================================================== --- include/llvm/Object/COFF.h +++ include/llvm/Object/COFF.h @@ -702,6 +702,8 @@ relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; + bool getRelocationIsDynamic(DataRefImpl Rel) const override { return false; } + uint64_t getRelocationAddress(DataRefImpl Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; uint64_t getRelocationType(DataRefImpl Rel) const override; Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -227,6 +227,8 @@ section_iterator getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; + bool getRelocationIsDynamic(DataRefImpl Rel) const override; + uint64_t getRelocationAddress(DataRefImpl Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; uint64_t getRelocationType(DataRefImpl Rel) const override; @@ -672,9 +674,8 @@ if (!symbolIdx) return symbol_end(); - bool IsDyn = Rel.d.b & 1; DataRefImpl SymbolData; - if (IsDyn) + if (getRelocationIsDynamic(Rel)) SymbolData = toDRI(DotDynSymSec, symbolIdx); else SymbolData = toDRI(DotSymtabSec, symbolIdx); @@ -682,7 +683,23 @@ } template -uint64_t ELFObjectFile::getRelocationOffset(DataRefImpl Rel) const { +bool ELFObjectFile::getRelocationIsDynamic(DataRefImpl Rel) const { + return Rel.d.b & 1; +} + +template +uint64_t ELFObjectFile::getRelocationAddress(DataRefImpl Rel) const { + assert(EF.getHeader()->e_type != ELF::ET_REL && + "Only executable and shared objcet files have relocation addresses"); + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->r_offset; + + return getRela(Rel)->r_offset; +} + +template +uint64_t ELFObjectFile::getRelocationOffset(DataRefImpl Rel) const { assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); const Elf_Shdr *sec = getRelSection(Rel); Index: include/llvm/Object/MachO.h =================================================================== --- include/llvm/Object/MachO.h +++ include/llvm/Object/MachO.h @@ -231,6 +231,8 @@ relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; + bool getRelocationIsDynamic(DataRefImpl Rel) const override { return false; } + uint64_t getRelocationAddress(DataRefImpl Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; section_iterator getRelocationSection(DataRefImpl Rel) const; Index: include/llvm/Object/ObjectFile.h =================================================================== --- include/llvm/Object/ObjectFile.h +++ include/llvm/Object/ObjectFile.h @@ -50,6 +50,8 @@ void moveNext(); + bool isDynamic() const; + uint64_t getAddress() const; uint64_t getOffset() const; symbol_iterator getSymbol() const; uint64_t getType() const; @@ -228,6 +230,8 @@ // Same as above for RelocationRef. friend class RelocationRef; virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; + virtual bool getRelocationIsDynamic(DataRefImpl Rel) const = 0; + virtual uint64_t getRelocationAddress(DataRefImpl Rel) const = 0; virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0; @@ -435,6 +439,14 @@ return OwningObject->moveRelocationNext(RelocationPimpl); } +inline bool RelocationRef::isDynamic() const { + return OwningObject->getRelocationIsDynamic(RelocationPimpl); +} + +inline uint64_t RelocationRef::getAddress() const { + return OwningObject->getRelocationAddress(RelocationPimpl); +} + inline uint64_t RelocationRef::getOffset() const { return OwningObject->getRelocationOffset(RelocationPimpl); } Index: lib/Object/COFFObjectFile.cpp =================================================================== --- lib/Object/COFFObjectFile.cpp +++ lib/Object/COFFObjectFile.cpp @@ -971,6 +971,11 @@ reinterpret_cast(Rel.p) + 1); } +uint64_t COFFObjectFile::getRelocationAddress(DataRefImpl Rel) const { + const coff_relocation *R = toRel(Rel); + return R->VirtualAddress; +} + uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { const coff_relocation *R = toRel(Rel); return R->VirtualAddress; Index: lib/Object/MachOObjectFile.cpp =================================================================== --- lib/Object/MachOObjectFile.cpp +++ lib/Object/MachOObjectFile.cpp @@ -666,6 +666,14 @@ ++Rel.d.b; } +uint64_t MachOObjectFile::getRelocationAddress(DataRefImpl Rel) const { + assert((getHeader().filetype == MachO::MH_DYLIB || + getHeader().filetype == MachO::MH_EXECUTE) && + "Only implemented for MH_DYLIB and MH_EXECUTE"); + MachO::any_relocation_info RE = getRelocation(Rel); + return getAnyRelocationAddress(RE); +} + uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { assert(getHeader().filetype == MachO::MH_OBJECT && "Only implemented for MH_OBJECT"); Index: test/tools/llvm-objdump/X86/relocations-in-nonrelocatable.test =================================================================== --- test/tools/llvm-objdump/X86/relocations-in-nonrelocatable.test +++ test/tools/llvm-objdump/X86/relocations-in-nonrelocatable.test @@ -0,0 +1,9 @@ +// This test checks that relocation in nonrelocatable files are printed +// RUN: llvm-objdump -r %p/Inputs/relocations-in-nonrelocatable.elf-x86_64 | FileCheck %s + +// (main.c) +// void g(void){} +// int main(void) { g(); }; +// gcc main.c -o main -Wl,--emit-relocs + +CHECK: 00000000000000f8 R_X86_64_PC32 g-4-P \ No newline at end of file Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -440,23 +440,26 @@ } } symbol_iterator SI = RelRef.getSymbol(); - const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl()); StringRef Target; - if (symb->getType() == ELF::STT_SECTION) { - ErrorOr SymSI = SI->getSection(); - if (std::error_code EC = SymSI.getError()) - return EC; - const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); - ErrorOr SecName = EF.getSectionName(SymSec); - if (std::error_code EC = SecName.getError()) - return EC; - Target = *SecName; - } else { - ErrorOr SymName = symb->getName(StrTab); - if (!SymName) - return SymName.getError(); - Target = *SymName; - } + if (SI != Obj->symbol_end()) { + const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl()); + if (symb->getType() == ELF::STT_SECTION) { + ErrorOr SymSI = SI->getSection(); + if (std::error_code EC = SymSI.getError()) + return EC; + const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); + ErrorOr SecName = EF.getSectionName(SymSec); + if (std::error_code EC = SecName.getError()) + return EC; + Target = *SecName; + } else { + ErrorOr SymName = symb->getName(StrTab); + if (!SymName) + return SymName.getError(); + Target = *SymName; + } + } else + Target = "*ABS*"; switch (EF.getHeader()->e_machine) { case ELF::EM_X86_64: switch (type) { @@ -1188,20 +1191,39 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64; - // Regular objdump doesn't print relocations in non-relocatable object - // files. - if (!Obj->isRelocatableObject()) - return; + std::map SectionAddress; + for (section_iterator i (Obj->section_begin()), n (Obj->section_end()); i != n; ++i) + SectionAddress [i->getAddress()] = *i; for (const SectionRef &Section : ToolSectionFilter(*Obj)) { + bool PrintHeader = true; if (Section.relocation_begin() == Section.relocation_end()) continue; - StringRef secname; - error(Section.getName(secname)); - outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n"; for (const RelocationRef &Reloc : Section.relocations()) { + if (Reloc.isDynamic()) + continue; + if (PrintHeader) { + StringRef secname; + error(Section.getName(secname)); + outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n"; + PrintHeader = false; + } bool hidden = getHidden(Reloc); - uint64_t address = Reloc.getOffset(); + uint64_t Address; + if (Obj->isRelocatableObject()) + Address = Reloc.getOffset(); + else { + Address = Reloc.getAddress(); + auto BoundingSection = SectionAddress.upper_bound(Address); + if (BoundingSection == SectionAddress.begin()) + // Lower than any section + continue; + --BoundingSection; + if ((BoundingSection->first + BoundingSection->second.getSize()) < Address) + // Not in closest section + continue; + Address -= BoundingSection->first; + } SmallString<32> relocname; SmallString<32> valuestr; if (hidden) @@ -1208,7 +1230,7 @@ continue; Reloc.getTypeName(relocname); error(getRelocationValueString(Reloc, valuestr)); - outs() << format(Fmt.data(), address) << " " << relocname << " " + outs() << format(Fmt.data(), Address) << " " << relocname << " " << valuestr << "\n"; } outs() << "\n";