group forwarder and named exports and sort them together

This commit is contained in:
Nikita Smith
2026-01-27 11:26:24 -08:00
parent cc43d17496
commit 3abfb800a8
2 changed files with 48 additions and 69 deletions
+46 -66
View File
@@ -75,36 +75,30 @@ pe_export_parse_list_concat_in_place(PE_ExportParseList *list, PE_ExportParseLis
internal int internal int
pe_named_export_is_before(void *raw_a, void *raw_b) pe_named_export_is_before(void *raw_a, void *raw_b)
{ {
PE_ExportParse *a = *(PE_ExportParse **)raw_a; PE_ExportParse *a = *(PE_ExportParse **)raw_a, *b = *(PE_ExportParse **)raw_b;
PE_ExportParse *b = *(PE_ExportParse **)raw_b; String8 name_a = a->alias.size ? a->alias : a->name;
int cmp = str8_compar_case_sensitive(&a->name, &b->name); String8 name_b = b->alias.size ? b->alias : b->name;
return cmp < 0; return str8_compar_case_sensitive(&name_a, &name_b) < 0;
} }
internal int internal int
pe_ordinal_export_is_before(void *raw_a, void *raw_b) pe_ordinal_export_is_before(void *raw_a, void *raw_b)
{ {
PE_ExportParse *a = raw_a; return ((PE_ExportParse * )raw_a)->ordinal < ((PE_ExportParse *)raw_b)->ordinal;
PE_ExportParse *b = raw_b;
return a->ordinal < b->ordinal;
} }
internal PE_FinalizedExports internal PE_FinalizedExports
pe_finalize_export_list(Arena *arena, PE_ExportParseList export_list) pe_finalize_export_list(Arena *arena, PE_ExportParseList export_list)
{ {
PE_ExportParsePtrArray named_exports = {0}; PE_ExportParsePtrArray named_exports = {0};
PE_ExportParsePtrArray ordinal_exports = {0}; PE_ExportParsePtrArray ordinal_exports = {0};
PE_ExportParsePtrArray forwarder_exports = {0};
{ {
// group exports based on flags // group exports based on flags
PE_ExportParseList named_exports_list = {0}; PE_ExportParseList named_exports_list = {0};
PE_ExportParseList ordinal_exports_list = {0}; PE_ExportParseList ordinal_exports_list = {0};
PE_ExportParseList forwarder_exports_list = {0};
for (PE_ExportParseNode *exp_n = export_list.first, *exp_n_next; exp_n != 0; exp_n = exp_n_next) { for (PE_ExportParseNode *exp_n = export_list.first, *exp_n_next; exp_n != 0; exp_n = exp_n_next) {
exp_n_next = exp_n->next; exp_n_next = exp_n->next;
if (exp_n->data.is_forwarder) { if (exp_n->data.is_noname_present) {
pe_export_parse_list_push_node(&forwarder_exports_list, exp_n);
} else if (exp_n->data.is_noname_present) {
AssertAlways(exp_n->data.is_ordinal_assigned); AssertAlways(exp_n->data.is_ordinal_assigned);
pe_export_parse_list_push_node(&ordinal_exports_list, exp_n); pe_export_parse_list_push_node(&ordinal_exports_list, exp_n);
} else { } else {
@@ -113,29 +107,29 @@ pe_finalize_export_list(Arena *arena, PE_ExportParseList export_list)
} }
// list -> array // list -> array
named_exports = pe_array_from_export_list(arena, named_exports_list); named_exports = pe_array_from_export_list(arena, named_exports_list);
forwarder_exports = pe_array_from_export_list(arena, forwarder_exports_list);
ordinal_exports = pe_array_from_export_list(arena, ordinal_exports_list); ordinal_exports = pe_array_from_export_list(arena, ordinal_exports_list);
for(int i = 0; i < ordinal_exports.count; ++i) {
PE_ExportParse p = *ordinal_exports.v[i];
}
// sort exports // sort exports
radsort(named_exports.v, named_exports.count, pe_named_export_is_before); radsort(named_exports.v, named_exports.count, pe_named_export_is_before);
radsort(ordinal_exports.v, ordinal_exports.count, pe_ordinal_export_is_before); radsort(ordinal_exports.v, ordinal_exports.count, pe_ordinal_export_is_before);
radsort(forwarder_exports.v, forwarder_exports.count, pe_named_export_is_before);
MemoryZeroStruct(&export_list); MemoryZeroStruct(&export_list);
pe_export_parse_list_concat_in_place(&export_list, &named_exports_list); pe_export_parse_list_concat_in_place(&export_list, &named_exports_list);
pe_export_parse_list_concat_in_place(&export_list, &forwarder_exports_list);
pe_export_parse_list_concat_in_place(&export_list, &ordinal_exports_list); pe_export_parse_list_concat_in_place(&export_list, &ordinal_exports_list);
} }
// compute max ordinal and used ordinal flag array // compute max ordinal and used ordinal flag array
U64 ordinal_low = max_U64; U64 ordinal_low = max_U64;
B8 *is_ordinal_used = push_array(arena, B8, max_U16); B8 *is_ordinal_used = push_array(arena, B8, max_U16);
for (PE_ExportParseNode *exp_n = export_list.first; exp_n != 0; exp_n = exp_n->next) { for EachNode(exp_n, PE_ExportParseNode, export_list.first) {
PE_ExportParse *exp = &exp_n->data; if (exp_n->data.is_ordinal_assigned) {
if (exp->is_ordinal_assigned) { ordinal_low = Min(ordinal_low, exp_n->data.ordinal);
ordinal_low = Min(ordinal_low, exp->ordinal); is_ordinal_used[exp_n->data.ordinal] = 1;
is_ordinal_used[exp->ordinal] = 1;
} }
} }
if (ordinal_low == max_U64) { if (ordinal_low == max_U64) {
@@ -154,15 +148,6 @@ pe_finalize_export_list(Arena *arena, PE_ExportParseList export_list)
is_ordinal_used[last_ordinal] = 1; is_ordinal_used[last_ordinal] = 1;
} }
} }
for (U64 exp_idx = 0; exp_idx < forwarder_exports.count; exp_idx += 1) {
PE_ExportParse *exp = forwarder_exports.v[exp_idx];
if (!exp->is_ordinal_assigned) {
for (; last_ordinal < max_U16 && is_ordinal_used[last_ordinal] != 0; last_ordinal += 1);
exp->ordinal = last_ordinal;
exp->is_ordinal_assigned = 1;
is_ordinal_used[last_ordinal] = 1;
}
}
for (U64 exp_idx = 0; exp_idx < ordinal_exports.count; exp_idx += 1) { for (U64 exp_idx = 0; exp_idx < ordinal_exports.count; exp_idx += 1) {
PE_ExportParse *exp = ordinal_exports.v[exp_idx]; PE_ExportParse *exp = ordinal_exports.v[exp_idx];
if (!exp->is_ordinal_assigned) { if (!exp->is_ordinal_assigned) {
@@ -179,18 +164,13 @@ pe_finalize_export_list(Arena *arena, PE_ExportParseList export_list)
for (U64 exp_idx = 0; exp_idx < named_exports.count; exp_idx += 1, hint += 1) { for (U64 exp_idx = 0; exp_idx < named_exports.count; exp_idx += 1, hint += 1) {
named_exports.v[exp_idx]->hint = hint; named_exports.v[exp_idx]->hint = hint;
} }
for (U64 exp_idx = 0; exp_idx < forwarder_exports.count; exp_idx += 1, hint += 1) {
forwarder_exports.v[exp_idx]->hint = hint;
}
} }
PE_FinalizedExports result = {0}; return (PE_FinalizedExports) {
result.ordinal_low = ordinal_low; .ordinal_low = ordinal_low,
result.named_exports = named_exports; .named_exports = named_exports,
result.forwarder_exports = forwarder_exports; .ordinal_exports = ordinal_exports
result.ordinal_exports = ordinal_exports; };
return result;
} }
internal String8 internal String8
@@ -214,34 +194,34 @@ pe_make_edata_obj(Arena *arena,
ProfBegin("Virtual Offset Table"); ProfBegin("Virtual Offset Table");
{ {
B8 *is_ordinal_bound = push_array(scratch.arena, B8, max_U16); B8 *is_ordinal_bound = push_array(scratch.arena, B8, max_U16);
for EachElement(arr_idx, finalized_exports.all) {
for (U64 arr_idx = 0; arr_idx < ArrayCount(finalized_exports.all); arr_idx += 1) { for EachIndex(exp_idx, finalized_exports.all[arr_idx].count) {
for (U64 exp_idx = 0; exp_idx < finalized_exports.all[arr_idx].count; exp_idx += 1) {
PE_ExportParse *exp = finalized_exports.all[arr_idx].v[exp_idx]; PE_ExportParse *exp = finalized_exports.all[arr_idx].v[exp_idx];
if (is_ordinal_bound[exp->ordinal] == 0) {
// alloc only one slot per ordinal, so it's possible to map ordinal to a virtual offset
is_ordinal_bound[exp->ordinal] = 1;
// create slot for the ordinal virtual offset // export with this ordinal was already allocated
U64 voff_offset = voff_table_sect->data.total_size; if (is_ordinal_bound[exp->ordinal]) { continue; }
U32 *voff = push_array(obj_writer->arena, U32, 1); is_ordinal_bound[exp->ordinal] = 1;
str8_list_push(obj_writer->arena, &voff_table_sect->data, str8_struct(voff));
COFF_ObjSymbol *exp_symbol; // create symbol for the export address table entry
if (exp->is_forwarder) { COFF_ObjSymbol *exp_symbol;
U64 forwarder_name_offset = string_table_sect->data.total_size; if (exp->is_forwarder) {
String8 forwarder_name_cstr = push_cstr(obj_writer->arena, exp->name); // symbol to the forwarder string
str8_list_push(obj_writer->arena, &string_table_sect->data, forwarder_name_cstr); U64 fwd_name_offset = string_table_sect->data.total_size;
// symbol to the name string str8_list_push(obj_writer->arena, &string_table_sect->data, push_cstr(obj_writer->arena, exp->name));
exp_symbol = coff_obj_writer_push_symbol_static(obj_writer, exp->name, forwarder_name_offset, string_table_sect); exp_symbol = coff_obj_writer_push_symbol_static(obj_writer, exp->name, fwd_name_offset, string_table_sect);
} else { } else {
// function or global var symbol // function or data symbol
exp_symbol = coff_obj_writer_push_symbol_undef(obj_writer, exp->name); exp_symbol = coff_obj_writer_push_symbol_undef(obj_writer, exp->name);
}
U16 ordinal_nb = exp->ordinal - finalized_exports.ordinal_low;
coff_obj_writer_section_push_reloc_voff(obj_writer, voff_table_sect, ordinal_nb*sizeof(U32), exp_symbol);
} }
// create slot for the ordinal virtual offset
U64 voff_offset = voff_table_sect->data.total_size;
U32 *voff = push_array(obj_writer->arena, U32, 1);
str8_list_push(obj_writer->arena, &voff_table_sect->data, str8_struct(voff));
// ordinal is an index into the export address table
U16 ordinal_nb = exp->ordinal - finalized_exports.ordinal_low;
coff_obj_writer_section_push_reloc_voff(obj_writer, voff_table_sect, ordinal_nb*sizeof(U32), exp_symbol);
} }
} }
} }
+2 -3
View File
@@ -45,11 +45,10 @@ typedef struct PE_FinalizedExports
union { union {
struct { struct {
PE_ExportParsePtrArray named_exports; PE_ExportParsePtrArray named_exports;
PE_ExportParsePtrArray forwarder_exports;
PE_ExportParsePtrArray ordinal_exports; PE_ExportParsePtrArray ordinal_exports;
}; };
PE_ExportParsePtrArray exports_with_names[2]; PE_ExportParsePtrArray exports_with_names[1];
PE_ExportParsePtrArray all[3]; PE_ExportParsePtrArray all[2];
}; };
} PE_FinalizedExports; } PE_FinalizedExports;