You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
376 lines
7.0 KiB
376 lines
7.0 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
vsym.c
|
|
|
|
Abstract:
|
|
|
|
This function implements virtual symbols that can be added by the caller.
|
|
|
|
Author:
|
|
|
|
Pat Styles (patst) 5-June-2001
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#include "private.h"
|
|
#include "symbols.h"
|
|
#include "globals.h"
|
|
|
|
|
|
int __cdecl
|
|
vsCompareAddrs(
|
|
const void *one,
|
|
const void *two
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs1 = (PVIRTUAL_SYMBOL)one;
|
|
PVIRTUAL_SYMBOL vs2 = (PVIRTUAL_SYMBOL)two;
|
|
|
|
if (vs2->addr > vs1->addr)
|
|
return -1;
|
|
|
|
if (vs1->addr > vs2->addr)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
vsAddSymbol(
|
|
PMODULE_ENTRY mi,
|
|
PCSTR name,
|
|
DWORD64 addr,
|
|
DWORD size
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
DWORD i;
|
|
|
|
// look for another symbol at the same address
|
|
|
|
vs = vsGetSymbol(mi, NULL, addr);
|
|
if (vs) {
|
|
SetLastError(ERROR_ALREADY_EXISTS);
|
|
return false;
|
|
}
|
|
|
|
// look for an empty slot in the already existing list
|
|
|
|
vs = vsBlankSymbol(mi);
|
|
|
|
// not found: allow a new list or realloc to new size
|
|
|
|
if (!vs) {
|
|
i = mi->cvs + 1;
|
|
if (!mi->vs) {
|
|
assert(mi->cvs == 0);
|
|
vs = (PVIRTUAL_SYMBOL)MemAlloc(sizeof(VIRTUAL_SYMBOL));
|
|
|
|
} else {
|
|
assert(mi->cvs);
|
|
vs = (PVIRTUAL_SYMBOL)MemReAlloc(mi->vs, i * sizeof(VIRTUAL_SYMBOL));
|
|
}
|
|
|
|
if (!vs) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return false;
|
|
}
|
|
|
|
// reset the pointer and increment the count
|
|
|
|
mi->vs = vs;
|
|
vs = mi->vs + mi->cvs;
|
|
mi->cvs++;
|
|
}
|
|
|
|
// copy in the new symbol
|
|
|
|
CopyStrArray(vs->name, name);
|
|
vs->addr = addr;
|
|
vs->size = size;
|
|
|
|
qsort(mi->vs, mi->cvs, sizeof(VIRTUAL_SYMBOL), vsCompareAddrs);
|
|
|
|
mi->SymLoadError = SYMLOAD_OK;
|
|
return true;
|
|
}
|
|
|
|
|
|
BOOL
|
|
vsMatchSymbol(
|
|
PVIRTUAL_SYMBOL vs,
|
|
PCSTR name,
|
|
DWORD64 addr
|
|
)
|
|
{
|
|
// Look for a mismatch in either name or addr.
|
|
|
|
if (name && *name && strcmp(vs->name, name))
|
|
return false;
|
|
|
|
if (addr && vs->addr != addr)
|
|
return false;
|
|
|
|
// When passing a null name and addr, we are looking
|
|
// for a blank entry. Check if addr is zero.
|
|
|
|
if (!name && !addr && vs->addr)
|
|
return false;
|
|
|
|
// hit!
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
PVIRTUAL_SYMBOL
|
|
vsGetSymbol(
|
|
PMODULE_ENTRY mi,
|
|
PCSTR name,
|
|
DWORD64 addr
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
DWORD i;
|
|
|
|
for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
|
|
if (vsMatchSymbol(vs, name, addr))
|
|
return vs;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BOOL
|
|
vsDeleteSymbol(
|
|
PMODULE_ENTRY mi,
|
|
PCSTR name,
|
|
DWORD64 addr
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
DWORD i;
|
|
|
|
// look for an empty slot in the already existing list
|
|
|
|
vs = NULL;
|
|
for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
|
|
if (vsMatchSymbol(vs, name, addr)) {
|
|
vs->addr = 0;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
SetLastError(ERROR_NOT_FOUND);
|
|
return false;
|
|
}
|
|
|
|
|
|
BOOL
|
|
vsDumpSymbols(
|
|
PMODULE_ENTRY mi
|
|
)
|
|
// for debugging...
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
DWORD i;
|
|
|
|
if (!mi->vs)
|
|
return false;
|
|
|
|
for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
|
|
if (vs->addr)
|
|
dtrace("%s %I64lx\n", vs->name, vs->addr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
BOOL
|
|
vsFillSymbolInfo(
|
|
PSYMBOL_INFO si,
|
|
PMODULE_ENTRY mi,
|
|
PVIRTUAL_SYMBOL vs
|
|
)
|
|
{
|
|
DWORD dw;
|
|
|
|
dw = si->MaxNameLen;
|
|
ZeroMemory(si, sizeof(SYMBOL_INFO));
|
|
si->MaxNameLen = dw;
|
|
|
|
CopyString(si->Name, vs->name, si->MaxNameLen);
|
|
si->ModBase = mi->BaseOfDll;
|
|
si->Address = vs->addr;
|
|
si->Size = vs->size;
|
|
si->Flags = SYMFLAG_VIRTUAL;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
BOOL
|
|
vsGetSymbols(
|
|
IN PPROCESS_ENTRY pe,
|
|
IN PMODULE_ENTRY mi,
|
|
IN PCSTR mask,
|
|
IN DWORD64 addr,
|
|
IN PROC callback,
|
|
IN PVOID context,
|
|
IN BOOL use64,
|
|
IN BOOL unicode
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
DWORD i;
|
|
BOOL fCase;
|
|
BOOL rc;
|
|
|
|
if (!mi->vs)
|
|
return callback ? true : false;
|
|
|
|
fCase = option(SYMOPT_CASE_INSENSITIVE) ? false : true;
|
|
|
|
for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
|
|
if (mask && *mask && strcmpre(vs->name, mask, fCase))
|
|
continue;
|
|
if (addr && (vs->addr != addr))
|
|
continue;
|
|
vsFillSymbolInfo(&mi->vssi, mi, vs);
|
|
if (!callback)
|
|
return true;
|
|
rc = DoEnumCallback(pe, &mi->vssi, mi->vssi.Size, callback, context, use64, unicode);
|
|
if (!rc) {
|
|
mi->code = ERROR_CANCELLED;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return callback ? true : false;
|
|
}
|
|
|
|
|
|
PSYMBOL_INFO
|
|
vsFindSymbolByName(
|
|
PPROCESS_ENTRY pe,
|
|
PMODULE_ENTRY mi,
|
|
LPSTR SymName
|
|
)
|
|
{
|
|
if (!vsGetSymbols(pe, mi, SymName, 0, NULL, NULL, 0, 0))
|
|
return NULL;
|
|
|
|
if (!mi)
|
|
mi = pe->ipmi;
|
|
|
|
return &mi->vssi;
|
|
}
|
|
|
|
|
|
PSYMBOL_INFO
|
|
vsGetSymNextPrev(
|
|
PMODULE_ENTRY mi,
|
|
DWORD64 addr,
|
|
BOOL direction
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
PVIRTUAL_SYMBOL vsprev;
|
|
DWORD i;
|
|
|
|
// no entries, bail
|
|
|
|
if (!mi->cvs)
|
|
return NULL;
|
|
|
|
// walk to the entry with a higher address
|
|
|
|
vsprev = NULL;
|
|
for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
|
|
if (vs->addr < addr)
|
|
vsprev = vs;
|
|
if (vs->addr > addr)
|
|
break;
|
|
}
|
|
|
|
if (direction < 0)
|
|
vs = vsprev;
|
|
else if (i == mi->cvs)
|
|
return NULL;
|
|
|
|
if (!vs)
|
|
return NULL;
|
|
|
|
vsFillSymbolInfo(&mi->vssi, mi, vs);
|
|
return &mi->vssi;
|
|
}
|
|
|
|
|
|
PSYMBOL_INFO
|
|
vsGetSymFromAddr(
|
|
PMODULE_ENTRY mi,
|
|
DWORD64 addr,
|
|
PDWORD64 disp
|
|
)
|
|
{
|
|
PVIRTUAL_SYMBOL vs;
|
|
DWORD i;
|
|
|
|
// find the entry with a higher address
|
|
|
|
for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
|
|
if (vs->addr > addr)
|
|
break;
|
|
}
|
|
|
|
// no hit, bail
|
|
|
|
if (!i)
|
|
return NULL;
|
|
|
|
// rewind back to the hit.
|
|
// If the symbol has a size, make sure we're within the limits.
|
|
|
|
vs--;
|
|
if (vs->size && (vs->addr + vs->size) < addr)
|
|
return NULL;
|
|
|
|
// bullseye!
|
|
|
|
vsFillSymbolInfo(&mi->vssi, mi, vs);
|
|
if (disp)
|
|
*disp = addr - mi->vssi.Address;
|
|
return &mi->vssi;
|
|
}
|
|
|
|
|
|
PSYMBOL_ENTRY
|
|
vsGetSymEntryFromAddr(
|
|
PMODULE_ENTRY mi,
|
|
DWORD64 addr,
|
|
PDWORD64 disp
|
|
)
|
|
{
|
|
PSYMBOL_INFO si;
|
|
|
|
si = vsGetSymFromAddr(mi, addr, disp);
|
|
if (!si)
|
|
return NULL;
|
|
|
|
si2se(si, &mi->vsTmpSym);
|
|
if (disp)
|
|
*disp = addr - si->Address;
|
|
return &mi->vsTmpSym;
|
|
}
|
|
|