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

1

2

3

4

5

6

7

8

11

12using namespace llvm;

15

17

19

21

22

23

26 : InUnit.getOrigUnit().getNextUnitOffset();

27

28

29

30

34

35

36 InUnit.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,

37 Data.isLittleEndian());

38

39

40

42

43 const auto *Abbrev = InputDieEntry->getAbbreviationDeclarationPtr();

45

46

48 for (const auto &AttrSpec : Abbrev->attributes()) {

49

52 InUnit.getFormParams());

53 continue;

54 }

55

58 &InUnit.getOrigUnit());

59

60

61 switch (AttrSpec.Form) {

62 case dwarf::DW_FORM_strp:

63 case dwarf::DW_FORM_line_strp:

64 case dwarf::DW_FORM_string:

65 case dwarf::DW_FORM_strx:

66 case dwarf::DW_FORM_strx1:

67 case dwarf::DW_FORM_strx2:

68 case dwarf::DW_FORM_strx3:

69 case dwarf::DW_FORM_strx4:

71 break;

72 case dwarf::DW_FORM_ref_addr:

73 case dwarf::DW_FORM_ref1:

74 case dwarf::DW_FORM_ref2:

75 case dwarf::DW_FORM_ref4:

76 case dwarf::DW_FORM_ref8:

77 case dwarf::DW_FORM_ref_udata:

79 break;

80 case dwarf::DW_FORM_data1:

81 case dwarf::DW_FORM_data2:

82 case dwarf::DW_FORM_data4:

83 case dwarf::DW_FORM_data8:

84 case dwarf::DW_FORM_udata:

85 case dwarf::DW_FORM_sdata:

86 case dwarf::DW_FORM_sec_offset:

87 case dwarf::DW_FORM_flag:

88 case dwarf::DW_FORM_flag_present:

89 case dwarf::DW_FORM_rnglistx:

90 case dwarf::DW_FORM_loclistx:

91 case dwarf::DW_FORM_implicit_const:

93 break;

94 case dwarf::DW_FORM_block:

95 case dwarf::DW_FORM_block1:

96 case dwarf::DW_FORM_block2:

97 case dwarf::DW_FORM_block4:

98 case dwarf::DW_FORM_exprloc:

100 break;

101 case dwarf::DW_FORM_addr:

102 case dwarf::DW_FORM_addrx:

103 case dwarf::DW_FORM_addrx1:

104 case dwarf::DW_FORM_addrx2:

105 case dwarf::DW_FORM_addrx3:

106 case dwarf::DW_FORM_addrx4:

108 break;

109 default:

110 InUnit.warn("unsupported attribute form " +

112 " in DieAttributeCloner::clone(). Dropping.",

114 }

115 }

116

117

118

119

120 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&

121 InUnit.getVersion() >= 5 && AttrInfo.HasStringOffsetBaseAttr) {

124 &OutUnit->getOrCreateSectionDescriptor(

126 true},

128

131 .addScalarAttribute(dwarf::DW_AT_str_offsets_base,

132 dwarf::DW_FORM_sec_offset,

133 OutUnit->getDebugStrOffsetsHeaderSize())

134 .second;

135 }

136}

137

140 switch (AttrSpec.Attr) {

141 default:

142 return false;

143 case dwarf::DW_AT_low_pc:

144 case dwarf::DW_AT_high_pc:

145 case dwarf::DW_AT_ranges:

146 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)

147 return false;

148

149

150

153 case dwarf::DW_AT_rnglists_base:

154

155

156

157

158 return InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;

159 case dwarf::DW_AT_loclists_base:

160

161

162

163

164 return InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;

165 case dwarf::DW_AT_location:

166 case dwarf::DW_AT_frame_base:

167 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)

168 return false;

169

170

171

174

175

176

179 }

180}

181

187 InUnit.warn("cann't read string attribute.");

188 return 0;

189 }

190

192 InUnit.getGlobalData().getStringPool().insert(*String).first;

193

194

195 if (AttrSpec.Attr == dwarf::DW_AT_name)

196 AttrInfo.Name = StringInPool;

197 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||

198 AttrSpec.Attr == dwarf::DW_AT_linkage_name)

199 AttrInfo.MangledName = StringInPool;

200

201 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {

202 if (OutUnit.isTypeUnit()) {

205 StringInPool});

206 } else {

209 }

211 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)

212 .second;

213 }

214

216 if (OutUnit.isTypeUnit()) {

220 } else {

223 }

224

226 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)

227 .second;

228 }

229

231 .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,

232 OutUnit->getDebugStrIndex(StringInPool))

233 .second;

234}

235

239 if (AttrSpec.Attr == dwarf::DW_AT_sibling)

240 return 0;

241

242 std::optional RefDiePair =

244 if (!RefDiePair || !RefDiePair->DieEntry) {

245

247 return 0;

248 }

249

250 TypeEntry *RefTypeName = nullptr;

252 RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);

254 RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);

255

256 if (OutUnit.isTypeUnit()) {

257 assert(RefTypeName && "Type name for referenced DIE is not set");

259 "Type name for DIE is not set");

260

263 RefTypeName});

264

266 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)

267 .second;

268 }

269

270 if (RefTypeName) {

273

275 .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)

276 .second;

277 }

278

279

280 uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);

281

282

283 bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();

284

285

286 dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;

287

288

289

290 if (IsLocal && (OutDieOffset != 0))

291 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)

292 .second;

293

294

295

298 RefDiePair->CU,

299 RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},

301 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;

302}

303

307

308

309

310

311 switch (AttrSpec.Attr) {

312 case dwarf::DW_AT_macro_info: {

315 InUnit.getContaingFile().Dwarf->getDebugMacinfo();

317 return 0;

318

321 &OutUnit->getOrCreateSectionDescriptor(

324 }

325 } break;

326 case dwarf::DW_AT_macros: {

329 InUnit.getContaingFile().Dwarf->getDebugMacro();

331 return 0;

332

335 &OutUnit->getOrCreateSectionDescriptor(

338 }

339 } break;

340 case dwarf::DW_AT_stmt_list: {

345 } break;

346 case dwarf::DW_AT_str_offsets_base: {

349 &OutUnit->getOrCreateSectionDescriptor(

351 true},

353

354

355

356 AttrInfo.HasStringOffsetBaseAttr = true;

358 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,

359 OutUnit->getDebugStrOffsetsHeaderSize())

360 .second;

361 } break;

362 case dwarf::DW_AT_decl_file: {

363

364

365

366

367

368 if (OutUnit.isTypeUnit()) {

369 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =

370 InUnit.getDirAndFilenameFromLineTable(Val))

375 .getStringPool()

376 .insert(DirAndFilename->first)

377 .first,

379 .getStringPool()

380 .insert(DirAndFilename->second)

381 .first,

382 });

383 return 0;

384 }

385 } break;

386 default: {

387 } break;

388 };

389

391 if (AttrSpec.Attr == dwarf::DW_AT_const_value &&

392 (InputDieEntry->getTag() == dwarf::DW_TAG_variable ||

393 InputDieEntry->getTag() == dwarf::DW_TAG_constant))

394 AttrInfo.HasLiveAddress = true;

395

396 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {

398 Value = *OptionalValue;

400 Value = *OptionalValue;

402 Value = *OptionalValue;

403 else {

404 InUnit.warn("unsupported scalar attribute form. Dropping attribute.",

406 return 0;

407 }

408

409 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)

410 AttrInfo.IsDeclaration = true;

411

412 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)

414 .second;

415

417 .second;

418 }

419

421 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {

422

423

424

426 if (!Index) {

428 return 0;

429 }

430 std::optional<uint64_t> Offset =

431 InUnit.getOrigUnit().getRnglistOffset(*Index);

434 return 0;

435 }

436

438 ResultingForm = dwarf::DW_FORM_sec_offset;

439 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {

440

441

442

444 if (!Index) {

446 return 0;

447 }

448 std::optional<uint64_t> Offset =

449 InUnit.getOrigUnit().getLoclistOffset(*Index);

452 return 0;

453 }

454

456 ResultingForm = dwarf::DW_FORM_sec_offset;

457 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&

458 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {

459 if (OutUnit.isCompileUnit())

460 return 0;

461

462 std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();

463 if (!LowPC)

464 return 0;

465

466 Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;

467 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)

469 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)

472 Value = *OptionalValue;

473 else {

474 InUnit.warn("unsupported scalar attribute form. Dropping attribute.",

476 return 0;

477 }

478

479 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||

480 AttrSpec.Attr == dwarf::DW_AT_start_scope) {

481

484 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},

490 InUnit.getOrigUnit().getVersion())) {

491 int64_t AddrAdjustmentValue = 0;

496

497

500 } else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {

505 true},

507

508

509

511 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,

512 OutUnit->getDebugAddrHeaderSize())

513 .second;

514 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)

515 AttrInfo.IsDeclaration = true;

516

517 return Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value)

518 .second;

519}

520

524

525 if (OutUnit.isTypeUnit())

526 return 0;

527

528 size_t NumberOfPatchesAtStart = PatchesOffsets.size();

529

530

531

538 InUnit.getOrigUnit().isLittleEndian(),

539 InUnit.getOrigUnit().getAddressByteSize());

541 InUnit.getFormParams().Format);

542

545 Bytes = Buffer;

546 }

547

548

549

551 if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||

552 (ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||

553 (ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))

554 ResultForm = dwarf::DW_FORM_block;

555

556 size_t FinalAttributeSize;

557 if (AttrSpec.Form == dwarf::DW_FORM_exprloc)

558 FinalAttributeSize =

559 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;

560 else

561 FinalAttributeSize =

562 Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;

563

564

565 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();

566 Idx++) {

567 assert(FinalAttributeSize > Bytes.size());

570 }

571

575 InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;

576

577 return FinalAttributeSize;

578}

579

583 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)

584 AttrInfo.HasLiveAddress = true;

585

586 if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)

589 .second;

590

591 if (OutUnit.isTypeUnit())

592 return 0;

593

594

595

596

597

598

599

600

601

602

603

604

605

606 std::optional AddrAttribute =

608 if (!AddrAttribute)

610

611 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();

612 if (!Addr) {

613 InUnit.warn("cann't read address attribute value.");

614 return 0;

615 }

616

617 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&

618 AttrSpec.Attr == dwarf::DW_AT_low_pc) {

619 if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())

620 Addr = *LowPC;

621 else

622 return 0;

623 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&

624 AttrSpec.Attr == dwarf::DW_AT_high_pc) {

625 if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())

626 Addr = HighPc;

627 else

628 return 0;

629 } else {

634 }

635

636 if (AttrSpec.Form == dwarf::DW_FORM_addr) {

637 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)

638 .second;

639 }

640

642 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,

643 OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))

644 .second;

645}

646

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

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

LLVM_ABI std::optional< ArrayRef< uint8_t > > getAsBlock() const

LLVM_ABI std::optional< uint64_t > getAsSectionOffset() const

LLVM_ABI bool isFormClass(FormClass FC) const

LLVM_ABI std::optional< int64_t > getAsSignedConstant() const

LLVM_ABI bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context=nullptr, const DWARFUnit *Unit=nullptr)

Extracts a value in Data at offset *OffsetPtr.

LLVM_ABI std::optional< uint64_t > getAsUnsignedConstant() const

bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const

Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.

uint64_t getRawUValue() const

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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

LLVM Value Representation.

size_t cloneBlockAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)

Clone block or exprloc attribute.

Definition DIEAttributeCloner.cpp:521

AttributesInfo AttrInfo

Cannot be used concurrently.

CompileUnit & InUnit

Input compilation unit.

bool HasLocationExpressionAddress

Indicates whether InputDieEntry has an location attribute containg address expression.

SectionDescriptor & DebugInfoOutputSection

.debug_info section descriptor.

unsigned finalizeAbbreviations(bool HasChildrenToClone)

Create abbreviations for the output DIE after all attributes are cloned.

Definition DIEAttributeCloner.cpp:647

unsigned AttrOutOffset

Output offset after all attributes.

DIEGenerator & Generator

Output DIE generator.

size_t cloneScalarAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)

Clone scalar attribute.

Definition DIEAttributeCloner.cpp:304

OffsetsPtrVector PatchesOffsets

Patches for the cloned attributes.

void clone()

Clone attributes of input DIE.

Definition DIEAttributeCloner.cpp:16

size_t cloneDieRefAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)

Clone attribute referencing another DIE.

Definition DIEAttributeCloner.cpp:236

bool shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec)

Returns true if attribute should be skipped.

Definition DIEAttributeCloner.cpp:138

size_t cloneStringAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)

Clone string attribute.

Definition DIEAttributeCloner.cpp:182

const DWARFDebugInfoEntry * InputDieEntry

Input DIE entry.

std::optional< int64_t > FuncAddressAdjustment

Relocation adjustment for the function address ranges.

CompileUnit::OutputUnitVariantPtr OutUnit

Output unit(either "plain" compilation unit, either artificial type unit).

size_t cloneAddressAttr(const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec)

Clone address attribute.

Definition DIEAttributeCloner.cpp:580

uint32_t InputDIEIdx

Input DIE index.

std::optional< int64_t > VarAddressAdjustment

Relocation adjustment for the variable locations.

bool Use_DW_FORM_strp

This flag forces using DW_FORM_strp for string attributes.

LLVM_ABI StringRef FormEncodingString(unsigned Encoding)

#define llvm_unreachable(msg)

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

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

StringMapEntry< EmptyStringSetTag > StringEntry

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

std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)

Take an optional DWARFFormValue and try to extract a string value from it.

LLVM_ABI bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, uint16_t DwarfVersion)

Check whether specified Form belongs to the FC class.

This is an optimization pass for GlobalISel generic memory operations.

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

static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)

Identify DWARF attributes that may contain a pointer to a location list.

static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)

Identifies DWARF attributes that may contain a reference to a DWARF expression.

Information gathered about source DIEs.

bool needToPlaceInTypeTable() const

This structure is used to update reference to the DIE.

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

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.

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