aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile3
-rw-r--r--tools/bugpoint/CrashDebugger.cpp3
-rw-r--r--tools/bugpoint/Miscompilation.cpp12
-rw-r--r--tools/dsymutil/CMakeLists.txt1
-rw-r--r--tools/dsymutil/DebugMap.cpp161
-rw-r--r--tools/dsymutil/DebugMap.h86
-rw-r--r--tools/dsymutil/DwarfLinker.cpp304
-rw-r--r--tools/dsymutil/MachODebugMapParser.cpp14
-rw-r--r--tools/dsymutil/dsymutil.cpp44
-rw-r--r--tools/dsymutil/dsymutil.h7
-rw-r--r--tools/llc/CMakeLists.txt2
-rw-r--r--tools/llc/LLVMBuild.txt2
-rw-r--r--tools/llc/Makefile2
-rw-r--r--tools/llc/llc.cpp8
-rw-r--r--tools/lli/CMakeLists.txt1
-rw-r--r--tools/lli/OrcLazyJIT.cpp7
-rw-r--r--tools/lli/OrcLazyJIT.h3
-rw-r--r--tools/lli/lli.cpp26
-rw-r--r--tools/llvm-ar/llvm-ar.cpp332
-rw-r--r--tools/llvm-cov/CodeCoverage.cpp3
-rw-r--r--tools/llvm-cov/llvm-cov.cpp8
-rw-r--r--tools/llvm-cxxdump/llvm-cxxdump.cpp5
-rw-r--r--tools/llvm-dwarfdump/CMakeLists.txt4
-rw-r--r--tools/llvm-dwarfdump/fuzzer/CMakeLists.txt14
-rw-r--r--tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp34
-rw-r--r--tools/llvm-lto/CMakeLists.txt1
-rw-r--r--tools/llvm-lto/llvm-lto.cpp8
-rw-r--r--tools/llvm-mc/llvm-mc.cpp26
-rw-r--r--tools/llvm-nm/llvm-nm.cpp3
-rw-r--r--tools/llvm-objdump/COFFDump.cpp8
-rw-r--r--tools/llvm-objdump/MachODump.cpp103
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp547
-rw-r--r--tools/llvm-objdump/llvm-objdump.h2
-rw-r--r--tools/llvm-pdbdump/LinePrinter.h2
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp2
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp44
-rw-r--r--tools/llvm-readobj/Win64EHDumper.cpp2
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp75
-rw-r--r--tools/llvm-size/llvm-size.cpp17
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp8
-rw-r--r--tools/lto/CMakeLists.txt1
-rw-r--r--tools/lto/lto.cpp43
-rw-r--r--tools/macho-dump/macho-dump.cpp16
-rw-r--r--tools/obj2yaml/coff2yaml.cpp2
-rw-r--r--tools/obj2yaml/elf2yaml.cpp2
-rw-r--r--tools/yaml2obj/yaml2elf.cpp8
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);