Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -83,6 +83,8 @@ SubtargetFeatures getRISCVFeatures() const; void setARMSubArch(Triple &TheTriple) const override; + + virtual uint16_t getEType() const = 0; }; class ELFSectionRef : public SectionRef { @@ -200,6 +202,7 @@ template class ELFObjectFile : public ELFObjectFileBase { uint16_t getEMachine() const override; + uint16_t getEType() const override; uint64_t getSymbolSize(DataRefImpl Sym) const override; public: @@ -507,6 +510,11 @@ return EF.getHeader()->e_machine; } +template +uint16_t ELFObjectFile::getEType() const { + return EF.getHeader()->e_type; +} + template uint64_t ELFObjectFile::getSymbolSize(DataRefImpl Sym) const { return getSymbol(Sym)->st_size; @@ -792,8 +800,6 @@ 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); if (sec->sh_type == ELF::SHT_REL) return getRel(Rel)->r_offset; Index: tools/llvm-objdump/llvm-objdump.h =================================================================== --- tools/llvm-objdump/llvm-objdump.h +++ tools/llvm-objdump/llvm-objdump.h @@ -56,6 +56,7 @@ extern cl::opt DisSymName; extern cl::opt NonVerbose; extern cl::opt Relocations; +extern cl::opt DynamicRelocations; extern cl::opt SectionHeaders; extern cl::opt SectionContents; extern cl::opt SymbolTable; @@ -88,6 +89,7 @@ void printWeakBindTable(object::ObjectFile *o); void printRawClangAST(const object::ObjectFile *o); void PrintRelocations(const object::ObjectFile *o); +void PrintDynamicRelocations(const object::ObjectFile *o); void PrintSectionHeaders(const object::ObjectFile *o); void PrintSectionContents(const object::ObjectFile *o); void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName, Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -93,6 +93,9 @@ cl::opt llvm::Relocations("r", cl::desc("Display the relocation entries in the file")); +cl::opt +llvm::DynamicRelocations("R", cl::desc("Display the dynamic relocation entries in the file")); + cl::opt llvm::SectionContents("s", cl::desc("Display the content of each section")); @@ -433,6 +436,7 @@ uint8_t type = RelRef.getType(); StringRef res; int64_t addend = 0; + bool undef = false; switch (Sec->sh_type) { default: return object_error::parse_failed; @@ -443,27 +447,32 @@ case ELF::SHT_RELA: { const Elf_Rela *ERela = Obj->getRela(Rel); addend = ERela->r_addend; + undef = ERela->getSymbol(false) == 0; break; } } - symbol_iterator SI = RelRef.getSymbol(); - const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl()); StringRef Target; - if (symb->getType() == ELF::STT_SECTION) { - Expected SymSI = SI->getSection(); - if (!SymSI) - return errorToErrorCode(SymSI.takeError()); - const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); - auto SecName = EF.getSectionName(SymSec); - if (!SecName) - return errorToErrorCode(SecName.takeError()); - Target = *SecName; - } else { - Expected SymName = symb->getName(StrTab); - if (!SymName) - return errorToErrorCode(SymName.takeError()); - Target = *SymName; + if (!undef) { + symbol_iterator SI = RelRef.getSymbol(); + const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl()); + if (symb->getType() == ELF::STT_SECTION) { + Expected SymSI = SI->getSection(); + if (!SymSI) + return errorToErrorCode(SymSI.takeError()); + const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); + auto SecName = EF.getSectionName(SymSec); + if (!SecName) + return errorToErrorCode(SecName.takeError()); + Target = *SecName; + } else { + Expected SymName = symb->getName(StrTab); + if (!SymName) + return errorToErrorCode(SymName.takeError()); + Target = *SymName; + } } + else + Target = "*ABS*"; switch (EF.getHeader()->e_machine) { case ELF::EM_X86_64: switch (type) { @@ -476,6 +485,19 @@ fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); } break; + case ELF::R_X86_64_RELATIVE: + case ELF::R_X86_64_GLOB_DAT: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + StringRef FmtNum = Obj->getBytesInAddress() > 4 ? "0x%016" PRIx64 : + "0x%08" PRIx64; + fmt << Target; + if (undef) + fmt << (addend < 0 ? "" : "+") << format(FmtNum.data(), addend); + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; case ELF::R_X86_64_8: case ELF::R_X86_64_16: case ELF::R_X86_64_32: @@ -1789,6 +1811,39 @@ } } +void llvm::PrintDynamicRelocations(const ObjectFile *Obj) { + + // For the moment, this option is for ELF only + if (!Obj->isELF()) + return; + + const auto *Elf = dyn_cast(Obj); + + if (Elf->getEType() != ELF::ET_DYN) { + error("not a dynamic object"); + return; + } + + StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : + "%08" PRIx64; + + // TODO: ensure the relocation is a dynamic relocation + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { + if (Section.relocation_begin() == Section.relocation_end()) + continue; + outs() << "DYNAMIC RELOCATION RECORDS\n"; + for (const RelocationRef &Reloc : Section.relocations()) { + uint64_t address = Reloc.getOffset(); + SmallString<32> relocname; + SmallString<32> valuestr; + Reloc.getTypeName(relocname); + error(getRelocationValueString(Reloc, valuestr)); + outs() << format(Fmt.data(), address) << " " << relocname << " " + << valuestr << "\n"; + } + } +} + void llvm::PrintSectionHeaders(const ObjectFile *Obj) { outs() << "Sections:\n" "Idx Name Size Address Type\n"; @@ -2131,6 +2186,8 @@ DisassembleObject(o, Relocations); if (Relocations && !Disassemble) PrintRelocations(o); + if (DynamicRelocations) + PrintDynamicRelocations(o); if (SectionHeaders) PrintSectionHeaders(o); if (SectionContents) @@ -2248,6 +2305,7 @@ Disassemble = true; if (!Disassemble && !Relocations + && !DynamicRelocations && !SectionHeaders && !SectionContents && !SymbolTable