DBGPlugInSolaris.cpp revision 6ec4e1827eab6a424d672ef0e5a17b065e52db20
/* $Id$ */
/** @file
* DBGPlugInSolaris - Debugger and Guest OS Digger Plugin For Solaris.
*/
/*
* 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "DBGPlugIns.h"
#include "DBGPlugInCommonELF.h"
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/** Solaris on little endian ASCII systems. */
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** @name InternalSolaris structures
* @{ */
typedef struct SOL32v11_modctl
{
typedef struct SOL64v11_modctl
{
typedef struct SOL32v9_modctl
{
/* DIFF 4: 4 bytes added in v11 */
/* DIFF 5: 8 bytes added in v11 */
typedef struct SOL64v9_modctl
{
/* DIFF 5: 8 bytes added in v11 */
typedef union SOL_modctl
{
} SOL_modctl_t;
typedef struct SOL32_module
{
typedef struct SOL64_module
{
typedef struct SOL_utsname
{
char sysname[257];
char nodename[257];
char release[257];
char version[257];
char machine[257];
/** @} */
/**
* Solaris guest OS digger instance data.
*/
typedef struct DBGDIGGERSOLARIS
{
/** Whether the information is valid or not.
* (For fending off illegal interface method calls.) */
bool fValid;
/** Address of the 'unix' text segment.
* This is set during probing. */
/** Address of the 'unix' text segment.
* This is set during probing. */
/** Address of the 'unix' modctl_t (aka modules). */
/** modctl_t version number. */
int iModCtlVer;
/** 64-bit/32-bit indicator. */
bool f64Bit;
/** Pointer to the solaris guest OS digger instance data. */
typedef DBGDIGGERSOLARIS *PDBGDIGGERSOLARIS;
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/** Min kernel address. */
/** Max kernel address. */
/** Min kernel address. */
/** Max kernel address. */
/** Validates a 32-bit solaris kernel address */
#if 0 /* OpenSolaris, early boot have symspace at 0x27a2000 */
#else
# define SOL32_VALID_ADDRESS(Addr) ( ((Addr) > SOL32_MIN_KRNL_ADDR && (Addr) < SOL32_MAX_KRNL_ADDR) \
#endif
/** Validates a 64-bit solaris kernel address */
&& (Addr) < SOL64_MAX_KRNL_ADDR)
/** The max data segment size of the 'unix' module. */
#define SOL_UNIX_MAX_DATA_SEG_SIZE 0x01000000
/** The max code segment size of the 'unix' module.
* This is the same for both 64-bit and 32-bit. */
#define SOL_UNIX_MAX_CODE_SEG_SIZE 0x00400000
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/**
* @copydoc DBGFOSREG::pfnQueryInterface
*/
static DECLCALLBACK(void *) dbgDiggerSolarisQueryInterface(PVM pVM, void *pvData, DBGFOSINTERFACE enmIf)
{
return NULL;
}
/**
* @copydoc DBGFOSREG::pfnQueryVersion
*/
static DECLCALLBACK(int) dbgDiggerSolarisQueryVersion(PVM pVM, void *pvData, char *pszVersion, size_t cchVersion)
{
/*
* It's all in the utsname symbol...
*/
if (RT_SUCCESS(rc))
rc = DBGFR3MemRead(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, SymUtsName.Value), &UtsName, sizeof(UtsName));
if (RT_FAILURE(rc))
{
/*
* Try searching by the name...
*/
if (RT_SUCCESS(rc))
rc = DBGFR3MemRead(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, Addr.FlatPtr - RT_OFFSETOF(SOL_utsname_t, sysname)),
}
/*
* Copy out the result (if any).
*/
if (RT_SUCCESS(rc))
{
{
//rc = VERR_DBGF_UNEXPECTED_OS_DATA;
}
else
}
else
return rc;
}
/**
* Processes a modctl_t.
*
* @param pVM The VM handle.
* @param pThis Our instance data.
* @param pModCtl Pointer to the modctl structure.
*/
static void dbgDiggerSolarisProcessModCtl32(PVM pVM, PDBGDIGGERSOLARIS pThis, SOL_modctl_t const *pModCtl)
{
/* skip it if it's not loaded and installed */
return;
/*
* Read the module and file names first
*/
char szModName[64];
int rc = DBGFR3MemReadString(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, pModCtl->v9_32.mod_modname), szModName, sizeof(szModName));
if (RT_FAILURE(rc))
return;
char szFilename[256];
rc = DBGFR3MemReadString(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, pModCtl->v9_32.mod_filename), szFilename, sizeof(szFilename));
if (RT_FAILURE(rc))
/*
* Then read the module struct and validate it.
*/
struct SOL32_module Module;
rc = DBGFR3MemRead(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, pModCtl->v9_32.mod_mp), &Module, sizeof(Module));
if (RT_FAILURE(rc))
return;
/* Basic validations of the elf header. */
)
return;
return;
return;
return;
return;
return;
return;
return;
/* Basic validations of the rest of the stuff. */
return;
return;
/* Ignore modules without symbols. */
return;
/* Check that the symtbl and strings points inside the symspace. */
return;
return;
/*
* Read the section headers, symbol table and string tables.
*/
if (!paShdrs)
return;
if (RT_SUCCESS(rc))
{
if (pvSymSpace)
{
rc = DBGFR3MemRead(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, Module.symspace), pvSymSpace, Module.symsize);
if (RT_SUCCESS(rc))
{
/*
* Hand it over to the common ELF32 module parser.
*/
Elf32_Sym const *paSyms = (Elf32_Sym const *)((uintptr_t)pvSymSpace + (Module.symtbl - Module.symspace));
}
}
}
return;
}
/**
* Processes a modctl_t.
*
* @param pVM The VM handle.
* @param pThis Our instance data.
* @param pModCtl Pointer to the modctl structure.
*/
static void dbgDiggerSolarisProcessModCtl64(PVM pVM, PDBGDIGGERSOLARIS pThis, SOL_modctl_t const *pModCtl)
{
/* skip it if it's not loaded and installed */
return;
/*
* Read the module and file names first
*/
char szModName[64];
int rc = DBGFR3MemReadString(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, pModCtl->v9_64.mod_modname), szModName, sizeof(szModName));
if (RT_FAILURE(rc))
return;
char szFilename[256];
rc = DBGFR3MemReadString(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, pModCtl->v9_64.mod_filename), szFilename, sizeof(szFilename));
if (RT_FAILURE(rc))
/*
* Then read the module struct and validate it.
*/
struct SOL64_module Module;
rc = DBGFR3MemRead(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, pModCtl->v9_64.mod_mp), &Module, sizeof(Module));
if (RT_FAILURE(rc))
return;
/* Basic validations of the elf header. */
)
return;
return;
return;
return;
return;
return;
return;
return;
/* Basic validations of the rest of the stuff. */
return;
return;
/* Ignore modules without symbols. */
return;
/* Check that the symtbl and strings points inside the symspace. */
return;
return;
/*
* Read the section headers, symbol table and string tables.
*/
if (!paShdrs)
return;
if (RT_SUCCESS(rc))
{
if (pvSymSpace)
{
rc = DBGFR3MemRead(pVM, 0, DBGFR3AddrFromFlat(pVM, &Addr, Module.symspace), pvSymSpace, Module.symsize);
if (RT_SUCCESS(rc))
{
/*
* Hand it over to the common ELF64 module parser.
*/
Elf64_Sym const *paSyms = (Elf64_Sym const *)((uintptr_t)pvSymSpace + (uintptr_t)(Module.symtbl - Module.symspace));
}
}
}
return;
}
/**
* @copydoc DBGFOSREG::pfnTerm
*/
{
}
/**
* @copydoc DBGFOSREG::pfnRefresh
*/
{
/*
* For now we'll flush and reload everything.
*/
if (hDbgAs != NIL_RTDBGAS)
{
while (iMod-- > 0)
{
if (hMod != NIL_RTDBGMOD)
{
{
}
}
}
}
}
/**
* @copydoc DBGFOSREG::pfnInit
*/
{
int rc;
/*
* On Solaris the kernel and is the global address space.
*/
/** @todo Use debug_info, build 7x / S10U6. */
/*
* Find the 'unix' modctl_t structure (aka modules).
* We know it resides in the unix data segment.
*/
{
rc = DBGFR3MemScan(pVM, 0, &CurAddr, MaxAddr.FlatPtr - CurAddr.FlatPtr, 1, pbExpr, cbExpr, &HitAddr);
if (RT_FAILURE(rc))
break;
/*
* Read out the modctl_t structure.
*/
/* v11 */
{
if (RT_SUCCESS(rc))
{
&& ModCtlv11.mod_requisites == 0
/*&& ModCtlv11.mod_text == pThis->AddrUnixText.FlatPtr*/
{
char szUnix[5];
if (RT_SUCCESS(rc))
{
{
break;
}
}
}
}
}
else
{
if (RT_SUCCESS(rc))
{
&& ModCtlv11.mod_requisites == 0
/*&& ModCtlv11.mod_text == pThis->AddrUnixText.FlatPtr*/
{
char szUnix[5];
if (RT_SUCCESS(rc))
{
{
break;
}
}
}
}
}
/* v9 */
{
if (RT_SUCCESS(rc))
{
&& ModCtlv9.mod_requisites == 0
/*&& ModCtlv9.mod_text == pThis->AddrUnixText.FlatPtr*/
{
char szUnix[5];
if (RT_SUCCESS(rc))
{
{
break;
}
}
}
}
}
else
{
if (RT_SUCCESS(rc))
{
&& ModCtlv9.mod_requisites == 0
/*&& ModCtlv9.mod_text == pThis->AddrUnixText.FlatPtr*/
{
char szUnix[5];
if (RT_SUCCESS(rc))
{
{
break;
}
}
}
}
}
/* next */
}
/*
* Walk the module chain and add the modules and their symbols.
*/
{
int iMod = 0;
do
{
/* read it */
if (RT_FAILURE(rc))
{
break;
}
/* process it. */
else
/* next */
{
{
LogRel(("sol64: bad modctl_t chain at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.v9_64.mod_next));
break;
}
}
else
{
{
LogRel(("sol32: bad modctl_t chain at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.v9_32.mod_next));
break;
}
}
if (++iMod >= 1024)
{
break;
}
}
return VINF_SUCCESS;
}
/**
* @copydoc DBGFOSREG::pfnProbe
*/
{
/*
* Look for "SunOS Release" in the text segment.
*/
bool f64Bit = false;
/* 32-bit search range. */
int rc = DBGFR3MemScan(pVM, 0, &Addr, cbRange, 1, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
if (RT_FAILURE(rc))
{
/* 64-bit.... */
rc = DBGFR3MemScan(pVM, 0, &Addr, cbRange, 1, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
if (RT_FAILURE(rc))
return false;
f64Bit = true;
}
/*
* Look for the copy right string too, just to be sure.
*/
if (RT_FAILURE(rc))
return false;
/*
* Remember the unix text and data addresses and bitness.
*/
return true;
}
/**
* @copydoc DBGFOSREG::pfnDestruct
*/
{
}
/**
* @copydoc DBGFOSREG::pfnConstruct
*/
{
return VINF_SUCCESS;
}
const DBGFOSREG g_DBGDiggerSolaris =
{
/* .u32Magic = */ DBGFOSREG_MAGIC,
/* .fFlags = */ 0,
/* .cbData = */ sizeof(DBGDIGGERSOLARIS),
/* .szName = */ "Solaris",
/* .pfnConstruct = */ dbgDiggerSolarisConstruct,
/* .pfnDestruct = */ dbgDiggerSolarisDestruct,
/* .pfnProbe = */ dbgDiggerSolarisProbe,
/* .pfnInit = */ dbgDiggerSolarisInit,
/* .pfnRefresh = */ dbgDiggerSolarisRefresh,
/* .pfnTerm = */ dbgDiggerSolarisTerm,
/* .pfnQueryVersion = */ dbgDiggerSolarisQueryVersion,
/* .pfnQueryInterface = */ dbgDiggerSolarisQueryInterface,
/* .u32EndMagic = */ DBGFOSREG_MAGIC
};