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