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

1

2

3

4

5

6

7

8

9

10

11

12

26

27#include

28#include

29#include

30

33using namespace llvm;

34

35namespace llvm {

37

41 return "COFF-import-file-i386";

43 return "COFF-import-file-x86-64";

45 return "COFF-import-file-ARM";

47 return "COFF-import-file-ARM64";

49 return "COFF-import-file-ARM64EC";

51 return "COFF-import-file-ARM64X";

52 default:

53 return "COFF-import-file-";

54 }

55}

56

59 return !s.empty() && chars.contains(s[0]) ? s.substr(1) : s;

60 };

61

62 switch (Type) {

65 break;

69 break;

70 default:

71 break;

72 }

74}

75

78 StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first;

79

83 break;

87 break;

89

90 name = Data.getBuffer().substr(sizeof(*hdr) + name.size() + 1);

91 name = name.split('\0').second.split('\0').first;

92 break;

93 }

94 default:

95 break;

96 }

97

99}

100

102 switch (Symb.p) {

103 case ImpSymbol:

104 OS << "__imp_";

105 break;

106 case ECAuxSymbol:

107 OS << "__imp_aux_";

108 break;

109 }

112 if (std::optionalstd::string DemangledName =

116 }

117 }

120}

121

140

141template static void append(std::vector<uint8_t> &B, const T &Data) {

142 size_t S = B.size();

143 B.resize(S + sizeof(T));

144 memcpy(&B[S], &Data, sizeof(T));

145}

146

149

150

151

152

153

154

155 size_t Pos = B.size();

156 size_t Offset = B.size();

157

158

159

161

162 for (const auto &S : Strings) {

163 B.resize(Pos + S.length() + 1);

164 llvm::copy(S, std::next(B.begin(), Pos));

165 B[Pos + S.length()] = 0;

166 Pos += S.length() + 1;

167 }

168

169

172}

173

176

177

178

179

180

181

184 if (Sym != ExtName)

189}

190

193 size_t Pos = S.find(From);

194

195

197 From = From.substr(1);

199 Pos = S.find(From);

200 }

201

206 }

207

209}

210

211namespace {

212

213

214

215

216class ObjectFactory {

223 std::string ImportDescriptorSymbolName;

224 std::string NullThunkSymbolName;

225

226public:

228 : NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)),

230 NullThunkSymbolName(

232

233

234

235

236

237 NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);

238

239

240

241

242 NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);

243

244

245

246

247 NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);

248

249

250

255

256

259

261};

262}

263

264NewArchiveMember

265ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {

266 const uint32_t NumberOfSections = 2;

267 const uint32_t NumberOfSymbols = 7;

268 const uint32_t NumberOfRelocations = 3;

269

270

271 coff_file_header Header{

272 u16(NativeMachine),

273 u16(NumberOfSections),

274 u32(0),

275 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +

276

277 sizeof(coff_import_directory_table_entry) +

278 NumberOfRelocations * sizeof(coff_relocation) +

279

280 (ImportName.size() + 1)),

281 u32(NumberOfSymbols),

282 u16(0),

284 };

285 append(Buffer, Header);

286

287

288 const coff_section SectionTable[NumberOfSections] = {

289 {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},

290 u32(0),

291 u32(0),

292 u32(sizeof(coff_import_directory_table_entry)),

293 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),

294 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +

295 sizeof(coff_import_directory_table_entry)),

296 u32(0),

297 u16(NumberOfRelocations),

298 u16(0),

301 {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},

302 u32(0),

303 u32(0),

304 u32(ImportName.size() + 1),

305 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +

306 sizeof(coff_import_directory_table_entry) +

307 NumberOfRelocations * sizeof(coff_relocation)),

308 u32(0),

309 u32(0),

310 u16(0),

311 u16(0),

314 };

315 append(Buffer, SectionTable);

316

317

318 const coff_import_directory_table_entry ImportDescriptor{

319 u32(0), u32(0), u32(0), u32(0), u32(0),

320 };

321 append(Buffer, ImportDescriptor);

322

323 const coff_relocation RelocationTable[NumberOfRelocations] = {

324 {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),

326 {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),

328 {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),

330 };

331 append(Buffer, RelocationTable);

332

333

334 auto S = Buffer.size();

335 Buffer.resize(S + ImportName.size() + 1);

336 memcpy(&Buffer[S], ImportName.data(), ImportName.size());

337 Buffer[S + ImportName.size()] = '\0';

338

339

341 {{{0, 0, 0, 0, 0, 0, 0, 0}},

342 u32(0),

343 u16(1),

344 u16(0),

346 0},

347 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},

348 u32(0),

349 u16(1),

350 u16(0),

352 0},

353 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},

354 u32(0),

355 u16(2),

356 u16(0),

358 0},

359 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},

360 u32(0),

361 u16(0),

362 u16(0),

364 0},

365 {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},

366 u32(0),

367 u16(0),

368 u16(0),

370 0},

371 {{{0, 0, 0, 0, 0, 0, 0, 0}},

372 u32(0),

373 u16(0),

374 u16(0),

376 0},

377 {{{0, 0, 0, 0, 0, 0, 0, 0}},

378 u32(0),

379 u16(0),

380 u16(0),

382 0},

383 };

384

385

387 sizeof(uint32_t);

389 sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;

391 sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +

393 append(Buffer, SymbolTable);

394

395

398 NullThunkSymbolName});

399

400 StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};

401 return {MemoryBufferRef(F, ImportName)};

402}

403

404NewArchiveMember

405ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {

406 const uint32_t NumberOfSections = 1;

407 const uint32_t NumberOfSymbols = 1;

408

409

410 coff_file_header Header{

411 u16(NativeMachine),

412 u16(NumberOfSections),

413 u32(0),

414 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +

415

416 sizeof(coff_import_directory_table_entry)),

417 u32(NumberOfSymbols),

418 u16(0),

420 };

421 append(Buffer, Header);

422

423

424 const coff_section SectionTable[NumberOfSections] = {

425 {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},

426 u32(0),

427 u32(0),

428 u32(sizeof(coff_import_directory_table_entry)),

429 u32(sizeof(coff_file_header) +

430 (NumberOfSections * sizeof(coff_section))),

431 u32(0),

432 u32(0),

433 u16(0),

434 u16(0),

437 };

438 append(Buffer, SectionTable);

439

440

441 const coff_import_directory_table_entry ImportDescriptor{

442 u32(0), u32(0), u32(0), u32(0), u32(0),

443 };

444 append(Buffer, ImportDescriptor);

445

446

448 {{{0, 0, 0, 0, 0, 0, 0, 0}},

449 u32(0),

450 u16(1),

451 u16(0),

453 0},

454 };

456 append(Buffer, SymbolTable);

457

458

460

461 StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};

462 return {MemoryBufferRef(F, ImportName)};

463}

464

465NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {

466 const uint32_t NumberOfSections = 2;

467 const uint32_t NumberOfSymbols = 1;

468 uint32_t VASize = is64Bit() ? 8 : 4;

469

470

471 coff_file_header Header{

472 u16(NativeMachine),

473 u16(NumberOfSections),

474 u32(0),

475 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +

476

477 VASize +

478

479 VASize),

480 u32(NumberOfSymbols),

481 u16(0),

483 };

484 append(Buffer, Header);

485

486

487 const coff_section SectionTable[NumberOfSections] = {

488 {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},

489 u32(0),

490 u32(0),

491 u32(VASize),

492 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),

493 u32(0),

494 u32(0),

495 u16(0),

496 u16(0),

500 {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},

501 u32(0),

502 u32(0),

503 u32(VASize),

504 u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +

505 VASize),

506 u32(0),

507 u32(0),

508 u16(0),

509 u16(0),

513 };

514 append(Buffer, SectionTable);

515

516

517 append(Buffer, u32(0));

519 append(Buffer, u32(0));

520

521

522 append(Buffer, u32(0));

524 append(Buffer, u32(0));

525

526

528 {{{0, 0, 0, 0, 0, 0, 0, 0}},

529 u32(0),

530 u16(1),

531 u16(0),

533 0},

534 };

536 append(Buffer, SymbolTable);

537

538

540

541 StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};

542 return {MemoryBufferRef{F, ImportName}};

543}

544

545NewArchiveMember

546ObjectFactory::createShortImport(StringRef Sym, uint16_t Ordinal,

549 size_t ImpSize = ImportName.size() + Sym.size() + 2;

550 if (!ExportName.empty())

551 ImpSize += ExportName.size() + 1;

552 size_t Size = sizeof(coff_import_header) + ImpSize;

553 char *Buf = Alloc.Allocate<char>(Size);

554 memset(Buf, 0, Size);

555 char *P = Buf;

556

557

558 auto *Imp = reinterpret_cast<coff_import_header *>(P);

559 P += sizeof(*Imp);

560 Imp->Sig2 = 0xFFFF;

562 Imp->SizeOfData = ImpSize;

563 if (Ordinal > 0)

564 Imp->OrdinalHint = Ordinal;

566

567

568 memcpy(P, Sym.data(), Sym.size());

569 P += Sym.size() + 1;

570 memcpy(P, ImportName.data(), ImportName.size());

571 if (!ExportName.empty()) {

572 P += ImportName.size() + 1;

573 memcpy(P, ExportName.data(), ExportName.size());

574 }

575

576 return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};

577}

578

579NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,

580 StringRef Weak, bool Imp,

582 std::vector<uint8_t> Buffer;

583 const uint32_t NumberOfSections = 1;

584 const uint32_t NumberOfSymbols = 5;

585

586

587 coff_file_header Header{

589 u16(NumberOfSections),

590 u32(0),

591 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),

592 u32(NumberOfSymbols),

593 u16(0),

594 u16(0),

595 };

596 append(Buffer, Header);

597

598

599 const coff_section SectionTable[NumberOfSections] = {

600 {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},

601 u32(0),

602 u32(0),

603 u32(0),

604 u32(0),

605 u32(0),

606 u32(0),

607 u16(0),

608 u16(0),

610 append(Buffer, SectionTable);

611

612

614 {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},

615 u32(0),

616 u16(0xFFFF),

617 u16(0),

619 0},

620 {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},

621 u32(0),

622 u16(0xFFFF),

623 u16(0),

625 0},

626 {{{0, 0, 0, 0, 0, 0, 0, 0}},

627 u32(0),

628 u16(0),

629 u16(0),

631 0},

632 {{{0, 0, 0, 0, 0, 0, 0, 0}},

633 u32(0),

634 u16(0),

635 u16(0),

637 1},

639 u32(0),

640 u16(0),

641 u16(0),

643 0},

644 };

646

647

648 StringRef Prefix = Imp ? "__imp_" : "";

650 sizeof(uint32_t) + Sym.size() + Prefix.size() + 1;

651 append(Buffer, SymbolTable);

654

655

656 char *Buf = Alloc.Allocate<char>(Buffer.size());

657 memcpy(Buf, Buffer.data(), Buffer.size());

658 return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};

659}

660

665

670 }

671

672 std::vector Members;

674

675 std::vector<uint8_t> ImportDescriptor;

676 Members.push_back(OF.createImportDescriptor(ImportDescriptor));

677

678 std::vector<uint8_t> NullImportDescriptor;

679 Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));

680

681 std::vector<uint8_t> NullThunk;

682 Members.push_back(OF.createNullThunk(NullThunk));

683

687 struct Deferred {

688 std::string Name;

691 };

694 if (E.Private)

695 continue;

696

698 if (E.Data)

700 if (E.Constant)

702

703 StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;

704 std::string Name;

705

706 if (E.ExtName.empty()) {

707 Name = std::string(SymbolName);

708 } else {

711 if (!ReplacedName)

713 Name.swap(*ReplacedName);

714 }

715

717 std::string ExportName;

718 if (E.Noname) {

720 } else if (!E.ExportAs.empty()) {

722 ExportName = E.ExportAs;

723 } else if (!E.ImportName.empty()) {

724

725

726

727

736 ExportName = E.ImportName;

737 } else if (Name == E.ImportName)

739 else {

740 Deferred D;

741 D.Name = Name;

743 D.Export = &E;

745 continue;

746 }

747 } else {

749 }

750

751

753 if (std::optionalstd::string MangledName =

755 if (!E.Noname && ExportName.empty()) {

757 ExportName.swap(Name);

758 }

759 Name = std::move(*MangledName);

760 } else if (!E.Noname && ExportName.empty()) {

761 std::optionalstd::string DemangledName =

763 if (!DemangledName)

765 StringRef(Twine("Invalid ARM64EC function name '" + Name + "'")

766 .str()),

769 ExportName = std::move(*DemangledName);

770 }

771 }

772

774 Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,

776 }

777 for (const auto &D : Renames) {

778 auto It = RegularImports.find(D.Export->ImportName);

779 if (It != RegularImports.end()) {

780

781

784 Members.push_back(OF.createWeakExternal(Symbol, D.Name, false, M));

785 Members.push_back(OF.createWeakExternal(Symbol, D.Name, true, M));

786 } else {

787 Members.push_back(OF.createShortImport(D.Name, D.Export->Ordinal,

789 D.Export->ImportName, M));

790 }

791 }

793 };

794

796 return e;

797 if (Error e = addExports(NativeExports, NativeMachine))

798 return e;

799

802 true, false,

804}

805

806}

807}

This file defines the StringMap class.

AMDGPU Prepare AGPR Alloc

This file defines the BumpPtrAllocator interface.

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

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

#define offsetof(TYPE, MEMBER)

Function const char TargetMachine * Machine

This file defines the SmallVector class.

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

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.

void push_back(const T &Elt)

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

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

iterator find(StringRef Key)

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

static constexpr size_t npos

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr bool empty() const

empty - Check if the string is empty.

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

bool contains(StringRef Other) const

Return true if the given string is a substring of *this, and false otherwise.

size_t find(char C, size_t From=0) const

Search for the first character C in the string.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

const coff_import_header * getCOFFImportHeader() const

StringRef getFileFormatName() const

Definition COFFImportFile.cpp:38

StringRef getExportName() const

Definition COFFImportFile.cpp:76

Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override

Definition COFFImportFile.cpp:101

uint16_t getMachine() const

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

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

@ IMAGE_REL_MIPS_REFWORDNB

@ IMAGE_FILE_MACHINE_ARM64

@ IMAGE_FILE_MACHINE_AMD64

@ IMAGE_FILE_MACHINE_ARM64EC

@ IMAGE_FILE_MACHINE_R4000

@ IMAGE_FILE_MACHINE_I386

@ IMAGE_FILE_MACHINE_ARM64X

@ IMAGE_FILE_MACHINE_ARMNT

@ IMAGE_SCN_CNT_INITIALIZED_DATA

@ IMAGE_REL_ARM64_ADDR32NB

@ IMAGE_REL_AMD64_ADDR32NB

@ IMAGE_SYM_CLASS_SECTION

Line number, reformatted as symbol.

@ IMAGE_SYM_CLASS_EXTERNAL

External symbol.

@ IMAGE_SYM_CLASS_NULL

No symbol.

@ IMAGE_SYM_CLASS_WEAK_EXTERNAL

Duplicate tag.

@ IMAGE_SYM_CLASS_STATIC

Static.

@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS

bool isArm64EC(T Machine)

@ IMPORT_ORDINAL

Import is by ordinal.

@ IMPORT_NAME_EXPORTAS

The import name is specified as a separate string in the import library object file.

@ IMPORT_NAME

The import name is identical to the public symbol name.

@ IMPORT_NAME_UNDECORATE

The import name is the public symbol name, but skipping the leading ?

@ IMPORT_NAME_NOPREFIX

The import name is the public symbol name, but skipping the leading ?

@ IMAGE_FILE_32BIT_MACHINE

Machine is based on a 32bit word architecture.

static void append(std::vector< uint8_t > &B, const T &Data)

Definition COFFImportFile.cpp:141

constexpr std::string_view NullImportDescriptorSymbolName

static StringRef applyNameType(ImportNameType Type, StringRef name)

Definition COFFImportFile.cpp:57

static Expected< std::string > replace(StringRef S, StringRef From, StringRef To)

Definition COFFImportFile.cpp:191

static uint16_t getImgRelRelocation(MachineTypes Machine)

Definition COFFImportFile.cpp:122

constexpr std::string_view NullThunkDataPrefix

coff_symbol< support::ulittle16_t > coff_symbol16

constexpr std::string_view NullThunkDataSuffix

static ImportNameType getNameType(StringRef Sym, StringRef ExtName, MachineTypes Machine, bool MinGW)

Definition COFFImportFile.cpp:174

static void writeStringTable(std::vector< uint8_t > &B, ArrayRef< const std::string_view > Strings)

Definition COFFImportFile.cpp:147

constexpr std::string_view ImportDescriptorPrefix

LLVM_ABI Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef< COFFShortExport > Exports, COFF::MachineTypes Machine, bool MinGW, ArrayRef< COFFShortExport > NativeExports={})

Writes a COFF import library containing entries described by the Exports array.

Definition COFFImportFile.cpp:661

void write32le(void *P, uint32_t V)

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

detail::packed_endian_specific_integral< uint16_t, llvm::endianness::little, unaligned > ulittle16_t

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI std::optional< std::string > getArm64ECMangledFunctionName(StringRef Name)

Returns the ARM64EC mangled function name unless the input is already mangled.

LLVM_ABI Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr, std::optional< bool > IsEC=std::nullopt, function_ref< void(Error)> Warn=warnToStderr)

@ Export

Export information to summary.

LLVM_ABI std::optional< std::string > getArm64ECDemangledFunctionName(StringRef Name)

Returns the ARM64EC demangled function name, unless the input is not mangled.

Error make_error(ArgTs &&... Args)

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

FunctionAddr VTableAddr uintptr_t uintptr_t Data

OutputIt copy(R &&Range, OutputIt Out)

BumpPtrAllocatorImpl<> BumpPtrAllocator

The standard BumpPtrAllocator which just uses the default template parameters.

support::ulittle32_t Offset

union llvm::object::coff_symbol::@265345154330271214162033131142206023012313265335 Name