Skip to content

Commit 934601b

Browse files
Merge pull request #8094 from felipepiovezan/felipe/cherry-picks-debugnames1
[Cherry-pick] Patches related to dwarf linker
2 parents 155cbe1 + d040b86 commit 934601b

File tree

137 files changed

+8440
-1054
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+8440
-1054
lines changed

llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,34 @@ struct DwarfStringPoolEntry {
2727
bool isIndexed() const { return Index != NotIndexed; }
2828
};
2929

30+
/// DwarfStringPoolEntry with string keeping externally.
31+
struct DwarfStringPoolEntryWithExtString : public DwarfStringPoolEntry {
32+
StringRef String;
33+
};
34+
3035
/// DwarfStringPoolEntryRef: Dwarf string pool entry reference.
3136
///
3237
/// Dwarf string pool entry keeps string value and its data.
3338
/// There are two variants how data are represented:
3439
///
35-
/// 1. By value - StringMapEntry<DwarfStringPoolEntry>.
36-
/// 2. By pointer - StringMapEntry<DwarfStringPoolEntry *>.
40+
/// 1. String data in pool - StringMapEntry<DwarfStringPoolEntry>.
41+
/// 2. External string data - DwarfStringPoolEntryWithExtString.
3742
///
38-
/// The "By pointer" variant allows for reducing memory usage for the case
39-
/// when string pool entry does not have data: it keeps the null pointer
40-
/// and so no need to waste space for the full DwarfStringPoolEntry.
41-
/// It is recommended to use "By pointer" variant if not all entries
42-
/// of dwarf string pool have corresponding DwarfStringPoolEntry.
43+
/// The external data variant allows reducing memory usage for the case
44+
/// when string pool entry does not have data: string entry does not
45+
/// keep any data and so no need to waste space for the full
46+
/// DwarfStringPoolEntry. It is recommended to use external variant if not all
47+
/// entries of dwarf string pool have corresponding DwarfStringPoolEntry.
4348

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

48-
/// Pointer type for "By pointer" string entry.
49-
using ByPtrStringEntryPtr = const StringMapEntry<DwarfStringPoolEntry *> *;
53+
/// Pointer type for external string entry.
54+
using ExtStringEntryPtr = const DwarfStringPoolEntryWithExtString *;
5055

5156
/// Pointer to the dwarf string pool Entry.
52-
PointerUnion<ByValStringEntryPtr, ByPtrStringEntryPtr> MapEntry = nullptr;
57+
PointerUnion<ByValStringEntryPtr, ExtStringEntryPtr> MapEntry = nullptr;
5358

5459
public:
5560
DwarfStringPoolEntryRef() = default;
@@ -61,10 +66,8 @@ class DwarfStringPoolEntryRef {
6166

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

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

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

91-
return cast<ByPtrStringEntryPtr>(MapEntry)->first();
94+
return cast<ExtStringEntryPtr>(MapEntry)->String;
9295
}
9396

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

99-
return *cast<ByPtrStringEntryPtr>(MapEntry)->second;
102+
return *cast<ExtStringEntryPtr>(MapEntry);
100103
}
101104

102105
bool operator==(const DwarfStringPoolEntryRef &X) const {

llvm/include/llvm/DWARFLinker/DWARFLinker.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,9 @@ using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
287287
/// and its address map.
288288
class DWARFFile {
289289
public:
290+
using UnloadCallbackTy = std::function<void(StringRef FileName)>;
290291
DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
291-
std::unique_ptr<AddressesMap> Addresses)
292+
std::unique_ptr<AddressesMap> Addresses, UnloadCallbackTy = nullptr)
292293
: FileName(Name), Dwarf(std::move(Dwarf)),
293294
Addresses(std::move(Addresses)) {}
294295

@@ -357,7 +358,7 @@ class DWARFLinker {
357358
Pub, ///< .debug_pubnames, .debug_pubtypes
358359
DebugNames ///< .debug_names.
359360
};
360-
typedef std::function<void(const DWARFFile &File)> inputVerificationHandler;
361+
typedef std::function<void(const DWARFFile &File, llvm::StringRef Output)> inputVerificationHandler;
361362
typedef std::function<ErrorOr<DWARFFile &>(StringRef ContainerName,
362363
StringRef Path)>
363364
objFileLoader;

llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#define LLVM_DWARFLINKERPARALLEL_ADDRESSESMAP_H
1111

1212
#include "llvm/ADT/AddressRanges.h"
13+
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
1314
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
1415
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
16+
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
1517
#include <cstdint>
1618

1719
namespace llvm {
@@ -80,6 +82,108 @@ class AddressesMap {
8082

8183
/// Erases all data.
8284
virtual void clear() = 0;
85+
86+
/// This function checks whether variable has DWARF expression containing
87+
/// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
88+
/// \returns first is true if the expression has an operation referencing an
89+
/// address.
90+
/// second is the relocation adjustment value if the live address is
91+
/// referenced.
92+
std::pair<bool, std::optional<int64_t>>
93+
getVariableRelocAdjustment(const DWARFDie &DIE) {
94+
assert((DIE.getTag() == dwarf::DW_TAG_variable ||
95+
DIE.getTag() == dwarf::DW_TAG_constant) &&
96+
"Wrong type of input die");
97+
98+
const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
99+
100+
// Check if DIE has DW_AT_location attribute.
101+
DWARFUnit *U = DIE.getDwarfUnit();
102+
std::optional<uint32_t> LocationIdx =
103+
Abbrev->findAttributeIndex(dwarf::DW_AT_location);
104+
if (!LocationIdx)
105+
return std::make_pair(false, std::nullopt);
106+
107+
// Get offset to the DW_AT_location attribute.
108+
uint64_t AttrOffset =
109+
Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
110+
111+
// Get value of the DW_AT_location attribute.
112+
std::optional<DWARFFormValue> LocationValue =
113+
Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
114+
if (!LocationValue)
115+
return std::make_pair(false, std::nullopt);
116+
117+
// Check that DW_AT_location attribute is of 'exprloc' class.
118+
// Handling value of location expressions for attributes of 'loclist'
119+
// class is not implemented yet.
120+
std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
121+
if (!Expr)
122+
return std::make_pair(false, std::nullopt);
123+
124+
// Parse 'exprloc' expression.
125+
DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
126+
U->getAddressByteSize());
127+
DWARFExpression Expression(Data, U->getAddressByteSize(),
128+
U->getFormParams().Format);
129+
130+
bool HasLocationAddress = false;
131+
uint64_t CurExprOffset = 0;
132+
for (DWARFExpression::iterator It = Expression.begin();
133+
It != Expression.end(); ++It) {
134+
DWARFExpression::iterator NextIt = It;
135+
++NextIt;
136+
137+
const DWARFExpression::Operation &Op = *It;
138+
switch (Op.getCode()) {
139+
case dwarf::DW_OP_const2u:
140+
case dwarf::DW_OP_const4u:
141+
case dwarf::DW_OP_const8u:
142+
case dwarf::DW_OP_const2s:
143+
case dwarf::DW_OP_const4s:
144+
case dwarf::DW_OP_const8s:
145+
if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))
146+
break;
147+
[[fallthrough]];
148+
case dwarf::DW_OP_addr: {
149+
HasLocationAddress = true;
150+
// Check relocation for the address.
151+
if (std::optional<int64_t> RelocAdjustment =
152+
getExprOpAddressRelocAdjustment(*U, Op,
153+
AttrOffset + CurExprOffset,
154+
AttrOffset + Op.getEndOffset()))
155+
return std::make_pair(HasLocationAddress, *RelocAdjustment);
156+
} break;
157+
case dwarf::DW_OP_constx:
158+
case dwarf::DW_OP_addrx: {
159+
HasLocationAddress = true;
160+
if (std::optional<uint64_t> AddressOffset =
161+
DIE.getDwarfUnit()->getIndexedAddressOffset(
162+
Op.getRawOperand(0))) {
163+
// Check relocation for the address.
164+
if (std::optional<int64_t> RelocAdjustment =
165+
getExprOpAddressRelocAdjustment(
166+
*U, Op, *AddressOffset,
167+
*AddressOffset +
168+
DIE.getDwarfUnit()->getAddressByteSize()))
169+
return std::make_pair(HasLocationAddress, *RelocAdjustment);
170+
}
171+
} break;
172+
default: {
173+
// Nothing to do.
174+
} break;
175+
}
176+
CurExprOffset = Op.getEndOffset();
177+
}
178+
179+
return std::make_pair(HasLocationAddress, std::nullopt);
180+
}
181+
182+
protected:
183+
inline bool isTlsAddressCode(uint8_t DW_OP_Code) {
184+
return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
185+
DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
186+
}
83187
};
84188

85189
} // end of namespace dwarflinker_parallel

llvm/include/llvm/DWARFLinkerParallel/DWARFFile.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,7 @@ class DWARFFile {
2929

3030
DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
3131
std::unique_ptr<AddressesMap> Addresses,
32-
UnloadCallbackTy UnloadFunc = nullptr)
33-
: FileName(Name), Dwarf(std::move(Dwarf)),
34-
Addresses(std::move(Addresses)), UnloadFunc(UnloadFunc) {
35-
if (this->Dwarf)
36-
Endianess = this->Dwarf->isLittleEndian() ? support::endianness::little
37-
: support::endianness::big;
38-
}
32+
UnloadCallbackTy UnloadFunc = nullptr);
3933

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

49-
/// Endiannes of source DWARF information.
50-
support::endianness Endianess = support::endianness::little;
51-
5243
/// Callback to the module keeping object file to unload.
5344
UnloadCallbackTy UnloadFunc;
5445

llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class DWARFLinker {
134134
const Twine &Warning, StringRef Context, const DWARFDie *DIE)>;
135135
using ObjFileLoaderTy = std::function<ErrorOr<DWARFFile &>(
136136
StringRef ContainerName, StringRef Path)>;
137-
using InputVerificationHandlerTy = std::function<void(const DWARFFile &File)>;
137+
using InputVerificationHandlerTy = std::function<void(const DWARFFile &File, llvm::StringRef Output)>;
138138
using ObjectPrefixMapTy = std::map<std::string, std::string>;
139139
using CompileUnitHandlerTy = function_ref<void(const DWARFUnit &Unit)>;
140140
using TranslatorFuncTy = std::function<StringRef(StringRef)>;

llvm/include/llvm/DWARFLinkerParallel/StringPool.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace dwarflinker_parallel {
2121

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

2626
class StringPoolEntryInfo {
2727
public:
@@ -64,6 +64,8 @@ class StringPool
6464

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

67+
void clear() { Allocator.Reset(); }
68+
6769
private:
6870
parallel::PerThreadBumpPtrAllocator Allocator;
6971
};

llvm/include/llvm/DWARFLinkerParallel/StringTable.h

Lines changed: 0 additions & 88 deletions
This file was deleted.

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class DwarfStreamer;
2222

2323
class DWARFDebugMacro {
2424
friend DwarfStreamer;
25+
friend dwarflinker_parallel::CompileUnit;
2526

2627
/// DWARFv5 section 6.3.1 Macro Information Header.
2728
enum HeaderFlagMask {

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,10 @@ DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
463463

464464
const DWARFExpression::Operation &Op = *It;
465465
switch (Op.getCode()) {
466+
case dwarf::DW_OP_const2u:
466467
case dwarf::DW_OP_const4u:
467468
case dwarf::DW_OP_const8u:
469+
case dwarf::DW_OP_const2s:
468470
case dwarf::DW_OP_const4s:
469471
case dwarf::DW_OP_const8s:
470472
if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))
@@ -3037,11 +3039,13 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
30373039
void DWARFLinker::verifyInput(const DWARFFile &File) {
30383040
assert(File.Dwarf);
30393041

3040-
raw_ostream &os = Options.Verbose ? errs() : nulls();
3042+
3043+
std::string Buffer;
3044+
raw_string_ostream OS(Buffer);
30413045
DIDumpOptions DumpOpts;
3042-
if (!File.Dwarf->verify(os, DumpOpts.noImplicitRecursion())) {
3046+
if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
30433047
if (Options.InputVerificationHandler)
3044-
Options.InputVerificationHandler(File);
3048+
Options.InputVerificationHandler(File, OS.str());
30453049
}
30463050
}
30473051

0 commit comments

Comments
 (0)