[qfcc] create a compilation unit for debug data

The compilation unit stores the directory from which qfcc was run and
any source files mentioned. This is similar to dwarf's compilation unit.
Right now, this is the only data in the new debug space, but more might
come in the future so it seems best to treat the debug space separately
in the object files.
This commit is contained in:
Bill Currie 2020-04-03 14:27:22 +09:00
parent 65e7df44d3
commit 049b8f392c
8 changed files with 161 additions and 4 deletions

View file

@ -34,6 +34,13 @@
#ifndef __QFCC__ #ifndef __QFCC__
#include "QF/pr_comp.h" #include "QF/pr_comp.h"
typedef struct pr_compunit_s {
pr_uint_t unit_name;
pr_uint_t basedir;
pr_uint_t num_files;
pr_uint_t files[1];
} pr_compunit_t;
typedef struct pr_auxfunction_s { typedef struct pr_auxfunction_s {
pr_uint_t function; // function def this aux info is for pr_uint_t function; // function def this aux info is for
pr_uint_t source_line; // first source line for this function pr_uint_t source_line; // first source line for this function

View file

@ -35,6 +35,8 @@
void line_info (char *text); void line_info (char *text);
pr_lineno_t *new_lineno (void); pr_lineno_t *new_lineno (void);
void add_source_file (const char *file);
void debug_finish_module (const char *modname);
extern int lineno_base; extern int lineno_base;

View file

@ -77,6 +77,7 @@ typedef enum qfos_type_e {
qfos_string, ///< strings. char data qfos_string, ///< strings. char data
qfos_entity, ///< entity field defs. no data qfos_entity, ///< entity field defs. no data
qfos_type, ///< type encodings qfos_type, ///< type encodings
qfos_debug, ///< debug data
} qfos_type_t; } qfos_type_t;
/** Representation of a space in the object file. /** Representation of a space in the object file.
@ -283,6 +284,7 @@ enum {
qfo_far_data_space, qfo_far_data_space,
qfo_entity_space, qfo_entity_space,
qfo_type_space, qfo_type_space,
qfo_debug_space,
qfo_num_spaces qfo_num_spaces
}; };

View file

@ -34,6 +34,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "QF/darray.h"
#include "QF/pr_comp.h" #include "QF/pr_comp.h"
/** \defgroup qfcc_general General functions /** \defgroup qfcc_general General functions
@ -68,6 +69,11 @@ typedef struct pr_info_s {
struct defspace_s *entity_data; ///< entity field address space. no struct defspace_s *entity_data; ///< entity field address space. no
///< data is stored in the progs file ///< data is stored in the progs file
struct defspace_s *type_data; ///< encoded type information. struct defspace_s *type_data; ///< encoded type information.
struct defspace_s *debug_data; ///< additional debug data.
struct strpool_s *comp_file_set;
struct DARRAY_TYPE (const char *) comp_files;
const char *comp_dir;
const char *unit_name;
struct symtab_s *symtab; struct symtab_s *symtab;
struct symtab_s *entity_fields; struct symtab_s *entity_fields;

View file

@ -44,10 +44,16 @@
#include "QF/pr_comp.h" #include "QF/pr_comp.h"
#include "debug.h" #include "debug.h"
#include "def.h"
#include "defspace.h"
#include "diagnostic.h" #include "diagnostic.h"
#include "emit.h"
#include "expr.h" #include "expr.h"
#include "qfcc.h" #include "qfcc.h"
#include "reloc.h"
#include "strpool.h" #include "strpool.h"
#include "struct.h"
#include "type.h"
#include "value.h" #include "value.h"
int lineno_base; int lineno_base;
@ -79,6 +85,17 @@ pop_source_file (void)
FREE (srclines, tmp); FREE (srclines, tmp);
} }
#define Sys_Error(fmt...) internal_error(0, fmt)
void
add_source_file (const char *file)
{
pr.source_file = ReuseString (file);
if (!strpool_findstr (pr.comp_file_set, file)) {
strpool_addstr (pr.comp_file_set, file);
DARRAY_APPEND (&pr.comp_files, save_string (file));
}
}
void void
line_info (char *text) line_info (char *text)
{ {
@ -111,7 +128,7 @@ line_info (char *text)
while (*p && *p != '\n') // ignore rest while (*p && *p != '\n') // ignore rest
p++; p++;
pr.source_line = line - 1; pr.source_line = line - 1;
pr.source_file = ReuseString (str); add_source_file (str);
} }
pr_lineno_t * pr_lineno_t *
@ -125,3 +142,67 @@ new_lineno (void)
memset (&pr.linenos[pr.num_linenos], 0, sizeof (pr_lineno_t)); memset (&pr.linenos[pr.num_linenos], 0, sizeof (pr_lineno_t));
return &pr.linenos[pr.num_linenos++]; return &pr.linenos[pr.num_linenos++];
} }
static void
emit_unit_name (def_t *def, void *data, int index)
{
if (!is_string (def->type)) {
internal_error (0, "%s: expected string def", __FUNCTION__);
}
EMIT_STRING (def->space, D_STRING (def), pr.unit_name);
}
static void
emit_basedir (def_t *def, void *data, int index)
{
if (!is_string (def->type)) {
internal_error (0, "%s: expected string def", __FUNCTION__);
}
EMIT_STRING (def->space, D_STRING (def), pr.comp_dir);
}
static void
emit_num_files (def_t *def, void *data, int index)
{
if (!is_integer (def->type)) {
internal_error (0, "%s: expected int def", __FUNCTION__);
}
D_INT (def) = pr.comp_files.size;
}
static void
emit_files_item (def_t *def, void *data, int index)
{
if (!is_array (def->type) || !is_string (def->type->t.array.type)) {
internal_error (0, "%s: expected array of string def", __FUNCTION__);
}
if ((unsigned) index >= pr.comp_files.size) {
internal_error (0, "%s: out of bounds index: %d %zd",
__FUNCTION__, index, pr.comp_files.size);
}
EMIT_STRING (def->space, D_STRING (def), pr.comp_files.a[index]);
}
static def_t *
emit_compunit (const char *modname)
{
static struct_def_t compunit_struct[] = {
{"unit_name", &type_string, emit_unit_name},
{"basedir", &type_string, emit_basedir},
{"num_files", &type_integer, emit_num_files},
{"files", 0, emit_files_item},
{0, 0}
};
int count = pr.comp_files.size;
pr.unit_name = modname;
compunit_struct[3].type = array_type (&type_string, count);
return emit_structure ("compile_unit", 's', compunit_struct, 0, &pr,
pr.debug_data, sc_static);
}
void
debug_finish_module (const char *modname)
{
emit_compunit (modname);
}

View file

@ -154,6 +154,7 @@ static defspace_t *work_near_data;
static defspace_t *work_far_data; static defspace_t *work_far_data;
static defspace_t *work_entity_data; static defspace_t *work_entity_data;
static defspace_t *work_type_data; static defspace_t *work_type_data;
static defspace_t *work_debug_data;
static qfo_reloc_t *work_loose_relocs; static qfo_reloc_t *work_loose_relocs;
static int work_num_loose_relocs; static int work_num_loose_relocs;
@ -163,6 +164,7 @@ static defspace_t **work_spaces[qfo_num_spaces] = {
&work_far_data, &work_far_data,
&work_entity_data, &work_entity_data,
&work_type_data, &work_type_data,
&work_debug_data,
}; };
static dstring_t *linker_current_file; static dstring_t *linker_current_file;
@ -684,6 +686,7 @@ linker_begin (void)
work_far_data = defspace_new (ds_backed); work_far_data = defspace_new (ds_backed);
work_entity_data = defspace_new (ds_virtual); work_entity_data = defspace_new (ds_virtual);
work_type_data = defspace_new (ds_backed); work_type_data = defspace_new (ds_backed);
work_debug_data = defspace_new (ds_backed);
pr.strings = work_strings; pr.strings = work_strings;
@ -709,6 +712,9 @@ linker_begin (void)
work->spaces[qfo_type_space].type = qfos_type; work->spaces[qfo_type_space].type = qfos_type;
work->spaces[qfo_type_space].d.data = work_type_data->data; work->spaces[qfo_type_space].d.data = work_type_data->data;
work->spaces[qfo_type_space].data_size = work_type_data->size; work->spaces[qfo_type_space].data_size = work_type_data->size;
work->spaces[qfo_debug_space].type = qfos_debug;
work->spaces[qfo_debug_space].d.data = work_type_data->data;
work->spaces[qfo_debug_space].data_size = work_type_data->size;
for (i = 0; i < qfo_num_spaces; i++) for (i = 0; i < qfo_num_spaces; i++)
work->spaces[i].id = i; work->spaces[i].id = i;
@ -906,6 +912,20 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
return 0; return 0;
} }
static int
process_debug_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
{
if (pass != 1)
return 0;
if (space->type != qfos_debug) {
linker_internal_error ("bad space type for add_data_space (): %d",
space->type);
}
add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def);
add_data (qfo_debug_space, space);
return 0;
}
static void static void
process_funcs (qfo_t *qfo) process_funcs (qfo_t *qfo)
{ {
@ -1002,6 +1022,7 @@ linker_add_qfo (qfo_t *qfo)
process_strings_space, process_strings_space,
process_entity_space, process_entity_space,
process_type_space, process_type_space,
process_debug_space,
}; };
unsigned i; unsigned i;
int pass; int pass;
@ -1014,7 +1035,7 @@ linker_add_qfo (qfo_t *qfo)
work_func_base = work->num_funcs; work_func_base = work->num_funcs;
for (pass = 0; pass < 2; pass++) { for (pass = 0; pass < 2; pass++) {
for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) { for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) {
if ((int) space->type < 0 || space->type > qfos_type) { if ((int) space->type < 0 || space->type > qfos_debug) {
linker_error ("bad space type"); linker_error ("bad space type");
return 1; return 1;
} }

View file

@ -183,6 +183,7 @@ qfo_count_stuff (qfo_t *qfo, pr_info_t *pr)
qfo_count_space_stuff (qfo, pr->far_data); qfo_count_space_stuff (qfo, pr->far_data);
qfo_count_space_stuff (qfo, pr->entity_data); qfo_count_space_stuff (qfo, pr->entity_data);
qfo_count_space_stuff (qfo, pr->type_data); qfo_count_space_stuff (qfo, pr->type_data);
qfo_count_space_stuff (qfo, pr->debug_data);
qfo_count_function_stuff (qfo, pr->func_head); qfo_count_function_stuff (qfo, pr->func_head);
qfo->num_relocs += count_relocs (pr->relocs); qfo->num_relocs += count_relocs (pr->relocs);
} }
@ -269,6 +270,24 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
space->id = qfo_type_space; space->id = qfo_type_space;
} }
static void
qfo_init_debug_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
qfo_mspace_t *space, defspace_t *data)
{
size_t size = data->size * sizeof (*data->data);
data->qfo_space = space - qfo->spaces;
space->type = qfos_debug;
space->defs = *defs;
space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs);
space->d.data = 0;
if (data->data) {
space->d.data = malloc (size);
memcpy (space->d.data, data->data, size);
}
space->data_size = data->size;
space->id = qfo_debug_space;
}
static void static void
qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
qfo_mspace_t *space, function_t *functions) qfo_mspace_t *space, function_t *functions)
@ -333,6 +352,8 @@ qfo_from_progs (pr_info_t *pr)
pr->entity_data); pr->entity_data);
qfo_init_type_space (qfo, &def, &reloc, &qfo->spaces[qfo_type_space], qfo_init_type_space (qfo, &def, &reloc, &qfo->spaces[qfo_type_space],
pr->type_data); pr->type_data);
qfo_init_debug_space (qfo, &def, &reloc, &qfo->spaces[qfo_debug_space],
pr->debug_data);
qfo_encode_functions (qfo, &def, &reloc, qfo->spaces + qfo_num_spaces, qfo_encode_functions (qfo, &def, &reloc, qfo->spaces + qfo_num_spaces,
pr->func_head); pr->func_head);
@ -382,6 +403,8 @@ qfo_space_size (qfo_mspace_t *space)
return 0; return 0;
case qfos_type: case qfos_type:
return space->data_size * sizeof (*space->d.data); return space->data_size * sizeof (*space->d.data);
case qfos_debug:
return space->data_size * sizeof (*space->d.data);
} }
return 0; return 0;
} }
@ -407,6 +430,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type)
case qfos_data: case qfos_data:
case qfos_entity: case qfos_entity:
case qfos_type: case qfos_type:
case qfos_debug:
for (val = (pr_type_t *) space, c = 0; c < size; c++, val++) for (val = (pr_type_t *) space, c = 0; c < size; c++, val++)
val->integer_var = LittleLong (val->integer_var); val->integer_var = LittleLong (val->integer_var);
break; break;
@ -949,6 +973,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
progs->numglobals += progs->numglobaldefs * type_size (&type_xdef); progs->numglobals += progs->numglobaldefs * type_size (&type_xdef);
progs->numglobals += progs->numfielddefs * type_size (&type_xdef); progs->numglobals += progs->numfielddefs * type_size (&type_xdef);
progs->entityfields = qfo->spaces[qfo_entity_space].data_size; progs->entityfields = qfo->spaces[qfo_entity_space].data_size;
// qfo_debug_space does not go in the progs file
*size += progs->numstatements * sizeof (dstatement_t); *size += progs->numstatements * sizeof (dstatement_t);
*size += progs->numglobaldefs * sizeof (ddef_t); *size += progs->numglobaldefs * sizeof (ddef_t);
*size += progs->numfielddefs * sizeof (ddef_t); *size += progs->numfielddefs * sizeof (ddef_t);

View file

@ -141,6 +141,12 @@ InitData (void)
defspace_delete (pr.far_data); defspace_delete (pr.far_data);
defspace_delete (pr.entity_data); defspace_delete (pr.entity_data);
defspace_delete (pr.type_data); defspace_delete (pr.type_data);
defspace_delete (pr.debug_data);
strpool_delete (pr.comp_file_set);
}
if (pr.comp_files.a) {
DARRAY_CLEAR (&pr.comp_files);
} }
if (pr.linenos) { if (pr.linenos) {
@ -173,6 +179,10 @@ InitData (void)
pr.type_data = defspace_new (ds_backed); pr.type_data = defspace_new (ds_backed);
defspace_alloc_loc (pr.type_data, 4);// reserve space for a null descriptor defspace_alloc_loc (pr.type_data, 4);// reserve space for a null descriptor
pr.debug_data = defspace_new (ds_backed);
pr.comp_file_set = strpool_new ();
DARRAY_INIT (&pr.comp_files, 16);
pr.symtab = new_symtab (0, stab_global); pr.symtab = new_symtab (0, stab_global);
pr.symtab->space = pr.near_data; pr.symtab->space = pr.near_data;
current_symtab = pr.symtab; current_symtab = pr.symtab;
@ -374,7 +384,8 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
InitData (); InitData ();
chain_initial_types (); chain_initial_types ();
begin_compilation (); begin_compilation ();
pr.source_file = ReuseString (file); pr.comp_dir = save_cwd ();
add_source_file (file);
err = yyparse () || pr.error_count; err = yyparse () || pr.error_count;
fclose (*yyin); fclose (*yyin);
if (cpp_name && !options.save_temps) { if (cpp_name && !options.save_temps) {
@ -392,6 +403,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
class_finish_module (); class_finish_module ();
err = pr.error_count; err = pr.error_count;
if (!err) { if (!err) {
debug_finish_module (obj);
qfo = qfo_from_progs (&pr); qfo = qfo_from_progs (&pr);
err = qfo_write (qfo, obj); err = qfo_write (qfo, obj);
qfo_delete (qfo); qfo_delete (qfo);
@ -630,7 +642,7 @@ compile_file (const char *filename)
if (!*yyin) if (!*yyin)
return !options.preprocess_only; return !options.preprocess_only;
pr.source_file = ReuseString (filename); add_source_file (filename);
pr.source_line = 1; pr.source_line = 1;
clear_frame_macros (); clear_frame_macros ();
err = yyparse () || pr.error_count; err = yyparse () || pr.error_count;
@ -774,6 +786,7 @@ progs_src_compile (void)
} }
class_finish_module (); class_finish_module ();
debug_finish_module (options.output_file);
qfo = qfo_from_progs (&pr); qfo = qfo_from_progs (&pr);
if (options.compile) { if (options.compile) {
qfo_write (qfo, options.output_file); qfo_write (qfo, options.output_file);