replace linker lib writer with one from COFF

This commit is contained in:
Nikita Smith
2025-05-08 12:42:20 -07:00
committed by Ryan Fleury
parent 120829095b
commit 3a7afcd80c
5 changed files with 57 additions and 551 deletions
+40 -1
View File
@@ -39,6 +39,7 @@
#include "coff/coff_enum.h"
#include "coff/coff_parse.h"
#include "coff/coff_obj_writer.h"
#include "coff/coff_lib_writer.h"
#include "pe/pe.h"
#include "codeview/codeview.h"
#include "codeview/codeview_parse.h"
@@ -56,6 +57,7 @@
#include "coff/coff_enum.c"
#include "coff/coff_parse.c"
#include "coff/coff_obj_writer.c"
#include "coff/coff_lib_writer.c"
#include "pe/pe.c"
#include "codeview/codeview.c"
#include "codeview/codeview_enum.c"
@@ -3077,6 +3079,43 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
return image_data;
}
internal String8List
lnk_build_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ExportTable *exptab)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
dll_name = str8_skip_last_slash(dll_name);
// These objects appear in first three members of any lib that linker produces with /dll.
// Objects are used by MSVC linker to build import table.
String8 import_entry_obj = lnk_build_import_entry_obj(scratch.arena, dll_name, time_stamp, machine);
String8 null_import_descriptor_obj = lnk_build_null_import_descriptor_obj(scratch.arena, time_stamp, machine);
String8 null_thunk_data_obj = lnk_build_null_thunk_data_obj(scratch.arena, dll_name, time_stamp, machine);
COFF_LibWriter *lib_writer = coff_lib_writer_alloc();
coff_lib_writer_push_obj(lib_writer, dll_name, import_entry_obj);
coff_lib_writer_push_obj(lib_writer, dll_name, null_import_descriptor_obj);
coff_lib_writer_push_obj(lib_writer, dll_name, null_thunk_data_obj);
KeyValuePair *raw_export_arr = key_value_pairs_from_hash_table(scratch.arena, exptab->name_export_ht);
for (U64 i = 0; i < exptab->name_export_ht->count; ++i) {
LNK_Export *exp = raw_export_arr[i].value_raw;
if (exp->name.size) {
coff_lib_writer_push_export_by_name(lib_writer, machine, time_stamp, dll_name, exp->type, exp->name, safe_cast_u16(exp->id));
} else {
coff_lib_writer_push_export_by_ordinal(lib_writer, machine, time_stamp, dll_name, exp->type, exp->ordinal);
}
}
String8List lib = coff_lib_writer_serialize(arena, lib_writer, COFF_TimeStamp_Max, 0, /* emit second member: */ 1);
coff_lib_writer_release(&lib_writer);
scratch_end(scratch);
ProfEnd();
return lib;
}
////////////////////////////////
internal
@@ -4304,7 +4343,7 @@ lnk_run(int argc, char **argv)
case State_BuildImpLib: {
ProfBegin("Build Imp Lib");
lnk_timer_begin(LNK_Timer_Lib);
String8List lib_list = lnk_build_import_lib(tp, tp_arena, config->machine, config->time_stamp, config->imp_lib_name, config->image_name, exptab);
String8List lib_list = lnk_build_import_lib(tp_arena->v[0], config->machine, config->time_stamp, config->image_name, exptab);
lnk_write_data_list_to_file_path(config->imp_lib_name, str8_zero(), lib_list);
lnk_timer_end(LNK_Timer_Lib);
ProfEnd();
+4
View File
@@ -192,6 +192,10 @@ internal String8List lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_temp, LN
internal String8List lnk_build_win32_image_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sect_arr, U64 expected_image_header_size);
internal String8 lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, LNK_ExportTable *exptab, LNK_ObjList obj_list);
// --- Import Lib --------------------------------------------------------------
internal String8List lnk_build_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ExportTable *exptab);
// --- Logger ------------------------------------------------------------------
internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab);
-468
View File
@@ -15,85 +15,6 @@ lnk_lib_list_reserve(Arena *arena, LNK_LibList *list, U64 count)
return arr;
}
internal LNK_LibMemberNode *
lnk_lib_member_list_push(Arena *arena, LNK_LibMemberList *list, LNK_LibMember member)
{
LNK_LibMemberNode *n = push_array_no_zero(arena, LNK_LibMemberNode, 1);
n->next = 0;
n->data = member;
SLLQueuePush(list->first, list->last, n);
++list->count;
return n;
}
internal LNK_LibMember *
lnk_lib_member_array_from_list(Arena *arena, LNK_LibMemberList list)
{
ProfBeginFunction();
LNK_LibMember *arr = push_array_no_zero(arena, LNK_LibMember, list.count);
LNK_LibMember *ptr = arr;
for (LNK_LibMemberNode *i = list.first; i != 0; i = i->next, ptr += 1) {
ptr->name = push_str8_copy(arena, i->data.name);
ptr->data = push_str8_copy(arena, i->data.data);
}
ProfEnd();
return arr;
}
internal LNK_LibSymbolNode *
lnk_lib_symbol_list_push(Arena *arena, LNK_LibSymbolList *list, LNK_LibSymbol symbol)
{
LNK_LibSymbolNode *n = push_array_no_zero(arena, LNK_LibSymbolNode, 1);
n->next = 0;
n->data = symbol;
SLLQueuePush(list->first, list->last, n);
++list->count;
return n;
}
internal LNK_LibSymbol *
lnk_lib_symbol_array_from_list(Arena *arena, LNK_LibSymbolList list)
{
LNK_LibSymbol *arr = push_array_no_zero(arena, LNK_LibSymbol, list.count + 2);
LNK_LibSymbol *ptr = arr + 1;
for (LNK_LibSymbolNode *i = list.first; i != 0; i = i->next, ptr += 1) {
ptr->name = push_str8_copy(arena, i->data.name);
ptr->member_idx = i->data.member_idx;
}
MemoryZeroStruct(&arr[0]);
MemoryZeroStruct(&arr[list.count+1]);
return arr;
}
int
lnk_lib_symbol_name_compar(const void *raw_a, const void *raw_b)
{
const LNK_Symbol *sa = (const LNK_Symbol *)raw_a;
const LNK_Symbol *sb = (const LNK_Symbol *)raw_b;
return str8_compar_case_sensitive(&sa->name, &sb->name);
}
int
lnk_lib_symbol_name_compar_is_before(void *raw_a, void *raw_b)
{
int compar = lnk_lib_symbol_name_compar(raw_a, raw_b);
int is_before = compar < 0;
return is_before;
}
internal void
lnk_lib_symbol_array_sort(LNK_LibSymbol *arr, U64 count)
{
Assert(count >= 2);
radsort(arr + 1, count - 2, lnk_lib_symbol_name_compar_is_before);
}
////////////////////////////////
internal LNK_Lib
lnk_lib_from_data(Arena *arena, String8 data, String8 path)
{
@@ -208,395 +129,6 @@ lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, S
return arr;
}
////////////////////////////////
internal LNK_LibWriter *
lnk_lib_writer_alloc(void)
{
Arena *arena = arena_alloc();
LNK_LibWriter *writer = push_array(arena, LNK_LibWriter, 1);
writer->arena = arena;
return writer;
}
internal void
lnk_lib_writer_release(LNK_LibWriter **writer_ptr)
{
arena_release((*writer_ptr)->arena);
*writer_ptr = 0;
}
internal void
lnk_lib_writer_push_obj(LNK_LibWriter *writer, LNK_Obj *obj)
{
ProfBeginFunction();
U64 member_idx = writer->member_list.count;
// push obj member
LNK_LibMember member = {0};
member.name = obj->path;
member.data = obj->data;
lnk_lib_member_list_push(writer->arena, &writer->member_list, member);
// push external symbols
{
COFF_FileHeaderInfo coff_info = coff_file_header_info_from_data(obj->data);
String8 string_table = str8_substr(obj->data, coff_info.string_table_range);
String8 symbol_table = str8_substr(obj->data, coff_info.symbol_table_range);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < coff_info.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
void *symbol_ptr;
if (coff_info.is_big_obj) {
symbol_ptr = &((COFF_Symbol32 *)symbol_table.str)[symbol_idx];
symbol = coff_parse_symbol32(string_table, symbol_ptr);
} else {
symbol_ptr = &((COFF_Symbol16 *)symbol_table.str)[symbol_idx];
symbol = coff_parse_symbol16(string_table, symbol_ptr);
}
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) {
if (symbol.storage_class == COFF_SymStorageClass_External) {
LNK_LibSymbol lib_symbol = {0};
lib_symbol.name = symbol.name;
lib_symbol.member_idx = member_idx;
lnk_lib_symbol_list_push(writer->arena, &writer->symbol_list, lib_symbol);
}
}
}
}
ProfEnd();
}
internal void
lnk_lib_writer_push_export(LNK_LibWriter *writer, COFF_MachineType machine, U64 time_stamp, String8 dll_name, LNK_Export *exp)
{
ProfBeginFunction();
U64 member_idx = writer->member_list.count;
// make import header
String8 import_data;
if (exp->name.size) {
U16 hint = safe_cast_u16(exp->id);
import_data = coff_make_import_header_by_name(writer->arena, dll_name, machine, time_stamp, exp->name, hint, exp->type);
} else {
U16 ordinal = safe_cast_u16(exp->id);
import_data = coff_make_import_header_by_ordinal(writer->arena, dll_name, machine, time_stamp, ordinal, exp->type);
}
// push import member
LNK_LibMember member = {0};
member.name = dll_name;
member.data = import_data;
lnk_lib_member_list_push(writer->arena, &writer->member_list, member);
switch (exp->type) {
case COFF_ImportHeader_Code: {
LNK_LibSymbol def_symbol = {0};
def_symbol.name = push_str8_copy(writer->arena, exp->name);
def_symbol.member_idx = member_idx;
lnk_lib_symbol_list_push(writer->arena, &writer->symbol_list, def_symbol);
}
case COFF_ImportHeader_Data: {
LNK_LibSymbol imp_symbol = {0};
imp_symbol.name = push_str8f(writer->arena, "__imp_%S", exp->name);
imp_symbol.member_idx = member_idx;
lnk_lib_symbol_list_push(writer->arena, &writer->symbol_list, imp_symbol);
} break;
case COFF_ImportHeader_Const: {
NotImplemented;
} break;
default: InvalidPath;
}
ProfEnd();
}
internal LNK_LibBuild
lnk_lib_build_from_writer(Arena *arena, LNK_LibWriter *writer)
{
ProfBeginFunction();
LNK_LibBuild lib = {0};
lib.symbol_count = writer->symbol_list.count + 2;
lib.member_count = writer->member_list.count;
lib.symbol_array = lnk_lib_symbol_array_from_list(arena, writer->symbol_list);
lib.member_array = lnk_lib_member_array_from_list(arena, writer->member_list);
lnk_lib_symbol_array_sort(lib.symbol_array, lib.symbol_count);
ProfEnd();
return lib;
}
internal String8List
lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second_member, COFF_TimeStamp time_stamp, U32 mode)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
U64 symbol_count = lib->symbol_count - 2;
LNK_LibSymbol *symbol_arr = lib->symbol_array + 1;
HashTable *name_ht = hash_table_init(scratch.arena, 1024);
U64 *member_off_arr = push_array_no_zero(scratch.arena, U64, lib->member_count);
String8List long_names_list = {0};
String8List member_data_list = {0};
for (U64 member_idx = 0; member_idx < lib->member_count; member_idx += 1) {
LNK_LibMember *member = &lib->member_array[member_idx];
// make member name
String8 name;
U64 name_with_slash_size = member->name.size + 1;
if (name_with_slash_size > COFF_Archive_MaxShortNameSize) {
// have we seen this member name before?
KeyValuePair *is_present = hash_table_search_string(name_ht, member->name);
if (is_present) {
name = is_present->value_string;
} else {
name = push_str8f(scratch.arena, "/%u", long_names_list.total_size);
str8_list_pushf(scratch.arena, &long_names_list, "%S/\n", member->name);
hash_table_push_string_string(scratch.arena, name_ht, member->name, name);
}
} else {
name = push_str8f(scratch.arena, "%S/", member->name);
}
member_off_arr[member_idx] = member_data_list.total_size;
String8 member_data = member->data;
String8 member_header = lnk_build_lib_member_header(arena, name, time_stamp, 0, 0, mode, member_data.size);
str8_list_push(arena, &member_data_list, member_header);
str8_list_push(arena, &member_data_list, member_data);
str8_list_push_pad(arena, &member_data_list, member_data_list.total_size, COFF_Archive_MemberAlign);
}
// long names member
if (long_names_list.total_size > 0) {
String8 header = lnk_build_lib_member_header(arena, str8_lit("//"), time_stamp, 0, 0, mode, long_names_list.total_size);
String8 data = str8_list_join(arena, &long_names_list, 0);
U64 member_offset = member_data_list.total_size + data.size + header.size;
str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_Archive_MemberAlign);
str8_list_push_front(arena, &member_data_list, data);
str8_list_push_front(arena, &member_data_list, header);
}
// compute size for symbol string table
U32 name_buffer_size = 0;
for (LNK_LibSymbol *ptr = &symbol_arr[0], *opl = ptr + symbol_count; ptr < opl; ptr += 1) {
name_buffer_size += ptr->name.size;
name_buffer_size += 1; // null
}
// write symbol name buffer
U8 *name_buffer = push_array_no_zero(scratch.arena, U8, name_buffer_size);
{
U64 name_cursor = 0;
for (LNK_LibSymbol *ptr = &symbol_arr[0], *opl = ptr + symbol_count; ptr < opl; ptr += 1) {
MemoryCopy(name_buffer + name_cursor, ptr->name.str, ptr->name.size);
name_buffer[name_cursor + ptr->name.size] = '\0';
name_cursor += ptr->name.size + 1;
}
}
U64 member_base_off;
{
U64 sizeof_first_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * symbol_count + name_buffer_size;
U64 sizeof_second_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * lib->member_count + sizeof(U32) + sizeof(U16) * symbol_count + name_buffer_size;
U64 sizeof_long_names = sizeof(COFF_ArchiveMemberHeader) + long_names_list.total_size;
sizeof_first_header = AlignPow2(sizeof_first_header, COFF_Archive_MemberAlign);
sizeof_second_header = AlignPow2(sizeof_second_header, COFF_Archive_MemberAlign);
sizeof_long_names = AlignPow2(sizeof_long_names, COFF_Archive_MemberAlign);
member_base_off = sizeof(g_coff_archive_sig);
member_base_off += sizeof_first_header;
if (emit_second_member) {
member_base_off += sizeof_second_header;
}
if (long_names_list.total_size > 0) {
member_base_off += sizeof_long_names;
}
}
// second linker member
if (emit_second_member) {
U32 member_count32 = safe_cast_u32(lib->member_count);
U32 symbol_count32 = safe_cast_u32(symbol_count);
U32 *member_off32_arr = push_array_no_zero(scratch.arena, U32, lib->member_count);
U16 *member_idx16_arr = push_array_no_zero(scratch.arena, U16, symbol_count);
// write member offset array
for (U64 member_idx = 0; member_idx < lib->member_count; member_idx += 1) {
U64 member_off = member_base_off + member_off_arr[member_idx];
U32 member_off32 = safe_cast_u32(member_off);
member_off32_arr[member_idx] = member_off32;
}
// write member offset indices for each symbol
for (U64 symbol_idx = 0; symbol_idx < symbol_count; symbol_idx += 1) {
// member offset indices are 1-based
U64 member_idx = symbol_arr[symbol_idx].member_idx + 1;
U16 member_idx16 = safe_cast_u16(member_idx);
member_idx16_arr[symbol_idx] = member_idx16;
}
// layout second member data
String8List second_member_data_list = {0};
str8_list_push(scratch.arena, &second_member_data_list, str8_struct(&member_count32));
str8_list_push(scratch.arena, &second_member_data_list, str8_array(member_off32_arr, lib->member_count));
str8_list_push(scratch.arena, &second_member_data_list, str8_struct(&symbol_count32));
str8_list_push(scratch.arena, &second_member_data_list, str8_array(member_idx16_arr, symbol_count));
str8_list_push(scratch.arena, &second_member_data_list, str8(name_buffer, name_buffer_size));
String8 member_data = str8_list_join(arena, &second_member_data_list, 0);
String8 member_header = lnk_build_lib_member_header(arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size);
U64 member_offset = member_data_list.total_size + member_data.size + member_header.size;
str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_Archive_MemberAlign);
str8_list_push_front(arena, &member_data_list, member_data);
str8_list_push_front(arena, &member_data_list, member_header);
}
// first linker member (obsolete, but kept for compatability reasons)
{
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) {
LNK_LibSymbol *symbol = &symbol_arr[symbol_idx];
// write big endian member offset
U64 member_off = member_base_off + member_off_arr[symbol->member_idx];
U32 member_off32 = from_be_u32(safe_cast_u32(member_off));
member_off32_arr[symbol_idx] = member_off32;
}
// layout first member data
String8List first_member_data_list = {0};
str8_list_push(scratch.arena, &first_member_data_list, str8_struct(&symbol_count_be));
str8_list_push(scratch.arena, &first_member_data_list, str8_array(member_off32_arr, symbol_count));
str8_list_push(scratch.arena, &first_member_data_list, str8(name_buffer, name_buffer_size));
String8 member_data = str8_list_join(arena, &first_member_data_list, 0);
String8 member_header = lnk_build_lib_member_header(arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size);
U64 member_offset = sizeof(g_coff_archive_sig) + member_header.size + member_data.size;
str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_Archive_MemberAlign);
str8_list_push_front(arena, &member_data_list, member_data);
str8_list_push_front(arena, &member_data_list, member_header);
}
// archive signature
str8_list_push_front(arena, &member_data_list, str8_struct(&g_coff_archive_sig));
scratch_end(scratch);
ProfEnd();
return member_data_list;
}
////////////////////////////////
internal LNK_LibBuild
lnk_build_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ObjList obj_list, LNK_ExportTable *exptab)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
LNK_LibWriter *writer = lnk_lib_writer_alloc();
for (LNK_ObjNode *obj_node = obj_list.first; obj_node != 0; obj_node = obj_node->next) {
lnk_lib_writer_push_obj(writer, &obj_node->data);
}
KeyValuePair *raw_export_arr = key_value_pairs_from_hash_table(scratch.arena, exptab->name_export_ht);
for (U64 i = 0; i < exptab->name_export_ht->count; ++i) {
LNK_Export *exp = raw_export_arr[i].value_raw;
lnk_lib_writer_push_export(writer, machine, time_stamp, dll_name, exp);
}
LNK_LibBuild lib = lnk_lib_build_from_writer(arena, writer);
lnk_lib_writer_release(&writer);
scratch_end(scratch);
ProfEnd();
return lib;
}
internal String8
lnk_build_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size)
{
ProfBeginFunction();
Assert(name.size < 16);
Assert(user_id < 10000);
Assert(group_id < 10000);
Assert(mode < 10000);
Assert(size < 1000000000);
//U64 sizeof_member_header = /* name */ 16 + /* time */ 12 + /* user_id */ 6 + /* group id */ 6 + /* mode */ 8 + /* size */ 10;
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
str8_list_pushf(scratch.arena, &list, "%-16.*s", str8_varg(name));
str8_list_pushf(scratch.arena, &list, "%-12u", time_stamp);
str8_list_pushf(scratch.arena, &list, "%-6u", user_id);
str8_list_pushf(scratch.arena, &list, "%-6u", group_id);
str8_list_pushf(scratch.arena, &list, "%-8u", mode);
str8_list_pushf(scratch.arena, &list, "%-10u", size);
str8_list_pushf(scratch.arena, &list, "`\n");
String8 result = str8_list_join(arena, &list, 0);
Assert(result.size == sizeof(COFF_ArchiveMemberHeader));
scratch_end(scratch);
ProfEnd();
return result;
}
internal String8List
lnk_build_import_lib(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 lib_name, String8 dll_name, LNK_ExportTable *exptab)
{
ProfBeginFunction();
Temp scratch = scratch_begin(arena->v, arena->count);
dll_name = str8_skip_last_slash(dll_name);
// These objects appear in first three members of any lib that linker produces with /dll.
// Objects are used by MSVC linker to build import table.
String8 import_obj_array[3];
import_obj_array[0] = lnk_build_import_entry_obj(scratch.arena, dll_name, time_stamp, machine);
import_obj_array[1] = lnk_build_null_import_descriptor_obj(scratch.arena, time_stamp, machine);
import_obj_array[2] = lnk_build_null_thunk_data_obj(scratch.arena, dll_name, time_stamp, machine);
// build input list
LNK_InputObjList input_obj_list = {0};
for (U64 i = 0; i < ArrayCount(import_obj_array); ++i) {
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
input->data = import_obj_array[i];
input->path = dll_name;
input->lib_path = lib_name;
}
LNK_InputObj **inputs = lnk_array_from_input_obj_list(scratch.arena, input_obj_list);
LNK_ObjList obj_list = {0};
lnk_obj_list_push_parallel(tp, arena, &obj_list, machine, input_obj_list.count, inputs);
LNK_LibBuild import_lib = lnk_build_lib(scratch.arena, machine, time_stamp, dll_name, obj_list, exptab);
B32 emit_second_member = 1;
String8List coff_archive_data = lnk_coff_archive_from_lib_build(arena->v[0], &import_lib, emit_second_member, COFF_TimeStamp_Max, 0);
// cleanup memory
scratch_end(scratch);
ProfEnd();
return coff_archive_data;
}
internal
THREAD_POOL_TASK_FUNC(lnk_push_lib_symbols_task)
{
+1 -82
View File
@@ -36,61 +36,6 @@ typedef struct LNK_LibList
////////////////////////////////
typedef struct LNK_LibMember
{
String8 name;
String8 data;
} LNK_LibMember;
typedef struct LNK_LibMemberNode
{
struct LNK_LibMemberNode *next;
LNK_LibMember data;
} LNK_LibMemberNode;
typedef struct LNK_LibMemberList
{
U64 count;
LNK_LibMemberNode *first;
LNK_LibMemberNode *last;
} LNK_LibMemberList;
typedef struct LNK_LibSymbol
{
String8 name;
U64 member_idx;
} LNK_LibSymbol;
typedef struct LNK_LibSymbolNode
{
struct LNK_LibSymbolNode *next;
LNK_LibSymbol data;
} LNK_LibSymbolNode;
typedef struct LNK_LibSymbolList
{
U64 count;
LNK_LibSymbolNode *first;
LNK_LibSymbolNode *last;
} LNK_LibSymbolList;
typedef struct LNK_LibWriter
{
Arena *arena;
LNK_LibMemberList member_list;
LNK_LibSymbolList symbol_list;
} LNK_LibWriter;
typedef struct LNK_LibBuild
{
U64 symbol_count;
U64 member_count;
LNK_LibSymbol *symbol_array;
LNK_LibMember *member_array;
} LNK_LibBuild;
////////////////////////////////
typedef struct
{
LNK_LibNode *node_arr;
@@ -101,32 +46,6 @@ typedef struct
////////////////////////////////
internal LNK_LibNode * lnk_lib_list_reserve(Arena *arena, LNK_LibList *list, U64 count);
internal LNK_LibMemberNode * lnk_lib_member_list_push(Arena *arena, LNK_LibMemberList *list, LNK_LibMember member);
internal LNK_LibMember * lnk_lib_member_array_from_list(Arena *arena, LNK_LibMemberList list);
internal LNK_LibSymbolNode * lnk_lib_symbol_list_push(Arena *arena, LNK_LibSymbolList *list, LNK_LibSymbol symbol);
internal LNK_LibSymbol * lnk_lib_symbol_array_from_list(Arena *arena, LNK_LibSymbolList list);
internal void lnk_lib_symbol_array_sort(LNK_LibSymbol *arr, U64 count);
////////////////////////////////
internal LNK_Lib lnk_lib_from_data(Arena *arena, String8 data, String8 path);
internal LNK_Lib lnk_lib_from_data(Arena *arena, String8 data, String8 path);
internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, String8Array data_arr, String8Array path_arr);
////////////////////////////////
internal LNK_LibWriter * lnk_lib_writer_alloc(void);
internal void lnk_lib_writer_release(LNK_LibWriter **writer_ptr);
internal void lnk_lib_writer_push_obj(LNK_LibWriter *writer, LNK_Obj *obj);
internal void lnk_lib_writer_push_export(LNK_LibWriter *writer, COFF_MachineType machine, U64 time_stamp, String8 dll_name, LNK_Export *exp);
internal LNK_LibBuild lnk_lib_build_from_writer(Arena *arena, LNK_LibWriter *writer);
internal String8List lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second_member, COFF_TimeStamp time_stamp, U32 mode);
////////////////////////////////
internal LNK_LibBuild lnk_build_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ObjList obj_list, LNK_ExportTable *exptab);
internal String8 lnk_build_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size);
internal String8List lnk_build_import_lib(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 lib_name, String8 dll_name, LNK_ExportTable *exptab);
+12
View File
@@ -9,21 +9,33 @@
////////////////////////////////
#include "third_party/xxHash/xxhash.c"
#include "third_party/xxHash/xxhash.h"
#include "third_party/radsort/radsort.h"
////////////////////////////////
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "path/path.h"
#include "coff/coff.h"
#include "coff/coff_enum.h"
#include "coff/coff_parse.h"
#include "coff/coff_obj_writer.h"
#include "coff/coff_lib_writer.h"
#include "pe/pe.h"
#include "linker/hash_table.h"
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "path/path.c"
#include "coff/coff.c"
#include "coff/coff_enum.c"
#include "coff/coff_parse.c"
#include "coff/coff_obj_writer.c"
#include "coff/coff_lib_writer.c"
#include "pe/pe.c"
#include "linker/hash_table.c"
#include "linker/lnk_cmd_line.h"
#include "linker/lnk_cmd_line.c"