mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-06 22:08:41 +00:00
make import lib objs with COFF obj writer
This commit is contained in:
committed by
Ryan Fleury
parent
e580b69180
commit
3a2bb318c7
+15
-1
@@ -21,6 +21,7 @@ read_only global U8 g_coff_thin_archive_sig[8] = "!<thin>\n";
|
|||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
#define COFF_TimeStamp_Max max_U32
|
||||||
typedef U32 COFF_TimeStamp;
|
typedef U32 COFF_TimeStamp;
|
||||||
|
|
||||||
typedef U16 COFF_FileHeaderFlags;
|
typedef U16 COFF_FileHeaderFlags;
|
||||||
@@ -135,6 +136,20 @@ enum
|
|||||||
COFF_SectionFlag_MemPreload = (1 << 19),
|
COFF_SectionFlag_MemPreload = (1 << 19),
|
||||||
COFF_SectionFlag_AlignShift = 20,
|
COFF_SectionFlag_AlignShift = 20,
|
||||||
COFF_SectionFlag_AlignMask = 0xf,
|
COFF_SectionFlag_AlignMask = 0xf,
|
||||||
|
COFF_SectionFlag_Align1Bytes = (COFF_SectionAlign_1Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align2Bytes = (COFF_SectionAlign_2Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align4Bytes = (COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align8Bytes = (COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align16Bytes = (COFF_SectionAlign_16Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align32Bytes = (COFF_SectionAlign_32Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align64Bytes = (COFF_SectionAlign_64Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align128Bytes = (COFF_SectionAlign_128Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align256Bytes = (COFF_SectionAlign_256Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align512Bytes = (COFF_SectionAlign_512Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align1024Bytes = (COFF_SectionAlign_1024Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align2048Bytes = (COFF_SectionAlign_2048Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align4096Bytes = (COFF_SectionAlign_4096Bytes << COFF_SectionFlag_AlignShift),
|
||||||
|
COFF_SectionFlag_Align8192Bytes = (COFF_SectionAlign_8192Bytes << COFF_SectionFlag_AlignShift),
|
||||||
COFF_SectionFlag_LnkNRelocOvfl = (1 << 24),
|
COFF_SectionFlag_LnkNRelocOvfl = (1 << 24),
|
||||||
COFF_SectionFlag_MemDiscardable = (1 << 25),
|
COFF_SectionFlag_MemDiscardable = (1 << 25),
|
||||||
COFF_SectionFlag_MemNotCached = (1 << 26),
|
COFF_SectionFlag_MemNotCached = (1 << 26),
|
||||||
@@ -144,7 +159,6 @@ enum
|
|||||||
COFF_SectionFlag_MemRead = (1 << 30),
|
COFF_SectionFlag_MemRead = (1 << 30),
|
||||||
COFF_SectionFlag_MemWrite = (1 << 31)
|
COFF_SectionFlag_MemWrite = (1 << 31)
|
||||||
};
|
};
|
||||||
#define COFF_SectionFlags_PackAlign(f) ((f) << COFF_SectionFlag_AlignShift)
|
|
||||||
#define COFF_SectionFlags_ExtractAlign(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_AlignShift) & COFF_SectionFlag_AlignMask)
|
#define COFF_SectionFlags_ExtractAlign(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_AlignShift) & COFF_SectionFlag_AlignMask)
|
||||||
#define COFF_SectionFlags_LnkFlags ((COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift) | COFF_SectionFlag_LnkCOMDAT | COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkOther | COFF_SectionFlag_LnkRemove | COFF_SectionFlag_LnkNRelocOvfl)
|
#define COFF_SectionFlags_LnkFlags ((COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift) | COFF_SectionFlag_LnkCOMDAT | COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkOther | COFF_SectionFlag_LnkRemove | COFF_SectionFlag_LnkNRelocOvfl)
|
||||||
|
|
||||||
|
|||||||
+64
-12
@@ -17,7 +17,7 @@ coff_obj_writer_release(COFF_ObjWriter **obj_writer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal COFF_ObjSymbol *
|
internal COFF_ObjSymbol *
|
||||||
coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section, COFF_SymbolType type, COFF_SymStorageClass storage_class)
|
coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class)
|
||||||
{
|
{
|
||||||
COFF_ObjSymbolNode *n = push_array(obj_writer->arena, COFF_ObjSymbolNode, 1);
|
COFF_ObjSymbolNode *n = push_array(obj_writer->arena, COFF_ObjSymbolNode, 1);
|
||||||
SLLQueuePush(obj_writer->symbol_first, obj_writer->symbol_last, n);
|
SLLQueuePush(obj_writer->symbol_first, obj_writer->symbol_last, n);
|
||||||
@@ -26,7 +26,7 @@ coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value,
|
|||||||
COFF_ObjSymbol *s = &n->v;
|
COFF_ObjSymbol *s = &n->v;
|
||||||
s->name = name;
|
s->name = name;
|
||||||
s->value = value;
|
s->value = value;
|
||||||
s->section = section;
|
s->loc = loc;
|
||||||
s->type = type;
|
s->type = type;
|
||||||
s->storage_class = storage_class;
|
s->storage_class = storage_class;
|
||||||
s->idx = obj_writer->symbol_count-1;
|
s->idx = obj_writer->symbol_count-1;
|
||||||
@@ -35,16 +35,41 @@ coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal COFF_ObjSymbol *
|
internal COFF_ObjSymbol *
|
||||||
coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section)
|
coff_obj_writer_push_symbol_external(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section)
|
||||||
{
|
{
|
||||||
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, off, section, (COFF_SymbolType){0}, COFF_SymStorageClass_Static);
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Section;
|
||||||
|
loc.u.section = section;
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, (COFF_SymbolType){0}, COFF_SymStorageClass_External);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal COFF_ObjSymbol *
|
internal COFF_ObjSymbol *
|
||||||
coff_obj_writer_push_symbol_abs(COFF_ObjWriter *obj_writer, String8 name, COFF_SymStorageClass storage_class, U32 value)
|
coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section)
|
||||||
{
|
{
|
||||||
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, 0, (COFF_SymbolType){0}, storage_class);
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Section;
|
||||||
|
loc.u.section = section;
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, off, loc, (COFF_SymbolType){0}, COFF_SymStorageClass_Static);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal COFF_ObjSymbol *
|
||||||
|
coff_obj_writer_push_symbol_abs(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymStorageClass storage_class)
|
||||||
|
{
|
||||||
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Abs;
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, (COFF_SymbolType){0}, storage_class);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal COFF_ObjSymbol *
|
||||||
|
coff_obj_writer_push_symbol_undef(COFF_ObjWriter *obj_writer, String8 name)
|
||||||
|
{
|
||||||
|
COFF_SymbolType type = {0};
|
||||||
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Undef;
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, loc, type, COFF_SymStorageClass_External);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +78,34 @@ coff_obj_writer_push_symbol_undef_func(COFF_ObjWriter *obj_writer, String8 name)
|
|||||||
{
|
{
|
||||||
COFF_SymbolType type = {0};
|
COFF_SymbolType type = {0};
|
||||||
type.u.msb = COFF_SymDType_Func;
|
type.u.msb = COFF_SymDType_Func;
|
||||||
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, 0, type, COFF_SymStorageClass_External);
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Undef;
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, loc, type, COFF_SymStorageClass_External);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal COFF_ObjSymbol *
|
||||||
|
coff_obj_writer_push_symbol_undef_sect(COFF_ObjWriter *obj_writer, String8 name, U32 value)
|
||||||
|
{
|
||||||
|
COFF_SymbolType type = {0};
|
||||||
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Undef;
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, type, COFF_SymStorageClass_Section);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal COFF_ObjSymbol *
|
||||||
|
coff_obj_writer_push_symbol_sect(COFF_ObjWriter *obj_writer, String8 name, COFF_ObjSection *sect)
|
||||||
|
{
|
||||||
|
COFF_SymbolType type = {0};
|
||||||
|
COFF_SymbolLocation loc = {0};
|
||||||
|
loc.type = COFF_SymbolLocation_Section;
|
||||||
|
loc.u.section = sect;
|
||||||
|
|
||||||
|
// strip align flags
|
||||||
|
COFF_SectionFlags expected_flags = sect->flags & ~(COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift);
|
||||||
|
|
||||||
|
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, expected_flags, loc, type, COFF_SymStorageClass_Section);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +119,6 @@ coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_Sect
|
|||||||
COFF_ObjSection *sect = §_n->v;
|
COFF_ObjSection *sect = §_n->v;
|
||||||
sect->name = name;
|
sect->name = name;
|
||||||
sect->flags = flags;
|
sect->flags = flags;
|
||||||
sect->symbol = coff_obj_writer_push_symbol_static(obj_writer, name, 0, sect);
|
|
||||||
|
|
||||||
str8_list_push(obj_writer->arena, §->data, data);
|
str8_list_push(obj_writer->arena, §->data, data);
|
||||||
|
|
||||||
@@ -234,10 +285,11 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
|||||||
AssertAlways(s->aux_symbols.node_count <= max_U8);
|
AssertAlways(s->aux_symbols.node_count <= max_U8);
|
||||||
d->name = name;
|
d->name = name;
|
||||||
d->value = s->value;
|
d->value = s->value;
|
||||||
if (s->section == 0) {
|
switch (s->loc.type) {
|
||||||
d->section_number = COFF_Symbol_AbsSection16;
|
case COFF_SymbolLocation_Null: break;
|
||||||
} else {
|
case COFF_SymbolLocation_Section: d->section_number = safe_cast_u16(s->loc.u.section->section_number); break;
|
||||||
d->section_number = safe_cast_u16(s->section->section_number);
|
case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break;
|
||||||
|
case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break;
|
||||||
}
|
}
|
||||||
d->type = s->type;
|
d->type = s->type;
|
||||||
d->storage_class = s->storage_class;
|
d->storage_class = s->storage_class;
|
||||||
|
|||||||
@@ -1,11 +1,27 @@
|
|||||||
#ifndef COFF_OBJ_WRITER_H
|
#ifndef COFF_OBJ_WRITER_H
|
||||||
#define COFF_OBJ_WRITER_H
|
#define COFF_OBJ_WRITER_H
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COFF_SymbolLocation_Null,
|
||||||
|
COFF_SymbolLocation_Section,
|
||||||
|
COFF_SymbolLocation_Abs,
|
||||||
|
COFF_SymbolLocation_Undef
|
||||||
|
} COFF_SymbolLocationType;
|
||||||
|
|
||||||
|
typedef struct COFF_SymbolLocation
|
||||||
|
{
|
||||||
|
COFF_SymbolLocationType type;
|
||||||
|
union {
|
||||||
|
struct COFF_ObjSection *section;
|
||||||
|
} u;
|
||||||
|
} COFF_SymbolLocation;
|
||||||
|
|
||||||
typedef struct COFF_ObjSymbol
|
typedef struct COFF_ObjSymbol
|
||||||
{
|
{
|
||||||
String8 name;
|
String8 name;
|
||||||
U32 value;
|
U32 value;
|
||||||
struct COFF_ObjSection *section;
|
COFF_SymbolLocation loc;
|
||||||
COFF_SymbolType type;
|
COFF_SymbolType type;
|
||||||
COFF_SymStorageClass storage_class;
|
COFF_SymStorageClass storage_class;
|
||||||
String8List aux_symbols;
|
String8List aux_symbols;
|
||||||
@@ -36,7 +52,6 @@ typedef struct COFF_ObjSection
|
|||||||
String8 name;
|
String8 name;
|
||||||
String8List data;
|
String8List data;
|
||||||
COFF_SectionFlags flags;
|
COFF_SectionFlags flags;
|
||||||
COFF_ObjSymbol *symbol;
|
|
||||||
|
|
||||||
U64 reloc_count;
|
U64 reloc_count;
|
||||||
COFF_ObjRelocNode *reloc_first;
|
COFF_ObjRelocNode *reloc_first;
|
||||||
@@ -71,7 +86,7 @@ typedef struct COFF_ObjWriter
|
|||||||
internal COFF_ObjWriter* coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine_type);
|
internal COFF_ObjWriter* coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine_type);
|
||||||
internal void coff_obj_writer_release(COFF_ObjWriter **obj_writer);
|
internal void coff_obj_writer_release(COFF_ObjWriter **obj_writer);
|
||||||
internal COFF_ObjSection* coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data);
|
internal COFF_ObjSection* coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data);
|
||||||
internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section, COFF_SymbolType type, COFF_SymStorageClass storage_class);
|
internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class);
|
||||||
internal COFF_ObjReloc* coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol, COFF_RelocType reloc_type);
|
internal COFF_ObjReloc* coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol, COFF_RelocType reloc_type);
|
||||||
|
|
||||||
#endif // COFF_OBJ_WRITER_H
|
#endif // COFF_OBJ_WRITER_H
|
||||||
|
|||||||
+8
-27
@@ -121,6 +121,7 @@
|
|||||||
#include "lnk_reloc.h"
|
#include "lnk_reloc.h"
|
||||||
#include "lnk_symbol_table.h"
|
#include "lnk_symbol_table.h"
|
||||||
#include "lnk_section_table.h"
|
#include "lnk_section_table.h"
|
||||||
|
#include "lnk_debug_helper.h"
|
||||||
#include "lnk_obj.h"
|
#include "lnk_obj.h"
|
||||||
#include "lnk_import_table.h"
|
#include "lnk_import_table.h"
|
||||||
#include "lnk_export_table.h"
|
#include "lnk_export_table.h"
|
||||||
@@ -139,6 +140,7 @@
|
|||||||
#include "lnk_symbol_table.c"
|
#include "lnk_symbol_table.c"
|
||||||
#include "lnk_section_table.c"
|
#include "lnk_section_table.c"
|
||||||
#include "lnk_obj.c"
|
#include "lnk_obj.c"
|
||||||
|
#include "lnk_debug_helper.c"
|
||||||
#include "lnk_import_table.c"
|
#include "lnk_import_table.c"
|
||||||
#include "lnk_export_table.c"
|
#include "lnk_export_table.c"
|
||||||
#include "lnk_lib.c"
|
#include "lnk_lib.c"
|
||||||
@@ -763,27 +765,16 @@ lnk_make_linker_coff_obj(Arena *arena,
|
|||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
String8 debug_s_data = {0};
|
String8 debug_symbols = {0};
|
||||||
{
|
{
|
||||||
CV_SymbolList symbol_list = {0};
|
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||||
symbol_list.signature = CV_Signature_C13;
|
|
||||||
|
|
||||||
// S_OBJ
|
// S_OBJ
|
||||||
String8 obj_data = cv_make_obj_name(scratch.arena, obj_name, 0);
|
String8 obj_data = cv_make_obj_name(scratch.arena, obj_name, 0);
|
||||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data);
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data);
|
||||||
|
|
||||||
// S_COMPILE3
|
// S_COMPILE3
|
||||||
CV_Arch cv_arch = cv_arch_from_coff_machine(machine);
|
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||||
U64 ver_fe_major = 0;
|
|
||||||
U64 ver_fe_minor = 0;
|
|
||||||
U64 ver_fe_build = 0;
|
|
||||||
U64 ver_feqfe = 0;
|
|
||||||
U64 ver_major = 14;
|
|
||||||
U64 ver_minor = 36;
|
|
||||||
U64 ver_build = 32537;
|
|
||||||
U64 ver_qfe = 0;
|
|
||||||
String8 version_string = push_str8f(scratch.arena, "Epic Games Tools (R) RAD Linker");
|
|
||||||
String8 comp3_data = cv_make_comp3(scratch.arena, 0, CV_Language_LINK, cv_arch, ver_fe_major, ver_fe_minor, ver_fe_build, ver_feqfe, ver_major, ver_minor, ver_build, ver_qfe, version_string);
|
|
||||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||||
|
|
||||||
// S_ENVBLOCK
|
// S_ENVBLOCK
|
||||||
@@ -798,28 +789,18 @@ lnk_make_linker_coff_obj(Arena *arena,
|
|||||||
str8_list_push(scratch.arena, &env_list, cmd_line);
|
str8_list_push(scratch.arena, &env_list, cmd_line);
|
||||||
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
||||||
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
||||||
String8 env_data = cv_make_envblock(scratch.arena, env_list);
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_ENVBLOCK, cv_make_envblock(scratch.arena, env_list));
|
||||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_ENVBLOCK, env_data);
|
|
||||||
|
|
||||||
// TODO: emit S_SECTION and S_COFFGROUP
|
// TODO: emit S_SECTION and S_COFFGROUP
|
||||||
// TODO: emit S_TRAMPOLINE
|
// TODO: emit S_TRAMPOLINE
|
||||||
|
|
||||||
String8List symbol_data_list = cv_data_from_symbol_list(scratch.arena, symbol_list, CV_SymbolAlign);
|
debug_symbols = lnk_make_debug_s(scratch.arena, symbol_list);
|
||||||
|
|
||||||
CV_DebugS debug_s = {0};
|
|
||||||
|
|
||||||
String8List *symbols_list_ptr = cv_sub_section_ptr_from_debug_s(&debug_s, CV_C13SubSectionKind_Symbols);
|
|
||||||
*symbols_list_ptr = symbol_data_list;
|
|
||||||
|
|
||||||
B32 include_sig = 1;
|
|
||||||
String8List debug_s_data_list = cv_data_c13_from_debug_s(scratch.arena, &debug_s, include_sig);
|
|
||||||
debug_s_data = str8_list_join(scratch.arena, &debug_s_data_list, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String8 obj;
|
String8 obj;
|
||||||
{
|
{
|
||||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||||
coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS, debug_s_data);
|
coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||||
obj = coff_obj_writer_serialize(arena, obj_writer);
|
obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||||
coff_obj_writer_release(&obj_writer);
|
coff_obj_writer_release(&obj_writer);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -89,8 +89,8 @@
|
|||||||
#define LNK_IDATA_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
#define LNK_IDATA_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
||||||
#define LNK_DEBUG_DIR_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
#define LNK_DEBUG_DIR_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
||||||
#define LNK_RSRC_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
#define LNK_RSRC_SECTION_FLAGS LNK_DATA_SECTION_FLAGS
|
||||||
#define LNK_RSRC1_SECTION_FLAGS (LNK_DATA_SECTION_FLAGS | COFF_SectionFlags_PackAlign(COFF_SectionAlign_4Bytes))
|
#define LNK_RSRC1_SECTION_FLAGS (LNK_DATA_SECTION_FLAGS | COFF_SectionFlag_Align4Bytes)
|
||||||
#define LNK_RSRC2_SECTION_FLAGS (LNK_DATA_SECTION_FLAGS | COFF_SectionFlags_PackAlign(COFF_SectionAlign_4Bytes))
|
#define LNK_RSRC2_SECTION_FLAGS (LNK_DATA_SECTION_FLAGS | COFF_SectionFlag_Align4Bytes)
|
||||||
#define LNK_XDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
#define LNK_XDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
||||||
#define LNK_PDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
#define LNK_PDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
||||||
#define LNK_EDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
#define LNK_EDATA_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS
|
||||||
|
|||||||
+92
-301
@@ -536,352 +536,143 @@ lnk_build_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp,
|
|||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal String8List
|
internal String8
|
||||||
lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType machine)
|
lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
Assert(machine == COFF_MachineType_X64);
|
Assert(machine == COFF_MachineType_X64);
|
||||||
Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy));
|
Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy));
|
||||||
|
|
||||||
String8List list = {0};
|
String8 dll_name_no_ext = str8_chop_last_dot(dll_name);
|
||||||
|
|
||||||
COFF_FileHeader *file_header = push_array(arena, COFF_FileHeader, 1);
|
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||||
file_header->machine = machine;
|
|
||||||
str8_list_push(arena, &list, str8_struct(file_header));
|
|
||||||
|
|
||||||
file_header->section_count = 2;
|
String8 debug_symbols;
|
||||||
COFF_SectionHeader *coff_sect_header_array = push_array(arena, COFF_SectionHeader, file_header->section_count);
|
|
||||||
str8_list_push(arena, &list, str8_array(coff_sect_header_array, file_header->section_count));
|
|
||||||
|
|
||||||
PE_ImportEntry *import_entry = push_array(arena, PE_ImportEntry, 1);
|
|
||||||
U64 import_entry_off = list.total_size;
|
|
||||||
str8_list_push(arena, &list, str8_struct(import_entry));
|
|
||||||
|
|
||||||
String8 dll_name_cstr = push_cstr(arena, dll_name);
|
|
||||||
U64 dll_name_off = list.total_size;
|
|
||||||
str8_list_push(arena, &list, dll_name_cstr);
|
|
||||||
|
|
||||||
U32 import_entry_reloc_count = 3;
|
|
||||||
COFF_Reloc *import_entry_reloc_array = push_array(arena, COFF_Reloc, import_entry_reloc_count);
|
|
||||||
U64 import_entry_reloc_off = list.total_size;
|
|
||||||
str8_list_push(arena, &list, str8_array(import_entry_reloc_array, import_entry_reloc_count));
|
|
||||||
|
|
||||||
file_header->symbol_count = 7;
|
|
||||||
COFF_Symbol16 *symbol_array = push_array(arena, COFF_Symbol16, file_header->symbol_count);
|
|
||||||
file_header->symbol_table_foff = safe_cast_u32(list.total_size);
|
|
||||||
str8_list_push(arena, &list, str8_array(symbol_array, file_header->symbol_count));
|
|
||||||
|
|
||||||
U64 string_table_base = list.total_size;
|
|
||||||
U32 *string_table_size_ptr = push_array(arena, U32, 1);
|
|
||||||
str8_list_push(arena, &list, str8_struct(string_table_size_ptr));
|
|
||||||
|
|
||||||
// PE_ImportEntry
|
|
||||||
{
|
{
|
||||||
COFF_SectionHeader *sect = &coff_sect_header_array[0];
|
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||||
sect->name[0] = '.';
|
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||||
sect->name[1] = 'i';
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||||
sect->name[2] = 'd';
|
debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||||
sect->name[3] = 'a';
|
|
||||||
sect->name[4] = 't';
|
|
||||||
sect->name[5] = 'a';
|
|
||||||
sect->name[6] = '$';
|
|
||||||
sect->name[7] = '2';
|
|
||||||
sect->fsize = sizeof(PE_ImportEntry);
|
|
||||||
sect->foff = import_entry_off;
|
|
||||||
sect->reloc_count = import_entry_reloc_count;
|
|
||||||
sect->relocs_foff = import_entry_reloc_off;
|
|
||||||
sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
COFF_Reloc *lookup_table_voff_reloc = &import_entry_reloc_array[0];
|
|
||||||
lookup_table_voff_reloc->apply_off = OffsetOf(PE_ImportEntry, lookup_table_voff);
|
|
||||||
lookup_table_voff_reloc->isymbol = 3;
|
|
||||||
lookup_table_voff_reloc->type = COFF_Reloc_X64_Addr32Nb;
|
|
||||||
|
|
||||||
COFF_Reloc *name_voff_reloc = &import_entry_reloc_array[1];
|
|
||||||
name_voff_reloc->apply_off = OffsetOf(PE_ImportEntry, name_voff);
|
|
||||||
name_voff_reloc->isymbol = 2;
|
|
||||||
name_voff_reloc->type = COFF_Reloc_X64_Addr32Nb;
|
|
||||||
|
|
||||||
COFF_Reloc *import_addr_table_voff = &import_entry_reloc_array[2];
|
|
||||||
import_addr_table_voff->apply_off = OffsetOf(PE_ImportEntry, import_addr_table_voff);
|
|
||||||
import_addr_table_voff->isymbol = 4;
|
|
||||||
import_addr_table_voff->type = COFF_Reloc_X64_Addr32Nb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dll name
|
String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name);
|
||||||
{
|
COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||||
COFF_SectionHeader *sect = &coff_sect_header_array[1];
|
COFF_ObjSection *idata2 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), LNK_DATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_zero());
|
||||||
sect->name[0] = '.';
|
COFF_ObjSection *idata6 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), LNK_DATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr);
|
||||||
sect->name[1] = 'i';
|
|
||||||
sect->name[2] = 'd';
|
|
||||||
sect->name[3] = 'a';
|
|
||||||
sect->name[4] = 't';
|
|
||||||
sect->name[5] = 'a';
|
|
||||||
sect->name[6] = '$';
|
|
||||||
sect->name[7] = '6';
|
|
||||||
sect->fsize = dll_name_cstr.size;
|
|
||||||
sect->foff = dll_name_off;
|
|
||||||
sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_2Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
// import descriptor
|
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@comp.id"), 0x1018175, COFF_SymStorageClass_Static);
|
||||||
{
|
{
|
||||||
String8 dll_name_no_ext = str8_substr(dll_name, r1u64(0, dll_name.size - 4));
|
|
||||||
String8 symbol_name = push_str8f(arena, "__IMPORT_DESCRIPTOR_%S", dll_name_no_ext);
|
String8 symbol_name = push_str8f(arena, "__IMPORT_DESCRIPTOR_%S", dll_name_no_ext);
|
||||||
|
coff_obj_writer_push_symbol_external(obj_writer, symbol_name, 0, idata2);
|
||||||
U64 symbol_name_off = (list.total_size - string_table_base);
|
|
||||||
str8_list_push(arena, &list, push_cstr(arena, symbol_name));
|
|
||||||
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[0];
|
|
||||||
symbol->name.long_name.zeroes = 0;
|
|
||||||
symbol->name.long_name.string_table_offset = symbol_name_off;
|
|
||||||
symbol->section_number = 1;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_External;
|
|
||||||
}
|
}
|
||||||
|
COFF_ObjSymbol *idata2_symbol = coff_obj_writer_push_symbol_sect(obj_writer, idata2->name, idata2);
|
||||||
// .idata$2
|
COFF_ObjSymbol *idata6_symbol = coff_obj_writer_push_symbol_static(obj_writer, idata6->name, 0, idata6);
|
||||||
|
COFF_ObjSymbol *idata4_symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".idata$4"), COFF_SectionFlag_MemWrite|COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData);
|
||||||
|
COFF_ObjSymbol *idata5_symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".idata$5"), COFF_SectionFlag_MemWrite|COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData);
|
||||||
|
coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__NULL_IMPORT_DESCRIPTOR"));
|
||||||
{
|
{
|
||||||
COFF_Symbol16 *symbol = &symbol_array[1];
|
|
||||||
symbol->name.short_name[0] = '.';
|
|
||||||
symbol->name.short_name[1] = 'i';
|
|
||||||
symbol->name.short_name[2] = 'd';
|
|
||||||
symbol->name.short_name[3] = 'a';
|
|
||||||
symbol->name.short_name[4] = 't';
|
|
||||||
symbol->name.short_name[5] = 'a';
|
|
||||||
symbol->name.short_name[6] = '$';
|
|
||||||
symbol->name.short_name[7] = '2';
|
|
||||||
symbol->section_number = 1;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_Section;
|
|
||||||
}
|
|
||||||
|
|
||||||
// .idata$6
|
|
||||||
{
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[2];
|
|
||||||
symbol->name.short_name[0] = '.';
|
|
||||||
symbol->name.short_name[1] = 'i';
|
|
||||||
symbol->name.short_name[2] = 'd';
|
|
||||||
symbol->name.short_name[3] = 'a';
|
|
||||||
symbol->name.short_name[4] = 't';
|
|
||||||
symbol->name.short_name[5] = 'a';
|
|
||||||
symbol->name.short_name[6] = '$';
|
|
||||||
symbol->name.short_name[7] = '6';
|
|
||||||
symbol->section_number = 2;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_Static;
|
|
||||||
}
|
|
||||||
|
|
||||||
// .idata$4
|
|
||||||
{
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[3];
|
|
||||||
symbol->name.short_name[0] = '.';
|
|
||||||
symbol->name.short_name[1] = 'i';
|
|
||||||
symbol->name.short_name[2] = 'd';
|
|
||||||
symbol->name.short_name[3] = 'a';
|
|
||||||
symbol->name.short_name[4] = 't';
|
|
||||||
symbol->name.short_name[5] = 'a';
|
|
||||||
symbol->name.short_name[6] = '$';
|
|
||||||
symbol->name.short_name[7] = '4';
|
|
||||||
symbol->section_number = COFF_Symbol_UndefinedSection;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_Section;
|
|
||||||
}
|
|
||||||
|
|
||||||
// .idata$5
|
|
||||||
{
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[4];
|
|
||||||
symbol->name.short_name[0] = '.';
|
|
||||||
symbol->name.short_name[1] = 'i';
|
|
||||||
symbol->name.short_name[2] = 'd';
|
|
||||||
symbol->name.short_name[3] = 'a';
|
|
||||||
symbol->name.short_name[4] = 't';
|
|
||||||
symbol->name.short_name[5] = 'a';
|
|
||||||
symbol->name.short_name[6] = '$';
|
|
||||||
symbol->name.short_name[7] = '5';
|
|
||||||
symbol->section_number = COFF_Symbol_UndefinedSection;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_Section;
|
|
||||||
}
|
|
||||||
|
|
||||||
// __NULL_IMPORT_DESCRIPTOR
|
|
||||||
{
|
|
||||||
U64 symbol_name_off = (list.total_size - string_table_base);
|
|
||||||
str8_list_push(arena, &list, push_cstr(arena, str8_lit("__NULL_IMPORT_DESCRIPTOR")));
|
|
||||||
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[5];
|
|
||||||
symbol->name.long_name.zeroes = 0;
|
|
||||||
symbol->name.long_name.string_table_offset = symbol_name_off;
|
|
||||||
symbol->section_number = COFF_Symbol_UndefinedSection;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_External;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NULL_THUNK_DATA
|
|
||||||
{
|
|
||||||
String8 dll_name_no_ext = str8_substr(dll_name, r1u64(0, dll_name.size - 4));
|
|
||||||
String8 symbol_name = push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name_no_ext);
|
String8 symbol_name = push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name_no_ext);
|
||||||
|
coff_obj_writer_push_symbol_undef(obj_writer, symbol_name);
|
||||||
U64 symbol_name_off = (list.total_size - string_table_base);
|
|
||||||
str8_list_push(arena, &list, push_cstr(arena, symbol_name));
|
|
||||||
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[6];
|
|
||||||
symbol->name.long_name.zeroes = 0;
|
|
||||||
symbol->name.long_name.string_table_offset = symbol_name_off;
|
|
||||||
symbol->section_number = COFF_Symbol_UndefinedSection;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_External;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update string table size
|
{
|
||||||
*string_table_size_ptr = (list.total_size - string_table_base);
|
PE_ImportEntry *import_entry = push_array(obj_writer->arena, PE_ImportEntry, 1);
|
||||||
|
str8_list_push(obj_writer->arena, &idata2->data, str8_struct(import_entry));
|
||||||
|
coff_obj_writer_section_push_reloc(obj_writer, idata2, OffsetOf(PE_ImportEntry, name_voff), idata6_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||||
|
coff_obj_writer_section_push_reloc(obj_writer, idata2, OffsetOf(PE_ImportEntry, lookup_table_voff), idata4_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||||
|
coff_obj_writer_section_push_reloc(obj_writer, idata2, OffsetOf(PE_ImportEntry, import_addr_table_voff), idata5_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||||
|
|
||||||
|
coff_obj_writer_release(&obj_writer);
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
return list;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal String8List
|
internal String8
|
||||||
lnk_build_null_import_descriptor_obj(Arena *arena, COFF_MachineType machine)
|
lnk_build_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
String8List list = {0};
|
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||||
|
|
||||||
COFF_FileHeader *coff_header = push_array(arena, COFF_FileHeader, 1);
|
|
||||||
coff_header->machine = machine;
|
|
||||||
str8_list_push(arena, &list, str8_struct(coff_header));
|
|
||||||
|
|
||||||
coff_header->section_count = 1;
|
|
||||||
COFF_SectionHeader *coff_sect_header_array = push_array(arena, COFF_SectionHeader, coff_header->section_count);
|
|
||||||
str8_list_push(arena, &list, str8_array(coff_sect_header_array, coff_header->section_count));
|
|
||||||
|
|
||||||
U64 null_import_data_size = 20;
|
|
||||||
U8 *null_import_data = push_array(arena, U8, null_import_data_size);
|
|
||||||
U64 null_import_data_off = list.total_size;
|
|
||||||
str8_list_push(arena, &list, str8(null_import_data, null_import_data_size));
|
|
||||||
|
|
||||||
coff_header->symbol_count = 1;
|
|
||||||
COFF_Symbol16 *symbol_array = push_array(arena, COFF_Symbol16, coff_header->symbol_count);
|
|
||||||
coff_header->symbol_table_foff = safe_cast_u32(list.total_size);
|
|
||||||
str8_list_push(arena, &list, str8_array(symbol_array, coff_header->symbol_count));
|
|
||||||
|
|
||||||
U64 string_table_base = list.total_size;
|
|
||||||
U32 *string_table_size_ptr = push_array(arena, U32, 1);
|
|
||||||
str8_list_push(arena, &list, str8_struct(string_table_size_ptr));
|
|
||||||
|
|
||||||
|
String8 debug_symbols;
|
||||||
{
|
{
|
||||||
COFF_SectionHeader *sect = &coff_sect_header_array[0];
|
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||||
sect->name[0] = '.';
|
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||||
sect->name[1] = 'i';
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||||
sect->name[2] = 'd';
|
debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||||
sect->name[3] = 'a';
|
|
||||||
sect->name[4] = 't';
|
|
||||||
sect->name[5] = 'a';
|
|
||||||
sect->name[6] = '$';
|
|
||||||
sect->name[7] = '3';
|
|
||||||
sect->fsize = null_import_data_size;
|
|
||||||
sect->foff = null_import_data_off;
|
|
||||||
sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
PE_ImportEntry *import_desc = push_array(obj_writer->arena, PE_ImportEntry, 1);
|
||||||
U64 symbol_name_off = list.total_size - string_table_base;
|
COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||||
str8_list_push(arena, &list, push_cstr(arena, str8_lit("__NULL_IMPORT_DESCRIPTOR")));
|
COFF_ObjSection *idata3 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$3"), LNK_DATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(import_desc));
|
||||||
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[0];
|
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@comp.id"), 0x01018175, COFF_SymStorageClass_Static);
|
||||||
symbol->name.long_name.zeroes = 0;
|
coff_obj_writer_push_symbol_external(obj_writer, str8_lit("__NULL_IMPORT_DESCRIPTOR"), 0, idata3);
|
||||||
symbol->name.long_name.string_table_offset = symbol_name_off;
|
|
||||||
symbol->section_number = 1;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_External;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update string table size
|
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||||
*string_table_size_ptr = (list.total_size - string_table_base);
|
|
||||||
|
|
||||||
|
coff_obj_writer_release(&obj_writer);
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
return list;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal String8List
|
internal String8
|
||||||
lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_MachineType machine)
|
lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy));
|
Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy));
|
||||||
|
|
||||||
String8List list = {0};
|
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||||
|
|
||||||
COFF_FileHeader *coff_header = push_array(arena, COFF_FileHeader, 1);
|
|
||||||
coff_header->machine = machine;
|
|
||||||
str8_list_push(arena, &list, str8_struct(coff_header));
|
|
||||||
|
|
||||||
coff_header->section_count = 2;
|
|
||||||
COFF_SectionHeader *coff_sect_header_array = push_array(arena, COFF_SectionHeader, coff_header->section_count);
|
|
||||||
str8_list_push(arena, &list, str8_array(coff_sect_header_array, coff_header->section_count));
|
|
||||||
|
|
||||||
U64 lookup_entry_data_size = 8;
|
|
||||||
U8 *lookup_entry_data = push_array(arena, U8, lookup_entry_data_size);
|
|
||||||
U64 lookup_entry_data_off = list.total_size;
|
|
||||||
str8_list_push(arena, &list, str8(lookup_entry_data, lookup_entry_data_size));
|
|
||||||
|
|
||||||
U64 null_thunk_data_size = 8;
|
|
||||||
U8 *null_thunk_data = push_array(arena, U8, null_thunk_data_size);
|
|
||||||
U64 null_thunk_data_off = list.total_size;
|
|
||||||
str8_list_push(arena, &list, str8(null_thunk_data, null_thunk_data_size));
|
|
||||||
|
|
||||||
coff_header->symbol_count = 1;
|
|
||||||
COFF_Symbol16 *symbol_array = push_array(arena, COFF_Symbol16, coff_header->symbol_count);
|
|
||||||
coff_header->symbol_table_foff = safe_cast_u32(list.total_size);
|
|
||||||
str8_list_push(arena, &list, str8_array(symbol_array, coff_header->symbol_count));
|
|
||||||
|
|
||||||
U64 string_table_base = list.total_size;
|
|
||||||
U32 *string_table_size_ptr = push_array(arena, U32, 1);
|
|
||||||
str8_list_push(arena, &list, str8_struct(string_table_size_ptr));
|
|
||||||
|
|
||||||
|
String8 debug_symbols;
|
||||||
{
|
{
|
||||||
COFF_SectionHeader *sect = &coff_sect_header_array[0];
|
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||||
sect->name[0] = '.';
|
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||||
sect->name[1] = 'i';
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||||
sect->name[2] = 'd';
|
debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||||
sect->name[3] = 'a';
|
|
||||||
sect->name[4] = 't';
|
|
||||||
sect->name[5] = 'a';
|
|
||||||
sect->name[6] = '$';
|
|
||||||
sect->name[7] = '5';
|
|
||||||
sect->fsize = lookup_entry_data_size;
|
|
||||||
sect->foff = lookup_entry_data_off;
|
|
||||||
sect->flags = COFF_SectionFlag_CntInitializedData | (COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift)|(COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||||
COFF_SectionHeader *sect = &coff_sect_header_array[1];
|
COFF_ObjSection *idata4 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite, str8_zero());
|
||||||
sect->name[0] = '.';
|
COFF_ObjSection *idata5 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite, str8_zero());
|
||||||
sect->name[1] = 'i';
|
|
||||||
sect->name[2] = 'd';
|
|
||||||
sect->name[3] = 'a';
|
|
||||||
sect->name[4] = 't';
|
|
||||||
sect->name[5] = 'a';
|
|
||||||
sect->name[6] = '$';
|
|
||||||
sect->name[7] = '4';
|
|
||||||
sect->fsize = null_thunk_data_size;
|
|
||||||
sect->foff = null_thunk_data_off;
|
|
||||||
sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
U64 import_size = coff_word_size_from_machine(machine);
|
||||||
|
|
||||||
|
U8 *null_thunk = push_array(obj_writer->arena, U8, import_size);
|
||||||
|
U8 *null_lookup = push_array(obj_writer->arena, U8, import_size);
|
||||||
|
|
||||||
|
str8_list_push(obj_writer->arena, &idata5->data, str8_array(null_thunk, import_size));
|
||||||
|
str8_list_push(obj_writer->arena, &idata4->data, str8_array(null_lookup, import_size));
|
||||||
|
|
||||||
|
idata4->flags |= coff_section_flag_from_align_size(import_size);
|
||||||
|
idata5->flags |= coff_section_flag_from_align_size(import_size);
|
||||||
|
|
||||||
|
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@comp.id"), 0x1018175, COFF_SymStorageClass_Static);
|
||||||
{
|
{
|
||||||
String8 dll_name_no_ext = str8_substr(dll_name, r1u64(0, dll_name.size - 4));
|
String8 dll_name_no_ext = str8_chop_last_dot(dll_name);
|
||||||
String8 symbol_name = push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name_no_ext);
|
String8 symbol_name = push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name_no_ext);
|
||||||
|
coff_obj_writer_push_symbol_external(obj_writer, symbol_name, 0, idata5);
|
||||||
U64 symbol_name_off = list.total_size - string_table_base;
|
|
||||||
str8_list_push(arena, &list, push_cstr(arena, symbol_name));
|
|
||||||
|
|
||||||
COFF_Symbol16 *symbol = &symbol_array[0];
|
|
||||||
symbol->name.long_name.zeroes = 0;
|
|
||||||
symbol->name.long_name.string_table_offset = symbol_name_off;
|
|
||||||
symbol->section_number = 1;
|
|
||||||
symbol->storage_class = COFF_SymStorageClass_External;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update string table size
|
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||||
*string_table_size_ptr = (list.total_size - string_table_base);
|
|
||||||
|
|
||||||
|
coff_obj_writer_release(&obj_writer);
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
return list;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
@@ -924,16 +715,16 @@ lnk_build_import_lib(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine,
|
|||||||
|
|
||||||
// These objects appear in first three members of any lib that linker produces with /dll.
|
// 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.
|
// Objects are used by MSVC linker to build import table.
|
||||||
String8List import_obj_array[3];
|
String8 import_obj_array[3];
|
||||||
import_obj_array[0] = lnk_build_import_entry_obj(scratch.arena, dll_name, machine);
|
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, 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, machine);
|
import_obj_array[2] = lnk_build_null_thunk_data_obj(scratch.arena, dll_name, time_stamp, machine);
|
||||||
|
|
||||||
// build input list
|
// build input list
|
||||||
LNK_InputObjList input_obj_list = {0};
|
LNK_InputObjList input_obj_list = {0};
|
||||||
for (U64 i = 0; i < ArrayCount(import_obj_array); ++i) {
|
for (U64 i = 0; i < ArrayCount(import_obj_array); ++i) {
|
||||||
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
||||||
input->data = str8_list_join(scratch.arena, &import_obj_array[i], 0);
|
input->data = import_obj_array[i];
|
||||||
input->path = dll_name;
|
input->path = dll_name;
|
||||||
input->lib_path = lib_name;
|
input->lib_path = lib_name;
|
||||||
}
|
}
|
||||||
@@ -944,8 +735,8 @@ lnk_build_import_lib(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine,
|
|||||||
lnk_obj_list_push_parallel(tp, arena, &obj_list, sectab, 0, machine, input_obj_list.count, inputs);
|
lnk_obj_list_push_parallel(tp, arena, &obj_list, sectab, 0, machine, input_obj_list.count, inputs);
|
||||||
|
|
||||||
LNK_LibBuild import_lib = lnk_build_lib(scratch.arena, machine, time_stamp, dll_name, obj_list, exptab);
|
LNK_LibBuild import_lib = lnk_build_lib(scratch.arena, machine, time_stamp, dll_name, obj_list, exptab);
|
||||||
B32 emit_second_member = 0; // MSVC linker refuses to link with lib that has the second member.
|
B32 emit_second_member = 1;
|
||||||
String8List coff_archive_data = lnk_coff_archive_from_lib_build(arena->v[0], &import_lib, emit_second_member, time_stamp, /* -rw-r--r-- */ 644);
|
String8List coff_archive_data = lnk_coff_archive_from_lib_build(arena->v[0], &import_lib, emit_second_member, COFF_TimeStamp_Max, 0);
|
||||||
|
|
||||||
// cleanup memory
|
// cleanup memory
|
||||||
lnk_section_table_release(§ab);
|
lnk_section_table_release(§ab);
|
||||||
|
|||||||
@@ -128,9 +128,9 @@ internal String8List lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBu
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
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 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 String8List lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType machine);
|
internal String8 lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||||
internal String8List lnk_build_null_import_descriptor_obj(Arena *arena, COFF_MachineType machine);
|
internal String8 lnk_build_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||||
internal String8List lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_MachineType machine);
|
internal String8 lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||||
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 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);
|
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);
|
||||||
|
|
||||||
|
|||||||
+23
-13
@@ -751,12 +751,17 @@ lnk_symbol_array_from_coff(Arena *arena,
|
|||||||
if (symbol.section_number == 0 || symbol.section_number > sect_count) {
|
if (symbol.section_number == 0 || symbol.section_number > sect_count) {
|
||||||
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "out ouf bounds section index in symbol \"%S (%u)\"", symbol.name, symbol.section_number);
|
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "out ouf bounds section index in symbol \"%S (%u)\"", symbol.name, symbol.section_number);
|
||||||
}
|
}
|
||||||
if (symbol.value > section_table[symbol.section_number-1].fsize) {
|
|
||||||
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "out of bounds section offset in symbol \"%S (%u)\"", symbol.name, symbol.value);
|
U32 section_offset = 0;
|
||||||
|
if (symbol.storage_class == COFF_SymStorageClass_External || symbol.storage_class == COFF_SymStorageClass_Static) {
|
||||||
|
section_offset = symbol.value;
|
||||||
|
}
|
||||||
|
if (section_offset > section_table[symbol.section_number-1].fsize) {
|
||||||
|
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "out of bounds section offset in symbol \"%S (%u)\"", symbol.name, section_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
LNK_Chunk *chunk = chunk_table[symbol.section_number-1];
|
LNK_Chunk *chunk = chunk_table[symbol.section_number-1];
|
||||||
if (symbol.value > 0) {
|
if (section_offset > 0) {
|
||||||
// convert leaf to list
|
// convert leaf to list
|
||||||
//
|
//
|
||||||
// there is no way to know up front how many splits we have,
|
// there is no way to know up front how many splits we have,
|
||||||
@@ -796,7 +801,7 @@ lnk_symbol_array_from_coff(Arena *arena,
|
|||||||
LNK_ChunkNode *current = chunk->u.list->last;
|
LNK_ChunkNode *current = chunk->u.list->last;
|
||||||
for (LNK_ChunkNode *c = chunk->u.list->first; c != 0; c = c->next) {
|
for (LNK_ChunkNode *c = chunk->u.list->first; c != 0; c = c->next) {
|
||||||
Assert(c->data->type == LNK_Chunk_Leaf);
|
Assert(c->data->type == LNK_Chunk_Leaf);
|
||||||
if (offset_cursor + c->data->u.leaf.size >= symbol.value) {
|
if (offset_cursor + c->data->u.leaf.size >= section_offset) {
|
||||||
current = c;
|
current = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -804,9 +809,9 @@ lnk_symbol_array_from_coff(Arena *arena,
|
|||||||
}
|
}
|
||||||
Assert(current->data->type == LNK_Chunk_Leaf);
|
Assert(current->data->type == LNK_Chunk_Leaf);
|
||||||
|
|
||||||
if (offset_cursor < symbol.value) {
|
if (offset_cursor < section_offset) {
|
||||||
// bifurcate chunk at symbol offset
|
// bifurcate chunk at symbol offset
|
||||||
U64 split_pos = symbol.value - offset_cursor;
|
U64 split_pos = section_offset - offset_cursor;
|
||||||
Rng1U64 left_data_range = rng_1u64(0, split_pos);
|
Rng1U64 left_data_range = rng_1u64(0, split_pos);
|
||||||
Rng1U64 right_data_range = rng_1u64(left_data_range.max, current->data->u.leaf.size);
|
Rng1U64 right_data_range = rng_1u64(left_data_range.max, current->data->u.leaf.size);
|
||||||
String8 left_data = str8_substr(current->data->u.leaf, left_data_range);
|
String8 left_data = str8_substr(current->data->u.leaf, left_data_range);
|
||||||
@@ -869,10 +874,16 @@ lnk_symbol_array_from_coff(Arena *arena,
|
|||||||
if (parsed_symbol.section_number == 0 || parsed_symbol.section_number > sect_count) {
|
if (parsed_symbol.section_number == 0 || parsed_symbol.section_number > sect_count) {
|
||||||
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "symbol %S (No. %llx) has out ouf bounds section index %x", parsed_symbol.name, symbol_idx, parsed_symbol.section_number);
|
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "symbol %S (No. %llx) has out ouf bounds section index %x", parsed_symbol.name, symbol_idx, parsed_symbol.section_number);
|
||||||
}
|
}
|
||||||
if (parsed_symbol.value > section_table[parsed_symbol.section_number-1].fsize) {
|
|
||||||
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "symbol %S (No. %llx) has out of bounds section offset %x into section %x", parsed_symbol.name, symbol_idx, parsed_symbol.value, parsed_symbol.section_number);
|
U32 section_offset = 0;
|
||||||
|
if (parsed_symbol.storage_class == COFF_SymStorageClass_External ||
|
||||||
|
parsed_symbol.storage_class == COFF_SymStorageClass_Static) {
|
||||||
|
section_offset = parsed_symbol.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (section_offset > section_table[parsed_symbol.section_number-1].fsize) {
|
||||||
|
lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "symbol %S (No. %llx) has out of bounds section offset %x into section %x", parsed_symbol.name, symbol_idx, section_offset, parsed_symbol.section_number);
|
||||||
|
}
|
||||||
|
|
||||||
LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Static;
|
LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Static;
|
||||||
if (parsed_symbol.storage_class == COFF_SymStorageClass_External) {
|
if (parsed_symbol.storage_class == COFF_SymStorageClass_External) {
|
||||||
@@ -885,7 +896,6 @@ lnk_symbol_array_from_coff(Arena *arena,
|
|||||||
|
|
||||||
|
|
||||||
LNK_Chunk *chunk = chunk_table[parsed_symbol.section_number-1];
|
LNK_Chunk *chunk = chunk_table[parsed_symbol.section_number-1];
|
||||||
U64 offset = parsed_symbol.value;
|
|
||||||
COFF_ComdatSelectType selection = COFF_ComdatSelect_Any;
|
COFF_ComdatSelectType selection = COFF_ComdatSelect_Any;
|
||||||
U64 check_sum = 0;
|
U64 check_sum = 0;
|
||||||
|
|
||||||
@@ -926,19 +936,19 @@ lnk_symbol_array_from_coff(Arena *arena,
|
|||||||
LNK_Chunk *closest_chunk = chunk->u.list->last->data;
|
LNK_Chunk *closest_chunk = chunk->u.list->last->data;
|
||||||
U64 offset_cursor = 0;
|
U64 offset_cursor = 0;
|
||||||
for (LNK_ChunkNode *c = chunk->u.list->first; c != 0; c = c->next) {
|
for (LNK_ChunkNode *c = chunk->u.list->first; c != 0; c = c->next) {
|
||||||
if (offset_cursor + c->data->u.leaf.size > offset) {
|
if (offset_cursor + c->data->u.leaf.size > section_offset) {
|
||||||
closest_chunk = c->data;
|
closest_chunk = c->data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset_cursor += c->data->u.leaf.size;
|
offset_cursor += c->data->u.leaf.size;
|
||||||
}
|
}
|
||||||
Assert(offset >= offset_cursor);
|
Assert(section_offset >= offset_cursor);
|
||||||
offset -= offset_cursor;
|
section_offset -= offset_cursor;
|
||||||
chunk = closest_chunk;
|
chunk = closest_chunk;
|
||||||
}
|
}
|
||||||
Assert(chunk->type == LNK_Chunk_Leaf);
|
Assert(chunk->type == LNK_Chunk_Leaf);
|
||||||
|
|
||||||
lnk_init_defined_symbol_chunk(&symbol_array.v[symbol_idx], parsed_symbol.name, visibility, flags, chunk, offset, selection, check_sum);
|
lnk_init_defined_symbol_chunk(&symbol_array.v[symbol_idx], parsed_symbol.name, visibility, flags, chunk, section_offset, selection, check_sum);
|
||||||
symbol_array.v[symbol_idx].obj = obj;
|
symbol_array.v[symbol_idx].obj = obj;
|
||||||
} break;
|
} break;
|
||||||
case COFF_SymbolValueInterp_Weak: {
|
case COFF_SymbolValueInterp_Weak: {
|
||||||
|
|||||||
Reference in New Issue
Block a user