Fixed IMemUtils::ResolveSymbol() on Mac OS X (bug 4448, r=dvander).

This commit is contained in:
Scott Ehlert 2010-06-07 13:26:45 -05:00
parent 0712db0d29
commit 124086419e

View File

@ -250,10 +250,11 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
#elif defined PLATFORM_APPLE #elif defined PLATFORM_APPLE
uintptr_t dlbase; uintptr_t dlbase, linkedit_addr;
uint32_t image_count; uint32_t image_count;
struct mach_header *file_hdr; struct mach_header *file_hdr;
struct load_command *loadcmds; struct load_command *loadcmds;
struct segment_command *linkedit_hdr;
struct symtab_command *symtab_hdr; struct symtab_command *symtab_hdr;
struct nlist *symtab; struct nlist *symtab;
const char *strtab; const char *strtab;
@ -265,7 +266,9 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
dlbase = 0; dlbase = 0;
image_count = m_ImageList->infoArrayCount; image_count = m_ImageList->infoArrayCount;
linkedit_hdr = NULL;
symtab_hdr = NULL; symtab_hdr = NULL;
table = NULL;
/* Loop through mach-o images in process. /* Loop through mach-o images in process.
* We can skip index 0 since that is just the executable. * We can skip index 0 since that is just the executable.
@ -327,27 +330,43 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header)); loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
loadcmd_count = file_hdr->ncmds; loadcmd_count = file_hdr->ncmds;
/* Loop through load commands until we find the one for the symbol table */ /* Loop through load commands until we find the ones for the symbol table */
for (uint32_t i = 0; i < loadcmd_count; i++) for (uint32_t i = 0; i < loadcmd_count; i++)
{ {
if (loadcmds->cmd == LC_SYMTAB) if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
{
struct segment_command *seg = (struct segment_command *)loadcmds;
if (strcmp(seg->segname, "__LINKEDIT") == 0)
{
linkedit_hdr = seg;
if (symtab_hdr)
{
break;
}
}
}
else if (loadcmds->cmd == LC_SYMTAB)
{ {
symtab_hdr = (struct symtab_command *)loadcmds; symtab_hdr = (struct symtab_command *)loadcmds;
break; if (linkedit_hdr)
{
break;
}
} }
/* Load commands are not of a fixed size which is why we add the size */ /* Load commands are not of a fixed size which is why we add the size */
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize); loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
} }
if (!symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff) if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
{ {
/* Uh oh, no symbol table */ /* Uh oh, no symbol table */
return NULL; return NULL;
} }
symtab = (struct nlist *)(dlbase + symtab_hdr->symoff); linkedit_addr = dlbase + linkedit_hdr->vmaddr;
strtab = (const char *)(dlbase + symtab_hdr->stroff); symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
symbol_count = symtab_hdr->nsyms; symbol_count = symtab_hdr->nsyms;
/* Iterate symbol table starting from the position we were at last time */ /* Iterate symbol table starting from the position we were at last time */