Enhanced ELF files lookup for symbolic info.
This commit is contained in:
parent
7c7e3ba5b2
commit
9454801cd9
|
@ -405,7 +405,6 @@ extern int DEBUG_GetCurrentFrame(struct name_hash ** name,
|
||||||
|
|
||||||
/* debugger/stabs.c */
|
/* debugger/stabs.c */
|
||||||
extern int DEBUG_ReadExecutableDbgInfo(const char* exe_name);
|
extern int DEBUG_ReadExecutableDbgInfo(const char* exe_name);
|
||||||
extern int DEBUG_ProcessElfObject(const char* filename, unsigned int load_offset);
|
|
||||||
extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff,
|
extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff,
|
||||||
int stablen, unsigned int strtaboff, int strtablen);
|
int stablen, unsigned int strtaboff, int strtablen);
|
||||||
|
|
||||||
|
|
186
debugger/stabs.c
186
debugger/stabs.c
|
@ -1179,10 +1179,19 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/*
|
||||||
DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset)
|
* Loads the symbolic information from ELF module stored in 'filename'
|
||||||
|
* the module has been loaded at 'load_offset' address, so symbols' address
|
||||||
|
* relocation is performed
|
||||||
|
* returns
|
||||||
|
* -1 if the file cannot be found/opened
|
||||||
|
* 0 if the file doesn't contain symbolic info (or this info cannot be
|
||||||
|
* read or parsed)
|
||||||
|
* 1 on success
|
||||||
|
*/
|
||||||
|
static int DEBUG_ProcessElfFile(const char * filename, unsigned int load_offset)
|
||||||
{
|
{
|
||||||
int rtn = FALSE;
|
int rtn = -1;
|
||||||
char * addr = (char*)0xffffffff;
|
char * addr = (char*)0xffffffff;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
@ -1193,87 +1202,46 @@ DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset)
|
||||||
int i;
|
int i;
|
||||||
int stabsect;
|
int stabsect;
|
||||||
int stabstrsect;
|
int stabstrsect;
|
||||||
|
|
||||||
/*
|
/* check that the file exists, and that the module hasn't been loaded yet */
|
||||||
* Make sure we can stat and open this file.
|
if (stat(filename, &statbuf) == -1) goto leave;
|
||||||
*/
|
|
||||||
if( filename == NULL )
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
if (stat(filename, &statbuf) == -1)
|
|
||||||
{
|
|
||||||
char *s,*t,*fn,*paths;
|
|
||||||
if (strchr(filename,'/'))
|
|
||||||
goto leave;
|
|
||||||
paths = DBG_strdup(getenv("PATH"));
|
|
||||||
s = paths;
|
|
||||||
while (s && *s) {
|
|
||||||
t = strchr(s,':');
|
|
||||||
if (t) *t='\0';
|
|
||||||
fn = (char*)DBG_alloc(strlen(filename)+1+strlen(s)+1);
|
|
||||||
strcpy(fn,s);
|
|
||||||
strcat(fn,"/");
|
|
||||||
strcat(fn,filename);
|
|
||||||
if ((rtn = DEBUG_ProcessElfObject(fn,load_offset))) {
|
|
||||||
DBG_free(fn);
|
|
||||||
DBG_free(paths);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
DBG_free(fn);
|
|
||||||
if (t) s = t+1; else break;
|
|
||||||
}
|
|
||||||
if (!s || !*s) DEBUG_Printf(DBG_CHN_MESG," not found");
|
|
||||||
DBG_free(paths);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_FindModuleByName(filename, DM_TYPE_ELF))
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "Loading stabs debug symbols from %s (0x%08x)\n",
|
|
||||||
filename, load_offset);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now open the file, so that we can mmap() it.
|
* Now open the file, so that we can mmap() it.
|
||||||
*/
|
*/
|
||||||
if ((fd = open(filename, O_RDONLY)) == -1)
|
if ((fd = open(filename, O_RDONLY)) == -1) goto leave;
|
||||||
goto leave;
|
|
||||||
|
rtn = 0;
|
||||||
/*
|
/*
|
||||||
* Now mmap() the file.
|
* Now mmap() the file.
|
||||||
*/
|
*/
|
||||||
addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
if (addr == (char*)0xffffffff)
|
if (addr == (char*)0xffffffff) goto leave;
|
||||||
goto leave;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next, we need to find a few of the internal ELF headers within
|
* Next, we need to find a few of the internal ELF headers within
|
||||||
* this thing. We need the main executable header, and the section
|
* this thing. We need the main executable header, and the section
|
||||||
* table.
|
* table.
|
||||||
*/
|
*/
|
||||||
ehptr = (Elf32_Ehdr *) addr;
|
ehptr = (Elf32_Ehdr *) addr;
|
||||||
|
|
||||||
if( load_offset == 0 )
|
DEBUG_RegisterELFModule((load_offset == 0) ? ehptr->e_entry : load_offset, filename);
|
||||||
DEBUG_RegisterELFModule(ehptr->e_entry, filename);
|
|
||||||
else
|
|
||||||
DEBUG_RegisterELFModule(load_offset, filename);
|
|
||||||
|
|
||||||
spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
|
spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
|
||||||
nsect = ehptr->e_shnum;
|
nsect = ehptr->e_shnum;
|
||||||
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
||||||
|
|
||||||
stabsect = stabstrsect = -1;
|
stabsect = stabstrsect = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < nsect; i++) {
|
||||||
|
if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
|
||||||
|
stabsect = i;
|
||||||
|
|
||||||
for(i=0; i < nsect; i++)
|
if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
|
||||||
{
|
stabstrsect = i;
|
||||||
if( strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0 )
|
}
|
||||||
stabsect = i;
|
|
||||||
|
|
||||||
if( strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0 )
|
if (stabsect == -1 || stabstrsect == -1) {
|
||||||
stabstrsect = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( stabsect == -1 || stabstrsect == -1 ) {
|
|
||||||
DEBUG_Printf(DBG_CHN_WARN, "no .stab section\n");
|
DEBUG_Printf(DBG_CHN_WARN, "no .stab section\n");
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
@ -1290,29 +1258,81 @@ DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i < nsect; i++)
|
for (i = 0; i < nsect; i++) {
|
||||||
{
|
if ( (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
|
||||||
if( (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
|
&& (spnt[i].sh_type == SHT_SYMTAB))
|
||||||
&& (spnt[i].sh_type == SHT_SYMTAB) )
|
DEBUG_ProcessElfSymtab(addr, load_offset,
|
||||||
DEBUG_ProcessElfSymtab(addr, load_offset,
|
spnt + i, spnt + spnt[i].sh_link);
|
||||||
spnt + i, spnt + spnt[i].sh_link);
|
|
||||||
|
|
||||||
if( (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
|
if ( (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
|
||||||
&& (spnt[i].sh_type == SHT_DYNSYM) )
|
&& (spnt[i].sh_type == SHT_DYNSYM))
|
||||||
DEBUG_ProcessElfSymtab(addr, load_offset,
|
DEBUG_ProcessElfSymtab(addr, load_offset,
|
||||||
spnt + i, spnt + spnt[i].sh_link);
|
spnt + i, spnt + spnt[i].sh_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
|
||||||
if (addr != (char*)0xffffffff)
|
|
||||||
munmap(addr, statbuf.st_size);
|
|
||||||
|
|
||||||
if (fd != -1) close(fd);
|
if (fd != -1) close(fd);
|
||||||
|
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int DEBUG_ProcessElfFileFromPath(const char * filename,
|
||||||
|
unsigned int load_offset, const char* path)
|
||||||
|
{
|
||||||
|
int rtn = FALSE;
|
||||||
|
char *s, *t, *fn;
|
||||||
|
char* paths = NULL;
|
||||||
|
|
||||||
|
for (s = paths = DBG_strdup(path); s && *s; s = (t) ? (t+1) : NULL) {
|
||||||
|
t = strchr(s, ':');
|
||||||
|
if (t) *t = '\0';
|
||||||
|
fn = (char*)DBG_alloc(strlen(filename) + 1 + strlen(s) + 1);
|
||||||
|
if (!fn) break;
|
||||||
|
strcpy(fn, s );
|
||||||
|
strcat(fn, "/");
|
||||||
|
strcat(fn, filename);
|
||||||
|
rtn = DEBUG_ProcessElfFile(fn, load_offset);
|
||||||
|
DBG_free(fn);
|
||||||
|
if (rtn >= 0) break;
|
||||||
|
s = (t) ? (t+1) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG_free(paths);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset)
|
||||||
|
{
|
||||||
|
int rtn = -1;
|
||||||
|
const char* fmt;
|
||||||
|
|
||||||
|
DEBUG_Printf(DBG_CHN_TRACE, "Processing elf file '%s'\n", filename);
|
||||||
|
|
||||||
|
if (filename == NULL) return FALSE;
|
||||||
|
if (DEBUG_FindModuleByName(filename, DM_TYPE_ELF)) return TRUE;
|
||||||
|
|
||||||
|
rtn = DEBUG_ProcessElfFile(filename, load_offset);
|
||||||
|
|
||||||
|
/* if relative pathname, try some absolute base dirs */
|
||||||
|
if (rtn < 0 && !strchr(filename, '/')) {
|
||||||
|
rtn = DEBUG_ProcessElfFileFromPath(filename, load_offset, getenv("PATH"));
|
||||||
|
if (rtn < 0)
|
||||||
|
rtn = DEBUG_ProcessElfFileFromPath(filename, load_offset, getenv("LD_LIBRARY_PATH"));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rtn) {
|
||||||
|
case 1: fmt = "Loaded stabs debug symbols from ELF '%s' (0x%08x)\n"; break;
|
||||||
|
case 0: fmt = "No stabs debug symbols in ELF '%s' (0x%08x)\n"; break;
|
||||||
|
case -1:fmt = "Can't find file for ELF '%s' (0x%08x)\n"; break;
|
||||||
|
default: DEBUG_Printf(DBG_CHN_ERR, "Oooocch (%d)\n", rtn); return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_Printf(DBG_CHN_MESG, fmt, filename, load_offset);
|
||||||
|
|
||||||
|
return rtn >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL DEBUG_WalkList(struct r_debug* dbg_hdr)
|
static BOOL DEBUG_WalkList(struct r_debug* dbg_hdr)
|
||||||
{
|
{
|
||||||
u_long lm_addr;
|
u_long lm_addr;
|
||||||
|
@ -1424,12 +1444,6 @@ leave:
|
||||||
|
|
||||||
#else /* !__ELF__ */
|
#else /* !__ELF__ */
|
||||||
|
|
||||||
int
|
|
||||||
DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<title>I Introduction</title>
|
<title>I Introduction</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
written by Eric Pouech (???) (Last updated: 6/14/2000)
|
written by Eric Pouech (Last updated: 8/15/2000)
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
(Extracted from <filename>wine/documentation/winedbg</filename>)
|
(Extracted from <filename>wine/documentation/winedbg</filename>)
|
||||||
|
@ -107,6 +107,12 @@
|
||||||
use of this API to allow debugging both any Wine or WineLib
|
use of this API to allow debugging both any Wine or WineLib
|
||||||
applications as well as Wine itself (kernel and all DLLs).
|
applications as well as Wine itself (kernel and all DLLs).
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>WineDbg</command> understands symbolic information
|
||||||
|
from both Unix world (mainly ELF stabs) and from Windows
|
||||||
|
(most Microsoft debugging formats are supported - CodeView,
|
||||||
|
.DBG files...)
|
||||||
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
@ -553,6 +559,18 @@ UseXTerm = 1
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>III.3 Finding files</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
WineDbg uses some lookup algorithms to find the files containing
|
||||||
|
the debugging information. For ELF files, the current directory,
|
||||||
|
the list of directories pointed by PATH, LD_LIBRARY_PATH are
|
||||||
|
searched (in that order). For Microsoft debugging files,
|
||||||
|
current directory, and directories pointed by _NT_SYMBOL_PATH and
|
||||||
|
_NT_ALT_SYMBOL_PATH (in that order) are searched.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="dbg-commands">
|
<sect1 id="dbg-commands">
|
||||||
|
|
Loading…
Reference in New Issue