diff --git a/docs/Extensions.rst b/docs/Extensions.rst index 9655adcb630..fac2289921e 100644 --- a/docs/Extensions.rst +++ b/docs/Extensions.rst @@ -329,6 +329,36 @@ symbol is undefined, then that symbol is defined as if ``.weak symbol`` has been written at the end of the file. This forces the symbol to show up in the symbol table. +``SHT_LLVM_ADDRSIG`` Section (address-significance table) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section is used to mark symbols as address-significant, i.e. the address +of the symbol is used in a comparison or leaks outside the translation unit. It +has the same meaning as the absence of the LLVM attributes ``unnamed_addr`` +and ``local_unnamed_addr``. + +Any sections referred to by symbols that are not marked as address-significant +in any object file may be safely merged by a linker without breaking the +address uniqueness guarantee provided by the C and C++ language standards. + +The contents of the section are a sequence of ULEB128-encoded integers +referring to the symbol table indexes of the address-significant symbols. + +There are two associated assembly directives: + +.. code-block:: gas + + .addrsig + +This instructs the assembler to emit an address-significance table. Without +this directive, all symbols are considered address-significant. + +.. code-block:: gas + + .addrsig_sym sym + +This marks ``sym`` as address-significant. + CodeView-Dependent ------------------ diff --git a/include/llvm/BinaryFormat/ELF.h b/include/llvm/BinaryFormat/ELF.h index 3756d03e301..0f3f1939ce6 100644 --- a/include/llvm/BinaryFormat/ELF.h +++ b/include/llvm/BinaryFormat/ELF.h @@ -797,6 +797,8 @@ enum : unsigned { SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table. SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01, // LLVM Linker Options. SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile. + SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols + // for safe ICF. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index e21eb680f1c..035206dce93 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -170,6 +170,9 @@ public: SMLoc Loc = SMLoc()) override; void EmitFileDirective(StringRef Filename) override; + void EmitAddrsig() override; + void EmitAddrsigSym(const MCSymbol *Sym) override; + void FinishImpl() override; /// Emit the absolute difference between two symbols if possible. diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 873b0d56bff..8bae2bf2008 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -92,6 +92,15 @@ public: bool InSet, bool IsPCRel) const; + /// Tell the object writer to emit an address-significance table during + /// writeObject(). If this function is not called, all symbols are treated as + /// address-significant. + virtual void emitAddrsigSection() {} + + /// Record the given symbol in the address-significance table to be written + /// diring writeObject(). + virtual void addAddrsigSymbol(const MCSymbol *Sym) {} + /// Write the object file and returns the number of bytes written. /// /// This routine is called by the assembler after layout and relaxation is diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index d33c31979b6..ff518d2c8ad 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -924,6 +924,9 @@ public: return true; } + virtual void EmitAddrsig() {} + virtual void EmitAddrsigSym(const MCSymbol *Sym) {} + /// Emit the given \p Instruction into the current section. /// PrintSchedInfo == true then schedul comment should be added to output virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index f4117e75516..db531f75c87 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -43,6 +43,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Host.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/StringSaver.h" @@ -199,6 +200,8 @@ public: const RevGroupMapTy &RevGroupMap, SectionOffsetsTy &SectionOffsets); + void writeAddrsigSection(); + MCSectionELF *createRelocationSection(MCContext &Ctx, const MCSectionELF &Sec); @@ -232,6 +235,9 @@ class ELFObjectWriter : public MCObjectWriter { DenseMap Renames; + bool EmitAddrsigSection = false; + std::vector AddrsigSyms; + bool hasRelocationAddend() const; bool shouldRelocateWithSymbol(const MCAssembler &Asm, @@ -267,6 +273,11 @@ public: void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; + void emitAddrsigSection() override { EmitAddrsigSection = true; } + void addAddrsigSymbol(const MCSymbol *Sym) override { + AddrsigSyms.push_back(Sym); + } + friend struct ELFWriter; }; @@ -747,6 +758,11 @@ void ELFWriter::computeSymbolTable( SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); } +void ELFWriter::writeAddrsigSection() { + for (const MCSymbol *Sym : OWriter.AddrsigSyms) + encodeULEB128(Sym->getIndex(), W.OS); +} + MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, const MCSectionELF &Sec) { if (OWriter.Relocations[&Sec].empty()) @@ -977,6 +993,7 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, case ELF::SHT_SYMTAB_SHNDX: case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: + case ELF::SHT_LLVM_ADDRSIG: sh_link = SymbolTableIndex; break; @@ -1123,6 +1140,13 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { // string tables. StrTabBuilder.finalize(); } else { + MCSectionELF *AddrsigSection; + if (OWriter.EmitAddrsigSection) { + AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG, + ELF::SHF_EXCLUDE); + addToSectionTable(AddrsigSection); + } + // Compute symbol table information. computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets); @@ -1139,6 +1163,13 @@ uint64_t ELFWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { uint64_t SecEnd = W.OS.tell(); SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); } + + if (OWriter.EmitAddrsigSection) { + uint64_t SecStart = W.OS.tell(); + writeAddrsigSection(); + uint64_t SecEnd = W.OS.tell(); + SectionOffsets[AddrsigSection] = std::make_pair(SecStart, SecEnd); + } } if (CGProfileSection) { @@ -1238,6 +1269,12 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, Renames.insert(std::make_pair(&Symbol, Alias)); } + + for (const MCSymbol *&Sym : AddrsigSyms) { + if (const MCSymbol *R = Renames.lookup(cast(Sym))) + Sym = R; + Sym->setUsedInReloc(); + } } // It is always valid to create a relocation with a symbol. It is preferable diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 5398cfea786..1429f647b61 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -319,6 +319,9 @@ public: const MCExpr *Expr, SMLoc Loc, const MCSubtargetInfo &STI) override; + void EmitAddrsig() override; + void EmitAddrsigSym(const MCSymbol *Sym) override; + /// If this file is backed by an assembly streamer, this dumps the specified /// string in the output .s file. This capability is indicated by the /// hasRawTextSupport() predicate. @@ -1846,6 +1849,17 @@ bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, return false; } +void MCAsmStreamer::EmitAddrsig() { + OS << "\t.addrsig"; + EmitEOL(); +} + +void MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) { + OS << "\t.addrsig_sym "; + Sym->print(OS, MAI); + EmitEOL(); +} + /// EmitRawText - If this file is backed by an assembly streamer, this dumps /// the specified string in the output .s file. This capability is /// indicated by the hasRawTextSupport() predicate. diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 9d536883b98..4b6dad5ce8f 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -660,6 +660,15 @@ void MCObjectStreamer::EmitFileDirective(StringRef Filename) { getAssembler().addFileName(Filename); } +void MCObjectStreamer::EmitAddrsig() { + getAssembler().getWriter().emitAddrsigSection(); +} + +void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) { + getAssembler().registerSymbol(*Sym); + getAssembler().getWriter().addAddrsigSymbol(Sym); +} + void MCObjectStreamer::FinishImpl() { getContext().RemapDebugPaths(); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index f79a21b05d2..68e6e94a492 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -506,6 +506,8 @@ private: DK_ERROR, DK_WARNING, DK_PRINT, + DK_ADDRSIG, + DK_ADDRSIG_SYM, DK_END }; @@ -654,6 +656,10 @@ private: // .print bool parseDirectivePrint(SMLoc DirectiveLoc); + // Directives to support address-significance tables. + bool parseDirectiveAddrsig(); + bool parseDirectiveAddrsigSym(); + void initializeDirectiveKindMap(); }; @@ -2127,6 +2133,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveDS(IDVal, 12); case DK_PRINT: return parseDirectivePrint(IDLoc); + case DK_ADDRSIG: + return parseDirectiveAddrsig(); + case DK_ADDRSIG_SYM: + return parseDirectiveAddrsigSym(); } return Error(IDLoc, "unknown directive"); @@ -5291,6 +5301,8 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".ds.w"] = DK_DS_W; DirectiveKindMap[".ds.x"] = DK_DS_X; DirectiveKindMap[".print"] = DK_PRINT; + DirectiveKindMap[".addrsig"] = DK_ADDRSIG; + DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { @@ -5530,6 +5542,21 @@ bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) { return false; } +bool AsmParser::parseDirectiveAddrsig() { + getStreamer().EmitAddrsig(); + return false; +} + +bool AsmParser::parseDirectiveAddrsigSym() { + StringRef Name; + if (check(parseIdentifier(Name), + "expected identifier in '.addrsig_sym' directive")) + return true; + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + getStreamer().EmitAddrsigSym(Sym); + return false; +} + // We are comparing pointers, but the pointers are relative to a single string. // Thus, this should always be deterministic. static int rewritesSort(const AsmRewrite *AsmRewriteA, diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp index d58a79115bd..3e2161a9396 100644 --- a/lib/Object/ELF.cpp +++ b/lib/Object/ELF.cpp @@ -246,6 +246,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LINKER_OPTIONS); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH_PROFILE); + STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ADDRSIG); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef); diff --git a/lib/ObjectYAML/ELFYAML.cpp b/lib/ObjectYAML/ELFYAML.cpp index 8964f5c811b..f916b5d5f39 100644 --- a/lib/ObjectYAML/ELFYAML.cpp +++ b/lib/ObjectYAML/ELFYAML.cpp @@ -444,6 +444,7 @@ void ScalarEnumerationTraits::enumeration( ECase(SHT_LLVM_ODRTAB); ECase(SHT_LLVM_LINKER_OPTIONS); ECase(SHT_LLVM_CALL_GRAPH_PROFILE); + ECase(SHT_LLVM_ADDRSIG); ECase(SHT_GNU_ATTRIBUTES); ECase(SHT_GNU_HASH); ECase(SHT_GNU_verdef); diff --git a/test/MC/ELF/addrsig-error.s b/test/MC/ELF/addrsig-error.s new file mode 100644 index 00000000000..3383de54641 --- /dev/null +++ b/test/MC/ELF/addrsig-error.s @@ -0,0 +1,5 @@ +// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s +// CHECK: Undefined temporary symbol + +.addrsig +.addrsig_sym .Lundef diff --git a/test/MC/ELF/addrsig.s b/test/MC/ELF/addrsig.s new file mode 100644 index 00000000000..256d8089d35 --- /dev/null +++ b/test/MC/ELF/addrsig.s @@ -0,0 +1,86 @@ +// RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -s -t -sd -elf-addrsig | FileCheck %s +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -split-dwarf-file %t.dwo -o - | llvm-readobj -s -t -sd -elf-addrsig | FileCheck %s +// RUN: llvm-readobj -s %t.dwo | FileCheck --check-prefix=DWO %s + +// CHECK: Name: .llvm_addrsig +// CHECK-NEXT: Type: SHT_LLVM_ADDRSIG (0x6FFF4C03) +// CHECK-NEXT: Flags [ (0x80000000) +// CHECK-NEXT: SHF_EXCLUDE (0x80000000) +// CHECK-NEXT: ] +// CHECK-NEXT: Address: +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 4 +// CHECK-NEXT: Link: 4 +// CHECK-NEXT: Info: 0 +// CHECK-NEXT: AddressAlignment: 1 +// CHECK-NEXT: EntrySize: 0 +// CHECK-NEXT: SectionData ( +// CHECK-NEXT: 0000: 03050201 +// CHECK-NEXT: ) +// CHECK-NEXT: } +// CHECK-NEXT: Section { +// CHECK-NEXT: Index: 4 +// CHECK-NEXT: Name: .symtab + +// CHECK: Name: .Llocal +// CHECK-NEXT: Value: +// CHECK-NEXT: Size: +// CHECK-NEXT: Binding: +// CHECK-NEXT: Type: +// CHECK-NEXT: Other: +// CHECK-NEXT: Section: +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: local +// CHECK-NEXT: Value: +// CHECK-NEXT: Size: +// CHECK-NEXT: Binding: +// CHECK-NEXT: Type: +// CHECK-NEXT: Other: +// CHECK-NEXT: Section: +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: g1 +// CHECK-NEXT: Value: +// CHECK-NEXT: Size: +// CHECK-NEXT: Binding: +// CHECK-NEXT: Type: +// CHECK-NEXT: Other: +// CHECK-NEXT: Section: +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: g2 +// CHECK-NEXT: Value: +// CHECK-NEXT: Size: +// CHECK-NEXT: Binding: +// CHECK-NEXT: Type: +// CHECK-NEXT: Other: +// CHECK-NEXT: Section: +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: g3 + +// CHECK: Addrsig [ +// CHECK-NEXT: Sym: g1 (3) +// CHECK-NEXT: Sym: g3 (5) +// CHECK-NEXT: Sym: local (2) +// CHECK-NEXT: Sym: .Llocal (1) +// CHECK-NEXT: ] + +// ASM: .addrsig +.addrsig +// ASM: .addrsig_sym g1 +.addrsig_sym g1 +.globl g2 +// ASM: .addrsig_sym g3 +.addrsig_sym g3 +// ASM: .addrsig_sym local +.addrsig_sym local +// ASM: .addrsig_sym .Llocal +.addrsig_sym .Llocal + +local: +.Llocal: + +// DWO-NOT: .llvm_addrsig diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 763d68a8e75..130c19cc888 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -44,6 +44,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/ScopedPrinter.h" @@ -170,6 +171,7 @@ public: void printHashHistogram() override; void printCGProfile() override; + void printAddrsig() override; void printNotes() override; @@ -219,6 +221,7 @@ private: const Elf_GnuHash *GnuHashTable = nullptr; const Elf_Shdr *DotSymtabSec = nullptr; const Elf_Shdr *DotCGProfileSec = nullptr; + const Elf_Shdr *DotAddrsigSec = nullptr; StringRef DynSymtabName; ArrayRef ShndxTable; @@ -272,6 +275,7 @@ public: void printSymbolsHelper(bool IsDynamic) const; const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } + const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } ArrayRef getShndxTable() const { return ShndxTable; } StringRef getDynamicStringTable() const { return DynamicStringTable; } const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } @@ -352,6 +356,7 @@ public: StringRef SectionName) = 0; virtual void printHashHistogram(const ELFFile *Obj) = 0; virtual void printCGProfile(const ELFFile *Obj) = 0; + virtual void printAddrsig(const ELFFile *Obj) = 0; virtual void printNotes(const ELFFile *Obj) = 0; virtual void printELFLinkerOptions(const ELFFile *Obj) = 0; virtual void printMipsGOT(const MipsGOTParser &Parser) = 0; @@ -384,6 +389,7 @@ public: void printSectionAsString(const ELFO *Obj, StringRef SectionName) override; void printHashHistogram(const ELFFile *Obj) override; void printCGProfile(const ELFFile *Obj) override; + void printAddrsig(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; void printELFLinkerOptions(const ELFFile *Obj) override; void printMipsGOT(const MipsGOTParser &Parser) override; @@ -448,6 +454,7 @@ public: void printSectionAsString(const ELFO *Obj, StringRef SectionName) override; void printHashHistogram(const ELFFile *Obj) override; void printCGProfile(const ELFFile *Obj) override; + void printAddrsig(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; void printELFLinkerOptions(const ELFFile *Obj) override; void printMipsGOT(const MipsGOTParser &Parser) override; @@ -1441,6 +1448,12 @@ ELFDumper::ELFDumper(const ELFFile *Obj, ScopedPrinter &Writer) if (DotCGProfileSec != nullptr) reportError("Multiple .note.llvm.cgprofile"); DotCGProfileSec = &Sec; + break; + case ELF::SHT_LLVM_ADDRSIG: + if (DotAddrsigSec != nullptr) + reportError("Multiple .llvm_addrsig"); + DotAddrsigSec = &Sec; + break; } } @@ -2460,6 +2473,10 @@ template void ELFDumper::printGroupSections() { ELFDumperStyle->printGroupSections(Obj); } +template void ELFDumper::printAddrsig() { + ELFDumperStyle->printAddrsig(Obj); +} + static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, StringRef Str2) { OS.PadToColumn(2u); @@ -2840,6 +2857,8 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) { return "LLVM_LINKER_OPTIONS"; case SHT_LLVM_CALL_GRAPH_PROFILE: return "LLVM_CALL_GRAPH_PROFILE"; + case SHT_LLVM_ADDRSIG: + return "LLVM_ADDRSIG"; // FIXME: Parse processor specific GNU attributes case SHT_GNU_ATTRIBUTES: return "ATTRIBUTES"; @@ -3541,6 +3560,11 @@ void GNUStyle::printCGProfile(const ELFFile *Obj) { OS << "GNUStyle::printCGProfile not implemented\n"; } +template +void GNUStyle::printAddrsig(const ELFFile *Obj) { + OS << "GNUStyle::printAddrsig not implemented\n"; +} + static std::string getGNUNoteTypeName(const uint32_t NT) { static const struct { uint32_t ID; @@ -4407,6 +4431,27 @@ void LLVMStyle::printCGProfile(const ELFFile *Obj) { } } +template +void LLVMStyle::printAddrsig(const ELFFile *Obj) { + ListScope L(W, "Addrsig"); + if (!this->dumper()->getDotAddrsigSec()) + return; + ArrayRef Contents = unwrapOrError( + Obj->getSectionContents(this->dumper()->getDotAddrsigSec())); + const uint8_t *Cur = Contents.begin(); + const uint8_t *End = Contents.end(); + while (Cur != End) { + unsigned Size; + const char *Err; + uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); + if (Err) + reportError(Err); + W.printNumber("Sym", this->dumper()->getStaticSymbolName(SymIndex), + SymIndex); + Cur += Size; + } +} + template void LLVMStyle::printNotes(const ELFFile *Obj) { W.startLine() << "printNotes not implemented!\n"; diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 09c8acb7493..ba036be6b60 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -52,6 +52,7 @@ public: virtual void printGroupSections() {} virtual void printHashHistogram() {} virtual void printCGProfile() {} + virtual void printAddrsig() {} virtual void printNotes() {} virtual void printELFLinkerOptions() {} diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 39567b80235..5c8a8803069 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -302,6 +302,9 @@ namespace opts { cl::opt CGProfile("elf-cg-profile", cl::desc("Display callgraph profile section")); + cl::opt Addrsig("elf-addrsig", + cl::desc("Display address-significance table")); + cl::opt Output("elf-output-style", cl::desc("Specify ELF dump style"), cl::values(clEnumVal(LLVM, "LLVM default style"), @@ -469,6 +472,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) { Dumper->printHashHistogram(); if (opts::CGProfile) Dumper->printCGProfile(); + if (opts::Addrsig) + Dumper->printAddrsig(); if (opts::Notes) Dumper->printNotes(); }