1
0
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:
Eugene Zelenko 2017-11-01 21:16:06 +00:00
parent 60862bee82
commit 0d3ac016c2
10 changed files with 490 additions and 252 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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