mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[dsymutil, llvm-objcopy] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).
llvm-svn: 317123
This commit is contained in:
parent
60862bee82
commit
0d3ac016c2
@ -6,16 +6,34 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DebugMap.h"
|
||||
#include "BinaryHolder.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Chrono.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace dsymutil {
|
||||
|
||||
using namespace llvm::object;
|
||||
@ -39,7 +57,7 @@ void DebugMapObject::print(raw_ostream &OS) const {
|
||||
OS << getObjectFilename() << ":\n";
|
||||
// Sort the symbols in alphabetical order, like llvm-nm (and to get
|
||||
// deterministic output for testing).
|
||||
typedef std::pair<StringRef, SymbolMapping> Entry;
|
||||
using Entry = std::pair<StringRef, SymbolMapping>;
|
||||
std::vector<Entry> Entries;
|
||||
Entries.reserve(Symbols.getNumItems());
|
||||
for (const auto &Sym : make_range(Symbols.begin(), Symbols.end()))
|
||||
@ -97,11 +115,13 @@ void DebugMap::dump() const { print(errs()); }
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
struct YAMLContext {
|
||||
StringRef PrependPath;
|
||||
Triple BinaryTriple;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||
DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
|
||||
@ -124,7 +144,8 @@ DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
|
||||
Result.push_back(std::move(Res));
|
||||
return std::move(Result);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace dsymutil
|
||||
|
||||
namespace yaml {
|
||||
|
||||
@ -155,8 +176,7 @@ void MappingTraits<dsymutil::DebugMapObject>::mapping(
|
||||
io.mapRequired("symbols", Norm->Entries);
|
||||
}
|
||||
|
||||
void ScalarTraits<Triple>::output(const Triple &val, void *,
|
||||
llvm::raw_ostream &out) {
|
||||
void ScalarTraits<Triple>::output(const Triple &val, void *, raw_ostream &out) {
|
||||
out << val.str();
|
||||
}
|
||||
|
||||
@ -221,8 +241,7 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
|
||||
sys::path::append(Path, Filename);
|
||||
auto ErrOrObjectFiles = BinHolder.GetObjectFiles(Path);
|
||||
if (auto EC = ErrOrObjectFiles.getError()) {
|
||||
llvm::errs() << "warning: Unable to open " << Path << " " << EC.message()
|
||||
<< '\n';
|
||||
errs() << "warning: Unable to open " << Path << " " << EC.message() << '\n';
|
||||
} else if (auto ErrOrObjectFile = BinHolder.Get(Ctxt.BinaryTriple)) {
|
||||
// Rewrite the object file symbol addresses in the debug map. The
|
||||
// YAML input is mainly used to test llvm-dsymutil without
|
||||
@ -256,5 +275,7 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace yaml
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -1,4 +1,4 @@
|
||||
//=== tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-//
|
||||
//=- tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@ -6,7 +6,7 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
//
|
||||
/// \file
|
||||
///
|
||||
/// This file contains the class declaration of the DebugMap
|
||||
@ -16,27 +16,35 @@
|
||||
/// The DebugMap is an input to the DwarfLinker class that will
|
||||
/// extract the Dwarf debug information from the referenced object
|
||||
/// files and link their usefull debug info together.
|
||||
///
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
||||
#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Chrono.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class raw_ostream;
|
||||
|
||||
namespace dsymutil {
|
||||
|
||||
class DebugMapObject;
|
||||
|
||||
/// \brief The DebugMap object stores the list of object files to
|
||||
@ -67,20 +75,24 @@ class DebugMapObject;
|
||||
class DebugMap {
|
||||
Triple BinaryTriple;
|
||||
std::string BinaryPath;
|
||||
typedef std::vector<std::unique_ptr<DebugMapObject>> ObjectContainer;
|
||||
|
||||
using ObjectContainer = std::vector<std::unique_ptr<DebugMapObject>>;
|
||||
|
||||
ObjectContainer Objects;
|
||||
|
||||
/// For YAML IO support.
|
||||
///@{
|
||||
friend yaml::MappingTraits<std::unique_ptr<DebugMap>>;
|
||||
friend yaml::MappingTraits<DebugMap>;
|
||||
|
||||
DebugMap() = default;
|
||||
///@}
|
||||
|
||||
public:
|
||||
DebugMap(const Triple &BinaryTriple, StringRef BinaryPath)
|
||||
: BinaryTriple(BinaryTriple), BinaryPath(BinaryPath) {}
|
||||
|
||||
typedef ObjectContainer::const_iterator const_iterator;
|
||||
using const_iterator = ObjectContainer::const_iterator;
|
||||
|
||||
iterator_range<const_iterator> objects() const {
|
||||
return make_range(begin(), end());
|
||||
@ -122,23 +134,25 @@ public:
|
||||
Optional<yaml::Hex64> ObjectAddress;
|
||||
yaml::Hex64 BinaryAddress;
|
||||
yaml::Hex32 Size;
|
||||
|
||||
SymbolMapping(Optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
|
||||
uint32_t Size)
|
||||
: BinaryAddress(BinaryAddress), Size(Size) {
|
||||
if (ObjectAddr)
|
||||
ObjectAddress = *ObjectAddr;
|
||||
}
|
||||
|
||||
/// For YAML IO support
|
||||
SymbolMapping() = default;
|
||||
};
|
||||
|
||||
typedef std::pair<std::string, SymbolMapping> YAMLSymbolMapping;
|
||||
typedef StringMapEntry<SymbolMapping> DebugMapEntry;
|
||||
using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
|
||||
using DebugMapEntry = StringMapEntry<SymbolMapping>;
|
||||
|
||||
/// \brief Adds a symbol mapping to this DebugMapObject.
|
||||
/// \returns false if the symbol was already registered. The request
|
||||
/// is discarded in this case.
|
||||
bool addSymbol(llvm::StringRef SymName, Optional<uint64_t> ObjectAddress,
|
||||
bool addSymbol(StringRef SymName, Optional<uint64_t> ObjectAddress,
|
||||
uint64_t LinkedAddress, uint32_t Size);
|
||||
|
||||
/// \brief Lookup a symbol mapping.
|
||||
@ -149,7 +163,7 @@ public:
|
||||
/// \returns null if the address isn't found.
|
||||
const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
|
||||
|
||||
llvm::StringRef getObjectFilename() const { return Filename; }
|
||||
StringRef getObjectFilename() const { return Filename; }
|
||||
|
||||
sys::TimePoint<std::chrono::seconds> getTimestamp() const {
|
||||
return Timestamp;
|
||||
@ -165,8 +179,10 @@ public:
|
||||
#ifndef NDEBUG
|
||||
void dump() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class DebugMap;
|
||||
|
||||
/// DebugMapObjects can only be constructed by the owning DebugMap.
|
||||
DebugMapObject(StringRef ObjectFilename,
|
||||
sys::TimePoint<std::chrono::seconds> Timestamp, uint8_t Type);
|
||||
@ -181,6 +197,7 @@ private:
|
||||
///@{
|
||||
friend yaml::MappingTraits<dsymutil::DebugMapObject>;
|
||||
friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
|
||||
|
||||
DebugMapObject() = default;
|
||||
|
||||
public:
|
||||
@ -188,8 +205,10 @@ public:
|
||||
DebugMapObject &operator=(DebugMapObject &&) = default;
|
||||
///@}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace dsymutil
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
|
||||
|
||||
@ -211,7 +230,7 @@ template <> struct MappingTraits<dsymutil::DebugMapObject> {
|
||||
};
|
||||
|
||||
template <> struct ScalarTraits<Triple> {
|
||||
static void output(const Triple &val, void *, llvm::raw_ostream &out);
|
||||
static void output(const Triple &val, void *, raw_ostream &out);
|
||||
static StringRef input(StringRef scalar, void *, Triple &value);
|
||||
static bool mustQuote(StringRef) { return true; }
|
||||
};
|
||||
@ -232,7 +251,8 @@ template <> struct MappingTraits<dsymutil::DebugMap> {
|
||||
template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
|
||||
static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace yaml
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
|
||||
|
@ -6,21 +6,43 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "BinaryHolder.h"
|
||||
#include "DebugMap.h"
|
||||
#include "MachOUtils.h"
|
||||
#include "NonRelocatableStringpool.h"
|
||||
#include "dsymutil.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/IntervalMap.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
@ -29,18 +51,47 @@
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCObjectFileInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCTargetOptions.h"
|
||||
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace dsymutil {
|
||||
@ -52,7 +103,7 @@ using HalfOpenIntervalMap =
|
||||
IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
|
||||
IntervalMapHalfOpenInfo<KeyT>>;
|
||||
|
||||
typedef HalfOpenIntervalMap<uint64_t, int64_t> FunctionIntervals;
|
||||
using FunctionIntervals = HalfOpenIntervalMap<uint64_t, int64_t>;
|
||||
|
||||
// FIXME: Delete this structure.
|
||||
struct PatchLocation {
|
||||
@ -95,6 +146,8 @@ struct DeclMapInfo;
|
||||
/// specific DeclContext using a separate DenseMap keyed on the hash
|
||||
/// of the fully qualified name of the context.
|
||||
class DeclContext {
|
||||
friend DeclMapInfo;
|
||||
|
||||
unsigned QualifiedNameHash = 0;
|
||||
uint32_t Line = 0;
|
||||
uint32_t ByteSize = 0;
|
||||
@ -107,10 +160,8 @@ class DeclContext {
|
||||
uint32_t LastSeenCompileUnitID = 0;
|
||||
uint32_t CanonicalDIEOffset = 0;
|
||||
|
||||
friend DeclMapInfo;
|
||||
|
||||
public:
|
||||
typedef DenseSet<DeclContext *, DeclMapInfo> Map;
|
||||
using Map = DenseSet<DeclContext *, DeclMapInfo>;
|
||||
|
||||
DeclContext() : DefinedInClangModule(0), Parent(*this) {}
|
||||
|
||||
@ -186,20 +237,35 @@ class CompileUnit {
|
||||
public:
|
||||
/// Information gathered about a DIE in the object file.
|
||||
struct DIEInfo {
|
||||
int64_t AddrAdjust; ///< Address offset to apply to the described entity.
|
||||
DeclContext *Ctxt; ///< ODR Declaration context.
|
||||
DIE *Clone; ///< Cloned version of that DIE.
|
||||
uint32_t ParentIdx; ///< The index of this DIE's parent.
|
||||
bool Keep : 1; ///< Is the DIE part of the linked output?
|
||||
bool InDebugMap : 1; ///< Was this DIE's entity found in the map?
|
||||
bool Prune : 1; ///< Is this a pure forward declaration we can strip?
|
||||
bool Incomplete : 1; ///< Does DIE transitively refer an incomplete decl?
|
||||
/// Address offset to apply to the described entity.
|
||||
int64_t AddrAdjust;
|
||||
|
||||
/// ODR Declaration context.
|
||||
DeclContext *Ctxt;
|
||||
|
||||
/// Cloned version of that DIE.
|
||||
DIE *Clone;
|
||||
|
||||
/// The index of this DIE's parent.
|
||||
uint32_t ParentIdx;
|
||||
|
||||
/// Is the DIE part of the linked output?
|
||||
bool Keep : 1;
|
||||
|
||||
/// Was this DIE's entity found in the map?
|
||||
bool InDebugMap : 1;
|
||||
|
||||
/// Is this a pure forward declaration we can strip?
|
||||
bool Prune : 1;
|
||||
|
||||
/// Does DIE transitively refer an incomplete decl?
|
||||
bool Incomplete : 1;
|
||||
};
|
||||
|
||||
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
|
||||
StringRef ClangModuleName)
|
||||
: OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
|
||||
Ranges(RangeAlloc), ClangModuleName(ClangModuleName) {
|
||||
: OrigUnit(OrigUnit), ID(ID), Ranges(RangeAlloc),
|
||||
ClangModuleName(ClangModuleName) {
|
||||
Info.resize(OrigUnit.getNumDIEs());
|
||||
|
||||
auto CUDie = OrigUnit.getUnitDIE(false);
|
||||
@ -245,7 +311,9 @@ public:
|
||||
Optional<PatchLocation> getUnitRangesAttribute() const {
|
||||
return UnitRangeAttribute;
|
||||
}
|
||||
|
||||
const FunctionIntervals &getFunctionRanges() const { return Ranges; }
|
||||
|
||||
const std::vector<PatchLocation> &getRangesAttributes() const {
|
||||
return RangeAttributes;
|
||||
}
|
||||
@ -337,8 +405,8 @@ private:
|
||||
uint64_t StartOffset;
|
||||
uint64_t NextUnitOffset;
|
||||
|
||||
uint64_t LowPc;
|
||||
uint64_t HighPc;
|
||||
uint64_t LowPc = std::numeric_limits<uint64_t>::max();
|
||||
uint64_t HighPc = 0;
|
||||
|
||||
/// A list of attributes to fixup with the absolute offset of
|
||||
/// a DIE in the debug_info section.
|
||||
@ -350,6 +418,7 @@ private:
|
||||
PatchLocation>> ForwardDIEReferences;
|
||||
|
||||
FunctionIntervals::Allocator RangeAlloc;
|
||||
|
||||
/// The ranges in that interval map are the PC ranges for
|
||||
/// functions in this unit, associated with the PC offset to apply
|
||||
/// to the addresses to get the linked address.
|
||||
@ -383,12 +452,16 @@ private:
|
||||
|
||||
/// Is this unit subject to the ODR rule?
|
||||
bool HasODR;
|
||||
|
||||
/// Did a DIE actually contain a valid reloc?
|
||||
bool HasInterestingContent;
|
||||
|
||||
/// If this is a Clang module, this holds the module's name.
|
||||
std::string ClangModuleName;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
void CompileUnit::markEverythingAsKept() {
|
||||
for (auto &I : Info)
|
||||
// Mark everything that wasn't explicity marked for pruning.
|
||||
@ -459,6 +532,8 @@ void CompileUnit::addTypeAccelerator(const DIE *Die, const char *Name,
|
||||
Pubtypes.emplace_back(Name, Die, Offset, false);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// The Dwarf streaming logic
|
||||
///
|
||||
/// All interactions with the MC layer that is used to build the debug
|
||||
@ -573,6 +648,8 @@ public:
|
||||
uint32_t getFrameSectionSize() const { return FrameSectionSize; }
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
|
||||
std::string ErrorStr;
|
||||
std::string TripleName;
|
||||
@ -919,7 +996,8 @@ void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
|
||||
if (Rows.empty()) {
|
||||
// We only have the dummy entry, dsymutil emits an entry with a 0
|
||||
// address in that case.
|
||||
MCDwarfLineAddr::Encode(*MC, Params, INT64_MAX, 0, EncodingOS);
|
||||
MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
|
||||
EncodingOS);
|
||||
MS->EmitBytes(EncodingOS.str());
|
||||
LineSectionSize += EncodingBuffer.size();
|
||||
MS->EmitLabel(LineEndSym);
|
||||
@ -1019,7 +1097,8 @@ void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
|
||||
MS->EmitULEB128IntValue(AddressDelta);
|
||||
LineSectionSize += 1 + getULEB128Size(AddressDelta);
|
||||
}
|
||||
MCDwarfLineAddr::Encode(*MC, Params, INT64_MAX, 0, EncodingOS);
|
||||
MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(),
|
||||
0, EncodingOS);
|
||||
MS->EmitBytes(EncodingOS.str());
|
||||
LineSectionSize += EncodingBuffer.size();
|
||||
EncodingBuffer.resize(0);
|
||||
@ -1030,7 +1109,8 @@ void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
|
||||
}
|
||||
|
||||
if (RowsSinceLastSequence) {
|
||||
MCDwarfLineAddr::Encode(*MC, Params, INT64_MAX, 0, EncodingOS);
|
||||
MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
|
||||
EncodingOS);
|
||||
MS->EmitBytes(EncodingOS.str());
|
||||
LineSectionSize += EncodingBuffer.size();
|
||||
EncodingBuffer.resize(0);
|
||||
@ -1112,6 +1192,8 @@ void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
|
||||
FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// The core of the Dwarf linking logic.
|
||||
///
|
||||
/// The link of the dwarf information from the object files will be
|
||||
@ -1179,13 +1261,13 @@ private:
|
||||
/// ValidRelocs is sorted by file offset, keeping this index
|
||||
/// uptodate is all we have to do to have a cheap lookup during the
|
||||
/// root DIE selection and during DIE cloning.
|
||||
unsigned NextValidReloc;
|
||||
unsigned NextValidReloc = 0;
|
||||
|
||||
public:
|
||||
RelocationManager(DwarfLinker &Linker)
|
||||
: Linker(Linker), NextValidReloc(0) {}
|
||||
RelocationManager(DwarfLinker &Linker) : Linker(Linker) {}
|
||||
|
||||
bool hasValidRelocs() const { return !ValidRelocs.empty(); }
|
||||
|
||||
/// Reset the NextValidReloc counter.
|
||||
void resetValidRelocs() { NextValidReloc = 0; }
|
||||
|
||||
@ -1284,8 +1366,10 @@ private:
|
||||
class DIECloner {
|
||||
DwarfLinker &Linker;
|
||||
RelocationManager &RelocMgr;
|
||||
|
||||
/// Allocator used for all the DIEValue objects.
|
||||
BumpPtrAllocator &DIEAlloc;
|
||||
|
||||
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
|
||||
LinkOptions Options;
|
||||
|
||||
@ -1318,25 +1402,35 @@ private:
|
||||
void cloneAllCompileUnits(DWARFContext &DwarfContext);
|
||||
|
||||
private:
|
||||
typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec;
|
||||
using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
|
||||
|
||||
/// Information gathered and exchanged between the various
|
||||
/// clone*Attributes helpers about the attributes of a particular DIE.
|
||||
struct AttributesInfo {
|
||||
const char *Name, *MangledName; ///< Names.
|
||||
uint32_t NameOffset, MangledNameOffset; ///< Offsets in the string pool.
|
||||
/// Names.
|
||||
const char *Name = nullptr;
|
||||
const char *MangledName = nullptr;
|
||||
|
||||
uint64_t OrigLowPc; ///< Value of AT_low_pc in the input DIE
|
||||
uint64_t OrigHighPc; ///< Value of AT_high_pc in the input DIE
|
||||
int64_t PCOffset; ///< Offset to apply to PC addresses inside a function.
|
||||
/// Offsets in the string pool.
|
||||
uint32_t NameOffset = 0;
|
||||
uint32_t MangledNameOffset = 0;
|
||||
|
||||
bool HasLowPc; ///< Does the DIE have a low_pc attribute?
|
||||
bool IsDeclaration; ///< Is this DIE only a declaration?
|
||||
/// Value of AT_low_pc in the input DIE
|
||||
uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
AttributesInfo()
|
||||
: Name(nullptr), MangledName(nullptr), NameOffset(0),
|
||||
MangledNameOffset(0), OrigLowPc(UINT64_MAX), OrigHighPc(0),
|
||||
PCOffset(0), HasLowPc(false), IsDeclaration(false) {}
|
||||
/// Value of AT_high_pc in the input DIE
|
||||
uint64_t OrigHighPc = 0;
|
||||
|
||||
/// Offset to apply to PC addresses inside a function.
|
||||
int64_t PCOffset = 0;
|
||||
|
||||
/// Does the DIE have a low_pc attribute?
|
||||
bool HasLowPc = false;
|
||||
|
||||
/// Is this DIE only a declaration?
|
||||
bool IsDeclaration = false;
|
||||
|
||||
AttributesInfo() = default;
|
||||
};
|
||||
|
||||
/// Helper for cloneDIE.
|
||||
@ -1397,13 +1491,6 @@ private:
|
||||
/// Assign an abbreviation number to \p Abbrev
|
||||
void AssignAbbrev(DIEAbbrev &Abbrev);
|
||||
|
||||
/// FoldingSet that uniques the abbreviations.
|
||||
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
||||
/// Storage for the unique Abbreviations.
|
||||
/// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot
|
||||
/// be changed to a vecot of unique_ptrs.
|
||||
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
|
||||
|
||||
/// Compute and emit debug_ranges section for \p Unit, and
|
||||
/// patch the attributes referencing it.
|
||||
void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf) const;
|
||||
@ -1424,10 +1511,20 @@ private:
|
||||
void patchFrameInfoForObject(const DebugMapObject &, DWARFContext &,
|
||||
unsigned AddressSize);
|
||||
|
||||
/// FoldingSet that uniques the abbreviations.
|
||||
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
||||
|
||||
/// Storage for the unique Abbreviations.
|
||||
/// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot
|
||||
/// be changed to a vecot of unique_ptrs.
|
||||
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
|
||||
|
||||
/// DIELoc objects that need to be destructed (but not freed!).
|
||||
std::vector<DIELoc *> DIELocs;
|
||||
|
||||
/// DIEBlock objects that need to be destructed (but not freed!).
|
||||
std::vector<DIEBlock *> DIEBlocks;
|
||||
|
||||
/// Allocator used for all the DIEValue objects.
|
||||
BumpPtrAllocator DIEAlloc;
|
||||
/// @}
|
||||
@ -1451,13 +1548,15 @@ private:
|
||||
BinaryHolder BinHolder;
|
||||
std::unique_ptr<DwarfStreamer> Streamer;
|
||||
uint64_t OutputDebugInfoSize;
|
||||
unsigned UnitID; ///< A unique ID that identifies each compile unit.
|
||||
|
||||
/// A unique ID that identifies each compile unit.
|
||||
unsigned UnitID;
|
||||
|
||||
unsigned MaxDwarfVersion = 0;
|
||||
|
||||
/// The units of the current debug map object.
|
||||
std::vector<std::unique_ptr<CompileUnit>> Units;
|
||||
|
||||
|
||||
/// The debug map object currently under consideration.
|
||||
DebugMapObject *CurrentDebugObject;
|
||||
|
||||
@ -1489,6 +1588,8 @@ private:
|
||||
bool ArchiveHintDisplayed = false;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Similar to DWARFUnitSection::getUnitForOffset(), but returning our
|
||||
/// CompileUnit object instead.
|
||||
static CompileUnit *getUnitForOffset(
|
||||
@ -1633,7 +1734,7 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
|
||||
return PointerIntPair<DeclContext *, 1>(nullptr);
|
||||
|
||||
unsigned Line = 0;
|
||||
unsigned ByteSize = UINT32_MAX;
|
||||
unsigned ByteSize = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
if (!InClangModule) {
|
||||
// Gather some discriminating data about the DeclContext we will be
|
||||
@ -1643,7 +1744,8 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
|
||||
// namespaces, use these additional data points to make the process
|
||||
// safer. This is disabled for clang modules, because forward
|
||||
// declarations of module-defined types do not have a file and line.
|
||||
ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), UINT64_MAX);
|
||||
ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size),
|
||||
std::numeric_limits<uint64_t>::max());
|
||||
if (Tag != dwarf::DW_TAG_namespace || !Name) {
|
||||
if (unsigned FileNum = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) {
|
||||
if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
|
||||
@ -2063,8 +2165,9 @@ hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
|
||||
const auto &ValidReloc = ValidRelocs[NextValidReloc++];
|
||||
const auto &Mapping = ValidReloc.Mapping->getValue();
|
||||
uint64_t ObjectAddress =
|
||||
Mapping.ObjectAddress ? uint64_t(*Mapping.ObjectAddress) : UINT64_MAX;
|
||||
uint64_t ObjectAddress = Mapping.ObjectAddress
|
||||
? uint64_t(*Mapping.ObjectAddress)
|
||||
: std::numeric_limits<uint64_t>::max();
|
||||
if (Linker.Options.Verbose)
|
||||
outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
|
||||
<< " " << format("\t%016" PRIx64 " => %016" PRIx64, ObjectAddress,
|
||||
@ -2539,11 +2642,13 @@ unsigned DwarfLinker::DIECloner::cloneAddressAttribute(
|
||||
// relocated because it happens to match the low_pc of the
|
||||
// enclosing subprogram. To prevent issues with that, always use
|
||||
// the low_pc from the input DIE if relocations have been applied.
|
||||
Addr = (Info.OrigLowPc != UINT64_MAX ? Info.OrigLowPc : Addr) +
|
||||
Addr = (Info.OrigLowPc != std::numeric_limits<uint64_t>::max()
|
||||
? Info.OrigLowPc
|
||||
: Addr) +
|
||||
Info.PCOffset;
|
||||
else if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
|
||||
Addr = Unit.getLowPc();
|
||||
if (Addr == UINT64_MAX)
|
||||
if (Addr == std::numeric_limits<uint64_t>::max())
|
||||
return 0;
|
||||
}
|
||||
Info.HasLowPc = true;
|
||||
@ -2820,8 +2925,8 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
|
||||
// Also store the low_pc. It might get relocated in an
|
||||
// inline_subprogram that happens at the beginning of its
|
||||
// inlining function.
|
||||
AttrInfo.OrigLowPc =
|
||||
dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), UINT64_MAX);
|
||||
AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc),
|
||||
std::numeric_limits<uint64_t>::max());
|
||||
}
|
||||
|
||||
// Reset the Offset to 0 as we will be working on the local copy of
|
||||
@ -3479,7 +3584,6 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits(DWARFContext &DwarfContext) {
|
||||
}
|
||||
|
||||
bool DwarfLinker::link(const DebugMap &Map) {
|
||||
|
||||
if (!createStreamer(Map.getTriple(), OutputFilename))
|
||||
return false;
|
||||
|
||||
@ -3594,7 +3698,6 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
|
||||
return Options.NoOutput ? true : Streamer->finish(Map);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the offset of string \p S in the string table. This
|
||||
/// can insert a new element or return the offset of a preexisitng
|
||||
@ -3646,5 +3749,6 @@ bool linkDwarf(StringRef OutputFilename, const DebugMap &DM,
|
||||
DwarfLinker Linker(OutputFilename, Options);
|
||||
return Linker.link(DM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace dsymutil
|
||||
} // end namespace llvm
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- NonRelocatableStringpool.h - A simple stringpool -----------------===//
|
||||
//===- NonRelocatableStringpool.h - A simple stringpool --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,10 +6,15 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_DSYMUTIL_NONRELOCATABLESTRINGPOOL_H
|
||||
#define LLVM_TOOLS_DSYMUTIL_NONRELOCATABLESTRINGPOOL_H
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
namespace dsymutil {
|
||||
@ -25,11 +30,10 @@ public:
|
||||
/// \brief Entries are stored into the StringMap and simply linked
|
||||
/// together through the second element of this pair in order to
|
||||
/// keep track of insertion order.
|
||||
typedef StringMap<std::pair<uint32_t, StringMapEntryBase *>, BumpPtrAllocator>
|
||||
MapTy;
|
||||
using MapTy =
|
||||
StringMap<std::pair<uint32_t, StringMapEntryBase *>, BumpPtrAllocator>;
|
||||
|
||||
NonRelocatableStringpool()
|
||||
: CurrentEndOffset(0), Sentinel(0), Last(&Sentinel) {
|
||||
NonRelocatableStringpool() : Sentinel(0), Last(&Sentinel) {
|
||||
// Legacy dsymutil puts an empty string at the start of the line
|
||||
// table.
|
||||
getStringOffset("");
|
||||
@ -61,10 +65,11 @@ public:
|
||||
|
||||
private:
|
||||
MapTy Strings;
|
||||
uint32_t CurrentEndOffset;
|
||||
uint32_t CurrentEndOffset = 0;
|
||||
MapTy::MapEntryTy Sentinel, *Last;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
} // end namespace dsymutil
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_DSYMUTIL_NONRELOCATABLESTRINGPOOL_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- dsymutil.cpp - Debug info dumping utility for llvm ----------------===//
|
||||
//===- dsymutil.cpp - Debug info dumping utility for llvm -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -15,25 +15,31 @@
|
||||
#include "dsymutil.h"
|
||||
#include "DebugMap.h"
|
||||
#include "MachOUtils.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/FileUtilities.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/Options.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/ThreadPool.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/thread.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
using namespace llvm::cl;
|
||||
using namespace llvm::dsymutil;
|
||||
|
||||
namespace {
|
||||
using namespace llvm::cl;
|
||||
|
||||
OptionCategory DsymCategory("Specific Options");
|
||||
static OptionCategory DsymCategory("Specific Options");
|
||||
static opt<bool> Help("h", desc("Alias for -help"), Hidden);
|
||||
static opt<bool> Version("v", desc("Alias for -version"), Hidden);
|
||||
|
||||
@ -77,10 +83,12 @@ static opt<bool>
|
||||
NoOutput("no-output",
|
||||
desc("Do the link in memory, but do not emit the result file."),
|
||||
init(false), cat(DsymCategory));
|
||||
|
||||
static opt<bool>
|
||||
NoTimestamp("no-swiftmodule-timestamp",
|
||||
desc("Don't check timestamp for swiftmodule files."),
|
||||
init(false), cat(DsymCategory));
|
||||
|
||||
static list<std::string> ArchFlags(
|
||||
"arch",
|
||||
desc("Link DWARF debug information only for specified CPU architecture\n"
|
||||
@ -103,7 +111,6 @@ static opt<bool> DumpDebugMap(
|
||||
static opt<bool> InputIsYAMLDebugMap(
|
||||
"y", desc("Treat the input file is a YAML debug map rather than a binary."),
|
||||
init(false), cat(DsymCategory));
|
||||
}
|
||||
|
||||
static bool createPlistFile(llvm::StringRef BundleRoot) {
|
||||
if (NoOutput)
|
||||
|
@ -6,38 +6,52 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
//
|
||||
/// \file
|
||||
///
|
||||
/// This file contains the class declaration for the code that parses STABS
|
||||
/// debug maps that are embedded in the binaries symbol tables.
|
||||
///
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
|
||||
#define LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
|
||||
|
||||
#include "DebugMap.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace dsymutil {
|
||||
|
||||
struct LinkOptions {
|
||||
bool Verbose; ///< Verbosity
|
||||
bool NoOutput; ///< Skip emitting output
|
||||
bool NoODR; ///< Do not unique types according to ODR
|
||||
bool NoTimestamp; ///< Do not check swiftmodule timestamp
|
||||
std::string PrependPath; ///< -oso-prepend-path
|
||||
/// Verbosity
|
||||
bool Verbose = false;
|
||||
|
||||
LinkOptions() : Verbose(false), NoOutput(false), NoTimestamp(false) {}
|
||||
/// Skip emitting output
|
||||
bool NoOutput = false;
|
||||
|
||||
/// Do not unique types according to ODR
|
||||
bool NoODR;
|
||||
|
||||
/// Do not check swiftmodule timestamp
|
||||
bool NoTimestamp = false;
|
||||
|
||||
/// -oso-prepend-path
|
||||
std::string PrependPath;
|
||||
|
||||
LinkOptions() = default;
|
||||
};
|
||||
|
||||
/// \brief Extract the DebugMaps from the given file.
|
||||
/// The file has to be a MachO object file. Multiple debug maps can be
|
||||
/// returned when the file is universal (aka fat) binary.
|
||||
llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||
ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||
parseDebugMap(StringRef InputFile, ArrayRef<std::string> Archs,
|
||||
StringRef PrependPath, bool Verbose, bool InputIsYAML);
|
||||
|
||||
@ -57,6 +71,8 @@ LLVM_ATTRIBUTE_NORETURN void exitDsymutil(int ExitStatus);
|
||||
|
||||
void warn(const Twine &Warning, const Twine &Context);
|
||||
bool error(const Twine &Error, const Twine &Context);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace dsymutil
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- Object.cpp -----------------------------------------------*- C++ -*-===//
|
||||
//===- Object.cpp ---------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,16 +6,32 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Object.h"
|
||||
#include "llvm-objcopy.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace object;
|
||||
using namespace ELF;
|
||||
|
||||
template <class ELFT> void Segment::writeHeader(FileOutputBuffer &Out) const {
|
||||
typedef typename ELFT::Ehdr Elf_Ehdr;
|
||||
typedef typename ELFT::Phdr Elf_Phdr;
|
||||
using Elf_Ehdr = typename ELFT::Ehdr;
|
||||
using Elf_Phdr = typename ELFT::Phdr;
|
||||
|
||||
uint8_t *Buf = Out.getBufferStart();
|
||||
Buf += sizeof(Elf_Ehdr) + Index * sizeof(Elf_Phdr);
|
||||
@ -191,8 +207,7 @@ const Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTableSectionImpl<ELFT>::writeSection(
|
||||
llvm::FileOutputBuffer &Out) const {
|
||||
void SymbolTableSectionImpl<ELFT>::writeSection(FileOutputBuffer &Out) const {
|
||||
uint8_t *Buf = Out.getBufferStart();
|
||||
Buf += Offset;
|
||||
typename ELFT::Sym *Sym = reinterpret_cast<typename ELFT::Sym *>(Buf);
|
||||
@ -212,9 +227,10 @@ template <class SymTabType>
|
||||
void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
|
||||
const SectionBase *Sec) {
|
||||
if (Symbols == Sec) {
|
||||
error("Symbol table " + Symbols->Name + " cannot be removed because it is "
|
||||
"referenced by the relocation "
|
||||
"section " +
|
||||
error("Symbol table " + Symbols->Name +
|
||||
" cannot be removed because it is "
|
||||
"referenced by the relocation "
|
||||
"section " +
|
||||
this->Name);
|
||||
}
|
||||
}
|
||||
@ -229,9 +245,9 @@ void RelocSectionWithSymtabBase<SymTabType>::initialize(
|
||||
" is not a symbol table"));
|
||||
|
||||
if (Info != SHN_UNDEF)
|
||||
setSection(SecTable.getSection(Info,
|
||||
"Info field value " + Twine(Info) +
|
||||
" in section " + Name + " is invalid"));
|
||||
setSection(SecTable.getSection(Info, "Info field value " + Twine(Info) +
|
||||
" in section " + Name +
|
||||
" is invalid"));
|
||||
else
|
||||
setSection(nullptr);
|
||||
}
|
||||
@ -263,7 +279,7 @@ void RelocationSection<ELFT>::writeRel(T *Buf) const {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const {
|
||||
void RelocationSection<ELFT>::writeSection(FileOutputBuffer &Out) const {
|
||||
uint8_t *Buf = Out.getBufferStart() + Offset;
|
||||
if (Type == SHT_REL)
|
||||
writeRel(reinterpret_cast<Elf_Rel *>(Buf));
|
||||
@ -271,15 +287,16 @@ void RelocationSection<ELFT>::writeSection(llvm::FileOutputBuffer &Out) const {
|
||||
writeRel(reinterpret_cast<Elf_Rela *>(Buf));
|
||||
}
|
||||
|
||||
void DynamicRelocationSection::writeSection(llvm::FileOutputBuffer &Out) const {
|
||||
void DynamicRelocationSection::writeSection(FileOutputBuffer &Out) const {
|
||||
std::copy(std::begin(Contents), std::end(Contents),
|
||||
Out.getBufferStart() + Offset);
|
||||
}
|
||||
|
||||
void SectionWithStrTab::removeSectionReferences(const SectionBase *Sec) {
|
||||
if (StrTab == Sec) {
|
||||
error("String table " + StrTab->Name + " cannot be removed because it is "
|
||||
"referenced by the section " +
|
||||
error("String table " + StrTab->Name +
|
||||
" cannot be removed because it is "
|
||||
"referenced by the section " +
|
||||
this->Name);
|
||||
}
|
||||
}
|
||||
@ -289,9 +306,9 @@ bool SectionWithStrTab::classof(const SectionBase *S) {
|
||||
}
|
||||
|
||||
void SectionWithStrTab::initialize(SectionTableRef SecTable) {
|
||||
auto StrTab = SecTable.getSection(Link,
|
||||
"Link field value " + Twine(Link) +
|
||||
" in section " + Name + " is invalid");
|
||||
auto StrTab =
|
||||
SecTable.getSection(Link, "Link field value " + Twine(Link) +
|
||||
" in section " + Name + " is invalid");
|
||||
if (StrTab->Type != SHT_STRTAB) {
|
||||
error("Link field value " + Twine(Link) + " in section " + Name +
|
||||
" is not a string table");
|
||||
@ -377,10 +394,9 @@ void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
void Object<ELFT>::initSymbolTable(const object::ELFFile<ELFT> &ElfFile,
|
||||
SymbolTableSection *SymTab,
|
||||
SectionTableRef SecTable) {
|
||||
|
||||
const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));
|
||||
StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));
|
||||
|
||||
@ -397,9 +413,9 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
}
|
||||
} else if (Sym.st_shndx != SHN_UNDEF) {
|
||||
DefSection = SecTable.getSection(
|
||||
Sym.st_shndx,
|
||||
"Symbol '" + Name + "' is defined in invalid section with index " +
|
||||
Twine(Sym.st_shndx));
|
||||
Sym.st_shndx, "Symbol '" + Name +
|
||||
"' is defined in invalid section with index " +
|
||||
Twine(Sym.st_shndx));
|
||||
}
|
||||
|
||||
SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
|
||||
@ -437,14 +453,14 @@ SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) {
|
||||
template <class T>
|
||||
T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg,
|
||||
Twine TypeErrMsg) {
|
||||
if (T *Sec = llvm::dyn_cast<T>(getSection(Index, IndexErrMsg)))
|
||||
if (T *Sec = dyn_cast<T>(getSection(Index, IndexErrMsg)))
|
||||
return Sec;
|
||||
error(TypeErrMsg);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::unique_ptr<SectionBase>
|
||||
Object<ELFT>::makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
Object<ELFT>::makeSection(const object::ELFFile<ELFT> &ElfFile,
|
||||
const Elf_Shdr &Shdr) {
|
||||
ArrayRef<uint8_t> Data;
|
||||
switch (Shdr.sh_type) {
|
||||
@ -621,7 +637,7 @@ void Object<ELFT>::writeSectionHeaders(FileOutputBuffer &Out) const {
|
||||
template <class ELFT>
|
||||
void Object<ELFT>::writeSectionData(FileOutputBuffer &Out) const {
|
||||
for (auto &Section : Sections)
|
||||
Section->writeSection(Out);
|
||||
Section->writeSection(Out);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@ -797,15 +813,13 @@ void BinaryObject<ELFT>::write(FileOutputBuffer &Out) const {
|
||||
for (auto &Segment : this->Segments) {
|
||||
// GNU objcopy does not output segments that do not cover a section. Such
|
||||
// segments can sometimes be produced by LLD due to how LLD handles PT_PHDR.
|
||||
if (Segment->Type == llvm::ELF::PT_LOAD &&
|
||||
Segment->firstSection() != nullptr) {
|
||||
if (Segment->Type == PT_LOAD && Segment->firstSection() != nullptr) {
|
||||
Segment->writeSegment(Out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT> void BinaryObject<ELFT>::finalize() {
|
||||
|
||||
// Put all segments in offset order.
|
||||
auto CompareSegments = [](const SegPtr &A, const SegPtr &B) {
|
||||
return A->Offset < B->Offset;
|
||||
@ -815,8 +829,7 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
|
||||
|
||||
uint64_t Offset = 0;
|
||||
for (auto &Segment : this->Segments) {
|
||||
if (Segment->Type == llvm::ELF::PT_LOAD &&
|
||||
Segment->firstSection() != nullptr) {
|
||||
if (Segment->Type == PT_LOAD && Segment->firstSection() != nullptr) {
|
||||
Offset = alignTo(Offset, Segment->Align);
|
||||
Segment->Offset = Offset;
|
||||
Offset += Segment->FileSize;
|
||||
@ -825,6 +838,8 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
|
||||
TotalSize = Offset;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template class Object<ELF64LE>;
|
||||
template class Object<ELF64BE>;
|
||||
template class Object<ELF32LE>;
|
||||
@ -839,3 +854,5 @@ template class BinaryObject<ELF64LE>;
|
||||
template class BinaryObject<ELF64BE>;
|
||||
template class BinaryObject<ELF32LE>;
|
||||
template class BinaryObject<ELF32BE>;
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -7,38 +7,46 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_OBJCOPY_OBJECT_H
|
||||
#define LLVM_OBJCOPY_OBJECT_H
|
||||
#ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H
|
||||
#define LLVM_TOOLS_OBJCOPY_OBJECT_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class Segment;
|
||||
namespace llvm {
|
||||
|
||||
class FileOutputBuffer;
|
||||
class SectionBase;
|
||||
class Segment;
|
||||
|
||||
class SectionTableRef {
|
||||
private:
|
||||
llvm::ArrayRef<std::unique_ptr<SectionBase>> Sections;
|
||||
ArrayRef<std::unique_ptr<SectionBase>> Sections;
|
||||
|
||||
public:
|
||||
SectionTableRef(llvm::ArrayRef<std::unique_ptr<SectionBase>> Secs)
|
||||
SectionTableRef(ArrayRef<std::unique_ptr<SectionBase>> Secs)
|
||||
: Sections(Secs) {}
|
||||
SectionTableRef(const SectionTableRef &) = default;
|
||||
|
||||
SectionBase *getSection(uint16_t Index, llvm::Twine ErrMsg);
|
||||
SectionBase *getSection(uint16_t Index, Twine ErrMsg);
|
||||
|
||||
template <class T>
|
||||
T *getSectionOfType(uint16_t Index, llvm::Twine IndexErrMsg,
|
||||
llvm::Twine TypeErrMsg);
|
||||
T *getSectionOfType(uint16_t Index, Twine IndexErrMsg, Twine TypeErrMsg);
|
||||
};
|
||||
|
||||
class SectionBase {
|
||||
public:
|
||||
llvm::StringRef Name;
|
||||
StringRef Name;
|
||||
Segment *ParentSegment = nullptr;
|
||||
uint64_t HeaderOffset;
|
||||
uint64_t OriginalOffset;
|
||||
@ -49,18 +57,19 @@ public:
|
||||
uint32_t EntrySize = 0;
|
||||
uint64_t Flags = 0;
|
||||
uint64_t Info = 0;
|
||||
uint64_t Link = llvm::ELF::SHN_UNDEF;
|
||||
uint64_t Link = ELF::SHN_UNDEF;
|
||||
uint64_t NameIndex = 0;
|
||||
uint64_t Offset = 0;
|
||||
uint64_t Size = 0;
|
||||
uint64_t Type = llvm::ELF::SHT_NULL;
|
||||
uint64_t Type = ELF::SHT_NULL;
|
||||
|
||||
virtual ~SectionBase() = default;
|
||||
|
||||
virtual ~SectionBase() {}
|
||||
virtual void initialize(SectionTableRef SecTable);
|
||||
virtual void finalize();
|
||||
virtual void removeSectionReferences(const SectionBase *Sec);
|
||||
template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
|
||||
virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0;
|
||||
template <class ELFT> void writeHeader(FileOutputBuffer &Out) const;
|
||||
virtual void writeSection(FileOutputBuffer &Out) const = 0;
|
||||
};
|
||||
|
||||
class Segment {
|
||||
@ -77,7 +86,7 @@ private:
|
||||
};
|
||||
|
||||
std::set<const SectionBase *, SectionCompare> Sections;
|
||||
llvm::ArrayRef<uint8_t> Contents;
|
||||
ArrayRef<uint8_t> Contents;
|
||||
|
||||
public:
|
||||
uint64_t Align;
|
||||
@ -93,25 +102,28 @@ public:
|
||||
uint64_t OriginalOffset;
|
||||
Segment *ParentSegment = nullptr;
|
||||
|
||||
Segment(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
|
||||
const SectionBase *firstSection() const {
|
||||
if (!Sections.empty())
|
||||
return *Sections.begin();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
|
||||
void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
|
||||
template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
|
||||
void writeSegment(llvm::FileOutputBuffer &Out) const;
|
||||
template <class ELFT> void writeHeader(FileOutputBuffer &Out) const;
|
||||
void writeSegment(FileOutputBuffer &Out) const;
|
||||
};
|
||||
|
||||
class Section : public SectionBase {
|
||||
private:
|
||||
llvm::ArrayRef<uint8_t> Contents;
|
||||
ArrayRef<uint8_t> Contents;
|
||||
|
||||
public:
|
||||
Section(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
void writeSection(llvm::FileOutputBuffer &Out) const override;
|
||||
Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
|
||||
void writeSection(FileOutputBuffer &Out) const override;
|
||||
};
|
||||
|
||||
// There are two types of string tables that can exist, dynamic and not dynamic.
|
||||
@ -124,21 +136,22 @@ public:
|
||||
// then agrees with the makeSection method used to construct most sections.
|
||||
class StringTableSection : public SectionBase {
|
||||
private:
|
||||
llvm::StringTableBuilder StrTabBuilder;
|
||||
StringTableBuilder StrTabBuilder;
|
||||
|
||||
public:
|
||||
StringTableSection() : StrTabBuilder(llvm::StringTableBuilder::ELF) {
|
||||
Type = llvm::ELF::SHT_STRTAB;
|
||||
StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
|
||||
Type = ELF::SHT_STRTAB;
|
||||
}
|
||||
|
||||
void addString(llvm::StringRef Name);
|
||||
uint32_t findIndex(llvm::StringRef Name) const;
|
||||
void addString(StringRef Name);
|
||||
uint32_t findIndex(StringRef Name) const;
|
||||
void finalize() override;
|
||||
void writeSection(llvm::FileOutputBuffer &Out) const override;
|
||||
void writeSection(FileOutputBuffer &Out) const override;
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
if (S->Flags & llvm::ELF::SHF_ALLOC)
|
||||
if (S->Flags & ELF::SHF_ALLOC)
|
||||
return false;
|
||||
return S->Type == llvm::ELF::SHT_STRTAB;
|
||||
return S->Type == ELF::SHT_STRTAB;
|
||||
}
|
||||
};
|
||||
|
||||
@ -148,12 +161,12 @@ public:
|
||||
// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
|
||||
enum SymbolShndxType {
|
||||
SYMBOL_SIMPLE_INDEX = 0,
|
||||
SYMBOL_ABS = llvm::ELF::SHN_ABS,
|
||||
SYMBOL_COMMON = llvm::ELF::SHN_COMMON,
|
||||
SYMBOL_HEXAGON_SCOMMON = llvm::ELF::SHN_HEXAGON_SCOMMON,
|
||||
SYMBOL_HEXAGON_SCOMMON_2 = llvm::ELF::SHN_HEXAGON_SCOMMON_2,
|
||||
SYMBOL_HEXAGON_SCOMMON_4 = llvm::ELF::SHN_HEXAGON_SCOMMON_4,
|
||||
SYMBOL_HEXAGON_SCOMMON_8 = llvm::ELF::SHN_HEXAGON_SCOMMON_8,
|
||||
SYMBOL_ABS = ELF::SHN_ABS,
|
||||
SYMBOL_COMMON = ELF::SHN_COMMON,
|
||||
SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
|
||||
SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
|
||||
SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
|
||||
SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
@ -161,7 +174,7 @@ struct Symbol {
|
||||
SectionBase *DefinedIn = nullptr;
|
||||
SymbolShndxType ShndxType;
|
||||
uint32_t Index;
|
||||
llvm::StringRef Name;
|
||||
StringRef Name;
|
||||
uint32_t NameIndex;
|
||||
uint64_t Size;
|
||||
uint8_t Type;
|
||||
@ -175,11 +188,11 @@ protected:
|
||||
std::vector<std::unique_ptr<Symbol>> Symbols;
|
||||
StringTableSection *SymbolNames = nullptr;
|
||||
|
||||
typedef std::unique_ptr<Symbol> SymPtr;
|
||||
using SymPtr = std::unique_ptr<Symbol>;
|
||||
|
||||
public:
|
||||
void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
|
||||
void addSymbol(llvm::StringRef Name, uint8_t Bind, uint8_t Type,
|
||||
void addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
|
||||
SectionBase *DefinedIn, uint64_t Value, uint16_t Shndx,
|
||||
uint64_t Sz);
|
||||
void addSymbolNames();
|
||||
@ -187,14 +200,15 @@ public:
|
||||
void removeSectionReferences(const SectionBase *Sec) override;
|
||||
void initialize(SectionTableRef SecTable) override;
|
||||
void finalize() override;
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == llvm::ELF::SHT_SYMTAB;
|
||||
return S->Type == ELF::SHT_SYMTAB;
|
||||
}
|
||||
};
|
||||
|
||||
// Only writeSection depends on the ELF type so we implement it in a subclass.
|
||||
template <class ELFT> class SymbolTableSectionImpl : public SymbolTableSection {
|
||||
void writeSection(llvm::FileOutputBuffer &Out) const override;
|
||||
void writeSection(FileOutputBuffer &Out) const override;
|
||||
};
|
||||
|
||||
struct Relocation {
|
||||
@ -222,7 +236,7 @@ public:
|
||||
void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA;
|
||||
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
|
||||
}
|
||||
};
|
||||
|
||||
@ -234,11 +248,10 @@ private:
|
||||
SymTabType *Symbols = nullptr;
|
||||
|
||||
protected:
|
||||
RelocSectionWithSymtabBase() {}
|
||||
RelocSectionWithSymtabBase() = default;
|
||||
|
||||
public:
|
||||
void setSymTab(SymTabType *StrTab) { Symbols = StrTab; }
|
||||
|
||||
void removeSectionReferences(const SectionBase *Sec) override;
|
||||
void initialize(SectionTableRef SecTable) override;
|
||||
void finalize() override;
|
||||
@ -248,8 +261,8 @@ template <class ELFT>
|
||||
class RelocationSection
|
||||
: public RelocSectionWithSymtabBase<SymbolTableSection> {
|
||||
private:
|
||||
typedef typename ELFT::Rel Elf_Rel;
|
||||
typedef typename ELFT::Rela Elf_Rela;
|
||||
using Elf_Rel = typename ELFT::Rel;
|
||||
using Elf_Rela = typename ELFT::Rela;
|
||||
|
||||
std::vector<Relocation> Relocations;
|
||||
|
||||
@ -257,12 +270,12 @@ private:
|
||||
|
||||
public:
|
||||
void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
|
||||
void writeSection(llvm::FileOutputBuffer &Out) const override;
|
||||
void writeSection(FileOutputBuffer &Out) const override;
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
if (S->Flags & llvm::ELF::SHF_ALLOC)
|
||||
if (S->Flags & ELF::SHF_ALLOC)
|
||||
return false;
|
||||
return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA;
|
||||
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
|
||||
}
|
||||
};
|
||||
|
||||
@ -271,7 +284,8 @@ private:
|
||||
const SectionBase *StrTab = nullptr;
|
||||
|
||||
public:
|
||||
SectionWithStrTab(llvm::ArrayRef<uint8_t> Data) : Section(Data) {}
|
||||
SectionWithStrTab(ArrayRef<uint8_t> Data) : Section(Data) {}
|
||||
|
||||
void setStrTab(const SectionBase *StringTable) { StrTab = StringTable; }
|
||||
void removeSectionReferences(const SectionBase *Sec) override;
|
||||
void initialize(SectionTableRef SecTable) override;
|
||||
@ -281,51 +295,54 @@ public:
|
||||
|
||||
class DynamicSymbolTableSection : public SectionWithStrTab {
|
||||
public:
|
||||
DynamicSymbolTableSection(llvm::ArrayRef<uint8_t> Data)
|
||||
: SectionWithStrTab(Data) {}
|
||||
DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == llvm::ELF::SHT_DYNSYM;
|
||||
return S->Type == ELF::SHT_DYNSYM;
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicSection : public SectionWithStrTab {
|
||||
public:
|
||||
DynamicSection(llvm::ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
DynamicSection(ArrayRef<uint8_t> Data) : SectionWithStrTab(Data) {}
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
return S->Type == llvm::ELF::SHT_DYNAMIC;
|
||||
return S->Type == ELF::SHT_DYNAMIC;
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicRelocationSection
|
||||
: public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
|
||||
private:
|
||||
llvm::ArrayRef<uint8_t> Contents;
|
||||
ArrayRef<uint8_t> Contents;
|
||||
|
||||
public:
|
||||
DynamicRelocationSection(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
void writeSection(llvm::FileOutputBuffer &Out) const override;
|
||||
DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
||||
|
||||
void writeSection(FileOutputBuffer &Out) const override;
|
||||
|
||||
static bool classof(const SectionBase *S) {
|
||||
if (!(S->Flags & llvm::ELF::SHF_ALLOC))
|
||||
if (!(S->Flags & ELF::SHF_ALLOC))
|
||||
return false;
|
||||
return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA;
|
||||
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ELFT> class Object {
|
||||
private:
|
||||
typedef std::unique_ptr<SectionBase> SecPtr;
|
||||
typedef std::unique_ptr<Segment> SegPtr;
|
||||
using SecPtr = std::unique_ptr<SectionBase>;
|
||||
using SegPtr = std::unique_ptr<Segment>;
|
||||
|
||||
typedef typename ELFT::Shdr Elf_Shdr;
|
||||
typedef typename ELFT::Ehdr Elf_Ehdr;
|
||||
typedef typename ELFT::Phdr Elf_Phdr;
|
||||
using Elf_Shdr = typename ELFT::Shdr;
|
||||
using Elf_Ehdr = typename ELFT::Ehdr;
|
||||
using Elf_Phdr = typename ELFT::Phdr;
|
||||
|
||||
void initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
void initSymbolTable(const object::ELFFile<ELFT> &ElfFile,
|
||||
SymbolTableSection *SymTab, SectionTableRef SecTable);
|
||||
SecPtr makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
|
||||
SecPtr makeSection(const object::ELFFile<ELFT> &ElfFile,
|
||||
const Elf_Shdr &Shdr);
|
||||
void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
|
||||
SectionTableRef readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
|
||||
void readProgramHeaders(const object::ELFFile<ELFT> &ElfFile);
|
||||
SectionTableRef readSectionHeaders(const object::ELFFile<ELFT> &ElfFile);
|
||||
|
||||
protected:
|
||||
StringTableSection *SectionNames = nullptr;
|
||||
@ -333,10 +350,10 @@ protected:
|
||||
std::vector<SecPtr> Sections;
|
||||
std::vector<SegPtr> Segments;
|
||||
|
||||
void writeHeader(llvm::FileOutputBuffer &Out) const;
|
||||
void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
|
||||
void writeSectionData(llvm::FileOutputBuffer &Out) const;
|
||||
void writeSectionHeaders(llvm::FileOutputBuffer &Out) const;
|
||||
void writeHeader(FileOutputBuffer &Out) const;
|
||||
void writeProgramHeaders(FileOutputBuffer &Out) const;
|
||||
void writeSectionData(FileOutputBuffer &Out) const;
|
||||
void writeSectionHeaders(FileOutputBuffer &Out) const;
|
||||
|
||||
public:
|
||||
uint8_t Ident[16];
|
||||
@ -348,45 +365,50 @@ public:
|
||||
uint32_t Flags;
|
||||
bool WriteSectionHeaders = true;
|
||||
|
||||
Object(const llvm::object::ELFObjectFile<ELFT> &Obj);
|
||||
Object(const object::ELFObjectFile<ELFT> &Obj);
|
||||
virtual ~Object() = default;
|
||||
|
||||
void removeSections(std::function<bool(const SectionBase &)> ToRemove);
|
||||
virtual size_t totalSize() const = 0;
|
||||
virtual void finalize() = 0;
|
||||
virtual void write(llvm::FileOutputBuffer &Out) const = 0;
|
||||
virtual ~Object() = default;
|
||||
virtual void write(FileOutputBuffer &Out) const = 0;
|
||||
};
|
||||
|
||||
template <class ELFT> class ELFObject : public Object<ELFT> {
|
||||
private:
|
||||
typedef std::unique_ptr<SectionBase> SecPtr;
|
||||
typedef std::unique_ptr<Segment> SegPtr;
|
||||
using SecPtr = std::unique_ptr<SectionBase>;
|
||||
using SegPtr = std::unique_ptr<Segment>;
|
||||
|
||||
typedef typename ELFT::Shdr Elf_Shdr;
|
||||
typedef typename ELFT::Ehdr Elf_Ehdr;
|
||||
typedef typename ELFT::Phdr Elf_Phdr;
|
||||
using Elf_Shdr = typename ELFT::Shdr;
|
||||
using Elf_Ehdr = typename ELFT::Ehdr;
|
||||
using Elf_Phdr = typename ELFT::Phdr;
|
||||
|
||||
void sortSections();
|
||||
void assignOffsets();
|
||||
|
||||
public:
|
||||
ELFObject(const llvm::object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {}
|
||||
ELFObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {}
|
||||
|
||||
void finalize() override;
|
||||
size_t totalSize() const override;
|
||||
void write(llvm::FileOutputBuffer &Out) const override;
|
||||
void write(FileOutputBuffer &Out) const override;
|
||||
};
|
||||
|
||||
template <class ELFT> class BinaryObject : public Object<ELFT> {
|
||||
private:
|
||||
typedef std::unique_ptr<SectionBase> SecPtr;
|
||||
typedef std::unique_ptr<Segment> SegPtr;
|
||||
using SecPtr = std::unique_ptr<SectionBase>;
|
||||
using SegPtr = std::unique_ptr<Segment>;
|
||||
|
||||
uint64_t TotalSize;
|
||||
|
||||
public:
|
||||
BinaryObject(const llvm::object::ELFObjectFile<ELFT> &Obj)
|
||||
: Object<ELFT>(Obj) {}
|
||||
BinaryObject(const object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {}
|
||||
|
||||
void finalize() override;
|
||||
size_t totalSize() const override;
|
||||
void write(llvm::FileOutputBuffer &Out) const override;
|
||||
void write(FileOutputBuffer &Out) const override;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- llvm-objcopy.cpp -----------------------------------------*- C++ -*-===//
|
||||
//===- llvm-objcopy.cpp ---------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,17 +6,37 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm-objcopy.h"
|
||||
#include "Object.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/ELFTypes.h"
|
||||
#include "llvm/Object/Error.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace object;
|
||||
@ -39,7 +59,7 @@ LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, llvm::Error E) {
|
||||
LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, Error E) {
|
||||
assert(E);
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
@ -48,22 +68,23 @@ LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, llvm::Error E) {
|
||||
errs() << ToolName << ": '" << File << "': " << Buf;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
|
||||
cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
|
||||
} // end namespace llvm
|
||||
|
||||
static cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input>"));
|
||||
static cl::opt<std::string> OutputFilename(cl::Positional, cl::desc("<output>"),
|
||||
cl::init("-"));
|
||||
cl::opt<std::string>
|
||||
static cl::opt<std::string>
|
||||
OutputFormat("O", cl::desc("set output format to one of the following:"
|
||||
"\n\tbinary"));
|
||||
cl::list<std::string> ToRemove("remove-section",
|
||||
cl::desc("Remove a specific section"));
|
||||
cl::alias ToRemoveA("R", cl::desc("Alias for remove-section"),
|
||||
cl::aliasopt(ToRemove));
|
||||
cl::opt<bool> StripSections("strip-sections",
|
||||
cl::desc("Remove all section headers"));
|
||||
static cl::list<std::string> ToRemove("remove-section",
|
||||
cl::desc("Remove a specific section"));
|
||||
static cl::alias ToRemoveA("R", cl::desc("Alias for remove-section"),
|
||||
cl::aliasopt(ToRemove));
|
||||
static cl::opt<bool> StripSections("strip-sections",
|
||||
cl::desc("Remove all section headers"));
|
||||
|
||||
typedef std::function<bool(const SectionBase &Sec)> SectionPred;
|
||||
using SectionPred = std::function<bool(const SectionBase &Sec)>;
|
||||
|
||||
void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) {
|
||||
std::unique_ptr<FileOutputBuffer> Buffer;
|
||||
|
@ -6,11 +6,15 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_OBJCOPY_H
|
||||
#define LLVM_OBJCOPY_H
|
||||
|
||||
#ifndef LLVM_TOOLS_OBJCOPY_OBJCOPY_H
|
||||
#define LLVM_TOOLS_OBJCOPY_OBJCOPY_H
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -27,6 +31,7 @@ template <class T> T unwrapOrError(Expected<T> EO) {
|
||||
OS.flush();
|
||||
error(Buf);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_TOOLS_OBJCOPY_OBJCOPY_H
|
||||
|
Loading…
Reference in New Issue
Block a user