swig/SWIG/Tools/WAD/Wad/stab.c
Dave Beazley 11790dbca8 *** empty log message ***
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@1012 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2001-02-01 13:34:18 +00:00

254 lines
7.7 KiB
C

/* -----------------------------------------------------------------------------
* stab.c
*
* This file reads stabs data and looks for various properties of a
* given symbol.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#include "wad.h"
/* stabs data structure. This appears to be somewhat universal. */
typedef struct Stab {
unsigned n_strx; /* index into file string table */
unsigned char n_type; /* type flag (N_TEXT,..) */
char n_other; /* used by N_SLINE stab */
unsigned short n_desc; /* see stabs documentation */
unsigned n_value; /* value of symbol (or sdb offset) */
} Stab;
/* stabs data types used by this module */
#define N_UNDF 0x0 /* undefined */
#define N_FUN 0x24 /* function */
#define N_OBJ 0x38 /* object file path */
#define N_RSYM 0x40 /* Register symbol */
#define N_SLINE 0x44 /* Source line */
#define N_SO 0x64 /* Source file name */
#define N_PSYM 0xa0 /* Parameter */
/* -----------------------------------------------------------------------------
* match_stab_symbol()
*
* Match a stabs symbol name against a stab string. The stab string may contain
* extra information delimited by a colon which is not used in the comparsion.
* Returns 1 on match, 0 on mismatch.
* ----------------------------------------------------------------------------- */
static int
match_stab_symbol(char *symbol, char *stabtext, int slen) {
if (strcmp(symbol,stabtext) == 0) {
return 1;
}
if ((strncmp(symbol, stabtext, slen) == 0) && (*(stabtext+slen) == ':')) return 1;
return 0;
}
/* -----------------------------------------------------------------------------
* scan_function()
*
* Collect stabs data for a function definition.
* ----------------------------------------------------------------------------- */
static void
scan_function(Stab *s, char *stabstr, int ns, WadFrame *f) {
int i;
unsigned long offset;
offset = f->pc - f->sym_base;
for (i = 0; i < ns; i++,s++) {
if (wad_debug_mode & DEBUG_STABS) {
wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
stabstr+s->n_strx);
}
if ((s->n_type == N_UNDF) || (s->n_type == N_SO) || (s->n_type == N_FUN) ||
(s->n_type == N_OBJ)) return;
if (s->n_type == N_SLINE) {
if (s->n_value < offset) {
f->loc_line = s->n_desc;
}
} else if ((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) {
/* Parameter counting */
char *pname;
char *c;
int len;
WadLocal *arg;
pname = stabstr+s->n_strx;
c = strchr(pname,':');
if (c) {
len = (c-pname);
} else {
len = strlen(pname);
}
/* Check if the argument was already used */
/* In this case, the first stab simply identifies an argument. The second
one identifies its location for the debugger */
if (f->debug_args) {
/* Need to do some fix up for linux here */
WadLocal *a = f->debug_args;
while (a) {
if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
/* We already saw this argument. Given a choice between a register and a stack
argument. We will choose the stack version */
if (a->loc == PARM_STACK) {
break;
}
/* Go ahead and use the new argument */
if (s->n_type == N_RSYM) {
a->loc = PARM_REGISTER;
a->reg = s->n_value;
} else {
a->loc = PARM_STACK;
a->stack = s->n_value;
}
break;
}
a = a->next;
}
if (a) continue; /* We got an argument match. Just skip to the next stab */
}
arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
arg->name = (char *) wad_malloc(len+1);
strncpy(arg->name, pname, len);
arg->name[len] = 0;
if (s->n_type == N_RSYM) {
arg->loc = PARM_REGISTER;
arg->reg = s->n_value;
arg->stack = 0;
} else {
arg->loc = PARM_STACK;
arg->line = s->n_desc;
arg->stack = s->n_value;
}
arg->type = 0;
arg->next = 0;
if (f->debug_args) {
f->debug_lastarg->next = arg;
f->debug_lastarg = arg;
} else {
f->debug_args = arg;
f->debug_lastarg = arg;
f->debug_nargs= 0;
}
f->debug_nargs++;
}
}
}
/* Given a stabs data segment (obtained somehow), this function tries to
collect as much information as it can about a given symbol.
s points to the stab data. stabstr points to the stab string section,
ns is the size of the stab section, symbol is the item of interest,
and offset is the offset in the object file of the symbol
Note: this function may recurse upon itself if there are multiple
stabs sections.
Note: If a symbol corresponds to a local symbol, it's entirely possible
that the only stabs data we will find is a file specifier. In this case,
*/
int
wad_search_stab(void *sp, int size, char *stabstr, WadFrame *f) {
Stab *s;
int ns;
int infunc;
int slen;
int i;
int found = 0;
char *file, *lastfile = 0;
int chk = 0;
WadLocal *arg;
char srcfile[MAX_PATH];
char objfile[MAX_PATH];
if (!f->sym_name) return 0;
s = (Stab *) sp; /* Stabs data */
ns = size/sizeof(Stab); /* number of stabs */
slen = strlen(f->sym_name);
srcfile[0] = 0;
objfile[0] = 0;
for (i = 0; i < ns; i++, s++) {
/*
if (wad_debug_mode & DEBUG_STABS) {
wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
stabstr+s->n_strx);
}
*/
if ((s->n_type == N_UNDF)) { /* && (s->n_desc >= 0)) { */
/* New stabs section. We need to be a little careful here. Do a recursive
search of the subsection. */
if (wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, f)) return 1;
/* On solaris, each stabs section seems to increment the stab string pointer. On Linux,
the linker seems to do a certain amount of optimization that results in a single
string table. */
#ifdef WAD_SOLARIS
stabstr += s->n_value; /* Update the string table location*/
#endif
i += s->n_desc;
s += s->n_desc;
objfile[0] = 0;
srcfile[0] = 0;
continue;
} else if (s->n_type == N_SO) {
/* Source file specification */
/* Look for directory */
file = stabstr+s->n_strx;
if (strlen(file) && (file[strlen(file)-1] == '/')) {
strcpy(srcfile,file);
} else {
strcat(srcfile,file);
}
objfile[0] = 0;
/* If we have a file match, we might be looking for a local symbol. If so,
we'll go ahead and set the srcfile field of the frame */
/* We're going to check for a file match. Maybe we're looking for a local symbol */
if (f->sym_file && strcmp(f->sym_file,file) == 0) {
found = 1;
}
lastfile = file;
} else if (s->n_type == N_OBJ) {
/* Object file specifier */
if (objfile[0]) {
strcat(objfile,"/");
}
strcat(objfile,stabstr+s->n_strx);
} else if (s->n_type == N_FUN) {
if (match_stab_symbol(f->sym_name, stabstr+s->n_strx, slen)) {
if (!f->sym_file || (strcmp(f->sym_file,lastfile) == 0)) {
/* Go find debugging information for the function */
scan_function(s+1, stabstr, ns -i - 1, f);
f->loc_srcfile = wad_strdup(srcfile);
f->loc_objfile = wad_strdup(objfile);
return 1;
}
}
}
}
if (found) {
f->loc_srcfile = wad_strdup(srcfile);
f->loc_objfile = wad_strdup(objfile);
}
return found;
}