DBGPlugInCommonELFTmpl.cpp.h revision ad27e1d5e48ca41245120c331cc88b50464813ce
/* $Id$ */
/** @file
* DBGPlugInCommonELF - Code Template for dealing with one kind of ELF.
*/
/*
* Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#if ELF_MODE == 32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Shdr Elf32_Shdr
# define Elf_Phdr Elf32_Phdr
# define MY_ELFCLASS ELFCLASS32
# define ELF_ST_BIND ELF32_ST_BIND
#else
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Shdr Elf64_Shdr
# define Elf_Phdr Elf64_Phdr
# define MY_ELFCLASS ELFCLASS64
# define ELF_ST_BIND ELF64_ST_BIND
#endif
/**
* Common ELF module parser.
*
* It takes the essential bits of the ELF module (elf header, section headers,
*
*
* @returns VBox status code.
*
* @param pVM The VM handle.
* @param pszModName The module name.
* @param pszFilename The filename. optional.
* @param fFlags Flags.
* @param pEhdr Pointer to the ELF header.
* @param paShdrs Pointer to the section headers. The caller must verify that
* the e_shnum member of the ELF header is within the bounds of
* this table. The caller should also adjust the section addresses
* so these correspond to actual load addresses.
* @param paSyms Pointer to the symbol table.
* @param cMaxSyms The maximum number of symbols paSyms may hold. This isn't
* the exact count, it's just a cap for avoiding SIGSEGVs
* and general corruption.
* @param pbStrings Pointer to the string table.
* @param cbMaxStrings The size of the memory pbStrings points to. This doesn't
* have to match the string table size exactly, it's just to
* avoid SIGSEGV when a bad string index is encountered.
* @param MinAddr Min address to care about.
* @param MaxAddr Max address to care about (inclusive). Together
* with MinAddr this forms a valid address range for
* symbols and sections that we care about. Anything
* outside the range is ignored, except when doing
* sanity checks..
* @param uModTag Module tag. Pass 0 if tagging is of no interest.
*/
int DBGDiggerCommonParseElfMod(PVM pVM, const char *pszModName, const char *pszFilename, uint32_t fFlags,
{
/*
* Validate the ELF header.
*/
return VERR_INVALID_EXE_SIGNATURE;
return VERR_LDRELF_MACHINE;
return VERR_LDRELF_ODD_ENDIAN;
return VERR_LDRELF_VERSION;
return VERR_LDRELF_VERSION;
return VERR_BAD_EXE_FORMAT;
#if ELF_MODE == 32
return VERR_LDRELF_MACHINE;
#else
return VERR_LDRELF_MACHINE;
#endif
return VERR_BAD_EXE_FORMAT;
return VERR_BAD_EXE_FORMAT;
return VERR_BAD_EXE_FORMAT;
return VERR_BAD_EXE_FORMAT;
return VERR_BAD_EXE_FORMAT;
/*
* Validate the section headers, finding the string and symbol table
* headers and the load address while at it.
*/
{
/* Minimal validation. */
return VERR_BAD_EXE_FORMAT;
/* Is it the symbol table?*/
{
if (pSymShdr)
return VERR_LDRELF_MULTIPLE_SYMTABS;
return VERR_BAD_EXE_FORMAT;
}
}
/*
* Validate the symbol table and determine the max section index
* when DBG_DIGGER_ELF_FUNNY_SHDRS is flagged.
*/
: cMaxSyms;
{
if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
{
}
/*|| paSyms[iSym].st_shndx > SHN_HIRESERVE*/
return VERR_BAD_EXE_FORMAT;
}
if (uMaxShIdx > 4096)
return VERR_BAD_EXE_FORMAT;
/*
* Create new module.
* The funny ELF section headers on solaris makes this very complicated.
*/
{
}
if (RT_FAILURE(rc))
return rc;
if (fFlags & DBG_DIGGER_ELF_FUNNY_SHDRS)
{
/* Seek out the min and max symbol values for each section. */
{
/* Ignore undefined, absolute and weak symbols in this pass,
but include local ones as well as nameless. */
{
/* Calc the address and check that it doesn't wrap with the size. */
if (AddressLast < Address)
continue;
|| AddressLast > MaxAddr)
continue;
}
}
/* Add the segments and fill in the translation table. */
for (unsigned i = 0; i < cSegs; i++)
{
char szSeg[32];
if (RT_FAILURE(rc))
break;
}
}
else
{
/* Add the segments and fill in the translation table. */
for (unsigned i = 0; i < cSegs; i++)
{
char szSeg[32];
rc = RTDbgModSegmentAdd(hMod, paShdrs[i].sh_addr - uLoadAddr, paShdrs[i].sh_size, szSeg, 0 /*fFlags*/, &paSegs[i].iSeg);
if (RT_FAILURE(rc))
break;
}
}
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Add all relevant symbols in the module
*/
{
/* Undefined symbols are not exports, they are imports. */
{
/* Get the symbol name. */
continue;
if (!*pszSymbol)
continue;
/* Calc the address (value) and size. */
else
{
if (iSeg == NIL_RTDBGSEGIDX)
continue;
}
continue;
Log(("%02x:%RGv %RGv %s!%s (rc=%Rrc)\n", paSyms[iSym].st_shndx, offSeg, cbSym, pszModName, pszSymbol, rc));
}
/*else: silently ignore */
}
/*
* Link it into the address space.
*/
if (hAs != NIL_RTDBGAS)
else
return rc;
}