/* outdbg.c output routines for the Netwide Assembler to produce * a debugging trace * * The Netwide Assembler is copyright (C) 1996 Simon Tatham and * Julian Hall. All rights reserved. The software is * redistributable under the licence given in the file "Licence" * distributed in the NASM archive. */ #include "compiler.h" #include #include #include #include #include #include "nasm.h" #include "nasmlib.h" #include "outform.h" #ifdef OF_DBG struct Section { struct Section *next; int32_t number; char *name; } *dbgsect; FILE *dbgf; efunc dbgef; struct ofmt of_dbg; static void dbg_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval) { (void)eval; dbgf = fp; dbgef = errfunc; dbgsect = NULL; (void)ldef; fprintf(fp, "NASM Output format debug dump\n"); of_dbg.current_dfmt->init(&of_dbg, 0, fp, errfunc); } static void dbg_cleanup(int debuginfo) { (void)debuginfo; of_dbg.current_dfmt->cleanup(); while (dbgsect) { struct Section *tmp = dbgsect; dbgsect = dbgsect->next; nasm_free(tmp->name); nasm_free(tmp); } fclose(dbgf); } static int32_t dbg_section_names(char *name, int pass, int *bits) { int seg; /* * We must have an initial default: let's make it 16. */ if (!name) *bits = 16; if (!name) fprintf(dbgf, "section_name on init: returning %d\n", seg = seg_alloc()); else { int n = strcspn(name, " \t"); char *sname = nasm_strndup(name, n); struct Section *s; seg = NO_SEG; for (s = dbgsect; s; s = s->next) if (!strcmp(s->name, sname)) seg = s->number; if (seg == NO_SEG) { s = nasm_malloc(sizeof(*s)); s->name = sname; s->number = seg = seg_alloc(); s->next = dbgsect; dbgsect = s; fprintf(dbgf, "section_name %s (pass %d): returning %d\n", name, pass, seg); } } return seg; } static void dbg_deflabel(char *name, int32_t segment, int32_t offset, int is_global, char *special) { fprintf(dbgf, "deflabel %s := %08lx:%08lx %s (%d)%s%s\n", name, segment, offset, is_global == 2 ? "common" : is_global ? "global" : "local", is_global, special ? ": " : "", special); } static void dbg_out(int32_t segto, const void *data, uint32_t type, int32_t segment, int32_t wrt) { int32_t realbytes = type & OUT_SIZMASK; int32_t ldata; int id; type &= OUT_TYPMASK; fprintf(dbgf, "out to %lx, len = %ld: ", segto, realbytes); switch (type) { case OUT_RESERVE: fprintf(dbgf, "reserved.\n"); break; case OUT_RAWDATA: fprintf(dbgf, "raw data = "); while (realbytes--) { id = *(uint8_t *)data; data = (char *)data + 1; fprintf(dbgf, "%02x ", id); } fprintf(dbgf, "\n"); break; case OUT_ADDRESS: ldata = 0; /* placate gcc */ if (realbytes == 1) ldata = *((char *)data); else if (realbytes == 2) ldata = *((int16_t *)data); else if (realbytes == 4) ldata = *((int32_t *)data); fprintf(dbgf, "addr %08lx (seg %08lx, wrt %08lx)\n", ldata, segment, wrt); break; case OUT_REL2ADR: fprintf(dbgf, "rel2adr %04x (seg %08lx)\n", (int)*(int16_t *)data, segment); break; case OUT_REL4ADR: fprintf(dbgf, "rel4adr %08lx (seg %08lx)\n", *(int32_t *)data, segment); break; default: fprintf(dbgf, "unknown\n"); break; } } static int32_t dbg_segbase(int32_t segment) { return segment; } static int dbg_directive(char *directive, char *value, int pass) { fprintf(dbgf, "directive [%s] value [%s] (pass %d)\n", directive, value, pass); return 1; } static void dbg_filename(char *inname, char *outname, efunc error) { standard_extension(inname, outname, ".dbg", error); } static int dbg_set_info(enum geninfo type, char **val) { (void)type; (void)val; return 0; } char *types[] = { "unknown", "label", "byte", "word", "dword", "float", "qword", "tbyte" }; void dbgdbg_init(struct ofmt *of, void *id, FILE * fp, efunc error) { (void)of; (void)id; (void)fp; (void)error; fprintf(fp, " With debug info\n"); } static void dbgdbg_cleanup(void) { } static void dbgdbg_linnum(const char *lnfname, int32_t lineno, int32_t segto) { fprintf(dbgf, "dbglinenum %s(%ld) := %08lx\n", lnfname, lineno, segto); } static void dbgdbg_deflabel(char *name, int32_t segment, int32_t offset, int is_global, char *special) { fprintf(dbgf, "dbglabel %s := %08lx:%08lx %s (%d)%s%s\n", name, segment, offset, is_global == 2 ? "common" : is_global ? "global" : "local", is_global, special ? ": " : "", special); } static void dbgdbg_define(const char *type, const char *params) { fprintf(dbgf, "dbgdirective [%s] value [%s]\n", type, params); } static void dbgdbg_output(int output_type, void *param) { (void)output_type; (void)param; } static void dbgdbg_typevalue(int32_t type) { fprintf(dbgf, "new type: %s(%lX)\n", types[TYM_TYPE(type) >> 3], TYM_ELEMENTS(type)); } static struct dfmt debug_debug_form = { "Trace of all info passed to debug stage", "debug", dbgdbg_init, dbgdbg_linnum, dbgdbg_deflabel, dbgdbg_define, dbgdbg_typevalue, dbgdbg_output, dbgdbg_cleanup, }; static struct dfmt *debug_debug_arr[3] = { &debug_debug_form, &null_debug_form, NULL }; struct ofmt of_dbg = { "Trace of all info passed to output stage", "dbg", NULL, debug_debug_arr, &null_debug_form, NULL, dbg_init, dbg_set_info, dbg_out, dbg_deflabel, dbg_section_names, dbg_segbase, dbg_directive, dbg_filename, dbg_cleanup }; #endif /* OF_DBG */