LLVM: lib/Object/GOFFObjectFile.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19

20#ifndef DEBUG_TYPE

21#define DEBUG_TYPE "goff"

22#endif

23

25using namespace llvm;

26

30 std::unique_ptr Ret(new GOFFObjectFile(Object, Err));

31 if (Err)

32 return std::move(Err);

33 return std::move(Ret);

34}

35

39

43 "object file is not the right size. Must be a multiple "

44 "of 80 bytes, but is " +

45 std::to_string(Object.getBufferSize()) + " bytes");

46 return;

47 }

48

49

50 if (Object.getBufferSize() != 0) {

53 "object file must start with HDR record");

54 return;

55 }

59 "object file must end with END record");

60 return;

61 }

62 }

63

64 SectionEntryImpl DummySection;

65 SectionList.emplace_back(DummySection);

66

67 uint8_t PrevRecordType = 0;

68 uint8_t PrevContinuationBits = 0;

69 const uint8_t *End = reinterpret_cast<const uint8_t *>(Data.getBufferEnd());

72 bool IsContinuation = I[1] & 0x02;

73 bool PrevWasContinued = PrevContinuationBits & 0x01;

75

76

77

78 if (PrevWasContinued && !IsContinuation) {

81 "record " + std::to_string(RecordNum) +

82 " is not a continuation record but the "

83 "preceding record is continued");

84 return;

85 }

86 }

87

88 if (IsContinuation) {

91 "record " + std::to_string(RecordNum) +

92 " is a continuation record that does not "

93 "match the type of the previous record");

94 return;

95 }

96 if (!PrevWasContinued) {

98 "record " + std::to_string(RecordNum) +

99 " is a continuation record that is not "

100 "preceded by a continued record");

101 return;

102 }

104 PrevContinuationBits = I[1] & 0x03;

105 continue;

106 }

109 if (J % 8 == 0)

110 dbgs() << " ";

112 });

113

116

119 EsdPtrs.grow(EsdId);

120 EsdPtrs[EsdId] = I;

121

122

123

124

125

126

127

128

129

130

133 SectionEntryImpl Section;

137

139 Section.d.a = EsdId;

140 SectionList.emplace_back(Section);

141 }

143

147 Section.d.a = SymEdId;

148 Section.d.b = EsdId;

149 SectionList.emplace_back(Section);

150 }

152

155 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];

158 if (!EdLength) {

159

160

161 Section.d.a = SymEdId;

162 SectionList.emplace_back(Section);

163 }

164 }

166 break;

167 }

169

170 TextPtrs.emplace_back(I);

172 break;

174 LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");

175 break;

177 LLVM_DEBUG(dbgs() << " -- HDR (GOFF record type) unhandled\n");

178 break;

179 default:

181 }

183 PrevContinuationBits = I[1] & 0x03;

184 }

185}

186

187const uint8_t *GOFFObjectFile::getSymbolEsdRecord(DataRefImpl Symb) const {

188 const uint8_t *EsdRecord = EsdPtrs[Symb.d.a];

189 return EsdRecord;

190}

191

193 if (auto It = EsdNamesCache.find(Symb.d.a); It != EsdNamesCache.end()) {

194 auto &StrPtr = It->second;

195 return StringRef(StrPtr.second.get(), StrPtr.first);

196 }

197

199 if (auto Err = ESDRecord::getData(getSymbolEsdRecord(Symb), SymbolName))

200 return std::move(Err);

201

204

205 size_t Size = SymbolNameConverted.size();

206 auto StrPtr = std::make_pair(Size, std::make_unique<char[]>(Size));

207 char *Buf = StrPtr.second.get();

208 memcpy(Buf, SymbolNameConverted.data(), Size);

209 EsdNamesCache[Symb.d.a] = std::move(StrPtr);

211}

212

216

219 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);

222}

223

226 const uint8_t *EsdRecord = getSymbolEsdRecord(Symb);

229}

230

231uint64_t GOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {

232 return 0;

233}

234

235bool GOFFObjectFile::isSymbolUnresolved(DataRefImpl Symb) const {

236 const uint8_t *Record = getSymbolEsdRecord(Symb);

239

241 return true;

246 return true;

247 }

248 return false;

249}

250

251bool GOFFObjectFile::isSymbolIndirect(DataRefImpl Symb) const {

252 const uint8_t *Record = getSymbolEsdRecord(Symb);

256}

257

258Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {

259 uint32_t Flags = 0;

260 if (isSymbolUnresolved(Symb))

262

263 const uint8_t *Record = getSymbolEsdRecord(Symb);

264

269

272

275 if (Name && *Name != " ") {

281 }

282 }

283

285}

286

287ExpectedSymbolRef::Type

288GOFFObjectFile::getSymbolType(DataRefImpl Symb) const {

289 const uint8_t *Record = getSymbolEsdRecord(Symb);

294

300 uint32_t EsdId;

303 "ESD record %" PRIu32

304 " has invalid symbol type 0x%02" PRIX8,

306 }

316 uint32_t EsdId;

319 "ESD record %" PRIu32

320 " has unknown Executable type 0x%02X",

321 EsdId, Executable);

322 }

323 switch (Executable) {

330 }

332 }

334}

335

336Expected<section_iterator>

337GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {

338 DataRefImpl Sec;

339

340 if (isSymbolUnresolved(Symb))

342

343 const uint8_t *SymEsdRecord = EsdPtrs[Symb.d.a];

344 uint32_t SymEdId;

346 const uint8_t *SymEdRecord = EsdPtrs[SymEdId];

347

348 for (size_t I = 0, E = SectionList.size(); I < E; ++I) {

349 bool Found;

350 const uint8_t *SectionPrRecord = getSectionPrEsdRecord(I);

351 if (SectionPrRecord) {

352 Found = SymEsdRecord == SectionPrRecord;

353 } else {

354 const uint8_t *SectionEdRecord = getSectionEdEsdRecord(I);

355 Found = SymEdRecord == SectionEdRecord;

356 }

357

358 if (Found) {

359 Sec.d.a = I;

361 }

362 }

364 "symbol with ESD id " + std::to_string(Symb.d.a) +

365 " refers to invalid section with ESD id " +

366 std::to_string(SymEdId));

367}

368

369uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {

370 const uint8_t *Record = getSymbolEsdRecord(Symb);

374}

375

376const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {

377 SectionEntryImpl EsdIds = SectionList[Sec.d.a];

378 const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];

379 return EsdRecord;

380}

381

382const uint8_t *GOFFObjectFile::getSectionPrEsdRecord(DataRefImpl &Sec) const {

383 SectionEntryImpl EsdIds = SectionList[Sec.d.a];

384 const uint8_t *EsdRecord = nullptr;

385 if (EsdIds.d.b)

386 EsdRecord = EsdPtrs[EsdIds.d.b];

387 return EsdRecord;

388}

389

390const uint8_t *

391GOFFObjectFile::getSectionEdEsdRecord(uint32_t SectionIndex) const {

392 DataRefImpl Sec;

393 Sec.d.a = SectionIndex;

394 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

395 return EsdRecord;

396}

397

398const uint8_t *

399GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {

400 DataRefImpl Sec;

401 Sec.d.a = SectionIndex;

402 const uint8_t *EsdRecord = getSectionPrEsdRecord(Sec);

403 return EsdRecord;

404}

405

406uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {

407 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

411 const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);

412 if (PrEsdRecord)

413 EsdRecord = PrEsdRecord;

414 }

415

416 uint32_t DefEsdId;

418 LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');

419 return DefEsdId;

420}

421

422void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {

423 Sec.d.a++;

424 if ((Sec.d.a) >= SectionList.size())

425 Sec.d.a = 0;

426}

427

428Expected GOFFObjectFile::getSectionName(DataRefImpl Sec) const {

429 DataRefImpl EdSym;

430 SectionEntryImpl EsdIds = SectionList[Sec.d.a];

431 EdSym.d.a = EsdIds.d.a;

433 if (Name) {

434 StringRef Res = *Name;

435 LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');

436 LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');

438 }

440}

441

442uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {

444 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

447}

448

449uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {

451 uint32_t DefEsdId = getSectionDefEsdId(Sec);

452 const uint8_t *EsdRecord = EsdPtrs[DefEsdId];

455 return static_cast<uint64_t>(Length);

456}

457

458

459

460Expected<ArrayRef<uint8_t>>

461GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {

462 if (auto It = SectionDataCache.find(Sec.d.a); It != SectionDataCache.end()) {

463 auto &Buf = It->second;

464 return ArrayRef<uint8_t>(Buf);

465 }

466 uint64_t SectionSize = getSectionSize(Sec);

467 uint32_t DefEsdId = getSectionDefEsdId(Sec);

468

469 const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);

470 bool FillBytePresent;

472 uint8_t FillByte = '\0';

473 if (FillBytePresent)

475

476

477 SmallVector<uint8_t> Data(SectionSize, FillByte);

478

479

480 for (const uint8_t *TxtRecordInt : TextPtrs) {

481 const uint8_t *TxtRecordPtr = TxtRecordInt;

482 uint32_t TxtEsdId;

484 LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');

485

486 if (TxtEsdId != DefEsdId)

487 continue;

488

489 uint32_t TxtDataOffset;

491

492 uint16_t TxtDataSize;

494

495 LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "

496 << TxtDataSize << "\n");

497

498 SmallString<256> CompleteData;

499 CompleteData.reserve(TxtDataSize);

501 return std::move(Err);

502 assert(CompleteData.size() == TxtDataSize && "Wrong length of data");

503 std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize,

504 Data.begin() + TxtDataOffset);

505 }

506 auto &Cache = SectionDataCache[Sec.d.a];

507 Cache = Data;

508 return ArrayRef<uint8_t>(Cache);

509}

510

511uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {

512 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

515 return 1ULL << static_cast<uint64_t>(Pow2Alignment);

516}

517

518bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {

519 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

523}

524

525bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {

526 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

530}

531

533 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

537}

538

540 if (!isSectionData(Sec))

541 return false;

542

543 const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);

547}

548

550

551

552 return false;

553}

554

557 moveSectionNext(Sec);

559}

560

565

567 for (uint32_t I = Symb.d.a + 1, E = EsdPtrs.size(); I < E; ++I) {

568 if (const uint8_t *EsdRecord = EsdPtrs[I]) {

571

572 bool IgnoreSpecialGOFFSymbols = true;

575 IgnoreSpecialGOFFSymbols;

576 if (!SkipSymbol) {

577 Symb.d.a = I;

578 return;

579 }

580 }

581 }

582 Symb.d.a = 0;

583}

584

590

595

598

600 size_t SliceLength =

603 DataLength -= SliceLength;

604 Slice += SliceLength;

605

606

607 for (; DataLength > 0;

609

610

612

615 "continued bit should not be set");

616

620 }

622}

623

629

635

642

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

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

FunctionLoweringInfo::StatepointRelocationRecord RecordType

Helper for Errors used as out-parameters.

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.

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

void append(StringRef RHS)

Append from a StringRef.

void reserve(size_type N)

pointer data()

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

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

static Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)

Definition GOFFObjectFile.cpp:643

static uint16_t getNameLength(const uint8_t *Record)

static void getIndirectReference(const uint8_t *Record, bool &Indirect)

static void getBindingStrength(const uint8_t *Record, GOFF::ESDBindingStrength &Strength)

static void getOffset(const uint8_t *Record, uint32_t &Offset)

static void getEsdId(const uint8_t *Record, uint32_t &EsdId)

static void getLoadingBehavior(const uint8_t *Record, GOFF::ESDLoadingBehavior &Behavior)

static Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)

Definition GOFFObjectFile.cpp:630

static void getFillBytePresent(const uint8_t *Record, bool &Present)

static void getLength(const uint8_t *Record, uint32_t &Length)

static void getParentEsdId(const uint8_t *Record, uint32_t &EsdId)

static void getFillByteValue(const uint8_t *Record, uint8_t &Fill)

static void getSymbolType(const uint8_t *Record, GOFF::ESDSymbolType &SymbolType)

static void getAlignment(const uint8_t *Record, GOFF::ESDAlignment &Alignment)

static uint16_t getNameLength(const uint8_t *Record)

static void getExecutable(const uint8_t *Record, GOFF::ESDExecutable &Executable)

static void getBindingScope(const uint8_t *Record, GOFF::ESDBindingScope &Scope)

section_iterator section_begin() const override

Definition GOFFObjectFile.cpp:555

basic_symbol_iterator symbol_end() const override

Definition GOFFObjectFile.cpp:591

GOFFObjectFile(MemoryBufferRef Object, Error &Err)

Definition GOFFObjectFile.cpp:36

bool isSectionReadOnlyData(DataRefImpl Sec) const

Definition GOFFObjectFile.cpp:539

bool isSectionNoLoad(DataRefImpl Sec) const

Definition GOFFObjectFile.cpp:532

section_iterator section_end() const override

Definition GOFFObjectFile.cpp:561

Expected< StringRef > getSymbolName(SymbolRef Symbol) const

Definition GOFFObjectFile.cpp:213

void moveSymbolNext(DataRefImpl &Symb) const override

Definition GOFFObjectFile.cpp:566

basic_symbol_iterator symbol_begin() const override

Definition GOFFObjectFile.cpp:585

bool isSectionZeroInit(DataRefImpl Sec) const

Definition GOFFObjectFile.cpp:549

static Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)

Definition GOFFObjectFile.cpp:624

static uint16_t getPropertyModuleLength(const uint8_t *Record)

const uint8_t * base() const

static Expected< std::unique_ptr< ObjectFile > > createGOFFObjectFile(MemoryBufferRef Object)

Definition GOFFObjectFile.cpp:28

ObjectFile(unsigned int Type, MemoryBufferRef Source)

Represents a GOFF physical record.

static bool isContinued(const uint8_t *Record)

static Error getContinuousData(const uint8_t *Record, uint16_t DataLength, int DataIndex, SmallString< 256 > &CompleteData)

Definition GOFFObjectFile.cpp:596

static bool isContinuation(const uint8_t *Record)

static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId)

static void getDataLength(const uint8_t *Record, uint16_t &Length)

static Error getData(const uint8_t *Record, SmallString< 256 > &CompleteData)

Definition GOFFObjectFile.cpp:636

static void getOffset(const uint8_t *Record, uint32_t &Offset)

#define llvm_unreachable(msg)

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

LLVM_ABI void convertToUTF8(StringRef Source, SmallVectorImpl< char > &Result)

constexpr uint8_t RecordPrefixLength

constexpr uint8_t PayloadLength

constexpr uint8_t RecordLength

Length of the parts of a physical GOFF record.

@ ESD_ST_ElementDefinition

@ ESD_ST_SectionDefinition

@ ESD_ST_ExternalReference

content_iterator< SectionRef > section_iterator

content_iterator< BasicSymbolRef > basic_symbol_iterator

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr uintptr_t uintptr_t DataSize

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d