WadObjectFile * wad_object_load(const char *path) { WadObjectFile *wo; WadFile *wf; WadObjectFile *wad_arobject_load(const char *path, const char *name); if (wad_debug_mode & DEBUG_OBJECT) { wad_printf("wad: Loading object '%s'", path); } for (wo = wad_objects; wo; wo=wo->next) { if (strcmp(wo->path,path) == 0) { if (wad_debug_mode & DEBUG_OBJECT) { wad_printf(" (cached)\n"); } return wo; } } if (wad_debug_mode & DEBUG_OBJECT) { wad_printf("\n"); } /* Didn't find it. Now we need to go load some files */ /* If this is an archive reference like /path/libfoo.a(blah.o), we need to split up the name a little bit */ { char realfile[MAX_PATH]; char *objfile; char *c; c = strchr(path,'('); if (c) { wad_strcpy(realfile,path); c = strchr(realfile,'('); *c = 0; objfile = c+1; c = strchr(objfile,')'); *c = 0; /* Okay, I'm going to attempt to map this as a library file */ wo = wad_arobject_load(realfile,objfile); if (wo) { /* Reset the path */ wo->path = wad_strdup(path); wo->next = wad_objects; wad_objects = wo; return wo; } } } wf = load_file(path); if (!wf) return 0; wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile)); wo->path = wad_strdup(path); wo->ptr = wf->addr; wo->len = wf->size; wo->next = wad_objects; wad_objects = wo; return wo; }
static int segment_read(int fd, WadSegment *s) { char pbuffer[1024]; char *c; int len; FILE *fs = (FILE *) fd; c = fgets(pbuffer,1024,fs); if (!c) return 0; pbuffer[strlen(pbuffer)-1] = 0; /* Chop off endline */ /* Break up the field into records */ /* 0-8 : Starting address 9-17 : Ending Address 18 : r 19 : w 20 : x 21 : p 23-31 : Offset 49- : Filename */ len = strlen(pbuffer); pbuffer[8] = 0; pbuffer[17] = 0; pbuffer[31] = 0; if (len >= 49) { s->mapname = wad_strdup(pbuffer+49); s->mappath = s->mapname; } else { s->mapname = ""; s->mappath = s->mapname; } if (linux_first) { wad_strcpy(linux_firstsegment, s->mappath); linux_first = 0; } s->vaddr = (char *) strtoul(pbuffer,NULL,16); s->size = strtoul(pbuffer+9,NULL,16) - (long) (s->vaddr); s->offset = strtoul(pbuffer+23,NULL,16); if (strcmp(linux_firstsegment, s->mappath) == 0) { s->base = 0; } else { s->base = s->vaddr; } s++; return 1; }
static void stab_symbol(Stab *s, char *stabstr) { char *str; char *pstr; char name[1024]; char value[65536]; str = stabstr+s->n_strx; pstr = stab_string_parm(str); if (!pstr) return; strncpy(name,str, pstr-str); name[(int)(pstr-str)] = 0; if ((pstr[1] == 't') || (pstr[1] == 'p') || (pstr[1] == 'r')) { /* A stabs type definition */ /* printf("stab lsym: other=%d, desc=%d, value=%d, str='%s'\n", s->n_other,s->n_desc,s->n_value, stabstr+s->n_strx); */ /* wad_printf("name = '%s', pstr='%s'\n", name, pstr+2); */ wad_strcpy(value,pstr+2); type_add(name,value); } }
static int segment_read(int fs, WadSegment *s) { int dz; int n; prmap_t pmap; n = read(fs, &pmap, sizeof(prmap_t)); if (n <= 0) return 0; s->mapname = wad_strdup(pmap.pr_mapname); s->mappath = (char *) wad_malloc(20+strlen(pmap.pr_mapname)); wad_strcpy(s->mappath,"/proc/self/object/"); strcat(s->mappath,pmap.pr_mapname); s->vaddr = (char *) pmap.pr_vaddr; /* This is a solaris oddity. a.out section starts 1 page up, but symbols are relative to a base of 0 */ if (strcmp(s->mapname,"a.out") == 0) s->base = 0; else s->base = s->vaddr; s->size = pmap.pr_size; s->offset = pmap.pr_offset; return 1; }
int wad_search_stab(void *sp, int size, char *stabstr, WadFrame *f) { Stab *s; int ns; int i; int found = 0; char *file, *lastfile = 0; char srcfile[MAX_PATH]; char objfile[MAX_PATH]; /* It appears to be necessary to clear the types table on each new stabs section */ init_hash(); if (!f->sym_name) return 0; s = (Stab *) sp; /* Stabs data */ ns = size/sizeof(Stab); /* number of stabs */ 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_LSYM) { stab_symbol(s,stabstr); continue; } 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] == '/')) { wad_strcpy(srcfile,file); } else { wad_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]) { wad_strcat(objfile,"/"); } wad_strcat(objfile,stabstr+s->n_strx); } else if (s->n_type == N_FUN) { if (match_stab_symbol(f->sym_name, stabstr+s->n_strx, f->sym_nlen)) { if (!f->sym_file || (strcmp(f->sym_file,lastfile) == 0)) { int n; /* Go find debugging information for the function */ n = scan_function(s+1, stabstr, ns -i - 1, f); f->loc_srcfile = wad_string_lookup(srcfile); f->loc_objfile = wad_string_lookup(objfile); return 1; } } } } /* If found, but no other debugging information was filled in, go ahead and copy the source and objfile information */ if ((found) && (!f->debug_check)) { f->loc_srcfile = wad_string_lookup(srcfile); f->loc_objfile = wad_string_lookup(objfile); } return found; }
int wad_elf_debug_info(WadFrame *f) { int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr; int ret; void *stab; char *stabstr; int stabsize; nstab = wad_elf_section_byname(f->object,".stab"); nstabstr = wad_elf_section_byname(f->object,".stabstr"); nstabindex = wad_elf_section_byname(f->object,".stab.index"); nstabindexstr = wad_elf_section_byname(f->object,".stab.indexstr"); nstabexcl = wad_elf_section_byname(f->object,".stab.excl"); nstabexclstr = wad_elf_section_byname(f->object,".stab.exclstr"); #ifdef DEBUG_DEBUG wad_printf("nstab = %d\n", nstab); wad_printf("nstabstr = %d\n", nstabstr); wad_printf("nstabindex = %d\n", nstabindex); wad_printf("nstabindexstr = %d\n", nstabindexstr); wad_printf("nstabexcl = %d\n", nstabexcl); wad_printf("nstabexclstr = %d\n", nstabexclstr); #endif /* Now start searching stabs */ /* Look in the .stab section */ if (nstab > 0) { stab = wad_elf_section_data(f->object,nstab); stabsize = wad_elf_section_size(f->object,nstab); stabstr = (char *) wad_elf_section_data(f->object,nstabstr); if (wad_search_stab(stab,stabsize,stabstr, f)) return 1; } /* Look in the .stab.excl section. A solaris oddity? */ if (nstabexcl > 0) { stab = wad_elf_section_data(f->object,nstabexcl); stabsize = wad_elf_section_size(f->object, nstabexcl); stabstr = (char *) wad_elf_section_data(f->object, nstabexclstr); if (wad_search_stab(stab,stabsize,stabstr, f)) return 1; } /* Look in the .stab.index section. A Solaris oddity? */ if (nstabindex > 0) { stab = wad_elf_section_data(f->object,nstabindex); stabsize = wad_elf_section_size(f->object, nstabindex); stabstr = (char *) wad_elf_section_data(f->object, nstabindexstr); if (wad_search_stab(stab,stabsize,stabstr, f)) { /* Hmmm. Might be in a different file */ WadObjectFile *wo1, *wold; char objfile[MAX_PATH]; /* printf("DEBUG %s\n", f->sym_name); */ wad_strcpy(objfile, f->loc_objfile); wo1 = wad_object_load(objfile); if (wo1) { wold = f->object; f->object = wo1; wad_find_debug(f); f->object = wold; return ret; } else { /* wad_printf("couldn't load %s\n", objfile); */ } /* if (!ret) return wad_search_stab(stab,stabsize,stabstr,f);*/ return ret; } } return 0; }
WadObjectFile * wad_arobject_load(const char *arpath, const char *robjname) { WadObjectFile *wo; WadFile *wf; int arlen; char *arptr; struct ar_hdr *ah; int offset; int msize; char *strtab = 0; int sobjname; char objname[MAX_PATH]; wad_strcpy(objname,robjname); wad_strcat(objname,"/"); sobjname = strlen(objname); wf = load_file(arpath); if (!wf) return 0; /* Doesn't exit */ arptr = (char *) wf->addr; arlen = wf->size; /* Now take a look at the archive */ if (strncmp(arptr,ARMAG,SARMAG) == 0) { /* printf("Got an archive\n"); */ } else { return 0; } /* Search the archive for the request member */ strtab = 0; offset = SARMAG; while (offset < arlen) { char mname[MAX_PATH]; ah = (struct ar_hdr *) (arptr + offset); if (strncmp(ah->ar_name,"// ", 3) == 0) { strtab = arptr + offset + sizeof(struct ar_hdr); } msize = atoi(ah->ar_size); offset += sizeof(struct ar_hdr); /* Try to figure out the filename */ if ((ah->ar_name[0] == '/') && (isdigit(ah->ar_name[1]))) { int soff; char *e; /* Must be in the string offset table */ soff = atoi(ah->ar_name+1); if (!strtab) { /* No offset table */ return 0; } e = strchr(strtab+soff,'\n'); if (e) { strncpy(mname, strtab+soff, (e - (strtab+soff))); mname[e-(strtab+soff)] = 0; } else { mname[0] = 0; } } else { /* Name must be in the name field */ strncpy(mname,ah->ar_name,16); mname[16] = 0; } /* Compare the names */ if (strncmp(mname,objname,sobjname) == 0) { /* Found the archive */ wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile)); wo->ptr = (void *) (arptr + offset); wo->len = msize; wo->path = 0; return wo; } offset += msize; } return 0; }
/* Try to make a formatted version of a local */ char *wad_format_var(WadLocal *l) { static char hexdigits[] = "0123456789abcdef"; static char buffer[1024]; double dval; float fval; buffer[0] = 0; switch(l->type) { case WAD_TYPE_INT32: wad_strcpy(buffer,wad_format_int(l->ptr,4,1)); break; case WAD_TYPE_UINT32: wad_strcpy(buffer,wad_format_int(l->ptr,4,0)); break; case WAD_TYPE_INT16: wad_strcpy(buffer,wad_format_int(l->ptr,2,1)); break; case WAD_TYPE_UINT16: wad_strcpy(buffer,wad_format_int(l->ptr,2,0)); break; case WAD_TYPE_INT8: wad_strcpy(buffer,wad_format_int(l->ptr,1,1)); break; case WAD_TYPE_UINT8: wad_strcpy(buffer,wad_format_int(l->ptr,1,0)); break; case WAD_TYPE_CHAR: buffer[0] = '\''; buffer[1] = *((char *) l->ptr); buffer[2] = '\''; buffer[3] = 0; break; case WAD_TYPE_FLOAT: wad_memcpy(&fval,l->ptr,sizeof(float)); sprintf(buffer,"%g",fval); break; case WAD_TYPE_DOUBLE: wad_memcpy(&dval,l->ptr,sizeof(double)); sprintf(buffer,"%g",dval); break; case WAD_TYPE_UNKNOWN: case WAD_TYPE_POINTER: default: /* Hmmm. Unknown data type. We'll just treat it as a word */ if (l->ptr) { int incr,i; int b; int leading = 1; char *c; char *ptr; #ifdef WAD_LITTLE_ENDIAN ptr = ((char *) l->ptr) + 3; incr = -1; #else ptr = (char *) l->ptr; incr =1 ; #endif wad_strcat(buffer,"0x"); c = buffer+2; for (i = 0; i < sizeof(void *); i++) { b = (int) *ptr; if (!leading || (b)) { if (!leading || (b & 0xf0)) *(c++) = hexdigits[(b & 0xf0) >> 4]; *(c++) = hexdigits[(b & 0xf)]; leading = 0; } ptr += incr; } if (leading) *(c++) = '0'; *c = 0; } }