Leaked source code of windows server 2003
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

/*++
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;
}