Created
March 3, 2013 20:40
-
-
Save EmacsUser/5078185 to your computer and use it in GitHub Desktop.
Extract of debug_load_symbols from zoom/src/debug.c in http://code.logicalshift.co.uk/zoom/zoom.git.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void debug_load_symbols(char* filename, | |
char* pathname) | |
{ | |
ZFile* file; | |
ZByte* db_file; | |
int size; | |
int pos; | |
int done; | |
int x; | |
debug_routine* this_routine = NULL; | |
debug_symbol* sym; | |
#ifdef REMOTE_BREAKPOINT | |
/* SIGUSR1 indicates that we should break ASAP */ | |
struct sigaction oldact; | |
sigaction(SIGUSR1, NULL, &oldact); | |
oldact.sa_flags |= SA_RESTART; | |
oldact.sa_flags &= ~(SA_NODEFER|SA_SIGINFO); | |
oldact.sa_handler = debug_sigusr1; | |
sigaction(SIGUSR1, &oldact, NULL); | |
#endif | |
size = get_file_size(filename); | |
file = open_file(filename); | |
if (file == NULL) | |
{ | |
display_printf("=! unable to open file '%s'\n", filename); | |
return; | |
} | |
db_file = read_block(file, 0, size); | |
close_file(file); | |
if (db_file == NULL) | |
return; | |
display_printf("= loading symbols from '%s'...\n", filename); | |
if (db_file[0] != 0xde || db_file[1] != 0xbf) | |
{ | |
display_printf("=! Bad debug file\n"); | |
free(db_file); | |
return; | |
} | |
debug_syms.largest_object = 0; | |
pos = 6; | |
done = 0; | |
if (debug_syms.symbol == NULL) | |
debug_syms.symbol = hash_create(); | |
if (debug_syms.file == NULL) | |
debug_syms.file = hash_create(); | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_global; | |
sym->data.global.name = "self"; | |
sym->data.global.number = 251-16; | |
debug_add_symbol(sym->data.global.name, sym); | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_global; | |
sym->data.global.name = "sender"; | |
sym->data.global.number = 250-16; | |
debug_add_symbol(sym->data.global.name, sym); | |
while (pos < size && !done) | |
{ | |
switch (db_file[pos]) | |
{ | |
case DEBUG_EOF_DBR: | |
done = 1; | |
break; | |
case DEBUG_FILE_DBR: | |
{ | |
debug_file* fl; | |
ZFile* fl_load; | |
ZDWord fl_len; | |
char* fn; | |
fl = malloc(sizeof(debug_file)); | |
fl->number = db_file[pos+1]; | |
fl->name = malloc(sizeof(char)*(strlen((char*)(db_file + pos + 2)) + 1)); | |
strcpy(fl->name, (char*)(db_file + pos + 2)); | |
pos += 3 + strlen(fl->name); | |
fl->realname = malloc(sizeof(char)*(strlen((char*)(db_file + pos)) + 1)); | |
strcpy(fl->realname, (char*)(db_file + pos)); | |
pos += strlen(fl->realname) + 1; | |
fl->data = NULL; | |
fl->nlines = 0; | |
fl->line = NULL; | |
fn = malloc(sizeof(char)*(strlen(fl->realname)+strlen(pathname)+1)); | |
strcpy(fn, fl->realname); | |
fl_len = get_file_size(fn); | |
if (fl_len == -1) | |
{ | |
strcpy(fn, pathname); | |
strcat(fn, fl->realname); | |
fl_len = get_file_size(fn); | |
} | |
if (fl_len >= 0) | |
{ | |
fl_load = open_file(fn); | |
if (fl_load != NULL) | |
{ | |
int x; | |
fl->data = (char*)read_block(fl_load, 0, fl_len); | |
close_file(fl_load); | |
fl->data = realloc(fl->data, sizeof(char)*(fl_len+2)); | |
fl->data[fl_len] = 0; | |
fl->nlines++; | |
fl->line = realloc(fl->line, sizeof(char*)*(fl->nlines)); | |
fl->line[0] = fl->data; | |
for (x=0; x<fl_len; x++) | |
{ | |
if (fl->data[x] == 13 || fl->data[x] == 10) | |
{ | |
int p; | |
p = x; | |
if (((fl->data[x+1] == 10 || fl->data[x+1] == 13) && | |
fl->data[x+1] != fl->data[x])) | |
x++; | |
fl->data[p] = 0; | |
if (x < fl_len) | |
{ | |
fl->nlines++; | |
fl->line = realloc(fl->line, | |
sizeof(char*)*fl->nlines); | |
fl->line[fl->nlines-1] = fl->data + x+1; | |
} | |
} | |
} | |
} | |
} | |
else | |
{ | |
display_printf("=? unable to load source file '%s'\n", fl->realname); | |
} | |
free(fn); | |
debug_syms.nfiles++; | |
if (debug_syms.nfiles != fl->number) | |
{ | |
display_printf("=! file '%s' doesn't appear in order\n", | |
fl->name); | |
goto failed; | |
} | |
debug_syms.files = realloc(debug_syms.files, | |
sizeof(debug_file)*(debug_syms.nfiles+1)); | |
debug_syms.files[fl->number] = *fl; | |
hash_store_happy(debug_syms.file, | |
(unsigned char*)fl->name, | |
strlen(fl->name), | |
fl); | |
} | |
break; | |
case DEBUG_CLASS_DBR: | |
{ | |
debug_class c; | |
pos++; | |
c.name = malloc(sizeof(char)*(strlen(db_file + pos)+1)); | |
strcpy(c.name, db_file + pos); | |
pos += strlen(db_file+pos) + 1; | |
c.st_fl = db_file[pos++]; | |
c.st_ln = db_file[pos++]<<8; | |
c.st_ln |= db_file[pos++]; | |
c.st_ch = db_file[pos++]; | |
c.end_fl = db_file[pos++]; | |
c.end_ln = db_file[pos++]<<8; | |
c.end_ln |= db_file[pos++]; | |
c.end_ch = db_file[pos++]; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_class; | |
sym->data.class = c; | |
debug_add_symbol(c.name, | |
sym); | |
} | |
break; | |
case DEBUG_OBJECT_DBR: | |
{ | |
debug_object o; | |
pos++; | |
o.number = db_file[pos++]<<8; | |
o.number |= db_file[pos++]; | |
o.name = malloc(sizeof(char)*(strlen(db_file + pos)+1)); | |
strcpy(o.name, db_file + pos); | |
pos += strlen(db_file+pos) + 1; | |
o.st_fl = db_file[pos++]; | |
o.st_ln = db_file[pos++]<<8; | |
o.st_ln |= db_file[pos++]; | |
o.st_ch = db_file[pos++]; | |
o.end_fl = db_file[pos++]; | |
o.end_ln = db_file[pos++]<<8; | |
o.end_ln |= db_file[pos++]; | |
o.end_ch = db_file[pos++]; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_object; | |
sym->data.object = o; | |
debug_add_symbol(o.name, | |
sym); | |
if (o.number > debug_syms.largest_object) debug_syms.largest_object = o.number; | |
} | |
break; | |
case DEBUG_GLOBAL_DBR: | |
{ | |
debug_global g; | |
pos++; | |
g.number = db_file[pos++]; | |
g.name = malloc(sizeof(char)*(strlen(db_file + pos) + 1)); | |
strcpy(g.name, db_file + pos); | |
pos += strlen(db_file + pos) + 1; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_global; | |
sym->data.global = g; | |
debug_add_symbol(g.name, | |
sym); | |
} | |
break; | |
case DEBUG_ATTR_DBR: | |
{ | |
debug_attr a; | |
pos++; | |
a.number = db_file[pos++]<<8; | |
a.number |= db_file[pos++]; | |
a.name = malloc(sizeof(char)*(strlen(db_file + pos) + 1)); | |
strcpy(a.name, db_file + pos); | |
pos += strlen(a.name)+1; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_attr; | |
sym->data.attr = a; | |
debug_add_symbol(a.name, | |
sym); | |
} | |
break; | |
case DEBUG_PROP_DBR: | |
{ | |
debug_prop p; | |
pos++; | |
p.number = db_file[pos++]<<8; | |
p.number |= db_file[pos++]; | |
p.name = malloc(sizeof(char)*(strlen(db_file + pos) + 1)); | |
strcpy(p.name, db_file + pos); | |
pos += strlen(p.name)+1; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_prop; | |
sym->data.prop = p; | |
debug_add_symbol(p.name, | |
sym); | |
} | |
break; | |
case DEBUG_ACTION_DBR: | |
{ | |
debug_action a; | |
pos++; | |
a.number = db_file[pos++]<<8; | |
a.number |= db_file[pos++]; | |
a.name = malloc(sizeof(char)*(strlen(db_file + pos) + 1)); | |
strcpy(a.name, db_file + pos); | |
pos += strlen(db_file + pos) + 1; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_action; | |
sym->data.action = a; | |
/* debug_add_symbol(a.name, | |
sym); */ | |
} | |
break; | |
case DEBUG_FAKEACT_DBR: | |
{ | |
debug_fakeact a; | |
pos++; | |
a.number = db_file[pos++]<<8; | |
a.number |= db_file[pos++]; | |
a.name = malloc(sizeof(char)*(strlen(db_file + pos) + 1)); | |
strcpy(a.name, db_file + pos); | |
pos += strlen(db_file + pos) + 1; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_fakeact; | |
sym->data.fakeact = a; | |
/* debug_add_symbol(a.name, | |
sym); */ | |
} | |
break; | |
case DEBUG_ARRAY_DBR: | |
{ | |
debug_array a; | |
pos++; | |
a.offset = db_file[pos++]<<8; | |
a.offset |= db_file[pos++]; | |
a.name = malloc(sizeof(char)*(strlen(db_file + pos) + 1)); | |
strcpy(a.name, db_file + pos); | |
pos += strlen(db_file + pos) + 1; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_array; | |
sym->data.array = a; | |
debug_add_symbol(a.name, | |
sym); | |
} | |
break; | |
case DEBUG_HEADER_DBR: | |
pos++; | |
pos += 64; | |
break; | |
case DEBUG_LINEREF_DBR: | |
{ | |
debug_line l; | |
int rno; | |
int nseq; | |
int x; | |
pos++; | |
rno = db_file[pos++]<<8; | |
rno |= db_file[pos++]; | |
nseq = db_file[pos++]<<8; | |
nseq |= db_file[pos++]; | |
if (rno != this_routine->number) | |
{ | |
display_printf("=! routine number of line does not match current routine\n"); | |
goto failed; | |
} | |
for (x=0; x<nseq; x++) | |
{ | |
l.fl = db_file[pos++]; | |
l.ln = db_file[pos++]<<8; | |
l.ln |= db_file[pos++]; | |
l.ch = db_file[pos++]; | |
l.address = db_file[pos++]<<8; | |
l.address |= db_file[pos++]; | |
l.address += this_routine->start; | |
this_routine->line = realloc(this_routine->line, | |
sizeof(debug_line)*(this_routine->nlines+1)); | |
this_routine->line[this_routine->nlines] = l; | |
this_routine->nlines++; | |
} | |
} | |
break; | |
case DEBUG_ROUTINE_DBR: | |
{ | |
debug_routine r; | |
pos++; | |
r.number = db_file[pos++]<<8; | |
r.number |= db_file[pos++]; | |
r.defn_fl = db_file[pos++]; | |
r.defn_ln = db_file[pos++]<<8; | |
r.defn_ln |= db_file[pos++]; | |
r.defn_ch = db_file[pos++]; | |
r.start = db_file[pos++]<<16; | |
r.start |= db_file[pos++]<<8; | |
r.start |= db_file[pos++]; | |
r.name = malloc(sizeof(char)*(strlen(db_file+pos) + 1)); | |
strcpy(r.name, db_file + pos); | |
pos += strlen(r.name)+1; | |
r.nvars = 0; | |
r.var = NULL; | |
while (db_file[pos] != 0) | |
{ | |
r.var = realloc(r.var, sizeof(char*)*(r.nvars+1)); | |
r.var[r.nvars] = malloc(sizeof(char)*(strlen(db_file+pos) + 1)); | |
strcpy(r.var[r.nvars], db_file+pos); | |
pos += strlen(r.var[r.nvars]) + 1; | |
r.nvars++; | |
} | |
pos++; | |
r.nlines = 0; | |
r.line = NULL; | |
if (this_routine != NULL && | |
this_routine->start >= r.start) | |
{ | |
display_printf("=! Out of order routines\n"); | |
} | |
debug_syms.routine = realloc(debug_syms.routine, | |
sizeof(debug_routine)* | |
(debug_syms.nroutines+1)); | |
debug_syms.routine[debug_syms.nroutines] = r; | |
this_routine = debug_syms.routine + debug_syms.nroutines; | |
debug_syms.nroutines++; | |
sym = malloc(sizeof(debug_symbol)); | |
sym->type = dbg_routine; | |
sym->data.routine = debug_syms.nroutines-1; | |
debug_add_symbol(this_routine->name, | |
sym); | |
} | |
break; | |
case DEBUG_ROUTINE_END_DBR: | |
{ | |
int rno; | |
pos++; | |
rno = db_file[pos++]<<8; | |
rno |= db_file[pos++]; | |
if (rno != this_routine->number) | |
{ | |
display_printf("=! routine number of EOR does not match current routine\n"); | |
goto failed; | |
} | |
this_routine->end_fl = db_file[pos++]; | |
this_routine->end_ln = db_file[pos++]<<8; | |
this_routine->end_ln |= db_file[pos++]; | |
this_routine->end_ch = db_file[pos++]; | |
this_routine->end = db_file[pos++]<<16; | |
this_routine->end |= db_file[pos++]<<8; | |
this_routine->end |= db_file[pos++]; | |
} | |
break; | |
case DEBUG_MAP_DBR: | |
{ | |
pos++; | |
while (db_file[pos] != 0) | |
{ | |
char* name; | |
ZDWord address; | |
name = db_file + pos; | |
pos += strlen(db_file + pos) + 1; | |
address = db_file[pos++]<<16; | |
address |= db_file[pos++]<<8; | |
address |= db_file[pos++]; | |
/* Fill in various fields according to what we get... */ | |
if (strcmp(name, "code area") == 0) | |
{ | |
debug_syms.codearea = address; | |
} else if (strcmp(name, "strings area") == 0) { | |
debug_syms.stringarea = address; | |
} | |
} | |
pos++; | |
} | |
break; | |
default: | |
display_printf("=! unknown record type %i\n", db_file[pos]); | |
goto failed; | |
return; | |
} | |
} | |
/* Update addresses of routines/lines */ | |
for (x=0; x<debug_syms.nroutines; x++) | |
{ | |
int y; | |
debug_syms.routine[x].start += debug_syms.codearea; | |
debug_syms.routine[x].end += debug_syms.codearea; | |
for (y=0; y<debug_syms.routine[x].nlines; y++) | |
{ | |
debug_syms.routine[x].line[y].address += debug_syms.codearea; | |
} | |
} | |
free(db_file); | |
return; | |
failed: | |
free(db_file); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment