mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-25 13:05:00 -07:00
pass over COFF resource reader and writer
This commit is contained in:
+119
-130
@@ -550,6 +550,39 @@ coff_make_import_header_by_ordinal(Arena *arena,
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resources
|
||||
|
||||
internal String8
|
||||
coff_resource_string_from_str16(Arena *arena, String16 string)
|
||||
{
|
||||
AssertAlways(string.size <= max_U16);
|
||||
U16 size16 = (U16)string.size;
|
||||
|
||||
U16 *buffer = push_array_no_zero(arena, U16, size16 + 1);
|
||||
MemoryCopy(buffer + 0, &size16, sizeof(size16));
|
||||
MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0]));
|
||||
|
||||
return str8_array(buffer, size16 + 1);
|
||||
}
|
||||
|
||||
internal String8
|
||||
coff_resource_string_from_str8(Arena *arena, String8 string)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String16 string16 = str16_from_8(scratch.arena, string);
|
||||
String8 result = coff_resource_string_from_str16(arena, string16);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
coff_resource_number_from_u16(Arena *arena, U16 number)
|
||||
{
|
||||
U16 *buffer = push_array_no_zero(arena, U16, 2);
|
||||
buffer[0] = max_U16;
|
||||
buffer[1] = number;
|
||||
return str8_array(buffer, 2);
|
||||
}
|
||||
|
||||
internal B32
|
||||
coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b)
|
||||
@@ -567,47 +600,9 @@ coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b)
|
||||
}
|
||||
|
||||
internal COFF_ResourceID
|
||||
coff_resource_id_copy(Arena *arena, COFF_ResourceID id)
|
||||
coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID_16 *id_16)
|
||||
{
|
||||
COFF_ResourceID result = zero_struct;
|
||||
switch (id.type) {
|
||||
case COFF_ResourceIDType_NULL: break;
|
||||
case COFF_ResourceIDType_NUMBER: {
|
||||
result.type = COFF_ResourceIDType_NUMBER;
|
||||
result.u.number = id.u.number;
|
||||
} break;
|
||||
case COFF_ResourceIDType_STRING: {
|
||||
result.type = COFF_ResourceIDType_STRING;
|
||||
result.u.string = id.u.string;
|
||||
} break;
|
||||
default: Assert(!"invalid resource id type");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
coff_sizeof_resource_id(COFF_ResourceID id)
|
||||
{
|
||||
U64 size = 0;
|
||||
switch (id.type) {
|
||||
case COFF_ResourceIDType_NULL: break;
|
||||
case COFF_ResourceIDType_NUMBER: {
|
||||
size += sizeof(U16);
|
||||
size += sizeof(U16);
|
||||
} break;
|
||||
case COFF_ResourceIDType_STRING: {
|
||||
size += sizeof(U16);
|
||||
size += (id.u.string.size + /* null: */1) * sizeof(U16);
|
||||
} break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
return AlignPow2(size, COFF_RES_ALIGN);
|
||||
}
|
||||
|
||||
internal COFF_ResourceID
|
||||
coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16)
|
||||
{
|
||||
COFF_ResourceID id;
|
||||
COFF_ResourceID id = {0};
|
||||
id.type = id_16->type;
|
||||
switch (id_16->type) {
|
||||
case COFF_ResourceIDType_NULL: break;
|
||||
@@ -617,23 +612,22 @@ coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16)
|
||||
case COFF_ResourceIDType_STRING: {
|
||||
id.u.string = str8_from_16(arena, id_16->u.string);
|
||||
} break;
|
||||
default: Assert(!"invalid resource id type");
|
||||
default: InvalidPath;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
internal U64
|
||||
coff_read_resource_id(String8 data, U64 off, COFF_ResourceID_16 *id_out)
|
||||
coff_read_resource_id_utf16(String8 data, U64 off, COFF_ResourceID_16 *id_out)
|
||||
{
|
||||
U64 cursor = off;
|
||||
|
||||
U16 flag = 0;
|
||||
str8_deserial_read_struct(data, cursor, &flag);
|
||||
|
||||
B32 is_number = flag == max_U16;
|
||||
if (is_number) {
|
||||
cursor += sizeof(flag);
|
||||
if (flag == max_U16) {
|
||||
id_out->type = COFF_ResourceIDType_NUMBER;
|
||||
cursor += sizeof(flag);
|
||||
cursor += str8_deserial_read_struct(data, cursor, &id_out->u.number);
|
||||
} else {
|
||||
id_out->type = COFF_ResourceIDType_STRING;
|
||||
@@ -641,93 +635,81 @@ coff_read_resource_id(String8 data, U64 off, COFF_ResourceID_16 *id_out)
|
||||
}
|
||||
|
||||
U64 read_size = cursor - off;
|
||||
read_size = AlignPow2(read_size, COFF_RES_ALIGN);
|
||||
return read_size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
coff_read_resource(String8 raw_res, U64 off, Arena *arena, COFF_Resource *res_out)
|
||||
{
|
||||
// parse header
|
||||
COFF_ResourceHeaderPrefix prefix; MemoryZeroStruct(&prefix);
|
||||
U64 cursor = str8_deserial_read_struct(raw_res, off, &prefix);
|
||||
String8 header_data = str8_substr(raw_res, rng_1u64(off, off + prefix.header_size));
|
||||
String8 raw_header = str8_skip(raw_res, off);
|
||||
U64 header_cursor = 0;
|
||||
|
||||
// prefix
|
||||
COFF_ResourceHeaderPrefix prefix = {0};
|
||||
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix);
|
||||
|
||||
Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix));
|
||||
raw_header = str8_prefix(raw_header, prefix.header_size);
|
||||
|
||||
// header
|
||||
COFF_ResourceID_16 type_16 = {0};
|
||||
COFF_ResourceID_16 name_16 = {0};
|
||||
header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &type_16);
|
||||
header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &name_16);
|
||||
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->data_version);
|
||||
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->memory_flags);
|
||||
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->language_id);
|
||||
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version);
|
||||
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics);
|
||||
Assert(prefix.header_size == header_cursor);
|
||||
|
||||
// convert utf-16 resource ids to utf-8
|
||||
res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16);
|
||||
res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16);
|
||||
|
||||
// read data
|
||||
U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data);
|
||||
Assert(prefix.data_size == data_read_size);
|
||||
|
||||
COFF_ResourceID_16 type_16; MemoryZeroStruct(&type_16);
|
||||
cursor += coff_read_resource_id(header_data, cursor, &type_16);
|
||||
cursor = AlignPow2(cursor, COFF_RES_ALIGN);
|
||||
|
||||
COFF_ResourceID_16 name_16; MemoryZeroStruct(&name_16);
|
||||
cursor += coff_read_resource_id(header_data, cursor, &name_16);
|
||||
cursor = AlignPow2(cursor, COFF_RES_ALIGN);
|
||||
|
||||
U32 data_version = 0;
|
||||
cursor += str8_deserial_read_struct(header_data, cursor, &data_version);
|
||||
|
||||
COFF_ResourceMemoryFlags memory_flags = 0;
|
||||
cursor += str8_deserial_read_struct(header_data, cursor, &memory_flags);
|
||||
|
||||
U16 language_id = 0;
|
||||
cursor += str8_deserial_read_struct(header_data, cursor, &language_id);
|
||||
|
||||
U32 version = 0;
|
||||
cursor += str8_deserial_read_struct(header_data, cursor, &version);
|
||||
|
||||
U32 characteristics = 0;
|
||||
cursor += str8_deserial_read_struct(header_data, cursor, &characteristics);
|
||||
|
||||
String8 data;
|
||||
cursor += str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &data);
|
||||
|
||||
// was resource parsed?
|
||||
Assert(cursor >= prefix.data_size + prefix.header_size);
|
||||
|
||||
// fill out result
|
||||
res_out->type = coff_convert_resource_id(arena, &type_16);
|
||||
res_out->name = coff_convert_resource_id(arena, &name_16);
|
||||
res_out->language_id = language_id;
|
||||
res_out->data_version = data_version;
|
||||
res_out->version = version;
|
||||
res_out->memory_flags = memory_flags;
|
||||
res_out->data = data;
|
||||
|
||||
U64 resource_size = AlignPow2(prefix.data_size + prefix.header_size, COFF_RES_ALIGN);
|
||||
return resource_size;
|
||||
// compute read size
|
||||
U64 read_size = Max(prefix.header_size, sizeof(prefix)) + AlignPow2(prefix.data_size, COFF_RES_ALIGN);
|
||||
return read_size;
|
||||
}
|
||||
|
||||
internal COFF_ResourceList
|
||||
coff_resource_list_from_data(Arena *arena, String8 data)
|
||||
{
|
||||
COFF_ResourceList list; MemoryZeroStruct(&list);
|
||||
for (U64 cursor = 0, stride; cursor < data.size; cursor += stride) {
|
||||
COFF_ResourceList list = {0};
|
||||
U64 cursor;
|
||||
for (cursor = 0 ; cursor < data.size; ) {
|
||||
COFF_ResourceNode *node = push_array(arena, COFF_ResourceNode, 1);
|
||||
stride = coff_read_resource(data, cursor, arena, &node->data);
|
||||
list.count += 1;
|
||||
cursor += coff_read_resource(data, cursor, arena, &node->data);
|
||||
SLLQueuePush(list.first, list.last, node);
|
||||
++list.count;
|
||||
}
|
||||
Assert(cursor == data.size);
|
||||
return list;
|
||||
}
|
||||
|
||||
internal void
|
||||
coff_write_resource_id(Arena *arena, String8List *srl, COFF_ResourceID id)
|
||||
internal String8
|
||||
coff_write_resource_id(Arena *arena, COFF_ResourceID id)
|
||||
{
|
||||
String8 result = str8_zero();
|
||||
switch (id.type) {
|
||||
case COFF_ResourceIDType_NULL: break;
|
||||
case COFF_ResourceIDType_NUMBER: {
|
||||
str8_serial_push_u16(arena, srl, max_U16);
|
||||
str8_serial_push_u16(arena, srl, id.u.number);
|
||||
result = coff_resource_number_from_u16(arena, id.u.number);
|
||||
} break;
|
||||
case COFF_ResourceIDType_STRING: {
|
||||
String16 str16 = str16_from_8(arena, id.u.string);
|
||||
Assert(str16.size <= max_U16);
|
||||
str8_serial_push_u16(arena, srl, str16.size);
|
||||
str8_serial_push_data(arena, srl, str16.str, str16.size);
|
||||
result = coff_resource_string_from_str8(arena, id.u.string);
|
||||
} break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
str8_serial_push_align(arena, srl, COFF_RES_ALIGN);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8List
|
||||
internal String8
|
||||
coff_write_resource(Arena *arena,
|
||||
COFF_ResourceID type,
|
||||
COFF_ResourceID name,
|
||||
@@ -738,34 +720,43 @@ coff_write_resource(Arena *arena,
|
||||
U32 characteristics,
|
||||
String8 data)
|
||||
{
|
||||
U64 header_size = sizeof(COFF_ResourceHeaderPrefix) +
|
||||
coff_sizeof_resource_id(type) +
|
||||
coff_sizeof_resource_id(name) +
|
||||
sizeof(data_version) +
|
||||
sizeof(memory_flags) +
|
||||
sizeof(language_id) +
|
||||
sizeof(version) +
|
||||
sizeof(characteristics);
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
COFF_ResourceHeaderPrefix *header = push_array(arena, COFF_ResourceHeaderPrefix, 1);
|
||||
header->data_size = safe_cast_u32(data.size);
|
||||
header->header_size = safe_cast_u32(header_size);
|
||||
String8List list = {0};
|
||||
|
||||
String8List srl = {0};
|
||||
str8_serial_begin(arena, &srl);
|
||||
str8_serial_push_data(arena, &srl, &g_coff_res_magic[0], sizeof(g_coff_res_magic));
|
||||
str8_serial_push_data(arena, &srl, header, sizeof(*header));
|
||||
coff_write_resource_id(arena, &srl, type);
|
||||
coff_write_resource_id(arena, &srl, name);
|
||||
str8_serial_push_u32(arena, &srl, data_version);
|
||||
str8_serial_push_u16(arena, &srl, memory_flags);
|
||||
str8_serial_push_u16(arena, &srl, language_id);
|
||||
str8_serial_push_u32(arena, &srl, version);
|
||||
str8_serial_push_u32(arena, &srl, characteristics);
|
||||
str8_serial_push_string(arena, &srl, data);
|
||||
str8_serial_push_align(arena, &srl, COFF_RES_ALIGN);
|
||||
COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1);
|
||||
String8 packed_type = coff_write_resource_id(scratch.arena, type);
|
||||
String8 packed_name = coff_write_resource_id(scratch.arena, name);
|
||||
|
||||
return srl;
|
||||
// prefix + header
|
||||
str8_list_push(scratch.arena, &list, str8_struct(prefix));
|
||||
str8_list_push(scratch.arena, &list, packed_type);
|
||||
str8_list_push(scratch.arena, &list, packed_name);
|
||||
str8_list_push(scratch.arena, &list, str8_struct(&data_version));
|
||||
str8_list_push(scratch.arena, &list, str8_struct(&memory_flags));
|
||||
str8_list_push(scratch.arena, &list, str8_struct(&language_id));
|
||||
str8_list_push(scratch.arena, &list, str8_struct(&version));
|
||||
str8_list_push(scratch.arena, &list, str8_struct(&characteristics));
|
||||
|
||||
prefix->data_size = safe_cast_u32(data.size);
|
||||
prefix->header_size = safe_cast_u32(list.total_size);
|
||||
|
||||
// data
|
||||
str8_list_push(scratch.arena, &list, data);
|
||||
|
||||
// magic
|
||||
str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic));
|
||||
|
||||
// align
|
||||
U64 align_size = AlignPow2(list.total_size, COFF_RES_ALIGN) - list.total_size;
|
||||
U8 *align = push_array(scratch.arena, U8, align_size);
|
||||
str8_list_push(scratch.arena, &list, str8(align, align_size));
|
||||
|
||||
// join
|
||||
String8 res = str8_list_join(arena, &list, 0);
|
||||
|
||||
scratch_end(scratch);
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -777,12 +768,10 @@ coff_data_type_from_data(String8 data)
|
||||
if (is_big_obj) {
|
||||
return COFF_DataType_BIG_OBJ;
|
||||
}
|
||||
|
||||
B32 is_import = coff_is_import(data);
|
||||
if (is_import) {
|
||||
return COFF_DataType_IMPORT;
|
||||
}
|
||||
|
||||
return COFF_DataType_OBJ;
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -608,10 +608,11 @@ typedef struct COFF_Resource
|
||||
{
|
||||
COFF_ResourceID type;
|
||||
COFF_ResourceID name;
|
||||
U16 language_id;
|
||||
U32 data_version;
|
||||
U32 version;
|
||||
COFF_ResourceMemoryFlags memory_flags;
|
||||
U16 language_id;
|
||||
U32 version;
|
||||
U32 characteristics;
|
||||
String8 data;
|
||||
} COFF_Resource;
|
||||
|
||||
@@ -877,25 +878,24 @@ internal String8 coff_make_import_header_by_ordinal(Arena *arena,
|
||||
U16 ordinal,
|
||||
COFF_ImportHeaderType type);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resources
|
||||
|
||||
internal B32 coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b);
|
||||
internal COFF_ResourceID coff_resource_id_copy(Arena *arena, COFF_ResourceID id);
|
||||
internal U64 coff_sizeof_resource_id(COFF_ResourceID id);
|
||||
internal COFF_ResourceID coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16);
|
||||
internal U64 coff_read_resource_id(String8 res, U64 off, COFF_ResourceID_16 *id_out);
|
||||
internal String8 coff_resource_string_from_str16(Arena *arena, String16 string);
|
||||
internal String8 coff_resource_string_from_str8(Arena *arena, String8 string);
|
||||
internal String8 coff_resource_number_from_u16(Arena *arena, U16 number);
|
||||
|
||||
internal B32 coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b);
|
||||
internal COFF_ResourceID coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID_16 *id_16);
|
||||
|
||||
internal U64 coff_read_resource_id_utf16(String8 res, U64 off, COFF_ResourceID_16 *id_out);
|
||||
internal U64 coff_read_resource(String8 data, U64 off, Arena *arena, COFF_Resource *res_out);
|
||||
internal COFF_ResourceList coff_resource_list_from_data(Arena *arena, String8 data);
|
||||
|
||||
internal void coff_write_resource_id(Arena *arena, String8List *srl, COFF_ResourceID id);
|
||||
internal String8List coff_write_resource(Arena *arena,
|
||||
COFF_ResourceID type,
|
||||
COFF_ResourceID name,
|
||||
U32 data_version,
|
||||
COFF_ResourceMemoryFlags memory_flags,
|
||||
U16 language_id,
|
||||
U32 version,
|
||||
U32 characteristics,
|
||||
String8 data);
|
||||
internal String8 coff_write_resource_id(Arena *arena, COFF_ResourceID id);
|
||||
internal String8 coff_write_resource(Arena *arena, COFF_ResourceID type, COFF_ResourceID name, U32 data_version, COFF_ResourceMemoryFlags memory_flags, U16 language_id, U32 version, U32 characteristics, String8 data);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal COFF_DataType coff_data_type_from_data(String8 data);
|
||||
internal B32 coff_is_import(String8 data);
|
||||
|
||||
+176
-206
@@ -180,7 +180,7 @@ lnk_input_import_arr_from_list(Arena *arena, LNK_InputImportList list)
|
||||
internal LNK_InputImportList
|
||||
lnk_list_from_input_import_arr(LNK_InputImport **arr, U64 count)
|
||||
{
|
||||
LNK_InputImportList list; MemoryZeroStruct(&list);
|
||||
LNK_InputImportList list = {0};
|
||||
for (U64 i = 0; i < count; i += 1) {
|
||||
SLLQueuePush(list.first, list.last, arr[i]);
|
||||
list.count += 1;
|
||||
@@ -218,12 +218,13 @@ internal void
|
||||
lnk_write_data_list_to_file_path(String8 path, String8List data)
|
||||
{
|
||||
#if PROFILE_TELEMETRY
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 size_str = str8_from_memory_size2(scratch.arena, data.total_size);
|
||||
ProfBeginDynamic("Write %.*s to %.*s", str8_varg(size_str), str8_varg(path));
|
||||
scratch_end(scratch);
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 size_str = str8_from_memory_size2(scratch.arena, data.total_size);
|
||||
ProfBeginDynamic("Write %.*s to %.*s", str8_varg(size_str), str8_varg(path));
|
||||
scratch_end(scratch);
|
||||
}
|
||||
#endif
|
||||
|
||||
B32 is_written = os_write_data_list_to_file_path(path, data);
|
||||
if (is_written) {
|
||||
if (lnk_get_log_status(LNK_Log_IO)) {
|
||||
@@ -256,7 +257,7 @@ lnk_make_full_path(Arena *arena, String8 work_dir, PathStyle system_path_style,
|
||||
PathStyle path_style = path_style_from_str8(path);
|
||||
if (path_style == PathStyle_Relative) {
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List list; MemoryZeroStruct(&list);
|
||||
String8List list = {0};
|
||||
str8_list_push(scratch.arena, &list, work_dir);
|
||||
str8_list_push(scratch.arena, &list, path);
|
||||
result = str8_path_list_join_by_style(arena, &list, system_path_style);
|
||||
@@ -326,10 +327,10 @@ lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
String8List invoke_cmd_line = {0};
|
||||
str8_list_push(scratch.arena, &invoke_cmd_line, mt_path);
|
||||
str8_list_pushf(scratch.arena, &invoke_cmd_line, "-out:%S", out_name);
|
||||
str8_list_pushf(scratch.arena, &invoke_cmd_line, "-nologo");
|
||||
String8List cmd_line = {0};
|
||||
str8_list_push(scratch.arena, &cmd_line, mt_path);
|
||||
str8_list_pushf(scratch.arena, &cmd_line, "-out:%S", out_name);
|
||||
str8_list_pushf(scratch.arena, &cmd_line, "-nologo");
|
||||
|
||||
// register input manifest files on command line
|
||||
String8 work_dir = os_get_current_path(scratch.arena);
|
||||
@@ -343,13 +344,13 @@ lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest
|
||||
full_path = path_convert_slashes(scratch.arena, full_path, PathStyle_UnixAbsolute);
|
||||
|
||||
// push input to command line
|
||||
str8_list_pushf(scratch.arena, &invoke_cmd_line, "-manifest");
|
||||
str8_list_push(scratch.arena, &invoke_cmd_line, full_path);
|
||||
str8_list_pushf(scratch.arena, &cmd_line, "-manifest");
|
||||
str8_list_push(scratch.arena, &cmd_line, full_path);
|
||||
}
|
||||
|
||||
// launch mt.exe with our command line
|
||||
OS_ProcessLaunchParams launch_opts = {0};
|
||||
launch_opts.cmd_line = invoke_cmd_line;
|
||||
launch_opts.cmd_line = cmd_line;
|
||||
launch_opts.path = str8_chop_last_slash(mt_path);
|
||||
launch_opts.inherit_env = 1;
|
||||
launch_opts.consoleless = 1;
|
||||
@@ -413,26 +414,6 @@ lnk_manifest_from_inputs(Arena *arena,
|
||||
return manifest_data;
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_res_from_data(Arena *arena, String8 data)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
COFF_ResourceID type;
|
||||
type.type = COFF_ResourceIDType_NUMBER;
|
||||
type.u.number = PE_ResourceKind_MANIFEST;
|
||||
|
||||
COFF_ResourceID name;
|
||||
name.type = COFF_ResourceIDType_NUMBER;
|
||||
name.u.number = 1;
|
||||
|
||||
String8List res_list = coff_write_resource(arena, type, name, 1, 0, 1033, 0, 0, data);
|
||||
String8 res_data = str8_serial_end(arena, &res_list);
|
||||
|
||||
scratch_end(scratch);
|
||||
return res_data;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal int
|
||||
@@ -461,167 +442,156 @@ internal void
|
||||
lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE_ResourceDir *root_dir)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
static const U64 ALIGN = 4;
|
||||
|
||||
struct stack_s {
|
||||
struct stack_s *next;
|
||||
U64 arr_idx;
|
||||
U64 res_idx[2];
|
||||
PE_ResourceArray res_arr[2];
|
||||
LNK_Chunk *coff_entry_array_chunk;
|
||||
LNK_Chunk *coff_entry_chunk;
|
||||
};
|
||||
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
LNK_Section *dir_sect = lnk_section_table_push(st, str8_lit(".rsrc$01"), LNK_RSRC_SECTION_FLAGS);
|
||||
LNK_Section *dir_sect = lnk_section_table_push(st, str8_lit(".rsrc$01"), LNK_RSRC_SECTION_FLAGS);
|
||||
LNK_Section *data_sect = lnk_section_table_push(st, str8_lit(".rsrc$02"), LNK_RSRC_SECTION_FLAGS);
|
||||
|
||||
LNK_Chunk *dir_tree_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8(0,0));
|
||||
LNK_Chunk *dir_data_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8(0,0));
|
||||
LNK_Chunk *dir_string_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8(0,0));
|
||||
|
||||
LNK_Chunk *dir_tree_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8_zero());
|
||||
LNK_Chunk *dir_data_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8_zero());
|
||||
LNK_Chunk *dir_string_chunk = lnk_section_push_chunk_list(dir_sect, dir_sect->root, str8_zero());
|
||||
|
||||
dir_tree_chunk->sort_idx = str8_lit("a");
|
||||
dir_string_chunk->sort_idx = str8_lit("b");
|
||||
dir_data_chunk->sort_idx = str8_lit("c");
|
||||
|
||||
PE_Resource root_wrapper; MemoryZeroStruct(&root_wrapper);
|
||||
root_wrapper.id.type = COFF_ResourceIDType_NUMBER;
|
||||
PE_Resource root_wrapper = {0};
|
||||
root_wrapper.id.type = COFF_ResourceIDType_NUMBER;
|
||||
root_wrapper.id.u.number = 0;
|
||||
root_wrapper.kind = PE_ResDataKind_DIR;
|
||||
root_wrapper.u.dir = root_dir;
|
||||
root_wrapper.kind = PE_ResDataKind_DIR;
|
||||
root_wrapper.u.dir = root_dir;
|
||||
|
||||
struct stack_s *stack = push_array(scratch.arena, struct stack_s, 1);
|
||||
struct Stack {
|
||||
struct Stack *next;
|
||||
U64 arr_idx;
|
||||
U64 res_idx[2];
|
||||
PE_ResourceArray res_arr[2];
|
||||
LNK_Chunk *coff_entry_array_chunk;
|
||||
LNK_Chunk *coff_entry_chunk;
|
||||
};
|
||||
struct Stack *stack = push_array(scratch.arena, struct Stack, 1);
|
||||
stack->res_arr[0].count = 1;
|
||||
stack->res_arr[0].v = &root_wrapper;
|
||||
stack->res_arr[0].v = &root_wrapper;
|
||||
|
||||
U64 res_counter = 0;
|
||||
U64 total_res_count = 0;
|
||||
|
||||
while (stack) {
|
||||
while (stack->arr_idx < ArrayCount(stack->res_arr)) {
|
||||
while (stack->res_idx[stack->arr_idx] < stack->res_arr[stack->arr_idx].count) {
|
||||
PE_Resource *res = &stack->res_arr[stack->arr_idx].v[stack->res_idx[stack->arr_idx]];
|
||||
stack->res_idx[stack->arr_idx] += 1;
|
||||
++stack->res_idx[stack->arr_idx];
|
||||
|
||||
String8 flag_name = push_str8f(symtab->arena, "flag_%u", res_counter);
|
||||
String8 offset_name = push_str8f(symtab->arena, "offset_%u", res_counter);
|
||||
++res_counter;
|
||||
String8 flag_name = push_str8f(symtab->arena, "flag_%u", total_res_count);
|
||||
String8 offset_name = push_str8f(symtab->arena, "offset_%u", total_res_count);
|
||||
++total_res_count;
|
||||
|
||||
if (stack->coff_entry_array_chunk) {
|
||||
COFF_ResourceDirEntry *entry = push_array(dir_sect->arena, COFF_ResourceDirEntry, 1);
|
||||
stack->coff_entry_chunk = lnk_section_push_chunk_data(dir_sect, stack->coff_entry_array_chunk, str8_struct(entry), str8(0,0));
|
||||
stack->coff_entry_chunk = lnk_section_push_chunk_data(dir_sect, stack->coff_entry_array_chunk, str8_struct(entry), str8_zero());
|
||||
|
||||
switch (res->id.type) {
|
||||
case COFF_ResourceIDType_NUMBER: {
|
||||
entry->name.id = res->id.u.number;
|
||||
} break;
|
||||
case COFF_ResourceIDType_STRING: {
|
||||
// TODO: we can make string table smaller by reusing offsets for same strings
|
||||
|
||||
// not sure why high bit has to be turned on here since number id and string id entries are
|
||||
// in separate arrays but windows doesn't treat name offset like string without this bit.
|
||||
entry->name.offset |= (1 << 31);
|
||||
|
||||
// convert name to utf-16
|
||||
String16 name16 = str16_from_8(dir_sect->arena, res->id.u.string);
|
||||
|
||||
// build name string
|
||||
U64 name16_byte_size = name16.size * sizeof(U16);
|
||||
U64 buffer_size = /* char count: */ sizeof(U16) + name16_byte_size;
|
||||
U8 *buffer = push_array_no_zero(dir_sect->arena, U8, buffer_size);
|
||||
*(U16*)buffer = name16.size;
|
||||
MemoryCopy(buffer + sizeof(U16), name16.str, name16_byte_size);
|
||||
|
||||
// push string table chunk
|
||||
String8 name_data = str8(buffer, buffer_size);
|
||||
LNK_Chunk *name_chunk = lnk_section_push_chunk_data(dir_sect, dir_string_chunk, name_data, str8(0,0));
|
||||
|
||||
// push name chunk symbol
|
||||
LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("COFF_RESOURCE_ID_STRING"), LNK_DefinedSymbolVisibility_Static, 0, name_chunk, 0, 0, 0);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, name.offset), name_symbol);
|
||||
} break;
|
||||
case COFF_ResourceIDType_NULL: break;
|
||||
default: InvalidPath;
|
||||
case COFF_ResourceIDType_NUMBER: {
|
||||
entry->name.id = res->id.u.number;
|
||||
} break;
|
||||
|
||||
case COFF_ResourceIDType_STRING: {
|
||||
// TODO: we can make string table smaller by reusing offsets for same strings
|
||||
|
||||
// not sure why high bit has to be turned on here since number id and string id entries are
|
||||
// in separate arrays but windows doesn't treat name offset like string without this bit.
|
||||
entry->name.offset |= (1 << 31);
|
||||
|
||||
// make chunk and symbol
|
||||
String8 res_name = coff_resource_string_from_str8(dir_sect->arena, res->id.u.string);
|
||||
LNK_Chunk *name_chunk = lnk_section_push_chunk_data(dir_sect, dir_string_chunk, res_name, str8_zero());
|
||||
LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("COFF_RESOURCE_ID_STRING"), LNK_DefinedSymbolVisibility_Static, 0, name_chunk, 0, 0, 0);
|
||||
|
||||
// patch COFF_ResourceDirEntry.name.offset
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, name.offset), name_symbol);
|
||||
} break;
|
||||
|
||||
case COFF_ResourceIDType_NULL: break;
|
||||
|
||||
default: InvalidPath;
|
||||
}
|
||||
}
|
||||
|
||||
switch (res->kind) {
|
||||
case PE_ResDataKind_DIR: {
|
||||
// initialize directory header
|
||||
COFF_ResourceDirTable *dir_header = push_array(dir_sect->arena, COFF_ResourceDirTable, 1);
|
||||
dir_header->characteristics = res->u.dir->characteristics;
|
||||
dir_header->time_stamp = res->u.dir->time_stamp;
|
||||
dir_header->major_version = res->u.dir->major_version;
|
||||
dir_header->minor_version = res->u.dir->minor_version;
|
||||
dir_header->name_entry_count = res->u.dir->named_list.count;
|
||||
dir_header->id_entry_count = res->u.dir->id_list.count;
|
||||
|
||||
// push sub directory chunk layout
|
||||
LNK_Chunk *dir_node_chunk = lnk_section_push_chunk_list(dir_sect, dir_tree_chunk, str8(0,0));
|
||||
dir_node_chunk->align = ALIGN;
|
||||
LNK_Chunk *dir_header_chunk = lnk_section_push_chunk_data(dir_sect, dir_node_chunk, str8_struct(dir_header), str8(0,0));
|
||||
LNK_Chunk *entry_array_chunk = lnk_section_push_chunk_list(dir_sect, dir_node_chunk, str8(0,0));
|
||||
lnk_chunk_set_debugf(dir_sect->arena, dir_header_chunk, "DIR_HEADER_CHUNK");
|
||||
lnk_chunk_set_debugf(dir_sect->arena, entry_array_chunk, "DIR_ENTRY_ARRAY_CHUNK");
|
||||
|
||||
// push symbols to patch coff entry
|
||||
LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena, flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_RESOURCE_SUB_DIR_FLAG);
|
||||
LNK_Symbol *offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena, offset_name, LNK_DefinedSymbolVisibility_Internal, 0, dir_header_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, flag_symbol); // set high bit to indicate directory
|
||||
lnk_symbol_table_push(symtab, offset_symbol); // write offset for this directory
|
||||
|
||||
// patch resource dir header
|
||||
if (stack->coff_entry_chunk) {
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), flag_symbol);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), offset_symbol);
|
||||
}
|
||||
|
||||
// sort entries by id
|
||||
PE_ResourceArray named_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->named_list);
|
||||
PE_ResourceArray id_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->id_list);
|
||||
radsort(named_array.v, named_array.count, lnk_res_string_id_is_before);
|
||||
radsort(id_array.v, id_array.count, lnk_res_number_id_is_before);
|
||||
|
||||
// frame for sub directory
|
||||
struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1);
|
||||
frame->coff_entry_array_chunk = entry_array_chunk;
|
||||
frame->res_arr[0] = named_array;
|
||||
frame->res_arr[1] = id_array;
|
||||
SLLStackPush(stack, frame);
|
||||
} goto yeild; // recurse to sub directory
|
||||
|
||||
case PE_ResDataKind_COFF_RESOURCE: {
|
||||
COFF_ResourceDataEntry *coff_resource_data_entry = push_array(dir_sect->arena, COFF_ResourceDataEntry, 1);
|
||||
coff_resource_data_entry->data_size = res->u.coff_res.data.size;
|
||||
coff_resource_data_entry->data_voff = 0; // relocated
|
||||
coff_resource_data_entry->code_page = 0; // TODO: whats this for? (lld-link writes zero)
|
||||
|
||||
// push layout chunks
|
||||
LNK_Chunk *coff_resource_data_entry_chunk = lnk_section_push_chunk_data(dir_sect, dir_data_chunk, str8_struct(coff_resource_data_entry), str8(0,0));
|
||||
LNK_Chunk *resource_data_chunk = lnk_section_push_chunk_data(data_sect, data_sect->root, res->u.coff_res.data, str8(0,0));
|
||||
|
||||
// windows errors out on unaligned data
|
||||
coff_resource_data_entry_chunk->align = ALIGN;
|
||||
resource_data_chunk->align = ALIGN;
|
||||
|
||||
// relocate data
|
||||
String8 resource_data_symbol_name = push_str8f(symtab->arena, "$R%06X", res_counter);
|
||||
LNK_Symbol *resource_data_symbol = lnk_make_defined_symbol_chunk(symtab->arena, resource_data_symbol_name, LNK_DefinedSymbolVisibility_Static, 0, resource_data_chunk, 0, 0, 0);
|
||||
lnk_section_push_reloc(dir_sect, coff_resource_data_entry_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(COFF_ResourceDataEntry, data_voff), resource_data_symbol);
|
||||
|
||||
// push symbol for data offset relocation
|
||||
LNK_Symbol *coff_data_offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena, offset_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_resource_data_entry_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, coff_data_offset_symbol);
|
||||
|
||||
Assert(stack->coff_entry_chunk);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), coff_data_offset_symbol);
|
||||
} break;
|
||||
|
||||
case PE_ResDataKind_NULL: break;
|
||||
|
||||
// we must not have this resource node here, it is used to represent on-disk version of entry
|
||||
case PE_ResDataKind_COFF_LEAF: InvalidPath;
|
||||
case PE_ResDataKind_DIR: {
|
||||
// initialize directory header
|
||||
COFF_ResourceDirTable *dir_header = push_array(dir_sect->arena, COFF_ResourceDirTable, 1);
|
||||
dir_header->characteristics = res->u.dir->characteristics;
|
||||
dir_header->time_stamp = res->u.dir->time_stamp;
|
||||
dir_header->major_version = res->u.dir->major_version;
|
||||
dir_header->minor_version = res->u.dir->minor_version;
|
||||
dir_header->name_entry_count = res->u.dir->named_list.count;
|
||||
dir_header->id_entry_count = res->u.dir->id_list.count;
|
||||
|
||||
// push sub directory chunk layout
|
||||
LNK_Chunk *dir_node_chunk = lnk_section_push_chunk_list(dir_sect, dir_tree_chunk, str8_zero());
|
||||
dir_node_chunk->align = COFF_RES_ALIGN;
|
||||
LNK_Chunk *dir_header_chunk = lnk_section_push_chunk_data(dir_sect, dir_node_chunk, str8_struct(dir_header), str8_zero());
|
||||
LNK_Chunk *entry_array_chunk = lnk_section_push_chunk_list(dir_sect, dir_node_chunk, str8_zero());
|
||||
lnk_chunk_set_debugf(dir_sect->arena, dir_header_chunk, "DIR_HEADER_CHUNK");
|
||||
lnk_chunk_set_debugf(dir_sect->arena, entry_array_chunk, "DIR_ENTRY_ARRAY_CHUNK");
|
||||
|
||||
// push symbols to patch coff entry
|
||||
LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena, flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_RESOURCE_SUB_DIR_FLAG);
|
||||
LNK_Symbol *offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena, offset_name, LNK_DefinedSymbolVisibility_Internal, 0, dir_header_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, flag_symbol); // set high bit to indicate directory
|
||||
lnk_symbol_table_push(symtab, offset_symbol); // write offset for this directory
|
||||
|
||||
// patch resource dir header
|
||||
if (stack->coff_entry_chunk) {
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), flag_symbol);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), offset_symbol);
|
||||
}
|
||||
|
||||
// sort entries by id
|
||||
PE_ResourceArray named_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->named_list);
|
||||
PE_ResourceArray id_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->id_list);
|
||||
radsort(named_array.v, named_array.count, lnk_res_string_id_is_before);
|
||||
radsort(id_array.v, id_array.count, lnk_res_number_id_is_before);
|
||||
|
||||
// frame for sub directory
|
||||
struct Stack *frame = push_array(scratch.arena, struct Stack, 1);
|
||||
frame->coff_entry_array_chunk = entry_array_chunk;
|
||||
frame->res_arr[0] = named_array;
|
||||
frame->res_arr[1] = id_array;
|
||||
SLLStackPush(stack, frame);
|
||||
} goto yeild; // recurse to sub directory
|
||||
|
||||
case PE_ResDataKind_COFF_RESOURCE: {
|
||||
COFF_ResourceDataEntry *coff_resource_data_entry = push_array(dir_sect->arena, COFF_ResourceDataEntry, 1);
|
||||
coff_resource_data_entry->data_size = res->u.coff_res.data.size;
|
||||
coff_resource_data_entry->data_voff = 0; // relocated
|
||||
coff_resource_data_entry->code_page = 0; // TODO: whats this for? (lld-link writes zero)
|
||||
|
||||
// push layout chunks
|
||||
LNK_Chunk *coff_resource_data_entry_chunk = lnk_section_push_chunk_data(dir_sect, dir_data_chunk, str8_struct(coff_resource_data_entry), str8_zero());
|
||||
LNK_Chunk *resource_data_chunk = lnk_section_push_chunk_data(data_sect, data_sect->root, res->u.coff_res.data, str8_zero());
|
||||
|
||||
// windows errors out on unaligned data
|
||||
coff_resource_data_entry_chunk->align = COFF_RES_ALIGN;
|
||||
resource_data_chunk->align = COFF_RES_ALIGN;
|
||||
|
||||
// relocate data
|
||||
String8 resource_data_symbol_name = push_str8f(symtab->arena, "$R%06X", total_res_count);
|
||||
LNK_Symbol *resource_data_symbol = lnk_make_defined_symbol_chunk(symtab->arena, resource_data_symbol_name, LNK_DefinedSymbolVisibility_Static, 0, resource_data_chunk, 0, 0, 0);
|
||||
lnk_section_push_reloc(dir_sect, coff_resource_data_entry_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(COFF_ResourceDataEntry, data_voff), resource_data_symbol);
|
||||
|
||||
// push symbol for data offset relocation
|
||||
LNK_Symbol *coff_data_offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena, offset_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_resource_data_entry_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, coff_data_offset_symbol);
|
||||
|
||||
Assert(stack->coff_entry_chunk);
|
||||
lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, id.data_entry_offset), coff_data_offset_symbol);
|
||||
} break;
|
||||
|
||||
case PE_ResDataKind_NULL: break;
|
||||
|
||||
// we must not have this resource node here, it is used to represent on-disk version of entry
|
||||
case PE_ResDataKind_COFF_LEAF: InvalidPath;
|
||||
}
|
||||
}
|
||||
++stack->arr_idx;
|
||||
@@ -731,7 +701,7 @@ lnk_add_resource_debug_s(LNK_SectionTable *st,
|
||||
|
||||
LNK_Section *debug_s = lnk_section_table_push(st, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS);
|
||||
String8 sub_sect_data = str8_serial_end(debug_s->arena, &sub_sect_srl);
|
||||
lnk_section_push_chunk_data(debug_s, debug_s->root, sub_sect_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(debug_s, debug_s->root, sub_sect_data, str8_zero());
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
@@ -882,10 +852,10 @@ lnk_make_res_obj(TP_Context *tp,
|
||||
reloc_sect->emit_header = 0;
|
||||
|
||||
// push chunk layout for relocations
|
||||
LNK_Chunk *reloc_array_chunk = lnk_section_push_chunk_list(reloc_sect, reloc_sect->root, str8(0,0));
|
||||
LNK_Chunk *reloc_array_chunk = lnk_section_push_chunk_list(reloc_sect, reloc_sect->root, str8_zero());
|
||||
for (COFF_RelocNode *i = coff_reloc_list.first; i != 0; i = i->next) {
|
||||
String8 reloc_data = push_str8_copy(reloc_sect->arena, str8_struct(&i->data));
|
||||
lnk_section_push_chunk_data(reloc_sect, reloc_array_chunk, reloc_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(reloc_sect, reloc_array_chunk, reloc_data, str8_zero());
|
||||
}
|
||||
|
||||
// emit symbols for coff section header patch
|
||||
@@ -908,7 +878,7 @@ lnk_make_res_obj(TP_Context *tp,
|
||||
str8_serial_push_struct(scratch.arena, &srl, &i->data);
|
||||
}
|
||||
String8 coff_symbol_table_data = str8_serial_end(scratch.arena, &srl);
|
||||
LNK_Chunk *coff_symbol_table_chunk = lnk_section_push_chunk_data(misc_sect, misc_sect->root, coff_symbol_table_data, str8(0,0));
|
||||
LNK_Chunk *coff_symbol_table_chunk = lnk_section_push_chunk_data(misc_sect, misc_sect->root, coff_symbol_table_data, str8_zero());
|
||||
LNK_Symbol *coff_symbol_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("COFF_SYMBOL_TABLE"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_table_chunk, 0, 0, 0);
|
||||
lnk_symbol_table_push(symtab, coff_symbol_table_symbol);
|
||||
|
||||
@@ -929,7 +899,7 @@ lnk_make_res_obj(TP_Context *tp,
|
||||
|
||||
// push coff header chunk
|
||||
String8 coff_header_data = str8_struct(coff_header);
|
||||
LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_data(header_sect, header_sect->root, coff_header_data, str8(0,0));
|
||||
LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_data(header_sect, header_sect->root, coff_header_data, str8_zero());
|
||||
|
||||
// relocate coff header fields
|
||||
lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal);
|
||||
@@ -943,7 +913,7 @@ lnk_make_res_obj(TP_Context *tp,
|
||||
|
||||
// build section headers
|
||||
{
|
||||
LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8(0,0));
|
||||
LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8_zero());
|
||||
for (LNK_SectionNode *sect_node = st->list.first; sect_node != 0; sect_node = sect_node->next) {
|
||||
if (sect_node == st->null_sect) continue;
|
||||
if (!sect_node->data.emit_header) continue;
|
||||
@@ -965,7 +935,7 @@ lnk_make_res_obj(TP_Context *tp,
|
||||
|
||||
// push section header chunk
|
||||
String8 coff_sect_header_data = str8_struct(coff_sect_header);
|
||||
String8 sort_index = lnk_make_section_sort_index(header_sect->arena, str8(0,0), 0, sect->isect);
|
||||
String8 sort_index = lnk_make_section_sort_index(header_sect->arena, str8_zero(), 0, sect->isect);
|
||||
LNK_Chunk *coff_sect_header_chunk = lnk_section_push_chunk_data(header_sect, coff_section_header_array_chunk, coff_sect_header_data, sort_index);
|
||||
lnk_chunk_set_debugf(header_sect->arena, coff_sect_header_chunk, "%S", sect->name);
|
||||
|
||||
@@ -1091,7 +1061,7 @@ lnk_make_linker_coff_obj(TP_Context *tp,
|
||||
coff_header->section_count = 0;
|
||||
coff_header->time_stamp = time_stamp;
|
||||
|
||||
LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, header_sect->root, coff_header, sizeof(*coff_header), str8(0,0));
|
||||
LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, header_sect->root, coff_header, sizeof(*coff_header), str8_zero());
|
||||
lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal);
|
||||
}
|
||||
|
||||
@@ -1147,7 +1117,7 @@ lnk_make_linker_coff_obj(TP_Context *tp,
|
||||
|
||||
// push debug info to section
|
||||
String8 debug_s_data = str8_list_join(debug_s_sect->arena, &debug_s_data_list, 0);
|
||||
lnk_section_push_chunk_data(debug_s_sect, debug_s_sect->root, debug_s_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(debug_s_sect, debug_s_sect->root, debug_s_data, str8_zero());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1158,7 +1128,7 @@ lnk_make_linker_coff_obj(TP_Context *tp,
|
||||
lnk_symbol_table_push(symtab, sect_symbol);
|
||||
}
|
||||
|
||||
LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8(0,0));
|
||||
LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8_zero());
|
||||
for (LNK_SectionNode *sect_node = st->list.first; sect_node != NULL; sect_node = sect_node->next) {
|
||||
if (sect_node == st->null_sect) continue;
|
||||
if (!sect_node->data.emit_header) continue;
|
||||
@@ -1179,7 +1149,7 @@ lnk_make_linker_coff_obj(TP_Context *tp,
|
||||
coff_sect_header->reloc_count = 0; // relocated
|
||||
|
||||
// push section header chunk
|
||||
String8 sort_index = lnk_make_section_sort_index(header_sect->arena, str8(0,0), 0, sect->isect);
|
||||
String8 sort_index = lnk_make_section_sort_index(header_sect->arena, str8_zero(), 0, sect->isect);
|
||||
LNK_Chunk *coff_sect_header_chunk = lnk_section_push_chunk_raw(header_sect, coff_section_header_array_chunk, coff_sect_header, sizeof(*coff_sect_header), sort_index);
|
||||
lnk_chunk_set_debugf(header_sect->arena, coff_sect_header_chunk, "%S", sect->name);
|
||||
|
||||
@@ -1458,7 +1428,7 @@ lnk_push_pe_debug_data_directory(LNK_Section *sect,
|
||||
//dir->size = 0; // relocated through 'symbol'
|
||||
|
||||
// push chunk
|
||||
LNK_Chunk *dir_entry_chunk = lnk_section_push_chunk_data(sect, dir_array_chunk, str8_struct(dir), str8(0,0));
|
||||
LNK_Chunk *dir_entry_chunk = lnk_section_push_chunk_data(sect, dir_array_chunk, str8_struct(dir), str8_zero());
|
||||
lnk_chunk_set_debugf(sect->arena, dir_entry_chunk, "DebugDirectory[%u]", type);
|
||||
|
||||
// push debug directory relocs
|
||||
@@ -1512,7 +1482,7 @@ lnk_build_debug_rdi(LNK_SectionTable *st,
|
||||
|
||||
// push chunks
|
||||
String8 debug_rdi = pe_make_debug_header_rdi(rdi_sect->arena, guid, rdi_path);
|
||||
LNK_Chunk *debug_rdi_chunk = lnk_section_push_chunk_data(rdi_sect, rdi_sect->root, debug_rdi, str8(0,0)); lnk_chunk_set_debugf(rdi_sect->arena, debug_rdi, LNK_CV_HEADER_RDI_SYMBOL_NAME);
|
||||
LNK_Chunk *debug_rdi_chunk = lnk_section_push_chunk_data(rdi_sect, rdi_sect->root, debug_rdi, str8_zero()); lnk_chunk_set_debugf(rdi_sect->arena, debug_rdi, LNK_CV_HEADER_RDI_SYMBOL_NAME);
|
||||
|
||||
// push symbols
|
||||
LNK_Symbol *debug_rdi_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_CV_HEADER_RDI_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, 0, 0, 0);
|
||||
@@ -1554,26 +1524,26 @@ lnk_build_guard_tables(TP_Context *tp,
|
||||
if (has_guard_flags) {
|
||||
LNK_SymbolArray symbol_arr = lnk_symbol_array_from_list(scratch.arena, obj->symbol_list);
|
||||
if (guard_flags & LNK_Guard_Cf) {
|
||||
LNK_ChunkList gfids_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gfids"), str8(0,0), 1);
|
||||
LNK_ChunkList gfids_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gfids"), str8_zero(), 1);
|
||||
for (LNK_ChunkNode *node = gfids_list.first; node != 0; node = node->next) {
|
||||
Assert(node->data->type == LNK_Chunk_Leaf);
|
||||
lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], node->data->u.leaf, symbol_arr);
|
||||
}
|
||||
LNK_ChunkList giats_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".giats"), str8(0,0), 1);
|
||||
LNK_ChunkList giats_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".giats"), str8_zero(), 1);
|
||||
for (LNK_ChunkNode *node = giats_list.first; node != 0; node = node->next) {
|
||||
Assert(node->data->type == LNK_Chunk_Leaf);
|
||||
lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_IATS], node->data->u.leaf, symbol_arr);
|
||||
}
|
||||
}
|
||||
if (guard_flags & LNK_Guard_LongJmp) {
|
||||
LNK_ChunkList gljmp_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gljmp"), str8(0,0), 1);
|
||||
LNK_ChunkList gljmp_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gljmp"), str8_zero(), 1);
|
||||
for (LNK_ChunkNode *node = gljmp_list.first; node != 0; node = node->next) {
|
||||
Assert(node->data->type == LNK_Chunk_Leaf);
|
||||
lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_LJMP], node->data->u.leaf, symbol_arr);
|
||||
}
|
||||
}
|
||||
if (guard_flags & LNK_Guard_EhCont) {
|
||||
LNK_ChunkList gehcont_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gehcont"), str8(0,0), 1);
|
||||
LNK_ChunkList gehcont_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gehcont"), str8_zero(), 1);
|
||||
for (LNK_ChunkNode *node = gehcont_list.first; node != 0; node = node->next) {
|
||||
Assert(node->data->type == LNK_Chunk_Leaf);
|
||||
lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_EHCONT], node->data->u.leaf, symbol_arr);
|
||||
@@ -1732,10 +1702,10 @@ lnk_build_guard_tables(TP_Context *tp,
|
||||
String8 gehcont_data = lnk_build_guard_data(gehcont_sect->arena, guard_voff_arr_table[GUARD_EHCONT], entry_stride);
|
||||
|
||||
// push guard data
|
||||
lnk_section_push_chunk_data(gfids_sect, gfids_array_chunk, gfids_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(giats_sect, giats_array_chunk, giats_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(gljmp_sect, gljmp_array_chunk, gljmp_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(gehcont_sect, gehcont_array_chunk, gehcont_data, str8(0,0));
|
||||
lnk_section_push_chunk_data(gfids_sect, gfids_array_chunk, gfids_data, str8_zero());
|
||||
lnk_section_push_chunk_data(giats_sect, giats_array_chunk, giats_data, str8_zero());
|
||||
lnk_section_push_chunk_data(gljmp_sect, gljmp_array_chunk, gljmp_data, str8_zero());
|
||||
lnk_section_push_chunk_data(gehcont_sect, gehcont_array_chunk, gehcont_data, str8_zero());
|
||||
|
||||
LNK_Symbol *gflags_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Main, str8_lit(LNK_GUARD_FLAGS_SYMBOL_NAME));
|
||||
LNK_Symbol *gfids_table_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Main, str8_lit(LNK_GUARD_FIDS_TABLE_SYMBOL_NAME));
|
||||
@@ -2065,7 +2035,7 @@ lnk_build_base_relocs(TP_Context *tp,
|
||||
Assert(*block_size_ptr <= buf_size);
|
||||
|
||||
// push page chunk
|
||||
lnk_section_push_chunk_raw(base_reloc_sect, base_reloc_sect->root, buf, block_size, str8(0,0));
|
||||
lnk_section_push_chunk_raw(base_reloc_sect, base_reloc_sect->root, buf, block_size, str8_zero());
|
||||
|
||||
// purge voffs for next run
|
||||
hash_table_purge(voff_ht);
|
||||
@@ -2102,9 +2072,9 @@ lnk_build_dos_header(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_Chun
|
||||
MemoryZeroArray(dos_header->reserved2);
|
||||
dos_header->coff_file_offset = 0; // :coff_file_offset
|
||||
|
||||
LNK_Chunk *dos_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk, str8(0,0));
|
||||
LNK_Chunk *dos_header_chunk = lnk_section_push_chunk_raw(header_sect, dos_chunk, dos_header, sizeof(*dos_header), str8(0,0));
|
||||
LNK_Chunk *dos_program_chunk = lnk_section_push_chunk_data(header_sect, dos_chunk, pe_dos_program, str8(0,0));
|
||||
LNK_Chunk *dos_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk, str8_zero());
|
||||
LNK_Chunk *dos_header_chunk = lnk_section_push_chunk_raw(header_sect, dos_chunk, dos_header, sizeof(*dos_header), str8_zero());
|
||||
LNK_Chunk *dos_program_chunk = lnk_section_push_chunk_data(header_sect, dos_chunk, pe_dos_program, str8_zero());
|
||||
lnk_chunk_set_debugf(header_sect->arena, dos_chunk, "DOS Header & Stub");
|
||||
lnk_chunk_set_debugf(header_sect->arena, dos_header_chunk, LNK_DOS_HEADER_SYMBOL_NAME);
|
||||
lnk_chunk_set_debugf(header_sect->arena, dos_program_chunk, LNK_DOS_PROGRAM_SYMBOL_NAME);
|
||||
@@ -2126,7 +2096,7 @@ lnk_build_pe_magic(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_Chunk
|
||||
U32 *pe_magic = push_array_no_zero(header_sect->arena, U32, 1);
|
||||
*pe_magic = PE_MAGIC;
|
||||
|
||||
LNK_Chunk *pe_magic_chunk = lnk_section_push_chunk_raw(header_sect, parent, pe_magic, sizeof(*pe_magic), str8(0,0));
|
||||
LNK_Chunk *pe_magic_chunk = lnk_section_push_chunk_raw(header_sect, parent, pe_magic, sizeof(*pe_magic), str8_zero());
|
||||
lnk_chunk_set_debugf(header_sect->arena, pe_magic_chunk, LNK_PE_MAGIC_SYMBOL_NAME);
|
||||
|
||||
LNK_Symbol *pe_magic_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_MAGIC_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, pe_magic_chunk, 0, 0, 0);
|
||||
@@ -2148,7 +2118,7 @@ lnk_build_coff_file_header(LNK_SymbolTable *symtab, LNK_Section *header_sect, LN
|
||||
file_header->optional_header_size = 0; // :optional_header_size
|
||||
file_header->flags = file_characteristics;
|
||||
|
||||
LNK_Chunk *file_header_chunk = lnk_section_push_chunk_raw(header_sect, parent, file_header, sizeof(*file_header), str8(0,0));
|
||||
LNK_Chunk *file_header_chunk = lnk_section_push_chunk_raw(header_sect, parent, file_header, sizeof(*file_header), str8_zero());
|
||||
lnk_chunk_set_debugf(header_sect->arena, file_header_chunk, LNK_COFF_HEADER_SYMBOL_NAME);
|
||||
|
||||
LNK_Symbol *file_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0);
|
||||
@@ -2217,7 +2187,7 @@ lnk_build_pe_optional_header_x64(LNK_SymbolTable *symtab,
|
||||
opt_header->data_dir_count = 0; // :data_dir_count
|
||||
|
||||
// push chunk
|
||||
LNK_Chunk *opt_header_chunk = lnk_section_push_chunk_raw(header_sect, parent, opt_header, sizeof(*opt_header), str8(0,0));
|
||||
LNK_Chunk *opt_header_chunk = lnk_section_push_chunk_raw(header_sect, parent, opt_header, sizeof(*opt_header), str8_zero());
|
||||
lnk_chunk_set_debugf(header_sect->arena, opt_header_chunk, LNK_PE_OPT_HEADER_SYMBOL_NAME);
|
||||
|
||||
// define optional header symbol
|
||||
@@ -2298,7 +2268,7 @@ lnk_build_pe_directories(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_
|
||||
U64 directory_count = PE_DataDirectoryIndex_COUNT;
|
||||
PE_DataDirectory *directory_array = push_array(header_sect->arena, PE_DataDirectory, directory_count);
|
||||
|
||||
LNK_Chunk *directory_array_chunk = lnk_section_push_chunk_raw(header_sect, parent, directory_array, sizeof(directory_array[0])*directory_count, str8(0,0));
|
||||
LNK_Chunk *directory_array_chunk = lnk_section_push_chunk_raw(header_sect, parent, directory_array, sizeof(directory_array[0])*directory_count, str8_zero());
|
||||
lnk_chunk_set_debugf(header_sect->arena, directory_array_chunk, LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME);
|
||||
|
||||
// define PE directory symbols
|
||||
@@ -2339,7 +2309,7 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect,
|
||||
}
|
||||
|
||||
// push COFF header array chunk
|
||||
LNK_Chunk *coff_header_array_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk, str8(0,0));
|
||||
LNK_Chunk *coff_header_array_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk, str8_zero());
|
||||
lnk_chunk_set_debugf(header_sect->arena, coff_header_array_chunk, LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME);
|
||||
|
||||
// define symbol for COFF header array
|
||||
@@ -2374,7 +2344,7 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect,
|
||||
coff_header->flags = sect->flags;
|
||||
|
||||
// push chunk
|
||||
LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, coff_header_array_chunk, coff_header, sizeof(*coff_header), str8(0,0));
|
||||
LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, coff_header_array_chunk, coff_header, sizeof(*coff_header), str8_zero());
|
||||
|
||||
// :vsize
|
||||
lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_CHUNK_SIZE_VIRT_32, OffsetOf(COFF_SectionHeader, vsize), sect->name, LNK_SymbolScopeFlag_Internal);
|
||||
@@ -2412,7 +2382,7 @@ lnk_build_win32_image_header(LNK_SymbolTable *symtab,
|
||||
// header sections must be written first
|
||||
Assert(header_sect->id == 0);
|
||||
|
||||
LNK_Chunk *win32_header_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk , str8(0,0) );
|
||||
LNK_Chunk *win32_header_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk , str8_zero() );
|
||||
LNK_Chunk *dos_chunk = lnk_section_push_chunk_list(header_sect, win32_header_chunk, str8_lit("a"));
|
||||
LNK_Chunk *nt_chunk = lnk_section_push_chunk_list(header_sect, win32_header_chunk, str8_lit("b"));
|
||||
LNK_Chunk *pe_magic_chunk = lnk_section_push_chunk_list(header_sect, nt_chunk , str8_lit("a"));
|
||||
@@ -3752,7 +3722,7 @@ l.count += 1; \
|
||||
|
||||
// search disk for library
|
||||
String8List match_list = os_file_search(scratch.arena, config->lib_dir_list, path);
|
||||
String8 absolute_path = match_list.node_count ? match_list.first->string : str8(0,0);
|
||||
String8 absolute_path = match_list.node_count ? match_list.first->string : str8_zero();
|
||||
|
||||
// default to first match
|
||||
if (lnk_is_lib_loaded(default_lib_ht, loaded_lib_ht, input_source, absolute_path)) {
|
||||
@@ -3857,7 +3827,7 @@ l.count += 1; \
|
||||
// TODO: currently we convert manifest to res and parse res again, this unnecessary instead push manifest
|
||||
// resource to the tree directly
|
||||
String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list);
|
||||
String8 manifest_res = lnk_res_from_data(scratch.arena, manifest_data);
|
||||
String8 manifest_res = pe_make_manifest_resource(scratch.arena, *config->manifest_resource_id, manifest_data);
|
||||
str8_list_push(scratch.arena, &res_data_list, manifest_res);
|
||||
str8_list_push(scratch.arena, &res_path_list, str8_lit("* Manifest *"));
|
||||
ProfEnd();
|
||||
@@ -4004,8 +3974,8 @@ l.count += 1; \
|
||||
|
||||
// push debug directory layout chunks
|
||||
LNK_Section *debug_sect = lnk_section_table_search(st, str8_lit(".rdata"));
|
||||
LNK_Chunk *debug_chunk = lnk_section_push_chunk_list(debug_sect, debug_sect->root, str8(0,0));
|
||||
LNK_Chunk *debug_dir_array_chunk = lnk_section_push_chunk_list(debug_sect, debug_chunk, str8(0,0));
|
||||
LNK_Chunk *debug_chunk = lnk_section_push_chunk_list(debug_sect, debug_sect->root, str8_zero());
|
||||
LNK_Chunk *debug_dir_array_chunk = lnk_section_push_chunk_list(debug_sect, debug_chunk, str8_zero());
|
||||
|
||||
// push symbols for PE directory patch
|
||||
LNK_Symbol *dir_array_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_DEBUG_DIR_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_dir_array_chunk, 0, 0, 0);
|
||||
@@ -4578,7 +4548,7 @@ lnk_dump_resource_dir_(COFF_ResourceID dir_id, PE_ResourceDir *dir)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
SYMS_String8 dir_id_syms = syms_str8(0,0);
|
||||
SYMS_String8 dir_id_syms = syms_str8_zero();
|
||||
if (dir_id.type == COFF_ResourceIDType_NUMBER) {
|
||||
dir_id_syms = syms_pe_resource_type_to_string(dir_id.u.number);
|
||||
}
|
||||
@@ -4612,7 +4582,7 @@ lnk_dump_resource_dir_(COFF_ResourceID dir_id, PE_ResourceDir *dir)
|
||||
} break;
|
||||
case PE_ResData_COFF_RESOURCE: {
|
||||
SYMS_String8 id_syms = syms_coff_resource_id_to_string(scratch.arena, res->id);
|
||||
SYMS_String8 type_syms = syms_str8(0,0);
|
||||
SYMS_String8 type_syms = syms_str8_zero();
|
||||
if (res->u.coff_res.type.type == COFF_ResourceIDType_NUMBER) {
|
||||
type_syms = syms_pe_resource_type_to_string(res->u.coff_res.type.u.number);
|
||||
}
|
||||
|
||||
@@ -254,7 +254,6 @@ internal void lnk_push_loaded_lib(Arena *arena, HashTable *default_lib_ht, Ha
|
||||
|
||||
internal String8 lnk_make_linker_manifest(Arena *arena, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List manifest_dependency_list);
|
||||
internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest_path_list);
|
||||
internal String8 lnk_res_from_data(Arena *arena, String8 data);
|
||||
|
||||
////////////////////////////////
|
||||
// Resources
|
||||
|
||||
+17
-10
@@ -832,7 +832,7 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
|
||||
|
||||
// parse command line
|
||||
String8List unwrapped_cmd_line = lnk_unwrap_rsp(scratch.arena, raw_cmd_line);
|
||||
LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, unwrapped_cmd_line);
|
||||
LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, unwrapped_cmd_line);
|
||||
|
||||
// setup default flags
|
||||
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Align, "%u", KB(4));
|
||||
@@ -1132,25 +1132,21 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
|
||||
config->manifest_opt = LNK_ManifestOpt_Embed;
|
||||
|
||||
if (param_arr.count == 1) {
|
||||
if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Dll)) {
|
||||
config->manifest_resource_id = 2;
|
||||
} else {
|
||||
config->manifest_resource_id = 1;
|
||||
}
|
||||
config->manifest_resource_id = 0;
|
||||
} else if (param_arr.count > 1) {
|
||||
// parse resource id
|
||||
if (str8_match(param_arr.v[1], str8_lit("id="), StringMatchFlag_RightSideSloppy|StringMatchFlag_CaseInsensitive)) {
|
||||
String8List res_id_list = str8_split_by_string_chars(scratch.arena, param_arr.v[1], str8_lit("="), 0);
|
||||
String8Array res_id_arr = str8_array_from_list(scratch.arena, &res_id_list);
|
||||
String8List res_id_list = str8_split_by_string_chars(scratch.arena, param_arr.v[1], str8_lit("="), 0);
|
||||
String8Array res_id_arr = str8_array_from_list(scratch.arena, &res_id_list);
|
||||
if (res_id_arr.count == 2) {
|
||||
U64 resource_id;
|
||||
if (try_u64_from_str8_c_rules(res_id_arr.v[1], &resource_id)) {
|
||||
config->manifest_resource_id = resource_id;
|
||||
config->manifest_resource_id = push_u64(arena, resource_id);
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, cmd_switch, "unable to parse resource_id \"%S\"", res_id_arr.v[1]);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, cmd_switch, "invalid syntax expected form ID=resource_id but got \"%S\"", param_arr.v[1]);
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, cmd_switch, "invalid syntax expected form ID=# but got \"%S\"", param_arr.v[1]);
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch_invalid_param(LNK_Error_Cmdl, cmd_switch, param_arr.v[0]);
|
||||
@@ -1168,6 +1164,8 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
|
||||
}
|
||||
} else if (cmd->value_strings.node_count == 0) {
|
||||
config->manifest_opt = LNK_ManifestOpt_WriteToFile;
|
||||
} else {
|
||||
lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, cmd_switch);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1616,6 +1614,15 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
|
||||
}
|
||||
}
|
||||
|
||||
// set default manifest resource id
|
||||
if (config->manifest_resource_id == 0) {
|
||||
if (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) {
|
||||
config->manifest_resource_id = push_u64(arena, 2);
|
||||
} else {
|
||||
config->manifest_resource_id = push_u64(arena, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// input files
|
||||
for (String8Node *input_node = cmd_line.input_list.first; input_node != 0; input_node = input_node->next) {
|
||||
String8 path = push_str8_copy(arena, input_node->string);
|
||||
|
||||
@@ -247,7 +247,7 @@ typedef struct LNK_Config
|
||||
U64 pdb_page_size;
|
||||
U64 worker_count;
|
||||
U64 function_pad_min;
|
||||
U64 manifest_resource_id;
|
||||
U64 *manifest_resource_id;
|
||||
Version link_ver;
|
||||
Version os_ver;
|
||||
Version image_ver;
|
||||
|
||||
+15
@@ -901,6 +901,21 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data)
|
||||
return bottom_frame->table;
|
||||
}
|
||||
|
||||
internal String8
|
||||
pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data)
|
||||
{
|
||||
COFF_ResourceID type = {0};
|
||||
type.type = COFF_ResourceIDType_NUMBER;
|
||||
type.u.number = PE_ResourceKind_MANIFEST;
|
||||
|
||||
COFF_ResourceID id = {0};
|
||||
id.type = COFF_ResourceIDType_NUMBER;
|
||||
id.u.number = resource_id;
|
||||
|
||||
String8 res = coff_write_resource(arena, type, id, 1, 0, 1033, 0, 0, manifest_data);
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Debug Directory
|
||||
|
||||
|
||||
+2
-2
@@ -452,8 +452,6 @@ struct PE_TLSHeader64
|
||||
U32 characteristics; // COFF_SectionFlags but only align flags are used.
|
||||
};
|
||||
|
||||
#define PE_RES_ALIGN 4u
|
||||
|
||||
global read_only U8 PE_RES_MAGIC[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
@@ -781,6 +779,8 @@ internal PE_Resource * pe_resource_dir_search(PE_ResourceDir *dir, COFF_Reso
|
||||
internal PE_ResourceArray pe_resource_list_to_array(Arena *arena, PE_ResourceList *list);
|
||||
internal PE_ResourceDir * pe_resource_table_from_directory_data(Arena *arena, String8 data);
|
||||
|
||||
internal String8 pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Debug Directory
|
||||
|
||||
|
||||
Reference in New Issue
Block a user