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

1

2

3

4

5

6

7

8

9

10

11

12

19#include

20#include

21

22using namespace llvm;

23using namespace object;

24

25namespace llvm {

27

28#define RETURN_IF_ERROR(X) \

29 if (auto EC = X) \

30 return EC;

31

32#define UNWRAP_REF_OR_RETURN(Name, Expr) \

33 auto Name##OrErr = Expr; \

34 if (!Name##OrErr) \

35 return Name##OrErr.takeError(); \

36 const auto &Name = *Name##OrErr;

37

38#define UNWRAP_OR_RETURN(Name, Expr) \

39 auto Name##OrErr = Expr; \

40 if (!Name##OrErr) \

41 return Name##OrErr.takeError(); \

42 auto Name = *Name##OrErr;

43

45

46

47

49

55}

56

57

62 Source.getBufferIdentifier() + ": too small to be a resource file",

64 std::unique_ptr Ret(new WindowsResource(Source));

65 return std::move(Ret);

66}

67

74

78

82 if (auto E = Ref.loadNext())

83 return E;

84 return Ref;

85}

86

88

89 if (Reader.bytesRemaining() == 0) {

90 End = true;

92 }

94

96}

97

102 IsString = IDFlag != 0xffff;

103

104 if (IsString) {

107 sizeof(uint16_t));

109 } else

111

113}

114

115Error ResourceEntryRef::loadNext() {

118

121 ": header size too small",

123

125

127

129

131

133

135

137}

138

140 : Root(false), MinGW(MinGW) {}

141

143 switch (TypeID) {

144 case 1: OS << "CURSOR (ID 1)"; break;

145 case 2: OS << "BITMAP (ID 2)"; break;

146 case 3: OS << "ICON (ID 3)"; break;

147 case 4: OS << "MENU (ID 4)"; break;

148 case 5: OS << "DIALOG (ID 5)"; break;

149 case 6: OS << "STRINGTABLE (ID 6)"; break;

150 case 7: OS << "FONTDIR (ID 7)"; break;

151 case 8: OS << "FONT (ID 8)"; break;

152 case 9: OS << "ACCELERATOR (ID 9)"; break;

153 case 10: OS << "RCDATA (ID 10)"; break;

154 case 11: OS << "MESSAGETABLE (ID 11)"; break;

155 case 12: OS << "GROUP_CURSOR (ID 12)"; break;

156 case 14: OS << "GROUP_ICON (ID 14)"; break;

157 case 16: OS << "VERSIONINFO (ID 16)"; break;

158 case 17: OS << "DLGINCLUDE (ID 17)"; break;

159 case 19: OS << "PLUGPLAY (ID 19)"; break;

160 case 20: OS << "VXD (ID 20)"; break;

161 case 21: OS << "ANICURSOR (ID 21)"; break;

162 case 22: OS << "ANIICON (ID 22)"; break;

163 case 23: OS << "HTML (ID 23)"; break;

164 case 24: OS << "MANIFEST (ID 24)"; break;

165 default: OS << "ID " << TypeID; break;

166 }

167}

168

172

173 std::vector EndianCorrectedSrc;

174 EndianCorrectedSrc.resize(Src.size() + 1);

175 llvm::copy(Src, EndianCorrectedSrc.begin() + 1);

178}

179

182 std::string Ret;

184

185 OS << "duplicate resource:";

186

187 OS << " type ";

188 if (Entry.checkTypeString()) {

189 std::string UTF8;

191 UTF8 = "(failed conversion from UTF16)";

192 OS << '\"' << UTF8 << '\"';

193 } else

195

196 OS << "/name ";

197 if (Entry.checkNameString()) {

198 std::string UTF8;

200 UTF8 = "(failed conversion from UTF16)";

201 OS << '\"' << UTF8 << '\"';

202 } else {

203 OS << "ID " << Entry.getNameID();

204 }

205

206 OS << "/language " << Entry.getLanguage() << ", in " << File1 << " and in "

207 << File2;

208

209 return OS.str();

210}

211

215 std::string UTF8;

217 UTF8 = "(failed conversion from UTF16)";

218 OS << '\"' << UTF8 << '\"';

219 } else if (IsType)

221 else if (IsID)

222 OS << "ID " << S.ID;

223 else

224 OS << S.ID;

225}

226

228 const std::vectorWindowsResourceParser::StringOrID &Context,

230 std::string Ret;

232

233 OS << "duplicate resource:";

234

235 if (Context.size() >= 1) {

236 OS << " type ";

237 printStringOrID(Context[0], OS, true, true);

238 }

239

240 if (Context.size() >= 2) {

241 OS << "/name ";

242 printStringOrID(Context[1], OS, false, true);

243 }

244

245 if (Context.size() >= 3) {

246 OS << "/language ";

247 printStringOrID(Context[2], OS, false, false);

248 }

249 OS << ", in " << File1 << " and in " << File2;

250

251 return OS.str();

252}

253

254

255

256

257

258

259

260

261

263 std::vectorstd::string &Duplicates) {

264 auto TypeIt = Root.IDChildren.find( 24);

265 if (TypeIt == Root.IDChildren.end())

266 return;

267

268 TreeNode *TypeNode = TypeIt->second.get();

269 auto NameIt =

270 TypeNode->IDChildren.find( 1);

271 if (NameIt == TypeNode->IDChildren.end())

272 return;

273

274 TreeNode *NameNode = NameIt->second.get();

275 if (NameNode->IDChildren.size() <= 1)

276 return;

277

278

279

280 auto LangZeroIt = NameNode->IDChildren.find(0);

281 if (LangZeroIt != NameNode->IDChildren.end() &&

282 LangZeroIt->second->IsDataNode) {

283 uint32_t RemovedIndex = LangZeroIt->second->DataIndex;

284 NameNode->IDChildren.erase(LangZeroIt);

285 Data.erase(Data.begin() + RemovedIndex);

286 Root.shiftDataIndexDown(RemovedIndex);

287

288

289 if (NameNode->IDChildren.size() <= 1)

290 return;

291 }

292

293

294 auto FirstIt = NameNode->IDChildren.begin();

295 uint32_t FirstLang = FirstIt->first;

296 TreeNode *FirstNode = FirstIt->second.get();

297 auto LastIt = NameNode->IDChildren.rbegin();

298 uint32_t LastLang = LastIt->first;

299 TreeNode *LastNode = LastIt->second.get();

300 Duplicates.push_back(

301 ("duplicate non-default manifests with languages " + Twine(FirstLang) +

302 " in " + InputFilenames[FirstNode->Origin] + " and " + Twine(LastLang) +

303 " in " + InputFilenames[LastNode->Origin])

304 .str());

305}

306

307

308

309

310

311bool WindowsResourceParser::shouldIgnoreDuplicate(

313 return MinGW && !Entry.checkTypeString() &&

314 Entry.getTypeID() == 24 &&

315 !Entry.checkNameString() &&

316 Entry.getNameID() == 1 &&

317 Entry.getLanguage() == 0;

318}

319

320bool WindowsResourceParser::shouldIgnoreDuplicate(

321 const std::vector &Context) const {

322 return MinGW && Context.size() == 3 && !Context[0].IsString &&

323 Context[0].ID == 24 && !Context[1].IsString &&

324 Context[1].ID == 1 &&

325 !Context[2].IsString && Context[2].ID == 0;

326}

327

329 std::vectorstd::string &Duplicates) {

331 if (!EntryOrErr) {

332 auto E = EntryOrErr.takeError();

334

335

336

337

338

339

342 }

343 return E;

344 }

345

347 uint32_t Origin = InputFilenames.size();

348 InputFilenames.push_back(std::string(WR->getFileName()));

349 bool End = false;

350 while (!End) {

351

353 bool IsNewNode = Root.addEntry(Entry, Origin, Data, StringTable, Node);

354 if (!IsNewNode) {

355 if (!shouldIgnoreDuplicate(Entry))

357 Entry, InputFilenames[Node->Origin], WR->getFileName()));

358 }

359

361 }

362

364}

365

367 std::vectorstd::string &Duplicates) {

369 uint32_t Origin = InputFilenames.size();

370 InputFilenames.push_back(std::string(Filename));

371 std::vector Context;

372 return addChildren(Root, RSR, BaseTable, Origin, Context, Duplicates);

373}

374

377 Root.print(Writer, "Resource Tree");

378}

379

380bool WindowsResourceParser::TreeNode::addEntry(

382 std::vector<std::vector<uint8_t>> &Data,

383 std::vector<std::vector> &StringTable, TreeNode *&Result) {

384 TreeNode &TypeNode = addTypeNode(Entry, StringTable);

385 TreeNode &NameNode = TypeNode.addNameNode(Entry, StringTable);

386 return NameNode.addLanguageNode(Entry, Origin, Data, Result);

387}

388

389Error WindowsResourceParser::addChildren(TreeNode &Node,

393 std::vector &Context,

394 std::vectorstd::string &Duplicates) {

395

397 i++) {

399 TreeNode *Child;

400

401 if (Entry.Offset.isSubDir()) {

402

403

407 Context.push_back(StringOrID(NameString));

408 } else {

409 Child = &Node.addIDChild(Entry.Identifier.ID);

410 Context.push_back(StringOrID(Entry.Identifier.ID));

411 }

412

415 addChildren(*Child, RSR, NextTable, Origin, Context, Duplicates);

416 if (E)

417 return E;

419

420 } else {

421

422

425 "unexpected string key for data object");

426

427

433 Origin, Data.size(), Child);

434 if (Added) {

436 Data.push_back(ArrayRef<uint8_t>(

437 reinterpret_cast<const uint8_t *>(Contents.data()),

438 Contents.size()));

439 } else {

440 if (!shouldIgnoreDuplicate(Context))

442 Context, InputFilenames[Child->Origin], InputFilenames.back()));

443 }

445

446 }

447 }

449}

450

451WindowsResourceParser::TreeNode::TreeNode(uint32_t StringIndex)

452 : StringIndex(StringIndex) {}

453

454WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion,

455 uint16_t MinorVersion,

456 uint32_t Characteristics,

457 uint32_t Origin, uint32_t DataIndex)

458 : IsDataNode(true), DataIndex(DataIndex), MajorVersion(MajorVersion),

460 Origin(Origin) {}

461

462std::unique_ptrWindowsResourceParser::TreeNode

463WindowsResourceParser::TreeNode::createStringNode(uint32_t Index) {

464 return std::unique_ptr(new TreeNode(Index));

465}

466

467std::unique_ptrWindowsResourceParser::TreeNode

468WindowsResourceParser::TreeNode::createIDNode() {

469 return std::unique_ptr(new TreeNode(0));

470}

471

472std::unique_ptrWindowsResourceParser::TreeNode

473WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion,

474 uint16_t MinorVersion,

475 uint32_t Characteristics,

476 uint32_t Origin,

477 uint32_t DataIndex) {

478 return std::unique_ptr(new TreeNode(

479 MajorVersion, MinorVersion, Characteristics, Origin, DataIndex));

480}

481

482WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addTypeNode(

483 const ResourceEntryRef &Entry,

484 std::vector<std::vector> &StringTable) {

485 if (Entry.checkTypeString())

486 return addNameChild(Entry.getTypeString(), StringTable);

487 else

488 return addIDChild(Entry.getTypeID());

489}

490

491WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addNameNode(

492 const ResourceEntryRef &Entry,

493 std::vector<std::vector> &StringTable) {

494 if (Entry.checkNameString())

495 return addNameChild(Entry.getNameString(), StringTable);

496 else

497 return addIDChild(Entry.getNameID());

498}

499

500bool WindowsResourceParser::TreeNode::addLanguageNode(

501 const ResourceEntryRef &Entry, uint32_t Origin,

502 std::vector<std::vector<uint8_t>> &Data, TreeNode *&Result) {

503 bool Added = addDataChild(Entry.getLanguage(), Entry.getMajorVersion(),

504 Entry.getMinorVersion(), Entry.getCharacteristics(),

505 Origin, Data.size(), Result);

506 if (Added)

507 Data.push_back(Entry.getData());

509}

510

511bool WindowsResourceParser::TreeNode::addDataChild(

512 uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,

513 uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex,

515 auto NewChild = createDataNode(MajorVersion, MinorVersion, Characteristics,

516 Origin, DataIndex);

517 auto ElementInserted = IDChildren.emplace(ID, std::move(NewChild));

518 Result = ElementInserted.first->second.get();

519 return ElementInserted.second;

520}

521

522WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addIDChild(

523 uint32_t ID) {

524 auto Child = IDChildren.find(ID);

525 if (Child == IDChildren.end()) {

526 auto NewChild = createIDNode();

527 WindowsResourceParser::TreeNode &Node = *NewChild;

528 IDChildren.emplace(ID, std::move(NewChild));

530 } else

531 return *(Child->second);

532}

533

534WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addNameChild(

535 ArrayRef NameRef, std::vector<std::vector> &StringTable) {

536 std::string NameString;

538

539 auto Child = StringChildren.find(NameString);

540 if (Child == StringChildren.end()) {

541 auto NewChild = createStringNode(StringTable.size());

542 StringTable.push_back(NameRef);

543 WindowsResourceParser::TreeNode &Node = *NewChild;

544 StringChildren.emplace(NameString, std::move(NewChild));

546 } else

547 return *(Child->second);

548}

549

552 ListScope NodeScope(Writer, Name);

553 for (auto const &Child : StringChildren) {

554 Child.second->print(Writer, Child.first);

555 }

556 for (auto const &Child : IDChildren) {

557 Child.second->print(Writer, to_string(Child.first));

558 }

559}

560

561

562

563

565 uint32_t Size = (IDChildren.size() + StringChildren.size()) *

567

568

569 if (IsDataNode) {

572 }

573

574

575

577

578 for (auto const &Child : StringChildren) {

579 Size += Child.second->getTreeSize();

580 }

581 for (auto const &Child : IDChildren) {

582 Size += Child.second->getTreeSize();

583 }

585}

586

587

588

589void WindowsResourceParser::TreeNode::shiftDataIndexDown(uint32_t Index) {

590 if (IsDataNode && DataIndex >= Index) {

591 DataIndex--;

592 } else {

593 for (auto &Child : IDChildren)

594 Child.second->shiftDataIndexDown(Index);

595 for (auto &Child : StringChildren)

596 Child.second->shiftDataIndexDown(Index);

597 }

598}

599

601public:

604 std::unique_ptr write(uint32_t TimeDateStamp);

605

606private:

607 void performFileLayout();

608 void performSectionOneLayout();

609 void performSectionTwoLayout();

610 void writeCOFFHeader(uint32_t TimeDateStamp);

611 void writeFirstSectionHeader();

612 void writeSecondSectionHeader();

613 void writeFirstSection();

614 void writeSecondSection();

617 void writeDirectoryTree();

618 void writeDirectoryStringTable();

619 void writeFirstSectionRelocations();

620 std::unique_ptr OutputBuffer;

621 char *BufferStart;

630 uint32_t SectionOneRelocations;

634 std::vector<uint32_t> StringTableOffsets;

635 std::vector<uint32_t> DataOffsets;

636 std::vector<uint32_t> RelocationAddresses;

637};

638

642 : MachineType(MachineType), Resources(Parser.getTree()),

644 performFileLayout();

645

647 FileSize, "internal .obj file created from .res files");

648}

649

650void WindowsResourceCOFFWriter::performFileLayout() {

651

653

654

656

657 performSectionOneLayout();

658 performSectionTwoLayout();

659

660

661 SymbolTableOffset = FileSize;

662

664 FileSize += 4 * COFF::Symbol16Size;

666 FileSize += 4;

667}

668

669void WindowsResourceCOFFWriter::performSectionOneLayout() {

670 SectionOneOffset = FileSize;

671

672 SectionOneSize = Resources.getTreeSize();

673 uint32_t CurrentStringOffset = SectionOneSize;

674 uint32_t TotalStringTableSize = 0;

676 StringTableOffsets.push_back(CurrentStringOffset);

678 CurrentStringOffset += StringSize;

679 TotalStringTableSize += StringSize;

680 }

681 SectionOneSize += alignTo(TotalStringTableSize, sizeof(uint32_t));

682

683

684 SectionOneRelocations = FileSize + SectionOneSize;

685 FileSize += SectionOneSize;

686 FileSize +=

689}

690

691void WindowsResourceCOFFWriter::performSectionTwoLayout() {

692

693

694 SectionTwoOffset = FileSize;

695 SectionTwoSize = 0;

696 for (auto const &Entry : Data) {

697 DataOffsets.push_back(SectionTwoSize);

698 SectionTwoSize += alignTo(Entry.size(), sizeof(uint64_t));

699 }

700 FileSize += SectionTwoSize;

702}

703

704std::unique_ptr

706 BufferStart = OutputBuffer->getBufferStart();

707

708 writeCOFFHeader(TimeDateStamp);

709 writeFirstSectionHeader();

710 writeSecondSectionHeader();

711 writeFirstSection();

712 writeSecondSection();

713 writeSymbolTable();

714 writeStringTable();

715

716 return std::move(OutputBuffer);

717}

718

719

720

723 "Src is larger than COFF::NameSize");

725 "Dest not zeroed upon initialization");

726 memcpy(Dest, Src.data(), Src.size());

727}

728

729void WindowsResourceCOFFWriter::writeCOFFHeader(uint32_t TimeDateStamp) {

730

731 auto *Header = reinterpret_cast<coff_file_header *>(BufferStart);

732 Header->Machine = MachineType;

733 Header->NumberOfSections = 2;

734 Header->TimeDateStamp = TimeDateStamp;

735 Header->PointerToSymbolTable = SymbolTableOffset;

736

737 Header->NumberOfSymbols = Data.size() + 5;

738 Header->SizeOfOptionalHeader = 0;

739

741}

742

743void WindowsResourceCOFFWriter::writeFirstSectionHeader() {

744

746 auto *SectionOneHeader =

747 reinterpret_cast<coff_section *>(BufferStart + CurrentOffset);

748 coffnamecpy(SectionOneHeader->Name, ".rsrc$01");

749 SectionOneHeader->VirtualSize = 0;

750 SectionOneHeader->VirtualAddress = 0;

751 SectionOneHeader->SizeOfRawData = SectionOneSize;

752 SectionOneHeader->PointerToRawData = SectionOneOffset;

753 SectionOneHeader->PointerToRelocations = SectionOneRelocations;

754 SectionOneHeader->PointerToLinenumbers = 0;

755 SectionOneHeader->NumberOfRelocations = Data.size();

756 SectionOneHeader->NumberOfLinenumbers = 0;

759}

760

761void WindowsResourceCOFFWriter::writeSecondSectionHeader() {

762

763 CurrentOffset += sizeof(coff_section);

764 auto *SectionTwoHeader =

765 reinterpret_cast<coff_section *>(BufferStart + CurrentOffset);

766 coffnamecpy(SectionTwoHeader->Name, ".rsrc$02");

767 SectionTwoHeader->VirtualSize = 0;

768 SectionTwoHeader->VirtualAddress = 0;

769 SectionTwoHeader->SizeOfRawData = SectionTwoSize;

770 SectionTwoHeader->PointerToRawData = SectionTwoOffset;

771 SectionTwoHeader->PointerToRelocations = 0;

772 SectionTwoHeader->PointerToLinenumbers = 0;

773 SectionTwoHeader->NumberOfRelocations = 0;

774 SectionTwoHeader->NumberOfLinenumbers = 0;

777}

778

779void WindowsResourceCOFFWriter::writeFirstSection() {

780

781 CurrentOffset += sizeof(coff_section);

782

783 writeDirectoryTree();

784 writeDirectoryStringTable();

785 writeFirstSectionRelocations();

786

788}

789

790void WindowsResourceCOFFWriter::writeSecondSection() {

791

792 for (auto const &RawDataEntry : Data) {

793 llvm::copy(RawDataEntry, BufferStart + CurrentOffset);

794 CurrentOffset += alignTo(RawDataEntry.size(), sizeof(uint64_t));

795 }

796

798}

799

800void WindowsResourceCOFFWriter::writeSymbolTable() {

801

802

803 auto *Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);

805 Symbol->Value = 0x11;

806 Symbol->SectionNumber = 0xffff;

809 Symbol->NumberOfAuxSymbols = 0;

811

812

816 Symbol->SectionNumber = 1;

819 Symbol->NumberOfAuxSymbols = 1;

821 auto *Aux = reinterpret_cast<coff_aux_section_definition *>(BufferStart +

822 CurrentOffset);

823 Aux->Length = SectionOneSize;

824 Aux->NumberOfRelocations = Data.size();

825 Aux->NumberOfLinenumbers = 0;

826 Aux->CheckSum = 0;

827 Aux->NumberLowPart = 0;

828 Aux->Selection = 0;

829 CurrentOffset += sizeof(coff_aux_section_definition);

830

831

835 Symbol->SectionNumber = 2;

838 Symbol->NumberOfAuxSymbols = 1;

840 Aux = reinterpret_cast<coff_aux_section_definition *>(BufferStart +

841 CurrentOffset);

842 Aux->Length = SectionTwoSize;

843 Aux->NumberOfRelocations = 0;

844 Aux->NumberOfLinenumbers = 0;

845 Aux->CheckSum = 0;

846 Aux->NumberLowPart = 0;

847 Aux->Selection = 0;

848 CurrentOffset += sizeof(coff_aux_section_definition);

849

850

851 for (unsigned i = 0; i < Data.size(); i++) {

855 Symbol->Value = DataOffsets[i];

856 Symbol->SectionNumber = 2;

859 Symbol->NumberOfAuxSymbols = 0;

861 }

862}

863

864void WindowsResourceCOFFWriter::writeStringTable() {

865

866 auto COFFStringTable = reinterpret_cast<void *>(BufferStart + CurrentOffset);

867 memset(COFFStringTable, 0, 4);

868}

869

870void WindowsResourceCOFFWriter::writeDirectoryTree() {

871

872

873 std::queue<const WindowsResourceParser::TreeNode *> Queue;

874 Queue.push(&Resources);

875 uint32_t NextLevelOffset =

876 sizeof(coff_resource_dir_table) + (Resources.getStringChildren().size() +

877 Resources.getIDChildren().size()) *

878 sizeof(coff_resource_dir_entry);

879 std::vector<const WindowsResourceParser::TreeNode *> DataEntriesTreeOrder;

880 uint32_t CurrentRelativeOffset = 0;

881

882 while (Queue.empty()) {

883 auto CurrentNode = Queue.front();

885 auto *Table = reinterpret_cast<coff_resource_dir_table *>(BufferStart +

886 CurrentOffset);

887 Table->Characteristics = CurrentNode->getCharacteristics();

889 Table->MajorVersion = CurrentNode->getMajorVersion();

890 Table->MinorVersion = CurrentNode->getMinorVersion();

891 auto &IDChildren = CurrentNode->getIDChildren();

892 auto &StringChildren = CurrentNode->getStringChildren();

895 CurrentOffset += sizeof(coff_resource_dir_table);

896 CurrentRelativeOffset += sizeof(coff_resource_dir_table);

897

898

899 for (auto const &Child : StringChildren) {

900 auto *Entry = reinterpret_cast<coff_resource_dir_entry *>(BufferStart +

901 CurrentOffset);

902 Entry->Identifier.setNameOffset(

903 StringTableOffsets[Child.second->getStringIndex()]);

904 if (Child.second->checkIsDataNode()) {

905 Entry->Offset.DataEntryOffset = NextLevelOffset;

906 NextLevelOffset += sizeof(coff_resource_data_entry);

907 DataEntriesTreeOrder.push_back(Child.second.get());

908 } else {

909 Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);

910 NextLevelOffset += sizeof(coff_resource_dir_table) +

911 (Child.second->getStringChildren().size() +

912 Child.second->getIDChildren().size()) *

913 sizeof(coff_resource_dir_entry);

914 Queue.push(Child.second.get());

915 }

916 CurrentOffset += sizeof(coff_resource_dir_entry);

917 CurrentRelativeOffset += sizeof(coff_resource_dir_entry);

918 }

919 for (auto const &Child : IDChildren) {

920 auto *Entry = reinterpret_cast<coff_resource_dir_entry *>(BufferStart +

921 CurrentOffset);

922 Entry->Identifier.ID = Child.first;

923 if (Child.second->checkIsDataNode()) {

924 Entry->Offset.DataEntryOffset = NextLevelOffset;

925 NextLevelOffset += sizeof(coff_resource_data_entry);

926 DataEntriesTreeOrder.push_back(Child.second.get());

927 } else {

928 Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);

929 NextLevelOffset += sizeof(coff_resource_dir_table) +

930 (Child.second->getStringChildren().size() +

931 Child.second->getIDChildren().size()) *

932 sizeof(coff_resource_dir_entry);

933 Queue.push(Child.second.get());

934 }

935 CurrentOffset += sizeof(coff_resource_dir_entry);

936 CurrentRelativeOffset += sizeof(coff_resource_dir_entry);

937 }

938 }

939

940 RelocationAddresses.resize(Data.size());

941

942 for (const auto *DataNodes : DataEntriesTreeOrder) {

943 auto *Entry = reinterpret_cast<coff_resource_data_entry *>(BufferStart +

944 CurrentOffset);

945 RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;

946 Entry->DataRVA = 0;

947 Entry->DataSize = Data[DataNodes->getDataIndex()].size();

948 Entry->Codepage = 0;

949 Entry->Reserved = 0;

950 CurrentOffset += sizeof(coff_resource_data_entry);

951 CurrentRelativeOffset += sizeof(coff_resource_data_entry);

952 }

953}

954

955void WindowsResourceCOFFWriter::writeDirectoryStringTable() {

956

957 uint32_t TotalStringTableSize = 0;

958 for (auto &String : StringTable) {

961 CurrentOffset += sizeof(uint16_t);

962 auto *Start = reinterpret_cast<UTF16 *>(BufferStart + CurrentOffset);

965 TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t);

966 }

967 CurrentOffset +=

968 alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize;

969}

970

971void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {

972

973

974

975

976 uint32_t NextSymbolIndex = 5;

977 for (unsigned i = 0; i < Data.size(); i++) {

978 auto *Reloc =

979 reinterpret_cast<coff_relocation *>(BufferStart + CurrentOffset);

980 Reloc->VirtualAddress = RelocationAddresses[i];

981 Reloc->SymbolTableIndex = NextSymbolIndex++;

985 break;

988 break;

991 break;

994 break;

995 default:

997 }

998 CurrentOffset += sizeof(coff_relocation);

999 }

1000}

1001

1002Expected<std::unique_ptr>

1008 if (E)

1009 return E;

1010 return Writer.write(TimeDateStamp);

1011}

1012

1013}

1014}

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

static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable, uint64_t MembersOffset, unsigned NumSyms, uint64_t PrevMemberOffset=0, uint64_t NextMemberOffset=0, bool Is64Bit=false)

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

#define RETURN_IF_ERROR(Expr)

static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)

#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED

static ManagedStatic< DebugCounterOwner > Owner

#define UNWRAP_OR_RETURN(Name, Expr)

Definition WindowsResource.cpp:38

#define UNWRAP_REF_OR_RETURN(Name, Expr)

Definition WindowsResource.cpp:32

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

An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.

Provides read only access to a subclass of BinaryStream.

Error readObject(const T *&Dest)

Get a pointer to an object of type T from the underlying stream, as if by memcpy, and store the resul...

LLVM_ABI Error readWideString(ArrayRef< UTF16 > &Dest)

Similar to readCString, however read a null-terminated UTF16 string instead.

Error readInteger(T &Dest)

Read an integer of the specified endianness into Dest and update the stream's offset.

uint64_t getOffset() const

LLVM_ABI Error padToAlignment(uint32_t Align)

void setOffset(uint64_t Off)

Error readArray(ArrayRef< T > &Array, uint32_t NumElements)

Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...

BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.

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.

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

A table of densely packed, null-terminated strings indexed by offset.

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.

static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")

Allocate a new zero-initialized MemoryBuffer of the specified size.

StringRef getFileName() const

LLVM_ABI Error moveNext(bool &End)

Definition WindowsResource.cpp:87

LLVM_ABI Expected< const coff_resource_dir_table & > getBaseTable()

LLVM_ABI Expected< const coff_resource_dir_table & > getEntrySubDir(const coff_resource_dir_entry &Entry)

LLVM_ABI Expected< const coff_resource_data_entry & > getEntryData(const coff_resource_dir_entry &Entry)

LLVM_ABI Expected< ArrayRef< UTF16 > > getEntryNameString(const coff_resource_dir_entry &Entry)

LLVM_ABI Expected< StringRef > getContents(const coff_resource_data_entry &Entry)

LLVM_ABI Expected< const coff_resource_dir_entry & > getTableEntry(const coff_resource_dir_table &Table, uint32_t Index)

WindowsResourceCOFFWriter(COFF::MachineTypes MachineType, const WindowsResourceParser &Parser, Error &E)

Definition WindowsResource.cpp:639

std::unique_ptr< MemoryBuffer > write(uint32_t TimeDateStamp)

Definition WindowsResource.cpp:705

LLVM_ABI uint32_t getTreeSize() const

Definition WindowsResource.cpp:564

LLVM_ABI void print(ScopedPrinter &Writer, StringRef Name) const

Definition WindowsResource.cpp:550

LLVM_ABI void cleanUpManifests(std::vector< std::string > &Duplicates)

Definition WindowsResource.cpp:262

const TreeNode & getTree() const

LLVM_ABI void printTree(raw_ostream &OS) const

Definition WindowsResource.cpp:375

ArrayRef< std::vector< uint8_t > > getData() const

LLVM_ABI WindowsResourceParser(bool MinGW=false)

Definition WindowsResource.cpp:139

ArrayRef< std::vector< UTF16 > > getStringTable() const

LLVM_ABI Error parse(WindowsResource *WR, std::vector< std::string > &Duplicates)

Definition WindowsResource.cpp:328

LLVM_ABI Expected< ResourceEntryRef > getHeadEntry()

Definition WindowsResource.cpp:68

static LLVM_ABI Expected< std::unique_ptr< WindowsResource > > createWindowsResource(MemoryBufferRef Source)

Definition WindowsResource.cpp:59

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

A raw_ostream that writes to an std::string.

std::string & str()

Returns the string's reference.

#define llvm_unreachable(msg)

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

@ IMAGE_SCN_CNT_INITIALIZED_DATA

@ IMAGE_REL_ARM64_ADDR32NB

@ IMAGE_REL_AMD64_ADDR32NB

@ IMAGE_SYM_CLASS_STATIC

Static.

@ IMAGE_FILE_32BIT_MACHINE

Machine is based on a 32bit word architecture.

@ IMAGE_SYM_DTYPE_NULL

No complex type; simple scalar variable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

const uint32_t MIN_HEADER_SIZE

Definition WindowsResource.cpp:44

static void printStringOrID(const WindowsResourceParser::StringOrID &S, raw_string_ostream &OS, bool IsType, bool IsID)

Definition WindowsResource.cpp:212

LLVM_ABI Expected< std::unique_ptr< MemoryBuffer > > writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, const WindowsResourceParser &Parser, uint32_t TimeDateStamp)

Definition WindowsResource.cpp:1003

const size_t WIN_RES_NULL_ENTRY_SIZE

const uint32_t WIN_RES_DATA_ALIGNMENT

LLVM_ABI void printResourceTypeName(uint16_t TypeID, raw_ostream &OS)

Definition WindowsResource.cpp:142

const uint32_t WIN_RES_HEADER_ALIGNMENT

static std::string makeDuplicateResourceError(const ResourceEntryRef &Entry, StringRef File1, StringRef File2)

Definition WindowsResource.cpp:180

static void coffnamecpy(char(&Dest)[COFF::NameSize], StringRef Src)

Definition WindowsResource.cpp:721

const size_t WIN_RES_MAGIC_SIZE

coff_symbol< support::ulittle16_t > coff_symbol16

static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID, ArrayRef< UTF16 > &Str, bool &IsString)

Definition WindowsResource.cpp:98

static bool convertUTF16LEToUTF8String(ArrayRef< UTF16 > Src, std::string &Out)

Definition WindowsResource.cpp:169

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

const uint32_t SECTION_ALIGNMENT

Definition WindowsResource.cpp:48

NodeAddr< NodeBase * > Node

void write16le(void *P, uint16_t V)

constexpr bool IsBigEndianHost

This is an optimization pass for GlobalISel generic memory operations.

Triple::ArchType getMachineArchType(T machine)

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

Create formatted StringError object.

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

LLVM_ABI bool convertUTF16ToUTF8String(ArrayRef< char > SrcBytes, std::string &Out)

Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.

const char * to_string(ThinOrFullLTOPhase Phase)

Error make_error(ArgTs &&... Args)

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

@ Ref

The access may reference the value stored in memory.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

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

OutputIt copy(R &&Range, OutputIt Out)

LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)

void consumeError(Error Err)

Consume a Error without doing anything.

support::ulittle16_t NumberOfNameEntries

support::ulittle32_t Characteristics

support::ulittle16_t NumberOfIDEntries

support::ulittle32_t TimeDateStamp

support::ulittle16_t MinorVersion

support::ulittle16_t MajorVersion