Skip to content

[Cherry-pick] Patches related to dwarf linker #8094

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,34 @@ struct DwarfStringPoolEntry {
bool isIndexed() const { return Index != NotIndexed; }
};

/// DwarfStringPoolEntry with string keeping externally.
struct DwarfStringPoolEntryWithExtString : public DwarfStringPoolEntry {
StringRef String;
};

/// DwarfStringPoolEntryRef: Dwarf string pool entry reference.
///
/// Dwarf string pool entry keeps string value and its data.
/// There are two variants how data are represented:
///
/// 1. By value - StringMapEntry<DwarfStringPoolEntry>.
/// 2. By pointer - StringMapEntry<DwarfStringPoolEntry *>.
/// 1. String data in pool - StringMapEntry<DwarfStringPoolEntry>.
/// 2. External string data - DwarfStringPoolEntryWithExtString.
///
/// The "By pointer" variant allows for reducing memory usage for the case
/// when string pool entry does not have data: it keeps the null pointer
/// and so no need to waste space for the full DwarfStringPoolEntry.
/// It is recommended to use "By pointer" variant if not all entries
/// of dwarf string pool have corresponding DwarfStringPoolEntry.
/// The external data variant allows reducing memory usage for the case
/// when string pool entry does not have data: string entry does not
/// keep any data and so no need to waste space for the full
/// DwarfStringPoolEntry. It is recommended to use external variant if not all
/// entries of dwarf string pool have corresponding DwarfStringPoolEntry.

class DwarfStringPoolEntryRef {
/// Pointer type for "By value" string entry.
using ByValStringEntryPtr = const StringMapEntry<DwarfStringPoolEntry> *;

/// Pointer type for "By pointer" string entry.
using ByPtrStringEntryPtr = const StringMapEntry<DwarfStringPoolEntry *> *;
/// Pointer type for external string entry.
using ExtStringEntryPtr = const DwarfStringPoolEntryWithExtString *;

/// Pointer to the dwarf string pool Entry.
PointerUnion<ByValStringEntryPtr, ByPtrStringEntryPtr> MapEntry = nullptr;
PointerUnion<ByValStringEntryPtr, ExtStringEntryPtr> MapEntry = nullptr;

public:
DwarfStringPoolEntryRef() = default;
Expand All @@ -61,10 +66,8 @@ class DwarfStringPoolEntryRef {

/// ASSUMPTION: DwarfStringPoolEntryRef keeps pointer to \p Entry,
/// thus specified entry mustn`t be reallocated.
DwarfStringPoolEntryRef(const StringMapEntry<DwarfStringPoolEntry *> &Entry)
: MapEntry(&Entry) {
assert(cast<ByPtrStringEntryPtr>(MapEntry)->second != nullptr);
}
DwarfStringPoolEntryRef(const DwarfStringPoolEntryWithExtString &Entry)
: MapEntry(&Entry) {}

explicit operator bool() const { return !MapEntry.isNull(); }

Expand All @@ -88,15 +91,15 @@ class DwarfStringPoolEntryRef {
if (isa<ByValStringEntryPtr>(MapEntry))
return cast<ByValStringEntryPtr>(MapEntry)->first();

return cast<ByPtrStringEntryPtr>(MapEntry)->first();
return cast<ExtStringEntryPtr>(MapEntry)->String;
}

/// \returns the entire string pool entry for convenience.
const DwarfStringPoolEntry &getEntry() const {
if (isa<ByValStringEntryPtr>(MapEntry))
return cast<ByValStringEntryPtr>(MapEntry)->second;

return *cast<ByPtrStringEntryPtr>(MapEntry)->second;
return *cast<ExtStringEntryPtr>(MapEntry);
}

bool operator==(const DwarfStringPoolEntryRef &X) const {
Expand Down
5 changes: 3 additions & 2 deletions llvm/include/llvm/DWARFLinker/DWARFLinker.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,9 @@ using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
/// and its address map.
class DWARFFile {
public:
using UnloadCallbackTy = std::function<void(StringRef FileName)>;
DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
std::unique_ptr<AddressesMap> Addresses)
std::unique_ptr<AddressesMap> Addresses, UnloadCallbackTy = nullptr)
: FileName(Name), Dwarf(std::move(Dwarf)),
Addresses(std::move(Addresses)) {}

Expand Down Expand Up @@ -357,7 +358,7 @@ class DWARFLinker {
Pub, ///< .debug_pubnames, .debug_pubtypes
DebugNames ///< .debug_names.
};
typedef std::function<void(const DWARFFile &File)> inputVerificationHandler;
typedef std::function<void(const DWARFFile &File, llvm::StringRef Output)> inputVerificationHandler;
typedef std::function<ErrorOr<DWARFFile &>(StringRef ContainerName,
StringRef Path)>
objFileLoader;
Expand Down
104 changes: 104 additions & 0 deletions llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
#define LLVM_DWARFLINKERPARALLEL_ADDRESSESMAP_H

#include "llvm/ADT/AddressRanges.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include <cstdint>

namespace llvm {
Expand Down Expand Up @@ -80,6 +82,108 @@ class AddressesMap {

/// Erases all data.
virtual void clear() = 0;

/// This function checks whether variable has DWARF expression containing
/// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
/// \returns first is true if the expression has an operation referencing an
/// address.
/// second is the relocation adjustment value if the live address is
/// referenced.
std::pair<bool, std::optional<int64_t>>
getVariableRelocAdjustment(const DWARFDie &DIE) {
assert((DIE.getTag() == dwarf::DW_TAG_variable ||
DIE.getTag() == dwarf::DW_TAG_constant) &&
"Wrong type of input die");

const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();

// Check if DIE has DW_AT_location attribute.
DWARFUnit *U = DIE.getDwarfUnit();
std::optional<uint32_t> LocationIdx =
Abbrev->findAttributeIndex(dwarf::DW_AT_location);
if (!LocationIdx)
return std::make_pair(false, std::nullopt);

// Get offset to the DW_AT_location attribute.
uint64_t AttrOffset =
Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);

// Get value of the DW_AT_location attribute.
std::optional<DWARFFormValue> LocationValue =
Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
if (!LocationValue)
return std::make_pair(false, std::nullopt);

// Check that DW_AT_location attribute is of 'exprloc' class.
// Handling value of location expressions for attributes of 'loclist'
// class is not implemented yet.
std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
if (!Expr)
return std::make_pair(false, std::nullopt);

// Parse 'exprloc' expression.
DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
U->getAddressByteSize());
DWARFExpression Expression(Data, U->getAddressByteSize(),
U->getFormParams().Format);

bool HasLocationAddress = false;
uint64_t CurExprOffset = 0;
for (DWARFExpression::iterator It = Expression.begin();
It != Expression.end(); ++It) {
DWARFExpression::iterator NextIt = It;
++NextIt;

const DWARFExpression::Operation &Op = *It;
switch (Op.getCode()) {
case dwarf::DW_OP_const2u:
case dwarf::DW_OP_const4u:
case dwarf::DW_OP_const8u:
case dwarf::DW_OP_const2s:
case dwarf::DW_OP_const4s:
case dwarf::DW_OP_const8s:
if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))
break;
[[fallthrough]];
case dwarf::DW_OP_addr: {
HasLocationAddress = true;
// Check relocation for the address.
if (std::optional<int64_t> RelocAdjustment =
getExprOpAddressRelocAdjustment(*U, Op,
AttrOffset + CurExprOffset,
AttrOffset + Op.getEndOffset()))
return std::make_pair(HasLocationAddress, *RelocAdjustment);
} break;
case dwarf::DW_OP_constx:
case dwarf::DW_OP_addrx: {
HasLocationAddress = true;
if (std::optional<uint64_t> AddressOffset =
DIE.getDwarfUnit()->getIndexedAddressOffset(
Op.getRawOperand(0))) {
// Check relocation for the address.
if (std::optional<int64_t> RelocAdjustment =
getExprOpAddressRelocAdjustment(
*U, Op, *AddressOffset,
*AddressOffset +
DIE.getDwarfUnit()->getAddressByteSize()))
return std::make_pair(HasLocationAddress, *RelocAdjustment);
}
} break;
default: {
// Nothing to do.
} break;
}
CurExprOffset = Op.getEndOffset();
}

return std::make_pair(HasLocationAddress, std::nullopt);
}

protected:
inline bool isTlsAddressCode(uint8_t DW_OP_Code) {
return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
}
};

} // end of namespace dwarflinker_parallel
Expand Down
11 changes: 1 addition & 10 deletions llvm/include/llvm/DWARFLinkerParallel/DWARFFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,7 @@ class DWARFFile {

DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
std::unique_ptr<AddressesMap> Addresses,
UnloadCallbackTy UnloadFunc = nullptr)
: FileName(Name), Dwarf(std::move(Dwarf)),
Addresses(std::move(Addresses)), UnloadFunc(UnloadFunc) {
if (this->Dwarf)
Endianess = this->Dwarf->isLittleEndian() ? support::endianness::little
: support::endianness::big;
}
UnloadCallbackTy UnloadFunc = nullptr);

/// Object file name.
StringRef FileName;
Expand All @@ -46,9 +40,6 @@ class DWARFFile {
/// Helpful address information(list of valid address ranges, relocations).
std::unique_ptr<AddressesMap> Addresses;

/// Endiannes of source DWARF information.
support::endianness Endianess = support::endianness::little;

/// Callback to the module keeping object file to unload.
UnloadCallbackTy UnloadFunc;

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class DWARFLinker {
const Twine &Warning, StringRef Context, const DWARFDie *DIE)>;
using ObjFileLoaderTy = std::function<ErrorOr<DWARFFile &>(
StringRef ContainerName, StringRef Path)>;
using InputVerificationHandlerTy = std::function<void(const DWARFFile &File)>;
using InputVerificationHandlerTy = std::function<void(const DWARFFile &File, llvm::StringRef Output)>;
using ObjectPrefixMapTy = std::map<std::string, std::string>;
using CompileUnitHandlerTy = function_ref<void(const DWARFUnit &Unit)>;
using TranslatorFuncTy = std::function<StringRef(StringRef)>;
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/DWARFLinkerParallel/StringPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace dwarflinker_parallel {

/// StringEntry keeps data of the string: the length, external offset
/// and a string body which is placed right after StringEntry.
using StringEntry = StringMapEntry<DwarfStringPoolEntry *>;
using StringEntry = StringMapEntry<std::nullopt_t>;

class StringPoolEntryInfo {
public:
Expand Down Expand Up @@ -64,6 +64,8 @@ class StringPool

parallel::PerThreadBumpPtrAllocator &getAllocatorRef() { return Allocator; }

void clear() { Allocator.Reset(); }

private:
parallel::PerThreadBumpPtrAllocator Allocator;
};
Expand Down
88 changes: 0 additions & 88 deletions llvm/include/llvm/DWARFLinkerParallel/StringTable.h

This file was deleted.

1 change: 1 addition & 0 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class DwarfStreamer;

class DWARFDebugMacro {
friend DwarfStreamer;
friend dwarflinker_parallel::CompileUnit;

/// DWARFv5 section 6.3.1 Macro Information Header.
enum HeaderFlagMask {
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/DWARFLinker/DWARFLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,10 @@ DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,

const DWARFExpression::Operation &Op = *It;
switch (Op.getCode()) {
case dwarf::DW_OP_const2u:
case dwarf::DW_OP_const4u:
case dwarf::DW_OP_const8u:
case dwarf::DW_OP_const2s:
case dwarf::DW_OP_const4s:
case dwarf::DW_OP_const8s:
if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))
Expand Down Expand Up @@ -3037,11 +3039,13 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
void DWARFLinker::verifyInput(const DWARFFile &File) {
assert(File.Dwarf);

raw_ostream &os = Options.Verbose ? errs() : nulls();

std::string Buffer;
raw_string_ostream OS(Buffer);
DIDumpOptions DumpOpts;
if (!File.Dwarf->verify(os, DumpOpts.noImplicitRecursion())) {
if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
if (Options.InputVerificationHandler)
Options.InputVerificationHandler(File);
Options.InputVerificationHandler(File, OS.str());
}
}

Expand Down
Loading