mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 15:42:23 -07:00
removed default lib directive parser, moved directive code to obj file,
getting ready to deprecate LNK_Directive struct
This commit is contained in:
@@ -99,6 +99,7 @@ coff_header_info_from_data(String8 data)
|
||||
COFF_HeaderBigObj *big_header = (COFF_HeaderBigObj*)data.str;
|
||||
info.type = COFF_DataType_BIG_OBJ;
|
||||
info.machine = big_header->machine;
|
||||
info.header_size = sizeof(COFF_HeaderBigObj);
|
||||
info.section_array_off = sizeof(COFF_HeaderBigObj);
|
||||
info.section_count_no_null = big_header->section_count;
|
||||
info.string_table_off = big_header->symbol_table_foff + sizeof(COFF_Symbol32) * big_header->symbol_count;
|
||||
@@ -109,6 +110,7 @@ coff_header_info_from_data(String8 data)
|
||||
COFF_Header *header = (COFF_Header*)data.str;
|
||||
info.type = COFF_DataType_OBJ;
|
||||
info.machine = header->machine;
|
||||
info.header_size = sizeof(COFF_Header);
|
||||
info.section_array_off = sizeof(COFF_Header);
|
||||
info.section_count_no_null = header->section_count;
|
||||
info.string_table_off = header->symbol_table_foff + sizeof(COFF_Symbol16) * header->symbol_count;
|
||||
|
||||
+2
-1
@@ -634,8 +634,9 @@ typedef U32 COFF_DataType;
|
||||
|
||||
typedef struct COFF_HeaderInfo
|
||||
{
|
||||
COFF_MachineType machine;
|
||||
COFF_DataType type;
|
||||
COFF_MachineType machine;
|
||||
U64 header_size;
|
||||
U64 section_array_off;
|
||||
U64 section_count_no_null;
|
||||
U64 string_table_off;
|
||||
|
||||
+11
-3
@@ -115,7 +115,6 @@
|
||||
#include "lnk_config.h"
|
||||
#include "lnk_chunk.h"
|
||||
#include "lnk_reloc.h"
|
||||
#include "lnk_directive.h"
|
||||
#include "lnk_symbol_table.h"
|
||||
#include "lnk_section_table.h"
|
||||
#include "lnk_obj.h"
|
||||
@@ -133,7 +132,6 @@
|
||||
#include "lnk_config.c"
|
||||
#include "lnk_chunk.c"
|
||||
#include "lnk_reloc.c"
|
||||
#include "lnk_directive.c"
|
||||
#include "lnk_symbol_table.c"
|
||||
#include "lnk_section_table.c"
|
||||
#include "lnk_obj.c"
|
||||
@@ -3553,6 +3551,8 @@ lnk_run(int argc, char **argv)
|
||||
// derive machine from obj
|
||||
if (config->machine == COFF_MachineType_UNKNOWN) {
|
||||
config->machine = obj->machine;
|
||||
} else if (config->machine != COFF_MachineType_X64) {
|
||||
lnk_error_with_loc(LNK_Error_UnsupportedMachine, obj->path, obj->lib_path, "%S machine is supported", coff_string_from_machine_type(obj->machine));
|
||||
} else {
|
||||
// is obj machine compatible?
|
||||
if (config->machine != obj->machine &&
|
||||
@@ -3901,8 +3901,16 @@ lnk_run(int argc, char **argv)
|
||||
} break;
|
||||
case State_BuildExportTable: {
|
||||
ProfBegin("Build Export Table");
|
||||
|
||||
|
||||
// push exports from command line
|
||||
for (LNK_ExportParse *exp_parse = config->export_symbol_list.first; exp_parse != 0; exp_parse = exp_parse->next) {
|
||||
lnk_export_table_push_export(exptab, symtab, exp_parse);
|
||||
}
|
||||
|
||||
// push exports from obj directives
|
||||
lnk_collect_exports_from_obj_directives(exptab, obj_list, symtab);
|
||||
|
||||
// build export table section
|
||||
lnk_build_edata(exptab, st, symtab, config->image_name, config->machine);
|
||||
|
||||
ProfEnd();
|
||||
|
||||
+93
-1
@@ -43,7 +43,7 @@ read_only struct
|
||||
{ LNK_CmdSwitch_NotImplemented, "EMITVOLATILEMETADATA", "", "" },
|
||||
{ LNK_CmdSwitch_Entry, "ENTRY", ":FUNCTION", "" },
|
||||
{ LNK_CmdSwitch_Null, "ERRORREPORT", "", "Deprecated starting Windows Vista." },
|
||||
{ LNK_CmdSwitch_NotImplemented, "EXPORT", ":SYMBOL", "" },
|
||||
{ LNK_CmdSwitch_Export, "EXPORT", ":SYMBOL", "" },
|
||||
{ LNK_CmdSwitch_NotImplemented, "EXPORTADMIN", "", "" },
|
||||
{ LNK_CmdSwitch_FastFail, "FASTFAIL", "", "Not used." },
|
||||
{ LNK_CmdSwitch_NotImplemented, "FASTGENPROFILE", "", "" },
|
||||
@@ -773,6 +773,13 @@ lnk_cmd_switch_parse_string_copy(Arena *arena, String8 obj_path, String8 lib_pat
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
lnk_alt_name_list_concat_in_place(LNK_AltNameList *list, LNK_AltNameList *to_concat)
|
||||
{
|
||||
str8_list_concat_in_place(&list->from_list, &to_concat->from_list);
|
||||
str8_list_concat_in_place(&list->to_list, &to_concat->to_list);
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_parse_alt_name_directive(Arena *arena, String8 input, LNK_AltNameList *list_out)
|
||||
{
|
||||
@@ -800,6 +807,86 @@ lnk_parse_alt_name_directive_list(Arena *arena, String8List list, LNK_AltNameLis
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal LNK_ExportParse *
|
||||
lnk_parse_export_directive(Arena *arena, LNK_ExportParseList *list, String8List value_list, String8 obj_path, String8 lib_path)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
LNK_ExportParse *parse = 0;
|
||||
|
||||
// parse directive
|
||||
String8 name = str8_zero();
|
||||
String8 alias = str8_zero();
|
||||
String8 type = coff_string_from_import_header_type(COFF_ImportHeaderType_CODE);
|
||||
if (value_list.node_count > 0) {
|
||||
String8List dir_split = str8_split_by_string_chars(scratch.arena, value_list.first->string, str8_lit("="), 0);
|
||||
B32 is_export_valid = value_list.node_count <= 2 && value_list.node_count > 0;
|
||||
if (is_export_valid) {
|
||||
if (dir_split.node_count > 0) {
|
||||
name = dir_split.last->string;
|
||||
}
|
||||
if (dir_split.node_count == 2) {
|
||||
alias = dir_split.first->string;
|
||||
}
|
||||
if (value_list.node_count == 2) {
|
||||
type = value_list.last->string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prase error check
|
||||
if (name.size == 0) {
|
||||
String8 dir = str8_list_join(scratch.arena, &value_list, 0);
|
||||
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "invalid export directive \"%S\"", dir);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
parse = push_array_no_zero(arena, LNK_ExportParse, 1);
|
||||
parse->next = 0;
|
||||
parse->name = name;
|
||||
parse->alias = alias;
|
||||
parse->type = type;
|
||||
|
||||
SLLQueuePush(list->first, list->last, parse);
|
||||
++list->count;
|
||||
|
||||
exit:;
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return parse;
|
||||
}
|
||||
|
||||
internal LNK_MergeDirectiveNode *
|
||||
lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective data)
|
||||
{
|
||||
LNK_MergeDirectiveNode *node = push_array_no_zero(arena, LNK_MergeDirectiveNode, 1);
|
||||
node->data = data;
|
||||
node->next = 0;
|
||||
|
||||
SLLQueuePush(list->first, list->last, node);
|
||||
++list->count;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_parse_merge_directive(String8 string, LNK_MergeDirective *out)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
B32 is_parse_ok = 0;
|
||||
|
||||
String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("="), 0);
|
||||
if (list.node_count == 2) {
|
||||
out->src = list.first->string;
|
||||
out->dst = list.last->string;
|
||||
is_parse_ok = 1;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return is_parse_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
@@ -1028,6 +1115,11 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
config->entry_point_name = new_entry_point_name;
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Export: {
|
||||
String8List value_strings_copy = str8_list_copy(arena, &value_strings);
|
||||
lnk_parse_export_directive(arena, &config->export_symbol_list, value_strings_copy, obj_path, lib_path);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_FastFail: {
|
||||
// do nothing
|
||||
} break;
|
||||
|
||||
+46
-2
@@ -7,7 +7,6 @@ typedef enum
|
||||
{
|
||||
LNK_CmdSwitch_Null,
|
||||
LNK_CmdSwitch_NotImplemented,
|
||||
LNK_CmdSwitch_Deprecated,
|
||||
|
||||
LNK_CmdSwitch_Align,
|
||||
LNK_CmdSwitch_AllowBind,
|
||||
@@ -22,6 +21,7 @@ typedef enum
|
||||
LNK_CmdSwitch_Dll,
|
||||
LNK_CmdSwitch_DynamicBase,
|
||||
LNK_CmdSwitch_Entry,
|
||||
LNK_CmdSwitch_Export,
|
||||
LNK_CmdSwitch_FastFail,
|
||||
LNK_CmdSwitch_FileAlign,
|
||||
LNK_CmdSwitch_Fixed,
|
||||
@@ -77,7 +77,6 @@ typedef enum
|
||||
LNK_CmdSwitch_EditAndContinue,
|
||||
LNK_CmdSwitch_EmitVolatileMetadata,
|
||||
LNK_CmdSwitch_ErrorReport,
|
||||
LNK_CmdSwitch_Export,
|
||||
LNK_CmdSwitch_ExportAdmin,
|
||||
LNK_CmdSwitch_FastGenProfile,
|
||||
LNK_CmdSwitch_FailIfMismatch,
|
||||
@@ -227,6 +226,42 @@ typedef struct LNK_AltNameList
|
||||
String8List to_list;
|
||||
} LNK_AltNameList;
|
||||
|
||||
typedef struct LNK_ExportParse
|
||||
{
|
||||
struct LNK_ExportParse *next;
|
||||
String8 name;
|
||||
String8 alias;
|
||||
String8 type;
|
||||
} LNK_ExportParse;
|
||||
|
||||
typedef struct LNK_ExportParseList
|
||||
{
|
||||
U64 count;
|
||||
LNK_ExportParse *first;
|
||||
LNK_ExportParse *last;
|
||||
} LNK_ExportParseList;
|
||||
|
||||
typedef struct LNK_MergeDirective
|
||||
{
|
||||
String8 src;
|
||||
String8 dst;
|
||||
} LNK_MergeDirective;
|
||||
|
||||
typedef struct LNK_MergeDirectiveNode
|
||||
{
|
||||
struct LNK_MergeDirectiveNode *next;
|
||||
LNK_MergeDirective data;
|
||||
} LNK_MergeDirectiveNode;
|
||||
|
||||
typedef struct LNK_MergeDirectiveList
|
||||
{
|
||||
U64 count;
|
||||
LNK_MergeDirectiveNode *first;
|
||||
LNK_MergeDirectiveNode *last;
|
||||
} LNK_MergeDirectiveList;
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_DebugInfoGuid_Null,
|
||||
@@ -301,6 +336,7 @@ typedef struct LNK_Config
|
||||
LNK_TypeNameHashMode pdb_hash_type_names;
|
||||
String8 pdb_hash_type_name_map;
|
||||
U64 pdb_hash_type_name_length;
|
||||
LNK_ExportParseList export_symbol_list;
|
||||
String8List input_list[LNK_Input_Count];
|
||||
String8List input_default_lib_list;
|
||||
String8List disallow_lib_list;
|
||||
@@ -506,9 +542,17 @@ internal void lnk_cmd_switch_set_flag_64(String8 obj_path, String8 lib_path, LNK
|
||||
internal B32 lnk_cmd_switch_parse_string(String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out);
|
||||
internal void lnk_cmd_switch_parse_string_copy(Arena *arena, String8 obj_path, String8 lib_path, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void lnk_alt_name_list_concat_in_place(LNK_AltNameList *list, LNK_AltNameList *to_concat);
|
||||
internal B32 lnk_parse_alt_name_directive(Arena *arena, String8 input, LNK_AltNameList *list_out);
|
||||
internal String8 * lnk_parse_alt_name_directive_list(Arena *arena, String8List list, LNK_AltNameList *list_out);
|
||||
|
||||
internal LNK_ExportParse * lnk_parse_export_directive(Arena *arena, LNK_ExportParseList *list, String8List value_list, String8 obj_path, String8 lib_path);
|
||||
|
||||
internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective data);
|
||||
internal B32 lnk_parse_merge_directive(String8 string, LNK_MergeDirective *out);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 name, String8List value_list, String8 obj_path, String8 lib_path);
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
lnk_alt_name_list_concat_in_place(LNK_AltNameList *list, LNK_AltNameList *to_concat)
|
||||
{
|
||||
str8_list_concat_in_place(&list->from_list, &to_concat->from_list);
|
||||
str8_list_concat_in_place(&list->to_list, &to_concat->to_list);
|
||||
}
|
||||
|
||||
internal LNK_MergeDirectiveNode *
|
||||
lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective data)
|
||||
{
|
||||
LNK_MergeDirectiveNode *node = push_array_no_zero(arena, LNK_MergeDirectiveNode, 1);
|
||||
node->data = data;
|
||||
node->next = 0;
|
||||
|
||||
SLLQueuePush(list->first, list->last, node);
|
||||
++list->count;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal B32
|
||||
lnk_is_directive_legal(LNK_CmdSwitchType type)
|
||||
{
|
||||
static B32 init_table = 1;
|
||||
static B8 is_legal[LNK_CmdSwitch_Count];
|
||||
if (init_table) {
|
||||
init_table = 0;
|
||||
is_legal[LNK_CmdSwitch_AlternateName] = 1;
|
||||
is_legal[LNK_CmdSwitch_DefaultLib] = 1;
|
||||
is_legal[LNK_CmdSwitch_DisallowLib] = 1;
|
||||
is_legal[LNK_CmdSwitch_EditAndContinue] = 1;
|
||||
is_legal[LNK_CmdSwitch_Entry] = 1;
|
||||
is_legal[LNK_CmdSwitch_Export] = 1;
|
||||
is_legal[LNK_CmdSwitch_FailIfMismatch] = 1;
|
||||
is_legal[LNK_CmdSwitch_GuardSym] = 1;
|
||||
is_legal[LNK_CmdSwitch_Include] = 1;
|
||||
is_legal[LNK_CmdSwitch_InferAsanLibs] = 1;
|
||||
is_legal[LNK_CmdSwitch_InferAsanLibsNo] = 1;
|
||||
is_legal[LNK_CmdSwitch_ManifestDependency] = 1;
|
||||
is_legal[LNK_CmdSwitch_Merge] = 1;
|
||||
is_legal[LNK_CmdSwitch_NoDefaultLib] = 1;
|
||||
is_legal[LNK_CmdSwitch_Release] = 1;
|
||||
is_legal[LNK_CmdSwitch_Section] = 1;
|
||||
is_legal[LNK_CmdSwitch_Stack] = 1;
|
||||
is_legal[LNK_CmdSwitch_SubSystem] = 1;
|
||||
is_legal[LNK_CmdSwitch_ThrowingNew] = 1;
|
||||
}
|
||||
return is_legal[type];
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_parse_directives(Arena *arena, LNK_DirectiveInfo *directive_info, String8 buffer, String8 obj_path)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
String8 to_parse;
|
||||
{
|
||||
local_persist const U8 bom_sig[] = { 0xEF, 0xBB, 0xBF };
|
||||
local_persist const U8 ascii_sig[] = { 0x20, 0x20, 0x20 };
|
||||
if (MemoryMatch(buffer.str, &bom_sig[0], sizeof(bom_sig))) {
|
||||
to_parse = str8_zero();
|
||||
lnk_not_implemented("TODO: support for BOM encoding");
|
||||
} else if (MemoryMatch(buffer.str, &ascii_sig[0], sizeof(ascii_sig))) {
|
||||
to_parse = str8_skip(buffer, sizeof(ascii_sig));
|
||||
} else {
|
||||
to_parse = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
String8List arg_list = lnk_arg_list_parse_windows_rules(scratch.arena, to_parse);
|
||||
LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, arg_list);
|
||||
|
||||
for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) {
|
||||
LNK_CmdSwitchType type = lnk_cmd_switch_type_from_string(opt->string);
|
||||
|
||||
if (type == LNK_CmdSwitch_Null) {
|
||||
lnk_error(LNK_Warning_UnknownDirective, "%S: unknown directive \"%S\"", obj_path, opt->string);
|
||||
continue;
|
||||
}
|
||||
if (!lnk_is_directive_legal(type)) {
|
||||
lnk_error(LNK_Warning_IllegalDirective, "%S: illegal directive \"%S\"", obj_path, opt->string);
|
||||
continue;
|
||||
}
|
||||
|
||||
LNK_Directive *directive = push_array_no_zero(arena, LNK_Directive, 1);
|
||||
directive->next = 0;
|
||||
directive->id = push_str8_copy(arena, opt->string);
|
||||
directive->value_list = str8_list_copy(arena, &opt->value_strings);
|
||||
|
||||
LNK_DirectiveList *directive_list = &directive_info->v[type];
|
||||
SLLQueuePush(directive_list->first, directive_list->last, directive);
|
||||
++directive_list->count;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal String8List
|
||||
lnk_parse_default_lib_directive(Arena *arena, LNK_DirectiveList *dir_list)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
String8List default_libs = {0};
|
||||
|
||||
for (LNK_Directive *dir = dir_list->first; dir != 0; dir = dir->next) {
|
||||
for (String8Node *i = dir->value_list.first; i != 0; i = i->next) {
|
||||
String8 lib_path = i->string;
|
||||
|
||||
// is there lib extension?
|
||||
String8 ext = str8_skip_last_dot(lib_path);
|
||||
if (ext.size == lib_path.size) { // TODO: fix string_extension_from_path, if there is no extension it should return zero
|
||||
lib_path = push_str8f(arena, "%S.lib", lib_path);
|
||||
} else {
|
||||
lib_path = push_str8_copy(arena, lib_path);
|
||||
}
|
||||
|
||||
str8_list_push(arena, &default_libs, lib_path);
|
||||
}
|
||||
}
|
||||
|
||||
ProfEnd();
|
||||
return default_libs;
|
||||
}
|
||||
|
||||
internal LNK_ExportParse *
|
||||
lnk_parse_export_direcive(Arena *arena, LNK_ExportParseList *list, String8List value_list, LNK_Obj *obj)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
LNK_ExportParse *parse = 0;
|
||||
|
||||
// parse directive
|
||||
String8 name = str8(0,0);
|
||||
String8 alias = str8(0,0);
|
||||
String8 type = coff_string_from_import_header_type(COFF_ImportHeaderType_CODE);
|
||||
if (value_list.node_count > 0) {
|
||||
String8List dir_split = str8_split_by_string_chars(scratch.arena, value_list.first->string, str8_lit("="), 0);
|
||||
B32 is_export_valid = value_list.node_count <= 2 && value_list.node_count > 0;
|
||||
if (is_export_valid) {
|
||||
if (dir_split.node_count > 0) {
|
||||
name = dir_split.last->string;
|
||||
}
|
||||
if (dir_split.node_count == 2) {
|
||||
alias = dir_split.first->string;
|
||||
}
|
||||
if (value_list.node_count == 2) {
|
||||
type = value_list.last->string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prase error check
|
||||
if (name.size == 0) {
|
||||
String8 dir = str8_list_join(scratch.arena, &value_list, 0);
|
||||
lnk_error_obj(LNK_Error_IllData, obj, "invalid export directive \"%S\"", dir);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
parse = push_array_no_zero(arena, LNK_ExportParse, 1);
|
||||
parse->next = 0;
|
||||
parse->name = name;
|
||||
parse->alias = alias;
|
||||
parse->type = type;
|
||||
|
||||
SLLQueuePush(list->first, list->last, parse);
|
||||
++list->count;
|
||||
|
||||
exit:;
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return parse;
|
||||
}
|
||||
|
||||
internal B32
|
||||
lnk_parse_merge_directive(String8 string, LNK_MergeDirective *out)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
B32 is_parse_ok = 0;
|
||||
|
||||
String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("="), 0);
|
||||
if (list.node_count == 2) {
|
||||
out->src = list.first->string;
|
||||
out->dst = list.last->string;
|
||||
is_parse_ok = 1;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return is_parse_ok;
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct LNK_Directive
|
||||
{
|
||||
struct LNK_Directive *next;
|
||||
String8 id;
|
||||
String8List value_list;
|
||||
} LNK_Directive;
|
||||
|
||||
typedef struct LNK_DirectiveList
|
||||
{
|
||||
U64 count;
|
||||
LNK_Directive *first;
|
||||
LNK_Directive *last;
|
||||
} LNK_DirectiveList;
|
||||
|
||||
typedef struct LNK_ExportParse
|
||||
{
|
||||
struct LNK_ExportParse *next;
|
||||
String8 name;
|
||||
String8 alias;
|
||||
String8 type;
|
||||
} LNK_ExportParse;
|
||||
|
||||
typedef struct LNK_ExportParseList
|
||||
{
|
||||
U64 count;
|
||||
LNK_ExportParse *first;
|
||||
LNK_ExportParse *last;
|
||||
} LNK_ExportParseList;
|
||||
|
||||
typedef struct LNK_MergeDirective
|
||||
{
|
||||
String8 src;
|
||||
String8 dst;
|
||||
} LNK_MergeDirective;
|
||||
|
||||
typedef struct LNK_MergeDirectiveNode
|
||||
{
|
||||
struct LNK_MergeDirectiveNode *next;
|
||||
LNK_MergeDirective data;
|
||||
} LNK_MergeDirectiveNode;
|
||||
|
||||
typedef struct LNK_MergeDirectiveList
|
||||
{
|
||||
U64 count;
|
||||
LNK_MergeDirectiveNode *first;
|
||||
LNK_MergeDirectiveNode *last;
|
||||
} LNK_MergeDirectiveList;
|
||||
|
||||
typedef struct LNK_DirectiveInfo
|
||||
{
|
||||
LNK_DirectiveList v[LNK_CmdSwitch_Count];
|
||||
} LNK_DirectiveInfo;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void lnk_alt_name_list_concat_in_place(LNK_AltNameList *list, LNK_AltNameList *to_concat);
|
||||
|
||||
internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective data);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void lnk_parse_directives(Arena *arena, LNK_DirectiveInfo *directive_info, String8 buffer, String8 obj_path);
|
||||
internal String8List lnk_parse_default_lib_directive(Arena *arena, LNK_DirectiveList *dir_list);
|
||||
internal B32 lnk_parse_merge_directive(String8 directive, LNK_MergeDirective *out);
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ typedef enum
|
||||
LNK_Warning_LongSectionName,
|
||||
LNK_Warning_UnknownSwitch,
|
||||
LNK_Warning_TLSAlign,
|
||||
LNK_Warning_DirectiveSectionWithRelocs,
|
||||
LNK_Warning_Last,
|
||||
|
||||
LNK_Error_Count
|
||||
|
||||
+154
-57
@@ -219,9 +219,10 @@ THREAD_POOL_TASK_FUNC(lnk_default_lib_collector)
|
||||
Rng1U64 range = task->range_arr[task_id];
|
||||
String8List *result = &task->out_arr[task_id];
|
||||
for (U64 obj_idx = range.min; obj_idx < range.max; obj_idx += 1) {
|
||||
LNK_Obj *obj = &task->in_arr.v[obj_idx].data;
|
||||
String8List list = lnk_parse_default_lib_directive(arena, &obj->directive_info.v[LNK_CmdSwitch_DefaultLib]);
|
||||
str8_list_concat_in_place(result, &list);
|
||||
LNK_Obj *obj = &task->in_arr.v[obj_idx].data;
|
||||
for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_DefaultLib].first; dir != 0; dir = dir->next) {
|
||||
str8_list_concat_in_place(result, &dir->value_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,19 +323,26 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
LNK_ObjNode *obj_node = task->obj_node_arr + task_id;
|
||||
LNK_Obj *obj = &obj_node->data;
|
||||
|
||||
// cache path, we need it for error reports and debug stuff
|
||||
String8 cached_path = push_str8_copy(arena, input->path);
|
||||
String8 cached_lib_path = push_str8_copy(arena, input->lib_path);
|
||||
|
||||
// parse coff obj
|
||||
COFF_HeaderInfo coff_info = coff_header_info_from_data(input->data);
|
||||
COFF_SectionHeader *coff_sect_arr = (COFF_SectionHeader *)(input->data.str + coff_info.section_array_off);
|
||||
void *coff_symbols = input->data.str + coff_info.symbol_off;
|
||||
COFF_HeaderInfo coff_info = coff_header_info_from_data(input->data);
|
||||
Rng1U64 coff_file_header_range = rng_1u64(0, coff_info.header_size);
|
||||
Rng1U64 coff_sect_arr_range = rng_1u64(coff_info.section_array_off, coff_info.section_array_off + coff_info.section_count_no_null * sizeof(COFF_SectionHeader));
|
||||
Rng1U64 coff_symbols_range = rng_1u64(coff_info.symbol_off, coff_info.symbol_off + coff_info.symbol_count * coff_info.symbol_size);
|
||||
String8 raw_coff_sect_arr = str8_substr(input->data, coff_sect_arr_range);
|
||||
String8 raw_coff_symbols = str8_substr(input->data, coff_symbols_range);
|
||||
|
||||
// handle machines we dont support
|
||||
if (coff_info.machine != COFF_MachineType_UNKNOWN && coff_info.machine != COFF_MachineType_X64) {
|
||||
lnk_error(LNK_Error_UnsupportedMachine, "%S: %S machine is supported", input->path, coff_string_from_machine_type(coff_info.machine));
|
||||
if (raw_coff_sect_arr.size != dim_1u64(coff_sect_arr_range)) {
|
||||
lnk_error_with_loc(LNK_Error_IllData, cached_path, cached_lib_path, "corrupted file, unable to read section header table");
|
||||
}
|
||||
if (raw_coff_symbols.size != dim_1u64(coff_symbols_range)) {
|
||||
lnk_error_with_loc(LNK_Error_IllData, cached_path, cached_lib_path, "corrupted file, unable to read symbol table");
|
||||
}
|
||||
|
||||
COFF_SectionHeader *coff_sect_arr = (COFF_SectionHeader *)raw_coff_sect_arr.str;
|
||||
void *coff_symbols = raw_coff_symbols.str;
|
||||
|
||||
// :function_pad_min
|
||||
U64 function_pad_min;
|
||||
@@ -344,30 +352,13 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
function_pad_min = lnk_get_default_function_pad_min(coff_info.machine);
|
||||
}
|
||||
|
||||
U64 chunk_count = 0;
|
||||
chunk_count += coff_info.section_count_no_null;
|
||||
chunk_count += 1; // :common_block
|
||||
U64 chunk_count = 1; // :common_block
|
||||
chunk_count += coff_info.section_count_no_null;
|
||||
|
||||
String8 *sect_name_arr = push_array_no_zero(arena, String8, chunk_count);
|
||||
String8 *sect_sort_arr = push_array_no_zero(arena, String8, chunk_count);
|
||||
String8 *sect_name_arr = push_array_no_zero(arena, String8, chunk_count);
|
||||
String8 *sect_sort_arr = push_array_no_zero(arena, String8, chunk_count);
|
||||
LNK_Chunk *chunk_arr = push_array_no_zero(arena, LNK_Chunk, chunk_count);
|
||||
|
||||
// init section name and postfix array
|
||||
for (U64 sect_idx = 0; sect_idx < coff_info.section_count_no_null; sect_idx += 1) {
|
||||
COFF_SectionHeader *coff_sect = &coff_sect_arr[sect_idx];
|
||||
|
||||
// read name
|
||||
String8 sect_name = coff_name_from_section_header(coff_sect, input->data, coff_info.string_table_off);
|
||||
|
||||
// parse section name
|
||||
String8 name, postfix;
|
||||
coff_parse_section_name(sect_name, &name, &postfix);
|
||||
|
||||
// fill out
|
||||
sect_name_arr[sect_idx] = name;
|
||||
sect_sort_arr[sect_idx] = postfix;
|
||||
}
|
||||
|
||||
// :common_block
|
||||
U64 common_block_idx = chunk_count - 1;
|
||||
sect_name_arr[common_block_idx] = str8_lit(".bss");
|
||||
@@ -376,11 +367,38 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
for (U64 sect_idx = 0; sect_idx < coff_info.section_count_no_null; sect_idx += 1) {
|
||||
COFF_SectionHeader *coff_sect = &coff_sect_arr[sect_idx];
|
||||
|
||||
// read name
|
||||
String8 sect_name = coff_name_from_section_header(coff_sect, input->data, coff_info.string_table_off);
|
||||
|
||||
// parse section name
|
||||
coff_parse_section_name(sect_name, §_name_arr[sect_idx], §_sort_arr[sect_idx]);
|
||||
|
||||
String8 data;
|
||||
if (coff_sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) {
|
||||
data = str8(0, coff_sect->fsize);
|
||||
} else {
|
||||
data = str8(input->data.str + coff_sect->foff, coff_sect->fsize);
|
||||
if (coff_sect->fsize > 0) {
|
||||
Rng1U64 range = rng_1u64(coff_sect->foff, coff_sect->foff + coff_sect->fsize);
|
||||
data = str8_substr(input->data, range);
|
||||
|
||||
if (contains_1u64(coff_file_header_range, coff_sect->foff) ||
|
||||
(coff_sect->fsize > 0 && contains_1u64(coff_file_header_range, coff_sect->foff + coff_sect->fsize-1))) {
|
||||
lnk_error_with_loc(LNK_Error_IllData, cached_path, cached_lib_path, "header (%S No. %#llx) defines out of bounds section data (file offsets point into file header)", sect_name, sect_idx+1);
|
||||
}
|
||||
if (contains_1u64(coff_sect_arr_range, coff_sect->foff) ||
|
||||
(coff_sect->fsize > 0 && contains_1u64(coff_sect_arr_range, coff_sect->foff + coff_sect->fsize-1))) {
|
||||
lnk_error_with_loc(LNK_Error_IllData, cached_path, cached_lib_path, "header (%S No. %#llx) defines out of bounds section data (file offsets point into section header table)", sect_name, sect_idx+1);
|
||||
}
|
||||
if (contains_1u64(coff_symbols_range, coff_sect->foff) ||
|
||||
(coff_sect->fsize > 0 && contains_1u64(coff_symbols_range, coff_sect->foff + coff_sect->fsize-1))) {
|
||||
lnk_error_with_loc(LNK_Error_IllData, cached_path, cached_lib_path, "header (%S No. %#llx) defines out of bounds section data (file offsets point into symbol table)", sect_name, sect_idx+1);
|
||||
}
|
||||
if (dim_1u64(range) != coff_sect->fsize) {
|
||||
lnk_error_with_loc(LNK_Error_IllData, cached_path, cached_lib_path, "header (%S No. %#llx) defines out of bounds section data", sect_name, sect_idx+1);
|
||||
}
|
||||
} else {
|
||||
data = str8_zero();
|
||||
}
|
||||
}
|
||||
|
||||
LNK_Chunk *chunk = &chunk_arr[sect_idx];
|
||||
@@ -418,10 +436,11 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
}
|
||||
|
||||
// convert from coff
|
||||
B32 is_big_obj = coff_info.type == COFF_DataType_BIG_OBJ;
|
||||
LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, obj, cached_path, is_big_obj, function_pad_min, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_info.symbol_count, coff_symbols, chunk_ptr_arr, master_common_block);
|
||||
LNK_SymbolList symbol_list = lnk_symbol_list_from_array(arena, symbol_arr);
|
||||
LNK_RelocList *reloc_list_arr = lnk_reloc_list_array_from_coff(arena, coff_info.machine, input->data, coff_info.section_count_no_null, coff_sect_arr, chunk_ptr_arr, symbol_arr);
|
||||
B32 is_big_obj = coff_info.type == COFF_DataType_BIG_OBJ;
|
||||
LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, obj, cached_path, is_big_obj, function_pad_min, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_info.symbol_count, coff_symbols, chunk_ptr_arr, master_common_block);
|
||||
LNK_SymbolList symbol_list = lnk_symbol_list_from_array(arena, symbol_arr);
|
||||
LNK_RelocList *reloc_list_arr = lnk_reloc_list_array_from_coff(arena, coff_info.machine, input->data, coff_info.section_count_no_null, coff_sect_arr, chunk_ptr_arr, symbol_arr);
|
||||
LNK_DirectiveInfo directive_info = lnk_directive_info_from_sections(arena, cached_path, cached_lib_path, coff_info.section_count_no_null, reloc_list_arr, sect_name_arr, chunk_arr);
|
||||
|
||||
// fill out obj
|
||||
obj->data = input->data;
|
||||
@@ -436,12 +455,12 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
obj->chunk_arr = chunk_ptr_arr;
|
||||
obj->symbol_list = symbol_list;
|
||||
obj->sect_reloc_list_arr = reloc_list_arr;
|
||||
obj->directive_info = lnk_init_directives(arena, cached_path, coff_info.section_count_no_null, sect_name_arr, chunk_arr);
|
||||
obj->directive_info = directive_info;
|
||||
|
||||
// parse exports
|
||||
LNK_ExportParseList export_parse = {0};
|
||||
for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_Export].first; dir != 0; dir = dir->next) {
|
||||
lnk_parse_export_direcive(arena, &obj->export_parse, dir->value_list, obj);
|
||||
lnk_parse_export_directive(arena, &obj->export_parse, dir->value_list, obj->path, obj->lib_path);
|
||||
}
|
||||
|
||||
// push /export symbols
|
||||
@@ -1029,30 +1048,108 @@ lnk_reloc_list_array_from_coff(Arena *arena, COFF_MachineType machine, String8 c
|
||||
return reloc_list_arr;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_parse_msvc_linker_directive(Arena *arena, String8 obj_path, String8 lib_path, LNK_DirectiveInfo *directive_info, String8 buffer)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
local_persist B32 init_table = 1;
|
||||
local_persist B8 is_legal[LNK_CmdSwitch_Count];
|
||||
if (init_table) {
|
||||
init_table = 0;
|
||||
is_legal[LNK_CmdSwitch_AlternateName] = 1;
|
||||
is_legal[LNK_CmdSwitch_DefaultLib] = 1;
|
||||
is_legal[LNK_CmdSwitch_DisallowLib] = 1;
|
||||
is_legal[LNK_CmdSwitch_EditAndContinue] = 1;
|
||||
is_legal[LNK_CmdSwitch_Entry] = 1;
|
||||
is_legal[LNK_CmdSwitch_Export] = 1;
|
||||
is_legal[LNK_CmdSwitch_FailIfMismatch] = 1;
|
||||
is_legal[LNK_CmdSwitch_GuardSym] = 1;
|
||||
is_legal[LNK_CmdSwitch_Include] = 1;
|
||||
is_legal[LNK_CmdSwitch_InferAsanLibs] = 1;
|
||||
is_legal[LNK_CmdSwitch_InferAsanLibsNo] = 1;
|
||||
is_legal[LNK_CmdSwitch_ManifestDependency] = 1;
|
||||
is_legal[LNK_CmdSwitch_Merge] = 1;
|
||||
is_legal[LNK_CmdSwitch_NoDefaultLib] = 1;
|
||||
is_legal[LNK_CmdSwitch_Release] = 1;
|
||||
is_legal[LNK_CmdSwitch_Section] = 1;
|
||||
is_legal[LNK_CmdSwitch_Stack] = 1;
|
||||
is_legal[LNK_CmdSwitch_SubSystem] = 1;
|
||||
is_legal[LNK_CmdSwitch_ThrowingNew] = 1;
|
||||
}
|
||||
|
||||
String8 to_parse;
|
||||
{
|
||||
local_persist const U8 bom_sig[] = { 0xEF, 0xBB, 0xBF };
|
||||
local_persist const U8 ascii_sig[] = { 0x20, 0x20, 0x20 };
|
||||
if (MemoryMatch(buffer.str, &bom_sig[0], sizeof(bom_sig))) {
|
||||
to_parse = str8_zero();
|
||||
lnk_error_with_loc(LNK_InternalError_NotImplemented, obj_path, lib_path, "TODO: support for BOM encoding");
|
||||
} else if (MemoryMatch(buffer.str, &ascii_sig[0], sizeof(ascii_sig))) {
|
||||
to_parse = str8_skip(buffer, sizeof(ascii_sig));
|
||||
} else {
|
||||
to_parse = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
String8List arg_list = lnk_arg_list_parse_windows_rules(scratch.arena, to_parse);
|
||||
LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, arg_list);
|
||||
|
||||
for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) {
|
||||
LNK_CmdSwitchType type = lnk_cmd_switch_type_from_string(opt->string);
|
||||
|
||||
if (type == LNK_CmdSwitch_Null) {
|
||||
lnk_error_with_loc(LNK_Warning_UnknownDirective, obj_path, lib_path, "unknown directive \"%S\"", opt->string);
|
||||
continue;
|
||||
}
|
||||
if (!is_legal[type]) {
|
||||
lnk_error_with_loc(LNK_Warning_IllegalDirective, obj_path, lib_path, "illegal directive \"%S\"", opt->string);
|
||||
continue;
|
||||
}
|
||||
|
||||
LNK_Directive *directive = push_array_no_zero(arena, LNK_Directive, 1);
|
||||
directive->next = 0;
|
||||
directive->id = push_str8_copy(arena, opt->string);
|
||||
directive->value_list = str8_list_copy(arena, &opt->value_strings);
|
||||
|
||||
LNK_DirectiveList *directive_list = &directive_info->v[type];
|
||||
SLLQueuePush(directive_list->first, directive_list->last, directive);
|
||||
++directive_list->count;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal LNK_DirectiveInfo
|
||||
lnk_init_directives(Arena *arena, String8 obj_path, U64 chunk_count, String8 *sect_name_arr, LNK_Chunk *chunk_arr)
|
||||
lnk_directive_info_from_sections(Arena *arena,
|
||||
String8 obj_path,
|
||||
String8 lib_path,
|
||||
U64 chunk_count,
|
||||
LNK_RelocList *reloc_list_arr,
|
||||
String8 *sect_name_arr,
|
||||
LNK_Chunk *chunk_arr)
|
||||
{
|
||||
LNK_DirectiveInfo directive_info = {0};
|
||||
for (U64 chunk_idx = 0; chunk_idx < chunk_count; chunk_idx += 1) {
|
||||
for (U64 chunk_idx = 0; chunk_idx < chunk_count; ++chunk_idx) {
|
||||
String8 sect_name = sect_name_arr[chunk_idx];
|
||||
LNK_Chunk *sect_chunk = &chunk_arr[chunk_idx];
|
||||
Assert(sect_chunk->type == LNK_Chunk_Leaf);
|
||||
|
||||
if (!str8_match(sect_name, str8_lit(".drectve"), 0)) {
|
||||
continue;
|
||||
LNK_Chunk *sect_chunk = chunk_arr + chunk_idx;
|
||||
if (str8_match(sect_name, str8_lit(".drectve"), 0)) {
|
||||
if (sect_chunk->type == LNK_Chunk_Leaf) {
|
||||
if (sect_chunk->u.leaf.size >= 3) {
|
||||
if (~sect_chunk->flags & COFF_SectionFlag_LNK_INFO) {
|
||||
lnk_error_with_loc(LNK_Warning_IllData, obj_path, lib_path, "%S missing COFF_SectionFlag_LNK_INFO", sect_name);
|
||||
}
|
||||
if (reloc_list_arr[chunk_idx].count > 0) {
|
||||
lnk_error_with_loc(LNK_Warning_DirectiveSectionWithRelocs, obj_path, lib_path, "directive section %S(%#x) has relocations", sect_name, (chunk_idx+1));
|
||||
}
|
||||
lnk_parse_msvc_linker_directive(arena, obj_path, lib_path, &directive_info, sect_chunk->u.leaf);
|
||||
} else {
|
||||
lnk_error_with_loc(LNK_Warning_IllData, obj_path, lib_path, "unable to parse %S", sect_name);
|
||||
}
|
||||
} else {
|
||||
Assert(!"linker directive section chunk must be of leaf type");
|
||||
}
|
||||
}
|
||||
if (sect_chunk->u.leaf.size < 3) {
|
||||
lnk_error(LNK_Warning_IllData, "%S: can't parse %S", obj_path, sect_name);
|
||||
continue;
|
||||
}
|
||||
if (~sect_chunk->flags & COFF_SectionFlag_LNK_INFO) {
|
||||
lnk_error(LNK_Warning_IllData, "%S: %S missing COFF_SectionFlag_LNK_INFO.", obj_path, sect_name);
|
||||
}
|
||||
|
||||
// TODO: warn if section has relocations
|
||||
|
||||
lnk_parse_directives(arena, &directive_info, sect_chunk->u.leaf, obj_path);
|
||||
int bad_vs = 0; (void)bad_vs;
|
||||
}
|
||||
return directive_info;
|
||||
}
|
||||
|
||||
+23
-2
@@ -25,6 +25,27 @@ typedef struct LNK_InputObjList
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct LNK_Directive
|
||||
{
|
||||
struct LNK_Directive *next;
|
||||
String8 id;
|
||||
String8List value_list;
|
||||
} LNK_Directive;
|
||||
|
||||
typedef struct LNK_DirectiveList
|
||||
{
|
||||
U64 count;
|
||||
LNK_Directive *first;
|
||||
LNK_Directive *last;
|
||||
} LNK_DirectiveList;
|
||||
|
||||
typedef struct LNK_DirectiveInfo
|
||||
{
|
||||
LNK_DirectiveList v[LNK_CmdSwitch_Count];
|
||||
} LNK_DirectiveInfo;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define LNK_MakeChunkInputIdx(obj_idx, sect_idx) (((U64)(obj_idx) << 32) | (U64)((sect_idx) & max_U32))
|
||||
|
||||
typedef struct LNK_Obj
|
||||
@@ -181,10 +202,10 @@ internal LNK_ChunkList * lnk_collect_obj_chunks(TP_Context *tp, TP_Arena *arena
|
||||
internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, LNK_SectionTable *st, U64 *function_pad_min, U64 input_count, LNK_InputObj **inputs);
|
||||
|
||||
internal LNK_Chunk * lnk_sect_chunk_array_from_coff(Arena *arena, U64 obj_id, String8 obj_path, String8 coff_data, U64 sect_count, COFF_SectionHeader *coff_sect_arr, String8 *sect_name_arr, String8 *sect_postfix_arr);
|
||||
internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, String8 coff_data, LNK_Obj *obj, String8 obj_path, B32 is_big_obj, U64 function_pad_min, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, U64 coff_symbol_count, void *coff_symbols, LNK_ChunkPtr *chunk_ptr_arr, LNK_Chunk *master_common_block);
|
||||
internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, String8 coff_data, LNK_Obj *obj, String8 obj_path, String8 lib_path, B32 is_big_obj, U64 function_pad_min, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, U64 coff_symbol_count, void *coff_symbols, LNK_ChunkPtr *chunk_ptr_arr, LNK_Chunk *master_common_block);
|
||||
internal LNK_RelocList lnk_reloc_list_from_coff_reloc_array(Arena *arena, COFF_MachineType machine, LNK_Chunk *chunk, LNK_SymbolArray symbol_array, COFF_Reloc *reloc_v, U64 reloc_count);
|
||||
internal LNK_RelocList * lnk_reloc_list_array_from_coff(Arena *arena, COFF_MachineType machine, String8 coff_data, U64 sect_count, COFF_SectionHeader *coff_sect_arr, LNK_ChunkPtr *chunk_ptr_arr, LNK_SymbolArray symbol_array);
|
||||
internal LNK_DirectiveInfo lnk_init_directives(Arena *arena, String8 obj_path, U64 chunk_count, String8 *sect_name_arr, LNK_Chunk *chunk_arr);
|
||||
internal LNK_DirectiveInfo lnk_directive_info_from_sections(Arena *arena, String8 obj_path, String8 lib_path, U64 chunk_count, LNK_RelocList *reloc_list_arr, String8 *sect_name_arr, LNK_Chunk *chunk_arr);
|
||||
|
||||
internal U32 lnk_obj_get_features(LNK_Obj *obj);
|
||||
internal U32 lnk_obj_get_comp_id(LNK_Obj *obj);
|
||||
|
||||
Reference in New Issue
Block a user