1//===-- WindowsResource.cpp -------------------------------------*- C++ -*-===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 9// This file implements the .res file class. 11//===----------------------------------------------------------------------===// 28#define RETURN_IF_ERROR(X) \ 32#define UNWRAP_REF_OR_RETURN(Name, Expr) \ 33 auto Name##OrErr = Expr; \ 35 return Name##OrErr.takeError(); \ 36 const auto &Name = *Name##OrErr; 38#define UNWRAP_OR_RETURN(Name, Expr) \ 39 auto Name##OrErr = Expr; \ 41 return Name##OrErr.takeError(); \ 42 auto Name = *Name##OrErr; 46// COFF files seem to be inconsistent with alignment between sections, just use 47// 8-byte because it makes everyone happy. 61return make_error<GenericBinaryError>(
62 Source.getBufferIdentifier() +
": too small to be a resource file",
63 object_error::invalid_file_type);
70return make_error<EmptyResError>(
getFileName() +
" contains no entries",
71 object_error::unexpected_eof);
77 : Reader(
Ref), Owner(Owner) {}
82if (
auto E =
Ref.loadNext())
88// Reached end of all the entries. 102 IsString = IDFlag != 0xffff;
107sizeof(
uint16_t));
// Re-read the bytes which we used to check the flag. 115Error ResourceEntryRef::loadNext() {
120return make_error<GenericBinaryError>(Owner->
getFileName() +
121": header size too small",
140 : Root(
false), MinGW(MinGW) {}
144case 1:
OS <<
"CURSOR (ID 1)";
break;
145case 2:
OS <<
"BITMAP (ID 2)";
break;
146case 3:
OS <<
"ICON (ID 3)";
break;
147case 4:
OS <<
"MENU (ID 4)";
break;
148case 5:
OS <<
"DIALOG (ID 5)";
break;
149case 6:
OS <<
"STRINGTABLE (ID 6)";
break;
150case 7:
OS <<
"FONTDIR (ID 7)";
break;
151case 8:
OS <<
"FONT (ID 8)";
break;
152case 9:
OS <<
"ACCELERATOR (ID 9)";
break;
153case 10:
OS <<
"RCDATA (ID 10)";
break;
154case 11:
OS <<
"MESSAGETABLE (ID 11)";
break;
155case 12:
OS <<
"GROUP_CURSOR (ID 12)";
break;
156case 14:
OS <<
"GROUP_ICON (ID 14)";
break;
157case 16:
OS <<
"VERSIONINFO (ID 16)";
break;
158case 17:
OS <<
"DLGINCLUDE (ID 17)";
break;
159case 19:
OS <<
"PLUGPLAY (ID 19)";
break;
160case 20:
OS <<
"VXD (ID 20)";
break;
161case 21:
OS <<
"ANICURSOR (ID 21)";
break;
162case 22:
OS <<
"ANIICON (ID 22)";
break;
163case 23:
OS <<
"HTML (ID 23)";
break;
164case 24:
OS <<
"MANIFEST (ID 24)";
break;
173 std::vector<UTF16> EndianCorrectedSrc;
174 EndianCorrectedSrc.resize(Src.size() + 1);
175llvm::copy(Src, EndianCorrectedSrc.begin() + 1);
185OS <<
"duplicate resource:";
188if (Entry.checkTypeString()) {
191UTF8 =
"(failed conversion from UTF16)";
197if (Entry.checkNameString()) {
200UTF8 =
"(failed conversion from UTF16)";
203OS <<
"ID " << Entry.getNameID();
206OS <<
"/language " << Entry.getLanguage() <<
", in " << File1 <<
" and in " 217UTF8 =
"(failed conversion from UTF16)";
228const std::vector<WindowsResourceParser::StringOrID> &Context,
233OS <<
"duplicate resource:";
235if (Context.size() >= 1) {
240if (Context.size() >= 2) {
245if (Context.size() >= 3) {
249OS <<
", in " << File1 <<
" and in " << File2;
254// MinGW specific. Remove default manifests (with language zero) if there are 255// other manifests present, and report an error if there are more than one 256// manifest with a non-zero language code. 257// GCC has the concept of a default manifest resource object, which gets 258// linked in implicitly if present. This default manifest has got language 259// id zero, and should be dropped silently if there's another manifest present. 260// If the user resources surprisignly had a manifest with language id zero, 261// we should also ignore the duplicate default manifest. 263 std::vector<std::string> &Duplicates) {
264auto TypeIt = Root.IDChildren.find(
/* RT_MANIFEST */ 24);
265if (TypeIt == Root.IDChildren.end())
268TreeNode *TypeNode = TypeIt->second.get();
270 TypeNode->IDChildren.find(
/* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 1);
271if (NameIt == TypeNode->IDChildren.end())
274TreeNode *NameNode = NameIt->second.get();
275if (NameNode->IDChildren.size() <= 1)
276return;
// None or one manifest present, all good. 278// If we have more than one manifest, drop the language zero one if present, 280auto LangZeroIt = NameNode->IDChildren.find(0);
281if (LangZeroIt != NameNode->IDChildren.end() &&
282 LangZeroIt->second->IsDataNode) {
283uint32_t RemovedIndex = LangZeroIt->second->DataIndex;
284 NameNode->IDChildren.erase(LangZeroIt);
285 Data.erase(Data.begin() + RemovedIndex);
286 Root.shiftDataIndexDown(RemovedIndex);
288// If we're now down to one manifest, all is good. 289if (NameNode->IDChildren.size() <= 1)
293// More than one non-language-zero manifest 294auto FirstIt = NameNode->IDChildren.begin();
296TreeNode *FirstNode = FirstIt->second.get();
297auto LastIt = NameNode->IDChildren.rbegin();
299TreeNode *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])
307// Ignore duplicates of manifests with language zero (the default manifest), 308// in case the user has provided a manifest with that language id. See 309// the function comment above for context. Only returns true if MinGW is set 311bool WindowsResourceParser::shouldIgnoreDuplicate(
313return MinGW && !Entry.checkTypeString() &&
314 Entry.getTypeID() ==
/* RT_MANIFEST */ 24 &&
315 !Entry.checkNameString() &&
316 Entry.getNameID() ==
/* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 1 &&
317 Entry.getLanguage() == 0;
320bool WindowsResourceParser::shouldIgnoreDuplicate(
321const std::vector<StringOrID> &Context)
const{
322return MinGW && Context.size() == 3 && !Context[0].IsString &&
323 Context[0].ID ==
/* RT_MANIFEST */ 24 && !Context[1].IsString &&
324 Context[1].ID ==
/* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 1 &&
325 !Context[2].IsString && Context[2].ID == 0;
329 std::vector<std::string> &Duplicates) {
332auto E = EntryOrErr.takeError();
334// Check if the .res file contains no entries. In this case we don't have 335// to throw an error but can rather just return without parsing anything. 336// This applies for files which have a valid PE header magic and the 337// mandatory empty null resource entry. Files which do not fit this 338// criteria would have already been filtered out by 339// WindowsResource::createWindowsResource(). 347uint32_t Origin = InputFilenames.size();
348 InputFilenames.push_back(std::string(WR->
getFileName()));
353bool IsNewNode = Root.addEntry(Entry, Origin, Data,
StringTable, Node);
355if (!shouldIgnoreDuplicate(Entry))
357 Entry, InputFilenames[Node->Origin], WR->
getFileName()));
367 std::vector<std::string> &Duplicates) {
369uint32_t Origin = InputFilenames.size();
370 InputFilenames.push_back(std::string(Filename));
371 std::vector<StringOrID> Context;
372return addChildren(Root, RSR, BaseTable, Origin, Context, Duplicates);
377 Root.
print(Writer,
"Resource Tree");
380bool WindowsResourceParser::TreeNode::addEntry(
382 std::vector<std::vector<uint8_t>> &
Data,
383 std::vector<std::vector<UTF16>> &
StringTable, TreeNode *&Result) {
384 TreeNode &TypeNode = addTypeNode(Entry,
StringTable);
385 TreeNode &NameNode = TypeNode.addNameNode(Entry,
StringTable);
386return NameNode.addLanguageNode(Entry, Origin, Data, Result);
389Error WindowsResourceParser::addChildren(TreeNode &Node,
393 std::vector<StringOrID> &Context,
394 std::vector<std::string> &Duplicates) {
401if (Entry.Offset.isSubDir()) {
403// Create a new subdirectory and recurse 406 Child = &Node.addNameChild(NameString,
StringTable);
407 Context.push_back(StringOrID(NameString));
409 Child = &
Node.addIDChild(Entry.Identifier.ID);
410 Context.push_back(StringOrID(Entry.Identifier.ID));
415 addChildren(*Child, RSR, NextTable, Origin, Context, Duplicates);
422// Data leaves are supposed to have a numeric ID as identifier (language). 425"unexpected string key for data object");
427// Try adding a data leaf 430 Context.push_back(StringOrID(
Entry.Identifier.ID));
433 Origin, Data.size(), Child);
437reinterpret_cast<constuint8_t *
>(Contents.data()),
440if (!shouldIgnoreDuplicate(Context))
442 Context, InputFilenames[Child->Origin], InputFilenames.back()));
451WindowsResourceParser::TreeNode::TreeNode(
uint32_t StringIndex)
452 : StringIndex(StringIndex) {}
454WindowsResourceParser::TreeNode::TreeNode(
uint16_t MajorVersion,
458 : IsDataNode(
true), DataIndex(DataIndex), MajorVersion(MajorVersion),
462std::unique_ptr<WindowsResourceParser::TreeNode>
463WindowsResourceParser::TreeNode::createStringNode(
uint32_t Index) {
464return std::unique_ptr<TreeNode>(
new TreeNode(Index));
467std::unique_ptr<WindowsResourceParser::TreeNode>
468WindowsResourceParser::TreeNode::createIDNode() {
469return std::unique_ptr<TreeNode>(
new TreeNode(0));
472std::unique_ptr<WindowsResourceParser::TreeNode>
473WindowsResourceParser::TreeNode::createDataNode(
uint16_t MajorVersion,
478return std::unique_ptr<TreeNode>(
new TreeNode(
485if (
Entry.checkTypeString())
488return addIDChild(
Entry.getTypeID());
494if (
Entry.checkNameString())
497return addIDChild(
Entry.getNameID());
500bool WindowsResourceParser::TreeNode::addLanguageNode(
502 std::vector<std::vector<uint8_t>> &Data, TreeNode *&Result) {
504Entry.getMinorVersion(),
Entry.getCharacteristics(),
505 Origin, Data.size(), Result);
507 Data.push_back(
Entry.getData());
511bool WindowsResourceParser::TreeNode::addDataChild(
515auto NewChild = createDataNode(MajorVersion, MinorVersion,
Characteristics,
517auto ElementInserted = IDChildren.emplace(
ID, std::move(NewChild));
518Result = ElementInserted.first->second.get();
519return ElementInserted.second;
524auto Child = IDChildren.find(
ID);
525if (Child == IDChildren.end()) {
526auto NewChild = createIDNode();
528 IDChildren.emplace(
ID, std::move(NewChild));
531return *(Child->second);
536 std::string NameString;
539auto Child = StringChildren.find(NameString);
540if (Child == StringChildren.end()) {
544 StringChildren.emplace(NameString, std::move(NewChild));
547return *(Child->second);
553for (
autoconst &Child : StringChildren) {
554 Child.second->print(Writer, Child.first);
556for (
autoconst &Child : IDChildren) {
557 Child.second->print(Writer,
to_string(Child.first));
561// This function returns the size of the entire resource tree, including 562// directory tables, directory entries, and data entries. It does not include 563// the directory strings or the relocations of the .rsrc section. 565uint32_tSize = (IDChildren.size() + StringChildren.size()) *
568// Reached a node pointing to a data entry. 574// If the node does not point to data, it must have a directory table pointing 578for (
autoconst &Child : StringChildren) {
579Size += Child.second->getTreeSize();
581for (
autoconst &Child : IDChildren) {
582Size += Child.second->getTreeSize();
587// Shift DataIndex of all data children with an Index greater or equal to the 588// given one, to fill a gap from removing an entry from the Data vector. 589void WindowsResourceParser::TreeNode::shiftDataIndexDown(
uint32_t Index) {
590if (IsDataNode && DataIndex >= Index) {
593for (
auto &Child : IDChildren)
594 Child.second->shiftDataIndexDown(Index);
595for (
auto &Child : StringChildren)
596 Child.second->shiftDataIndexDown(Index);
607void performFileLayout();
608void performSectionOneLayout();
609void performSectionTwoLayout();
610void writeCOFFHeader(
uint32_t TimeDateStamp);
611void writeFirstSectionHeader();
612void writeSecondSectionHeader();
613void writeFirstSection();
614void writeSecondSection();
617void writeDirectoryTree();
618void writeDirectoryStringTable();
619void writeFirstSectionRelocations();
620 std::unique_ptr<WritableMemoryBuffer> OutputBuffer;
634 std::vector<uint32_t> StringTableOffsets;
635 std::vector<uint32_t> DataOffsets;
636 std::vector<uint32_t> RelocationAddresses;
647 FileSize,
"internal .obj file created from .res files");
650void WindowsResourceCOFFWriter::performFileLayout() {
651// Add size of COFF header. 654// one .rsrc section header for directory tree, another for resource data. 657 performSectionOneLayout();
658 performSectionTwoLayout();
660// We have reached the address of the symbol table. 661 SymbolTableOffset = FileSize;
666 FileSize += 4;
// four null bytes for the string table. 669void WindowsResourceCOFFWriter::performSectionOneLayout() {
670 SectionOneOffset = FileSize;
673uint32_t CurrentStringOffset = SectionOneSize;
676 StringTableOffsets.push_back(CurrentStringOffset);
678 CurrentStringOffset += StringSize;
679 TotalStringTableSize += StringSize;
683// account for the relocations of section one. 684 SectionOneRelocations = FileSize + SectionOneSize;
685 FileSize += SectionOneSize;
691void WindowsResourceCOFFWriter::performSectionTwoLayout() {
692// add size of .rsrc$2 section, which contains all resource data on 8-byte 694 SectionTwoOffset = FileSize;
696for (
autoconst &Entry : Data) {
697 DataOffsets.push_back(SectionTwoSize);
700 FileSize += SectionTwoSize;
704std::unique_ptr<MemoryBuffer>
706 BufferStart = OutputBuffer->getBufferStart();
708 writeCOFFHeader(TimeDateStamp);
709 writeFirstSectionHeader();
710 writeSecondSectionHeader();
712 writeSecondSection();
716return std::move(OutputBuffer);
719// According to COFF specification, if the Src has a size equal to Dest, 720// it's okay to *not* copy the trailing zero. 723"Src is larger than COFF::NameSize");
725"Dest not zeroed upon initialization");
726 memcpy(Dest, Src.data(), Src.size());
729void WindowsResourceCOFFWriter::writeCOFFHeader(
uint32_t TimeDateStamp) {
730// Write the COFF header. 732 Header->Machine = MachineType;
733 Header->NumberOfSections = 2;
734 Header->TimeDateStamp = TimeDateStamp;
735 Header->PointerToSymbolTable = SymbolTableOffset;
736// One symbol for every resource plus 2 for each section and 1 for @feat.00 737 Header->NumberOfSymbols = Data.size() + 5;
738 Header->SizeOfOptionalHeader = 0;
739// cvtres.exe sets 32BIT_MACHINE even for 64-bit machine types. Match it. 743void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
744// Write the first section header. 746auto *SectionOneHeader =
747reinterpret_cast<coff_section *
>(BufferStart + CurrentOffset);
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;
761void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
762// Write the second section header. 764auto *SectionTwoHeader =
765reinterpret_cast<coff_section *
>(BufferStart + CurrentOffset);
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;
779void WindowsResourceCOFFWriter::writeFirstSection() {
783 writeDirectoryTree();
784 writeDirectoryStringTable();
785 writeFirstSectionRelocations();
790void WindowsResourceCOFFWriter::writeSecondSection() {
791// Now write the .rsrc$02 section. 792for (
autoconst &RawDataEntry : Data) {
793llvm::copy(RawDataEntry, BufferStart + CurrentOffset);
800void WindowsResourceCOFFWriter::writeSymbolTable() {
801// Now write the symbol table. 802// First, the feat symbol. 806Symbol->SectionNumber = 0xffff;
809Symbol->NumberOfAuxSymbols = 0;
812// Now write the .rsrc1 symbol + aux. 819Symbol->NumberOfAuxSymbols = 1;
823 Aux->
Length = SectionOneSize;
824 Aux->NumberOfRelocations = Data.size();
825 Aux->NumberOfLinenumbers = 0;
827 Aux->NumberLowPart = 0;
831// Now write the .rsrc2 symbol + aux. 838Symbol->NumberOfAuxSymbols = 1;
842 Aux->
Length = SectionTwoSize;
843 Aux->NumberOfRelocations = 0;
844 Aux->NumberOfLinenumbers = 0;
846 Aux->NumberLowPart = 0;
850// Now write a symbol for each relocation. 851for (
unsigned i = 0; i < Data.size(); i++) {
855Symbol->Value = DataOffsets[i];
859Symbol->NumberOfAuxSymbols = 0;
864void WindowsResourceCOFFWriter::writeStringTable() {
865// Just 4 null bytes for the string table. 866auto COFFStringTable =
reinterpret_cast<void *
>(BufferStart + CurrentOffset);
867 memset(COFFStringTable, 0, 4);
870void WindowsResourceCOFFWriter::writeDirectoryTree() {
871// Traverse parsed resource tree breadth-first and write the corresponding 873 std::queue<const WindowsResourceParser::TreeNode *>
Queue;
874Queue.push(&Resources);
879 std::vector<const WindowsResourceParser::TreeNode *> DataEntriesTreeOrder;
882while (!
Queue.empty()) {
883auto CurrentNode =
Queue.front();
891auto &IDChildren = CurrentNode->getIDChildren();
892auto &StringChildren = CurrentNode->getStringChildren();
898// Write the directory entries immediately following each directory table. 899for (
autoconst &Child : StringChildren) {
902Entry->Identifier.setNameOffset(
903 StringTableOffsets[Child.second->getStringIndex()]);
904if (Child.second->checkIsDataNode()) {
905Entry->Offset.DataEntryOffset = NextLevelOffset;
907 DataEntriesTreeOrder.push_back(Child.second.get());
909Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
911 (Child.second->getStringChildren().size() +
912 Child.second->getIDChildren().size()) *
914Queue.push(Child.second.get());
919for (
autoconst &Child : IDChildren) {
922Entry->Identifier.ID = Child.first;
923if (Child.second->checkIsDataNode()) {
924Entry->Offset.DataEntryOffset = NextLevelOffset;
926 DataEntriesTreeOrder.push_back(Child.second.get());
928Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
930 (Child.second->getStringChildren().size() +
931 Child.second->getIDChildren().size()) *
933Queue.push(Child.second.get());
940 RelocationAddresses.resize(Data.size());
941// Now write all the resource data entries. 942for (
constauto *DataNodes : DataEntriesTreeOrder) {
945 RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;
946Entry->DataRVA = 0;
// Set to zero because it is a relocation. 947Entry->DataSize = Data[DataNodes->getDataIndex()].size();
955void WindowsResourceCOFFWriter::writeDirectoryStringTable() {
956// Now write the directory string table for .rsrc$01 962auto *Start =
reinterpret_cast<UTF16 *
>(BufferStart + CurrentOffset);
971void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
973// Now write the relocations for .rsrc$01 974// Five symbols already in table before we start, @feat.00 and 2 for each 977for (
unsigned i = 0; i < Data.size(); i++) {
981 Reloc->SymbolTableIndex = NextSymbolIndex++;
1010return Writer.
write(TimeDateStamp);
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)
COFFYAML::WeakExternalCharacteristics Characteristics
static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)
#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define UNWRAP_OR_RETURN(Name, Expr)
#define UNWRAP_REF_OR_RETURN(Name, Expr)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
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...
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 bytesRemaining() const
uint64_t getOffset() const
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.
constexpr size_t size() const
Returns the byte size of the table.
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.
TypeID
Definitions of all of the base types for the Type system.
static std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
StringRef getFileName() const
Error moveNext(bool &End)
Expected< const coff_resource_dir_table & > getBaseTable()
Expected< const coff_resource_dir_table & > getEntrySubDir(const coff_resource_dir_entry &Entry)
Expected< const coff_resource_data_entry & > getEntryData(const coff_resource_dir_entry &Entry)
Expected< ArrayRef< UTF16 > > getEntryNameString(const coff_resource_dir_entry &Entry)
Expected< StringRef > getContents(const coff_resource_data_entry &Entry)
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)
std::unique_ptr< MemoryBuffer > write(uint32_t TimeDateStamp)
const Children< std::string > & getStringChildren() const
uint32_t getTreeSize() const
const Children< uint32_t > & getIDChildren() const
void print(ScopedPrinter &Writer, StringRef Name) const
void cleanUpManifests(std::vector< std::string > &Duplicates)
const TreeNode & getTree() const
void printTree(raw_ostream &OS) const
ArrayRef< std::vector< uint8_t > > getData() const
WindowsResourceParser(bool MinGW=false)
ArrayRef< std::vector< UTF16 > > getStringTable() const
Error parse(WindowsResource *WR, std::vector< std::string > &Duplicates)
Expected< ResourceEntryRef > getHeadEntry()
static Expected< std::unique_ptr< WindowsResource > > createWindowsResource(MemoryBufferRef Source)
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.
#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.
const uint32_t MIN_HEADER_SIZE
static void printStringOrID(const WindowsResourceParser::StringOrID &S, raw_string_ostream &OS, bool IsType, bool IsID)
Expected< std::unique_ptr< MemoryBuffer > > writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, const WindowsResourceParser &Parser, uint32_t TimeDateStamp)
const size_t WIN_RES_NULL_ENTRY_SIZE
const uint32_t WIN_RES_DATA_ALIGNMENT
void printResourceTypeName(uint16_t TypeID, raw_ostream &OS)
const uint32_t WIN_RES_HEADER_ALIGNMENT
static std::string makeDuplicateResourceError(const ResourceEntryRef &Entry, StringRef File1, StringRef File2)
static void coffnamecpy(char(&Dest)[COFF::NameSize], StringRef Src)
const size_t WIN_RES_MAGIC_SIZE
static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID, ArrayRef< UTF16 > &Str, bool &IsString)
static bool convertUTF16LEToUTF8String(ArrayRef< UTF16 > Src, std::string &Out)
coff_symbol< support::ulittle16_t > coff_symbol16
static void writeStringTable(std::vector< uint8_t > &B, ArrayRef< const std::string_view > Strings)
const uint32_t SECTION_ALIGNMENT
void write16le(void *P, uint16_t V)
constexpr bool IsBigEndianHost
This is an optimization pass for GlobalISel generic memory operations.
std::string to_string(const T &Value)
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)
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
bool convertUTF16ToUTF8String(ArrayRef< char > SrcBytes, std::string &Out)
Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
@ Ref
The access may reference the value stored in memory.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt copy(R &&Range, OutputIt Out)
void consumeError(Error Err)
Consume a Error without doing anything.
support::ulittle32_t Length
support::ulittle32_t VirtualAddress
support::ulittle16_t NumberOfNameEntries
support::ulittle32_t Characteristics
support::ulittle16_t NumberOfIDEntries
support::ulittle32_t TimeDateStamp
support::ulittle16_t MinorVersion
support::ulittle16_t MajorVersion