LLVM: lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

32#include

33#include

34

35using namespace llvm;

39

40

42

44

46

47

48

49

50

51

53

55

58

61

62

63

64

67};

68

69

84 return LHS.RecordData == RHS.RecordData;

85 }

86};

87

88namespace {

90struct PublicSym32Layout {

93

94};

96}

97

98

101 NameLen = std::min(NameLen,

103 return alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);

104}

105

107

110 size_t Size = alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);

112 auto *FixedMem = reinterpret_cast<PublicSym32Layout *>(Mem);

113 FixedMem->Prefix.RecordKind = static_cast<uint16_t>(codeview::S_PUB32);

114 FixedMem->Prefix.RecordLen = static_cast<uint16_t>(Size - 2);

115 FixedMem->Pub.Flags = Pub.Flags;

116 FixedMem->Pub.Offset = Pub.Offset;

117 FixedMem->Pub.Segment = Pub.Segment;

118 char *NameMem = reinterpret_cast<char *>(FixedMem + 1);

119 memcpy(NameMem, Pub.Name, NameLen);

120

121 memset(&NameMem[NameLen], 0, Size - sizeof(PublicSym32Layout) - NameLen);

123}

124

132

139

141 return EC;

142

144 return EC;

146 return EC;

148 return EC;

150}

151

155

156

158 size_t LS = S1.size();

159 size_t RS = S2.size();

160

161 if (LS != RS)

162 return (LS > RS) - (LS < RS);

163

164

167

168

169 return S1.compare_insensitive(S2.data());

170}

171

172void GSIStreamBuilder::finalizePublicBuckets() {

173 PSH->finalizeBuckets(0, Publics);

174}

175

176void GSIStreamBuilder::finalizeGlobalBuckets(uint32_t RecordZeroOffset) {

177

178

179

180

181

182

183

184

185 std::vector Records;

187 uint32_t SymOffset = RecordZeroOffset;

188 for (size_t I = 0, E = Globals.size(); I < E; ++I) {

192 Records[I].SymOffset = SymOffset;

193 SymOffset += Globals[I].length();

194 }

195

196 GSH->finalizeBuckets(RecordZeroOffset, Records);

197}

198

201

203 Records[I].setBucketIdx(hashStringV1(Records[I].Name) % IPHR_HASH);

204 });

205

206

207

208

211 ++BucketStarts[P.BucketIdx];

213 for (uint32_t &B : BucketStarts) {

215 B = Sum;

217 }

218

219

220

221

224 memcpy(BucketCursors, BucketStarts, sizeof(BucketCursors));

225 for (int I = 0, E = Records.size(); I < E; ++I) {

226 uint32_t HashIdx = BucketCursors[Records[I].BucketIdx]++;

229 }

230

231

232

233

234

235

236

239 auto E = HashRecords.begin() + BucketCursors[I];

240 if (B == E)

241 return;

242 auto BucketCmp = [Records](const PSHashRecord &LHash,

246 assert(L.BucketIdx == R.BucketIdx);

247 int Cmp = gsiRecordCmp(L.getName(), R.getName());

248 if (Cmp != 0)

249 return Cmp < 0;

250

251

252

253 return L.SymOffset < R.SymOffset;

254 };

256

257

258

259

261 HRec.Off = Records[uint32_t(HRec.Off)].SymOffset + 1;

262 });

263

264

265

268 for (uint32_t J = 0; J < 32; ++J) {

269

272 BucketStarts[BucketIdx] == BucketCursors[BucketIdx])

273 continue;

274 Word |= (1U << J);

275

276

277

278

279 const int SizeOfHROffsetCalc = 12;

281 ulittle32_t(BucketStarts[BucketIdx] * SizeOfHROffsetCalc);

283 }

285 }

286}

287

291

293

294uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const {

297 Size += PSH->calculateSerializedLength();

298 Size += Publics.size() * sizeof(uint32_t);

299

300

302}

303

304uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize() const {

305 return GSH->calculateSerializedLength();

306}

307

309

310 finalizePublicBuckets();

311 finalizeGlobalBuckets(PSH->RecordByteSize);

312

313 Expected<uint32_t> Idx = Msf.addStream(calculateGlobalsHashStreamSize());

314 if (!Idx)

316 GlobalsStreamIndex = *Idx;

317

318 Idx = Msf.addStream(calculatePublicsHashStreamSize());

319 if (!Idx)

321 PublicsStreamIndex = *Idx;

322

323 uint64_t RecordBytes = PSH->RecordByteSize + GSH->RecordByteSize;

324 if (RecordBytes > UINT32_MAX)

326 formatv("the public symbols ({0} bytes) and global symbols ({1} bytes) "

327 "are too large to fit in a PDB file; "

328 "the maximum total is {2} bytes.",

329 PSH->RecordByteSize, GSH->RecordByteSize, UINT32_MAX),

331

332 Idx = Msf.addStream(RecordBytes);

333 if (!Idx)

335 RecordStreamIndex = *Idx;

337}

338

340 assert(Publics.empty() && PSH->RecordByteSize == 0 &&

341 "publics can only be added once");

342 Publics = std::move(PublicsIn);

343

344

346 return L.getName() < R.getName();

347 });

348

349

352 Pub.SymOffset = SymOffset;

354 }

355

356

357 PSH->RecordByteSize = SymOffset;

358}

359

361 serializeAndAddGlobal(Sym);

362}

363

365 serializeAndAddGlobal(Sym);

366}

367

369 serializeAndAddGlobal(Sym);

370}

371

372template

373void GSIStreamBuilder::serializeAndAddGlobal(const T &Symbol) {

377}

378

380

381 if (Symbol.kind() == S_UDT || Symbol.kind() == S_CONSTANT) {

382 auto Iter = GlobalsSeen.insert(Symbol);

383 if (!Iter.second)

384 return;

385 }

386 GSH->RecordByteSize += Symbol.length();

387 Globals.push_back(Symbol);

388}

389

390

393 std::vector<uint8_t> Storage;

394 for (const BulkPublic &Pub : Publics) {

398 return E;

399 }

401}

402

410

411Error GSIStreamBuilder::commitSymbolRecordStream(

412 WritableBinaryStreamRef Stream) {

413 BinaryStreamWriter Writer(Stream);

414

415

416

417

419 return EC;

421 return EC;

422

424}

425

426static std::vectorsupport::ulittle32\_t

428

429

430 std::vector<ulittle32_t> PubAddrMap;

431 PubAddrMap.reserve(Publics.size());

432 for (int I = 0, E = Publics.size(); I < E; ++I)

434

438 if (L.Segment != R.Segment)

439 return L.Segment < R.Segment;

440 if (L.Offset != R.Offset)

441 return L.Offset < R.Offset;

442

443

444 return L.getName() < R.getName();

445 };

447

448

450 Entry = Publics[Entry].SymOffset;

451 return PubAddrMap;

452}

453

454Error GSIStreamBuilder::commitPublicsHashStream(

455 WritableBinaryStreamRef Stream) {

456 BinaryStreamWriter Writer(Stream);

457 PublicsStreamHeader Header;

458

459

460 Header.SymHash = PSH->calculateSerializedLength();

461 Header.AddrMap = Publics.size() * 4;

462 Header.NumThunks = 0;

463 Header.SizeOfThunk = 0;

464 Header.ISectThunkTable = 0;

465 memset(Header.Padding, 0, sizeof(Header.Padding));

466 Header.OffThunkTable = 0;

467 Header.NumSections = 0;

468 if (auto EC = Writer.writeObject(Header))

469 return EC;

470

471 if (auto EC = PSH->commit(Writer))

472 return EC;

473

474 std::vectorsupport::ulittle32\_t PubAddrMap = computeAddrMap(Publics);

475 assert(PubAddrMap.size() == Publics.size());

476 if (auto EC = Writer.writeArray(ArrayRef(PubAddrMap)))

477 return EC;

478

480}

481

482Error GSIStreamBuilder::commitGlobalsHashStream(

483 WritableBinaryStreamRef Stream) {

484 BinaryStreamWriter Writer(Stream);

485 return GSH->commit(Writer);

486}

487

497

498 if (auto EC = commitSymbolRecordStream(*PRS))

499 return EC;

500 if (auto EC = commitGlobalsHashStream(*GS))

501 return EC;

502 if (auto EC = commitPublicsHashStream(*PS))

503 return EC;

505}

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

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define LLVM_UNLIKELY(EXPR)

#define LLVM_PACKED_START

static CVSymbol serializePublic(uint8_t *Mem, const BulkPublic &Pub)

Definition GSIStreamBuilder.cpp:106

static Error writePublics(BinaryStreamWriter &Writer, ArrayRef< BulkPublic > Publics)

Definition GSIStreamBuilder.cpp:391

static bool isAsciiString(StringRef S)

Definition GSIStreamBuilder.cpp:152

static Error writeRecords(BinaryStreamWriter &Writer, ArrayRef< CVSymbol > Records)

Definition GSIStreamBuilder.cpp:403

static int gsiRecordCmp(StringRef S1, StringRef S2)

Definition GSIStreamBuilder.cpp:157

static std::vector< support::ulittle32_t > computeAddrMap(ArrayRef< BulkPublic > Publics)

Definition GSIStreamBuilder.cpp:427

static uint32_t sizeOfPublic(const BulkPublic &Pub)

Definition GSIStreamBuilder.cpp:99

Merge contiguous icmps into a memcmp

LocallyHashedType DenseMapInfo< LocallyHashedType >::Tombstone

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

BinaryItemStream represents a sequence of objects stored in some kind of external container but for w...

void setItems(ArrayRef< T > ItemArray)

BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.

Provides write only access to a subclass of WritableBinaryStream.

Error writeArray(ArrayRef< T > Array)

Writes an array of objects of type T to the underlying stream, as if by using memcpy.

LLVM_ABI Error writeStreamRef(BinaryStreamRef Ref)

Efficiently reads all data from Ref, and writes it to this stream.

LLVM_ABI Error writeBytes(ArrayRef< uint8_t > Buffer)

Write the bytes specified in Buffer to the underlying stream.

Error writeObject(const T &Obj)

Writes the object Obj to the underlying stream, as if by using memcpy.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

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

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

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

The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.

ArrayRef< uint8_t > RecordData

static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, CodeViewContainer Container)

BumpPtrAllocator & getAllocator()

static std::unique_ptr< WritableMappedBlockStream > createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, uint32_t StreamIndex, BumpPtrAllocator &Allocator)

LLVM_ABI void addPublicSymbols(std::vector< BulkPublic > &&PublicsIn)

Definition GSIStreamBuilder.cpp:339

LLVM_ABI Error finalizeMsfLayout()

Definition GSIStreamBuilder.cpp:308

uint32_t getRecordStreamIndex() const

LLVM_ABI ~GSIStreamBuilder()

LLVM_ABI Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer)

Definition GSIStreamBuilder.cpp:488

LLVM_ABI GSIStreamBuilder(msf::MSFBuilder &Msf)

Definition GSIStreamBuilder.cpp:288

LLVM_ABI void addGlobalSymbol(const codeview::ProcRefSym &Sym)

Definition GSIStreamBuilder.cpp:360

uint32_t getPublicsStreamIndex() const

uint32_t getGlobalsStreamIndex() const

@ C

The default llvm calling convention, compatible with C.

llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records

CVRecord< SymbolKind > CVSymbol

LLVM_ABI StringRef getSymbolName(CVSymbol Sym)

detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI uint64_t xxh3_64bits(ArrayRef< uint8_t > data)

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

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

void parallelSort(RandomAccessIterator Start, RandomAccessIterator End, const Comparator &Comp=Comparator())

void sort(IteratorTy Start, IteratorTy End)

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)

Implement std::hash so that hash_code can be used in STL containers.

An information struct used to provide DenseMap with the various necessary components for a given valu...

This struct is equivalent to codeview::PublicSym32, but it has been optimized for size to speed up bu...

uint32_t calculateSerializedLength() const

Definition GSIStreamBuilder.cpp:125

std::vector< support::ulittle32_t > HashBuckets

Definition GSIStreamBuilder.cpp:54

void finalizePublicBuckets()

uint64_t RecordByteSize

Definition GSIStreamBuilder.cpp:43

Error commit(BinaryStreamWriter &Writer)

Definition GSIStreamBuilder.cpp:133

std::array< support::ulittle32_t,(IPHR_HASH+32)/32 > HashBitmap

Definition GSIStreamBuilder.cpp:52

void finalizeGlobalBuckets(uint32_t RecordZeroOffset)

std::vector< PSHashRecord > HashRecords

Definition GSIStreamBuilder.cpp:45

void finalizeBuckets(uint32_t RecordZeroOffset, MutableArrayRef< BulkPublic > Globals)

Definition GSIStreamBuilder.cpp:199

static unsigned getHashValue(const CVSymbol &Val)

Definition GSIStreamBuilder.cpp:80

static CVSymbol getEmptyKey()

Definition GSIStreamBuilder.cpp:71

static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS)

Definition GSIStreamBuilder.cpp:83

static CVSymbol getTombstoneKey()

Definition GSIStreamBuilder.cpp:75