pass over COFF archive parser

This commit is contained in:
Nikita Smith
2024-12-06 11:53:16 -08:00
parent 29de0c5a9e
commit 80fa226432
8 changed files with 455 additions and 335 deletions
-8
View File
@@ -114,14 +114,6 @@
////////////////////////////////
#if ARCH_LITTLE_ENDIAN
# define BE_U32(x) bswap_u32(x)
#else
# define BE_U32(x) (x)
#endif
////////////////////////////////
typedef struct
{
U64 major;
+13
View File
@@ -243,6 +243,19 @@ key_value_pair_is_before_u64(void *raw_a, void *raw_b)
return a->key_u64 < b->key_u64;
}
internal U32 *
keys_from_hash_table_u32(Arena *arena, HashTable *ht)
{
U32 *result = push_array_no_zero(arena, U32, ht->count);
for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) {
for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) {
Assert(cursor < ht->count);
result[cursor++] = n->v.key_u32;
}
}
return result;
}
internal KeyValuePair *
key_value_pairs_from_hash_table(Arena *arena, HashTable *ht)
{
+1
View File
@@ -75,6 +75,7 @@ internal B32 hash_table_search_path_u64(HashTable *ht, String8 key, U64 *value_o
//- key-value helpers
internal U32 * keys_from_hash_table_u32(Arena *arena, HashTable *ht);
internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht);
internal void sort_key_value_pairs_as_u32(KeyValuePair *pairs, U64 count);
internal void sort_key_value_pairs_as_u64(KeyValuePair *pairs, U64 count);
+2 -2
View File
@@ -1221,7 +1221,7 @@ internal void
lnk_push_input_from_lazy(Arena *arena, PathStyle path_style, LNK_LazySymbol *lazy, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list)
{
// parse member
COFF_ArchiveMember member_info = coff_read_archive_member(lazy->lib->data, lazy->member_offset);
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lazy->lib->data, lazy->member_offset);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
switch (member_type) {
@@ -1231,7 +1231,7 @@ lnk_push_input_from_lazy(Arena *arena, PathStyle path_style, LNK_LazySymbol *laz
} break;
case COFF_DataType_BIG_OBJ:
case COFF_DataType_OBJ: {
String8 obj_path = coff_read_archive_long_name(lazy->lib->long_names, member_info.header.name);
String8 obj_path = coff_parse_long_name(lazy->lib->long_names, member_info.header.name);
// obj path in thin archive has slash appended which screws up
// file lookup on disk; it couble be there to enable paths to symbols
+16 -13
View File
@@ -109,25 +109,28 @@ lnk_lib_from_data(Arena *arena, String8 data, String8 path)
lnk_not_implemented("TODO: data is not archive");
}
COFF_ArchiveParse parse = coff_archive_parse_from_data(arena, data);
COFF_ArchiveParse parse = coff_archive_parse_from_data(data);
// report archive parser errors
if (parse.error.size) {
lnk_error(LNK_Error_IllData, "%S: %S", path, parse.error);
}
// try to init library from optional second member
if (parse.second_member.member_count) {
COFF_ArchiveSecondMember second_member = parse.second_member;
Assert(second_member.symbol_count == second_member.symbol_indices.size / sizeof(U16));
Assert(second_member.member_count == second_member.member_offsets.size / sizeof(U32));
Assert(second_member.symbol_count == second_member.symbol_index_count);
Assert(second_member.member_count == second_member.member_offset_count);
symbol_count = second_member.symbol_count;
string_table = second_member.string_table;
member_off_arr = push_array_no_zero(arena, U32, symbol_count);
// decompress member offsets
U32 *comp_off_arr = (U32*)second_member.member_offsets.str;
U16 *off_number_arr = (U16*)second_member.symbol_indices.str;
for (U64 symbol_idx = 0; symbol_idx < symbol_count; symbol_idx += 1) {
U16 off_number = off_number_arr[symbol_idx];
U16 off_number = second_member.symbol_indices[symbol_idx];
if (0 < off_number && off_number <= second_member.member_count) {
member_off_arr[symbol_idx] = comp_off_arr[off_number - 1];
member_off_arr[symbol_idx] = second_member.member_offsets[off_number - 1];
} else {
// TODO: log bad offset
member_off_arr[symbol_idx] = max_U32;
@@ -138,19 +141,19 @@ lnk_lib_from_data(Arena *arena, String8 data, String8 path)
// and lld-link with /DLL emits only first member
else if (parse.first_member.symbol_count) {
COFF_ArchiveFirstMember first_member = parse.first_member;
Assert(first_member.symbol_count == first_member.member_offsets.size / sizeof(U32));
Assert(first_member.symbol_count == first_member.member_offset_count);
symbol_count = first_member.symbol_count;
string_table = first_member.string_table;
member_off_arr = (U32*)first_member.member_offsets.str;
member_off_arr = first_member.member_offsets;
// convert big endian offsets
for (U32 offset_idx = 0; offset_idx < symbol_count; offset_idx += 1) {
member_off_arr[offset_idx] = BE_U32(member_off_arr[offset_idx]);
member_off_arr[offset_idx] = from_be_u32(member_off_arr[offset_idx]);
}
} else {
symbol_count = 0;
string_table = str8(0,0);
string_table = str8_zero();
member_off_arr = 0;
}
@@ -472,7 +475,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second
// first linker member (obsolete, but kept for compatability reasons)
{
U32 symbol_count_be = BE_U32(symbol_count);
U32 symbol_count_be = from_be_u32(symbol_count);
U32 *member_off32_arr = push_array_no_zero(scratch.arena, U32, symbol_count);
for (U64 symbol_idx = 0; symbol_idx < symbol_count; symbol_idx += 1) {
@@ -480,7 +483,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second
// write big endian member offset
U64 member_off = member_base_off + member_off_arr[symbol->member_idx];
U32 member_off32 = BE_U32(safe_cast_u32(member_off));
U32 member_off32 = from_be_u32(safe_cast_u32(member_off));
member_off32_arr[symbol_idx] = member_off32;
}
+1 -1
View File
@@ -359,7 +359,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
COFF_SectionHeader *coff_sect = &coff_sect_arr[sect_idx];
// read name
String8 sect_name = coff_section_header_get_name(coff_sect, input->data, coff_info.string_table_off);
String8 sect_name = coff_name_from_section_header(coff_sect, input->data, coff_info.string_table_off);
// parse section name
String8 name, postfix;