diff options
Diffstat (limited to 'tools')
46 files changed, 1333 insertions, 673 deletions
diff --git a/tools/Makefile b/tools/Makefile index d8534866c3d3..a47710f111a4 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -19,9 +19,8 @@ else OPTIONAL_PARALLEL_DIRS := clang endif -# Build LLD and LLDB if present. Note LLDB must be built last as it depends on +# Build LLDB if present. Note LLDB must be built last as it depends on # the wider LLVM infrastructure (including Clang). -OPTIONAL_PARALLEL_DIRS += lld OPTIONAL_DIRS := lldb # NOTE: The tools are organized into five groups of four consisting of one diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 6f41d3030d00..e2aaf6b01fc5 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -385,8 +385,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { std::vector<std::pair<std::string, std::string> > BlockInfo; for (BasicBlock *BB : Blocks) - BlockInfo.push_back(std::make_pair(BB->getParent()->getName(), - BB->getName())); + BlockInfo.emplace_back(BB->getParent()->getName(), BB->getName()); // Now run the CFG simplify pass on the function... std::vector<std::string> Passes; diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 53631d25c390..fad16368698d 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -386,10 +386,8 @@ static bool ExtractLoops(BugDriver &BD, // that masked the error. Stop loop extraction now. std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions; - for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) { - Function *F = MiscompiledFunctions[i]; - MisCompFunctions.push_back(std::make_pair(F->getName(), - F->getFunctionType())); + for (Function *F : MiscompiledFunctions) { + MisCompFunctions.emplace_back(F->getName(), F->getFunctionType()); } if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted)) @@ -414,8 +412,7 @@ static bool ExtractLoops(BugDriver &BD, for (Module::iterator I = ToOptimizeLoopExtracted->begin(), E = ToOptimizeLoopExtracted->end(); I != E; ++I) if (!I->isDeclaration()) - MisCompFunctions.push_back(std::make_pair(I->getName(), - I->getFunctionType())); + MisCompFunctions.emplace_back(I->getName(), I->getFunctionType()); // Okay, great! Now we know that we extracted a loop and that loop // extraction both didn't break the program, and didn't mask the problem. @@ -596,8 +593,7 @@ static bool ExtractBlocks(BugDriver &BD, for (Module::iterator I = Extracted->begin(), E = Extracted->end(); I != E; ++I) if (!I->isDeclaration()) - MisCompFunctions.push_back(std::make_pair(I->getName(), - I->getFunctionType())); + MisCompFunctions.emplace_back(I->getName(), I->getFunctionType()); if (Linker::LinkModules(ProgClone, Extracted.get())) exit(1); diff --git a/tools/dsymutil/CMakeLists.txt b/tools/dsymutil/CMakeLists.txt index 59b37a9b2900..88f9f1f083db 100644 --- a/tools/dsymutil/CMakeLists.txt +++ b/tools/dsymutil/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS MC Object Support + Target ) add_llvm_tool(llvm-dsymutil diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp index 9fa3f788a89f..1a81848847f6 100644 --- a/tools/dsymutil/DebugMap.cpp +++ b/tools/dsymutil/DebugMap.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include "DebugMap.h" +#include "BinaryHolder.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/DataTypes.h" @@ -46,8 +47,9 @@ void DebugMapObject::print(raw_ostream &OS) const { [](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; }); for (const auto &Sym : Entries) { OS << format("\t%016" PRIx64 " => %016" PRIx64 "+0x%x\t%s\n", - Sym.second.ObjectAddress, Sym.second.BinaryAddress, - Sym.second.Size, Sym.first.data()); + uint64_t(Sym.second.ObjectAddress), + uint64_t(Sym.second.BinaryAddress), uint32_t(Sym.second.Size), + Sym.first.data()); } OS << '\n'; } @@ -78,15 +80,160 @@ DebugMapObject::lookupObjectAddress(uint64_t Address) const { } void DebugMap::print(raw_ostream &OS) const { - OS << "DEBUG MAP: " << BinaryTriple.getTriple() - << "\n\tobject addr => executable addr\tsymbol name\n"; - for (const auto &Obj : objects()) - Obj->print(OS); - OS << "END DEBUG MAP\n"; + yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0); + yout << const_cast<DebugMap &>(*this); } #ifndef NDEBUG void DebugMap::dump() const { print(errs()); } #endif + +namespace { +struct YAMLContext { + StringRef PrependPath; + Triple BinaryTriple; +}; +} + +ErrorOr<std::unique_ptr<DebugMap>> +DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, + bool Verbose) { + auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile); + if (auto Err = ErrOrFile.getError()) + return Err; + + YAMLContext Ctxt; + + Ctxt.PrependPath = PrependPath; + + std::unique_ptr<DebugMap> Res; + yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt); + yin >> Res; + + if (auto EC = yin.error()) + return EC; + + return std::move(Res); +} +} + +namespace yaml { + +// Normalize/Denormalize between YAML and a DebugMapObject. +struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO { + YamlDMO(IO &io) {} + YamlDMO(IO &io, dsymutil::DebugMapObject &Obj); + dsymutil::DebugMapObject denormalize(IO &IO); + + std::string Filename; + std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries; +}; + +void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>:: + mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) { + io.mapRequired("sym", s.first); + io.mapRequired("objAddr", s.second.ObjectAddress); + io.mapRequired("binAddr", s.second.BinaryAddress); + io.mapOptional("size", s.second.Size); +} + +void MappingTraits<dsymutil::DebugMapObject>::mapping( + IO &io, dsymutil::DebugMapObject &DMO) { + MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO); + io.mapRequired("filename", Norm->Filename); + io.mapRequired("symbols", Norm->Entries); +} + +void ScalarTraits<Triple>::output(const Triple &val, void *, + llvm::raw_ostream &out) { + out << val.str(); +} + +StringRef ScalarTraits<Triple>::input(StringRef scalar, void *, Triple &value) { + value = Triple(scalar); + return StringRef(); +} + +size_t +SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::size( + IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) { + return seq.size(); +} + +dsymutil::DebugMapObject & +SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element( + IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq, + size_t index) { + if (index >= seq.size()) { + seq.resize(index + 1); + seq[index].reset(new dsymutil::DebugMapObject); + } + return *seq[index]; +} + +void MappingTraits<dsymutil::DebugMap>::mapping(IO &io, + dsymutil::DebugMap &DM) { + io.mapRequired("triple", DM.BinaryTriple); + io.mapOptional("objects", DM.Objects); + if (void *Ctxt = io.getContext()) + reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM.BinaryTriple; +} + +void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping( + IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) { + if (!DM) + DM.reset(new DebugMap()); + io.mapRequired("triple", DM->BinaryTriple); + io.mapOptional("objects", DM->Objects); + if (void *Ctxt = io.getContext()) + reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple; +} + +MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO( + IO &io, dsymutil::DebugMapObject &Obj) { + Filename = Obj.Filename; + Entries.reserve(Obj.Symbols.size()); + for (auto &Entry : Obj.Symbols) + Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue())); +} + +dsymutil::DebugMapObject +MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) { + BinaryHolder BinHolder(/* Verbose =*/false); + const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext()); + SmallString<80> Path(Ctxt.PrependPath); + StringMap<uint64_t> SymbolAddresses; + + sys::path::append(Path, Filename); + auto ErrOrObjectFile = BinHolder.GetObjectFile(Path); + if (auto EC = ErrOrObjectFile.getError()) { + llvm::errs() << "warning: Unable to open " << Path << " " << EC.message() + << '\n'; + } else { + // Rewrite the object file symbol addresses in the debug map. The + // YAML input is mainly used to test llvm-dsymutil without + // requiring binaries checked-in. If we generate the object files + // during the test, we can't hardcode the symbols addresses, so + // look them up here and rewrite them. + for (const auto &Sym : ErrOrObjectFile->symbols()) { + StringRef Name; + uint64_t Address; + if (Sym.getName(Name) || Sym.getAddress(Address)) + continue; + SymbolAddresses[Name] = Address; + } + } + + dsymutil::DebugMapObject Res(Path); + for (auto &Entry : Entries) { + auto &Mapping = Entry.second; + uint64_t ObjAddress = Mapping.ObjectAddress; + auto AddressIt = SymbolAddresses.find(Entry.first); + if (AddressIt != SymbolAddresses.end()) + ObjAddress = AddressIt->getValue(); + Res.addSymbol(Entry.first, ObjAddress, Mapping.BinaryAddress, Mapping.Size); + } + return Res; +} } } diff --git a/tools/dsymutil/DebugMap.h b/tools/dsymutil/DebugMap.h index ee48b093d4fd..d0edbabb404b 100644 --- a/tools/dsymutil/DebugMap.h +++ b/tools/dsymutil/DebugMap.h @@ -28,6 +28,8 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/YAMLTraits.h" #include <vector> namespace llvm { @@ -66,6 +68,12 @@ class DebugMap { typedef std::vector<std::unique_ptr<DebugMapObject>> ObjectContainer; ObjectContainer Objects; + /// For YAML IO support. + ///@{ + friend yaml::MappingTraits<std::unique_ptr<DebugMap>>; + friend yaml::MappingTraits<DebugMap>; + DebugMap() = default; + ///@} public: DebugMap(const Triple &BinaryTriple) : BinaryTriple(BinaryTriple) {} @@ -90,6 +98,10 @@ public: #ifndef NDEBUG void dump() const; #endif + + /// Read a debug map for \a InputFile. + static ErrorOr<std::unique_ptr<DebugMap>> + parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose); }; /// \brief The DebugMapObject represents one object file described by @@ -99,12 +111,14 @@ public: class DebugMapObject { public: struct SymbolMapping { - uint64_t ObjectAddress; - uint64_t BinaryAddress; - uint32_t Size; + yaml::Hex64 ObjectAddress; + yaml::Hex64 BinaryAddress; + yaml::Hex32 Size; SymbolMapping(uint64_t ObjectAddress, uint64_t BinaryAddress, uint32_t Size) : ObjectAddress(ObjectAddress), BinaryAddress(BinaryAddress), Size(Size) {} + /// For YAML IO support + SymbolMapping() = default; }; typedef StringMapEntry<SymbolMapping> DebugMapEntry; @@ -141,6 +155,72 @@ private: std::string Filename; StringMap<SymbolMapping> Symbols; DenseMap<uint64_t, DebugMapEntry *> AddressToMapping; + + /// For YAMLIO support. + ///@{ + typedef std::pair<std::string, SymbolMapping> YAMLSymbolMapping; + friend yaml::MappingTraits<dsymutil::DebugMapObject>; + friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>; + friend yaml::SequenceTraits<std::vector<YAMLSymbolMapping>>; + DebugMapObject() = default; + +public: + DebugMapObject &operator=(DebugMapObject RHS) { + std::swap(Filename, RHS.Filename); + std::swap(Symbols, RHS.Symbols); + std::swap(AddressToMapping, RHS.AddressToMapping); + return *this; + } + DebugMapObject(DebugMapObject &&RHS) { + Filename = std::move(RHS.Filename); + Symbols = std::move(RHS.Symbols); + AddressToMapping = std::move(RHS.AddressToMapping); + } + ///@} +}; +} +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping) + +namespace llvm { +namespace yaml { + +using namespace llvm::dsymutil; + +template <> +struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> { + static void mapping(IO &io, + std::pair<std::string, DebugMapObject::SymbolMapping> &s); + static const bool flow = true; +}; + +template <> struct MappingTraits<dsymutil::DebugMapObject> { + struct YamlDMO; + static void mapping(IO &io, dsymutil::DebugMapObject &DMO); +}; + +template <> struct ScalarTraits<Triple> { + static void output(const Triple &val, void *, llvm::raw_ostream &out); + static StringRef input(StringRef scalar, void *, Triple &value); + static bool mustQuote(StringRef) { return true; } +}; + +template <> +struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> { + static size_t + size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq); + static dsymutil::DebugMapObject & + element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq, + size_t index); +}; + +template <> struct MappingTraits<dsymutil::DebugMap> { + static void mapping(IO &io, dsymutil::DebugMap &DM); +}; + +template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> { + static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM); }; } } diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index a6e62a838945..7dc15b990ec5 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -60,6 +60,36 @@ using HalfOpenIntervalMap = typedef HalfOpenIntervalMap<uint64_t, int64_t> FunctionIntervals; +// FIXME: Delete this structure once DIE::Values has a stable iterator we can +// use instead. +struct PatchLocation { + DIE *Die; + unsigned Index; + + PatchLocation() : Die(nullptr), Index(0) {} + PatchLocation(DIE &Die, unsigned Index) : Die(&Die), Index(Index) {} + PatchLocation(DIE &Die) + : Die(&Die), Index(std::distance(Die.values_begin(), Die.values_end())) {} + + void set(uint64_t New) const { + assert(Die); + assert((signed)Index < + std::distance(Die->values_begin(), Die->values_end())); + const auto &Old = Die->values_begin()[Index]; + assert(Old.getType() == DIEValue::isInteger); + Die->setValue(Index, + DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New))); + } + + uint64_t get() const { + assert(Die); + assert((signed)Index < + std::distance(Die->values_begin(), Die->values_end())); + assert(Die->values_begin()[Index].getType() == DIEValue::isInteger); + return Die->values_begin()[Index].getDIEInteger().getValue(); + } +}; + /// \brief Stores all information relating to a compile unit, be it in /// its original instance in the object file to its brand new cloned /// and linked DIE tree. @@ -76,7 +106,7 @@ public: CompileUnit(DWARFUnit &OrigUnit, unsigned ID) : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), - Ranges(RangeAlloc), UnitRangeAttribute(nullptr) { + Ranges(RangeAlloc) { Info.resize(OrigUnit.getNumDIEs()); } @@ -106,13 +136,15 @@ public: uint64_t getLowPc() const { return LowPc; } uint64_t getHighPc() const { return HighPc; } - DIEInteger *getUnitRangesAttribute() const { return UnitRangeAttribute; } + Optional<PatchLocation> getUnitRangesAttribute() const { + return UnitRangeAttribute; + } const FunctionIntervals &getFunctionRanges() const { return Ranges; } - const std::vector<DIEInteger *> &getRangesAttributes() const { + const std::vector<PatchLocation> &getRangesAttributes() const { return RangeAttributes; } - const std::vector<std::pair<DIEInteger *, int64_t>> & + const std::vector<std::pair<PatchLocation, int64_t>> & getLocationAttributes() const { return LocationAttributes; } @@ -127,7 +159,7 @@ public: /// RefUnit by \p Attr. The attribute should be fixed up later to /// point to the absolute offset of \p Die in the debug_info section. void noteForwardReference(DIE *Die, const CompileUnit *RefUnit, - DIEInteger *Attr); + PatchLocation Attr); /// \brief Apply all fixups recored by noteForwardReference(). void fixupForwardReferences(); @@ -138,11 +170,11 @@ public: /// \brief Keep track of a DW_AT_range attribute that we will need to /// patch up later. - void noteRangeAttribute(const DIE &Die, DIEInteger *Attr); + void noteRangeAttribute(const DIE &Die, PatchLocation Attr); /// \brief Keep track of a location attribute pointing to a location /// list in the debug_loc section. - void noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset); + void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset); /// \brief Add a name accelerator entry for \p Die with \p Name /// which is stored in the string table at \p Offset. @@ -154,8 +186,8 @@ public: void addTypeAccelerator(const DIE *Die, const char *Name, uint32_t Offset); struct AccelInfo { - StringRef Name; ///< Name of the entry. - const DIE *Die; ///< DIE this entry describes. + StringRef Name; ///< Name of the entry. + const DIE *Die; ///< DIE this entry describes. uint32_t NameOffset; ///< Offset of Name in the string pool. bool SkipPubSection; ///< Emit this entry only in the apple_* sections. @@ -186,7 +218,7 @@ private: /// The offsets for the attributes in this array couldn't be set while /// cloning because for cross-cu forward refences the target DIE's /// offset isn't known you emit the reference attribute. - std::vector<std::tuple<DIE *, const CompileUnit *, DIEInteger *>> + std::vector<std::tuple<DIE *, const CompileUnit *, PatchLocation>> ForwardDIEReferences; FunctionIntervals::Allocator RangeAlloc; @@ -198,15 +230,15 @@ private: /// \brief DW_AT_ranges attributes to patch after we have gathered /// all the unit's function addresses. /// @{ - std::vector<DIEInteger *> RangeAttributes; - DIEInteger *UnitRangeAttribute; + std::vector<PatchLocation> RangeAttributes; + Optional<PatchLocation> UnitRangeAttribute; /// @} /// \brief Location attributes that need to be transfered from th /// original debug_loc section to the liked one. They are stored /// along with the PC offset that is to be applied to their /// function's address. - std::vector<std::pair<DIEInteger *, int64_t>> LocationAttributes; + std::vector<std::pair<PatchLocation, int64_t>> LocationAttributes; /// \brief Accelerator entries for the unit, both for the pub* /// sections and the apple* ones. @@ -229,7 +261,7 @@ uint64_t CompileUnit::computeNextUnitOffset() { /// \brief Keep track of a forward cross-cu reference from this unit /// to \p Die that lives in \p RefUnit. void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit, - DIEInteger *Attr) { + PatchLocation Attr) { ForwardDIEReferences.emplace_back(Die, RefUnit, Attr); } @@ -238,9 +270,9 @@ void CompileUnit::fixupForwardReferences() { for (const auto &Ref : ForwardDIEReferences) { DIE *RefDie; const CompileUnit *RefUnit; - DIEInteger *Attr; + PatchLocation Attr; std::tie(RefDie, RefUnit, Attr) = Ref; - Attr->setValue(RefDie->getOffset() + RefUnit->getStartOffset()); + Attr.set(RefDie->getOffset() + RefUnit->getStartOffset()); } } @@ -251,14 +283,14 @@ void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, this->HighPc = std::max(HighPc, FuncHighPc + PcOffset); } -void CompileUnit::noteRangeAttribute(const DIE &Die, DIEInteger *Attr) { +void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) { if (Die.getTag() != dwarf::DW_TAG_compile_unit) RangeAttributes.push_back(Attr); else UnitRangeAttribute = Attr; } -void CompileUnit::noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset) { +void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) { LocationAttributes.emplace_back(Attr, PcOffset); } @@ -387,6 +419,7 @@ class DwarfStreamer { uint32_t RangesSectionSize; uint32_t LocSectionSize; uint32_t LineSectionSize; + uint32_t FrameSectionSize; /// \brief Emit the pubnames or pubtypes section contribution for \p /// Unit into \p Sec. The data is provided in \p Names. @@ -460,6 +493,15 @@ public: /// \brief Emit the .debug_pubtypes contribution for \p Unit. void emitPubTypesForUnit(const CompileUnit &Unit); + + /// \brief Emit a CIE. + void emitCIE(StringRef CIEBytes); + + /// \brief Emit an FDE with data \p Bytes. + void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint32_t Address, + StringRef Bytes); + + uint32_t getFrameSectionSize() const { return FrameSectionSize; } }; bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) { @@ -529,6 +571,7 @@ bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) { RangesSectionSize = 0; LocSectionSize = 0; LineSectionSize = 0; + FrameSectionSize = 0; return true; } @@ -717,8 +760,7 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit, /// point to the new entries. void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf) { - const std::vector<std::pair<DIEInteger *, int64_t>> &Attributes = - Unit.getLocationAttributes(); + const auto &Attributes = Unit.getLocationAttributes(); if (Attributes.empty()) return; @@ -737,8 +779,8 @@ void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit, UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc(); for (const auto &Attr : Attributes) { - uint32_t Offset = Attr.first->getValue(); - Attr.first->setValue(LocSectionSize); + uint32_t Offset = Attr.first.get(); + Attr.first.set(LocSectionSize); // This is the quantity to add to the old location address to get // the correct address for the new one. int64_t LocPcOffset = Attr.second + UnitPcOffset; @@ -934,7 +976,7 @@ void DwarfStreamer::emitPubSectionForUnit( Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Length Asm->OutStreamer->EmitLabel(BeginLabel); Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); // Version - Asm->EmitInt32(Unit.getStartOffset()); // Unit offset + Asm->EmitInt32(Unit.getStartOffset()); // Unit offset Asm->EmitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size HeaderEmitted = true; } @@ -961,6 +1003,28 @@ void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) { "types", Unit, Unit.getPubtypes()); } +/// \brief Emit a CIE into the debug_frame section. +void DwarfStreamer::emitCIE(StringRef CIEBytes) { + MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); + + MS->EmitBytes(CIEBytes); + FrameSectionSize += CIEBytes.size(); +} + +/// \brief Emit a FDE into the debug_frame section. \p FDEBytes +/// contains the FDE data without the length, CIE offset and address +/// which will be replaced with the paramter values. +void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, + uint32_t Address, StringRef FDEBytes) { + MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); + + MS->EmitIntValue(FDEBytes.size() + 4 + AddrSize, 4); + MS->EmitIntValue(CIEOffset, 4); + MS->EmitIntValue(Address, AddrSize); + MS->EmitBytes(FDEBytes); + FrameSectionSize += FDEBytes.size() + 8 + AddrSize; +} + /// \brief The core of the Dwarf linking logic. /// /// The link of the dwarf information from the object files will be @@ -979,7 +1043,7 @@ class DwarfLinker { public: DwarfLinker(StringRef OutputFilename, const LinkOptions &Options) : OutputFilename(OutputFilename), Options(Options), - BinHolder(Options.Verbose) {} + BinHolder(Options.Verbose), LastCIEOffset(0) {} ~DwarfLinker() { for (auto *Abbrev : Abbreviations) @@ -1177,6 +1241,10 @@ private: /// \brief Emit the accelerator entries for \p Unit. void emitAcceleratorEntriesForUnit(CompileUnit &Unit); + /// \brief Patch the frame info for an object file and emit it. + void patchFrameInfoForObject(const DebugMapObject &, DWARFContext &, + unsigned AddressSize); + /// \brief DIELoc objects that need to be destructed (but not freed!). std::vector<DIELoc *> DIELocs; /// \brief DIEBlock objects that need to be destructed (but not freed!). @@ -1226,6 +1294,16 @@ private: /// /// See startDebugObject() for a more complete description of its use. std::map<uint64_t, std::pair<uint64_t, int64_t>> Ranges; + + /// \brief The CIEs that have been emitted in the output + /// section. The actual CIE data serves a the key to this StringMap, + /// this takes care of comparing the semantics of CIEs defined in + /// different object files. + StringMap<uint32_t> EmittedCIEs; + + /// Offset of the last CIE that has been emitted in the output + /// debug_frame section. + uint32_t LastCIEOffset; }; /// \brief Similar to DWARFUnitSection::getUnitForOffset(), but @@ -1477,15 +1555,15 @@ bool DwarfLinker::hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset, return false; const auto &ValidReloc = ValidRelocs[NextValidReloc++]; + const auto &Mapping = ValidReloc.Mapping->getValue(); if (Options.Verbose) outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey() << " " << format("\t%016" PRIx64 " => %016" PRIx64, - ValidReloc.Mapping->getValue().ObjectAddress, - ValidReloc.Mapping->getValue().BinaryAddress); + uint64_t(Mapping.ObjectAddress), + uint64_t(Mapping.BinaryAddress)); - Info.AddrAdjust = int64_t(ValidReloc.Mapping->getValue().BinaryAddress) + - ValidReloc.Addend - - ValidReloc.Mapping->getValue().ObjectAddress; + Info.AddrAdjust = int64_t(Mapping.BinaryAddress) + ValidReloc.Addend - + Mapping.ObjectAddress; Info.InDebugMap = true; return true; } @@ -1760,7 +1838,7 @@ unsigned DwarfLinker::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec, const char *String = *Val.getAsCString(&U); unsigned Offset = StringPool.getStringOffset(String); Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp, - new (DIEAlloc) DIEInteger(Offset)); + DIEInteger(Offset)); return 4; } @@ -1803,24 +1881,24 @@ unsigned DwarfLinker::cloneDieReferenceAttribute( // to find the unit offset. (We don't have a DwarfDebug) // FIXME: we should be able to design DIEEntry reliance on // DwarfDebug away. - DIEInteger *Attr; + uint64_t Attr; if (Ref < InputDIE.getOffset()) { // We must have already cloned that DIE. uint32_t NewRefOffset = RefUnit->getStartOffset() + NewRefDie->getOffset(); - Attr = new (DIEAlloc) DIEInteger(NewRefOffset); + Attr = NewRefOffset; } else { // A forward reference. Note and fixup later. - Attr = new (DIEAlloc) DIEInteger(0xBADDEF); - Unit.noteForwardReference(NewRefDie, RefUnit, Attr); + Attr = 0xBADDEF; + Unit.noteForwardReference(NewRefDie, RefUnit, PatchLocation(Die)); } Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_ref_addr, - Attr); + DIEInteger(Attr)); return AttrSize; } Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form), - new (DIEAlloc) DIEEntry(*NewRefDie)); + DIEEntry(*NewRefDie)); return AttrSize; } @@ -1831,23 +1909,29 @@ unsigned DwarfLinker::cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize) { DIE *Attr; - DIEValue *Value; + DIEValue Value; DIELoc *Loc = nullptr; DIEBlock *Block = nullptr; // Just copy the block data over. if (AttrSpec.Form == dwarf::DW_FORM_exprloc) { - Loc = new (DIEAlloc) DIELoc(); + Loc = new (DIEAlloc) DIELoc; DIELocs.push_back(Loc); } else { - Block = new (DIEAlloc) DIEBlock(); + Block = new (DIEAlloc) DIEBlock; DIEBlocks.push_back(Block); } Attr = Loc ? static_cast<DIE *>(Loc) : static_cast<DIE *>(Block); - Value = Loc ? static_cast<DIEValue *>(Loc) : static_cast<DIEValue *>(Block); + + if (Loc) + Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), + dwarf::Form(AttrSpec.Form), Loc); + else + Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), + dwarf::Form(AttrSpec.Form), Block); ArrayRef<uint8_t> Bytes = *Val.getAsBlock(); for (auto Byte : Bytes) Attr->addValue(static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1, - new (DIEAlloc) DIEInteger(Byte)); + DIEInteger(Byte)); // FIXME: If DIEBlock and DIELoc just reuses the Size field of // the DIE class, this if could be replaced by // Attr->setSize(Bytes.size()). @@ -1857,8 +1941,7 @@ unsigned DwarfLinker::cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec, else Block->ComputeSize(&Streamer->getAsmPrinter()); } - Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form), - Value); + Die.addValue(Value); return AttrSize; } @@ -1893,8 +1976,7 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec, } Die.addValue(static_cast<dwarf::Attribute>(AttrSpec.Attr), - static_cast<dwarf::Form>(AttrSpec.Form), - new (DIEAlloc) DIEInteger(Addr)); + static_cast<dwarf::Form>(AttrSpec.Form), DIEInteger(Addr)); return Unit.getOrigUnit().getAddressByteSize(); } @@ -1922,15 +2004,15 @@ unsigned DwarfLinker::cloneScalarAttribute( &Unit.getOrigUnit(), &InputDIE); return 0; } - DIEInteger *Attr = new (DIEAlloc) DIEInteger(Value); + DIEInteger Attr(Value); if (AttrSpec.Attr == dwarf::DW_AT_ranges) - Unit.noteRangeAttribute(Die, Attr); + Unit.noteRangeAttribute(Die, PatchLocation(Die)); // A more generic way to check for location attributes would be // nice, but it's very unlikely that any other attribute needs a // location list. else if (AttrSpec.Attr == dwarf::DW_AT_location || AttrSpec.Attr == dwarf::DW_AT_frame_base) - Unit.noteLocationAttribute(Attr, Info.PCOffset); + Unit.noteLocationAttribute(PatchLocation(Die), Info.PCOffset); else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) Info.IsDeclaration = true; @@ -2157,14 +2239,15 @@ DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, Unit.addTypeAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset); } - DIEAbbrev &NewAbbrev = Die->getAbbrev(); + DIEAbbrev NewAbbrev = Die->generateAbbrev(); // If a scope DIE is kept, we must have kept at least one child. If // it's not the case, we'll just be emitting one wasteful end of // children marker, but things won't break. if (InputDIE.hasChildren()) NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); // Assign a permanent abbrev number - AssignAbbrev(Die->getAbbrev()); + AssignAbbrev(NewAbbrev); + Die->setAbbrevNumber(NewAbbrev.getNumber()); // Add the size of the abbreviation number to the output offset. OutOffset += getULEB128Size(Die->getAbbrevNumber()); @@ -2213,8 +2296,8 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc(); for (const auto &RangeAttribute : Unit.getRangesAttributes()) { - uint32_t Offset = RangeAttribute->getValue(); - RangeAttribute->setValue(Streamer->getRangesSectionSize()); + uint32_t Offset = RangeAttribute.get(); + RangeAttribute.set(Streamer->getRangesSectionSize()); RangeList.extract(RangeExtractor, &Offset); const auto &Entries = RangeList.getEntries(); const DWARFDebugRangeList::RangeListEntry &First = Entries.front(); @@ -2241,10 +2324,10 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, /// but for the sake of initial bit-for-bit compatibility with legacy /// dsymutil, we have to do it in a delayed pass. void DwarfLinker::generateUnitRanges(CompileUnit &Unit) const { - DIEInteger *Attr = Unit.getUnitRangesAttribute(); + auto Attr = Unit.getUnitRangesAttribute(); if (Attr) - Attr->setValue(Streamer->getRangesSectionSize()); - Streamer->emitUnitRangesEntries(Unit, Attr != nullptr); + Attr->set(Streamer->getRangesSectionSize()); + Streamer->emitUnitRangesEntries(Unit, static_cast<bool>(Attr)); } /// \brief Insert the new line info sequence \p Seq into the current @@ -2286,8 +2369,7 @@ static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, /// are present in the binary. void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf) { - const DWARFDebugInfoEntryMinimal *CUDie = - Unit.getOrigUnit().getUnitDIE(); + const DWARFDebugInfoEntryMinimal *CUDie = Unit.getOrigUnit().getUnitDIE(); uint64_t StmtList = CUDie->getAttributeValueAsSectionOffset( &Unit.getOrigUnit(), dwarf::DW_AT_stmt_list, -1ULL); if (StmtList == -1ULL) @@ -2295,15 +2377,16 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, // Update the cloned DW_AT_stmt_list with the correct debug_line offset. if (auto *OutputDIE = Unit.getOutputUnitDIE()) { - const auto &Abbrev = OutputDIE->getAbbrev().getData(); - auto Stmt = std::find_if( - Abbrev.begin(), Abbrev.end(), [](const DIEAbbrevData &AbbrevData) { - return AbbrevData.getAttribute() == dwarf::DW_AT_stmt_list; - }); - assert(Stmt < Abbrev.end() && "Didn't find DW_AT_stmt_list in cloned DIE!"); - DIEInteger *StmtAttr = - cast<DIEInteger>(OutputDIE->getValues()[Stmt - Abbrev.begin()]); - StmtAttr->setValue(Streamer->getLineSectionSize()); + auto Stmt = + std::find_if(OutputDIE->values_begin(), OutputDIE->values_end(), + [](const DIEValue &Value) { + return Value.getAttribute() == dwarf::DW_AT_stmt_list; + }); + assert(Stmt != OutputDIE->values_end() && + "Didn't find DW_AT_stmt_list in cloned DIE!"); + OutputDIE->setValue(Stmt - OutputDIE->values_begin(), + DIEValue(Stmt->getAttribute(), Stmt->getForm(), + DIEInteger(Streamer->getLineSectionSize()))); } // Parse the original line info for the unit. @@ -2422,6 +2505,91 @@ void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { Streamer->emitPubTypesForUnit(Unit); } +/// \brief Read the frame info stored in the object, and emit the +/// patched frame descriptions for the linked binary. +/// +/// This is actually pretty easy as the data of the CIEs and FDEs can +/// be considered as black boxes and moved as is. The only thing to do +/// is to patch the addresses in the headers. +void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO, + DWARFContext &OrigDwarf, + unsigned AddrSize) { + StringRef FrameData = OrigDwarf.getDebugFrameSection(); + if (FrameData.empty()) + return; + + DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0); + uint32_t InputOffset = 0; + + // Store the data of the CIEs defined in this object, keyed by their + // offsets. + DenseMap<uint32_t, StringRef> LocalCIES; + + while (Data.isValidOffset(InputOffset)) { + uint32_t EntryOffset = InputOffset; + uint32_t InitialLength = Data.getU32(&InputOffset); + if (InitialLength == 0xFFFFFFFF) + return reportWarning("Dwarf64 bits no supported"); + + uint32_t CIEId = Data.getU32(&InputOffset); + if (CIEId == 0xFFFFFFFF) { + // This is a CIE, store it. + StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4); + LocalCIES[EntryOffset] = CIEData; + // The -4 is to account for the CIEId we just read. + InputOffset += InitialLength - 4; + continue; + } + + uint32_t Loc = Data.getUnsigned(&InputOffset, AddrSize); + + // Some compilers seem to emit frame info that doesn't start at + // the function entry point, thus we can't just lookup the address + // in the debug map. Use the linker's range map to see if the FDE + // describes something that we can relocate. + auto Range = Ranges.upper_bound(Loc); + if (Range != Ranges.begin()) + --Range; + if (Range == Ranges.end() || Range->first > Loc || + Range->second.first <= Loc) { + // The +4 is to account for the size of the InitialLength field itself. + InputOffset = EntryOffset + InitialLength + 4; + continue; + } + + // This is an FDE, and we have a mapping. + // Have we already emitted a corresponding CIE? + StringRef CIEData = LocalCIES[CIEId]; + if (CIEData.empty()) + return reportWarning("Inconsistent debug_frame content. Dropping."); + + // Look if we already emitted a CIE that corresponds to the + // referenced one (the CIE data is the key of that lookup). + auto IteratorInserted = EmittedCIEs.insert( + std::make_pair(CIEData, Streamer->getFrameSectionSize())); + // If there is no CIE yet for this ID, emit it. + if (IteratorInserted.second || + // FIXME: dsymutil-classic only caches the last used CIE for + // reuse. Mimic that behavior for now. Just removing that + // second half of the condition and the LastCIEOffset variable + // makes the code DTRT. + LastCIEOffset != IteratorInserted.first->getValue()) { + LastCIEOffset = Streamer->getFrameSectionSize(); + IteratorInserted.first->getValue() = LastCIEOffset; + Streamer->emitCIE(CIEData); + } + + // Emit the FDE with updated address and CIE pointer. + // (4 + AddrSize) is the size of the CIEId + initial_location + // fields that will get reconstructed by emitFDE(). + unsigned FDERemainingBytes = InitialLength - (4 + AddrSize); + Streamer->emitFDE(IteratorInserted.first->getValue(), AddrSize, + Loc + Range->second.second, + FrameData.substr(InputOffset, FDERemainingBytes)); + InputOffset += FDERemainingBytes; + } +} + bool DwarfLinker::link(const DebugMap &Map) { if (Map.begin() == Map.end()) { @@ -2519,6 +2687,10 @@ bool DwarfLinker::link(const DebugMap &Map) { Streamer->emitDIE(*CurrentUnit.getOutputUnitDIE()); } + if (!ValidRelocs.empty() && !Options.NoOutput && !Units.empty()) + patchFrameInfoForObject(*Obj, DwarfContext, + Units[0].getOrigUnit().getAddressByteSize()); + // Clean-up before starting working on the next object. endDebugObject(); } diff --git a/tools/dsymutil/MachODebugMapParser.cpp b/tools/dsymutil/MachODebugMapParser.cpp index bf64303b9eab..b803e410199d 100644 --- a/tools/dsymutil/MachODebugMapParser.cpp +++ b/tools/dsymutil/MachODebugMapParser.cpp @@ -244,10 +244,16 @@ void MachODebugMapParser::loadMainBinarySymbols() { namespace llvm { namespace dsymutil { -llvm::ErrorOr<std::unique_ptr<DebugMap>> -parseDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose) { - MachODebugMapParser Parser(InputFile, PrependPath, Verbose); - return Parser.parse(); +llvm::ErrorOr<std::unique_ptr<DebugMap>> parseDebugMap(StringRef InputFile, + StringRef PrependPath, + bool Verbose, + bool InputIsYAML) { + if (!InputIsYAML) { + MachODebugMapParser Parser(InputFile, PrependPath, Verbose); + return Parser.parse(); + } else { + return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose); + } } } } diff --git a/tools/dsymutil/dsymutil.cpp b/tools/dsymutil/dsymutil.cpp index 4fc91b029f68..50091935a44e 100644 --- a/tools/dsymutil/dsymutil.cpp +++ b/tools/dsymutil/dsymutil.cpp @@ -30,26 +30,32 @@ using namespace llvm::cl; static opt<std::string> InputFile(Positional, desc("<input file>"), init("a.out")); -static opt<std::string> OutputFileOpt("o", desc("Specify the output file." - " default: <input file>.dwarf"), - value_desc("filename")); +static opt<std::string> + OutputFileOpt("o", + desc("Specify the output file. default: <input file>.dwarf"), + value_desc("filename")); -static opt<std::string> OsoPrependPath("oso-prepend-path", - desc("Specify a directory to prepend " - "to the paths of object files."), - value_desc("path")); +static opt<std::string> OsoPrependPath( + "oso-prepend-path", + desc("Specify a directory to prepend to the paths of object files."), + value_desc("path")); static opt<bool> Verbose("v", desc("Verbosity level"), init(false)); -static opt<bool> NoOutput("no-output", desc("Do the link in memory, but do " - "not emit the result file."), - init(false)); - static opt<bool> - ParseOnly("parse-only", - desc("Only parse the debug map, do not actaully link " - "the DWARF."), - init(false)); + NoOutput("no-output", + desc("Do the link in memory, but do not emit the result file."), + init(false)); + +static opt<bool> DumpDebugMap( + "dump-debug-map", + desc("Parse and dump the debug map to standard output. Not DWARF link " + "will take place."), + init(false)); + +static opt<bool> InputIsYAMLDebugMap( + "y", desc("Treat the input file is a YAML debug map rather than a binary."), + init(false)); } int main(int argc, char **argv) { @@ -59,7 +65,9 @@ int main(int argc, char **argv) { LinkOptions Options; llvm::cl::ParseCommandLineOptions(argc, argv, "llvm dsymutil\n"); - auto DebugMapPtrOrErr = parseDebugMap(InputFile, OsoPrependPath, Verbose); + + auto DebugMapPtrOrErr = + parseDebugMap(InputFile, OsoPrependPath, Verbose, InputIsYAMLDebugMap); Options.Verbose = Verbose; Options.NoOutput = NoOutput; @@ -75,10 +83,10 @@ int main(int argc, char **argv) { return 1; } - if (Verbose) + if (Verbose || DumpDebugMap) (*DebugMapPtrOrErr)->print(llvm::outs()); - if (ParseOnly) + if (DumpDebugMap) return 0; std::string OutputFile; diff --git a/tools/dsymutil/dsymutil.h b/tools/dsymutil/dsymutil.h index e9f7cd951878..408918779833 100644 --- a/tools/dsymutil/dsymutil.h +++ b/tools/dsymutil/dsymutil.h @@ -33,9 +33,10 @@ struct LinkOptions { /// \brief Extract the DebugMap from the given file. /// The file has to be a MachO object file. -llvm::ErrorOr<std::unique_ptr<DebugMap>> -parseDebugMap(StringRef InputFile, StringRef PrependPath = "", - bool Verbose = false); +llvm::ErrorOr<std::unique_ptr<DebugMap>> parseDebugMap(StringRef InputFile, + StringRef PrependPath, + bool Verbose, + bool InputIsYAML); /// \brief Link the Dwarf debuginfo as directed by the passed DebugMap /// \p DM into a DwarfFile named \p OutputFilename. diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt index dcbcf9da6128..ff5a89e1da44 100644 --- a/tools/llc/CMakeLists.txt +++ b/tools/llc/CMakeLists.txt @@ -6,9 +6,11 @@ set(LLVM_LINK_COMPONENTS Core IRReader MC + MIRParser ScalarOpts SelectionDAG Support + Target ) # Support plugins. diff --git a/tools/llc/LLVMBuild.txt b/tools/llc/LLVMBuild.txt index 45cdc6498f86..38660cf27a46 100644 --- a/tools/llc/LLVMBuild.txt +++ b/tools/llc/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llc parent = Tools -required_libraries = AsmParser BitReader IRReader all-targets +required_libraries = AsmParser BitReader IRReader MIRParser all-targets diff --git a/tools/llc/Makefile b/tools/llc/Makefile index 71bce4dc1adf..ae64c9a5b57c 100644 --- a/tools/llc/Makefile +++ b/tools/llc/Makefile @@ -9,7 +9,7 @@ LEVEL := ../.. TOOLNAME := llc -LINK_COMPONENTS := all-targets bitreader asmparser irreader +LINK_COMPONENTS := all-targets bitreader asmparser irreader mirparser # Support plugins. NO_DEAD_STRIP := 1 diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 0977418e0231..fadcfa90235c 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" @@ -109,6 +110,8 @@ GetOutputStream(const char *TargetName, Triple::OSType OS, StringRef IFN = InputFilename; if (IFN.endswith(".bc") || IFN.endswith(".ll")) OutputFilename = IFN.drop_back(3); + else if (IFN.endswith(".mir")) + OutputFilename = IFN.drop_back(4); else OutputFilename = IFN; @@ -214,7 +217,10 @@ static int compileModule(char **argv, LLVMContext &Context) { // If user just wants to list available options, skip module loading if (!SkipModule) { - M = parseIRFile(InputFilename, Err, Context); + if (StringRef(InputFilename).endswith_lower(".mir")) + M = parseMIRFile(InputFilename, Err, Context); + else + M = parseIRFile(InputFilename, Err, Context); if (!M) { Err.print(argv[0], errs()); return 1; diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt index 844b99464cb7..4af05969af16 100644 --- a/tools/lli/CMakeLists.txt +++ b/tools/lli/CMakeLists.txt @@ -14,6 +14,7 @@ set(LLVM_LINK_COMPONENTS RuntimeDyld SelectionDAG Support + Target TransformUtils native ) diff --git a/tools/lli/OrcLazyJIT.cpp b/tools/lli/OrcLazyJIT.cpp index bda5d6dcd26c..afccfa6b0328 100644 --- a/tools/lli/OrcLazyJIT.cpp +++ b/tools/lli/OrcLazyJIT.cpp @@ -108,6 +108,9 @@ OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() { llvm_unreachable("Unknown DumpKind"); } +// Defined in lli.cpp. +CodeGenOpt::Level getOptLevel(); + int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) { // Add the program's symbols into the JIT's search space. if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { @@ -117,7 +120,9 @@ int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) { // Grab a target machine and try to build a factory function for the // target-specific Orc callback manager. - auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget()); + EngineBuilder EB; + EB.setOptLevel(getOptLevel()); + auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget()); auto &Context = getGlobalContext(); auto CallbackMgrBuilder = OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple())); diff --git a/tools/lli/OrcLazyJIT.h b/tools/lli/OrcLazyJIT.h index bff2eca26a5f..c4a12b6dd9e0 100644 --- a/tools/lli/OrcLazyJIT.h +++ b/tools/lli/OrcLazyJIT.h @@ -116,8 +116,7 @@ public: orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H); CtorRunner.runViaLayer(CODLayer); - IRStaticDestructorRunners.push_back( - orc::CtorDtorRunner<CODLayerT>(std::move(DtorNames), H)); + IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H); return H; } diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp index 6916d1609b83..057841f0ad60 100644 --- a/tools/lli/lli.cpp +++ b/tools/lli/lli.cpp @@ -365,6 +365,19 @@ static void addCygMingExtraModule(ExecutionEngine *EE, EE->addModule(std::move(M)); } +CodeGenOpt::Level getOptLevel() { + switch (OptLevel) { + default: + errs() << "lli: Invalid optimization level.\n"; + exit(1); + case '0': return CodeGenOpt::None; + case '1': return CodeGenOpt::Less; + case ' ': + case '2': return CodeGenOpt::Default; + case '3': return CodeGenOpt::Aggressive; + } + llvm_unreachable("Unrecognized opt level."); +} //===----------------------------------------------------------------------===// // main Driver function @@ -451,18 +464,7 @@ int main(int argc, char **argv, char * const *envp) { exit(1); } - CodeGenOpt::Level OLvl = CodeGenOpt::Default; - switch (OptLevel) { - default: - errs() << argv[0] << ": invalid optimization level.\n"; - return 1; - case ' ': break; - case '0': OLvl = CodeGenOpt::None; break; - case '1': OLvl = CodeGenOpt::Less; break; - case '2': OLvl = CodeGenOpt::Default; break; - case '3': OLvl = CodeGenOpt::Aggressive; break; - } - builder.setOptLevel(OLvl); + builder.setOptLevel(getOptLevel()); TargetOptions Options; if (FloatABIForCalls != FloatABI::Default) diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index f813465daafa..1f55e8a4968b 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Errc.h" @@ -45,16 +46,9 @@ using namespace llvm; // The name this program was invoked as. static StringRef ToolName; -static const char *TemporaryOutput; -static int TmpArchiveFD = -1; - // Show the error message and exit. LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) { outs() << ToolName << ": " << Error << ".\n"; - if (TmpArchiveFD != -1) - close(TmpArchiveFD); - if (TemporaryOutput) - sys::fs::remove(TemporaryOutput); exit(1); } @@ -405,70 +399,6 @@ static void performReadOperation(ArchiveOperation Operation, } } -namespace { -class NewArchiveIterator { - bool IsNewMember; - StringRef Name; - - object::Archive::child_iterator OldI; - - StringRef NewFilename; - -public: - NewArchiveIterator(object::Archive::child_iterator I, StringRef Name); - NewArchiveIterator(StringRef I, StringRef Name); - NewArchiveIterator(); - bool isNewMember() const; - StringRef getName() const; - - object::Archive::child_iterator getOld() const; - - StringRef getNew() const; - int getFD(sys::fs::file_status &NewStatus) const; - const sys::fs::file_status &getStatus() const; -}; -} - -NewArchiveIterator::NewArchiveIterator() {} - -NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I, - StringRef Name) - : IsNewMember(false), Name(Name), OldI(I) {} - -NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name) - : IsNewMember(true), Name(Name), NewFilename(NewFilename) {} - -StringRef NewArchiveIterator::getName() const { return Name; } - -bool NewArchiveIterator::isNewMember() const { return IsNewMember; } - -object::Archive::child_iterator NewArchiveIterator::getOld() const { - assert(!IsNewMember); - return OldI; -} - -StringRef NewArchiveIterator::getNew() const { - assert(IsNewMember); - return NewFilename; -} - -int NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const { - assert(IsNewMember); - int NewFD; - failIfError(sys::fs::openFileForRead(NewFilename, NewFD), NewFilename); - assert(NewFD != -1); - - failIfError(sys::fs::status(NewFD, NewStatus), NewFilename); - - // Opening a directory doesn't make sense. Let it fail. - // Linux cannot open directories with open(2), although - // cygwin and *bsd can. - if (NewStatus.type() == sys::fs::file_type::directory_file) - failIfError(make_error_code(errc::is_a_directory), NewFilename); - - return NewFD; -} - template <typename T> void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name, int Pos = -1) { @@ -605,269 +535,19 @@ computeNewArchiveMembers(ArchiveOperation Operation, return Ret; } -template <typename T> -static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size, - bool MayTruncate = false) { - uint64_t OldPos = OS.tell(); - OS << Data; - unsigned SizeSoFar = OS.tell() - OldPos; - if (Size > SizeSoFar) { - unsigned Remaining = Size - SizeSoFar; - for (unsigned I = 0; I < Remaining; ++I) - OS << ' '; - } else if (Size < SizeSoFar) { - assert(MayTruncate && "Data doesn't fit in Size"); - // Some of the data this is used for (like UID) can be larger than the - // space available in the archive format. Truncate in that case. - OS.seek(OldPos + Size); - } -} - -static void print32BE(raw_fd_ostream &Out, unsigned Val) { - for (int I = 3; I >= 0; --I) { - char V = (Val >> (8 * I)) & 0xff; - Out << V; - } -} - -static void printRestOfMemberHeader(raw_fd_ostream &Out, - const sys::TimeValue &ModTime, unsigned UID, - unsigned GID, unsigned Perms, - unsigned Size) { - printWithSpacePadding(Out, ModTime.toEpochTime(), 12); - printWithSpacePadding(Out, UID, 6, true); - printWithSpacePadding(Out, GID, 6, true); - printWithSpacePadding(Out, format("%o", Perms), 8); - printWithSpacePadding(Out, Size, 10); - Out << "`\n"; -} - -static void printMemberHeader(raw_fd_ostream &Out, StringRef Name, - const sys::TimeValue &ModTime, unsigned UID, - unsigned GID, unsigned Perms, unsigned Size) { - printWithSpacePadding(Out, Twine(Name) + "/", 16); - printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); -} - -static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset, - const sys::TimeValue &ModTime, unsigned UID, - unsigned GID, unsigned Perms, unsigned Size) { - Out << '/'; - printWithSpacePadding(Out, NameOffset, 15); - printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); -} - -static void writeStringTable(raw_fd_ostream &Out, - ArrayRef<NewArchiveIterator> Members, - std::vector<unsigned> &StringMapIndexes) { - unsigned StartOffset = 0; - for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), - E = Members.end(); - I != E; ++I) { - StringRef Name = I->getName(); - if (Name.size() < 16) - continue; - if (StartOffset == 0) { - printWithSpacePadding(Out, "//", 58); - Out << "`\n"; - StartOffset = Out.tell(); - } - StringMapIndexes.push_back(Out.tell() - StartOffset); - Out << Name << "/\n"; - } - if (StartOffset == 0) - return; - if (Out.tell() % 2) - Out << '\n'; - int Pos = Out.tell(); - Out.seek(StartOffset - 12); - printWithSpacePadding(Out, Pos - StartOffset, 10); - Out.seek(Pos); -} - -// Returns the offset of the first reference to a member offset. -static unsigned writeSymbolTable(raw_fd_ostream &Out, - ArrayRef<NewArchiveIterator> Members, - ArrayRef<MemoryBufferRef> Buffers, - std::vector<unsigned> &MemberOffsetRefs) { - unsigned StartOffset = 0; - unsigned MemberNum = 0; - std::string NameBuf; - raw_string_ostream NameOS(NameBuf); - unsigned NumSyms = 0; - LLVMContext &Context = getGlobalContext(); - for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), - E = Members.end(); - I != E; ++I, ++MemberNum) { - MemoryBufferRef MemberBuffer = Buffers[MemberNum]; - ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr = - object::SymbolicFile::createSymbolicFile( - MemberBuffer, sys::fs::file_magic::unknown, &Context); - if (!ObjOrErr) - continue; // FIXME: check only for "not an object file" errors. - object::SymbolicFile &Obj = *ObjOrErr.get(); - - if (!StartOffset) { - printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); - StartOffset = Out.tell(); - print32BE(Out, 0); - } - - for (const object::BasicSymbolRef &S : Obj.symbols()) { - uint32_t Symflags = S.getFlags(); - if (Symflags & object::SymbolRef::SF_FormatSpecific) - continue; - if (!(Symflags & object::SymbolRef::SF_Global)) - continue; - if (Symflags & object::SymbolRef::SF_Undefined) - continue; - failIfError(S.printName(NameOS)); - NameOS << '\0'; - ++NumSyms; - MemberOffsetRefs.push_back(MemberNum); - print32BE(Out, 0); - } - } - Out << NameOS.str(); - - if (StartOffset == 0) - return 0; - - if (Out.tell() % 2) - Out << '\0'; - - unsigned Pos = Out.tell(); - Out.seek(StartOffset - 12); - printWithSpacePadding(Out, Pos - StartOffset, 10); - Out.seek(StartOffset); - print32BE(Out, NumSyms); - Out.seek(Pos); - return StartOffset + 4; -} - -static void -performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, - std::vector<NewArchiveIterator> &NewMembers) { - SmallString<128> TmpArchive; - failIfError(sys::fs::createUniqueFile(ArchiveName + ".temp-archive-%%%%%%%.a", - TmpArchiveFD, TmpArchive)); - - TemporaryOutput = TmpArchive.c_str(); - tool_output_file Output(TemporaryOutput, TmpArchiveFD); - raw_fd_ostream &Out = Output.os(); - Out << "!<arch>\n"; - - std::vector<unsigned> MemberOffsetRefs; - - std::vector<std::unique_ptr<MemoryBuffer>> Buffers; - std::vector<MemoryBufferRef> Members; - std::vector<sys::fs::file_status> NewMemberStatus; - - for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) { - NewArchiveIterator &Member = NewMembers[I]; - MemoryBufferRef MemberRef; - - if (Member.isNewMember()) { - StringRef Filename = Member.getNew(); - NewMemberStatus.resize(NewMemberStatus.size() + 1); - sys::fs::file_status &Status = NewMemberStatus.back(); - int FD = Member.getFD(Status); - ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr = - MemoryBuffer::getOpenFile(FD, Filename, Status.getSize(), false); - failIfError(MemberBufferOrErr.getError(), Filename); - if (close(FD) != 0) - fail("Could not close file"); - Buffers.push_back(std::move(MemberBufferOrErr.get())); - MemberRef = Buffers.back()->getMemBufferRef(); - } else { - object::Archive::child_iterator OldMember = Member.getOld(); - ErrorOr<MemoryBufferRef> MemberBufferOrErr = - OldMember->getMemoryBufferRef(); - failIfError(MemberBufferOrErr.getError()); - MemberRef = MemberBufferOrErr.get(); - } - Members.push_back(MemberRef); - } - - unsigned MemberReferenceOffset = 0; - if (Symtab) { - MemberReferenceOffset = - writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs); - } - - std::vector<unsigned> StringMapIndexes; - writeStringTable(Out, NewMembers, StringMapIndexes); - - unsigned MemberNum = 0; - unsigned LongNameMemberNum = 0; - unsigned NewMemberNum = 0; - std::vector<unsigned> MemberOffset; - for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(), - E = NewMembers.end(); - I != E; ++I, ++MemberNum) { - - unsigned Pos = Out.tell(); - MemberOffset.push_back(Pos); - - MemoryBufferRef File = Members[MemberNum]; - if (I->isNewMember()) { - StringRef FileName = I->getNew(); - const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum]; - NewMemberNum++; - - StringRef Name = sys::path::filename(FileName); - if (Name.size() < 16) - printMemberHeader(Out, Name, Status.getLastModificationTime(), - Status.getUser(), Status.getGroup(), - Status.permissions(), Status.getSize()); - else - printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], - Status.getLastModificationTime(), Status.getUser(), - Status.getGroup(), Status.permissions(), - Status.getSize()); - } else { - object::Archive::child_iterator OldMember = I->getOld(); - StringRef Name = I->getName(); - - if (Name.size() < 16) - printMemberHeader(Out, Name, OldMember->getLastModified(), - OldMember->getUID(), OldMember->getGID(), - OldMember->getAccessMode(), OldMember->getSize()); - else - printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], - OldMember->getLastModified(), OldMember->getUID(), - OldMember->getGID(), OldMember->getAccessMode(), - OldMember->getSize()); - } - - Out << File.getBuffer(); - - if (Out.tell() % 2) - Out << '\n'; - } - - if (MemberReferenceOffset) { - Out.seek(MemberReferenceOffset); - for (unsigned MemberNum : MemberOffsetRefs) - print32BE(Out, MemberOffset[MemberNum]); - } - - Output.keep(); - Out.close(); - sys::fs::rename(TemporaryOutput, ArchiveName); - TemporaryOutput = nullptr; -} - static void performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, std::vector<NewArchiveIterator> *NewMembersP) { if (NewMembersP) { - performWriteOperation(Operation, OldArchive, *NewMembersP); + std::pair<StringRef, std::error_code> Result = + writeArchive(ArchiveName, *NewMembersP, Symtab); + failIfError(Result.second, Result.first); return; } std::vector<NewArchiveIterator> NewMembers = computeNewArchiveMembers(Operation, OldArchive); - performWriteOperation(Operation, OldArchive, NewMembers); + auto Result = writeArchive(ArchiveName, NewMembers, Symtab); + failIfError(Result.second, Result.first); } static void createSymbolTable(object::Archive *OldArchive) { diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp index f85f3b13b675..4ff53301881d 100644 --- a/tools/llvm-cov/CodeCoverage.cpp +++ b/tools/llvm-cov/CodeCoverage.cpp @@ -116,8 +116,7 @@ CodeCoverageTool::getSourceFile(StringRef SourceFile) { error(EC.message(), SourceFile); return EC; } - LoadedSourceFiles.push_back( - std::make_pair(SourceFile, std::move(Buffer.get()))); + LoadedSourceFiles.emplace_back(SourceFile, std::move(Buffer.get())); return *LoadedSourceFiles.back().second; } diff --git a/tools/llvm-cov/llvm-cov.cpp b/tools/llvm-cov/llvm-cov.cpp index bf66f583a528..8c5acaef63b2 100644 --- a/tools/llvm-cov/llvm-cov.cpp +++ b/tools/llvm-cov/llvm-cov.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" @@ -43,6 +44,12 @@ static int helpMain(int argc, const char *argv[]) { return 0; } +/// \brief Top level version information. +static int versionMain(int argc, const char *argv[]) { + cl::PrintVersionMessage(); + return 0; +} + int main(int argc, const char **argv) { // If argv[0] is or ends with 'gcov', always be gcov compatible if (sys::path::stem(argv[0]).endswith_lower("gcov")) @@ -57,6 +64,7 @@ int main(int argc, const char **argv) { .Case("report", reportMain) .Case("show", showMain) .Cases("-h", "-help", "--help", helpMain) + .Cases("-version", "--version", versionMain) .Default(nullptr); if (Func) { diff --git a/tools/llvm-cxxdump/llvm-cxxdump.cpp b/tools/llvm-cxxdump/llvm-cxxdump.cpp index 447d55afa8b8..ef42211cf897 100644 --- a/tools/llvm-cxxdump/llvm-cxxdump.cpp +++ b/tools/llvm-cxxdump/llvm-cxxdump.cpp @@ -204,9 +204,10 @@ static void dumpCXXData(const ObjectFile *Obj) { StringRef SecContents; if (error(Sec.getContents(SecContents))) return; - uint64_t SymAddress, SymSize; - if (error(Sym.getAddress(SymAddress)) || error(Sym.getSize(SymSize))) + uint64_t SymAddress; + if (error(Sym.getAddress(SymAddress))) return; + uint64_t SymSize = Sym.getSize(); uint64_t SecAddress = Sec.getAddress(); uint64_t SecSize = Sec.getSize(); uint64_t SymOffset = SymAddress - SecAddress; diff --git a/tools/llvm-dwarfdump/CMakeLists.txt b/tools/llvm-dwarfdump/CMakeLists.txt index 086b13974614..9a2e53f5a4bb 100644 --- a/tools/llvm-dwarfdump/CMakeLists.txt +++ b/tools/llvm-dwarfdump/CMakeLists.txt @@ -7,3 +7,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-dwarfdump llvm-dwarfdump.cpp ) + +if(LLVM_USE_SANITIZE_COVERAGE) + add_subdirectory(fuzzer) +endif() diff --git a/tools/llvm-dwarfdump/fuzzer/CMakeLists.txt b/tools/llvm-dwarfdump/fuzzer/CMakeLists.txt new file mode 100644 index 000000000000..1de35a3de478 --- /dev/null +++ b/tools/llvm-dwarfdump/fuzzer/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS + DebugInfoDWARF + Object + Support + ) + +add_llvm_executable(llvm-dwarfdump-fuzzer + EXCLUDE_FROM_ALL + llvm-dwarfdump-fuzzer.cpp + ) + +target_link_libraries(llvm-dwarfdump-fuzzer + LLVMFuzzer + ) diff --git a/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp b/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp new file mode 100644 index 000000000000..af0ac3652287 --- /dev/null +++ b/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp @@ -0,0 +1,34 @@ +//===-- llvm-dwarfdump-fuzzer.cpp - Fuzz the llvm-dwarfdump tool ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements a function that runs llvm-dwarfdump +/// on a single input. This function is then linked into the Fuzzer library. +/// +//===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace object; + +extern "C" void LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + std::unique_ptr<MemoryBuffer> Buff = MemoryBuffer::getMemBuffer( + StringRef((const char *)data, size), "", false); + + ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = + ObjectFile::createObjectFile(Buff->getMemBufferRef()); + if (!ObjOrErr) + return; + ObjectFile &Obj = *ObjOrErr.get(); + std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj)); + DICtx->dump(nulls(), DIDT_All); +} diff --git a/tools/llvm-lto/CMakeLists.txt b/tools/llvm-lto/CMakeLists.txt index 9adf6294631d..3ea1aeea9a41 100644 --- a/tools/llvm-lto/CMakeLists.txt +++ b/tools/llvm-lto/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS LTO MC Support + Target ) add_llvm_tool(llvm-lto diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index 9cd6587c2622..9678c8397e0e 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -253,11 +253,9 @@ int main(int argc, char **argv) { CodeGen.setAttr(attrs.c_str()); if (!OutputFilename.empty()) { - size_t len = 0; std::string ErrorInfo; - const void *Code = - CodeGen.compile(&len, DisableInline, DisableGVNLoadPRE, - DisableLTOVectorization, ErrorInfo); + std::unique_ptr<MemoryBuffer> Code = CodeGen.compile( + DisableInline, DisableGVNLoadPRE, DisableLTOVectorization, ErrorInfo); if (!Code) { errs() << argv[0] << ": error compiling the code: " << ErrorInfo << "\n"; @@ -272,7 +270,7 @@ int main(int argc, char **argv) { return 1; } - FileStream.write(reinterpret_cast<const char *>(Code), len); + FileStream.write(Code->getBufferStart(), Code->getBufferSize()); } else { std::string ErrorInfo; const char *OutputName = nullptr; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 6a8b49373df5..9a9185c7523c 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -70,6 +70,9 @@ static cl::opt<bool> PrintImmHex("print-imm-hex", cl::init(false), cl::desc("Prefer hex format for immediate values")); +static cl::list<std::string> +DefineSymbol("defsym", cl::desc("Defines a symbol to be an integer constant")); + enum OutputFileType { OFT_Null, OFT_AssemblyFile, @@ -316,6 +319,26 @@ static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, return Error; } +static int fillCommandLineSymbols(MCAsmParser &Parser){ + for(auto &I: DefineSymbol){ + auto Pair = StringRef(I).split('='); + if(Pair.second.empty()){ + errs() << "error: defsym must be of the form: sym=value: " << I; + return 1; + } + int64_t Value; + if(Pair.second.getAsInteger(0, Value)){ + errs() << "error: Value is not an integer: " << Pair.second; + return 1; + } + auto &Context = Parser.getContext(); + auto Symbol = Context.getOrCreateSymbol(Pair.first); + Parser.getStreamer().EmitAssignment(Symbol, + MCConstantExpr::create(Value, Context)); + } + return 0; +} + static int AssembleInput(const char *ProgName, const Target *TheTarget, SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str, MCAsmInfo &MAI, MCSubtargetInfo &STI, @@ -331,6 +354,9 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget, return 1; } + int SymbolResult = fillCommandLineSymbols(*Parser); + if(SymbolResult) + return SymbolResult; Parser->setShowParsedOperands(ShowInstOperands); Parser->setTargetParser(*TAP); diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index f3197bbfd104..8013f5842399 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -934,8 +934,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, S.Address = UnknownAddressOrSize; if (PrintSize && isa<ELFObjectFileBase>(Obj)) { symbol_iterator SymI = I; - if (error(SymI->getSize(S.Size))) - break; + S.Size = SymI->getSize(); } if (PrintAddress && isa<ObjectFile>(Obj)) if (error(symbol_iterator(I)->getAddress(S.Address))) diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp index 4a20b91b71fb..976a92154bda 100644 --- a/tools/llvm-objdump/COFFDump.cpp +++ b/tools/llvm-objdump/COFFDump.cpp @@ -167,7 +167,7 @@ resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym, if (std::error_code EC = Sym.getSection(iter)) return EC; ResolvedSection = Obj->getCOFFSection(*iter); - return object_error::success; + return std::error_code(); } // Given a vector of relocations for a section and an offset into this section @@ -182,7 +182,7 @@ static std::error_code resolveSymbol(const std::vector<RelocationRef> &Rels, return EC; if (Ofs == Offset) { Sym = *I->getSymbol(); - return object_error::success; + return std::error_code(); } } return object_error::parse_failed; @@ -204,7 +204,7 @@ getSectionContents(const COFFObjectFile *Obj, return EC; if (std::error_code EC = Obj->getSectionContents(Section, Contents)) return EC; - return object_error::success; + return std::error_code(); } // Given a vector of relocations for a section and an offset into this section @@ -217,7 +217,7 @@ static std::error_code resolveSymbolName(const std::vector<RelocationRef> &Rels, return EC; if (std::error_code EC = Sym.getName(Name)) return EC; - return object_error::success; + return std::error_code(); } static void printCOFFSymbolAddress(llvm::raw_ostream &Out, diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 84212c94bbb2..bf7451eb86d7 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -67,10 +67,6 @@ static cl::opt<bool> FullLeadingAddr("full-leading-addr", static cl::opt<bool> NoLeadingAddr("no-leading-addr", cl::desc("Print no leading address")); -static cl::opt<bool> - PrintImmHex("print-imm-hex", - cl::desc("Use hex format for immediate values")); - cl::opt<bool> llvm::UniversalHeaders("universal-headers", cl::desc("Print Mach-O universal headers " "(requires -macho)")); @@ -228,19 +224,19 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, case MachO::DICE_KIND_DATA: if (Length >= 4) { if (!NoShowRawInsn) - DumpBytes(ArrayRef<uint8_t>(bytes, 4)); + dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs()); Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; outs() << "\t.long " << Value; Size = 4; } else if (Length >= 2) { if (!NoShowRawInsn) - DumpBytes(ArrayRef<uint8_t>(bytes, 2)); + dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs()); Value = bytes[1] << 8 | bytes[0]; outs() << "\t.short " << Value; Size = 2; } else { if (!NoShowRawInsn) - DumpBytes(ArrayRef<uint8_t>(bytes, 2)); + dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs()); Value = bytes[0]; outs() << "\t.byte " << Value; Size = 1; @@ -252,14 +248,14 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, break; case MachO::DICE_KIND_JUMP_TABLE8: if (!NoShowRawInsn) - DumpBytes(ArrayRef<uint8_t>(bytes, 1)); + dumpBytes(ArrayRef<uint8_t>(bytes, 1), outs()); Value = bytes[0]; outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; Size = 1; break; case MachO::DICE_KIND_JUMP_TABLE16: if (!NoShowRawInsn) - DumpBytes(ArrayRef<uint8_t>(bytes, 2)); + dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs()); Value = bytes[1] << 8 | bytes[0]; outs() << "\t.short " << format("%5u", Value & 0xffff) << "\t@ KIND_JUMP_TABLE16\n"; @@ -268,7 +264,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, case MachO::DICE_KIND_JUMP_TABLE32: case MachO::DICE_KIND_ABS_JUMP_TABLE32: if (!NoShowRawInsn) - DumpBytes(ArrayRef<uint8_t>(bytes, 4)); + dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs()); Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; outs() << "\t.long " << Value; if (Kind == MachO::DICE_KIND_JUMP_TABLE32) @@ -281,8 +277,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, return Size; } -static void getSectionsAndSymbols(const MachO::mach_header Header, - MachOObjectFile *MachOObj, +static void getSectionsAndSymbols(MachOObjectFile *MachOObj, std::vector<SectionRef> &Sections, std::vector<SymbolRef> &Symbols, SmallVectorImpl<uint64_t> &FoundFns, @@ -300,10 +295,8 @@ static void getSectionsAndSymbols(const MachO::mach_header Header, Sections.push_back(Section); } - MachOObjectFile::LoadCommandInfo Command = - MachOObj->getFirstLoadCommandInfo(); bool BaseSegmentAddressSet = false; - for (unsigned i = 0;; ++i) { + for (const auto &Command : MachOObj->load_commands()) { if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { // We found a function starts segment, parse the addresses for later // consumption. @@ -319,11 +312,6 @@ static void getSectionsAndSymbols(const MachO::mach_header Header, BaseSegmentAddress = SLC.vmaddr; } } - - if (i == Header.ncmds - 1) - break; - else - Command = MachOObj->getNextLoadCommandInfo(Command); } } @@ -386,9 +374,7 @@ static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, } static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { - uint32_t LoadCommandCount = O->getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo(); - for (unsigned I = 0;; ++I) { + for (const auto &Load : O->load_commands()) { if (Load.C.cmd == MachO::LC_SEGMENT_64) { MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); for (unsigned J = 0; J < Seg.nsects; ++J) { @@ -446,10 +432,6 @@ static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { } } } - if (I == LoadCommandCount - 1) - break; - else - Load = O->getNextLoadCommandInfo(Load); } } @@ -553,9 +535,8 @@ static void PrintLinkOptHints(MachOObjectFile *O) { } static void PrintDylibs(MachOObjectFile *O, bool JustId) { - uint32_t LoadCommandCount = O->getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo(); - for (unsigned I = 0;; ++I) { + unsigned Index = 0; + for (const auto &Load : O->load_commands()) { if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || Load.C.cmd == MachO::LC_LOAD_DYLIB || @@ -595,13 +576,9 @@ static void PrintDylibs(MachOObjectFile *O, bool JustId) { outs() << "LC_LOAD_UPWARD_DYLIB "; else outs() << "LC_??? "; - outs() << "command " << I << "\n"; + outs() << "command " << Index++ << "\n"; } } - if (I == LoadCommandCount - 1) - break; - else - Load = O->getNextLoadCommandInfo(Load); } } @@ -2132,9 +2109,7 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, // it returns a pointer to that string. Else it returns nullptr. static const char *GuessCstringPointer(uint64_t ReferenceValue, struct DisassembleInfo *info) { - uint32_t LoadCommandCount = info->O->getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); - for (unsigned I = 0;; ++I) { + for (const auto &Load : info->O->load_commands()) { if (Load.C.cmd == MachO::LC_SEGMENT_64) { MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); for (unsigned J = 0; J < Seg.nsects; ++J) { @@ -2178,10 +2153,6 @@ static const char *GuessCstringPointer(uint64_t ReferenceValue, } } } - if (I == LoadCommandCount - 1) - break; - else - Load = info->O->getNextLoadCommandInfo(Load); } return nullptr; } @@ -2192,11 +2163,9 @@ static const char *GuessCstringPointer(uint64_t ReferenceValue, // symbol name being referenced by the stub or pointer. static const char *GuessIndirectSymbol(uint64_t ReferenceValue, struct DisassembleInfo *info) { - uint32_t LoadCommandCount = info->O->getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); - for (unsigned I = 0;; ++I) { + for (const auto &Load : info->O->load_commands()) { if (Load.C.cmd == MachO::LC_SEGMENT_64) { MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); for (unsigned J = 0; J < Seg.nsects; ++J) { @@ -2266,10 +2235,6 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue, } } } - if (I == LoadCommandCount - 1) - break; - else - Load = info->O->getNextLoadCommandInfo(Load); } return nullptr; } @@ -2356,9 +2321,7 @@ static uint64_t GuessPointerPointer(uint64_t ReferenceValue, selref = false; msgref = false; cfstring = false; - uint32_t LoadCommandCount = info->O->getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); - for (unsigned I = 0;; ++I) { + for (const auto &Load : info->O->load_commands()) { if (Load.C.cmd == MachO::LC_SEGMENT_64) { MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); for (unsigned J = 0; J < Seg.nsects; ++J) { @@ -2403,10 +2366,6 @@ static uint64_t GuessPointerPointer(uint64_t ReferenceValue, } } // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. - if (I == LoadCommandCount - 1) - break; - else - Load = info->O->getNextLoadCommandInfo(Load); } return 0; } @@ -6075,7 +6034,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, SmallVector<uint64_t, 8> FoundFns; uint64_t BaseSegmentAddress; - getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns, + getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, BaseSegmentAddress); // Sort the symbols by address, just in case they didn't come in that way. @@ -6313,7 +6272,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, DebugOut, Annotations); if (gotInst) { if (!NoShowRawInsn) { - DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size)); + dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size), outs()); } formatted_raw_ostream FormattedOS(outs()); Annotations.flush(); @@ -6378,7 +6337,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, } if (!NoShowRawInsn) { outs() << "\t"; - DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize)); + dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize), outs()); } IP->printInst(&Inst, outs(), "", *STI); outs() << "\n"; @@ -8367,15 +8326,12 @@ static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, outs() << "\n"; } -static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds, - uint32_t filetype, uint32_t cputype, - bool verbose) { - if (ncmds == 0) - return; +static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, + uint32_t cputype, bool verbose) { StringRef Buf = Obj->getData(); - MachOObjectFile::LoadCommandInfo Command = Obj->getFirstLoadCommandInfo(); - for (unsigned i = 0;; ++i) { - outs() << "Load command " << i << "\n"; + unsigned Index = 0; + for (const auto &Command : Obj->load_commands()) { + outs() << "Load command " << Index++ << "\n"; if (Command.C.cmd == MachO::LC_SEGMENT) { MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); const char *sg_segname = SLC.segname; @@ -8494,14 +8450,10 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds, // TODO: get and print the raw bytes of the load command. } // TODO: print all the other kinds of load commands. - if (i == ncmds - 1) - break; - else - Command = Obj->getNextLoadCommandInfo(Command); } } -static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds, +static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &filetype, uint32_t &cputype, bool verbose) { if (Obj->is64Bit()) { @@ -8509,7 +8461,6 @@ static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds, H_64 = Obj->getHeader64(); PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); - ncmds = H_64.ncmds; filetype = H_64.filetype; cputype = H_64.cputype; } else { @@ -8517,7 +8468,6 @@ static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds, H = Obj->getHeader(); PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, H.sizeofcmds, H.flags, verbose); - ncmds = H.ncmds; filetype = H.filetype; cputype = H.cputype; } @@ -8525,11 +8475,10 @@ static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds, void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); - uint32_t ncmds = 0; uint32_t filetype = 0; uint32_t cputype = 0; - getAndPrintMachHeader(file, ncmds, filetype, cputype, !NonVerbose); - PrintLoadCommands(file, ncmds, filetype, cputype, !NonVerbose); + getAndPrintMachHeader(file, filetype, cputype, !NonVerbose); + PrintLoadCommands(file, filetype, cputype, !NonVerbose); } //===----------------------------------------------------------------------===// diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index e442ac050fce..1152a154b4db 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -32,12 +32,14 @@ #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/COFF.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/GraphWriter.h" @@ -147,6 +149,10 @@ static cl::alias PrivateHeadersShort("p", cl::desc("Alias for --private-headers"), cl::aliasopt(PrivateHeaders)); +cl::opt<bool> + llvm::PrintImmHex("print-imm-hex", + cl::desc("Use hex format for immediate values")); + static StringRef ToolName; static int ReturnValue = EXIT_SUCCESS; @@ -160,6 +166,12 @@ bool llvm::error(std::error_code EC) { return true; } +static void report_error(StringRef File, std::error_code EC) { + assert(EC); + errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n"; + ReturnValue = EXIT_FAILURE; +} + static const Target *getTarget(const ObjectFile *Obj = nullptr) { // Figure out the target triple. llvm::Triple TheTriple("unknown-unknown-unknown"); @@ -194,19 +206,6 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) { return TheTarget; } -void llvm::DumpBytes(ArrayRef<uint8_t> bytes) { - static const char hex_rep[] = "0123456789abcdef"; - SmallString<64> output; - - for (char i: bytes) { - output.push_back(hex_rep[(i & 0xF0) >> 4]); - output.push_back(hex_rep[i & 0xF]); - output.push_back(' '); - } - - outs() << output.c_str(); -} - bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; if (error(a.getOffset(a_addr))) return false; @@ -214,6 +213,474 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { return a_addr < b_addr; } +namespace { +class PrettyPrinter { +public: + virtual ~PrettyPrinter(){} + virtual void printInst(MCInstPrinter &IP, const MCInst *MI, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI) { + outs() << format("%8" PRIx64 ":", Address); + if (!NoShowRawInsn) { + outs() << "\t"; + dumpBytes(Bytes, outs()); + } + IP.printInst(MI, outs(), "", STI); + } +}; +PrettyPrinter PrettyPrinterInst; +class HexagonPrettyPrinter : public PrettyPrinter { +public: + void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &OS) { + uint32_t opcode = + (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0]; + OS << format("%8" PRIx64 ":", Address); + if (!NoShowRawInsn) { + OS << "\t"; + dumpBytes(Bytes.slice(0, 4), OS); + OS << format("%08" PRIx32, opcode); + } + } + void printInst(MCInstPrinter &IP, const MCInst *MI, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI) override { + std::string Buffer; + { + raw_string_ostream TempStream(Buffer); + IP.printInst(MI, TempStream, "", STI); + } + StringRef Contents(Buffer); + // Split off bundle attributes + auto PacketBundle = Contents.rsplit('\n'); + // Split off first instruction from the rest + auto HeadTail = PacketBundle.first.split('\n'); + auto Preamble = " { "; + auto Separator = ""; + while(!HeadTail.first.empty()) { + OS << Separator; + Separator = "\n"; + printLead(Bytes, Address, OS); + OS << Preamble; + Preamble = " "; + StringRef Inst; + auto Duplex = HeadTail.first.split('\v'); + if(!Duplex.second.empty()){ + OS << Duplex.first; + OS << "; "; + Inst = Duplex.second; + } + else + Inst = HeadTail.first; + OS << Inst; + Bytes = Bytes.slice(4); + Address += 4; + HeadTail = HeadTail.second.split('\n'); + } + OS << " } " << PacketBundle.second; + } +}; +HexagonPrettyPrinter HexagonPrettyPrinterInst; +PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { + switch(Triple.getArch()) { + default: + return PrettyPrinterInst; + case Triple::hexagon: + return HexagonPrettyPrinterInst; + } +} +} + +template <class ELFT> +static const typename ELFObjectFile<ELFT>::Elf_Rel * +getRel(const ELFFile<ELFT> &EF, DataRefImpl Rel) { + typedef typename ELFObjectFile<ELFT>::Elf_Rel Elf_Rel; + return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); +} + +template <class ELFT> +static const typename ELFObjectFile<ELFT>::Elf_Rela * +getRela(const ELFFile<ELFT> &EF, DataRefImpl Rela) { + typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela; + return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); +} + +template <class ELFT> +static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, + DataRefImpl Rel, + SmallVectorImpl<char> &Result) { + typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; + const ELFFile<ELFT> &EF = *Obj->getELFFile(); + + const Elf_Shdr *sec = EF.getSection(Rel.d.a); + uint8_t type; + StringRef res; + int64_t addend = 0; + uint16_t symbol_index = 0; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(EF, Rel)->getType(EF.isMips64EL()); + symbol_index = getRel(EF, Rel)->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + type = getRela(EF, Rel)->getType(EF.isMips64EL()); + symbol_index = getRela(EF, Rel)->getSymbol(EF.isMips64EL()); + addend = getRela(EF, Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry<Elf_Sym>(sec->sh_link, symbol_index); + StringRef Target; + const Elf_Shdr *SymSec = EF.getSection(symb); + if (symb->getType() == ELF::STT_SECTION) { + ErrorOr<StringRef> SecName = EF.getSectionName(SymSec); + if (std::error_code EC = SecName.getError()) + return EC; + Target = *SecName; + } else { + ErrorOr<StringRef> SymName = + EF.getSymbolName(EF.getSection(sec->sh_link), symb); + if (!SymName) + return SymName.getError(); + Target = *SymName; + } + switch (EF.getHeader()->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_PC8: + case ELF::R_X86_64_PC16: + case ELF::R_X86_64_PC32: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << Target << (addend < 0 ? "" : "+") << addend << "-P"; + 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: + case ELF::R_X86_64_32S: + case ELF::R_X86_64_64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << Target << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + default: + res = "Unknown"; + } + break; + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << Target; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } + case ELF::EM_386: + case ELF::EM_ARM: + case ELF::EM_HEXAGON: + case ELF::EM_MIPS: + res = Target; + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return std::error_code(); +} + +static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj, + const RelocationRef &RelRef, + SmallVectorImpl<char> &Result) { + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj)) + return getRelocationValueString(ELF32LE, Rel, Result); + if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj)) + return getRelocationValueString(ELF64LE, Rel, Result); + if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj)) + return getRelocationValueString(ELF32BE, Rel, Result); + auto *ELF64BE = cast<ELF64BEObjectFile>(Obj); + return getRelocationValueString(ELF64BE, Rel, Result); +} + +static std::error_code getRelocationValueString(const COFFObjectFile *Obj, + const RelocationRef &Rel, + SmallVectorImpl<char> &Result) { + symbol_iterator SymI = Rel.getSymbol(); + StringRef SymName; + if (std::error_code EC = SymI->getName(SymName)) + return EC; + Result.append(SymName.begin(), SymName.end()); + return std::error_code(); +} + +static void printRelocationTargetName(const MachOObjectFile *O, + const MachO::any_relocation_info &RE, + raw_string_ostream &fmt) { + bool IsScattered = O->isRelocationScattered(RE); + + // Target of a scattered relocation is an address. In the interest of + // generating pretty output, scan through the symbol table looking for a + // symbol that aligns with that address. If we find one, print it. + // Otherwise, we just print the hex address of the target. + if (IsScattered) { + uint32_t Val = O->getPlainRelocationSymbolNum(RE); + + for (const SymbolRef &Symbol : O->symbols()) { + std::error_code ec; + uint64_t Addr; + StringRef Name; + + if ((ec = Symbol.getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) + continue; + if ((ec = Symbol.getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + // If we couldn't find a symbol that this relocation refers to, try + // to find a section beginning instead. + for (const SectionRef &Section : O->sections()) { + std::error_code ec; + + StringRef Name; + uint64_t Addr = Section.getAddress(); + if (Addr != Val) + continue; + if ((ec = Section.getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + fmt << format("0x%x", Val); + return; + } + + StringRef S; + bool isExtern = O->getPlainRelocationExternal(RE); + uint64_t Val = O->getPlainRelocationSymbolNum(RE); + + if (isExtern) { + symbol_iterator SI = O->symbol_begin(); + advance(SI, Val); + SI->getName(S); + } else { + section_iterator SI = O->section_begin(); + // Adjust for the fact that sections are 1-indexed. + advance(SI, Val - 1); + SI->getName(S); + } + + fmt << S; +} + +static std::error_code getRelocationValueString(const MachOObjectFile *Obj, + const RelocationRef &RelRef, + SmallVectorImpl<char> &Result) { + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + MachO::any_relocation_info RE = Obj->getRelocation(Rel); + + unsigned Arch = Obj->getArch(); + + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + unsigned Type = Obj->getAnyRelocationType(RE); + bool IsPCRel = Obj->getAnyRelocationPCRel(RE); + + // Determine any addends that should be displayed with the relocation. + // These require decoding the relocation type, which is triple-specific. + + // X86_64 has entirely custom relocation types. + if (Arch == Triple::x86_64) { + bool isPCRel = Obj->getAnyRelocationPCRel(RE); + + switch (Type) { + case MachO::X86_64_RELOC_GOT_LOAD: + case MachO::X86_64_RELOC_GOT: { + printRelocationTargetName(Obj, RE, fmt); + fmt << "@GOT"; + if (isPCRel) + fmt << "PCREL"; + break; + } + case MachO::X86_64_RELOC_SUBTRACTOR: { + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type + // X86_64_RELOC_UNSIGNED. + // NOTE: Scattered relocations don't exist on x86_64. + unsigned RType = Obj->getAnyRelocationType(RENext); + if (RType != MachO::X86_64_RELOC_UNSIGNED) + report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); + + // The X86_64_RELOC_UNSIGNED contains the minuend symbol; + // X86_64_RELOC_SUBTRACTOR contains the subtrahend. + printRelocationTargetName(Obj, RENext, fmt); + fmt << "-"; + printRelocationTargetName(Obj, RE, fmt); + break; + } + case MachO::X86_64_RELOC_TLV: + printRelocationTargetName(Obj, RE, fmt); + fmt << "@TLV"; + if (isPCRel) + fmt << "P"; + break; + case MachO::X86_64_RELOC_SIGNED_1: + printRelocationTargetName(Obj, RE, fmt); + fmt << "-1"; + break; + case MachO::X86_64_RELOC_SIGNED_2: + printRelocationTargetName(Obj, RE, fmt); + fmt << "-2"; + break; + case MachO::X86_64_RELOC_SIGNED_4: + printRelocationTargetName(Obj, RE, fmt); + fmt << "-4"; + break; + default: + printRelocationTargetName(Obj, RE, fmt); + break; + } + // X86 and ARM share some relocation types in common. + } else if (Arch == Triple::x86 || Arch == Triple::arm || + Arch == Triple::ppc) { + // Generic relocation types... + switch (Type) { + case MachO::GENERIC_RELOC_PAIR: // prints no info + return std::error_code(); + case MachO::GENERIC_RELOC_SECTDIFF: { + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = Obj->getAnyRelocationType(RENext); + + if (RType != MachO::GENERIC_RELOC_PAIR) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); + + printRelocationTargetName(Obj, RE, fmt); + fmt << "-"; + printRelocationTargetName(Obj, RENext, fmt); + break; + } + } + + if (Arch == Triple::x86 || Arch == Triple::ppc) { + switch (Type) { + case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = Obj->getAnyRelocationType(RENext); + if (RType != MachO::GENERIC_RELOC_PAIR) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); + + printRelocationTargetName(Obj, RE, fmt); + fmt << "-"; + printRelocationTargetName(Obj, RENext, fmt); + break; + } + case MachO::GENERIC_RELOC_TLV: { + printRelocationTargetName(Obj, RE, fmt); + fmt << "@TLV"; + if (IsPCRel) + fmt << "P"; + break; + } + default: + printRelocationTargetName(Obj, RE, fmt); + } + } else { // ARM-specific relocations + switch (Type) { + case MachO::ARM_RELOC_HALF: + case MachO::ARM_RELOC_HALF_SECTDIFF: { + // Half relocations steal a bit from the length field to encode + // whether this is an upper16 or a lower16 relocation. + bool isUpper = Obj->getAnyRelocationLength(RE) >> 1; + + if (isUpper) + fmt << ":upper16:("; + else + fmt << ":lower16:("; + printRelocationTargetName(Obj, RE, fmt); + + DataRefImpl RelNext = Rel; + Obj->moveRelocationNext(RelNext); + MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); + + // ARM half relocs must be followed by a relocation of type + // ARM_RELOC_PAIR. + unsigned RType = Obj->getAnyRelocationType(RENext); + if (RType != MachO::ARM_RELOC_PAIR) + report_fatal_error("Expected ARM_RELOC_PAIR after " + "ARM_RELOC_HALF"); + + // NOTE: The half of the target virtual address is stashed in the + // address field of the secondary relocation, but we can't reverse + // engineer the constant offset from it without decoding the movw/movt + // instruction to find the other half in its immediate field. + + // ARM_RELOC_HALF_SECTDIFF encodes the second section in the + // symbol/section pointer of the follow-on relocation. + if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { + fmt << "-"; + printRelocationTargetName(Obj, RENext, fmt); + } + + fmt << ")"; + break; + } + default: { printRelocationTargetName(Obj, RE, fmt); } + } + } + } else + printRelocationTargetName(Obj, RE, fmt); + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + return std::error_code(); +} + +static std::error_code getRelocationValueString(const RelocationRef &Rel, + SmallVectorImpl<char> &Result) { + const ObjectFile *Obj = Rel.getObjectFile(); + if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj)) + return getRelocationValueString(ELF, Rel, Result); + if (auto *COFF = dyn_cast<COFFObjectFile>(Obj)) + return getRelocationValueString(COFF, Rel, Result); + auto *MachO = cast<MachOObjectFile>(Obj); + return getRelocationValueString(MachO, Rel, Result); +} + static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = getTarget(Obj); // getTarget() will have already issued a diagnostic if necessary, so @@ -280,6 +747,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { << '\n'; return; } + IP->setPrintImmHex(PrintImmHex); + PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; @@ -352,11 +821,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { outs() << SegmentName << ","; outs() << name << ':'; - // If the section has no symbols just insert a dummy one and disassemble - // the whole section. - if (Symbols.empty()) - Symbols.push_back(std::make_pair(0, name)); - + // If the section has no symbol at the start, just insert a dummy one. + if (Symbols.empty() || Symbols[0].first != 0) + Symbols.insert(Symbols.begin(), std::make_pair(0, name)); SmallString<40> Comments; raw_svector_ostream CommentStream(Comments); @@ -396,12 +863,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), SectionAddr + Index, DebugOut, CommentStream)) { - outs() << format("%8" PRIx64 ":", SectionAddr + Index); - if (!NoShowRawInsn) { - outs() << "\t"; - DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size)); - } - IP->printInst(&Inst, outs(), "", *STI); + PIP.printInst(*IP, &Inst, + Bytes.slice(Index, Size), + SectionAddr + Index, outs(), "", *STI); outs() << CommentStream.str(); Comments.clear(); outs() << "\n"; @@ -426,8 +890,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; if (error(rel_cur->getTypeName(name))) goto skip_print_rel; - if (error(rel_cur->getValueString(val))) goto skip_print_rel; - + if (error(getRelocationValueString(*rel_cur, val))) + goto skip_print_rel; outs() << format(Fmt.data(), SectionAddr + addr) << name << "\t" << val << "\n"; @@ -467,7 +931,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { continue; if (error(Reloc.getOffset(address))) continue; - if (error(Reloc.getValueString(valuestr))) + if (error(getRelocationValueString(Reloc, valuestr))) continue; outs() << format(Fmt.data(), address) << " " << relocname << " " << valuestr << "\n"; @@ -608,22 +1072,23 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { return; } for (const SymbolRef &Symbol : o->symbols()) { - StringRef Name; uint64_t Address; SymbolRef::Type Type; - uint64_t Size; uint32_t Flags = Symbol.getFlags(); section_iterator Section = o->section_end(); - if (error(Symbol.getName(Name))) - continue; if (error(Symbol.getAddress(Address))) continue; if (error(Symbol.getType(Type))) continue; - if (error(Symbol.getSize(Size))) - continue; + uint64_t Size = Symbol.getSize(); if (error(Symbol.getSection(Section))) continue; + StringRef Name; + if (Type == SymbolRef::ST_Debug && Section != o->section_end()) { + Section->getName(Name); + } else if (error(Symbol.getName(Name))) { + continue; + } bool Global = Flags & SymbolRef::SF_Global; bool Weak = Flags & SymbolRef::SF_Weak; @@ -632,9 +1097,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { bool Hidden = Flags & SymbolRef::SF_Hidden; if (Common) { - uint32_t Alignment; - if (error(Symbol.getAlignment(Alignment))) - Alignment = 0; + uint32_t Alignment = Symbol.getAlignment(); Address = Size; Size = Alignment; } @@ -812,15 +1275,13 @@ static void DumpArchive(const Archive *a) { if (std::error_code EC = ChildOrErr.getError()) { // Ignore non-object files. if (EC != object_error::invalid_file_type) - errs() << ToolName << ": '" << a->getFileName() << "': " << EC.message() - << ".\n"; + report_error(a->getFileName(), EC); continue; } if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) DumpObject(o); else - errs() << ToolName << ": '" << a->getFileName() << "': " - << "Unrecognized file type.\n"; + report_error(a->getFileName(), object_error::invalid_file_type); } } @@ -828,7 +1289,7 @@ static void DumpArchive(const Archive *a) { static void DumpInput(StringRef file) { // If file isn't stdin, check that it exists. if (file != "-" && !sys::fs::exists(file)) { - errs() << ToolName << ": '" << file << "': " << "No such file\n"; + report_error(file, errc::no_such_file_or_directory); return; } @@ -843,7 +1304,7 @@ static void DumpInput(StringRef file) { // Attempt to open the binary. ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file); if (std::error_code EC = BinaryOrErr.getError()) { - errs() << ToolName << ": '" << file << "': " << EC.message() << ".\n"; + report_error(file, EC); return; } Binary &Binary = *BinaryOrErr.get().getBinary(); @@ -853,7 +1314,7 @@ static void DumpInput(StringRef file) { else if (ObjectFile *o = dyn_cast<ObjectFile>(&Binary)) DumpObject(o); else - errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n"; + report_error(file, object_error::invalid_file_type); } int main(int argc, char **argv) { diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index bde72e004a1f..b4d34f4033bc 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -51,11 +51,11 @@ extern cl::opt<bool> SectionHeaders; extern cl::opt<bool> SectionContents; extern cl::opt<bool> SymbolTable; extern cl::opt<bool> UnwindInfo; +extern cl::opt<bool> PrintImmHex; // Various helper functions. bool error(std::error_code ec); bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b); -void DumpBytes(ArrayRef<uint8_t> bytes); void ParseInputMachO(StringRef Filename); void printCOFFUnwindInfo(const object::COFFObjectFile* o); void printMachOUnwindInfo(const object::MachOObjectFile* o); diff --git a/tools/llvm-pdbdump/LinePrinter.h b/tools/llvm-pdbdump/LinePrinter.h index c2a3ab60d90f..b985e9341909 100644 --- a/tools/llvm-pdbdump/LinePrinter.h +++ b/tools/llvm-pdbdump/LinePrinter.h @@ -41,7 +41,7 @@ private: void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) { List.clear(); for (; Begin != End; ++Begin) - List.push_back(StringRef(*Begin)); + List.emplace_back(StringRef(*Begin)); } raw_ostream &OS; diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index 141211134ffd..4a1d5da30e65 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -142,7 +142,7 @@ std::error_code COFFDumper::resolveSymbolName(const coff_section *Section, return EC; if (std::error_code EC = Symbol.getName(Name)) return EC; - return object_error::success; + return std::error_code(); } static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = { diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index a20512f20534..0931cb70f6d8 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -141,19 +141,19 @@ static void getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol, StringRef &SectionName, unsigned &SectionIndex) { SectionIndex = Symbol->st_shndx; - if (SectionIndex == SHN_UNDEF) { + if (Symbol->isUndefined()) SectionName = "Undefined"; - } else if (SectionIndex >= SHN_LOPROC && SectionIndex <= SHN_HIPROC) { + else if (Symbol->isProcessorSpecific()) SectionName = "Processor Specific"; - } else if (SectionIndex >= SHN_LOOS && SectionIndex <= SHN_HIOS) { + else if (Symbol->isOSSpecific()) SectionName = "Operating System Specific"; - } else if (SectionIndex > SHN_HIOS && SectionIndex < SHN_ABS) { + else if (Symbol->isReserved()) SectionName = "Reserved"; - } else if (SectionIndex == SHN_ABS) { + else if (Symbol->isAbsolute()) SectionName = "Absolute"; - } else if (SectionIndex == SHN_COMMON) { + else if (Symbol->isCommon()) SectionName = "Common"; - } else { + else { if (SectionIndex == SHN_XINDEX) SectionIndex = Obj.getSymbolTableIndex(&*Symbol); assert(SectionIndex != SHN_XINDEX && @@ -705,26 +705,30 @@ void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel) { SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); - StringRef SymbolName; + StringRef TargetName; std::pair<const Elf_Shdr *, const Elf_Sym *> Sym = Obj->getRelocationSymbol(Sec, &Rel); - if (Sym.first) - SymbolName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); + if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) { + const Elf_Shdr *Sec = Obj->getSection(Sym.second); + ErrorOr<StringRef> SecName = Obj->getSectionName(Sec); + if (SecName) + TargetName = SecName.get(); + } else if (Sym.first) { + TargetName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); + } if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printNumber("Symbol", SymbolName.size() > 0 ? SymbolName : "-", + W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", Rel.getSymbol(Obj->isMips64EL())); W.printHex("Addend", Rel.r_addend); } else { raw_ostream& OS = W.startLine(); - OS << W.hex(Rel.r_offset) - << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Rel.r_addend) - << "\n"; + OS << W.hex(Rel.r_offset) << " " << RelocName << " " + << (TargetName.size() > 0 ? TargetName : "-") << " " + << W.hex(Rel.r_addend) << "\n"; } } @@ -991,11 +995,10 @@ void ELFDumper<ELFT>::printUnwindInfo() { } namespace { -template <> -void ELFDumper<ELFType<support::little, 2, false> >::printUnwindInfo() { +template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { - ARM::EHABI::PrinterContext<ELFType<support::little, 2, false> > Ctx(W, Obj); + ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(W, Obj); return Ctx.PrintUnwindInformation(); } W.startLine() << "UnwindInfo not implemented.\n"; @@ -1075,8 +1078,7 @@ void ELFDumper<ELFT>::printAttributes() { } namespace { -template <> -void ELFDumper<ELFType<support::little, 2, false> >::printAttributes() { +template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { if (Obj->getHeader()->e_machine != EM_ARM) { W.startLine() << "Attributes not implemented.\n"; return; diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp index f058632a8ce8..b148c5d2abda 100644 --- a/tools/llvm-readobj/Win64EHDumper.cpp +++ b/tools/llvm-readobj/Win64EHDumper.cpp @@ -152,7 +152,7 @@ static std::error_code resolveRelocation(const Dumper::Context &Ctx, return EC; ResolvedSection = Ctx.COFF.getCOFFSection(*SI); - return object_error::success; + return std::error_code(); } namespace llvm { diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index e87f1e2d4c19..f857b2ef9735 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -47,6 +47,7 @@ InputFileList(cl::Positional, cl::ZeroOrMore, enum ActionType { AC_Execute, + AC_PrintObjectLineInfo, AC_PrintLineInfo, AC_PrintDebugLineInfo, AC_Verify @@ -61,6 +62,8 @@ Action(cl::desc("Action to perform:"), "Load, link, and print line information for each function."), clEnumValN(AC_PrintDebugLineInfo, "printdebugline", "Load, link, and print line information for each function using the debug object"), + clEnumValN(AC_PrintObjectLineInfo, "printobjline", + "Like -printlineinfo but does not load the object first"), clEnumValN(AC_Verify, "verify", "Load, link and verify the resulting memory image."), clEnumValEnd)); @@ -136,6 +139,11 @@ public: // explicit cache flush, otherwise JIT code manipulations (like resolved // relocations) will get to the data cache but not to the instruction cache. virtual void invalidateInstructionCache(); + + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override {} + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override {} }; uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, @@ -244,26 +252,69 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { std::unique_ptr<DIContext> Context( new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get())); + // FIXME: This is generally useful. Figure out a place in lib/Object to + // put utility functions. + std::map<object::SectionRef, std::vector<uint64_t>> FuncAddresses; + if (!isa<ELFObjectFileBase>(SymbolObj)) { + for (object::SymbolRef Sym : SymbolObj->symbols()) { + object::SymbolRef::Type SymType; + if (Sym.getType(SymType)) + continue; + if (SymType != object::SymbolRef::ST_Function) + continue; + uint64_t Addr; + if (Sym.getAddress(Addr)) + continue; + object::section_iterator Sec = SymbolObj->section_end(); + if (Sym.getSection(Sec)) + continue; + std::vector<uint64_t> &Addrs = FuncAddresses[*Sec]; + if (Addrs.empty()) { + uint64_t SecAddr = Sec->getAddress(); + uint64_t SecSize = Sec->getSize(); + Addrs.push_back(SecAddr + SecSize); + } + Addrs.push_back(Addr); + } + for (auto &Pair : FuncAddresses) { + std::vector<uint64_t> &Addrs = Pair.second; + array_pod_sort(Addrs.begin(), Addrs.end()); + } + } + // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = SymbolObj->symbol_begin(), - E = SymbolObj->symbol_end(); - I != E; ++I) { + for (object::SymbolRef Sym : SymbolObj->symbols()) { object::SymbolRef::Type SymType; - if (I->getType(SymType)) continue; + if (Sym.getType(SymType)) + continue; if (SymType == object::SymbolRef::ST_Function) { StringRef Name; uint64_t Addr; - uint64_t Size; - if (I->getName(Name)) continue; - if (I->getAddress(Addr)) continue; - if (I->getSize(Size)) continue; + if (Sym.getName(Name)) + continue; + if (Sym.getAddress(Addr)) + continue; + + uint64_t Size; + if (isa<ELFObjectFileBase>(SymbolObj)) { + Size = Sym.getSize(); + } else { + object::section_iterator Sec = SymbolObj->section_end(); + if (Sym.getSection(Sec)) + continue; + const std::vector<uint64_t> &Addrs = FuncAddresses[*Sec]; + auto AddrI = std::find(Addrs.begin(), Addrs.end(), Addr); + assert(AddrI != Addrs.end() && (AddrI + 1) != Addrs.end()); + assert(*AddrI == Addr); + Size = *(AddrI + 1) - Addr; + } // If we're not using the debug object, compute the address of the // symbol in memory (rather than that in the unrelocated object file) // and use that to query the DWARFContext. if (!UseDebugObj && LoadObjects) { object::section_iterator Sec(SymbolObj->section_end()); - I->getSection(Sec); + Sym.getSection(Sec); StringRef SecName; Sec->getName(SecName); uint64_t SectionLoadAddress = @@ -622,9 +673,11 @@ int main(int argc, char **argv) { case AC_Execute: return executeInput(); case AC_PrintDebugLineInfo: - return printLineInfoForInput(true,true); + return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */ true); case AC_PrintLineInfo: - return printLineInfoForInput(true,false); + return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */false); + case AC_PrintObjectLineInfo: + return printLineInfoForInput(/* LoadObjects */false,/* UseDebugObj */false); case AC_Verify: return linkAndVerify(); } diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp index 0e0dd59ce92f..c64c1d722d3d 100644 --- a/tools/llvm-size/llvm-size.cpp +++ b/tools/llvm-size/llvm-size.cpp @@ -122,12 +122,10 @@ static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { fmt << "0x"; fmt << "%" << radix_fmt; - uint32_t LoadCommandCount = MachO->getHeader().ncmds; uint32_t Filetype = MachO->getHeader().filetype; - MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo(); uint64_t total = 0; - for (unsigned I = 0;; ++I) { + for (const auto &Load : MachO->load_commands()) { if (Load.C.cmd == MachO::LC_SEGMENT_64) { MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load); outs() << "Segment " << Seg.segname << ": " @@ -181,10 +179,6 @@ static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { if (Seg.nsects != 0) outs() << "\ttotal " << format(fmt.str().c_str(), sec_total) << "\n"; } - if (I == LoadCommandCount - 1) - break; - else - Load = MachO->getNextLoadCommandInfo(Load); } outs() << "total " << format(fmt.str().c_str(), total) << "\n"; } @@ -194,14 +188,11 @@ static void PrintDarwinSectionSizes(MachOObjectFile *MachO) { /// This is when used when @c OutputFormat is berkeley with a Mach-O file and /// produces the same output as darwin's size(1) default output. static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) { - uint32_t LoadCommandCount = MachO->getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = MachO->getFirstLoadCommandInfo(); - uint64_t total_text = 0; uint64_t total_data = 0; uint64_t total_objc = 0; uint64_t total_others = 0; - for (unsigned I = 0;; ++I) { + for (const auto &Load : MachO->load_commands()) { if (Load.C.cmd == MachO::LC_SEGMENT_64) { MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Load); if (MachO->getHeader().filetype == MachO::MH_OBJECT) { @@ -255,10 +246,6 @@ static void PrintDarwinSegmentSizes(MachOObjectFile *MachO) { total_others += Seg.vmsize; } } - if (I == LoadCommandCount - 1) - break; - else - Load = MachO->getNextLoadCommandInfo(Load); } uint64_t total = total_text + total_data + total_objc + total_others; diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index afb7cc81c824..b8fa83839cf7 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -113,9 +113,11 @@ void ModuleInfo::addSymbol(const SymbolRef &Symbol, DataExtractor *OpdExtractor, // occupies the memory range up to the following symbol. if (isa<MachOObjectFile>(Module)) SymbolSize = 0; - else if (error(Symbol.getSize(SymbolSize)) || - SymbolSize == UnknownAddressOrSize) - return; + else { + SymbolSize = Symbol.getSize(); + if (SymbolSize == UnknownAddressOrSize) + return; + } StringRef SymbolName; if (error(Symbol.getName(SymbolName))) return; diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt index 87f42e87cb41..c479fa954cb0 100644 --- a/tools/lto/CMakeLists.txt +++ b/tools/lto/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS MC MCDisassembler Support + Target ) set(SOURCES diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index d6ceebed728f..e55708c70f89 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -73,7 +73,22 @@ static void lto_initialize() { } } -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOCodeGenerator, lto_code_gen_t) +namespace { + +// This derived class owns the native object file. This helps implement the +// libLTO API semantics, which require that the code generator owns the object +// file. +struct LibLTOCodeGenerator : LTOCodeGenerator { + LibLTOCodeGenerator() {} + LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context) + : LTOCodeGenerator(std::move(Context)) {} + + std::unique_ptr<MemoryBuffer> NativeObjectFile; +}; + +} + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t) // Convert the subtarget features into a string to pass to LTOCodeGenerator. @@ -235,11 +250,10 @@ static lto_code_gen_t createCodeGen(bool InLocalContext) { TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); - LTOCodeGenerator *CodeGen = - InLocalContext ? new LTOCodeGenerator(make_unique<LLVMContext>()) - : new LTOCodeGenerator(); - if (CodeGen) - CodeGen->setTargetOptions(Options); + LibLTOCodeGenerator *CodeGen = + InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>()) + : new LibLTOCodeGenerator(); + CodeGen->setTargetOptions(Options); return wrap(CodeGen); } @@ -304,9 +318,13 @@ bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { maybeParseOptions(cg); - return unwrap(cg)->compile(length, DisableInline, - DisableGVNLoadPRE, DisableLTOVectorization, - sLastErrorString); + LibLTOCodeGenerator *CG = unwrap(cg); + CG->NativeObjectFile = CG->compile(DisableInline, DisableGVNLoadPRE, + DisableLTOVectorization, sLastErrorString); + if (!CG->NativeObjectFile) + return nullptr; + *length = CG->NativeObjectFile->getBufferSize(); + return CG->NativeObjectFile->getBufferStart(); } bool lto_codegen_optimize(lto_code_gen_t cg) { @@ -318,7 +336,12 @@ bool lto_codegen_optimize(lto_code_gen_t cg) { const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) { maybeParseOptions(cg); - return unwrap(cg)->compileOptimized(length, sLastErrorString); + LibLTOCodeGenerator *CG = unwrap(cg); + CG->NativeObjectFile = CG->compileOptimized(sLastErrorString); + if (!CG->NativeObjectFile) + return nullptr; + *length = CG->NativeObjectFile->getBufferSize(); + return CG->NativeObjectFile->getBufferStart(); } bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index 604f93adfbbf..39c2860df355 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -340,7 +340,7 @@ DumpDylibID(const MachOObjectFile &Obj, } static int DumpLoadCommand(const MachOObjectFile &Obj, - MachOObjectFile::LoadCommandInfo &LCI) { + const MachOObjectFile::LoadCommandInfo &LCI) { switch (LCI.C.cmd) { case MachO::LC_SEGMENT: return DumpSegmentCommand(Obj, LCI); @@ -369,9 +369,8 @@ static int DumpLoadCommand(const MachOObjectFile &Obj, } } - static int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index, - MachOObjectFile::LoadCommandInfo &LCI) { + const MachOObjectFile::LoadCommandInfo &LCI) { outs() << " # Load Command " << Index << "\n" << " (('command', " << LCI.C.cmd << ")\n" << " ('size', " << LCI.C.cmdsize << ")\n"; @@ -423,16 +422,11 @@ int main(int argc, char **argv) { // Print the load commands. int Res = 0; - MachOObjectFile::LoadCommandInfo Command = - InputObject->getFirstLoadCommandInfo(); + unsigned Index = 0; outs() << "('load_commands', [\n"; - for (unsigned i = 0; ; ++i) { - if (DumpLoadCommand(*InputObject, i, Command)) - break; - - if (i == Header->ncmds - 1) + for (const auto &Load : InputObject->load_commands()) { + if (DumpLoadCommand(*InputObject, Index++, Load)) break; - Command = InputObject->getNextLoadCommandInfo(Command); } outs() << "])\n"; diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp index 5baa644557cd..1e29107029ed 100644 --- a/tools/obj2yaml/coff2yaml.cpp +++ b/tools/obj2yaml/coff2yaml.cpp @@ -271,5 +271,5 @@ std::error_code coff2yaml(raw_ostream &Out, const object::COFFObjectFile &Obj) { yaml::Output Yout(Out); Yout << Dumper.getYAMLObj(); - return object::object_error::success; + return std::error_code(); } diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index 8ce70bc3652a..eeabb0f130c3 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -367,7 +367,7 @@ static std::error_code elf2yaml(raw_ostream &Out, yaml::Output Yout(Out); Yout << *YAML; - return object::object_error::success; + return std::error_code(); } std::error_code elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 338658805638..772b5b918eca 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -552,10 +552,10 @@ int yaml2elf(yaml::Input &YIn, raw_ostream &Out) { return 1; } using object::ELFType; - typedef ELFType<support::little, 8, true> LE64; - typedef ELFType<support::big, 8, true> BE64; - typedef ELFType<support::little, 4, false> LE32; - typedef ELFType<support::big, 4, false> BE32; + typedef ELFType<support::little, true> LE64; + typedef ELFType<support::big, true> BE64; + typedef ELFType<support::little, false> LE32; + typedef ELFType<support::big, false> BE32; if (is64Bit(Doc)) { if (isLittleEndian(Doc)) return ELFState<LE64>::writeELF(Out, Doc); |