Skip to content

Commit 034c7a5

Browse files
author
Pascal Beyer
committed
Share line information code between obj and pdb and use arenas for the module symbol stream.
1 parent 46ded85 commit 034c7a5

File tree

2 files changed

+257
-290
lines changed

2 files changed

+257
-290
lines changed

src/coff_writer.c

Lines changed: 116 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,6 +2968,9 @@ func void print_coff(struct string output_file_path, struct memory_arena *arena,
29682968
}
29692969
}
29702970

2971+
#undef begin_id_record
2972+
#undef end_id_record
2973+
29712974
ipi_stream_header->byte_count_of_type_record_data_following_the_header = (u32)(arena_current(&ipi_stream) - (u8 *)(ipi_stream_header + 1));
29722975
ipi_stream_header->one_past_last_type_index = id_index_at;
29732976

@@ -3027,211 +3030,155 @@ func void print_coff(struct string output_file_path, struct memory_arena *arena,
30273030
stream_emit_struct(context, ipi_stream.base, arena_current(&ipi_stream) - ipi_stream.base);
30283031
}
30293032

3030-
3033+
//
3034+
// We for now just have a single module stream.
3035+
// I don't really see a reason to have multiple.
3036+
// And we don't have to duplicate things like file tables if we only have one.
3037+
//
30313038

30323039
u32 module_stream_symbol_size;
30333040
u32 module_stream_line_info_size;
30343041

3035-
begin_counter(timing, module_stream);
3036-
// stream > 12: Module streams
3037-
{ // :module_streams
3038-
set_current_stream(context, STREAM_module_zero);
3039-
// module layout:
3040-
// u32 signature; always 4
3041-
// u8 symbols[symbol_byte_size - 4];
3042-
// u8 line_information[line_info_byte_size]
3043-
// u32 global_refs_byte_size;
3044-
// u8 global_refs[global_refs_byte_size]
3042+
struct string module_object_name_full_path = push_format_string(scratch, "%.*s.obj", root_file_name.size, root_file_name.data);
3043+
replace_characters(module_object_name_full_path, "/", '\\');
3044+
3045+
struct memory_arena module_stream = create_memory_arena(giga_bytes(4), 2.0f, 0);
3046+
3047+
{ // Module streams :module_streams
3048+
//
3049+
// Module stream layout:
3050+
//
3051+
// u32 signature;
3052+
// u8 symbols[symbol_byte_size - 4];
3053+
// u8 line_information[line_info_byte_size];
3054+
// u32 global_refs_byte_size;
3055+
// u8 global_refs[global_refs_byte_size];
3056+
//
30453057

3046-
struct pdb_location module_stream_begin = get_current_pdb_location(context);
3047-
context->module_stream_begin = module_stream_begin;
3058+
*push_struct(&module_stream, u32) = /*CV_SIGNATURE_C13*/4;
30483059

3049-
out_int(4, u32); // signature
3060+
#define begin_symbol_record(record_kind) { current_symbol_record = push_struct(&module_stream, struct codeview_type_record_header); current_symbol_record->kind = (record_kind); }
3061+
#define end_symbol_record() { push_f3f2f1_align(&module_stream, sizeof(u32)); current_symbol_record->length = to_u16(arena_current(&module_stream) - (u8 *)&current_symbol_record->kind); }
30503062

3051-
// first thing is always the OBJNAME, then the COMPILE3
3063+
struct codeview_type_record_header *current_symbol_record;
30523064

3053-
begin_symbol(0x1101);{ // OBJNAME
3054-
out_int(0, u32); // signature
3055-
char module_string[] = "l:\\l++\\build\\test.obj";
3056-
out_struct(module_string); // obj name
3057-
}end_symbol();
3065+
//
3066+
// First thing is always the S_OBJNAME, then the S_COMPILE3.
3067+
//
3068+
begin_symbol_record(0x1101); // S_OBJNAME
3069+
*push_struct(&module_stream, u32) = 0; // Signature (?)
3070+
push_zero_terminated_string_copy(&module_stream, module_object_name_full_path);
3071+
end_symbol_record();
30583072

3059-
begin_symbol(0x113c);{ // S_COMPILE3
3060-
3061-
out_int(0, u32); // flags, the first byte is for the _language index_ 0 means C
3062-
out_int(0xd0, u16); // machine
3063-
3064-
// @note: this is copied from the dump
3065-
out_int(19, u16); // front end major version
3066-
out_int(11, u16); // front end minor version
3067-
out_int(25506, u16); // front end build version
3068-
out_int(0, u16); // front end QFE version ????
3069-
out_int(19, u16); // back end major version
3070-
out_int(11, u16); // back end minor version
3071-
out_int(25506, u16); // back end build version
3072-
out_int(0, u16); // back end QFE version ????
3073-
char version_string[] = "ccup";
3074-
out_struct(version_string);
3075-
}end_symbol();
30763073

3074+
begin_symbol_record(0x113c); // S_COMPILE3
3075+
3076+
struct codeview_compile3{
3077+
u32 flags;
3078+
u16 machine;
3079+
3080+
u16 front_end_major_version;
3081+
u16 front_end_minor_version;
3082+
u16 front_end_build_version;
3083+
u16 front_end_QFE_version;
3084+
3085+
u16 back_end_major_version;
3086+
u16 back_end_minor_version;
3087+
u16 back_end_build_version;
3088+
u16 back_end_QFE_version;
3089+
3090+
char compiler_version_string[];
3091+
} *compile3 = push_struct(&module_stream, struct codeview_compile3);
3092+
compile3->flags = 0; // 0 means C
3093+
compile3->machine = 0xd0; // machine = x64 <- This is used by cvdump.
3094+
3095+
// @cleanup: Not sure what to do about these, but I am also not sure that anyone cares.
3096+
compile3->front_end_major_version = 19;
3097+
compile3->front_end_minor_version = 11;
3098+
compile3->front_end_build_version = 25506;
3099+
compile3->front_end_QFE_version = 0;
3100+
3101+
compile3->back_end_major_version = 19;
3102+
compile3->back_end_minor_version = 11;
3103+
compile3->back_end_build_version = 25506;
3104+
compile3->back_end_QFE_version = 0;
3105+
3106+
push_zero_terminated_string_copy(&module_stream, string("hlc")); // @cleanup: When we have a version system thing, we should probably put it in here.
3107+
3108+
end_symbol_record();
30773109

3078-
begin_counter(timing, module_function_info);
30793110
for_ast_list(defined_functions){
3080-
struct ast_function *function = cast(struct ast_function *)it->value;
3111+
struct ast_function *function = (struct ast_function *)it->value;
30813112

3082-
function->debug_symbol_offset = pdb_current_offset_from_location(context, module_stream_begin);
3083-
3084-
struct pdb_location function_pointer_to_end;
3085-
3086-
u16 symbol = (function->decl_flags & DECLARATION_FLAGS_is_static) ? /* LPROC32 */ 0x110f: /* GPROC32 */ 0x1110;
3087-
begin_symbol(symbol);{ // GPROC32 (global procdure start)
3088-
out_int(0, u32); // pointer to parent (what is a pointer ?)
3089-
function_pointer_to_end = stream_allocate_bytes(context, sizeof(u32)); // pointer to end
3090-
out_int(0, u32); // pointer to next symbol? why is this always 0?
3091-
out_int(function->byte_size, u32); // length of the procedure
3092-
out_int(function->size_of_prolog, u32); // offset in the function where debugging makes sense
3093-
out_int(function->byte_size, u32); // end of the section where it makes sense to debug @cleanup
3094-
out_int(function->type->base.pdb_type_index, u32); // type_index
3095-
out_int(function->offset_in_text_section, u32); // offset in segment
3096-
out_int(text_section_id, u16); // segment
3097-
out_int(0, u8); // flags: Frame pointer, @cleanup: custom calling convention, no_return
3098-
// these are somehow never present???
3099-
out_string(function->identifier->string);
3100-
}end_symbol();
3113+
function->debug_symbol_offset = (u32)(arena_current(&module_stream) - module_stream.base);
31013114

3102-
begin_symbol(0x1012);{ // FRAMEPROC
3103-
3104-
// dll_return_a_struct:
3105-
// 0000000180001030: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
3106-
// 0000000180001035: 56 push rsi
3107-
// 0000000180001036: 57 push rdi
3108-
// 0000000180001037: 48 81 EC 88 00 00 sub rsp,88h
3109-
3110-
// Frame size = 0x00000088 bytes
3111-
// Pad size = 0x00000000 bytes
3112-
// Offset of pad in frame = 0x00000000
3113-
// Size of callee save registers = 0x00000000
3114-
// Address of exception handler = 0000:00000000
3115-
// Function info: asynceh invalid_pgo_counts opt_for_speed Local=rsp Param=rsp (0x00114200)
3116-
3117-
// this appearanly is not really the frame size, but only the space used by the function
3118-
// no pushed registers and return value usw.
3119-
u32 frame_size = to_u32(function->stack_space_needed);
3120-
3121-
out_int(frame_size, u32); // frame size
3122-
out_int(0, u32); // pad size @cleanup: search up what this was again
3123-
out_int(0, u32); // offset of pad
3124-
out_int(0, u32); // callee saved register byte size (not sure)
3125-
out_int(0, u32); // offset of exception handler
3126-
out_int(0, u16); // section id of exception handler
3127-
3128-
u32 flags = 0;
3129-
flags |= (2 << 14); // local base pointer (3 = r13) (2 = rbp) (1 = rsp) (0 = none)
3130-
flags |= (2 << 16); // param base pointer (3 = r13) (2 = rbp) (1 = rsp) (0 = none)
3131-
flags |= (1 << 9); // asynceh, function compiled with /EHa ?
3132-
flags |= (1 << 20); // opt_for_speed, always set for some reason
3133-
out_int(flags, u32); // asynceh invalid_pgo_counts opt_for_speed Local=rsp Param=rsp ???
3134-
}end_symbol();
3115+
u16 function_symbol_kind = (function->decl_flags & DECLARATION_FLAGS_is_static) ? /* LPROC32 */ 0x110f: /* GPROC32 */ 0x1110;
31353116

3136-
// @cleanup: we don't have to emit blocks, that do not have variables
3137-
// and also we do not have to emit the _initial_ block as it is implicit,
3138-
// but these might be things to do in the part that creates debug_members
3117+
begin_symbol_record(function_symbol_kind);
31393118

3119+
struct codeview_proc{
3120+
u32 pointer_to_parent;
3121+
u32 pointer_to_end;
3122+
u32 pointer_to_next;
3123+
u32 procedure_length;
3124+
u32 debug_start_offset;
3125+
u32 debug_end_offset;
3126+
u32 type_index;
3127+
u32 offset_in_section;
3128+
u16 section_id;
3129+
u8 procedure_flags;
3130+
u8 procedure_name[];
3131+
} *proc_symbol = push_struct_(&module_stream, offset_in_type(struct codeview_proc, procedure_name) + (function->identifier->length + 1), 4);
3132+
proc_symbol->pointer_to_parent = 0;
3133+
proc_symbol->pointer_to_end = 0;
3134+
proc_symbol->pointer_to_next = 0;
3135+
proc_symbol->procedure_length = (u32)function->byte_size;
3136+
proc_symbol->debug_start_offset = (u32)function->size_of_prolog;
3137+
proc_symbol->debug_end_offset = (u32)function->byte_size;
3138+
proc_symbol->type_index = function->type->base.pdb_type_index;
3139+
proc_symbol->offset_in_section = (u32)function->offset_in_text_section;
3140+
proc_symbol->section_id = text_section_id;
3141+
proc_symbol->procedure_flags = 0; // Flags, somehow never present.
3142+
memcpy(proc_symbol->procedure_name, function->identifier->data, function->identifier->length);
3143+
proc_symbol->procedure_name[function->identifier->length] = 0;
3144+
3145+
end_symbol_record();
31403146

31413147
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
31423148

3143-
emit_debug_info_for_function(context, function);
3149+
codeview_emit_debug_info_for_function(function, &module_stream, /*relocation_arena (used by obj_writer.c)*/null, /*debug_symbol_base (used by obj_writer.c)*/null, text_section_id);
31443150

31453151
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31463152

3153+
proc_symbol->pointer_to_end = (u32)(arena_current(&module_stream) - module_stream.base);
31473154

3148-
u32 diff = pdb_current_offset_from_location(context, module_stream_begin);
3149-
stream_write_bytes(context, &function_pointer_to_end, &diff, sizeof(u32));
3150-
begin_symbol(0x6);{ // S_END
3151-
}end_symbol();
3155+
begin_symbol_record(0x6); end_symbol_record(); // S_END
31523156
}
3153-
end_counter(timing, module_function_info);
31543157

3155-
begin_symbol(0x114c);{ // S_BUILDINFO
3156-
out_int(build_info_symbol, u32); // Item Id: type_index of a LF_BUILDINFO in the IPI stream
3157-
}end_symbol();
3158+
begin_symbol_record(0x114c); // S_BUILDINFO
3159+
*push_struct(&module_stream, u32) = build_info_symbol; // Item Id: type_index of a LF_BUILDINFO in the IPI stream
3160+
end_symbol_record();
31583161

3159-
struct pdb_location symbols_end = get_current_pdb_location(context);
3160-
module_stream_symbol_size = pdb_location_diff(symbols_end, module_stream_begin);
3162+
module_stream_symbol_size = (u32)(arena_current(&module_stream) - module_stream.base);
31613163

3162-
begin_counter(timing, module_file_info);
3163-
//
3164-
// Here come the md5's
3165-
//
3166-
{
3167-
out_int(0xf4, u32); // DEBUG_S_FILECHKSUM or something like that
3168-
struct pdb_location size_loc = stream_allocate_bytes(context, sizeof(u32));
3169-
struct pdb_location begin_loc = get_current_pdb_location(context);
3170-
for(smm file_index = 0; file_index < array_count(globals.file_table.data); file_index++){
3171-
struct file *node = globals.file_table.data[file_index];
3172-
if(!node) continue;
3173-
3174-
node->offset_in_f4 = pdb_current_offset_from_location(context, begin_loc);
3175-
out_int(node->offset_in_names, u32); // offset in /names
3176-
out_int(0x110, u16); // kind of hash function (md5)
3177-
3178-
// :padded_file_size
3179-
//
3180-
// We have padded the file size when allocating for it so we can use 'hash_md5_inplace'
3181-
// here instead of 'hash_md5' which would have to allocate.
3182-
//
3183-
m128 md5 = hash_md5_inplace(node->file.memory, node->file.size, node->file.size + 128);
3184-
3185-
stream_emit_struct(context, md5._u8, 16);
3186-
out_align(sizeof(u32)); // align up to 32.. there are two bytes of pad
3187-
}
3188-
struct pdb_location end_loc = get_current_pdb_location(context);
3189-
smm size = pdb_location_diff(end_loc, begin_loc);
3190-
stream_write_bytes(context, &size_loc, &size, sizeof(u32));
3191-
}
3164+
u8 *line_information_start = arena_current(&module_stream);
31923165

3193-
end_counter(timing, module_file_info);
3166+
codeview_push_debug_s_file_checksums(&module_stream);
31943167

3195-
begin_counter(timing, module_line_info);
31963168
// now comes the line info
31973169
for_ast_list(defined_functions){
31983170
struct ast_function *function = cast(struct ast_function *)it->value;
3199-
struct ast_scope *scope = function->scope;
3200-
3201-
out_int(0xf2, u32); // DEBUG_S_LINES
3202-
struct pdb_location size_loc = stream_allocate_bytes(context, sizeof(u32));
3203-
struct pdb_location begin_loc = get_current_pdb_location(context);
3204-
3205-
// DEBUG_S_LINES header
3206-
out_int(function->offset_in_text_section, u32); // offset in the section contribution
3207-
out_int(text_section_id, u16); // section id (segment ?)
3208-
out_int(0, u16); // flags (0x1 = have columns)
3209-
out_int(function->byte_size, u32); // the size of the contribution
3210-
3211-
struct pdb_location block_begin = get_current_pdb_location(context);
32123171

3213-
// offset of the file info in the 0xf4 DEBUG_S_SECTION
3214-
out_int(globals.file_table.data[scope->token->file_index]->offset_in_f4, u32);
3215-
struct pdb_location amount_of_lines_loc = stream_allocate_bytes(context, sizeof(u32));
3216-
struct pdb_location block_write = stream_allocate_bytes(context, sizeof(u32));
3217-
3218-
emit_pdb_line_info_for_function(context, function);
3219-
u32 amount_of_lines = save_truncate_smm_to_u32(context->pdb_amount_of_lines);
3220-
stream_write_bytes(context, &amount_of_lines_loc, &amount_of_lines, sizeof(u32));
3221-
3222-
struct pdb_location end_loc = get_current_pdb_location(context);
3223-
smm block_size = pdb_location_diff(end_loc, block_begin);
3224-
stream_write_bytes(context, &block_write, &block_size, sizeof(u32));
3225-
3226-
smm size = pdb_location_diff(end_loc, begin_loc);
3227-
stream_write_bytes(context, &size_loc, &size, sizeof(u32));
3172+
codeview_push_debug_s_lines(function, &module_stream, /*relocation_arena (used by obj_writer.c)*/null, /*debug_symbol_base (used by obj_writer.c)*/null, text_section_id);
32283173
}
3229-
end_counter(timing, module_line_info);
32303174

3231-
struct pdb_location module_stream_end = get_current_pdb_location(context);
3232-
module_stream_line_info_size = pdb_location_diff(module_stream_end, symbols_end);
32333175

3234-
out_int(0, u32); // amount_of global references
3176+
module_stream_line_info_size = (u32)(arena_current(&module_stream) - line_information_start);
3177+
3178+
*push_struct(&module_stream, u32) = 0; // Amount of global references.
3179+
3180+
set_current_stream(context, STREAM_module_zero);
3181+
stream_emit_struct(context, module_stream.base, arena_current(&module_stream) - module_stream.base);
32353182
}
32363183
end_counter(timing, module_stream);
32373184

0 commit comments

Comments
 (0)