mirror of
https://github.com/reactos/reactos.git
synced 2024-10-15 13:45:58 +00:00
KDB stabs file.
svn path=/trunk/; revision=3246
This commit is contained in:
parent
e646abc58c
commit
bbeb8dbe36
899
reactos/ntoskrnl/dbg/kdb_stabs.c
Normal file
899
reactos/ntoskrnl/dbg/kdb_stabs.c
Normal file
|
@ -0,0 +1,899 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: ntoskrnl/ke/i386/exp.c
|
||||||
|
* PURPOSE: Handling exceptions
|
||||||
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||||
|
* REVISION HISTORY:
|
||||||
|
* ??/??/??: Created
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <roscfg.h>
|
||||||
|
#include <internal/ntoskrnl.h>
|
||||||
|
#include <internal/ke.h>
|
||||||
|
#include <internal/i386/segment.h>
|
||||||
|
#include <internal/i386/mm.h>
|
||||||
|
#include <internal/module.h>
|
||||||
|
#include <internal/mm.h>
|
||||||
|
#include <internal/ps.h>
|
||||||
|
#include <internal/trap.h>
|
||||||
|
#include <ntdll/ldr.h>
|
||||||
|
#include <internal/safe.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
|
||||||
|
typedef struct _SYMBOLFILE_HEADER {
|
||||||
|
unsigned long StabsOffset;
|
||||||
|
unsigned long StabsLength;
|
||||||
|
unsigned long StabstrOffset;
|
||||||
|
unsigned long StabstrLength;
|
||||||
|
} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
|
||||||
|
|
||||||
|
typedef struct _IMAGE_SYMBOL_INFO_CACHE {
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
UNICODE_STRING FullName;
|
||||||
|
PVOID FileBuffer;
|
||||||
|
PVOID SymbolsBase;
|
||||||
|
ULONG SymbolsLength;
|
||||||
|
PVOID SymbolStringsBase;
|
||||||
|
ULONG SymbolStringsLength;
|
||||||
|
} IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _STAB_ENTRY {
|
||||||
|
unsigned long n_strx; /* index into string table of name */
|
||||||
|
unsigned char n_type; /* type of symbol */
|
||||||
|
unsigned char n_other; /* misc info (usually empty) */
|
||||||
|
unsigned short n_desc; /* description field */
|
||||||
|
unsigned long n_value; /* value of symbol */
|
||||||
|
} _STAB_ENTRY, *PSTAB_ENTRY;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Desc - Line number
|
||||||
|
* Value - Relative virtual address
|
||||||
|
*/
|
||||||
|
#define N_FUN 0x24
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Desc - Line number
|
||||||
|
* Value - Relative virtual address
|
||||||
|
*/
|
||||||
|
#define N_SLINE 0x44
|
||||||
|
|
||||||
|
/*
|
||||||
|
* String - First containing a '/' is the compillation directory (CD)
|
||||||
|
* Not containing a '/' is a source file relative to CD
|
||||||
|
*/
|
||||||
|
#define N_SO 0x64
|
||||||
|
|
||||||
|
LIST_ENTRY SymbolListHead;
|
||||||
|
|
||||||
|
#endif /* DBG */
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||||
|
IN ULONG_PTR RelativeAddress,
|
||||||
|
OUT PULONG LineNumber,
|
||||||
|
OUT PCH FileName OPTIONAL,
|
||||||
|
OUT PCH FunctionName OPTIONAL);
|
||||||
|
|
||||||
|
#endif /* DBG */
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
STATIC BOOLEAN
|
||||||
|
print_user_address(PVOID address)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY current_entry;
|
||||||
|
PLDR_MODULE current;
|
||||||
|
PEPROCESS CurrentProcess;
|
||||||
|
PPEB Peb = NULL;
|
||||||
|
ULONG_PTR RelativeAddress;
|
||||||
|
#ifdef DBG
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG LineNumber;
|
||||||
|
CHAR FileName[256];
|
||||||
|
CHAR FunctionName[256];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CurrentProcess = PsGetCurrentProcess();
|
||||||
|
if (NULL != CurrentProcess)
|
||||||
|
{
|
||||||
|
Peb = CurrentProcess->Peb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == Peb)
|
||||||
|
{
|
||||||
|
DbgPrint("<%x>", address);
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_entry = Peb->Ldr->InLoadOrderModuleList.Flink;
|
||||||
|
|
||||||
|
while (current_entry != &Peb->Ldr->InLoadOrderModuleList &&
|
||||||
|
current_entry != NULL)
|
||||||
|
{
|
||||||
|
current =
|
||||||
|
CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList);
|
||||||
|
|
||||||
|
if (address >= (PVOID)current->BaseAddress &&
|
||||||
|
address < (PVOID)(current->BaseAddress + current->SizeOfImage))
|
||||||
|
{
|
||||||
|
RelativeAddress = (ULONG_PTR) address - (ULONG_PTR)current->BaseAddress;
|
||||||
|
#ifdef DBG
|
||||||
|
Status = LdrGetAddressInformation(¤t->SymbolInfo,
|
||||||
|
RelativeAddress,
|
||||||
|
&LineNumber,
|
||||||
|
FileName,
|
||||||
|
FunctionName);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DbgPrint("<%wZ: %x (%s:%d (%s))>",
|
||||||
|
¤t->BaseDllName, RelativeAddress, FileName, LineNumber, FunctionName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgPrint("<%wZ: %x>", ¤t->BaseDllName, RelativeAddress);
|
||||||
|
}
|
||||||
|
#else /* !DBG */
|
||||||
|
DbgPrint("<%wZ: %x>", ¤t->BaseDllName, RelativeAddress);
|
||||||
|
#endif /* !DBG */
|
||||||
|
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
}
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC BOOLEAN
|
||||||
|
print_address(PVOID address)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY current_entry;
|
||||||
|
MODULE_TEXT_SECTION* current;
|
||||||
|
extern LIST_ENTRY ModuleTextListHead;
|
||||||
|
ULONG_PTR RelativeAddress;
|
||||||
|
#ifdef DBG
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG LineNumber;
|
||||||
|
CHAR FileName[256];
|
||||||
|
CHAR FunctionName[256];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
current_entry = ModuleTextListHead.Flink;
|
||||||
|
|
||||||
|
while (current_entry != &ModuleTextListHead &&
|
||||||
|
current_entry != NULL)
|
||||||
|
{
|
||||||
|
current =
|
||||||
|
CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
|
||||||
|
|
||||||
|
if (address >= (PVOID)current->Base &&
|
||||||
|
address < (PVOID)(current->Base + current->Length))
|
||||||
|
{
|
||||||
|
RelativeAddress = (ULONG_PTR) address - current->Base;
|
||||||
|
#ifdef kDBG
|
||||||
|
Status = LdrGetAddressInformation(¤t->SymbolInfo,
|
||||||
|
RelativeAddress,
|
||||||
|
&LineNumber,
|
||||||
|
FileName,
|
||||||
|
FunctionName);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DbgPrint("<%ws: %x (%s:%d (%s))>",
|
||||||
|
current->Name, RelativeAddress, FileName, LineNumber, FunctionName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
|
||||||
|
}
|
||||||
|
#else /* !DBG */
|
||||||
|
DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
|
||||||
|
#endif /* !DBG */
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
}
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
|
||||||
|
VOID
|
||||||
|
PiFreeSymbols(PPEB Peb)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
PLDR_MODULE Current;
|
||||||
|
PIMAGE_SYMBOL_INFO SymbolInfo;
|
||||||
|
|
||||||
|
assert (Peb);
|
||||||
|
assert (Peb->Ldr);
|
||||||
|
|
||||||
|
CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
|
||||||
|
while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList &&
|
||||||
|
CurrentEntry != NULL)
|
||||||
|
{
|
||||||
|
Current = CONTAINING_RECORD(CurrentEntry, LDR_MODULE,
|
||||||
|
InLoadOrderModuleList);
|
||||||
|
|
||||||
|
SymbolInfo = &Current->SymbolInfo;
|
||||||
|
LdrUnloadModuleSymbols(SymbolInfo);
|
||||||
|
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KdbLdrInit(VOID)
|
||||||
|
{
|
||||||
|
#ifdef DBG
|
||||||
|
RtlZeroMemory(&NtoskrnlTextSection.SymbolInfo, sizeof(NtoskrnlTextSection.SymbolInfo));
|
||||||
|
NtoskrnlTextSection.SymbolInfo.ImageBase = OptionalHeader->ImageBase;
|
||||||
|
NtoskrnlTextSection.SymbolInfo.ImageSize = NtoskrnlTextSection.Length;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
RtlZeroMemory(&LdrHalTextSection.SymbolInfo, sizeof(LdrHalTextSection.SymbolInfo));
|
||||||
|
LdrHalTextSection.SymbolInfo.ImageBase = OptionalHeader->ImageBase;
|
||||||
|
LdrHalTextSection.SymbolInfo.ImageSize = LdrHalTextSection.Length;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
InitializeListHead(&SymbolListHead);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
|
||||||
|
VOID
|
||||||
|
LdrpParseImageSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
|
||||||
|
/* Note: It is important that the symbol strings buffer not be released after
|
||||||
|
this function is called because the strings are still referenced */
|
||||||
|
{
|
||||||
|
PSYMBOL CurrentFileNameSymbol;
|
||||||
|
PSYMBOL CurrentFunctionSymbol;
|
||||||
|
PSYMBOL CurrentLineNumberSymbol;
|
||||||
|
PSYMBOL Symbol;
|
||||||
|
PSTAB_ENTRY StabEntry;
|
||||||
|
PVOID StabsEnd;
|
||||||
|
PCHAR String;
|
||||||
|
ULONG_PTR FunRelativeAddress;
|
||||||
|
ULONG FunLineNumber;
|
||||||
|
ULONG_PTR ImageBase;
|
||||||
|
|
||||||
|
assert(SymbolInfo);
|
||||||
|
|
||||||
|
DPRINT("Parsing symbols.\n");
|
||||||
|
|
||||||
|
SymbolInfo->FileNameSymbols.SymbolCount = 0;
|
||||||
|
SymbolInfo->FileNameSymbols.Symbols = NULL;
|
||||||
|
SymbolInfo->FunctionSymbols.SymbolCount = 0;
|
||||||
|
SymbolInfo->FunctionSymbols.Symbols = NULL;
|
||||||
|
SymbolInfo->LineNumberSymbols.SymbolCount = 0;
|
||||||
|
SymbolInfo->LineNumberSymbols.Symbols = NULL;
|
||||||
|
StabsEnd = SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength;
|
||||||
|
StabEntry = (PSTAB_ENTRY) SymbolInfo->SymbolsBase;
|
||||||
|
ImageBase = SymbolInfo->ImageBase;
|
||||||
|
FunRelativeAddress = 0;
|
||||||
|
FunLineNumber = 0;
|
||||||
|
CurrentFileNameSymbol = NULL;
|
||||||
|
CurrentFunctionSymbol = NULL;
|
||||||
|
CurrentLineNumberSymbol = NULL;
|
||||||
|
while ((ULONG_PTR) StabEntry < (ULONG_PTR) StabsEnd)
|
||||||
|
{
|
||||||
|
Symbol = NULL;
|
||||||
|
|
||||||
|
if (StabEntry->n_type == N_FUN)
|
||||||
|
{
|
||||||
|
if (StabEntry->n_desc > 0)
|
||||||
|
{
|
||||||
|
assert(StabEntry->n_value >= ImageBase);
|
||||||
|
|
||||||
|
FunRelativeAddress = StabEntry->n_value - ImageBase;
|
||||||
|
FunLineNumber = StabEntry->n_desc;
|
||||||
|
|
||||||
|
Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
|
||||||
|
assert(Symbol);
|
||||||
|
Symbol->Next = NULL;
|
||||||
|
Symbol->SymbolType = ST_FUNCTION;
|
||||||
|
Symbol->RelativeAddress = FunRelativeAddress;
|
||||||
|
Symbol->LineNumber = FunLineNumber;
|
||||||
|
String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
|
||||||
|
RtlInitAnsiString(&Symbol->Name, String);
|
||||||
|
|
||||||
|
DPRINT("FUN found. '%s' %d @ %x\n",
|
||||||
|
Symbol->Name.Buffer, FunLineNumber, FunRelativeAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (StabEntry->n_type == N_SLINE)
|
||||||
|
{
|
||||||
|
Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
|
||||||
|
assert(Symbol);
|
||||||
|
Symbol->Next = NULL;
|
||||||
|
Symbol->SymbolType = ST_LINENUMBER;
|
||||||
|
Symbol->RelativeAddress = FunRelativeAddress + StabEntry->n_value;
|
||||||
|
Symbol->LineNumber = StabEntry->n_desc;
|
||||||
|
|
||||||
|
DPRINT("SLINE found. %d @ %x\n",
|
||||||
|
Symbol->LineNumber, Symbol->RelativeAddress);
|
||||||
|
}
|
||||||
|
else if (StabEntry->n_type == N_SO)
|
||||||
|
{
|
||||||
|
Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
|
||||||
|
assert(Symbol);
|
||||||
|
Symbol->Next = NULL;
|
||||||
|
Symbol->SymbolType = ST_FILENAME;
|
||||||
|
Symbol->RelativeAddress = StabEntry->n_value - ImageBase;
|
||||||
|
Symbol->LineNumber = 0;
|
||||||
|
String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
|
||||||
|
RtlInitAnsiString(&Symbol->Name, String);
|
||||||
|
|
||||||
|
DPRINT("SO found. '%s' @ %x\n",
|
||||||
|
Symbol->Name.Buffer, Symbol->RelativeAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Symbol != NULL)
|
||||||
|
{
|
||||||
|
switch (Symbol->SymbolType)
|
||||||
|
{
|
||||||
|
case ST_FILENAME:
|
||||||
|
if (SymbolInfo->FileNameSymbols.Symbols == NULL)
|
||||||
|
SymbolInfo->FileNameSymbols.Symbols = Symbol;
|
||||||
|
else
|
||||||
|
CurrentFileNameSymbol->Next = Symbol;
|
||||||
|
|
||||||
|
CurrentFileNameSymbol = Symbol;
|
||||||
|
|
||||||
|
SymbolInfo->FileNameSymbols.SymbolCount++;
|
||||||
|
break;
|
||||||
|
case ST_FUNCTION:
|
||||||
|
if (SymbolInfo->FunctionSymbols.Symbols == NULL)
|
||||||
|
SymbolInfo->FunctionSymbols.Symbols = Symbol;
|
||||||
|
else
|
||||||
|
CurrentFunctionSymbol->Next = Symbol;
|
||||||
|
|
||||||
|
CurrentFunctionSymbol = Symbol;
|
||||||
|
|
||||||
|
SymbolInfo->FunctionSymbols.SymbolCount++;
|
||||||
|
break;
|
||||||
|
case ST_LINENUMBER:
|
||||||
|
if (SymbolInfo->LineNumberSymbols.Symbols == NULL)
|
||||||
|
SymbolInfo->LineNumberSymbols.Symbols = Symbol;
|
||||||
|
else
|
||||||
|
CurrentLineNumberSymbol->Next = Symbol;
|
||||||
|
|
||||||
|
CurrentLineNumberSymbol = Symbol;
|
||||||
|
|
||||||
|
SymbolInfo->LineNumberSymbols.SymbolCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StabEntry++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
LdrpGetFileName(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||||
|
IN ULONG_PTR RelativeAddress,
|
||||||
|
OUT PCH FileName)
|
||||||
|
{
|
||||||
|
PSYMBOL NextSymbol;
|
||||||
|
ULONG_PTR NextAddress;
|
||||||
|
PSYMBOL Symbol;
|
||||||
|
|
||||||
|
Symbol = SymbolInfo->FileNameSymbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
if (NextSymbol != NULL)
|
||||||
|
NextAddress = NextSymbol->RelativeAddress;
|
||||||
|
else
|
||||||
|
NextAddress = SymbolInfo->ImageSize;
|
||||||
|
|
||||||
|
DPRINT("FN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
|
||||||
|
Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
|
||||||
|
|
||||||
|
if ((Symbol->SymbolType == ST_FILENAME) &&
|
||||||
|
(RelativeAddress >= Symbol->RelativeAddress) &&
|
||||||
|
(RelativeAddress < NextAddress))
|
||||||
|
{
|
||||||
|
DPRINT("FN found\n");
|
||||||
|
strcpy(FileName, Symbol->Name.Buffer);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("FN not found\n");
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
LdrpGetFunctionName(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||||
|
IN ULONG_PTR RelativeAddress,
|
||||||
|
OUT PCH FunctionName)
|
||||||
|
{
|
||||||
|
PSYMBOL NextSymbol;
|
||||||
|
ULONG_PTR NextAddress;
|
||||||
|
PSYMBOL Symbol;
|
||||||
|
|
||||||
|
Symbol = SymbolInfo->FunctionSymbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
if (NextSymbol != NULL)
|
||||||
|
NextAddress = NextSymbol->RelativeAddress;
|
||||||
|
else
|
||||||
|
NextAddress = SymbolInfo->ImageSize;
|
||||||
|
|
||||||
|
DPRINT("FUN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
|
||||||
|
Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
|
||||||
|
|
||||||
|
if ((Symbol->SymbolType == ST_FUNCTION) &&
|
||||||
|
(RelativeAddress >= Symbol->RelativeAddress) &&
|
||||||
|
(RelativeAddress < NextAddress))
|
||||||
|
{
|
||||||
|
PCHAR ExtraInfo;
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
DPRINT("FUN found\n");
|
||||||
|
|
||||||
|
/* Remove the extra information from the function name */
|
||||||
|
ExtraInfo = strchr(Symbol->Name.Buffer, ':');
|
||||||
|
if (ExtraInfo != NULL)
|
||||||
|
Length = ExtraInfo - Symbol->Name.Buffer;
|
||||||
|
else
|
||||||
|
Length = strlen(Symbol->Name.Buffer);
|
||||||
|
|
||||||
|
strncpy(FunctionName, Symbol->Name.Buffer, Length);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("FUN not found\n");
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
LdrpGetLineNumber(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||||
|
IN ULONG_PTR RelativeAddress,
|
||||||
|
OUT PULONG LineNumber)
|
||||||
|
{
|
||||||
|
PSYMBOL NextSymbol;
|
||||||
|
ULONG_PTR NextAddress;
|
||||||
|
PSYMBOL Symbol;
|
||||||
|
|
||||||
|
Symbol = SymbolInfo->LineNumberSymbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
if (NextSymbol != NULL)
|
||||||
|
NextAddress = NextSymbol->RelativeAddress;
|
||||||
|
else
|
||||||
|
NextAddress = SymbolInfo->ImageSize;
|
||||||
|
|
||||||
|
DPRINT("LN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
|
||||||
|
Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
|
||||||
|
|
||||||
|
if ((Symbol->SymbolType == ST_LINENUMBER) &&
|
||||||
|
(RelativeAddress >= Symbol->RelativeAddress) &&
|
||||||
|
(RelativeAddress < NextAddress))
|
||||||
|
{
|
||||||
|
DPRINT("LN found\n");
|
||||||
|
*LineNumber = Symbol->LineNumber;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("LN not found\n");
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||||
|
IN ULONG_PTR RelativeAddress,
|
||||||
|
OUT PULONG LineNumber,
|
||||||
|
OUT PCH FileName OPTIONAL,
|
||||||
|
OUT PCH FunctionName OPTIONAL)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
*LineNumber = 0;
|
||||||
|
|
||||||
|
DPRINT("RelativeAddress %p\n", RelativeAddress);
|
||||||
|
|
||||||
|
if (RelativeAddress >= SymbolInfo->ImageSize)
|
||||||
|
{
|
||||||
|
DPRINT("Address is not within .text section. RelativeAddress %p Length 0x%x\n",
|
||||||
|
RelativeAddress, SymbolInfo->ImageSize);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AreSymbolsParsed(SymbolInfo))
|
||||||
|
{
|
||||||
|
LdrpParseImageSymbols(SymbolInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = LdrpGetLineNumber(SymbolInfo, RelativeAddress, LineNumber);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileName)
|
||||||
|
{
|
||||||
|
Status = LdrpGetFileName(SymbolInfo, RelativeAddress, FileName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
strcpy(FileName, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FunctionName)
|
||||||
|
{
|
||||||
|
Status = LdrpGetFunctionName(SymbolInfo, RelativeAddress, FunctionName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
strcpy(FunctionName, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
LdrpLoadModuleSymbols(PUNICODE_STRING FileName,
|
||||||
|
PIMAGE_SYMBOL_INFO SymbolInfo)
|
||||||
|
{
|
||||||
|
FILE_STANDARD_INFORMATION FileStdInfo;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
WCHAR TmpFileName[MAX_PATH];
|
||||||
|
UNICODE_STRING SymFileName;
|
||||||
|
LPWSTR Start, Ext;
|
||||||
|
HANDLE FileHandle;
|
||||||
|
PVOID FileBuffer;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG Length;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
PSYMBOLFILE_HEADER SymbolFileHeader;
|
||||||
|
|
||||||
|
/* Get the path to the symbol store */
|
||||||
|
wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
|
||||||
|
|
||||||
|
/* Get the symbol filename from the module name */
|
||||||
|
Start = wcsrchr(FileName->Buffer, L'\\');
|
||||||
|
if (Start == NULL)
|
||||||
|
Start = FileName->Buffer;
|
||||||
|
else
|
||||||
|
Start++;
|
||||||
|
|
||||||
|
Ext = wcsrchr(FileName->Buffer, L'.');
|
||||||
|
if (Ext != NULL)
|
||||||
|
Length = Ext - Start;
|
||||||
|
else
|
||||||
|
Length = wcslen(Start);
|
||||||
|
|
||||||
|
wcsncat(TmpFileName, Start, Length);
|
||||||
|
wcscat(TmpFileName, L".sym");
|
||||||
|
RtlInitUnicodeString(&SymFileName, TmpFileName);
|
||||||
|
|
||||||
|
/* Open the file */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&SymFileName,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = ZwOpenFile(&FileHandle,
|
||||||
|
FILE_ALL_ACCESS,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Could not open symbol file: %wZ\n", &SymFileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPRINT("Loading symbols from %wZ...\n", &SymFileName);
|
||||||
|
|
||||||
|
/* Get the size of the file */
|
||||||
|
Status = ZwQueryInformationFile(FileHandle,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&FileStdInfo,
|
||||||
|
sizeof(FileStdInfo),
|
||||||
|
FileStandardInformation);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Could not get file size\n");
|
||||||
|
ZwClose(FileHandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate nonpageable memory for symbol file */
|
||||||
|
FileBuffer = ExAllocatePool(NonPagedPool,
|
||||||
|
FileStdInfo.EndOfFile.u.LowPart);
|
||||||
|
|
||||||
|
if (FileBuffer == NULL)
|
||||||
|
{
|
||||||
|
DPRINT("Could not allocate memory for symbol file\n");
|
||||||
|
ZwClose(FileHandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load file into memory chunk */
|
||||||
|
Status = ZwReadFile(FileHandle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatusBlock,
|
||||||
|
FileBuffer,
|
||||||
|
FileStdInfo.EndOfFile.u.LowPart,
|
||||||
|
0, 0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status);
|
||||||
|
ExFreePool(FileBuffer);
|
||||||
|
ZwClose(FileHandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZwClose(FileHandle);
|
||||||
|
|
||||||
|
SymbolFileHeader = (PSYMBOLFILE_HEADER) FileBuffer;
|
||||||
|
SymbolInfo->FileBuffer = FileBuffer;
|
||||||
|
SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->StabsOffset;
|
||||||
|
SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
|
||||||
|
SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset;
|
||||||
|
SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
LdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
|
||||||
|
{
|
||||||
|
PSYMBOL NextSymbol;
|
||||||
|
PSYMBOL Symbol;
|
||||||
|
|
||||||
|
DPRINT("Unloading symbols\n");
|
||||||
|
|
||||||
|
if (SymbolInfo != NULL)
|
||||||
|
{
|
||||||
|
Symbol = SymbolInfo->FileNameSymbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
RtlFreeAnsiString(&Symbol->Name);
|
||||||
|
ExFreePool(Symbol);
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolInfo->FileNameSymbols.SymbolCount = 0;
|
||||||
|
SymbolInfo->FileNameSymbols.Symbols = NULL;
|
||||||
|
|
||||||
|
Symbol = SymbolInfo->FunctionSymbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
RtlFreeAnsiString(&Symbol->Name);
|
||||||
|
ExFreePool(Symbol);
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolInfo->FunctionSymbols.SymbolCount = 0;
|
||||||
|
SymbolInfo->FunctionSymbols.Symbols = NULL;
|
||||||
|
|
||||||
|
Symbol = SymbolInfo->LineNumberSymbols.Symbols;
|
||||||
|
while (Symbol != NULL)
|
||||||
|
{
|
||||||
|
NextSymbol = Symbol->Next;
|
||||||
|
RtlFreeAnsiString(&Symbol->Name);
|
||||||
|
ExFreePool(Symbol);
|
||||||
|
Symbol = NextSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolInfo->LineNumberSymbols.SymbolCount = 0;
|
||||||
|
SymbolInfo->LineNumberSymbols.Symbols = NULL;
|
||||||
|
#if 0
|
||||||
|
/* Don't free buffers because we cache symbol buffers
|
||||||
|
(eg. they are shared across processes) */
|
||||||
|
/* FIXME: We can free them if we do reference counting */
|
||||||
|
if (SymbolInfo->FileBuffer != NULL)
|
||||||
|
{
|
||||||
|
ExFreePool(SymbolInfo->FileBuffer);
|
||||||
|
SymbolInfo->FileBuffer = NULL;
|
||||||
|
SymbolInfo->SymbolsBase = NULL;
|
||||||
|
SymbolInfo->SymbolsLength = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIMAGE_SYMBOL_INFO_CACHE
|
||||||
|
LdrpLookupUserSymbolInfo(PLDR_MODULE LdrModule)
|
||||||
|
{
|
||||||
|
PIMAGE_SYMBOL_INFO_CACHE Current;
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
DPRINT("Searching symbols for %S\n", LdrModule->FullDllName.Buffer);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ModuleListLock,&Irql);
|
||||||
|
|
||||||
|
CurrentEntry = SymbolListHead.Flink;
|
||||||
|
while (CurrentEntry != (&SymbolListHead))
|
||||||
|
{
|
||||||
|
Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
|
||||||
|
|
||||||
|
if (RtlEqualUnicodeString(&Current->FullName, &LdrModule->FullDllName, TRUE))
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&ModuleListLock, Irql);
|
||||||
|
return Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ModuleListLock, Irql);
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
LdrLoadUserModuleSymbols(PLDR_MODULE LdrModule)
|
||||||
|
{
|
||||||
|
PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
|
||||||
|
|
||||||
|
DPRINT("LdrModule %p\n", LdrModule);
|
||||||
|
|
||||||
|
RtlZeroMemory(&LdrModule->SymbolInfo, sizeof(LdrModule->SymbolInfo));
|
||||||
|
LdrModule->SymbolInfo.ImageBase = (ULONG_PTR) LdrModule->BaseAddress;
|
||||||
|
LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage;
|
||||||
|
|
||||||
|
CacheEntry = LdrpLookupUserSymbolInfo(LdrModule);
|
||||||
|
if (CacheEntry != NULL)
|
||||||
|
{
|
||||||
|
DPRINT("Symbol cache hit for %S\n", CacheEntry->FullName.Buffer);
|
||||||
|
|
||||||
|
LdrModule->SymbolInfo.FileBuffer = CacheEntry->FileBuffer;
|
||||||
|
LdrModule->SymbolInfo.SymbolsBase = CacheEntry->SymbolsBase;
|
||||||
|
LdrModule->SymbolInfo.SymbolsLength = CacheEntry->SymbolsLength;
|
||||||
|
LdrModule->SymbolInfo.SymbolStringsBase = CacheEntry->SymbolStringsBase;
|
||||||
|
LdrModule->SymbolInfo.SymbolStringsLength = CacheEntry->SymbolStringsLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CacheEntry = ExAllocatePool(NonPagedPool, sizeof(IMAGE_SYMBOL_INFO_CACHE));
|
||||||
|
assert(CacheEntry);
|
||||||
|
RtlZeroMemory(CacheEntry, sizeof(IMAGE_SYMBOL_INFO_CACHE));
|
||||||
|
RtlCreateUnicodeString(&CacheEntry->FullName, LdrModule->FullDllName.Buffer);
|
||||||
|
assert(CacheEntry->FullName.Buffer);
|
||||||
|
LdrpLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo);
|
||||||
|
InsertTailList(&SymbolListHead, &CacheEntry->ListEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DBG */
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KdbLoadDriver(VOID)
|
||||||
|
{
|
||||||
|
#ifdef DBG
|
||||||
|
/* Load symbols for the image if available */
|
||||||
|
LdrpLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo);
|
||||||
|
#endif /* DBG */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KdbUnloadDriver(VOID)
|
||||||
|
{
|
||||||
|
#ifdef DBG
|
||||||
|
/* Unload symbols for module if available */
|
||||||
|
LdrUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo);
|
||||||
|
#endif /* DBG */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KdbInitializeDriver(VOID)
|
||||||
|
{
|
||||||
|
#ifdef DBG
|
||||||
|
PSYMBOLFILE_HEADER SymbolFileHeader;
|
||||||
|
PIMAGE_SYMBOL_INFO SymbolInfo;
|
||||||
|
#endif /* DBG */
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
CHAR TmpBaseName[MAX_PATH];
|
||||||
|
CHAR TmpFileName[MAX_PATH];
|
||||||
|
ANSI_STRING AnsiString;
|
||||||
|
#endif /* DBG */
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
|
||||||
|
if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
|
||||||
|
{
|
||||||
|
DPRINT("Module %s is a symbol file\n", FileName);
|
||||||
|
|
||||||
|
strncpy(TmpBaseName, FileName, Length);
|
||||||
|
TmpBaseName[Length] = '\0';
|
||||||
|
|
||||||
|
DPRINT("base: %s (Length %d)\n", TmpBaseName, Length);
|
||||||
|
|
||||||
|
strcpy(TmpFileName, TmpBaseName);
|
||||||
|
strcat(TmpFileName, ".sys");
|
||||||
|
RtlInitAnsiString(&AnsiString, TmpFileName);
|
||||||
|
|
||||||
|
RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
|
||||||
|
ModuleObject = LdrGetModuleObject(&ModuleName);
|
||||||
|
RtlFreeUnicodeString(&ModuleName);
|
||||||
|
if (ModuleObject == NULL)
|
||||||
|
{
|
||||||
|
strcpy(TmpFileName, TmpBaseName);
|
||||||
|
strcat(TmpFileName, ".exe");
|
||||||
|
RtlInitAnsiString(&AnsiString, TmpFileName);
|
||||||
|
RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
|
||||||
|
ModuleObject = LdrGetModuleObject(&ModuleName);
|
||||||
|
RtlFreeUnicodeString(&ModuleName);
|
||||||
|
}
|
||||||
|
if (ModuleObject != NULL)
|
||||||
|
{
|
||||||
|
SymbolInfo = (PIMAGE_SYMBOL_INFO) &ModuleObject->TextSection->SymbolInfo;
|
||||||
|
SymbolFileHeader = (PSYMBOLFILE_HEADER) ModuleLoadBase;
|
||||||
|
SymbolInfo->FileBuffer = ModuleLoadBase;
|
||||||
|
SymbolInfo->SymbolsBase = ModuleLoadBase + SymbolFileHeader->StabsOffset;
|
||||||
|
SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
|
||||||
|
SymbolInfo->SymbolStringsBase = ModuleLoadBase + SymbolFileHeader->StabstrOffset;
|
||||||
|
SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Module %s is non-symbol file\n", FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !DBG */
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
RtlZeroMemory(&ModuleTextSection->SymbolInfo, sizeof(ModuleTextSection->SymbolInfo));
|
||||||
|
ModuleTextSection->SymbolInfo.ImageBase = PEOptionalHeader->ImageBase;
|
||||||
|
ModuleTextSection->SymbolInfo.ImageSize = ModuleTextSection->Length;
|
||||||
|
#endif /* DBG */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DBG */
|
Loading…
Reference in a new issue