forked from OSchip/llvm-project
Group debugging info representation and serialization code.
Summary: Moved the classes related to representing and serializing DWARF entities into a single header, DebugData.h. (cherry picked from FBD3153279)
This commit is contained in:
parent
f6c8929799
commit
ad344c4387
|
@ -1,76 +0,0 @@
|
|||
//===--- AddressRangesDWARFObject.h - DWARF Entities with address ranges --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Represents DWARF lexical blocks, maintaining their list of address ranges to
|
||||
// be updated in the output debugging information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_ADDRESS_RANGES_DWARF_OBJECT_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_ADDRESS_RANGES_DWARF_OBJECT_H
|
||||
|
||||
#include "DebugRangesSectionsWriter.h"
|
||||
#include "BasicBlockOffsetRanges.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFCompileUnit;
|
||||
class DWARFDebugInfoEntryMinimal;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class BasicBlockTable;
|
||||
class BinaryBasicBlock;
|
||||
class BinaryFunction;
|
||||
|
||||
class AddressRangesDWARFObject : public AddressRangesOwner {
|
||||
public:
|
||||
AddressRangesDWARFObject(const DWARFCompileUnit *CU,
|
||||
const DWARFDebugInfoEntryMinimal *DIE)
|
||||
: CU(CU), DIE(DIE) { }
|
||||
|
||||
/// Add range [BeginAddress, EndAddress) to this object.
|
||||
void addAddressRange(BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress) {
|
||||
BBOffsetRanges.addAddressRange(Function, BeginAddress, EndAddress);
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint64_t, uint64_t>> getAbsoluteAddressRanges() const {
|
||||
auto AddressRangesWithData = BBOffsetRanges.getAbsoluteAddressRanges();
|
||||
std::vector<std::pair<uint64_t, uint64_t>> AddressRanges(
|
||||
AddressRangesWithData.size());
|
||||
for (unsigned I = 0, S = AddressRanges.size(); I != S; ++I) {
|
||||
AddressRanges[I] = std::make_pair(AddressRangesWithData[I].Begin,
|
||||
AddressRangesWithData[I].End);
|
||||
}
|
||||
return AddressRanges;
|
||||
}
|
||||
|
||||
void setAddressRangesOffset(uint32_t Offset) { AddressRangesOffset = Offset; }
|
||||
|
||||
uint32_t getAddressRangesOffset() const { return AddressRangesOffset; }
|
||||
|
||||
const DWARFCompileUnit *getCompileUnit() const { return CU; }
|
||||
const DWARFDebugInfoEntryMinimal *getDIE() const { return DIE; }
|
||||
|
||||
private:
|
||||
const DWARFCompileUnit *CU;
|
||||
const DWARFDebugInfoEntryMinimal *DIE;
|
||||
|
||||
BasicBlockOffsetRanges BBOffsetRanges;
|
||||
|
||||
// Offset of the address ranges of this object in the output .debug_ranges.
|
||||
uint32_t AddressRangesOffset;
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,96 +0,0 @@
|
|||
//===- BasicBlockOffsetRanges.cpp - list of address ranges relative to BBs ===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "BasicBlockOffsetRanges.h"
|
||||
#include "BinaryBasicBlock.h"
|
||||
#include "BinaryFunction.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
void BasicBlockOffsetRanges::addAddressRange(BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress,
|
||||
const BinaryData *Data) {
|
||||
auto FirstBB = Function.getBasicBlockContainingOffset(
|
||||
BeginAddress - Function.getAddress());
|
||||
assert(FirstBB && "No basic blocks in the function intersect given range.");
|
||||
|
||||
for (auto I = Function.getIndex(FirstBB), S = Function.size(); I != S; ++I) {
|
||||
auto BB = Function.getBasicBlockAtIndex(I);
|
||||
uint64_t BBAddress = Function.getAddress() + BB->getOffset();
|
||||
if (BBAddress >= EndAddress)
|
||||
break;
|
||||
|
||||
uint64_t InternalAddressRangeBegin = std::max(BBAddress, BeginAddress);
|
||||
assert(BB->getFunction() == &Function &&
|
||||
"Mismatching functions.\n");
|
||||
uint64_t InternalAddressRangeEnd =
|
||||
std::min(BBAddress + Function.getBasicBlockOriginalSize(BB),
|
||||
EndAddress);
|
||||
|
||||
AddressRanges.push_back(
|
||||
BBAddressRange{
|
||||
BB,
|
||||
static_cast<uint16_t>(InternalAddressRangeBegin - BBAddress),
|
||||
static_cast<uint16_t>(InternalAddressRangeEnd - BBAddress),
|
||||
Data});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<BasicBlockOffsetRanges::AbsoluteRange>
|
||||
BasicBlockOffsetRanges::getAbsoluteAddressRanges() const {
|
||||
std::vector<AbsoluteRange> AbsoluteRanges;
|
||||
for (const auto &BBAddressRange : AddressRanges) {
|
||||
auto BBOutputAddressRange =
|
||||
BBAddressRange.BasicBlock->getOutputAddressRange();
|
||||
uint64_t NewRangeBegin = BBOutputAddressRange.first +
|
||||
BBAddressRange.RangeBeginOffset;
|
||||
// If the end offset pointed to the end of the basic block, then we set
|
||||
// the new end range to cover the whole basic block as the BB's size
|
||||
// might have increased.
|
||||
auto BBFunction = BBAddressRange.BasicBlock->getFunction();
|
||||
uint64_t NewRangeEnd =
|
||||
(BBAddressRange.RangeEndOffset ==
|
||||
BBFunction->getBasicBlockOriginalSize(BBAddressRange.BasicBlock))
|
||||
? BBOutputAddressRange.second
|
||||
: (BBOutputAddressRange.first + BBAddressRange.RangeEndOffset);
|
||||
AbsoluteRanges.emplace_back(AbsoluteRange{NewRangeBegin, NewRangeEnd,
|
||||
BBAddressRange.Data});
|
||||
}
|
||||
if (AbsoluteRanges.empty()) {
|
||||
return AbsoluteRanges;
|
||||
}
|
||||
// Merge adjacent ranges that have the same data.
|
||||
std::sort(AbsoluteRanges.begin(), AbsoluteRanges.end(),
|
||||
[](const AbsoluteRange &A, const AbsoluteRange &B) {
|
||||
return A.Begin < B.Begin;
|
||||
});
|
||||
decltype(AbsoluteRanges) MergedRanges;
|
||||
|
||||
MergedRanges.emplace_back(AbsoluteRanges[0]);
|
||||
for (unsigned I = 1, S = AbsoluteRanges.size(); I != S; ++I) {
|
||||
// If this range complements the last one and they point to the same
|
||||
// (possibly null) data, merge them instead of creating another one.
|
||||
if (AbsoluteRanges[I].Begin == MergedRanges.back().End &&
|
||||
AbsoluteRanges[I].Data == MergedRanges.back().Data) {
|
||||
MergedRanges.back().End = AbsoluteRanges[I].End;
|
||||
} else {
|
||||
MergedRanges.emplace_back(AbsoluteRanges[I]);
|
||||
}
|
||||
}
|
||||
|
||||
return MergedRanges;
|
||||
}
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
|
@ -1,70 +0,0 @@
|
|||
//===--- BasicBlockOffsetRanges.h - list of address ranges relative to BBs ===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Represents a list of address ranges where addresses are relative to the
|
||||
// beginning of basic blocks. Useful for converting address ranges in the input
|
||||
// binary to equivalent ranges after optimizations take place.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_BASIC_BLOCK_OFFSET_RANGES_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_BASIC_BLOCK_OFFSET_RANGES_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
class BinaryFunction;
|
||||
class BinaryBasicBlock;
|
||||
|
||||
class BasicBlockOffsetRanges {
|
||||
public:
|
||||
typedef SmallVectorImpl<unsigned char> BinaryData;
|
||||
struct AbsoluteRange {
|
||||
uint64_t Begin;
|
||||
uint64_t End;
|
||||
const BinaryData *Data;
|
||||
};
|
||||
|
||||
/// Add range [BeginAddress, EndAddress) to the address ranges list.
|
||||
/// \p Function is the function that contains the given address range.
|
||||
void addAddressRange(BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress,
|
||||
const BinaryData *Data = nullptr);
|
||||
|
||||
/// Returns the list of absolute addresses calculated using the output address
|
||||
/// of the basic blocks, i.e. the input ranges updated after basic block
|
||||
/// addresses might have changed, together with the data associated to them.
|
||||
std::vector<AbsoluteRange> getAbsoluteAddressRanges() const;
|
||||
|
||||
private:
|
||||
/// An address range inside one basic block.
|
||||
struct BBAddressRange {
|
||||
const BinaryBasicBlock *BasicBlock;
|
||||
/// Beginning of the range counting from BB's start address.
|
||||
uint16_t RangeBeginOffset;
|
||||
/// (Exclusive) end of the range counting from BB's start address.
|
||||
uint16_t RangeEndOffset;
|
||||
/// Binary data associated with this range.
|
||||
const BinaryData *Data;
|
||||
};
|
||||
|
||||
std::vector<BBAddressRange> AddressRanges;
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -14,8 +14,7 @@
|
|||
#ifndef LLVM_TOOLS_LLVM_BOLT_BINARY_CONTEXT_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_BINARY_CONTEXT_H
|
||||
|
||||
#include "AddressRangesDWARFObject.h"
|
||||
#include "LocationList.h"
|
||||
#include "DebugData.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
|
@ -75,14 +74,14 @@ public:
|
|||
/// Maps DWARF CUID to offset of stmt_list attribute in .debug_info.
|
||||
std::map<unsigned, uint32_t> LineTableOffsetCUMap;
|
||||
|
||||
/// List of DWARF location lists in .debug_loc.
|
||||
std::vector<LocationList> LocationLists;
|
||||
|
||||
/// List of DWARF entries in .debug_info that have address ranges to be
|
||||
/// updated. These include lexical blocks (DW_TAG_lexical_block) and concrete
|
||||
/// instances of inlined subroutines (DW_TAG_inlined_subroutine).
|
||||
std::vector<AddressRangesDWARFObject> AddressRangesObjects;
|
||||
|
||||
/// List of DWARF location lists in .debug_loc.
|
||||
std::vector<LocationList> LocationLists;
|
||||
|
||||
using DIECompileUnitVector =
|
||||
std::vector<std::pair<const DWARFDebugInfoEntryMinimal *,
|
||||
const DWARFCompileUnit *>> ;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "BinaryBasicBlock.h"
|
||||
#include "BinaryFunction.h"
|
||||
#include "DataReader.h"
|
||||
#include "DebugLineTableRowRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "BinaryBasicBlock.h"
|
||||
#include "BinaryContext.h"
|
||||
#include "DebugRangesSectionsWriter.h"
|
||||
#include "DebugData.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
//===--- BinaryPatcher.h - Classes for modifying sections of the binary --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "BinaryPatcher.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
void SimpleBinaryPatcher::addBinaryPatch(uint32_t Offset,
|
||||
const std::string &NewValue) {
|
||||
Patches.emplace_back(std::make_pair(Offset, NewValue));
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addBytePatch(uint32_t Offset, uint8_t Value) {
|
||||
Patches.emplace_back(std::make_pair(Offset, std::string(1, Value)));
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addLEPatch(uint32_t Offset, uint64_t NewValue,
|
||||
size_t ByteSize) {
|
||||
std::string LE64(ByteSize, 0);
|
||||
for (size_t I = 0; I < ByteSize; ++I) {
|
||||
LE64[I] = NewValue & 0xff;
|
||||
NewValue >>= 8;
|
||||
}
|
||||
Patches.emplace_back(std::make_pair(Offset, LE64));
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addLE64Patch(uint32_t Offset, uint64_t NewValue) {
|
||||
addLEPatch(Offset, NewValue, 8);
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) {
|
||||
addLEPatch(Offset, NewValue, 4);
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents) {
|
||||
for (const auto &Patch : Patches) {
|
||||
uint32_t Offset = Patch.first;
|
||||
const std::string &ByteSequence = Patch.second;
|
||||
assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
|
||||
"Applied patch runs over binary size.");
|
||||
for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
|
||||
BinaryContents[Offset + I] = ByteSequence[I];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::addAttributePatch(const DWARFUnit *Unit,
|
||||
uint32_t AbbrevCode,
|
||||
uint16_t AttrTag,
|
||||
uint8_t NewAttrTag,
|
||||
uint8_t NewAttrForm) {
|
||||
assert(Unit && "No compile unit specified.");
|
||||
Patches[Unit].push_back(
|
||||
AbbrevAttrPatch{AbbrevCode, AttrTag, NewAttrTag, NewAttrForm});
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::patchBinary(std::string &Contents) {
|
||||
SimpleBinaryPatcher Patcher;
|
||||
|
||||
for (const auto &UnitPatchesPair : Patches) {
|
||||
const auto *Unit = UnitPatchesPair.first;
|
||||
const auto *UnitAbbreviations = Unit->getAbbreviations();
|
||||
assert(UnitAbbreviations &&
|
||||
"Compile unit doesn't have associated abbreviations.");
|
||||
const auto &UnitPatches = UnitPatchesPair.second;
|
||||
for (const auto &AttrPatch : UnitPatches) {
|
||||
const auto *AbbreviationDeclaration =
|
||||
UnitAbbreviations->getAbbreviationDeclaration(AttrPatch.Code);
|
||||
assert(AbbreviationDeclaration && "No abbreviation with given code.");
|
||||
const auto *Attribute = AbbreviationDeclaration->findAttribute(
|
||||
AttrPatch.Attr);
|
||||
|
||||
if (!Attribute) {
|
||||
errs() << "Attribute " << AttrPatch.Attr << " does not occur in "
|
||||
<< " abbrev " << AttrPatch.Code << " of CU " << Unit->getOffset()
|
||||
<< " in decl@" << AbbreviationDeclaration
|
||||
<< " and index = " << AbbreviationDeclaration->findAttributeIndex(AttrPatch.Attr)
|
||||
<< "\n";
|
||||
errs() << "Look at the abbrev:\n";
|
||||
AbbreviationDeclaration->dump(errs());
|
||||
|
||||
assert(Attribute && "Specified attribute doesn't occur in abbreviation.");
|
||||
}
|
||||
// Because we're only handling standard values (i.e. no DW_FORM_GNU_* or
|
||||
// DW_AT_APPLE_*), they are all small (< 128) and encoded in a single
|
||||
// byte in ULEB128, otherwise it'll be more tricky as we may need to
|
||||
// grow or shrink the section.
|
||||
Patcher.addBytePatch(Attribute->AttrOffset,
|
||||
AttrPatch.NewAttr);
|
||||
Patcher.addBytePatch(Attribute->FormOffset,
|
||||
AttrPatch.NewForm);
|
||||
}
|
||||
}
|
||||
Patcher.patchBinary(Contents);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
} // namespace bolt
|
|
@ -1,101 +0,0 @@
|
|||
//===--- BinaryPatcher.h - Classes for modifying sections of the binary --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Interfaces for applying small modifications to parts of a binary file. Some
|
||||
// specializations facilitate the modification of specific ELF/DWARF sections.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_BINARY_PATCHER_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_BINARY_PATCHER_H
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
/// Abstract interface for classes that apply modifications to a binary string.
|
||||
class BinaryPatcher {
|
||||
public:
|
||||
virtual ~BinaryPatcher() {}
|
||||
/// Applies in-place modifications to the binary string \p BinaryContents .
|
||||
virtual void patchBinary(std::string &BinaryContents) = 0;
|
||||
};
|
||||
|
||||
/// Applies simple modifications to a binary string, such as directly replacing
|
||||
/// the contents of a certain portion with a string or an integer.
|
||||
class SimpleBinaryPatcher : public BinaryPatcher {
|
||||
private:
|
||||
std::vector<std::pair<uint32_t, std::string>> Patches;
|
||||
|
||||
/// Adds a patch to replace the contents of \p ByteSize bytes with the integer
|
||||
/// \p NewValue encoded in little-endian, with the least-significant byte
|
||||
/// being written at the offset \p Offset .
|
||||
void addLEPatch(uint32_t Offset, uint64_t NewValue, size_t ByteSize);
|
||||
|
||||
public:
|
||||
~SimpleBinaryPatcher() {}
|
||||
|
||||
/// Adds a patch to replace the contents of the binary string starting at the
|
||||
/// specified \p Offset with the string \p NewValue.
|
||||
void addBinaryPatch(uint32_t Offset, const std::string &NewValue);
|
||||
|
||||
/// Adds a patch to replace the contents of a single byte of the string, at
|
||||
/// the offset \p Offset, with the value \Value .
|
||||
void addBytePatch(uint32_t Offset, uint8_t Value);
|
||||
|
||||
/// Adds a patch to put the integer \p NewValue encoded as a 64-bit
|
||||
/// little-endian value at offset \p Offset.
|
||||
void addLE64Patch(uint32_t Offset, uint64_t NewValue);
|
||||
|
||||
/// Adds a patch to put the integer \p NewValue encoded as a 32-bit
|
||||
/// little-endian value at offset \p Offset.
|
||||
void addLE32Patch(uint32_t Offset, uint32_t NewValue);
|
||||
|
||||
void patchBinary(std::string &BinaryContents) override;
|
||||
};
|
||||
|
||||
/// Apply small modifications to the .debug_abbrev DWARF section.
|
||||
class DebugAbbrevPatcher : public BinaryPatcher {
|
||||
private:
|
||||
/// Patch of changing one attribute to another.
|
||||
struct AbbrevAttrPatch {
|
||||
uint32_t Code; // Code of abbreviation to be modified.
|
||||
uint16_t Attr; // ID of attribute to be replaced.
|
||||
uint8_t NewAttr; // ID of the new attribute.
|
||||
uint8_t NewForm; // Form of the new attribute.
|
||||
};
|
||||
|
||||
std::map<const DWARFUnit *, std::vector<AbbrevAttrPatch>> Patches;
|
||||
|
||||
public:
|
||||
~DebugAbbrevPatcher() { }
|
||||
/// Adds a patch to change an attribute of an abbreviation that belongs to
|
||||
/// \p Unit to another attribute.
|
||||
/// \p AbbrevCode code of the abbreviation to be modified.
|
||||
/// \p AttrTag ID of the attribute to be replaced.
|
||||
/// \p NewAttrTag ID of the new attribute.
|
||||
/// \p NewAttrForm Form of the new attribute.
|
||||
/// We only handle standard forms, that are encoded in a single byte.
|
||||
void addAttributePatch(const DWARFUnit *Unit,
|
||||
uint32_t AbbrevCode,
|
||||
uint16_t AttrTag,
|
||||
uint8_t NewAttrTag,
|
||||
uint8_t NewAttrForm);
|
||||
|
||||
void patchBinary(std::string &Contents) override;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
} // namespace bolt
|
||||
|
||||
#endif
|
|
@ -13,15 +13,11 @@ set(LLVM_LINK_COMPONENTS
|
|||
|
||||
add_llvm_tool(llvm-bolt
|
||||
llvm-bolt.cpp
|
||||
BasicBlockOffsetRanges.cpp
|
||||
BinaryBasicBlock.cpp
|
||||
BinaryContext.cpp
|
||||
BinaryFunction.cpp
|
||||
BinaryPatcher.cpp
|
||||
DataReader.cpp
|
||||
DebugLineTableRowRef.cpp
|
||||
DebugLocWriter.cpp
|
||||
DebugRangesSectionsWriter.cpp
|
||||
DebugData.cpp
|
||||
Exceptions.cpp
|
||||
RewriteInstance.cpp
|
||||
)
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
//===- DebugData.cpp - Representation and writing of debugging information. ==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DebugData.h"
|
||||
#include "BinaryBasicBlock.h"
|
||||
#include "BinaryFunction.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
|
||||
|
||||
void BasicBlockOffsetRanges::addAddressRange(BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress,
|
||||
const BinaryData *Data) {
|
||||
auto FirstBB = Function.getBasicBlockContainingOffset(
|
||||
BeginAddress - Function.getAddress());
|
||||
assert(FirstBB && "No basic blocks in the function intersect given range.");
|
||||
|
||||
for (auto I = Function.getIndex(FirstBB), S = Function.size(); I != S; ++I) {
|
||||
auto BB = Function.getBasicBlockAtIndex(I);
|
||||
uint64_t BBAddress = Function.getAddress() + BB->getOffset();
|
||||
if (BBAddress >= EndAddress)
|
||||
break;
|
||||
|
||||
uint64_t InternalAddressRangeBegin = std::max(BBAddress, BeginAddress);
|
||||
assert(BB->getFunction() == &Function &&
|
||||
"Mismatching functions.\n");
|
||||
uint64_t InternalAddressRangeEnd =
|
||||
std::min(BBAddress + Function.getBasicBlockOriginalSize(BB),
|
||||
EndAddress);
|
||||
|
||||
AddressRanges.push_back(
|
||||
BBAddressRange{
|
||||
BB,
|
||||
static_cast<uint16_t>(InternalAddressRangeBegin - BBAddress),
|
||||
static_cast<uint16_t>(InternalAddressRangeEnd - BBAddress),
|
||||
Data});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<BasicBlockOffsetRanges::AbsoluteRange>
|
||||
BasicBlockOffsetRanges::getAbsoluteAddressRanges() const {
|
||||
std::vector<AbsoluteRange> AbsoluteRanges;
|
||||
for (const auto &BBAddressRange : AddressRanges) {
|
||||
auto BBOutputAddressRange =
|
||||
BBAddressRange.BasicBlock->getOutputAddressRange();
|
||||
uint64_t NewRangeBegin = BBOutputAddressRange.first +
|
||||
BBAddressRange.RangeBeginOffset;
|
||||
// If the end offset pointed to the end of the basic block, then we set
|
||||
// the new end range to cover the whole basic block as the BB's size
|
||||
// might have increased.
|
||||
auto BBFunction = BBAddressRange.BasicBlock->getFunction();
|
||||
uint64_t NewRangeEnd =
|
||||
(BBAddressRange.RangeEndOffset ==
|
||||
BBFunction->getBasicBlockOriginalSize(BBAddressRange.BasicBlock))
|
||||
? BBOutputAddressRange.second
|
||||
: (BBOutputAddressRange.first + BBAddressRange.RangeEndOffset);
|
||||
AbsoluteRanges.emplace_back(AbsoluteRange{NewRangeBegin, NewRangeEnd,
|
||||
BBAddressRange.Data});
|
||||
}
|
||||
if (AbsoluteRanges.empty()) {
|
||||
return AbsoluteRanges;
|
||||
}
|
||||
// Merge adjacent ranges that have the same data.
|
||||
std::sort(AbsoluteRanges.begin(), AbsoluteRanges.end(),
|
||||
[](const AbsoluteRange &A, const AbsoluteRange &B) {
|
||||
return A.Begin < B.Begin;
|
||||
});
|
||||
decltype(AbsoluteRanges) MergedRanges;
|
||||
|
||||
MergedRanges.emplace_back(AbsoluteRanges[0]);
|
||||
for (unsigned I = 1, S = AbsoluteRanges.size(); I != S; ++I) {
|
||||
// If this range complements the last one and they point to the same
|
||||
// (possibly null) data, merge them instead of creating another one.
|
||||
if (AbsoluteRanges[I].Begin == MergedRanges.back().End &&
|
||||
AbsoluteRanges[I].Data == MergedRanges.back().Data) {
|
||||
MergedRanges.back().End = AbsoluteRanges[I].End;
|
||||
} else {
|
||||
MergedRanges.emplace_back(AbsoluteRanges[I]);
|
||||
}
|
||||
}
|
||||
|
||||
return MergedRanges;
|
||||
}
|
||||
|
||||
void DebugRangesSectionsWriter::AddRange(uint32_t CompileUnitOffset,
|
||||
uint64_t Address,
|
||||
uint64_t Size) {
|
||||
CUAddressRanges[CompileUnitOffset].push_back(std::make_pair(Address, Size));
|
||||
}
|
||||
|
||||
void DebugRangesSectionsWriter::AddRange(AddressRangesOwner *BF,
|
||||
uint64_t Address,
|
||||
uint64_t Size) {
|
||||
ObjectAddressRanges[BF].push_back(std::make_pair(Address, Size));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Writes address ranges to Writer as pairs of 64-bit (address, size).
|
||||
// If RelativeRange is true, assumes the address range to be written must be of
|
||||
// the form (begin address, range size), otherwise (begin address, end address).
|
||||
// Terminates the list by writing a pair of two zeroes.
|
||||
// Returns the number of written bytes.
|
||||
uint32_t WriteAddressRanges(
|
||||
MCObjectWriter *Writer,
|
||||
const std::vector<std::pair<uint64_t, uint64_t>> &AddressRanges,
|
||||
bool RelativeRange) {
|
||||
// Write entries.
|
||||
for (auto &Range : AddressRanges) {
|
||||
Writer->writeLE64(Range.first);
|
||||
Writer->writeLE64((!RelativeRange) * Range.first + Range.second);
|
||||
}
|
||||
// Finish with 0 entries.
|
||||
Writer->writeLE64(0);
|
||||
Writer->writeLE64(0);
|
||||
return AddressRanges.size() * 16 + 16;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void DebugRangesSectionsWriter::WriteRangesSection(MCObjectWriter *Writer) {
|
||||
uint32_t SectionOffset = 0;
|
||||
for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
|
||||
uint64_t CUOffset = CUOffsetAddressRangesPair.first;
|
||||
RangesSectionOffsetCUMap[CUOffset] = SectionOffset;
|
||||
const auto &AddressRanges = CUOffsetAddressRangesPair.second;
|
||||
SectionOffset += WriteAddressRanges(Writer, AddressRanges, false);
|
||||
}
|
||||
|
||||
for (const auto &BFAddressRangesPair : ObjectAddressRanges) {
|
||||
BFAddressRangesPair.first->setAddressRangesOffset(SectionOffset);
|
||||
const auto &AddressRanges = BFAddressRangesPair.second;
|
||||
SectionOffset += WriteAddressRanges(Writer, AddressRanges, false);
|
||||
}
|
||||
|
||||
// Write an empty address list to be used for objects with unknown address
|
||||
// ranges.
|
||||
EmptyRangesListOffset = SectionOffset;
|
||||
SectionOffset += WriteAddressRanges(
|
||||
Writer,
|
||||
std::vector<std::pair<uint64_t, uint64_t>>{},
|
||||
false);
|
||||
}
|
||||
|
||||
void
|
||||
DebugRangesSectionsWriter::WriteArangesSection(MCObjectWriter *Writer) const {
|
||||
// For reference on the format of the .debug_aranges section, see the DWARF4
|
||||
// specification, section 6.1.4 Lookup by Address
|
||||
// http://www.dwarfstd.org/doc/DWARF4.pdf
|
||||
for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
|
||||
uint64_t Offset = CUOffsetAddressRangesPair.first;
|
||||
const auto &AddressRanges = CUOffsetAddressRangesPair.second;
|
||||
|
||||
// Emit header.
|
||||
|
||||
// Size of this set: 8 (size of the header) + 4 (padding after header)
|
||||
// + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
|
||||
// pair of uint64_t's for the terminating, zero-length range.
|
||||
// Does not include size field itself.
|
||||
uint64_t Size = 8 + 4 + 2*sizeof(uint64_t) * (AddressRanges.size() + 1);
|
||||
|
||||
// Header field #1: set size.
|
||||
Writer->writeLE32(Size);
|
||||
|
||||
// Header field #2: version number, 2 as per the specification.
|
||||
Writer->writeLE16(2);
|
||||
|
||||
// Header field #3: debug info offset of the correspondent compile unit.
|
||||
Writer->writeLE32(Offset);
|
||||
|
||||
// Header field #4: address size.
|
||||
// 8 since we only write ELF64 binaries for now.
|
||||
Writer->write8(8);
|
||||
|
||||
// Header field #5: segment size of target architecture.
|
||||
Writer->write8(0);
|
||||
|
||||
// Padding before address table - 4 bytes in the 64-bit-pointer case.
|
||||
Writer->writeLE32(0);
|
||||
|
||||
WriteAddressRanges(Writer, AddressRanges, true);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugLocWriter::write(const LocationList &LocList,
|
||||
MCObjectWriter *Writer) {
|
||||
// Reference: DWARF 4 specification section 7.7.3.
|
||||
UpdatedOffsets[LocList.getOriginalOffset()] = SectionOffset;
|
||||
auto AbsoluteRanges = LocList.getAbsoluteAddressRanges();
|
||||
|
||||
for (const auto &Entry : LocList.getAbsoluteAddressRanges()) {
|
||||
Writer->writeLE64(Entry.Begin);
|
||||
Writer->writeLE64(Entry.End);
|
||||
assert(Entry.Data && "Entry with null location expression.");
|
||||
Writer->writeLE16(Entry.Data->size());
|
||||
|
||||
// Need to convert binary data from unsigned char to char.
|
||||
Writer->writeBytes(
|
||||
StringRef(reinterpret_cast<const char *>(Entry.Data->data()),
|
||||
Entry.Data->size()));
|
||||
|
||||
SectionOffset += 2 * 8 + 2 + Entry.Data->size();
|
||||
}
|
||||
Writer->writeLE64(0);
|
||||
Writer->writeLE64(0);
|
||||
SectionOffset += 2 * 8;
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addBinaryPatch(uint32_t Offset,
|
||||
const std::string &NewValue) {
|
||||
Patches.emplace_back(std::make_pair(Offset, NewValue));
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addBytePatch(uint32_t Offset, uint8_t Value) {
|
||||
Patches.emplace_back(std::make_pair(Offset, std::string(1, Value)));
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addLEPatch(uint32_t Offset, uint64_t NewValue,
|
||||
size_t ByteSize) {
|
||||
std::string LE64(ByteSize, 0);
|
||||
for (size_t I = 0; I < ByteSize; ++I) {
|
||||
LE64[I] = NewValue & 0xff;
|
||||
NewValue >>= 8;
|
||||
}
|
||||
Patches.emplace_back(std::make_pair(Offset, LE64));
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addLE64Patch(uint32_t Offset, uint64_t NewValue) {
|
||||
addLEPatch(Offset, NewValue, 8);
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) {
|
||||
addLEPatch(Offset, NewValue, 4);
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents) {
|
||||
for (const auto &Patch : Patches) {
|
||||
uint32_t Offset = Patch.first;
|
||||
const std::string &ByteSequence = Patch.second;
|
||||
assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
|
||||
"Applied patch runs over binary size.");
|
||||
for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
|
||||
BinaryContents[Offset + I] = ByteSequence[I];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::addAttributePatch(const DWARFUnit *Unit,
|
||||
uint32_t AbbrevCode,
|
||||
uint16_t AttrTag,
|
||||
uint8_t NewAttrTag,
|
||||
uint8_t NewAttrForm) {
|
||||
assert(Unit && "No compile unit specified.");
|
||||
Patches[Unit].push_back(
|
||||
AbbrevAttrPatch{AbbrevCode, AttrTag, NewAttrTag, NewAttrForm});
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::patchBinary(std::string &Contents) {
|
||||
SimpleBinaryPatcher Patcher;
|
||||
|
||||
for (const auto &UnitPatchesPair : Patches) {
|
||||
const auto *Unit = UnitPatchesPair.first;
|
||||
const auto *UnitAbbreviations = Unit->getAbbreviations();
|
||||
assert(UnitAbbreviations &&
|
||||
"Compile unit doesn't have associated abbreviations.");
|
||||
const auto &UnitPatches = UnitPatchesPair.second;
|
||||
for (const auto &AttrPatch : UnitPatches) {
|
||||
const auto *AbbreviationDeclaration =
|
||||
UnitAbbreviations->getAbbreviationDeclaration(AttrPatch.Code);
|
||||
assert(AbbreviationDeclaration && "No abbreviation with given code.");
|
||||
const auto *Attribute = AbbreviationDeclaration->findAttribute(
|
||||
AttrPatch.Attr);
|
||||
|
||||
assert(Attribute && "Specified attribute doesn't occur in abbreviation.");
|
||||
// Because we're only handling standard values (i.e. no DW_FORM_GNU_* or
|
||||
// DW_AT_APPLE_*), they are all small (< 128) and encoded in a single
|
||||
// byte in ULEB128, otherwise it'll be more tricky as we may need to
|
||||
// grow or shrink the section.
|
||||
Patcher.addBytePatch(Attribute->AttrOffset,
|
||||
AttrPatch.NewAttr);
|
||||
Patcher.addBytePatch(Attribute->FormOffset,
|
||||
AttrPatch.NewForm);
|
||||
}
|
||||
}
|
||||
Patcher.patchBinary(Contents);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
|
@ -0,0 +1,355 @@
|
|||
//===-- DebugData.h - Representation and writing of debugging information. -==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Classes that represent and serialize DWARF-related entities.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_DEBUG_DATA_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_DEBUG_DATA_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFCompileUnit;
|
||||
class DWARFDebugInfoEntryMinimal;
|
||||
class MCObjectWriter;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class BasicBlockTable;
|
||||
class BinaryBasicBlock;
|
||||
class BinaryFunction;
|
||||
|
||||
/// Eeferences a row in a DWARFDebugLine::LineTable by the DWARF
|
||||
/// Context index of the DWARF Compile Unit that owns the Line Table and the row
|
||||
/// index. This is tied to our IR during disassembly so that we can later update
|
||||
/// .debug_line information. RowIndex has a base of 1, which means a RowIndex
|
||||
/// of 1 maps to the first row of the line table and a RowIndex of 0 is invalid.
|
||||
struct DebugLineTableRowRef {
|
||||
uint32_t DwCompileUnitIndex;
|
||||
uint32_t RowIndex;
|
||||
|
||||
const static DebugLineTableRowRef NULL_ROW;
|
||||
|
||||
bool operator==(const DebugLineTableRowRef &Rhs) const {
|
||||
return DwCompileUnitIndex == Rhs.DwCompileUnitIndex &&
|
||||
RowIndex == Rhs.RowIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const DebugLineTableRowRef &Rhs) const {
|
||||
return !(*this == Rhs);
|
||||
}
|
||||
|
||||
static DebugLineTableRowRef fromSMLoc(const SMLoc &Loc) {
|
||||
union {
|
||||
decltype(Loc.getPointer()) Ptr;
|
||||
DebugLineTableRowRef Ref;
|
||||
} U;
|
||||
U.Ptr = Loc.getPointer();
|
||||
return U.Ref;
|
||||
}
|
||||
|
||||
SMLoc toSMLoc() const {
|
||||
union {
|
||||
decltype(SMLoc().getPointer()) Ptr;
|
||||
DebugLineTableRowRef Ref;
|
||||
} U;
|
||||
U.Ref = *this;
|
||||
return SMLoc::getFromPointer(U.Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a list of address ranges where addresses are relative to the
|
||||
/// beginning of basic blocks. Useful for converting address ranges in the input
|
||||
/// binary to equivalent ranges after optimizations take place.
|
||||
class BasicBlockOffsetRanges {
|
||||
public:
|
||||
typedef SmallVectorImpl<unsigned char> BinaryData;
|
||||
struct AbsoluteRange {
|
||||
uint64_t Begin;
|
||||
uint64_t End;
|
||||
const BinaryData *Data;
|
||||
};
|
||||
|
||||
/// Add range [BeginAddress, EndAddress) to the address ranges list.
|
||||
/// \p Function is the function that contains the given address range.
|
||||
void addAddressRange(BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress,
|
||||
const BinaryData *Data = nullptr);
|
||||
|
||||
/// Returns the list of absolute addresses calculated using the output address
|
||||
/// of the basic blocks, i.e. the input ranges updated after basic block
|
||||
/// addresses might have changed, together with the data associated to them.
|
||||
std::vector<AbsoluteRange> getAbsoluteAddressRanges() const;
|
||||
|
||||
private:
|
||||
/// An address range inside one basic block.
|
||||
struct BBAddressRange {
|
||||
const BinaryBasicBlock *BasicBlock;
|
||||
/// Beginning of the range counting from BB's start address.
|
||||
uint16_t RangeBeginOffset;
|
||||
/// (Exclusive) end of the range counting from BB's start address.
|
||||
uint16_t RangeEndOffset;
|
||||
/// Binary data associated with this range.
|
||||
const BinaryData *Data;
|
||||
};
|
||||
|
||||
std::vector<BBAddressRange> AddressRanges;
|
||||
};
|
||||
|
||||
/// Abstract interface for classes that represent objects that have
|
||||
/// associated address ranges in .debug_ranges. These address ranges can
|
||||
/// be serialized by DebugRangesSectionsWriter which notifies the object
|
||||
/// of where in the section its address ranges list was written.
|
||||
class AddressRangesOwner {
|
||||
public:
|
||||
virtual void setAddressRangesOffset(uint32_t Offset) = 0;
|
||||
};
|
||||
|
||||
/// Represents DWARF entities that have generic address ranges, maintaining
|
||||
/// their address ranges to be updated on the output debugging information.
|
||||
class AddressRangesDWARFObject : public AddressRangesOwner {
|
||||
public:
|
||||
AddressRangesDWARFObject(const DWARFCompileUnit *CU,
|
||||
const DWARFDebugInfoEntryMinimal *DIE)
|
||||
: CU(CU), DIE(DIE) { }
|
||||
|
||||
/// Add range [BeginAddress, EndAddress) to this object.
|
||||
void addAddressRange(BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress) {
|
||||
BBOffsetRanges.addAddressRange(Function, BeginAddress, EndAddress);
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint64_t, uint64_t>> getAbsoluteAddressRanges() const {
|
||||
auto AddressRangesWithData = BBOffsetRanges.getAbsoluteAddressRanges();
|
||||
std::vector<std::pair<uint64_t, uint64_t>> AddressRanges(
|
||||
AddressRangesWithData.size());
|
||||
for (unsigned I = 0, S = AddressRanges.size(); I != S; ++I) {
|
||||
AddressRanges[I] = std::make_pair(AddressRangesWithData[I].Begin,
|
||||
AddressRangesWithData[I].End);
|
||||
}
|
||||
return AddressRanges;
|
||||
}
|
||||
|
||||
void setAddressRangesOffset(uint32_t Offset) { AddressRangesOffset = Offset; }
|
||||
|
||||
uint32_t getAddressRangesOffset() const { return AddressRangesOffset; }
|
||||
|
||||
const DWARFCompileUnit *getCompileUnit() const { return CU; }
|
||||
const DWARFDebugInfoEntryMinimal *getDIE() const { return DIE; }
|
||||
|
||||
private:
|
||||
const DWARFCompileUnit *CU;
|
||||
const DWARFDebugInfoEntryMinimal *DIE;
|
||||
|
||||
BasicBlockOffsetRanges BBOffsetRanges;
|
||||
|
||||
// Offset of the address ranges of this object in the output .debug_ranges.
|
||||
uint32_t AddressRangesOffset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Represents DWARF location lists, maintaining their list of location
|
||||
/// expressions and the address ranges in which they are valid to be updated in
|
||||
/// the output debugging information.
|
||||
class LocationList {
|
||||
public:
|
||||
LocationList(uint32_t Offset) : DebugLocOffset(Offset) { }
|
||||
|
||||
/// Add a location expression that is valid in [BeginAddress, EndAddress)
|
||||
/// within Function to location list.
|
||||
void addLocation(const BasicBlockOffsetRanges::BinaryData *Expression,
|
||||
BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress) {
|
||||
BBOffsetRanges.addAddressRange(Function, BeginAddress, EndAddress,
|
||||
Expression);
|
||||
}
|
||||
|
||||
std::vector<BasicBlockOffsetRanges::AbsoluteRange>
|
||||
getAbsoluteAddressRanges() const {
|
||||
return BBOffsetRanges.getAbsoluteAddressRanges();
|
||||
}
|
||||
|
||||
uint32_t getOriginalOffset() const { return DebugLocOffset; }
|
||||
|
||||
private:
|
||||
BasicBlockOffsetRanges BBOffsetRanges;
|
||||
|
||||
// Offset of this location list in the input .debug_loc section.
|
||||
uint32_t DebugLocOffset;
|
||||
};
|
||||
|
||||
/// Serializes the .debug_ranges and .debug_aranges DWARF sections.
|
||||
class DebugRangesSectionsWriter {
|
||||
public:
|
||||
DebugRangesSectionsWriter() = default;
|
||||
|
||||
/// Adds a range to the .debug_arange section.
|
||||
void AddRange(uint32_t CompileUnitOffset, uint64_t Address, uint64_t Size);
|
||||
|
||||
/// Adds an address range that belongs to a given object.
|
||||
/// When .debug_ranges is written, the offset of the range corresponding
|
||||
/// to the function will be set using BF->setAddressRangesOffset().
|
||||
void AddRange(AddressRangesOwner *ARO, uint64_t Address, uint64_t Size);
|
||||
|
||||
using RangesCUMapType = std::map<uint32_t, uint32_t>;
|
||||
|
||||
/// Writes .debug_aranges with the added ranges to the MCObjectWriter.
|
||||
void WriteArangesSection(MCObjectWriter *Writer) const;
|
||||
|
||||
/// Writes .debug_ranges with the added ranges to the MCObjectWriter.
|
||||
void WriteRangesSection(MCObjectWriter *Writer);
|
||||
|
||||
/// Resets the writer to a clear state.
|
||||
void reset() {
|
||||
CUAddressRanges.clear();
|
||||
ObjectAddressRanges.clear();
|
||||
RangesSectionOffsetCUMap.clear();
|
||||
}
|
||||
|
||||
/// Return mapping of CUs to offsets in .debug_ranges.
|
||||
const RangesCUMapType &getRangesOffsetCUMap() const {
|
||||
return RangesSectionOffsetCUMap;
|
||||
}
|
||||
|
||||
/// Returns an offset of an empty address ranges list that is always written
|
||||
/// to .debug_ranges
|
||||
uint32_t getEmptyRangesListOffset() const { return EmptyRangesListOffset; }
|
||||
|
||||
private:
|
||||
// Map from compile unit offset to the list of address intervals that belong
|
||||
// to that compile unit. Each interval is a pair
|
||||
// (first address, interval size).
|
||||
std::map<uint32_t, std::vector<std::pair<uint64_t, uint64_t>>>
|
||||
CUAddressRanges;
|
||||
|
||||
// Map from BinaryFunction to the list of address intervals that belong
|
||||
// to that function, represented like CUAddressRanges.
|
||||
std::map<AddressRangesOwner *, std::vector<std::pair<uint64_t, uint64_t>>>
|
||||
ObjectAddressRanges;
|
||||
|
||||
// Offset of an empty address ranges list.
|
||||
uint32_t EmptyRangesListOffset;
|
||||
|
||||
/// When writing data to .debug_ranges remember offset per CU.
|
||||
RangesCUMapType RangesSectionOffsetCUMap;
|
||||
};
|
||||
|
||||
/// Serializes the .debug_loc DWARF section with LocationLists.
|
||||
class DebugLocWriter {
|
||||
public:
|
||||
/// Writes the given location list to the writer.
|
||||
void write(const LocationList &LocList, MCObjectWriter *Writer);
|
||||
|
||||
using UpdatedOffsetMapType = std::map<uint32_t, uint32_t>;
|
||||
|
||||
/// Returns mapping from offsets in the input .debug_loc to offsets in the
|
||||
/// output .debug_loc section with the corresponding updated location list
|
||||
/// entry.
|
||||
const UpdatedOffsetMapType &getUpdatedLocationListOffsets() const {
|
||||
return UpdatedOffsets;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Current offset in the section (updated as new entries are written).
|
||||
uint32_t SectionOffset{0};
|
||||
|
||||
/// Map from input offsets to output offsets for location lists that were
|
||||
/// updated, generated after write().
|
||||
UpdatedOffsetMapType UpdatedOffsets;
|
||||
};
|
||||
|
||||
/// Abstract interface for classes that apply modifications to a binary string.
|
||||
class BinaryPatcher {
|
||||
public:
|
||||
virtual ~BinaryPatcher() {}
|
||||
/// Applies in-place modifications to the binary string \p BinaryContents .
|
||||
virtual void patchBinary(std::string &BinaryContents) = 0;
|
||||
};
|
||||
|
||||
/// Applies simple modifications to a binary string, such as directly replacing
|
||||
/// the contents of a certain portion with a string or an integer.
|
||||
class SimpleBinaryPatcher : public BinaryPatcher {
|
||||
private:
|
||||
std::vector<std::pair<uint32_t, std::string>> Patches;
|
||||
|
||||
/// Adds a patch to replace the contents of \p ByteSize bytes with the integer
|
||||
/// \p NewValue encoded in little-endian, with the least-significant byte
|
||||
/// being written at the offset \p Offset .
|
||||
void addLEPatch(uint32_t Offset, uint64_t NewValue, size_t ByteSize);
|
||||
|
||||
public:
|
||||
~SimpleBinaryPatcher() {}
|
||||
|
||||
/// Adds a patch to replace the contents of the binary string starting at the
|
||||
/// specified \p Offset with the string \p NewValue.
|
||||
void addBinaryPatch(uint32_t Offset, const std::string &NewValue);
|
||||
|
||||
/// Adds a patch to replace the contents of a single byte of the string, at
|
||||
/// the offset \p Offset, with the value \Value .
|
||||
void addBytePatch(uint32_t Offset, uint8_t Value);
|
||||
|
||||
/// Adds a patch to put the integer \p NewValue encoded as a 64-bit
|
||||
/// little-endian value at offset \p Offset.
|
||||
void addLE64Patch(uint32_t Offset, uint64_t NewValue);
|
||||
|
||||
/// Adds a patch to put the integer \p NewValue encoded as a 32-bit
|
||||
/// little-endian value at offset \p Offset.
|
||||
void addLE32Patch(uint32_t Offset, uint32_t NewValue);
|
||||
|
||||
void patchBinary(std::string &BinaryContents) override;
|
||||
};
|
||||
|
||||
/// Apply small modifications to the .debug_abbrev DWARF section.
|
||||
class DebugAbbrevPatcher : public BinaryPatcher {
|
||||
private:
|
||||
/// Patch of changing one attribute to another.
|
||||
struct AbbrevAttrPatch {
|
||||
uint32_t Code; // Code of abbreviation to be modified.
|
||||
uint16_t Attr; // ID of attribute to be replaced.
|
||||
uint8_t NewAttr; // ID of the new attribute.
|
||||
uint8_t NewForm; // Form of the new attribute.
|
||||
};
|
||||
|
||||
std::map<const DWARFUnit *, std::vector<AbbrevAttrPatch>> Patches;
|
||||
|
||||
public:
|
||||
~DebugAbbrevPatcher() { }
|
||||
/// Adds a patch to change an attribute of an abbreviation that belongs to
|
||||
/// \p Unit to another attribute.
|
||||
/// \p AbbrevCode code of the abbreviation to be modified.
|
||||
/// \p AttrTag ID of the attribute to be replaced.
|
||||
/// \p NewAttrTag ID of the new attribute.
|
||||
/// \p NewAttrForm Form of the new attribute.
|
||||
/// We only handle standard forms, that are encoded in a single byte.
|
||||
void addAttributePatch(const DWARFUnit *Unit,
|
||||
uint32_t AbbrevCode,
|
||||
uint16_t AttrTag,
|
||||
uint8_t NewAttrTag,
|
||||
uint8_t NewAttrForm);
|
||||
|
||||
void patchBinary(std::string &Contents) override;
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,21 +0,0 @@
|
|||
//===--- DebugLineTableRowRef.cpp - Identifies a row in a .debug_line table ==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DebugLineTableRowRef.h"
|
||||
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
|
@ -1,64 +0,0 @@
|
|||
//===--- DebugLineTableRowRef.h - Identifies a row in a .debug_line table -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Class that references a row in a DWARFDebugLine::LineTable by the DWARF
|
||||
// Context index of the DWARF Compile Unit that owns the Line Table and the row
|
||||
// index. This is tied to our IR during disassembly so that we can later update
|
||||
// .debug_line information. The RowIndex has a base of 1, which means a RowIndex
|
||||
// of 1 maps to the first row of the line table and a RowIndex of 0 is invalid.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_DEBUGLINETABLEROWREF_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_DEBUGLINETABLEROWREF_H
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
struct DebugLineTableRowRef {
|
||||
uint32_t DwCompileUnitIndex;
|
||||
uint32_t RowIndex;
|
||||
|
||||
const static DebugLineTableRowRef NULL_ROW;
|
||||
|
||||
bool operator==(const DebugLineTableRowRef &Rhs) const {
|
||||
return DwCompileUnitIndex == Rhs.DwCompileUnitIndex &&
|
||||
RowIndex == Rhs.RowIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const DebugLineTableRowRef &Rhs) const {
|
||||
return !(*this == Rhs);
|
||||
}
|
||||
|
||||
static DebugLineTableRowRef fromSMLoc(const SMLoc &Loc) {
|
||||
union {
|
||||
decltype(Loc.getPointer()) Ptr;
|
||||
DebugLineTableRowRef Ref;
|
||||
} U;
|
||||
U.Ptr = Loc.getPointer();
|
||||
return U.Ref;
|
||||
}
|
||||
|
||||
SMLoc toSMLoc() const {
|
||||
union {
|
||||
decltype(SMLoc().getPointer()) Ptr;
|
||||
DebugLineTableRowRef Ref;
|
||||
} U;
|
||||
U.Ref = *this;
|
||||
return SMLoc::getFromPointer(U.Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||
//===-- DebugLocWriter.cpp - Writes the DWARF .debug_loc section. ----------==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DebugLocWriter.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
void DebugLocWriter::write(const LocationList &LocList,
|
||||
MCObjectWriter *Writer) {
|
||||
// Reference: DWARF 4 specification section 7.7.3.
|
||||
UpdatedOffsets[LocList.getOriginalOffset()] = SectionOffset;
|
||||
auto AbsoluteRanges = LocList.getAbsoluteAddressRanges();
|
||||
|
||||
for (const auto &Entry : LocList.getAbsoluteAddressRanges()) {
|
||||
Writer->writeLE64(Entry.Begin);
|
||||
Writer->writeLE64(Entry.End);
|
||||
assert(Entry.Data && "Entry with null location expression.");
|
||||
Writer->writeLE16(Entry.Data->size());
|
||||
|
||||
// Need to convert binary data from unsigned char to char.
|
||||
Writer->writeBytes(
|
||||
StringRef(reinterpret_cast<const char *>(Entry.Data->data()),
|
||||
Entry.Data->size()));
|
||||
|
||||
SectionOffset += 2 * 8 + 2 + Entry.Data->size();
|
||||
}
|
||||
Writer->writeLE64(0);
|
||||
Writer->writeLE64(0);
|
||||
SectionOffset += 2 * 8;
|
||||
}
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
|
@ -1,53 +0,0 @@
|
|||
//===-- DebugLocWriter.h - Writes the DWARF .debug_loc section -------------==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Class that serializes the .debug_loc section given LocationLists.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_DEBUG_LOC_WRITER_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_DEBUG_LOC_WRITER_H
|
||||
|
||||
#include "LocationList.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCObjectWriter;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class DebugLocWriter {
|
||||
public:
|
||||
/// Writes the given location list to the writer.
|
||||
void write(const LocationList &LocList, MCObjectWriter *Writer);
|
||||
|
||||
using UpdatedOffsetMapType = std::map<uint32_t, uint32_t>;
|
||||
|
||||
/// Returns mapping from offsets in the input .debug_loc to offsets in the
|
||||
/// output .debug_loc section with the corresponding updated location list
|
||||
/// entry.
|
||||
const UpdatedOffsetMapType &getUpdatedLocationListOffsets() const {
|
||||
return UpdatedOffsets;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Current offset in the section (updated as new entries are written).
|
||||
uint32_t SectionOffset{0};
|
||||
|
||||
/// Map from input offsets to output offsets for location lists that were
|
||||
/// updated, generated after write().
|
||||
UpdatedOffsetMapType UpdatedOffsets;
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,119 +0,0 @@
|
|||
//===-- DebugRangesSectionsWriter.h - Writes DWARF address ranges sections -==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DebugRangesSectionsWriter.h"
|
||||
#include "BinaryFunction.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
void DebugRangesSectionsWriter::AddRange(uint32_t CompileUnitOffset,
|
||||
uint64_t Address,
|
||||
uint64_t Size) {
|
||||
CUAddressRanges[CompileUnitOffset].push_back(std::make_pair(Address, Size));
|
||||
}
|
||||
|
||||
void DebugRangesSectionsWriter::AddRange(AddressRangesOwner *BF,
|
||||
uint64_t Address,
|
||||
uint64_t Size) {
|
||||
ObjectAddressRanges[BF].push_back(std::make_pair(Address, Size));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Writes address ranges to Writer as pairs of 64-bit (address, size).
|
||||
// If RelativeRange is true, assumes the address range to be written must be of
|
||||
// the form (begin address, range size), otherwise (begin address, end address).
|
||||
// Terminates the list by writing a pair of two zeroes.
|
||||
// Returns the number of written bytes.
|
||||
uint32_t WriteAddressRanges(
|
||||
MCObjectWriter *Writer,
|
||||
const std::vector<std::pair<uint64_t, uint64_t>> &AddressRanges,
|
||||
bool RelativeRange) {
|
||||
// Write entries.
|
||||
for (auto &Range : AddressRanges) {
|
||||
Writer->writeLE64(Range.first);
|
||||
Writer->writeLE64((!RelativeRange) * Range.first + Range.second);
|
||||
}
|
||||
// Finish with 0 entries.
|
||||
Writer->writeLE64(0);
|
||||
Writer->writeLE64(0);
|
||||
return AddressRanges.size() * 16 + 16;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void DebugRangesSectionsWriter::WriteRangesSection(MCObjectWriter *Writer) {
|
||||
uint32_t SectionOffset = 0;
|
||||
for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
|
||||
uint64_t CUOffset = CUOffsetAddressRangesPair.first;
|
||||
RangesSectionOffsetCUMap[CUOffset] = SectionOffset;
|
||||
const auto &AddressRanges = CUOffsetAddressRangesPair.second;
|
||||
SectionOffset += WriteAddressRanges(Writer, AddressRanges, false);
|
||||
}
|
||||
|
||||
for (const auto &BFAddressRangesPair : ObjectAddressRanges) {
|
||||
BFAddressRangesPair.first->setAddressRangesOffset(SectionOffset);
|
||||
const auto &AddressRanges = BFAddressRangesPair.second;
|
||||
SectionOffset += WriteAddressRanges(Writer, AddressRanges, false);
|
||||
}
|
||||
|
||||
// Write an empty address list to be used for objects with unknown address
|
||||
// ranges.
|
||||
EmptyRangesListOffset = SectionOffset;
|
||||
SectionOffset += WriteAddressRanges(
|
||||
Writer,
|
||||
std::vector<std::pair<uint64_t, uint64_t>>{},
|
||||
false);
|
||||
}
|
||||
|
||||
void
|
||||
DebugRangesSectionsWriter::WriteArangesSection(MCObjectWriter *Writer) const {
|
||||
// For reference on the format of the .debug_aranges section, see the DWARF4
|
||||
// specification, section 6.1.4 Lookup by Address
|
||||
// http://www.dwarfstd.org/doc/DWARF4.pdf
|
||||
for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
|
||||
uint64_t Offset = CUOffsetAddressRangesPair.first;
|
||||
const auto &AddressRanges = CUOffsetAddressRangesPair.second;
|
||||
|
||||
// Emit header.
|
||||
|
||||
// Size of this set: 8 (size of the header) + 4 (padding after header)
|
||||
// + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
|
||||
// pair of uint64_t's for the terminating, zero-length range.
|
||||
// Does not include size field itself.
|
||||
uint64_t Size = 8 + 4 + 2*sizeof(uint64_t) * (AddressRanges.size() + 1);
|
||||
|
||||
// Header field #1: set size.
|
||||
Writer->writeLE32(Size);
|
||||
|
||||
// Header field #2: version number, 2 as per the specification.
|
||||
Writer->writeLE16(2);
|
||||
|
||||
// Header field #3: debug info offset of the correspondent compile unit.
|
||||
Writer->writeLE32(Offset);
|
||||
|
||||
// Header field #4: address size.
|
||||
// 8 since we only write ELF64 binaries for now.
|
||||
Writer->write8(8);
|
||||
|
||||
// Header field #5: segment size of target architecture.
|
||||
Writer->write8(0);
|
||||
|
||||
// Padding before address table - 4 bytes in the 64-bit-pointer case.
|
||||
Writer->writeLE32(0);
|
||||
|
||||
WriteAddressRanges(Writer, AddressRanges, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
|
@ -1,94 +0,0 @@
|
|||
//===-- DebugRangesSectionsWriter.h - Writes DWARF address ranges sections -==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Class that serializes the .debug_ranges and .debug_aranges sections.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_DEBUG_RANGES_SECTIONS_WRITER_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_DEBUG_RANGES_SECTIONS_WRITER_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCObjectWriter;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
/// Abstract interface for classes that represent objects that have
|
||||
/// associated address ranges in .debug_ranges. These address ranges can
|
||||
/// be serialized by DebugRangesSectionsWriter which notifies the object
|
||||
/// of where in the section its address ranges list was written.
|
||||
class AddressRangesOwner {
|
||||
public:
|
||||
virtual void setAddressRangesOffset(uint32_t Offset) = 0;
|
||||
};
|
||||
|
||||
class DebugRangesSectionsWriter {
|
||||
public:
|
||||
DebugRangesSectionsWriter() = default;
|
||||
|
||||
/// Adds a range to the .debug_arange section.
|
||||
void AddRange(uint32_t CompileUnitOffset, uint64_t Address, uint64_t Size);
|
||||
|
||||
/// Adds an address range that belongs to a given object.
|
||||
/// When .debug_ranges is written, the offset of the range corresponding
|
||||
/// to the function will be set using BF->setAddressRangesOffset().
|
||||
void AddRange(AddressRangesOwner *ARO, uint64_t Address, uint64_t Size);
|
||||
|
||||
using RangesCUMapType = std::map<uint32_t, uint32_t>;
|
||||
|
||||
/// Writes .debug_aranges with the added ranges to the MCObjectWriter.
|
||||
void WriteArangesSection(MCObjectWriter *Writer) const;
|
||||
|
||||
/// Writes .debug_ranges with the added ranges to the MCObjectWriter.
|
||||
void WriteRangesSection(MCObjectWriter *Writer);
|
||||
|
||||
/// Resets the writer to a clear state.
|
||||
void reset() {
|
||||
CUAddressRanges.clear();
|
||||
ObjectAddressRanges.clear();
|
||||
RangesSectionOffsetCUMap.clear();
|
||||
}
|
||||
|
||||
/// Return mapping of CUs to offsets in .debug_ranges.
|
||||
const RangesCUMapType &getRangesOffsetCUMap() const {
|
||||
return RangesSectionOffsetCUMap;
|
||||
}
|
||||
|
||||
/// Returns an offset of an empty address ranges list that is always written
|
||||
/// to .debug_ranges
|
||||
uint32_t getEmptyRangesListOffset() const { return EmptyRangesListOffset; }
|
||||
|
||||
private:
|
||||
// Map from compile unit offset to the list of address intervals that belong
|
||||
// to that compile unit. Each interval is a pair
|
||||
// (first address, interval size).
|
||||
std::map<uint32_t, std::vector<std::pair<uint64_t, uint64_t>>>
|
||||
CUAddressRanges;
|
||||
|
||||
// Map from BinaryFunction to the list of address intervals that belong
|
||||
// to that function, represented like CUAddressRanges.
|
||||
std::map<AddressRangesOwner *, std::vector<std::pair<uint64_t, uint64_t>>>
|
||||
ObjectAddressRanges;
|
||||
|
||||
// Offset of an empty address ranges list.
|
||||
uint32_t EmptyRangesListOffset;
|
||||
|
||||
/// When writing data to .debug_ranges remember offset per CU.
|
||||
RangesCUMapType RangesSectionOffsetCUMap;
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,61 +0,0 @@
|
|||
//===--- LocationList.h - DWARF location lists ----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Represents DWARF location lists, maintaining their list of location
|
||||
// expressions and the address ranges in which they are valid to be updated in
|
||||
// the output debugging information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_BOLT_LOCATION_LIST_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_LOCATION_LIST_H
|
||||
|
||||
#include "BasicBlockOffsetRanges.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFCompileUnit;
|
||||
class DWARFDebugInfoEntryMinimal;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class BinaryBasicBlock;
|
||||
|
||||
class LocationList {
|
||||
public:
|
||||
LocationList(uint32_t Offset) : DebugLocOffset(Offset) { }
|
||||
|
||||
/// Add a location expression that is valid in [BeginAddress, EndAddress)
|
||||
/// within Function to location list.
|
||||
void addLocation(const BasicBlockOffsetRanges::BinaryData *Expression,
|
||||
BinaryFunction &Function,
|
||||
uint64_t BeginAddress,
|
||||
uint64_t EndAddress) {
|
||||
BBOffsetRanges.addAddressRange(Function, BeginAddress, EndAddress,
|
||||
Expression);
|
||||
}
|
||||
|
||||
std::vector<BasicBlockOffsetRanges::AbsoluteRange>
|
||||
getAbsoluteAddressRanges() const {
|
||||
return BBOffsetRanges.getAbsoluteAddressRanges();
|
||||
}
|
||||
|
||||
uint32_t getOriginalOffset() const { return DebugLocOffset; }
|
||||
|
||||
private:
|
||||
BasicBlockOffsetRanges BBOffsetRanges;
|
||||
|
||||
// Offset of this location list in the input .debug_loc section.
|
||||
uint32_t DebugLocOffset;
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -14,7 +14,6 @@
|
|||
#include "BinaryContext.h"
|
||||
#include "BinaryFunction.h"
|
||||
#include "DataReader.h"
|
||||
#include "DebugLineTableRowRef.h"
|
||||
#include "Exceptions.h"
|
||||
#include "RewriteInstance.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
#ifndef LLVM_TOOLS_LLVM_BOLT_REWRITE_INSTANCE_H
|
||||
#define LLVM_TOOLS_LLVM_BOLT_REWRITE_INSTANCE_H
|
||||
|
||||
#include "BinaryPatcher.h"
|
||||
#include "DebugLocWriter.h"
|
||||
#include "DebugRangesSectionsWriter.h"
|
||||
#include "DebugData.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
|
|
Loading…
Reference in New Issue