LLVM: lib/DWARFLinker/Parallel/OutputSections.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

12

13using namespace llvm;

16

20 RefCU(RefCU, (SrcCU != nullptr) &&

21 (SrcCU->getUniqueID() == RefCU->getUniqueID())),

22 RefDieIdxOrClonedOffset(RefIdx) {}

23

29 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),

30 RefDieIdxOrClonedOffset(RefIdx) {}

31

35

41 RefTypeName(RefTypeName) {}

42

47

53

58

62 ListDebugStrPatch.erase();

63 ListDebugLineStrPatch.erase();

64 ListDebugRangePatch.erase();

65 ListDebugLocPatch.erase();

66 ListDebugDieRefPatch.erase();

67 ListDebugULEB128DieRefPatch.erase();

68 ListDebugOffsetPatch.erase();

69 ListDebugType2TypeDieRefPatch.erase();

70 ListDebugTypeDeclFilePatch.erase();

71 ListDebugTypeLineStrPatch.erase();

72 ListDebugTypeStrPatch.erase();

73}

74

76

79 return;

80

84 if (!Obj) {

87 return;

88 }

89

92 if (!SectNameOrErr) {

94 continue;

95 }

96 if (std::optional SectKind =

103 return;

104 }

105

110 }

111 }

112 }

113}

114

116 const char *StringVal) {

117 assert(StringVal != nullptr);

118

119 switch (StringForm) {

120 case dwarf::DW_FORM_string: {

122 } break;

123 case dwarf::DW_FORM_strp: {

125 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});

127 } break;

128 case dwarf::DW_FORM_line_strp: {

130 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});

132 } break;

133 default:

135 break;

136 };

137}

138

140 switch (Size) {

141 case 1: {

142 OS.write(static_cast<uint8_t>(Val));

143 } break;

144 case 2: {

148 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);

149 } break;

150 case 4: {

154 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);

155 } break;

156 case 8: {

159 OS.write(reinterpret_cast<const char *>(&Val), Size);

160 } break;

161 default:

163 }

164}

165

169

172 switch (AttrForm) {

173 case dwarf::DW_FORM_strp:

174 case dwarf::DW_FORM_line_strp: {

176 } break;

177

178 case dwarf::DW_FORM_ref_addr: {

180 } break;

181 case dwarf::DW_FORM_ref1: {

183 } break;

184 case dwarf::DW_FORM_ref2: {

186 } break;

187 case dwarf::DW_FORM_ref4: {

189 } break;

190 case dwarf::DW_FORM_ref8: {

192 } break;

193

194 case dwarf::DW_FORM_data1: {

196 } break;

197 case dwarf::DW_FORM_data2: {

199 } break;

200 case dwarf::DW_FORM_data4: {

202 } break;

203 case dwarf::DW_FORM_data8: {

205 } break;

206 case dwarf::DW_FORM_udata: {

208 } break;

209 case dwarf::DW_FORM_sdata: {

211 } break;

212 case dwarf::DW_FORM_sec_offset: {

214 } break;

215 case dwarf::DW_FORM_flag: {

217 } break;

218

219 default:

221 break;

222 }

223}

224

227 switch (Size) {

228 case 1: {

229 return *reinterpret_cast<const uint8_t *>(

231 }

232 case 2: {

235 }

236 case 4: {

239 }

240 case 8: {

243 }

244 }

246 return 0;

247}

248

250 unsigned Size) {

252

253 switch (Size) {

254 case 1: {

258 } break;

259 case 2: {

263 } break;

264 case 4: {

268 } break;

269 case 8: {

273 } break;

274 default:

276 }

277}

278

281

283 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;

285

286 memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,

287 RealSize);

288}

289

290

293

295 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;

297

298 memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,

299 RealSize);

300}

301

307 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {

310 assert(Entry != nullptr);

311

312 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);

313 });

314 Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {

315 assert(TypeUnitPtr != nullptr);

318 formatv("No data for type {0}", Patch.TypeName->getKey())

319 .str()

320 .c_str());

321

322 if (&TypeEntry->getFinalDie() != Patch.Die)

323 return;

324

327 assert(Entry != nullptr);

328

330 Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());

331

332 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);

333 });

334

335 Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {

338 assert(Entry != nullptr);

339

340 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);

341 });

343 assert(TypeUnitPtr != nullptr);

346 formatv("No data for type {0}", Patch.TypeName->getKey())

347 .str()

348 .c_str());

349

350 if (&TypeEntry->getFinalDie() != Patch.Die)

351 return;

352

355 assert(Entry != nullptr);

356

358 Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());

359

360 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);

361 });

362

363 std::optional<SectionDescriptor *> RangeSection;

364 if (Format.Version >= 5)

366 else

368

369 if (RangeSection) {

370 Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {

372 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());

373 FinalValue += (*RangeSection)->StartOffset;

374

375 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);

376 });

377 }

378

379 std::optional<SectionDescriptor *> LocationSection;

380 if (Format.Version >= 5)

382 else

384

385 if (LocationSection) {

386 Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {

388 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());

389 FinalValue += (*LocationSection)->StartOffset;

390

391 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);

392 });

393 }

394

395 Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {

396 uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;

397 dwarf::Form FinalForm = dwarf::DW_FORM_ref4;

398

399

400 if (!Patch.RefCU.getInt()) {

402 Patch.RefCU.getPointer()->getSectionDescriptor(

404

405 FinalForm = dwarf::DW_FORM_ref_addr;

406 FinalOffset += ReferencedSectionDescriptor.StartOffset;

407 }

408

409 Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);

410 });

411

412 Section.ListDebugULEB128DieRefPatch.forEach(

414 assert(Patch.RefCU.getInt());

415 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,

416 Patch.RefDieIdxOrClonedOffset);

417 });

418

420 assert(TypeUnitPtr != nullptr);

421 assert(Patch.RefTypeName != nullptr);

422

425 formatv("No data for type {0}", Patch.RefTypeName->getKey())

426 .str()

427 .c_str());

428

429 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,

430 TypeEntry->getFinalDie().getOffset());

431 });

432

433 Section.ListDebugType2TypeDieRefPatch.forEach(

435 assert(TypeUnitPtr != nullptr);

438 formatv("No data for type {0}", Patch.TypeName->getKey())

439 .str()

440 .c_str());

441

442 if (&TypeEntry->getFinalDie() != Patch.Die)

443 return;

444

445 Patch.PatchOffset += Patch.Die->getOffset() +

447

448 assert(Patch.RefTypeName != nullptr);

449 TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();

451 formatv("No data for type {0}", Patch.RefTypeName->getKey())

452 .str()

453 .c_str());

454

455 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,

457 });

458

459 Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {

460 uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;

461

462

463 if (Patch.SectionPtr.getInt())

464 FinalValue +=

465 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());

466

467 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);

468 });

469}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

A structured debug information entry.

unsigned getOffset() const

Get the compile/type unit relative offset of this DIE.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

StringRef - Represent a constant reference to a string, i.e.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

Stores all information related to a compile unit, be it in its original instance of the object file o...

void applyPatches(SectionDescriptor &Section, StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, TypeUnit *TypeUnitPtr)

Enumerate all sections, for each section apply all section patches.

Definition OutputSections.cpp:302

dwarf::FormParams Format

Format for sections.

std::optional< const SectionDescriptor * > tryGetSectionDescriptor(DebugSectionKind SectionKind) const

Returns descriptor for the specified section of SectionKind.

This class creates a DwarfStringPoolEntry for the corresponding StringEntry.

DwarfStringPoolEntryWithExtString * getExistingEntry(const StringEntry *String) const

Returns already existed DwarfStringPoolEntry for the specified StringEntry.

Keeps cloned data for the type DIE.

DIE & getFinalDie() const

Returns copy of type DIE which should be emitted into resulting file.

Type Unit is used to represent an artificial compilation unit which keeps all type information.

static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)

This is a value type class that represents a single section in the list of sections in the object fil...

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

SmallString< 0 > OutSectionDataTy

Type for section data.

StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry

LLVM_ABI std::optional< DebugSectionKind > parseDebugTableName(StringRef Name)

Recognise the table name and match it with the DebugSectionKind.

StringMapEntry< EmptyStringSetTag > StringEntry

StringEntry keeps data of the string: the length, external offset and a string body which is placed r...

uint32_t read32(const void *P, endianness E)

uint64_t read64(const void *P, endianness E)

void write(void *memory, value_type value, endianness endian)

Write a value to memory with a particular endianness.

uint16_t read16(const void *P, endianness E)

void swapByteOrder(T &Value)

This is an optimization pass for GlobalISel generic memory operations.

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

LLVM_ABI unsigned getULEB128Size(uint64_t Value)

Utility function to get the size of the ULEB128-encoded value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a SLEB128 value to an output stream.

unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a ULEB128 value to an output stream.

void consumeError(Error Err)

Consume a Error without doing anything.

DwarfStringPoolEntry with string keeping externally.

This structure is used to update reference to the DIE.

PointerIntPair< CompileUnit *, 1 > RefCU

DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, uint32_t RefIdx)

Definition OutputSections.cpp:17

This structure is used to update reference to the type DIE.

DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName)

Definition OutputSections.cpp:32

This structure is used to update strings offsets into .debug_line_str.

This structure is used to update location list offset into .debug_loc/.debug_loclists.

This structure is used to update range list offset into .debug_ranges/.debug_rnglists.

This structure is used to update strings offsets into .debug_str.

const StringEntry * String

This structure is used to update reference to the type DIE.

DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, TypeEntry *RefTypeName)

Definition OutputSections.cpp:36

DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory, StringEntry *FilePath)

Definition OutputSections.cpp:54

DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, StringEntry *String)

Definition OutputSections.cpp:48

DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, StringEntry *String)

Definition OutputSections.cpp:43

This structure is used to update reference to the DIE of ULEB128 form.

DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, uint32_t RefIdx)

Definition OutputSections.cpp:24

PointerIntPair< CompileUnit *, 1 > RefCU

DebugSectionKind SectionKind

The section kind.

llvm::endianness Endianess

dwarf::FormParams Format

Output format.

This structure is used to keep data of the concrete section.

raw_svector_ostream OS

Stream which stores data to the Contents.

void setSizesForSectionCreatedByAsmPrinter()

Some sections are emitted using AsmPrinter.

Definition OutputSections.cpp:77

OutSectionDataTy Contents

Section data bits.

void emitString(dwarf::Form StringForm, const char *StringVal)

Definition OutputSections.cpp:115

void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size)

Writes integer value Val of Size by specified PatchOffset.

Definition OutputSections.cpp:249

void emitIntVal(uint64_t Val, unsigned Size)

Emit specified integer value into the current section contents.

Definition OutputSections.cpp:139

void applySLEB128(uint64_t PatchOffset, uint64_t Val)

Writes integer value Val of SLEB128 format by specified PatchOffset.

Definition OutputSections.cpp:291

void applyULEB128(uint64_t PatchOffset, uint64_t Val)

Writes integer value Val of ULEB128 format by specified PatchOffset.

Definition OutputSections.cpp:279

void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)

Write specified Value of AttrForm to the PatchOffset.

Definition OutputSections.cpp:170

void emitInplaceString(StringRef String)

Emit specified inplace string value into the current section contents.

uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)

Returns integer value of Size located by specified PatchOffset.

Definition OutputSections.cpp:225

void clearSectionContent()

Erase only section output data bits.

Definition OutputSections.cpp:75

void emitBinaryData(llvm::StringRef Data)

Definition OutputSections.cpp:166

StringRef getContents() override

Returns section content.

size_t SectionOffsetInsideAsmPrinterOutputStart

Some sections are generated using AsmPrinter.

void clearAllSectionData()

Erase whole section content(data bits, list of patches).

Definition OutputSections.cpp:59

size_t SectionOffsetInsideAsmPrinterOutputEnd

void emitStringPlaceholder()

Emit string placeholder into the current section contents.

LinkingGlobalData & GlobalData

uint64_t StartOffset

When objects(f.e.

There are fields(sizes, offsets) which should be updated after sections are generated.