'\xac', '\x9b', '\xd6', '\xb6', '\x22', '\x26', '\x53', '\xc2',
};
+// The signature bytes that start a .res file.
+static const char WinResMagic[] = {
+ '\x00', '\x00', '\x00', '\x00', '\x20', '\x00', '\x00', '\x00',
+ '\xff', '\xff', '\x00', '\x00', '\xff', '\xff', '\x00', '\x00',
+};
+
// Sizes in bytes of various things in the COFF format.
enum {
Header16Size = 20,
#include <map>
namespace llvm {
-
namespace object {
class WindowsResource;
-enum class Machine { UNKNOWN, ARM, X64, X86 };
+const size_t WIN_RES_MAGIC_SIZE = 16;
+const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
+const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
+const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
+const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
+
+struct WinResHeaderPrefix {
+ support::ulittle32_t DataSize;
+ support::ulittle32_t HeaderSize;
+};
+
+// Type and Name may each either be an integer ID or a string. This struct is
+// only used in the case where they are both IDs.
+struct WinResIDs {
+ uint16_t TypeFlag;
+ support::ulittle16_t TypeID;
+ uint16_t NameFlag;
+ support::ulittle16_t NameID;
+
+ void setType(uint16_t ID) {
+ TypeFlag = 0xffff;
+ TypeID = ID;
+ }
+
+ void setName(uint16_t ID) {
+ NameFlag = 0xffff;
+ NameID = ID;
+ }
+};
+
+struct WinResHeaderSuffix {
+ support::ulittle32_t DataVersion;
+ support::ulittle16_t MemoryFlags;
+ support::ulittle16_t Language;
+ support::ulittle32_t Version;
+ support::ulittle32_t Characteristics;
+};
class ResourceEntryRef {
public:
Error loadNext();
- struct HeaderSuffix {
- support::ulittle32_t DataVersion;
- support::ulittle16_t MemoryFlags;
- support::ulittle16_t Language;
- support::ulittle32_t Version;
- support::ulittle32_t Characteristics;
- };
-
BinaryStreamReader Reader;
bool IsStringType;
ArrayRef<UTF16> Type;
bool IsStringName;
ArrayRef<UTF16> Name;
uint16_t NameID;
- const HeaderSuffix *Suffix = nullptr;
+ const WinResHeaderSuffix *Suffix = nullptr;
ArrayRef<uint8_t> Data;
const WindowsResource *OwningRes = nullptr;
};
return file_magic::coff_import_library;
}
// Windows resource file
- if (startswith(Magic, "\0\0\0\0\x20\0\0\0\xFF"))
+ if (Magic.size() >= sizeof(COFF::WinResMagic) &&
+ memcmp(Magic.data(), COFF::WinResMagic, sizeof(COFF::WinResMagic)) == 0)
return file_magic::windows_resource;
// 0x0000 = COFF unknown machine type
if (Magic[1] == 0)
// 8-byte because it makes everyone happy.
const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t);
-static const size_t ResourceMagicSize = 16;
-
-static const size_t NullEntrySize = 16;
-
uint32_t WindowsResourceParser::TreeNode::StringCount = 0;
uint32_t WindowsResourceParser::TreeNode::DataCount = 0;
WindowsResource::WindowsResource(MemoryBufferRef Source)
: Binary(Binary::ID_WinRes, Source) {
- size_t LeadingSize = ResourceMagicSize + NullEntrySize;
+ size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE;
BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
support::little);
}
Expected<std::unique_ptr<WindowsResource>>
WindowsResource::createWindowsResource(MemoryBufferRef Source) {
- if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
+ if (Source.getBufferSize() < WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE)
return make_error<GenericBinaryError>(
"File too small to be a resource file",
object_error::invalid_file_type);
}
Error ResourceEntryRef::loadNext() {
- uint32_t DataSize;
- RETURN_IF_ERROR(Reader.readInteger(DataSize));
- uint32_t HeaderSize;
- RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
+ const WinResHeaderPrefix *Prefix;
+ RETURN_IF_ERROR(Reader.readObject(Prefix));
- if (HeaderSize < MIN_HEADER_SIZE)
+ if (Prefix->HeaderSize < MIN_HEADER_SIZE)
return make_error<GenericBinaryError>("Header size is too small.",
object_error::parse_failed);
RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName));
- RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+ RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_HEADER_ALIGNMENT));
RETURN_IF_ERROR(Reader.readObject(Suffix));
- RETURN_IF_ERROR(Reader.readArray(Data, DataSize));
+ RETURN_IF_ERROR(Reader.readArray(Data, Prefix->DataSize));
- RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+ RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_DATA_ALIGNMENT));
return Error::success();
}
: MachineType(MachineType), Resources(Parser.getTree()),
Data(Parser.getData()), StringTable(Parser.getStringTable()) {
performFileLayout();
+
OutputBuffer = MemoryBuffer::getNewMemBuffer(FileSize);
}
SectionOneHeader->PointerToLinenumbers = 0;
SectionOneHeader->NumberOfRelocations = Data.size();
SectionOneHeader->NumberOfLinenumbers = 0;
- SectionOneHeader->Characteristics = COFF::IMAGE_SCN_ALIGN_1BYTES;
- SectionOneHeader->Characteristics += COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
SectionOneHeader->Characteristics += COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
SectionOneHeader->Characteristics += COFF::IMAGE_SCN_MEM_READ;
}
std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),
FileBuffer->getBufferStart());
error(FileBuffer->commit());
+
if (Verbose) {
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(OutputFile);
if (!BinaryOrErr)
"\xfe\xed\xfa\xce........\x00\x00\x00\x0a............";
const char macho_kext_bundle[] =
"\xfe\xed\xfa\xce........\x00\x00\x00\x0b............";
-const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff";
+const char windows_resource[] =
+ "\x00\x00\x00\x00\x020\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00";
const char macho_dynamically_linked_shared_lib_stub[] =
"\xfe\xed\xfa\xce........\x00\x00\x00\x09............";