Initial revision
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@931 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
70567cf21d
commit
2659475432
14 changed files with 1556 additions and 0 deletions
104
Tools/WAD/Include/wad.h
Normal file
104
Tools/WAD/Include/wad.h
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad.h
|
||||||
|
*
|
||||||
|
* WAD header file (obviously)
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifndef MAX_PATH
|
||||||
|
#define MAX_PATH 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Typedef's for various addresses and sizes */
|
||||||
|
typedef char * wadaddr_t;
|
||||||
|
typedef unsigned long wadlen_t;
|
||||||
|
|
||||||
|
/* Memory management */
|
||||||
|
extern void *wadmalloc(unsigned int);
|
||||||
|
extern void wadfree(void *ptr);
|
||||||
|
|
||||||
|
typedef struct WadSegment {
|
||||||
|
wadaddr_t vaddr; /* Virtual address start */
|
||||||
|
wadlen_t size; /* Size of the segment (bytes) */
|
||||||
|
int flags; /* Memory access permissions */
|
||||||
|
wadlen_t offset; /* Offset into mapped object */
|
||||||
|
char mapname[MAX_PATH]; /* Filename mapped to this region */
|
||||||
|
char mappath[MAX_PATH]; /* Full path to mapname */
|
||||||
|
int identifier; /* identifier (if SysV shmem) */
|
||||||
|
long wad; /* Private wad data (if any) */
|
||||||
|
} WadSegment;
|
||||||
|
|
||||||
|
extern void wad_segment_print(WadSegment *s);
|
||||||
|
extern WadSegment *wad_segment_find(wadaddr_t addr);
|
||||||
|
extern WadSegment *wad_segment_first();
|
||||||
|
extern WadSegment *wad_segment_next();
|
||||||
|
|
||||||
|
/* Structure for managing object files */
|
||||||
|
typedef struct WadObject {
|
||||||
|
void *mptr; /* mmap'd pointer */
|
||||||
|
int mlen; /* mmap'd length */
|
||||||
|
void *ptr; /* Pointer to real data */
|
||||||
|
int len; /* Length of real data */
|
||||||
|
int refcnt; /* Reference count */
|
||||||
|
int type; /* Type of the object file */
|
||||||
|
char path[MAX_PATH]; /* Path name of this object */
|
||||||
|
} WadObject;
|
||||||
|
|
||||||
|
extern char *wad_find_symbol(WadObject *wo, void *ptr, unsigned base, unsigned long *value);
|
||||||
|
|
||||||
|
/* Maximum number of object files that can be simultaneously loaded into memory */
|
||||||
|
#define WAD_MAX_OBJECT 32
|
||||||
|
|
||||||
|
extern WadObject *wad_object_load(const char *path);
|
||||||
|
extern WadObject *wad_arobject_load(const char *path, const char *name);
|
||||||
|
extern void wad_object_release(WadObject *);
|
||||||
|
|
||||||
|
extern void wad_init();
|
||||||
|
extern void wad_signalhandler(int, siginfo_t *, void *);
|
||||||
|
extern void wad_set_return(char *name, long value);
|
||||||
|
extern int wad_elf_check(WadObject *wo);
|
||||||
|
extern void wad_elf_debug(WadObject *wo);
|
||||||
|
|
||||||
|
/* Debugging information */
|
||||||
|
typedef struct WadDebug {
|
||||||
|
int found; /* Whether or not debugging information was found */
|
||||||
|
char srcfile[1024]; /* Source file */
|
||||||
|
char objfile[1024]; /* Object file */
|
||||||
|
int line_number; /* Line number */
|
||||||
|
int nargs; /* Number of function arguments */
|
||||||
|
} WadDebug;
|
||||||
|
|
||||||
|
extern WadDebug *wad_search_stab(void *stab, int size, char *stabstr, char *symbol, unsigned long offset);
|
||||||
|
extern WadDebug *wad_debug_info(WadObject *wo, char *symbol, unsigned long offset);
|
||||||
|
|
||||||
|
/* This data structure is used to report exception data back to handler functions
|
||||||
|
The offset fields contain offsets from the start of the frame to a location in
|
||||||
|
the data segment */
|
||||||
|
|
||||||
|
typedef struct WadFrame {
|
||||||
|
long size; /* Frame size */
|
||||||
|
long frameno; /* Frame number */
|
||||||
|
long pc; /* Program counter */
|
||||||
|
long sp; /* Stack pointer */
|
||||||
|
long fp; /* Frame pointer */
|
||||||
|
long line_number; /* Source line number */
|
||||||
|
long sym_base; /* Symbol base address */
|
||||||
|
long sym_off; /* Symbol name offset */
|
||||||
|
long src_off; /* Source filename offset */
|
||||||
|
long obj_off; /* Object filename offset */
|
||||||
|
char data[8]; /* Frame data */
|
||||||
|
} WadFrame;
|
||||||
|
|
||||||
|
|
||||||
26
Tools/WAD/Makefile
Normal file
26
Tools/WAD/Makefile
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
SRCS = stab.c elf.c object.c init.c segment.c signal.c
|
||||||
|
OBJS = stab.o elf.o object.o signal.o segment.o init.o main.o
|
||||||
|
|
||||||
|
all::
|
||||||
|
CC -Kpic -c main.cxx
|
||||||
|
cc -c $(SRCS)
|
||||||
|
CC -G $(OBJS) -o libwad.so
|
||||||
|
|
||||||
|
swig::
|
||||||
|
swig -python wad.i
|
||||||
|
CC -Kpic -c main.cxx
|
||||||
|
cc -c $(SRCS) wad_wrap.c -I/usr/local/include/python1.6
|
||||||
|
CC -G $(OBJS) wad_wrap.o -o wadmodule.so
|
||||||
|
|
||||||
|
|
||||||
|
some::
|
||||||
|
cc -g bar.c blah.c -L. -lwad -R /u0/beazley/Projects/WAD -lelf
|
||||||
|
|
||||||
|
wc::
|
||||||
|
wc $(SRCS)
|
||||||
|
|
||||||
|
semi::
|
||||||
|
egrep ";" $(SRCS) | wc
|
||||||
|
|
||||||
|
|
||||||
13
Tools/WAD/Misc/fileheader
Normal file
13
Tools/WAD/Misc/fileheader
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* segment.c
|
||||||
|
*
|
||||||
|
* This file provides access to the virtual memory map of a process
|
||||||
|
* including the location of the executable, data segments, shared
|
||||||
|
* libraries, and memory mapped regions. This information is
|
||||||
|
* obtained through /proc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
58
Tools/WAD/Python/wad.i
Normal file
58
Tools/WAD/Python/wad.i
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
%module wad
|
||||||
|
%{
|
||||||
|
#include "wad.h"
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
extern jmp_buf Py_cerror;
|
||||||
|
extern PyObject *Py_cerror_obj;
|
||||||
|
|
||||||
|
static PyObject *segfault_exc = 0;
|
||||||
|
static PyObject *buserror_exc = 0;
|
||||||
|
static PyObject *abort_exc = 0;
|
||||||
|
|
||||||
|
/* Handler function */
|
||||||
|
static void handler(int signo, void *clientdata) {
|
||||||
|
static char message[65536];
|
||||||
|
int len = 0;
|
||||||
|
PyObject *type;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
strcpy(message,"[ C stack trace ]\n\n");
|
||||||
|
switch(signo) {
|
||||||
|
case SIGSEGV:
|
||||||
|
type = segfault_exc;
|
||||||
|
break;
|
||||||
|
case SIGBUS:
|
||||||
|
type = buserror_exc;
|
||||||
|
break;
|
||||||
|
case SIGABRT:
|
||||||
|
type = abort_exc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = PyExc_RuntimeError;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PyErr_SetString(type, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
%init %{
|
||||||
|
wad_set_callback(handler);
|
||||||
|
|
||||||
|
wad_set_return("call_builtin", 0);
|
||||||
|
|
||||||
|
segfault_exc = PyErr_NewException("exceptions.SegFault", NULL, NULL);
|
||||||
|
PyDict_SetItemString(d,"SegFault",segfault_exc);
|
||||||
|
|
||||||
|
buserror_exc = PyErr_NewException("exceptions.BusError", NULL, NULL);
|
||||||
|
PyDict_SetItemString(d,"BusError",buserror_exc);
|
||||||
|
|
||||||
|
abort_exc = PyErr_NewException("exceptions.AbortError", NULL, NULL);
|
||||||
|
PyDict_SetItemString(d,"AbortError",abort_exc);
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
11
Tools/WAD/README
Normal file
11
Tools/WAD/README
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
WAD (Wrapped Application Debugger)
|
||||||
|
|
||||||
|
David M. Beazley
|
||||||
|
Department of Computer Science
|
||||||
|
University of Chicago
|
||||||
|
Chicago, IL 60637
|
||||||
|
beazley@cs.uchicago.edu
|
||||||
|
|
||||||
|
Copyright (C) 2000
|
||||||
|
University of Chicago
|
||||||
|
All Rights Reserved
|
||||||
21
Tools/WAD/Wad/Makefile
Normal file
21
Tools/WAD/Wad/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
SRCS = stab.c elf.c object.c init.c segment.c signal.c
|
||||||
|
OBJS = stab.o elf.o object.o signal.o segment.o init.o main.o
|
||||||
|
INCLUDE = -I../Include
|
||||||
|
|
||||||
|
all::
|
||||||
|
CC -Kpic -c $(INCLUDE) main.cxx
|
||||||
|
cc -c $(INCLUDE) $(SRCS)
|
||||||
|
CC -G $(OBJS) -o libwad.so
|
||||||
|
cp libwad.so ..
|
||||||
|
|
||||||
|
wc::
|
||||||
|
wc $(SRCS)
|
||||||
|
|
||||||
|
semi::
|
||||||
|
egrep ";" $(SRCS) | wc
|
||||||
|
|
||||||
|
|
||||||
|
clean::
|
||||||
|
rm -f *.o *.so *~
|
||||||
|
|
||||||
355
Tools/WAD/Wad/elf.c
Normal file
355
Tools/WAD/Wad/elf.c
Normal file
|
|
@ -0,0 +1,355 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* elf.c
|
||||||
|
*
|
||||||
|
* ELF file management. This file contains functions for accessing ELF
|
||||||
|
* file data from a raw memory mapped ELF file (as performed by the
|
||||||
|
* functions in object.c).
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include <sys/elf.h>
|
||||||
|
|
||||||
|
/* --- What's needed here (high level interface) :
|
||||||
|
|
||||||
|
- Mapping of addresses to symbols
|
||||||
|
- Mapping of symbols to file+line
|
||||||
|
- Parameter passing information?
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_check()
|
||||||
|
*
|
||||||
|
* Checks to see if an object file is an ELF file. Returns 1 on success and
|
||||||
|
* changes the type flag of wo to indicate the type of ELF file.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int
|
||||||
|
wad_elf_check(WadObject *wo) {
|
||||||
|
int t;
|
||||||
|
|
||||||
|
if (strncmp((char *)wo->ptr,ELFMAG, SELFMAG) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Probably need to put some kind of 32/64 bit check here */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_phdrcnt()
|
||||||
|
*
|
||||||
|
* Return number of entries in the ELF program header section
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int
|
||||||
|
wad_elf_phdrcnt(WadObject *wo) {
|
||||||
|
Elf32_Ehdr *eh;
|
||||||
|
|
||||||
|
eh = (Elf32_Ehdr *) wo->ptr;
|
||||||
|
return eh->e_phnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_phdrpos()
|
||||||
|
*
|
||||||
|
* Return the location of the ELF program header.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void *
|
||||||
|
wad_elf_phdrpos(WadObject *wo) {
|
||||||
|
Elf32_Ehdr *eh;
|
||||||
|
char *c;
|
||||||
|
eh = (Elf32_Ehdr *) wo->ptr;
|
||||||
|
c = (char *) wo->ptr;
|
||||||
|
return (void *) (c+eh->e_phoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_shdrcnt()
|
||||||
|
*
|
||||||
|
* Return number of entries in the ELF section header
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int
|
||||||
|
wad_elf_shdrcnt(WadObject *wo) {
|
||||||
|
Elf32_Ehdr *eh;
|
||||||
|
|
||||||
|
eh = (Elf32_Ehdr *) wo->ptr;
|
||||||
|
return eh->e_shnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_shdrpos()
|
||||||
|
*
|
||||||
|
* Return the location of the section headers
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void *
|
||||||
|
wad_elf_shdrpos(WadObject *wo) {
|
||||||
|
Elf32_Ehdr *eh;
|
||||||
|
char *c;
|
||||||
|
eh = (Elf32_Ehdr *) wo->ptr;
|
||||||
|
c = (char *) wo->ptr;
|
||||||
|
return (void *) (c+eh->e_shoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_section_header()
|
||||||
|
*
|
||||||
|
* Get a specific section number
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void *wad_elf_section_header(WadObject *wo, int sn) {
|
||||||
|
Elf32_Ehdr *eh;
|
||||||
|
char *r;
|
||||||
|
|
||||||
|
eh = (Elf32_Ehdr *) wo->ptr;
|
||||||
|
if ((sn < 0) || (sn >= eh->e_shnum)) return 0;
|
||||||
|
|
||||||
|
r = (char *) wad_elf_shdrpos(wo) + (sn*eh->e_shentsize);
|
||||||
|
return (void *) r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_section_data()
|
||||||
|
*
|
||||||
|
* Get section data
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void *wad_elf_section_data(WadObject *wo, int sn) {
|
||||||
|
Elf32_Shdr *sh;
|
||||||
|
char *r;
|
||||||
|
|
||||||
|
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||||
|
if (!sh) return 0;
|
||||||
|
|
||||||
|
r = ((char *) wo->ptr) + sh->sh_offset;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_section_size()
|
||||||
|
* Return section size
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int wad_elf_section_size(WadObject *wo, int sn) {
|
||||||
|
Elf32_Shdr *sh;
|
||||||
|
|
||||||
|
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||||
|
if (!sh) return -1;
|
||||||
|
return sh->sh_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_section_name()
|
||||||
|
*
|
||||||
|
* Returns the name of an ELF section
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
char *wad_elf_section_name(WadObject *wo, int sn) {
|
||||||
|
Elf32_Ehdr *eh;
|
||||||
|
Elf32_Shdr *sh;
|
||||||
|
char *sectionstr;
|
||||||
|
|
||||||
|
eh = (Elf32_Ehdr *) wo->ptr;
|
||||||
|
|
||||||
|
/* Get the string table */
|
||||||
|
sectionstr = (char *) wad_elf_section_data(wo,eh->e_shstrndx);
|
||||||
|
if (!sectionstr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the section header for the section */
|
||||||
|
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||||
|
if (!sh) return 0;
|
||||||
|
return sectionstr + sh->sh_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_section_byname()
|
||||||
|
*
|
||||||
|
* Get section data given a section name
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int
|
||||||
|
wad_elf_section_byname(WadObject *wo, char *name) {
|
||||||
|
int i;
|
||||||
|
char *sn;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = wad_elf_shdrcnt(wo);
|
||||||
|
for (i = 0; i <n; i++) {
|
||||||
|
sn = wad_elf_section_name(wo,i);
|
||||||
|
if (strcmp(sn,name) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_find_symbol()
|
||||||
|
*
|
||||||
|
* Tries to find the symbol associated with a given address. base is the
|
||||||
|
* base address of the object file.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
wad_elf_find_symbol(WadObject *wo, void *ptr, unsigned base, unsigned long *value) {
|
||||||
|
int nsymtab;
|
||||||
|
int nstrtab;
|
||||||
|
int symtab_size;
|
||||||
|
Elf32_Sym *sym;
|
||||||
|
int nsym;
|
||||||
|
char *str;
|
||||||
|
int i;
|
||||||
|
unsigned long vaddr;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
vaddr = (unsigned long) ptr;
|
||||||
|
|
||||||
|
nsymtab = wad_elf_section_byname(wo,".symtab");
|
||||||
|
if (nsymtab < 0) return 0;
|
||||||
|
nstrtab = wad_elf_section_byname(wo,".strtab");
|
||||||
|
if (nstrtab < 0) return 0;
|
||||||
|
|
||||||
|
symtab_size = wad_elf_section_size(wo,nsymtab);
|
||||||
|
sym = (Elf32_Sym *) wad_elf_section_data(wo,nsymtab);
|
||||||
|
str = (char *) wad_elf_section_data(wo,nstrtab);
|
||||||
|
|
||||||
|
nsym = (symtab_size/sizeof(Elf32_Sym));
|
||||||
|
for (i = 0; i < nsym; i++) {
|
||||||
|
name = str + sym[i].st_name;
|
||||||
|
if (((base + sym[i].st_value) <= vaddr) && (vaddr < (base+sym[i].st_value + sym[i].st_size))) {
|
||||||
|
if (value)
|
||||||
|
*value = sym[i].st_value;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/* printf("%s %x\n", name, sym[i].st_value); */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_debug_info()
|
||||||
|
*
|
||||||
|
* Gather debugging information about a function (if possible)
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
WadDebug *
|
||||||
|
wad_elf_debug_info(WadObject *wo, char *symbol, unsigned long offset) {
|
||||||
|
int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr;
|
||||||
|
|
||||||
|
void *stab;
|
||||||
|
char *stabstr;
|
||||||
|
int stabsize;
|
||||||
|
WadDebug *wd;
|
||||||
|
|
||||||
|
nstab = wad_elf_section_byname(wo,".stab");
|
||||||
|
nstabstr = wad_elf_section_byname(wo,".stabstr");
|
||||||
|
nstabindex = wad_elf_section_byname(wo,".stab.index");
|
||||||
|
nstabindexstr = wad_elf_section_byname(wo,".stab.indexstr");
|
||||||
|
nstabexcl = wad_elf_section_byname(wo,".stab.excl");
|
||||||
|
nstabexclstr = wad_elf_section_byname(wo,".stab.exclstr");
|
||||||
|
|
||||||
|
#ifdef DEBUG_DEBUG
|
||||||
|
printf("nstab = %d\n", nstab);
|
||||||
|
printf("nstabstr = %d\n", nstabstr);
|
||||||
|
printf("nstabindex = %d\n", nstabindex);
|
||||||
|
printf("nstabindexstr = %d\n", nstabindexstr);
|
||||||
|
printf("nstabexcl = %d\n", nstabexcl);
|
||||||
|
printf("nstabexclstr = %d\n", nstabexclstr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now start searching stabs */
|
||||||
|
|
||||||
|
/* Look in the .stab section */
|
||||||
|
if (nstab > 0) {
|
||||||
|
stab = wad_elf_section_data(wo,nstab);
|
||||||
|
stabsize = wad_elf_section_size(wo,nstab);
|
||||||
|
stabstr = (char *) wad_elf_section_data(wo,nstabstr);
|
||||||
|
|
||||||
|
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||||
|
if (wd) return wd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look in the .stab.excl section. A solaris oddity? */
|
||||||
|
|
||||||
|
if (nstabexcl > 0) {
|
||||||
|
stab = wad_elf_section_data(wo,nstabexcl);
|
||||||
|
stabsize = wad_elf_section_size(wo, nstabexcl);
|
||||||
|
stabstr = (char *) wad_elf_section_data(wo, nstabexclstr);
|
||||||
|
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||||
|
if (wd) return wd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look in the .stab.index section. Another solaris oddity? */
|
||||||
|
if (nstabindex > 0) {
|
||||||
|
stab = wad_elf_section_data(wo,nstabindex);
|
||||||
|
stabsize = wad_elf_section_size(wo, nstabindex);
|
||||||
|
stabstr = (char *) wad_elf_section_data(wo, nstabindexstr);
|
||||||
|
wd = wad_search_stab(stab,stabsize,stabstr, symbol, offset);
|
||||||
|
if (wd) {
|
||||||
|
WadObject *wo1;
|
||||||
|
/* Hmmm. Might be in a different file */
|
||||||
|
char objfile[MAX_PATH];
|
||||||
|
strcpy(objfile, wd->objfile);
|
||||||
|
wo1 = wad_object_load(objfile);
|
||||||
|
if (wo1) {
|
||||||
|
wd = wad_debug_info(wo1,symbol,offset);
|
||||||
|
wad_object_release(wo1);
|
||||||
|
} else {
|
||||||
|
printf("couldn't load %s\n", objfile);
|
||||||
|
}
|
||||||
|
if (!wd) return wad_search_stab(stab,stabsize,stabstr,symbol,offset);
|
||||||
|
return wd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_elf_debug()
|
||||||
|
*
|
||||||
|
* Print some debugging information about an object
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
wad_elf_debug(WadObject *wo) {
|
||||||
|
int i;
|
||||||
|
printf("ELF Debug : obj = %x (%s)\n", wo, wo->path);
|
||||||
|
printf(" phdrcnt = %d\n", wad_elf_phdrcnt(wo));
|
||||||
|
printf(" phdrpos = %x\n", wad_elf_phdrpos(wo));
|
||||||
|
printf(" shdrcnt = %d\n", wad_elf_shdrcnt(wo));
|
||||||
|
printf(" shdrpos = %x\n", wad_elf_shdrpos(wo));
|
||||||
|
for (i = 0; i < wad_elf_shdrcnt(wo); i++) {
|
||||||
|
printf(" section '%s': data = 0x%x, size = %d\n",
|
||||||
|
wad_elf_section_name(wo,i),
|
||||||
|
wad_elf_section_data(wo,i),
|
||||||
|
wad_elf_section_size(wo,i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* general purpose functions exposed to the outside world */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_find_symbol()
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
char *
|
||||||
|
wad_find_symbol(WadObject *wo, void *ptr, unsigned base, unsigned long *value) {
|
||||||
|
return wad_elf_find_symbol(wo,ptr,base,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
WadDebug *
|
||||||
|
wad_debug_info(WadObject *wo, char *symbol, unsigned long offset) {
|
||||||
|
return wad_elf_debug_info(wo,symbol,offset);
|
||||||
|
}
|
||||||
48
Tools/WAD/Wad/init.c
Normal file
48
Tools/WAD/Wad/init.c
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* init.c
|
||||||
|
*
|
||||||
|
* Initialize the wad system. This sets up a signal handler for catching
|
||||||
|
* SIGSEGV, SIGBUS, and SIGABRT.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/* Size of signal stack */
|
||||||
|
#define STACK_SIZE 4*SIGSTKSZ
|
||||||
|
|
||||||
|
/* Make the alternate signal stack part of the wad data segment as
|
||||||
|
opposed to putting it on the process heap */
|
||||||
|
|
||||||
|
char wad_sig_stack[STACK_SIZE];
|
||||||
|
|
||||||
|
/* Set up signal handler function for events we care about */
|
||||||
|
void wad_init() {
|
||||||
|
struct sigaction newvec;
|
||||||
|
static int init = 0;
|
||||||
|
static stack_t sigstk;
|
||||||
|
|
||||||
|
if (!init) {
|
||||||
|
/* Set up an alternative stack */
|
||||||
|
sigstk.ss_sp = (char *) wad_sig_stack;
|
||||||
|
sigstk.ss_size = STACK_SIZE;
|
||||||
|
sigstk.ss_flags = 0;
|
||||||
|
if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
|
||||||
|
perror("sigaltstack");
|
||||||
|
}
|
||||||
|
sigemptyset(&newvec.sa_mask);
|
||||||
|
sigaddset(&newvec.sa_mask, SIGSEGV);
|
||||||
|
sigaddset(&newvec.sa_mask, SIGBUS);
|
||||||
|
sigaddset(&newvec.sa_mask, SIGABRT);
|
||||||
|
newvec.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESETHAND;
|
||||||
|
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
||||||
|
sigaction(SIGSEGV, &newvec, NULL);
|
||||||
|
sigaction(SIGBUS, &newvec, NULL);
|
||||||
|
sigaction(SIGABRT, &newvec, NULL);
|
||||||
|
}
|
||||||
|
init = 1;
|
||||||
|
}
|
||||||
14
Tools/WAD/Wad/main.cxx
Normal file
14
Tools/WAD/Wad/main.cxx
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
extern "C" {
|
||||||
|
#include "wad.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a sick hack to force initialization upon loading */
|
||||||
|
|
||||||
|
class StartDebug {
|
||||||
|
public:
|
||||||
|
StartDebug() {
|
||||||
|
wad_init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static StartDebug s;
|
||||||
270
Tools/WAD/Wad/object.c
Normal file
270
Tools/WAD/Wad/object.c
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* object.c
|
||||||
|
*
|
||||||
|
* This file provides access to raw object files and executables.
|
||||||
|
* All memory management is done through mmap() to avoid the
|
||||||
|
* use of malloc()/free()
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <ar.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static WadObject wad_objects[WAD_MAX_OBJECT]; /* Object file descriptor table */
|
||||||
|
static int wad_obj_free[WAD_MAX_OBJECT]; /* Free object stack */
|
||||||
|
static int wad_obj_nfree = 0; /* Num free object descriptors */
|
||||||
|
static int wad_obj_init = 0; /* Initialized? */
|
||||||
|
|
||||||
|
/* Initialize internal memory management */
|
||||||
|
static void
|
||||||
|
init_object() {
|
||||||
|
int i;
|
||||||
|
if (wad_obj_init) return;
|
||||||
|
for (i = 0; i < WAD_MAX_OBJECT; i++) {
|
||||||
|
wad_objects[i].mptr = 0;
|
||||||
|
wad_objects[i].mlen = 0;
|
||||||
|
wad_objects[i].ptr = 0;
|
||||||
|
wad_objects[i].len = 0;
|
||||||
|
wad_objects[i].refcnt = 0;
|
||||||
|
wad_objects[i].path[0] = 0;
|
||||||
|
wad_obj_free[i] = i;
|
||||||
|
wad_obj_nfree++;
|
||||||
|
}
|
||||||
|
wad_obj_init = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_object_release()
|
||||||
|
*
|
||||||
|
* Done with the object.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
wad_object_release(WadObject *wo) {
|
||||||
|
int n;
|
||||||
|
if (!wo) return;
|
||||||
|
wo->refcnt--;
|
||||||
|
if (wo->refcnt > 0) return;
|
||||||
|
if (wo->mptr) {
|
||||||
|
munmap(wo->mptr, wo->mlen);
|
||||||
|
}
|
||||||
|
wo->mptr = 0;
|
||||||
|
wo->mlen = 0;
|
||||||
|
wo->ptr = 0;
|
||||||
|
wo->len = 0;
|
||||||
|
wo->path[0] = 0;
|
||||||
|
n = wo - wad_objects;
|
||||||
|
wad_obj_free[wad_obj_nfree++] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_object_load()
|
||||||
|
*
|
||||||
|
* Load an object file into memory using mmap. Returns 0 if the object does
|
||||||
|
* not exist or if there are no more object descriptor slots
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
WadObject *
|
||||||
|
wad_object_load(const char *path) {
|
||||||
|
WadObject *wo;
|
||||||
|
int nf;
|
||||||
|
int fd;
|
||||||
|
int i;
|
||||||
|
if (!wad_obj_init) init_object();
|
||||||
|
|
||||||
|
/* printf("loading '%s'\n", path); */
|
||||||
|
|
||||||
|
/* See if the path has already been loaded */
|
||||||
|
for (i = 0; i < WAD_MAX_OBJECT; i++) {
|
||||||
|
if (strcmp(wad_objects[i].path,path) == 0) {
|
||||||
|
wo = &wad_objects[i];
|
||||||
|
wo->refcnt++;
|
||||||
|
return wo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wad_obj_nfree == 0) {
|
||||||
|
printf("wad_object_load: No more space!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
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) {
|
||||||
|
strncpy(wo->path, path, MAX_PATH);
|
||||||
|
return wo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to open the requested pathname */
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0) return 0; /* Doesn't exist */
|
||||||
|
|
||||||
|
nf = wad_obj_free[wad_obj_nfree-1];
|
||||||
|
wo = wad_objects + nf;
|
||||||
|
wad_obj_nfree--;
|
||||||
|
|
||||||
|
wo->refcnt = 1;
|
||||||
|
strncpy(wo->path,path, MAX_PATH);
|
||||||
|
wo->mlen = lseek(fd,0,SEEK_END); /* Get length of the file */
|
||||||
|
lseek(fd,0,SEEK_SET);
|
||||||
|
|
||||||
|
/* Try to mmap the file */
|
||||||
|
wo->mptr = mmap(NULL,wo->mlen, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||||
|
if (wo->mptr == MAP_FAILED) {
|
||||||
|
perror("Whoa. Can't mmap.");
|
||||||
|
wo->mptr = 0;
|
||||||
|
wad_object_release(wo);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
wo->ptr = wo->mptr;
|
||||||
|
wo->len = wo->mlen;
|
||||||
|
return wo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_arobject_load()
|
||||||
|
*
|
||||||
|
* Load an archive file object into memory using mmap.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
WadObject *
|
||||||
|
wad_arobject_load(const char *arpath, const char *robjname) {
|
||||||
|
WadObject *wo;
|
||||||
|
int nf;
|
||||||
|
int fd;
|
||||||
|
int i;
|
||||||
|
int arlen;
|
||||||
|
char *arptr;
|
||||||
|
struct ar_hdr *ah;
|
||||||
|
int offset;
|
||||||
|
int msize;
|
||||||
|
char *strtab = 0;
|
||||||
|
int sobjname;
|
||||||
|
char objname[MAX_PATH];
|
||||||
|
|
||||||
|
strcpy(objname,robjname);
|
||||||
|
strcat(objname,"/");
|
||||||
|
sobjname = strlen(objname);
|
||||||
|
if (!wad_obj_init) init_object();
|
||||||
|
|
||||||
|
if (wad_obj_nfree == 0) {
|
||||||
|
printf("wad_object_load: No more space!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to open the requested archive name */
|
||||||
|
fd = open(arpath, O_RDONLY);
|
||||||
|
if (fd < 0) return 0; /* Doesn't exist */
|
||||||
|
|
||||||
|
nf = wad_obj_free[wad_obj_nfree-1];
|
||||||
|
wo = wad_objects + nf;
|
||||||
|
wad_obj_nfree--;
|
||||||
|
wo->refcnt = 1;
|
||||||
|
wo->ptr = 0;
|
||||||
|
|
||||||
|
arlen = lseek(fd,0,SEEK_END); /* Get length of the file */
|
||||||
|
lseek(fd,0,SEEK_SET);
|
||||||
|
|
||||||
|
/* Try to mmap the file */
|
||||||
|
arptr = (char *) mmap(NULL,arlen, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||||
|
if (arptr == MAP_FAILED) {
|
||||||
|
perror("Whoa. Can't mmap.");
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now take a look at the archive */
|
||||||
|
if (strncmp(arptr,ARMAG,SARMAG) == 0) {
|
||||||
|
/* printf("Got an archive\n"); */
|
||||||
|
} else {
|
||||||
|
printf("Not an archive file\n");
|
||||||
|
goto fatal_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
printf("Whoa. No string offset table\n");
|
||||||
|
goto fatal_error;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf("ar_name = '%s', ar_size = '%0.10s'\n", mname, ah->ar_size); */
|
||||||
|
/* Compare the names */
|
||||||
|
if (strncmp(mname,objname,sobjname) == 0) {
|
||||||
|
/* Leave the archive mapped in memory, but set a pointer to the member
|
||||||
|
name */
|
||||||
|
|
||||||
|
wo->mptr = (void *) arptr;
|
||||||
|
wo->mlen = arlen;
|
||||||
|
wo->ptr = (void *) (arptr + offset);
|
||||||
|
wo->len = msize;
|
||||||
|
close(fd);
|
||||||
|
return wo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += msize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal_error:
|
||||||
|
munmap(arptr,arlen);
|
||||||
|
close(fd);
|
||||||
|
wad_object_release(wo);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
163
Tools/WAD/Wad/segment.c
Normal file
163
Tools/WAD/Wad/segment.c
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* segment.c
|
||||||
|
*
|
||||||
|
* This file provides access to the virtual memory map of a process
|
||||||
|
* including the location of the executable, data segments, shared
|
||||||
|
* libraries, and memory mapped regions. This information is
|
||||||
|
* obtained through /proc.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include <procfs.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The current segment is stored in statically allocated memory to avoid
|
||||||
|
the use of malloc()/free(). If a caller wants to make a copy, that is
|
||||||
|
their problem */
|
||||||
|
|
||||||
|
static WadSegment segment; /* Currently loaded segment */
|
||||||
|
static int read_segment = 0;
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_segment_print()
|
||||||
|
*
|
||||||
|
* Print the contents of a memory segment. (Debugging)
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
wad_segment_print(WadSegment *s) {
|
||||||
|
printf("Segment %x:::\n",s);
|
||||||
|
printf(" mapname = %s\n", s->mapname);
|
||||||
|
printf(" mappath = %s\n", s->mappath);
|
||||||
|
printf(" vaddr = 0x%x\n", s->vaddr);
|
||||||
|
printf(" size = %d\n", s->size);
|
||||||
|
printf(" offset = %d\n", s->offset);
|
||||||
|
printf(" flags = 0x%x\n", s->flags);
|
||||||
|
printf(" identifier = %d\n", s->identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_segment_find()
|
||||||
|
*
|
||||||
|
* Try to find the virtual memory segment corresponding to a virtual address.
|
||||||
|
* This overwrites the previously returned segment data.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
WadSegment *
|
||||||
|
wad_segment_find(wadaddr_t addr) {
|
||||||
|
char dirname[MAX_PATH];
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
int fd;
|
||||||
|
prmap_t pmap;
|
||||||
|
int offset = 0;
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (read_segment) {
|
||||||
|
if ((addr >= segment.vaddr) && (addr < (segment.vaddr+segment.size))) return &segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set location in /proc */
|
||||||
|
sprintf(dirname,"/proc/%d",getpid());
|
||||||
|
|
||||||
|
/* Try to load the virtual address map */
|
||||||
|
sprintf(filename,"%s/map",dirname);
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("wad_segment_find: couldn't open '%s'\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_segment = 0;
|
||||||
|
while (1) {
|
||||||
|
n = read(fd,&pmap,sizeof(prmap_t));
|
||||||
|
if (n < 0) break;
|
||||||
|
offset += n;
|
||||||
|
if ((addr >= (wadaddr_t) pmap.pr_vaddr) && (addr <= (wadaddr_t) (pmap.pr_vaddr + pmap.pr_size))) {
|
||||||
|
strncpy(segment.mapname, pmap.pr_mapname, MAX_PATH);
|
||||||
|
strcpy(segment.mappath,dirname);
|
||||||
|
strcat(segment.mappath,"/object/");
|
||||||
|
strcat(segment.mappath,pmap.pr_mapname);
|
||||||
|
segment.vaddr = (wadaddr_t) pmap.pr_vaddr;
|
||||||
|
segment.size = pmap.pr_size;
|
||||||
|
segment.offset = pmap.pr_offset;
|
||||||
|
segment.flags = pmap.pr_mflags;
|
||||||
|
segment.identifier = pmap.pr_shmid;
|
||||||
|
segment.wad = offset;
|
||||||
|
read_segment = 1;
|
||||||
|
close(fd);
|
||||||
|
return &segment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* wad_segment_next()
|
||||||
|
*
|
||||||
|
* Read the next segment
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
WadSegment *wad_segment_next() {
|
||||||
|
|
||||||
|
char dirname[MAX_PATH];
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
int fd;
|
||||||
|
prmap_t pmap;
|
||||||
|
int offset = 0;
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (!read_segment) {
|
||||||
|
segment.wad = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set location in /proc */
|
||||||
|
sprintf(dirname,"/proc/%d",getpid());
|
||||||
|
|
||||||
|
/* Try to load the virtual address map */
|
||||||
|
sprintf(filename,"%s/map",dirname);
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("wad_segment_find: couldn't open '%s'\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (lseek(fd, segment.wad, SEEK_SET) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n = read(fd,&pmap,sizeof(prmap_t));
|
||||||
|
if (n <= 0) {
|
||||||
|
read_segment = 0;
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strncpy(segment.mapname, pmap.pr_mapname, MAX_PATH);
|
||||||
|
strcpy(segment.mappath,dirname);
|
||||||
|
strcat(segment.mappath,"/object/");
|
||||||
|
strcat(segment.mappath,pmap.pr_mapname);
|
||||||
|
segment.vaddr = (wadaddr_t) pmap.pr_vaddr;
|
||||||
|
segment.size = pmap.pr_size;
|
||||||
|
segment.offset = pmap.pr_offset;
|
||||||
|
segment.flags = pmap.pr_mflags;
|
||||||
|
segment.identifier = pmap.pr_shmid;
|
||||||
|
segment.wad += n;
|
||||||
|
read_segment = 1;
|
||||||
|
close(fd);
|
||||||
|
return &segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
WadSegment *
|
||||||
|
wad_segment_first() {
|
||||||
|
segment.wad = 0;
|
||||||
|
read_segment = 0;
|
||||||
|
return wad_segment_next();
|
||||||
|
}
|
||||||
332
Tools/WAD/Wad/signal.c
Normal file
332
Tools/WAD/Wad/signal.c
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* signal.c
|
||||||
|
*
|
||||||
|
* WAD signal handler.
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
static char *strip_dir(char *name) {
|
||||||
|
char *c;
|
||||||
|
c = name + strlen(name);
|
||||||
|
while (c != name) {
|
||||||
|
if (*c == '/') {
|
||||||
|
c++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
c--;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Default callback
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void wad_default_callback(int signo, void *framedata) {
|
||||||
|
char *fd;
|
||||||
|
WadFrame *f;
|
||||||
|
switch(signo) {
|
||||||
|
case SIGSEGV:
|
||||||
|
printf("Segmentation fault.\n");
|
||||||
|
break;
|
||||||
|
case SIGBUS:
|
||||||
|
printf("Bus error.\n");
|
||||||
|
break;
|
||||||
|
case SIGABRT:
|
||||||
|
printf("Abort.\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Signal %d\n", signo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fd = (char *) framedata;
|
||||||
|
f = (WadFrame *) fd;
|
||||||
|
while (f->size) {
|
||||||
|
printf("#%-3d 0x%08x in %s()", f->frameno, f->pc, *(fd + f->sym_off) ? fd+f->sym_off : "?");
|
||||||
|
if (strlen(fd+f->src_off)) {
|
||||||
|
printf(" in '%s'", strip_dir(fd+f->src_off));
|
||||||
|
if (f->line_number >= 0) {
|
||||||
|
printf(", line %d", f->line_number);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strlen(fd+f->obj_off)) {
|
||||||
|
printf(" from '%s'", fd+f->obj_off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
fd = fd + f->size;
|
||||||
|
f = (WadFrame *) fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Perform one level of stack unwinding */
|
||||||
|
unsigned long *stack_unwind(unsigned long *sp) {
|
||||||
|
unsigned long *new_sp;
|
||||||
|
unsigned long ret_addr;
|
||||||
|
int i;
|
||||||
|
new_sp = (unsigned long *) *(sp+14);
|
||||||
|
ret_addr = *(sp+15);
|
||||||
|
return (unsigned long *) new_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data structures for containing information about non-local returns */
|
||||||
|
|
||||||
|
typedef struct nonlocal {
|
||||||
|
char symname[256];
|
||||||
|
long value;
|
||||||
|
struct nonlocal *next;
|
||||||
|
} nonlocal;
|
||||||
|
|
||||||
|
static nonlocal *return_points = 0;
|
||||||
|
|
||||||
|
void wad_set_return(char *name, long value) {
|
||||||
|
nonlocal *nl;
|
||||||
|
nl = (nonlocal *) malloc(sizeof(nonlocal));
|
||||||
|
strcpy(nl->symname,name);
|
||||||
|
nl->value = value;
|
||||||
|
nl->next = return_points;
|
||||||
|
return_points = nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (*sig_callback)(int signo, void *data) = 0;
|
||||||
|
|
||||||
|
void wad_set_callback(void (*s)(int,void *)) {
|
||||||
|
sig_callback = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This bit of nastiness is used to make a non-local return from the
|
||||||
|
signal handler to a configurable location on the call stack. In a nutshell,
|
||||||
|
this works by repeatedly calling "restore" to roll back the
|
||||||
|
register windows and stack pointer. Then we fake a return value and
|
||||||
|
return to the caller as if the function had actually completed
|
||||||
|
normally. */
|
||||||
|
|
||||||
|
static int nlr_levels = 0;
|
||||||
|
static int *volatile nlr_p = &nlr_levels;
|
||||||
|
static long nlr_value = 0;
|
||||||
|
|
||||||
|
static void nonlocalret() {
|
||||||
|
long a;
|
||||||
|
|
||||||
|
a = nlr_value;
|
||||||
|
/* We never call this procedure as a function. This code
|
||||||
|
causes an immediate return if someone does this */
|
||||||
|
|
||||||
|
asm("jmp %i7 + 8");
|
||||||
|
asm("restore");
|
||||||
|
|
||||||
|
/* This is the real entry point */
|
||||||
|
/* asm(".globl _returnsignal");*/
|
||||||
|
asm(".type _returnsignal,2");
|
||||||
|
asm("_returnsignal:");
|
||||||
|
|
||||||
|
while (*nlr_p > 0) {
|
||||||
|
(*nlr_p)--;
|
||||||
|
asm("restore");
|
||||||
|
}
|
||||||
|
|
||||||
|
asm("sethi %hi(nlr_value), %o0");
|
||||||
|
asm("or %o0, %lo(nlr_value), %o0");
|
||||||
|
asm("ld [%o0], %i0");
|
||||||
|
|
||||||
|
asm("jmp %i7 + 8");
|
||||||
|
asm("restore");
|
||||||
|
asm(".size _returnsignal,(.-_returnsignal)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||||
|
int current;
|
||||||
|
greg_t *pc;
|
||||||
|
greg_t *npc;
|
||||||
|
greg_t *ret;
|
||||||
|
greg_t *sp;
|
||||||
|
int i;
|
||||||
|
unsigned long *user_fp;
|
||||||
|
unsigned long *addr;
|
||||||
|
ucontext_t *context;
|
||||||
|
unsigned long *p_sp; /* process stack pointer */
|
||||||
|
unsigned long *p_pc; /* Process program counter */
|
||||||
|
WadSegment *ws;
|
||||||
|
WadObject *wo;
|
||||||
|
int nlevels;
|
||||||
|
int found = 0;
|
||||||
|
void _returnsignal();
|
||||||
|
int n = 0;
|
||||||
|
char framefile[256];
|
||||||
|
int ffile;
|
||||||
|
WadFrame frame;
|
||||||
|
void *framedata;
|
||||||
|
int fsize = 0; /* Total frame size */
|
||||||
|
sprintf(framefile,"/tmp/wad.%d", getpid());
|
||||||
|
|
||||||
|
/* Open the output file for the traceback */
|
||||||
|
|
||||||
|
ffile = open(framefile, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||||
|
|
||||||
|
if (ffile < 0) {
|
||||||
|
printf("can't open %s\n", framefile);
|
||||||
|
}
|
||||||
|
|
||||||
|
context = (ucontext_t *) vcontext;
|
||||||
|
|
||||||
|
/* Get some information about the current context */
|
||||||
|
pc = &((context->uc_mcontext).gregs[REG_PC]);
|
||||||
|
npc = &((context->uc_mcontext).gregs[REG_nPC]);
|
||||||
|
sp = &((context->uc_mcontext).gregs[REG_SP]);
|
||||||
|
ret = &((context->uc_mcontext).gregs[REG_O7]);
|
||||||
|
|
||||||
|
/* Get some information out of the signal handler stack */
|
||||||
|
user_fp = (unsigned long *) _get_fp(); /* Current frame pointer */
|
||||||
|
addr = (unsigned long *) si->si_addr;
|
||||||
|
|
||||||
|
/* Try to do a stack traceback */
|
||||||
|
nlevels = 0;
|
||||||
|
p_pc = (unsigned long *) (*pc);
|
||||||
|
p_sp = (unsigned long *) (*sp);
|
||||||
|
|
||||||
|
while (p_pc) {
|
||||||
|
ws = wad_segment_find((wadaddr_t) p_pc);
|
||||||
|
if (!ws) {
|
||||||
|
printf("No segment found for %x\n", p_pc);
|
||||||
|
} else {
|
||||||
|
WadObject *wo;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int symsize = 0; /* Symbol size */
|
||||||
|
int srcsize = 0;
|
||||||
|
int objsize = 0;
|
||||||
|
char *srcname = 0;
|
||||||
|
char *objname = 0;
|
||||||
|
char *symname = 0;
|
||||||
|
int pad = 0;
|
||||||
|
|
||||||
|
unsigned long value;
|
||||||
|
wo = wad_object_load(ws->mappath);
|
||||||
|
if (strcmp(ws->mapname,"a.out") == 0) ws->vaddr= 0;
|
||||||
|
name = wad_find_symbol(wo,(void *) p_pc, (unsigned long) ws->vaddr, &value);
|
||||||
|
|
||||||
|
/* Build up some information about the exception frame */
|
||||||
|
frame.frameno = n;
|
||||||
|
frame.pc = (long) p_pc;
|
||||||
|
frame.sp = (long) p_sp;
|
||||||
|
n++;
|
||||||
|
if (name) {
|
||||||
|
nonlocal *nl;
|
||||||
|
symsize = strlen(name)+1;
|
||||||
|
symname = name;
|
||||||
|
nl = return_points;
|
||||||
|
while (nl) {
|
||||||
|
if (strcmp(name,nl->symname) == 0) {
|
||||||
|
found = 1;
|
||||||
|
nlr_value = nl->value;
|
||||||
|
}
|
||||||
|
nl = nl->next;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
WadDebug *wd;
|
||||||
|
wd = wad_debug_info(wo,name, (unsigned long) p_pc - (unsigned long) ws->vaddr - value);
|
||||||
|
if (wd) {
|
||||||
|
srcname = wd->srcfile;
|
||||||
|
srcsize = strlen(srcname)+1;
|
||||||
|
objname = wd->objfile;
|
||||||
|
objsize = strlen(objname)+1;
|
||||||
|
frame.line_number = wd->line_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Build up the exception frame object */
|
||||||
|
frame.size = sizeof(WadFrame) + symsize + srcsize + objsize;
|
||||||
|
pad = 8 - (frame.size % 8);
|
||||||
|
frame.size += pad;
|
||||||
|
|
||||||
|
frame.data[0] = 0;
|
||||||
|
frame.data[1] = 0;
|
||||||
|
|
||||||
|
/* Build up the offsets */
|
||||||
|
if (!name) {
|
||||||
|
frame.sym_off = sizeof(WadFrame) - 8;
|
||||||
|
frame.src_off = sizeof(WadFrame) - 8;
|
||||||
|
frame.obj_off = sizeof(WadFrame) - 8;
|
||||||
|
} else {
|
||||||
|
frame.sym_off = sizeof(WadFrame);
|
||||||
|
frame.src_off = sizeof(WadFrame)+symsize;
|
||||||
|
frame.obj_off = sizeof(WadFrame)+symsize+srcsize;
|
||||||
|
}
|
||||||
|
write(ffile,&frame,sizeof(WadFrame));
|
||||||
|
if (symname) {
|
||||||
|
write(ffile,symname,symsize);
|
||||||
|
write(ffile,srcname,srcsize);
|
||||||
|
write(ffile,objname,objsize);
|
||||||
|
}
|
||||||
|
write(ffile,frame.data, pad);
|
||||||
|
wad_object_release(wo);
|
||||||
|
}
|
||||||
|
if (!found) nlevels++;
|
||||||
|
p_pc = (unsigned long *) *(p_sp+15);
|
||||||
|
p_sp = stack_unwind(p_sp);
|
||||||
|
if (found) break;
|
||||||
|
}
|
||||||
|
/* Write terminator */
|
||||||
|
frame.size = 0;
|
||||||
|
write(ffile,&frame,sizeof(WadFrame));
|
||||||
|
close(ffile);
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
nlr_levels = nlevels - 1;
|
||||||
|
} else {
|
||||||
|
nlr_levels = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go mmap the debug file */
|
||||||
|
ffile = open(framefile, O_RDONLY, 0644);
|
||||||
|
fsize = lseek(ffile,0,SEEK_END);
|
||||||
|
lseek(ffile,0,SEEK_SET);
|
||||||
|
|
||||||
|
framedata = mmap(NULL, fsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, ffile, 0);
|
||||||
|
|
||||||
|
if (sig_callback) {
|
||||||
|
(*sig_callback)(sig,framedata);
|
||||||
|
} else {
|
||||||
|
/* No signal handler defined. Go invoke the default */
|
||||||
|
wad_default_callback(sig, framedata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we found a function to which we should return, we jump to
|
||||||
|
an alternative piece of code that unwinds the stack and
|
||||||
|
initiates a non-local return. */
|
||||||
|
|
||||||
|
munmap(framedata,fsize);
|
||||||
|
close(ffile);
|
||||||
|
unlink(framefile);
|
||||||
|
if (nlr_levels > 0) {
|
||||||
|
*(pc) = (greg_t) _returnsignal;
|
||||||
|
*(npc) = *(pc) + 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
asm_stuff()
|
||||||
|
{
|
||||||
|
asm(" .globl _get_sp");
|
||||||
|
asm("_get_sp:");
|
||||||
|
asm(" retl");
|
||||||
|
asm(" mov %sp, %o0");
|
||||||
|
asm(" .globl _get_fp");
|
||||||
|
asm("_get_fp:");
|
||||||
|
asm(" retl");
|
||||||
|
asm(" mov %fp, %o0");
|
||||||
|
}
|
||||||
|
|
||||||
127
Tools/WAD/Wad/stab.c
Normal file
127
Tools/WAD/Wad/stab.c
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* 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. I ripped
|
||||||
|
it out of the Sun C compiler include directory */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
short n_desc; /* see stabs documentation */
|
||||||
|
unsigned n_value; /* value of symbol (or sdb offset) */
|
||||||
|
} Stab;
|
||||||
|
|
||||||
|
/* Match a stabs symbol name against a stab string (which may contain
|
||||||
|
extra information delimetered by a colon */
|
||||||
|
|
||||||
|
int match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||||
|
/* printf("matching: %s -> %s\n", symbol, stabtext); */
|
||||||
|
if (strcmp(symbol,stabtext) == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((strncmp(symbol, stabtext, slen) == 0) && (*(stabtext+slen) == ':')) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
static WadDebug debug;
|
||||||
|
|
||||||
|
WadDebug *
|
||||||
|
wad_search_stab(void *sp, int size, char *stabstr, char *symbol, unsigned long offset) {
|
||||||
|
Stab *s;
|
||||||
|
int ns;
|
||||||
|
int infunc;
|
||||||
|
int slen;
|
||||||
|
int i;
|
||||||
|
char *file;
|
||||||
|
int chk = 0;
|
||||||
|
|
||||||
|
s = (Stab *) sp; /* Stabs data */
|
||||||
|
ns = size/sizeof(Stab); /* number of stabs */
|
||||||
|
slen = strlen(symbol);
|
||||||
|
|
||||||
|
/* Reset the debug information section */
|
||||||
|
debug.found = 0;
|
||||||
|
debug.srcfile[0] = 0;
|
||||||
|
debug.objfile[0] = 0;
|
||||||
|
debug.line_number = -1;
|
||||||
|
debug.nargs = 0;
|
||||||
|
for (i = 0; i < ns; i++, s++) {
|
||||||
|
/*#define DEBUG_DEBUG */
|
||||||
|
#ifdef DEBUG_DEBUG
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
#undef DEBUG_DEBUG
|
||||||
|
if (s->n_type == 0) {
|
||||||
|
/* New stabs section. We need to be a little careful here. Do a recursive
|
||||||
|
search of the subsection. */
|
||||||
|
WadDebug *wd;
|
||||||
|
#ifdef DEBUG_DEBUG
|
||||||
|
printf("Section: %d stabs.\n", s->n_desc);
|
||||||
|
#endif
|
||||||
|
wd = wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, symbol, offset);
|
||||||
|
if (wd) return wd;
|
||||||
|
stabstr += s->n_value; /* Update the string table location*/
|
||||||
|
i += s->n_desc;
|
||||||
|
s += s->n_desc;
|
||||||
|
debug.objfile[0] = 0;
|
||||||
|
debug.srcfile[0] = 0;
|
||||||
|
debug.line_number = -1;
|
||||||
|
debug.found = 0;
|
||||||
|
} else if (s->n_type == 0x64) {
|
||||||
|
if (debug.found) return &debug; /* New file and we already found what we wanted */
|
||||||
|
/* Source file specification */
|
||||||
|
/* Look for directory */
|
||||||
|
file = stabstr+s->n_strx;
|
||||||
|
if (file[strlen(file)] == '/') {
|
||||||
|
strcpy(debug.srcfile,file);
|
||||||
|
} else {
|
||||||
|
strcat(debug.srcfile,file);
|
||||||
|
}
|
||||||
|
debug.objfile[0] = 0;
|
||||||
|
} else if (s->n_type == 0x38) {
|
||||||
|
/* Object file specifier */
|
||||||
|
if (debug.objfile[0]) {
|
||||||
|
strcat(debug.objfile,"/");
|
||||||
|
}
|
||||||
|
strcat(debug.objfile,stabstr+s->n_strx);
|
||||||
|
} else if (s->n_type == 0x24) {
|
||||||
|
if (match_stab_symbol(symbol, stabstr+s->n_strx, slen)) {
|
||||||
|
infunc = 1;
|
||||||
|
debug.found = 1;
|
||||||
|
} else {
|
||||||
|
infunc = 0;
|
||||||
|
}
|
||||||
|
} else if (debug.found && (s->n_type == 0x44) && (infunc)) {
|
||||||
|
if (s->n_value <= offset) {
|
||||||
|
debug.line_number = s->n_desc;
|
||||||
|
} else return &debug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debug.found) return &debug;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
Tools/WAD/main.cxx
Normal file
14
Tools/WAD/main.cxx
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
extern "C" {
|
||||||
|
#include "wad.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a sick hack to force initialization upon loading */
|
||||||
|
|
||||||
|
class StartDebug {
|
||||||
|
public:
|
||||||
|
StartDebug() {
|
||||||
|
wad_init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static StartDebug s;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue