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

1

2

3

4

5

6

7

8

13

14using namespace llvm;

15using namespace dwarf_linker;

16using namespace dwarf_linker::parallel;

17

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

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

23 RefDieIdxOrClonedOffset(RefIdx) {}

24

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

31 RefDieIdxOrClonedOffset(RefIdx) {}

32

36

42 RefTypeName(RefTypeName) {}

43

48

54

58 : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}

59

63 ListDebugStrPatch.erase();

64 ListDebugLineStrPatch.erase();

65 ListDebugRangePatch.erase();

66 ListDebugLocPatch.erase();

67 ListDebugDieRefPatch.erase();

68 ListDebugULEB128DieRefPatch.erase();

69 ListDebugOffsetPatch.erase();

70 ListDebugType2TypeDieRefPatch.erase();

71 ListDebugTypeDeclFilePatch.erase();

72 ListDebugTypeLineStrPatch.erase();

73 ListDebugTypeStrPatch.erase();

74}

75

77

80 return;

81

85 if (!Obj) {

88 return;

89 }

90

93 if (!SectNameOrErr) {

95 continue;

96 }

97 if (std::optional SectKind =

104 return;

105 }

106

111 }

112 }

113 }

114}

115

117 const char *StringVal) {

118 assert(StringVal != nullptr);

119

120 switch (StringForm) {

121 case dwarf::DW_FORM_string: {

123 } break;

124 case dwarf::DW_FORM_strp: {

128 } break;

129 case dwarf::DW_FORM_line_strp: {

133 } break;

134 default:

136 break;

137 };

138}

139

141 switch (Size) {

142 case 1: {

144 } break;

145 case 2: {

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

150 } break;

151 case 4: {

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

156 } break;

157 case 8: {

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

161 } break;

162 default:

164 }

165}

166

169}

170

173 switch (AttrForm) {

174 case dwarf::DW_FORM_strp:

175 case dwarf::DW_FORM_line_strp: {

177 } break;

178

179 case dwarf::DW_FORM_ref_addr: {

181 } break;

182 case dwarf::DW_FORM_ref1: {

184 } break;

185 case dwarf::DW_FORM_ref2: {

187 } break;

188 case dwarf::DW_FORM_ref4: {

190 } break;

191 case dwarf::DW_FORM_ref8: {

193 } break;

194

195 case dwarf::DW_FORM_data1: {

197 } break;

198 case dwarf::DW_FORM_data2: {

200 } break;

201 case dwarf::DW_FORM_data4: {

203 } break;

204 case dwarf::DW_FORM_data8: {

206 } break;

207 case dwarf::DW_FORM_udata: {

209 } break;

210 case dwarf::DW_FORM_sdata: {

212 } break;

213 case dwarf::DW_FORM_sec_offset: {

215 } break;

216 case dwarf::DW_FORM_flag: {

218 } break;

219

220 default:

222 break;

223 }

224}

225

228 switch (Size) {

229 case 1: {

230 return *reinterpret_cast<const uint8_t *>(

232 }

233 case 2: {

236 }

237 case 4: {

240 }

241 case 8: {

244 }

245 }

247 return 0;

248}

249

251 unsigned Size) {

253

254 switch (Size) {

255 case 1: {

259 } break;

260 case 2: {

264 } break;

265 case 4: {

269 } break;

270 case 8: {

274 } break;

275 default:

277 }

278}

279

282

286

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

288 RealSize);

289}

290

291

294

298

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

300 RealSize);

301}

302

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

311 assert(Entry != nullptr);

312

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

314 });

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

316 assert(TypeUnitPtr != nullptr);

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

320 .str()

321 .c_str());

322

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

324 return;

325

328 assert(Entry != nullptr);

329

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

332

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

334 });

335

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

339 assert(Entry != nullptr);

340

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

342 });

344 assert(TypeUnitPtr != nullptr);

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

348 .str()

349 .c_str());

350

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

352 return;

353

356 assert(Entry != nullptr);

357

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

360

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

362 });

363

364 std::optional<SectionDescriptor *> RangeSection;

367 else

369

370 if (RangeSection) {

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

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

375

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

377 });

378 }

379

380 std::optional<SectionDescriptor *> LocationSection;

383 else

385

386 if (LocationSection) {

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

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

391

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

393 });

394 }

395

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

397 uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;

398 dwarf::Form FinalForm = dwarf::DW_FORM_ref4;

399

400

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

402 SectionDescriptor &ReferencedSectionDescriptor =

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

404 DebugSectionKind::DebugInfo);

405

406 FinalForm = dwarf::DW_FORM_ref_addr;

407 FinalOffset += ReferencedSectionDescriptor.StartOffset;

408 }

409

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

411 });

412

413 Section.ListDebugULEB128DieRefPatch.forEach(

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

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

417 Patch.RefDieIdxOrClonedOffset);

418 });

419

421 assert(TypeUnitPtr != nullptr);

422 assert(Patch.RefTypeName != nullptr);

423

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

427 .str()

428 .c_str());

429

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

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

432 });

433

434 Section.ListDebugType2TypeDieRefPatch.forEach(

436 assert(TypeUnitPtr != nullptr);

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

440 .str()

441 .c_str());

442

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

444 return;

445

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

448

449 assert(Patch.RefTypeName != nullptr);

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

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

453 .str()

454 .c_str());

455

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

458 });

459

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

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

462

463

464 if (Patch.SectionPtr.getInt())

465 FinalValue +=

467

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

469 });

470}

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...

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.

SectionKind - This is a simple POD value that classifies the properties of a section.

pointer data()

Return a pointer to the vector's buffer, even if empty().

StringMapEntry - This is used to represent one value that is inserted into a StringMap.

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

StringPool & getStringPool()

Returns global string pool.

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

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

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

uint64_t tell() const

tell - Return the current offset with the file.

raw_ostream & write(unsigned char C)

#define llvm_unreachable(msg)

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

SmallString< 0 > OutSectionDataTy

Type for section data.

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

Recognise the table name and match it with the DebugSectionKind.

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)

unsigned getULEB128Size(uint64_t Value)

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

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.

uint8_t getDwarfOffsetByteSize() const

The size of a reference is determined by the DWARF 32/64-bit format.

uint8_t getRefAddrByteSize() const

The definition of the size of form DW_FORM_ref_addr depends on the version.

This structure is used to update reference to the DIE.

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

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

DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName)

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)

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

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

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

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

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

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.

OutSectionDataTy Contents

Section data bits.

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

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

Writes integer value Val of Size by specified PatchOffset.

void emitIntVal(uint64_t Val, unsigned Size)

Emit specified integer value into the current section contents.

void applySLEB128(uint64_t PatchOffset, uint64_t Val)

Writes integer value Val of SLEB128 format by specified PatchOffset.

void applyULEB128(uint64_t PatchOffset, uint64_t Val)

Writes integer value Val of ULEB128 format by specified PatchOffset.

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

Write specified Value of AttrForm to the PatchOffset.

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.

void clearSectionContent()

Erase only section output data bits.

void emitBinaryData(llvm::StringRef Data)

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

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.