[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__
#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 {
pr_uint_t function; // function def this aux info is for
pr_uint_t source_line; // first source line for this function

View file

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

View file

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

View file

@ -34,6 +34,7 @@
*/
#include <stdio.h>
#include "QF/darray.h"
#include "QF/pr_comp.h"
/** \defgroup qfcc_general General functions
@ -68,6 +69,11 @@ typedef struct pr_info_s {
struct defspace_s *entity_data; ///< entity field address space. no
///< data is stored in the progs file
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 *entity_fields;

View file

@ -44,10 +44,16 @@
#include "QF/pr_comp.h"
#include "debug.h"
#include "def.h"
#include "defspace.h"
#include "diagnostic.h"
#include "emit.h"
#include "expr.h"
#include "qfcc.h"
#include "reloc.h"
#include "strpool.h"
#include "struct.h"
#include "type.h"
#include "value.h"
int lineno_base;
@ -79,6 +85,17 @@ pop_source_file (void)
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
line_info (char *text)
{
@ -111,7 +128,7 @@ line_info (char *text)
while (*p && *p != '\n') // ignore rest
p++;
pr.source_line = line - 1;
pr.source_file = ReuseString (str);
add_source_file (str);
}
pr_lineno_t *
@ -125,3 +142,67 @@ new_lineno (void)
memset (&pr.linenos[pr.num_linenos], 0, sizeof (pr_lineno_t));
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_entity_data;
static defspace_t *work_type_data;
static defspace_t *work_debug_data;
static qfo_reloc_t *work_loose_relocs;
static int work_num_loose_relocs;
@ -163,6 +164,7 @@ static defspace_t **work_spaces[qfo_num_spaces] = {
&work_far_data,
&work_entity_data,
&work_type_data,
&work_debug_data,
};
static dstring_t *linker_current_file;
@ -684,6 +686,7 @@ linker_begin (void)
work_far_data = defspace_new (ds_backed);
work_entity_data = defspace_new (ds_virtual);
work_type_data = defspace_new (ds_backed);
work_debug_data = defspace_new (ds_backed);
pr.strings = work_strings;
@ -709,6 +712,9 @@ linker_begin (void)
work->spaces[qfo_type_space].type = qfos_type;
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_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++)
work->spaces[i].id = i;
@ -906,6 +912,20 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
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
process_funcs (qfo_t *qfo)
{
@ -1002,6 +1022,7 @@ linker_add_qfo (qfo_t *qfo)
process_strings_space,
process_entity_space,
process_type_space,
process_debug_space,
};
unsigned i;
int pass;
@ -1014,7 +1035,7 @@ linker_add_qfo (qfo_t *qfo)
work_func_base = work->num_funcs;
for (pass = 0; pass < 2; pass++) {
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");
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->entity_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->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;
}
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
qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
qfo_mspace_t *space, function_t *functions)
@ -333,6 +352,8 @@ qfo_from_progs (pr_info_t *pr)
pr->entity_data);
qfo_init_type_space (qfo, &def, &reloc, &qfo->spaces[qfo_type_space],
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,
pr->func_head);
@ -382,6 +403,8 @@ qfo_space_size (qfo_mspace_t *space)
return 0;
case qfos_type:
return space->data_size * sizeof (*space->d.data);
case qfos_debug:
return space->data_size * sizeof (*space->d.data);
}
return 0;
}
@ -407,6 +430,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type)
case qfos_data:
case qfos_entity:
case qfos_type:
case qfos_debug:
for (val = (pr_type_t *) space, c = 0; c < size; c++, val++)
val->integer_var = LittleLong (val->integer_var);
break;
@ -949,6 +973,7 @@ qfo_to_progs (qfo_t *qfo, int *size)
progs->numglobals += progs->numglobaldefs * type_size (&type_xdef);
progs->numglobals += progs->numfielddefs * type_size (&type_xdef);
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->numglobaldefs * 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.entity_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) {
@ -173,6 +179,10 @@ InitData (void)
pr.type_data = defspace_new (ds_backed);
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->space = pr.near_data;
current_symtab = pr.symtab;
@ -374,7 +384,8 @@ compile_to_obj (const char *file, const char *obj, lang_t lang)
InitData ();
chain_initial_types ();
begin_compilation ();
pr.source_file = ReuseString (file);
pr.comp_dir = save_cwd ();
add_source_file (file);
err = yyparse () || pr.error_count;
fclose (*yyin);
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 ();
err = pr.error_count;
if (!err) {
debug_finish_module (obj);
qfo = qfo_from_progs (&pr);
err = qfo_write (qfo, obj);
qfo_delete (qfo);
@ -630,7 +642,7 @@ compile_file (const char *filename)
if (!*yyin)
return !options.preprocess_only;
pr.source_file = ReuseString (filename);
add_source_file (filename);
pr.source_line = 1;
clear_frame_macros ();
err = yyparse () || pr.error_count;
@ -774,6 +786,7 @@ progs_src_compile (void)
}
class_finish_module ();
debug_finish_module (options.output_file);
qfo = qfo_from_progs (&pr);
if (options.compile) {
qfo_write (qfo, options.output_file);