mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 17:10:22 +00:00
Change stabs handling of KDB - does no longer allocate a block of memory for each stub entry, instead each .sym file is loaded completely into (non-paged) memory.
svn path=/trunk/; revision=10692
This commit is contained in:
parent
66ff876aa8
commit
87bdedbed2
12 changed files with 1227 additions and 963 deletions
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.139 2004/08/15 16:38:59 chorns Exp $
|
||||
# $Id: Makefile,v 1.140 2004/08/26 16:04:49 blight Exp $
|
||||
#
|
||||
# ReactOS Operating System
|
||||
#
|
||||
|
@ -33,7 +33,7 @@ endif
|
|||
|
||||
ifeq ($(KDBG), 1)
|
||||
OBJECTS_KDBG := dbg/kdb.o dbg/kdb_serial.o dbg/kdb_keyboard.o dbg/rdebug.o \
|
||||
dbg/i386/kdb_help.o dbg/kdb_stabs.o dbg/profile.o \
|
||||
dbg/i386/kdb_help.o dbg/kdb_stabs.o dbg/kdb_symbols.o dbg/profile.o \
|
||||
../dk/w32/lib/kjs.a dbg/i386/i386-dis.o
|
||||
CFLAGS += -I../lib/kjs/include
|
||||
preall: all
|
||||
|
|
|
@ -63,10 +63,8 @@ NtSystemDebugControl(DEBUG_CONTROL_CODE ControlCode,
|
|||
case DebugQuerySpecialCalls:
|
||||
case DebugDbgBreakPoint:
|
||||
break;
|
||||
#ifdef KDBG
|
||||
case DebugDbgLoadSymbols:
|
||||
KdbLdrLoadUserModuleSymbols((PLDR_MODULE) InputBuffer);
|
||||
#endif /* KDBG */
|
||||
KDB_LOADUSERMODULE_HOOK((PLDR_MODULE) InputBuffer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -35,7 +35,7 @@ extern void DbgPrint(const char *format, ...);
|
|||
#define sprintf_vma(BUF, VMA) sprintf(BUF, "0x%X", VMA)
|
||||
#define _setjmp setjmp
|
||||
unsigned int
|
||||
KdbPrintAddress(void* address);
|
||||
KdbSymPrintAddress(void* address);
|
||||
|
||||
struct disassemble_info;
|
||||
|
||||
|
@ -79,7 +79,7 @@ KdbMemoryError(int Status, unsigned int Addr,
|
|||
void static
|
||||
KdbPrintAddressInCode(unsigned int Addr, struct disassemble_info * Ignored)
|
||||
{
|
||||
if (!KdbPrintAddress((void*)Addr))
|
||||
if (!KdbSymPrintAddress((void*)Addr))
|
||||
{
|
||||
DbgPrint("<0x%X>", Addr);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2001 David Welch <welch@cwcom.net>
|
||||
* Copyright (C) 2001-2004 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
|
||||
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: kdb.c,v 1.28 2004/08/15 16:39:00 chorns Exp $
|
||||
/* $Id: kdb.c,v 1.29 2004/08/26 16:04:49 blight Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/dbg/kdb.c
|
||||
|
@ -741,7 +741,7 @@ DbgDisassemble(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf)
|
|||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if (!KdbPrintAddress((PVOID)Address))
|
||||
if (!KdbSymPrintAddress((PVOID)Address))
|
||||
{
|
||||
DbgPrint("<%x>", Address);
|
||||
}
|
||||
|
@ -832,7 +832,7 @@ DbgPrintBackTrace(PULONG Frame, ULONG StackBase, ULONG StackLimit)
|
|||
while (Frame != NULL && (ULONG)Frame >= StackLimit &&
|
||||
(ULONG)Frame < StackBase)
|
||||
{
|
||||
KdbPrintAddress((PVOID)Frame[1]);
|
||||
KdbSymPrintAddress((PVOID)Frame[1]);
|
||||
DbgPrint("\n");
|
||||
Frame = (PULONG)Frame[0];
|
||||
i++;
|
||||
|
@ -852,7 +852,7 @@ DbgAddrCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME tf)
|
|||
if (Argc == 2)
|
||||
{
|
||||
Addr = (PVOID)strtoul(Argv[1], NULL, 0);
|
||||
KdbPrintAddress(Addr);
|
||||
KdbSymPrintAddress(Addr);
|
||||
}
|
||||
|
||||
return(1);
|
||||
|
@ -1499,7 +1499,7 @@ KdbMainLoop(PKTRAP_FRAME Tf)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!KdbPrintAddress((PVOID)Tf->Eip))
|
||||
if (!KdbSymPrintAddress((PVOID)Tf->Eip))
|
||||
{
|
||||
DbgPrint("<%x>", Tf->Eip);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,47 @@
|
|||
#define NTOS_MODE_KERNEL
|
||||
#include <ntos.h>
|
||||
|
||||
typedef struct _KDB_MODULE_INFO
|
||||
{
|
||||
WCHAR Name[256];
|
||||
ULONG_PTR Base;
|
||||
ULONG Size;
|
||||
PIMAGE_SYMBOL_INFO SymbolInfo;
|
||||
} KDB_MODULE_INFO, *PKDB_MODULE_INFO;
|
||||
|
||||
/* from kdb_symbols.c */
|
||||
|
||||
BOOLEAN
|
||||
KdbpSymFindModuleByAddress(IN PVOID Address,
|
||||
OUT PKDB_MODULE_INFO pInfo);
|
||||
|
||||
BOOLEAN
|
||||
KdbpSymFindModuleByName(IN LPCWSTR Name,
|
||||
OUT PKDB_MODULE_INFO pInfo);
|
||||
|
||||
BOOLEAN
|
||||
KdbpSymFindModuleByIndex(IN INT Index,
|
||||
OUT PKDB_MODULE_INFO pInfo);
|
||||
|
||||
BOOLEAN
|
||||
KdbSymPrintAddress(IN PVOID Address);
|
||||
|
||||
NTSTATUS
|
||||
LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
IN ULONG_PTR RelativeAddress,
|
||||
OUT PULONG LineNumber,
|
||||
OUT PULONG LineNumber OPTIONAL,
|
||||
OUT PCH FileName OPTIONAL,
|
||||
OUT PCH FunctionName OPTIONAL);
|
||||
|
||||
BOOLEAN
|
||||
KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
IN PCHAR FileName,
|
||||
IN ULONG LineNumber OPTIONAL,
|
||||
IN PCHAR FuncName OPTIONAL,
|
||||
OUT PVOID *Address);
|
||||
|
||||
/* other functions */
|
||||
|
||||
CHAR
|
||||
KdbTryGetCharKeyboard(PULONG ScanCode);
|
||||
ULONG
|
||||
|
|
File diff suppressed because it is too large
Load diff
69
reactos/ntoskrnl/dbg/kdb_stabs.h
Normal file
69
reactos/ntoskrnl/dbg/kdb_stabs.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
#ifndef __KDB_STABS_H__
|
||||
#define __KDB_STABS_H__
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* String - Function name with type information
|
||||
* Desc - Line number
|
||||
* Value - Absolute virtual address
|
||||
*/
|
||||
#define N_FUN 0x24
|
||||
|
||||
/*
|
||||
* Desc - Line number
|
||||
* Value - Relative virtual address
|
||||
*/
|
||||
#define N_SLINE 0x44
|
||||
|
||||
/*
|
||||
* String - First ending with a '/' is the compillation directory (CD)
|
||||
* Not ending with a '/' is a source file relative to CD
|
||||
*/
|
||||
#define N_SO 0x64
|
||||
|
||||
/*
|
||||
* String - Variable name with type information
|
||||
* Value - Register
|
||||
*/
|
||||
#define N_RSYM 0x40
|
||||
|
||||
/*
|
||||
* String - Variable name with type information
|
||||
* Value - Offset of variable within local variables (from %ebp)
|
||||
*/
|
||||
#define N_LSYM 0x80
|
||||
|
||||
#define N_SOL 0x84
|
||||
|
||||
|
||||
#define N_PSYM 0xa0
|
||||
|
||||
/*
|
||||
* Value - Start address of code block
|
||||
*/
|
||||
#define N_LBRAC 0xc0
|
||||
|
||||
/*
|
||||
* Value - End address of code block
|
||||
*/
|
||||
#define N_RBRAC 0xe0
|
||||
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
PSTAB_ENTRY
|
||||
KdbpStabFindEntry(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
IN CHAR Type,
|
||||
IN PVOID RelativeAddress OPTIONAL,
|
||||
IN PSTAB_ENTRY StartEntry OPTIONAL);
|
||||
|
||||
#endif /* __KDB_STABS_H__ */
|
991
reactos/ntoskrnl/dbg/kdb_symbols.c
Normal file
991
reactos/ntoskrnl/dbg/kdb_symbols.c
Normal file
|
@ -0,0 +1,991 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 1998-2004 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/dbg/kdb_symbols.c
|
||||
* PURPOSE: Getting symbol information...
|
||||
* 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>
|
||||
#include <internal/kd.h>
|
||||
#include <rosrtl/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "kdb.h"
|
||||
#include "kdb_stabs.h"
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
typedef struct _SYMBOLFILE_HEADER {
|
||||
ULONG StabsOffset;
|
||||
ULONG StabsLength;
|
||||
ULONG StabstrOffset;
|
||||
ULONG StabstrLength;
|
||||
} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
|
||||
|
||||
typedef struct _IMAGE_SYMBOL_INFO_CACHE {
|
||||
LIST_ENTRY ListEntry;
|
||||
ULONG RefCount;
|
||||
UNICODE_STRING FileName;
|
||||
PVOID FileBuffer;
|
||||
PVOID SymbolsBase;
|
||||
ULONG SymbolsLength;
|
||||
PVOID SymbolStringsBase;
|
||||
ULONG SymbolStringsLength;
|
||||
} IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
|
||||
|
||||
|
||||
static LIST_ENTRY SymbolFileListHead;
|
||||
static KSPIN_LOCK SymbolFileListLock;
|
||||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/*! \brief Find a user-mode module...
|
||||
*
|
||||
* \param Address If \a Address is not NULL the module containing \a Address
|
||||
* is searched.
|
||||
* \param Name If \a Name is not NULL the module named \a Name will be
|
||||
* searched.
|
||||
* \param Index If \a Index is >= 0 the Index'th module will be returned.
|
||||
* \param pInfo Pointer to a KDB_MODULE_INFO which is filled.
|
||||
*
|
||||
* \retval TRUE Module was found, \a pInfo was filled.
|
||||
* \retval FALSE No module was found.
|
||||
*
|
||||
* \sa KdbpSymFindModule
|
||||
*/
|
||||
STATIC BOOLEAN
|
||||
KdbpSymFindUserModule(IN PVOID Address OPTIONAL,
|
||||
IN LPCWSTR Name OPTIONAL,
|
||||
IN INT Index OPTIONAL,
|
||||
OUT PKDB_MODULE_INFO pInfo)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
PLDR_MODULE current;
|
||||
PEPROCESS CurrentProcess;
|
||||
PPEB Peb = NULL;
|
||||
INT Count = 0;
|
||||
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
if (CurrentProcess != NULL)
|
||||
{
|
||||
Peb = CurrentProcess->Peb;
|
||||
}
|
||||
|
||||
if (Peb == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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 != NULL && (Address >= (PVOID)current->BaseAddress &&
|
||||
Address < (PVOID)((char *)current->BaseAddress + current->SizeOfImage))) ||
|
||||
(Name != NULL && _wcsicmp(current->BaseDllName.Buffer, Name) == 0) ||
|
||||
(Index >= 0 && Count++ == Index))
|
||||
{
|
||||
INT Length = current->BaseDllName.Length;
|
||||
if (Length > 255)
|
||||
Length = 255;
|
||||
wcsncpy(pInfo->Name, current->BaseDllName.Buffer, Length);
|
||||
pInfo->Name[Length] = L'\0';
|
||||
pInfo->Base = (ULONG_PTR)current->BaseAddress;
|
||||
pInfo->Size = current->SizeOfImage;
|
||||
pInfo->SymbolInfo = ¤t->SymbolInfo;
|
||||
return TRUE;
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*! \brief Find a kernel-mode module...
|
||||
*
|
||||
* Works like \a KdbpSymFindUserModule.
|
||||
*
|
||||
* \sa KdbpSymFindUserModule
|
||||
*/
|
||||
STATIC BOOLEAN
|
||||
KdbpSymFindModule(IN PVOID Address OPTIONAL,
|
||||
IN LPCWSTR Name OPTIONAL,
|
||||
IN INT Index OPTIONAL,
|
||||
OUT PKDB_MODULE_INFO pInfo)
|
||||
{
|
||||
PLIST_ENTRY current_entry;
|
||||
MODULE_TEXT_SECTION* current;
|
||||
extern LIST_ENTRY ModuleTextListHead;
|
||||
INT Count = 0;
|
||||
|
||||
current_entry = ModuleTextListHead.Flink;
|
||||
|
||||
while (current_entry != &ModuleTextListHead &&
|
||||
current_entry != NULL)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
|
||||
|
||||
if ((Address != NULL && (Address >= (PVOID)current->Base &&
|
||||
Address < (PVOID)(current->Base + current->Length))) ||
|
||||
(Name != NULL && _wcsicmp(current->Name, Name) == 0) ||
|
||||
(Index >= 0 && Count++ == Index))
|
||||
{
|
||||
wcsncpy(pInfo->Name, current->Name, 255);
|
||||
pInfo->Name[255] = L'\0';
|
||||
pInfo->Base = (ULONG_PTR)current->Base;
|
||||
pInfo->Size = current->Length;
|
||||
pInfo->SymbolInfo = ¤t->SymbolInfo;
|
||||
return TRUE;
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
|
||||
return KdbpSymFindUserModule(Address, Name, Index-Count, pInfo);
|
||||
}
|
||||
|
||||
/*! \brief Find module by address...
|
||||
*
|
||||
* \param Address Any address inside the module to look for.
|
||||
* \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
|
||||
* success.
|
||||
*
|
||||
* \retval TRUE Success - module found.
|
||||
* \retval FALSE Failure - module not found.
|
||||
*
|
||||
* \sa KdbpSymFindModuleByName
|
||||
* \sa KdbpSymFindModuleByIndex
|
||||
*/
|
||||
BOOLEAN
|
||||
KdbpSymFindModuleByAddress(IN PVOID Address,
|
||||
OUT PKDB_MODULE_INFO pInfo)
|
||||
{
|
||||
return KdbpSymFindModule(Address, NULL, -1, pInfo);
|
||||
}
|
||||
|
||||
/*! \brief Find module by name...
|
||||
*
|
||||
* \param Name Name of the module to look for.
|
||||
* \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
|
||||
* success.
|
||||
*
|
||||
* \retval TRUE Success - module found.
|
||||
* \retval FALSE Failure - module not found.
|
||||
*
|
||||
* \sa KdbpSymFindModuleByAddress
|
||||
* \sa KdbpSymFindModuleByIndex
|
||||
*/
|
||||
BOOLEAN
|
||||
KdbpSymFindModuleByName(IN LPCWSTR Name,
|
||||
OUT PKDB_MODULE_INFO pInfo)
|
||||
{
|
||||
return KdbpSymFindModule(NULL, Name, -1, pInfo);
|
||||
}
|
||||
|
||||
/*! \brief Find module by index...
|
||||
*
|
||||
* \param Index Index of the module to return.
|
||||
* \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
|
||||
* success.
|
||||
*
|
||||
* \retval TRUE Success - module found.
|
||||
* \retval FALSE Failure - module not found.
|
||||
*
|
||||
* \sa KdbpSymFindModuleByName
|
||||
* \sa KdbpSymFindModuleByAddress
|
||||
*/
|
||||
BOOLEAN
|
||||
KdbpSymFindModuleByIndex(IN INT Index,
|
||||
OUT PKDB_MODULE_INFO pInfo)
|
||||
{
|
||||
return KdbpSymFindModule(NULL, NULL, Index, pInfo);
|
||||
}
|
||||
|
||||
/*! \brief Print address...
|
||||
*
|
||||
* Tries to lookup line number, file name and function name for the given
|
||||
* address and prints it.
|
||||
* If no such information is found the address is printed in the format
|
||||
* <module: offset>, otherwise the format will be
|
||||
* <module: offset (filename:linenumber (functionname))>
|
||||
*
|
||||
* \retval TRUE Module containing \a Address was found, \a Address was printed.
|
||||
* \retval FALSE No module containing \a Address was found, nothing was printed.
|
||||
*/
|
||||
BOOLEAN
|
||||
KdbSymPrintAddress(IN PVOID Address)
|
||||
{
|
||||
KDB_MODULE_INFO Info;
|
||||
ULONG_PTR RelativeAddress;
|
||||
NTSTATUS Status;
|
||||
ULONG LineNumber;
|
||||
CHAR FileName[256];
|
||||
CHAR FunctionName[256];
|
||||
|
||||
if (!KdbpSymFindModuleByAddress(Address, &Info))
|
||||
return FALSE;
|
||||
|
||||
RelativeAddress = (ULONG_PTR) Address - Info.Base;
|
||||
Status = KdbSymGetAddressInformation(Info.SymbolInfo,
|
||||
RelativeAddress,
|
||||
&LineNumber,
|
||||
FileName,
|
||||
FunctionName);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("<%ws: %x (%s:%d (%s))>",
|
||||
Info.Name, RelativeAddress, FileName, LineNumber, FunctionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint("<%ws: %x>", Info.Name, RelativeAddress);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Get information for an address (source file, line number,
|
||||
* function name)
|
||||
*
|
||||
* \param SymbolInfo Pointer to IMAGE_SYMBOL_INFO.
|
||||
* \param RelativeAddress Relative address to look up.
|
||||
* \param LineNumber Pointer to an ULONG which is filled with the line
|
||||
* number (can be NULL)
|
||||
* \param FileName Pointer to an array of CHARs which gets filled with
|
||||
* the filename (can be NULL)
|
||||
* \param FunctionName Pointer to an array of CHARs which gets filled with
|
||||
* the function name (can be NULL)
|
||||
*
|
||||
* \returns NTSTATUS error code.
|
||||
* \retval STATUS_SUCCESS At least one of the requested informations was found.
|
||||
* \retval STATUS_UNSUCCESSFUL None of the requested information was found.
|
||||
*/
|
||||
NTSTATUS
|
||||
KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
IN ULONG_PTR RelativeAddress,
|
||||
OUT PULONG LineNumber OPTIONAL,
|
||||
OUT PCH FileName OPTIONAL,
|
||||
OUT PCH FunctionName OPTIONAL)
|
||||
{
|
||||
PSTAB_ENTRY FunctionEntry = NULL, FileEntry = NULL, LineEntry = NULL;
|
||||
|
||||
DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress);
|
||||
|
||||
if (SymbolInfo->SymbolsBase == NULL || SymbolInfo->SymbolsLength == 0 ||
|
||||
SymbolInfo->SymbolStringsBase == NULL || SymbolInfo->SymbolStringsLength == 0)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
#ifdef PEDANTIC_STABS
|
||||
if (RelativeAddress >= SymbolInfo->ImageSize)
|
||||
{
|
||||
DPRINT("Address is not within .text section. RelativeAddress %p Length 0x%x\n",
|
||||
RelativeAddress, SymbolInfo->ImageSize);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(LineNumber || FileName || FunctionName);
|
||||
|
||||
if (LineNumber != NULL || FunctionName != NULL)
|
||||
{
|
||||
/* find stab entry for function */
|
||||
FunctionEntry = KdbpStabFindEntry(SymbolInfo, N_FUN, (PVOID)RelativeAddress, NULL);
|
||||
if (FunctionEntry == NULL)
|
||||
{
|
||||
DPRINT("No function stab entry found. RelativeAddress %p\n", RelativeAddress);
|
||||
}
|
||||
|
||||
if (LineNumber != NULL && FunctionEntry != NULL)
|
||||
{
|
||||
/* find stab entry for line number */
|
||||
ULONG_PTR FunctionRelativeAddress = FunctionEntry->n_value - (ULONG_PTR)SymbolInfo->ImageBase;
|
||||
ULONG_PTR AddrFound = 0;
|
||||
PSTAB_ENTRY NextLineEntry;
|
||||
|
||||
LineEntry = NextLineEntry = FunctionEntry;
|
||||
while (NextLineEntry != NULL)
|
||||
{
|
||||
NextLineEntry++;
|
||||
if ((ULONG_PTR)NextLineEntry >= ((ULONG_PTR)SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength))
|
||||
break;
|
||||
if (NextLineEntry->n_type == N_FUN)
|
||||
break;
|
||||
if (NextLineEntry->n_type != N_SLINE)
|
||||
continue;
|
||||
|
||||
if (((NextLineEntry->n_value+FunctionRelativeAddress) <= RelativeAddress) &&
|
||||
(NextLineEntry->n_value > AddrFound))
|
||||
{
|
||||
AddrFound = NextLineEntry->n_value;
|
||||
LineEntry = NextLineEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FileName != NULL)
|
||||
{
|
||||
/* find stab entry for file name */
|
||||
PCHAR p;
|
||||
INT Length;
|
||||
|
||||
FileEntry = KdbpStabFindEntry(SymbolInfo, N_SO, (PVOID)RelativeAddress, NULL);
|
||||
if (FileEntry != NULL)
|
||||
{
|
||||
p = (PCHAR)SymbolInfo->SymbolStringsBase + FileEntry->n_strx;
|
||||
Length = strlen(p);
|
||||
if (p[Length - 1] == '/' || p[Length - 1] == '\\') /* source dir */
|
||||
FileEntry = KdbpStabFindEntry(SymbolInfo, N_SO, (PVOID)RelativeAddress, FileEntry + 1);
|
||||
}
|
||||
if (FileEntry == NULL)
|
||||
{
|
||||
DPRINT("No filename stab entry found. RelativeAddress %p\n", RelativeAddress);
|
||||
}
|
||||
}
|
||||
|
||||
if (((LineNumber != NULL && LineEntry == NULL) || LineNumber == NULL) &&
|
||||
((FileName != NULL && FileEntry == NULL) || FileName == NULL) &&
|
||||
((FunctionName != NULL && FunctionEntry == NULL) || FunctionName == NULL))
|
||||
{
|
||||
DPRINT("None of the requested information was found!\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (LineNumber != NULL)
|
||||
{
|
||||
*LineNumber = 0;
|
||||
if (LineEntry != NULL)
|
||||
*LineNumber = LineEntry->n_desc;
|
||||
}
|
||||
if (FileName != NULL)
|
||||
{
|
||||
PCHAR Name = "";
|
||||
if (FileEntry != NULL)
|
||||
{
|
||||
Name = (PCHAR)SymbolInfo->SymbolStringsBase + FileEntry->n_strx;
|
||||
}
|
||||
strcpy(FileName, Name);
|
||||
}
|
||||
if (FunctionName != NULL)
|
||||
{
|
||||
PCHAR Name = "", p;
|
||||
if (FunctionEntry != NULL)
|
||||
Name = (PCHAR)SymbolInfo->SymbolStringsBase + FunctionEntry->n_strx;
|
||||
strcpy(FunctionName, Name);
|
||||
if ((p = strchr(FunctionName, ':')) != NULL) /* remove extra info from function name */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Get absolute source-line number or function address
|
||||
*
|
||||
* \param SymbolInfo IMAGE_SYMBOL_INFO of the module containing source file/line number.
|
||||
* \param FileName Source filename.
|
||||
* \param LineNumber Line number in source file.
|
||||
* \param FuncName Function name.
|
||||
* \param Address Filled with the address on success.
|
||||
*
|
||||
* \retval TRUE Success.
|
||||
* \retval FALSE Failure.
|
||||
*/
|
||||
BOOLEAN
|
||||
KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
IN PCHAR FileName,
|
||||
IN ULONG LineNumber OPTIONAL,
|
||||
IN PCHAR FuncName OPTIONAL,
|
||||
OUT PVOID *Address)
|
||||
{
|
||||
PSTAB_ENTRY Entry, FunctionEntry = NULL;
|
||||
PCHAR SymbolName, p;
|
||||
CHAR Buffer[512] = "";
|
||||
INT Length, FileNameLength, FuncNameLength = 0;
|
||||
|
||||
if (FuncName == NULL && LineNumber < 1)
|
||||
return FALSE;
|
||||
|
||||
FileNameLength = strlen(FileName);
|
||||
FuncNameLength = strlen(FuncName);
|
||||
for (Entry = SymbolInfo->SymbolsBase;
|
||||
(ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength);
|
||||
Entry++)
|
||||
{
|
||||
if (Entry->n_type != N_SO)
|
||||
continue;
|
||||
|
||||
SymbolName = (PCHAR)SymbolInfo->SymbolStringsBase + Entry->n_strx;
|
||||
Length = strlen(SymbolName);
|
||||
if (SymbolName[Length - 1] == '/' ||
|
||||
SymbolName[Length - 1] == '\\')
|
||||
{
|
||||
strncpy(Buffer, SymbolName, sizeof (Buffer) - 1);
|
||||
Buffer[sizeof (Buffer) - 1] = '\0';
|
||||
continue;
|
||||
}
|
||||
strncat(Buffer, SymbolName, sizeof (Buffer) - 1);
|
||||
Buffer[sizeof (Buffer) - 1] = '\0';
|
||||
|
||||
Length = strlen(Buffer);
|
||||
if (strcmp(Buffer + Length - FileNameLength, FileName) != 0)
|
||||
continue;
|
||||
|
||||
Entry++;
|
||||
for (;(ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength);
|
||||
Entry++)
|
||||
{
|
||||
if (Entry->n_type == N_FUN)
|
||||
FunctionEntry = Entry;
|
||||
else if (Entry->n_type == N_SO)
|
||||
break;
|
||||
else if (Entry->n_type != N_SLINE || LineNumber < 1)
|
||||
continue;
|
||||
|
||||
if (LineNumber > 0 && Entry->n_desc != LineNumber)
|
||||
continue;
|
||||
else /* if (FunctionName != NULL) */
|
||||
{
|
||||
SymbolName = (PCHAR)SymbolInfo->SymbolStringsBase + Entry->n_strx;
|
||||
p = strchr(SymbolName, ':');
|
||||
if (p == NULL)
|
||||
return FALSE;
|
||||
Length = p - SymbolName;
|
||||
if (Length != FuncNameLength)
|
||||
continue;
|
||||
if (strncmp(FuncName, SymbolName, Length) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* found */
|
||||
if (Entry->n_type == N_FUN)
|
||||
{
|
||||
*Address = (PVOID)Entry->n_value; /* FIXME: relocate address */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (FunctionEntry == NULL)
|
||||
return FALSE;
|
||||
|
||||
*Address = (PVOID)((ULONG_PTR)Entry->n_value + FunctionEntry->n_value); /* FIXME: relocate address */
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*! \brief Find cached symbol file.
|
||||
*
|
||||
* Looks through the list of cached symbol files and tries to find an already
|
||||
* loaded one.
|
||||
*
|
||||
* \param FileName FileName of the symbol file to look for.
|
||||
*
|
||||
* \returns A pointer to the cached symbol info.
|
||||
* \retval NULL No cached info found.
|
||||
*
|
||||
* \sa KdbpSymAddCachedFile
|
||||
*/
|
||||
STATIC PIMAGE_SYMBOL_INFO_CACHE
|
||||
KdbpSymFindCachedFile(IN PUNICODE_STRING FileName)
|
||||
{
|
||||
PIMAGE_SYMBOL_INFO_CACHE Current;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
KIRQL Irql;
|
||||
|
||||
DPRINT("Looking for cached symbol file %wZ\n", FileName);
|
||||
|
||||
KeAcquireSpinLock(&SymbolFileListLock, &Irql);
|
||||
|
||||
CurrentEntry = SymbolFileListHead.Flink;
|
||||
while (CurrentEntry != (&SymbolFileListHead))
|
||||
{
|
||||
Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
|
||||
|
||||
DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName);
|
||||
if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE))
|
||||
{
|
||||
KeReleaseSpinLock(&SymbolFileListLock, Irql);
|
||||
DPRINT("Found cached file!\n");
|
||||
return Current;
|
||||
}
|
||||
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&SymbolFileListLock, Irql);
|
||||
|
||||
DPRINT("Cached file not found!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! \brief Add a symbol file to the cache.
|
||||
*
|
||||
* \param FileName Filename of the symbol file.
|
||||
* \param SymbolInfo Pointer to the symbol info.
|
||||
*
|
||||
* \sa KdbpSymRemoveCachedFile
|
||||
*/
|
||||
STATIC VOID
|
||||
KdbpSymAddCachedFile(IN PUNICODE_STRING FileName,
|
||||
IN PIMAGE_SYMBOL_INFO SymbolInfo)
|
||||
{
|
||||
PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
|
||||
|
||||
DPRINT("Adding symbol file: FileBuffer = %p, ImageBase = %p\n",
|
||||
SymbolInfo->FileBuffer, SymbolInfo->ImageBase);
|
||||
|
||||
/* allocate entry */
|
||||
CacheEntry = ExAllocatePool(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE));
|
||||
assert(CacheEntry);
|
||||
RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
|
||||
|
||||
/* fill entry */
|
||||
RtlCreateUnicodeString(&CacheEntry->FileName, FileName->Buffer);
|
||||
assert(CacheEntry->FileName.Buffer);
|
||||
CacheEntry->RefCount = 1;
|
||||
CacheEntry->FileBuffer = SymbolInfo->FileBuffer;
|
||||
CacheEntry->SymbolsBase = SymbolInfo->SymbolsBase;
|
||||
CacheEntry->SymbolsLength = SymbolInfo->SymbolsLength;
|
||||
CacheEntry->SymbolStringsBase = SymbolInfo->SymbolStringsBase;
|
||||
CacheEntry->SymbolStringsLength = SymbolInfo->SymbolStringsLength;
|
||||
InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */
|
||||
}
|
||||
|
||||
/*! \brief Remove a symbol file (reference) from the cache.
|
||||
*
|
||||
* Tries to find a cache entry matching the given symbol info and decreases
|
||||
* it's reference count. If the refcount is 0 after decreasing it the cache
|
||||
* entry will be removed from the list and freed.
|
||||
*
|
||||
* \param SymbolInfo Pointer to the symbol info.
|
||||
*
|
||||
* \sa KdbpSymAddCachedFile
|
||||
*/
|
||||
STATIC VOID
|
||||
KdbpSymRemoveCachedFile(IN PIMAGE_SYMBOL_INFO SymbolInfo)
|
||||
{
|
||||
PIMAGE_SYMBOL_INFO_CACHE Current;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
KIRQL Irql;
|
||||
|
||||
KeAcquireSpinLock(&SymbolFileListLock, &Irql);
|
||||
|
||||
CurrentEntry = SymbolFileListHead.Flink;
|
||||
while (CurrentEntry != (&SymbolFileListHead))
|
||||
{
|
||||
Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
|
||||
|
||||
if (Current->FileBuffer == SymbolInfo->FileBuffer) /* found */
|
||||
{
|
||||
assert(Current->RefCount > 0);
|
||||
Current->RefCount--;
|
||||
if (Current->RefCount < 1)
|
||||
{
|
||||
RemoveEntryList(&Current->ListEntry);
|
||||
ExFreePool(Current->FileBuffer);
|
||||
ExFreePool(Current);
|
||||
}
|
||||
KeReleaseSpinLock(&SymbolFileListLock, Irql);
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&SymbolFileListLock, Irql);
|
||||
DPRINT1("Warning: Removing unknown symbol file: FileBuffer = %p, ImageBase = %p\n",
|
||||
SymbolInfo->FileBuffer, SymbolInfo->ImageBase);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*! \brief Loads a symbol file.
|
||||
*
|
||||
* \param FileName Filename of the symbol file to load.
|
||||
* \param SymbolInfo Pointer to a SymbolInfo which gets filled.
|
||||
*
|
||||
* \sa KdbpSymUnloadModuleSymbols
|
||||
*/
|
||||
STATIC VOID
|
||||
KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName,
|
||||
OUT 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;
|
||||
PIMAGE_SYMBOL_INFO_CACHE CachedSymbolFile;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Try to find cached (already loaded) symbol file */
|
||||
CachedSymbolFile = KdbpSymFindCachedFile(&SymFileName);
|
||||
if (CachedSymbolFile != NULL)
|
||||
{
|
||||
DPRINT("Found cached symbol file %wZ\n", &SymFileName);
|
||||
CachedSymbolFile->RefCount++;
|
||||
SymbolInfo->FileBuffer = CachedSymbolFile->FileBuffer;
|
||||
SymbolInfo->SymbolsBase = CachedSymbolFile->SymbolsBase;
|
||||
SymbolInfo->SymbolsLength = CachedSymbolFile->SymbolsLength;
|
||||
SymbolInfo->SymbolStringsBase = CachedSymbolFile->SymbolStringsBase;
|
||||
SymbolInfo->SymbolStringsLength = CachedSymbolFile->SymbolStringsLength;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SymFileName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
DPRINT("Attempting to open symbols: %wZ\n", &SymFileName);
|
||||
|
||||
Status = ZwOpenFile(&FileHandle,
|
||||
FILE_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
&IoStatusBlock,
|
||||
0,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Could not open symbol file: %wZ\n", &SymFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINT("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;
|
||||
}
|
||||
|
||||
DPRINT("Symbol file is %08x bytes\n", FileStdInfo.EndOfFile.u.LowPart);
|
||||
|
||||
/* Allocate nonpageable memory for symbol file */
|
||||
FileBuffer = ExAllocatePool(NonPagedPool,
|
||||
FileStdInfo.AllocationSize.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) && Status != STATUS_END_OF_FILE)
|
||||
{
|
||||
DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status);
|
||||
ExFreePool(FileBuffer);
|
||||
ZwClose(FileHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
ZwClose(FileHandle);
|
||||
|
||||
DPRINT("Symbols loaded.\n");
|
||||
|
||||
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;
|
||||
|
||||
/* add file to cache */
|
||||
KdbpSymAddCachedFile(&SymFileName, SymbolInfo);
|
||||
|
||||
DPRINT("Installed stabs: %wZ (%08x-%08x,%08x)\n",
|
||||
FileName,
|
||||
SymbolInfo->SymbolsBase,
|
||||
SymbolInfo->SymbolsLength + SymbolInfo->SymbolsBase,
|
||||
SymbolInfo->SymbolStringsBase);
|
||||
}
|
||||
|
||||
/*! \brief Unloads symbol info.
|
||||
*
|
||||
* \param SymbolInfo Pointer to the symbol info to unload.
|
||||
*
|
||||
* \sa KdbpSymLoadModuleSymbols
|
||||
*/
|
||||
STATIC VOID
|
||||
KdbpSymUnloadModuleSymbols(IN PIMAGE_SYMBOL_INFO SymbolInfo)
|
||||
{
|
||||
DPRINT("Unloading symbols\n");
|
||||
|
||||
if (SymbolInfo != NULL && SymbolInfo->FileBuffer != NULL)
|
||||
{
|
||||
KdbpSymRemoveCachedFile(SymbolInfo);
|
||||
SymbolInfo->FileBuffer = NULL;
|
||||
SymbolInfo->SymbolsBase = NULL;
|
||||
SymbolInfo->SymbolsLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Load symbol info for a user module.
|
||||
*
|
||||
* \param LdrModule Pointer to the module to load symbols for.
|
||||
*/
|
||||
VOID
|
||||
KdbSymLoadUserModuleSymbols(IN PLDR_MODULE LdrModule)
|
||||
{
|
||||
DPRINT("LdrModule %p\n", LdrModule);
|
||||
|
||||
RtlZeroMemory(&LdrModule->SymbolInfo, sizeof (LdrModule->SymbolInfo));
|
||||
LdrModule->SymbolInfo.ImageBase = (ULONG_PTR)LdrModule->BaseAddress;
|
||||
LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage;
|
||||
|
||||
KdbpSymLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo);
|
||||
}
|
||||
|
||||
/*! \brief Frees all symbols loaded for a process.
|
||||
*
|
||||
* \param Process Pointer to a process.
|
||||
*/
|
||||
VOID
|
||||
KdbSymFreeProcessSymbols(IN PEPROCESS Process)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLDR_MODULE Current;
|
||||
PIMAGE_SYMBOL_INFO SymbolInfo;
|
||||
PEPROCESS CurrentProcess;
|
||||
PPEB Peb;
|
||||
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
if (CurrentProcess != Process)
|
||||
{
|
||||
KeAttachProcess(Process);
|
||||
}
|
||||
Peb = Process->Peb;
|
||||
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;
|
||||
KdbpSymUnloadModuleSymbols(SymbolInfo);
|
||||
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
if (CurrentProcess != Process)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Load symbol info for a driver.
|
||||
*
|
||||
* \param Filename Filename of the driver.
|
||||
* \param Module Pointer to the driver MODULE_OBJECT.
|
||||
*/
|
||||
VOID
|
||||
KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename,
|
||||
IN PMODULE_OBJECT Module)
|
||||
{
|
||||
/* Load symbols for the image if available */
|
||||
DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename, Module->Base);
|
||||
|
||||
RtlZeroMemory(&Module->TextSection->SymbolInfo, sizeof (Module->TextSection->SymbolInfo));
|
||||
Module->TextSection->SymbolInfo.ImageBase = Module->TextSection->Base;
|
||||
Module->TextSection->SymbolInfo.ImageSize = Module->TextSection->Length;
|
||||
|
||||
KdbpSymLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo);
|
||||
}
|
||||
|
||||
/*! \brief Unloads symbol info for a driver.
|
||||
*
|
||||
* \param ModuleObject Pointer to the driver MODULE_OBJECT.
|
||||
*/
|
||||
VOID
|
||||
KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject)
|
||||
{
|
||||
/* Unload symbols for module if available */
|
||||
KdbpSymUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo);
|
||||
}
|
||||
|
||||
/*! \brief Called when a symbol file is loaded by the loader?
|
||||
*
|
||||
* Tries to find a driver (.sys) or executable (.exe) with the same base name
|
||||
* as the symbol file and sets the drivers/exes symbol info to the loaded
|
||||
* module.
|
||||
* Used to load ntoskrnl and hal symbols before the SystemRoot is available to us.
|
||||
*
|
||||
* \param ModuleLoadBase Base address of the loaded symbol file.
|
||||
* \param FileName Filename of the symbol file.
|
||||
* \param Length Length of the loaded symbol file/module.
|
||||
*/
|
||||
VOID
|
||||
KdbSymProcessSymbolFile(IN PVOID ModuleLoadBase,
|
||||
IN PCHAR FileName,
|
||||
IN ULONG Length)
|
||||
{
|
||||
PMODULE_OBJECT ModuleObject;
|
||||
UNICODE_STRING ModuleName;
|
||||
CHAR TmpBaseName[MAX_PATH];
|
||||
CHAR TmpFileName[MAX_PATH];
|
||||
PSYMBOLFILE_HEADER SymbolFileHeader;
|
||||
PIMAGE_SYMBOL_INFO SymbolInfo;
|
||||
ANSI_STRING AnsiString;
|
||||
PCHAR Extension;
|
||||
|
||||
DPRINT("Module %s is a symbol file\n", FileName);
|
||||
|
||||
strncpy(TmpBaseName, FileName, MAX_PATH-1);
|
||||
TmpBaseName[MAX_PATH-1] = '\0';
|
||||
/* remove the extension '.sym' */
|
||||
Extension = strrchr(TmpBaseName, '.');
|
||||
if (Extension && 0 == _stricmp(Extension, ".sym"))
|
||||
{
|
||||
*Extension = 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;
|
||||
if (SymbolInfo->FileBuffer != NULL)
|
||||
{
|
||||
KdbpSymRemoveCachedFile(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;
|
||||
DPRINT("Installed stabs: %s@%08x-%08x (%08x-%08x,%08x)\n",
|
||||
FileName,
|
||||
ModuleObject->Base, ModuleObject->Length + ModuleObject->Base,
|
||||
SymbolInfo->SymbolsBase,
|
||||
SymbolInfo->SymbolsLength + SymbolInfo->SymbolsBase,
|
||||
SymbolInfo->SymbolStringsBase);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Initializes the KDB symbols implementation.
|
||||
*
|
||||
* \param NtoskrnlTextSection MODULE_TEXT_SECTION of ntoskrnl.exe
|
||||
* \param LdrHalTextSection MODULE_TEXT_SECTION of hal.sys
|
||||
*/
|
||||
VOID
|
||||
KdbSymInit(IN PMODULE_TEXT_SECTION NtoskrnlTextSection,
|
||||
IN PMODULE_TEXT_SECTION LdrHalTextSection)
|
||||
{
|
||||
RtlZeroMemory(&NtoskrnlTextSection->SymbolInfo, sizeof(NtoskrnlTextSection->SymbolInfo));
|
||||
NtoskrnlTextSection->SymbolInfo.ImageBase = NtoskrnlTextSection->OptionalHeader->ImageBase;
|
||||
NtoskrnlTextSection->SymbolInfo.ImageSize = NtoskrnlTextSection->Length;
|
||||
|
||||
RtlZeroMemory(&LdrHalTextSection->SymbolInfo, sizeof(LdrHalTextSection->SymbolInfo));
|
||||
LdrHalTextSection->SymbolInfo.ImageBase = LdrHalTextSection->OptionalHeader->ImageBase;
|
||||
LdrHalTextSection->SymbolInfo.ImageSize = LdrHalTextSection->Length;
|
||||
|
||||
InitializeListHead(&SymbolFileListHead);
|
||||
KeInitializeSpinLock(&SymbolFileListLock);
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: profile.c,v 1.8 2004/08/15 16:39:00 chorns Exp $
|
||||
/* $Id: profile.c,v 1.9 2004/08/26 16:04:49 blight Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/dbg/profile.c
|
||||
|
@ -170,7 +170,7 @@ KdbProfilerGetSymbolInfo(PVOID address, OUT PCH NameBuffer)
|
|||
address < (PVOID)(current->Base + current->Length))
|
||||
{
|
||||
RelativeAddress = (ULONG_PTR) address - current->Base;
|
||||
Status = LdrGetAddressInformation(¤t->SymbolInfo,
|
||||
Status = KdbSymGetAddressInformation(¤t->SymbolInfo,
|
||||
RelativeAddress,
|
||||
&LineNumber,
|
||||
FileName,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: kd.h,v 1.26 2004/08/07 03:41:30 sedwards Exp $
|
||||
/* $Id: kd.h,v 1.27 2004/08/26 16:04:50 blight Exp $
|
||||
*
|
||||
* kernel debugger prototypes
|
||||
*/
|
||||
|
@ -108,42 +108,57 @@ VOID KdInitializeMda(VOID);
|
|||
VOID KdPrintMda(PCH pch);
|
||||
|
||||
#ifndef KDBG
|
||||
#define KDB_DELETEPROCESS_HOOK(PROCESS)
|
||||
#define KDB_LOADDRIVER_HOOK(FILENAME, MODULE)
|
||||
#define KDB_UNLOADDRIVER_HOOK(MODULE)
|
||||
#define KDB_LOADERINIT_HOOK(NTOS, HAL)
|
||||
#define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH)
|
||||
#define KDB_CREATE_THREAD_HOOK(CONTEXT)
|
||||
# define KDB_LOADUSERMODULE_HOOK(LDRMOD) do { } while (0)
|
||||
# define KDB_DELETEPROCESS_HOOK(PROCESS) do { } while (0)
|
||||
# define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) do { } while (0)
|
||||
# define KDB_UNLOADDRIVER_HOOK(MODULE) do { } while (0)
|
||||
# define KDB_LOADERINIT_HOOK(NTOS, HAL) do { } while (0)
|
||||
# define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) do { } while (0)
|
||||
# define KDB_CREATE_THREAD_HOOK(CONTEXT) do { } while (0)
|
||||
#else
|
||||
#define KDB_DELETEPROCESS_HOOK(PROCESS) KdbFreeSymbolsProcess(PROCESS)
|
||||
#define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) KdbLoadDriver(FILENAME, MODULE)
|
||||
#define KDB_UNLOADDRIVER_HOOK(MODULE) KdbUnloadDriver(MODULE)
|
||||
#define KDB_LOADERINIT_HOOK(NTOS, HAL) KdbLdrInit(NTOS, HAL)
|
||||
#define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) \
|
||||
KdbProcessSymbolFile(LOADBASE, FILENAME, LENGTH)
|
||||
#define KDB_CREATE_THREAD_HOOK(CONTEXT) \
|
||||
# define KDB_LOADUSERMODULE_HOOK(LDRMOD) KdbSymLoadUserModuleSymbols(LDRMOD)
|
||||
# define KDB_DELETEPROCESS_HOOK(PROCESS) KdbSymFreeProcessSymbols(PROCESS)
|
||||
# define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) KdbSymLoadDriverSymbols(FILENAME, MODULE)
|
||||
# define KDB_UNLOADDRIVER_HOOK(MODULE) KdbSymUnloadDriverSymbols(MODULE)
|
||||
# define KDB_LOADERINIT_HOOK(NTOS, HAL) KdbSymInit(NTOS, HAL)
|
||||
# define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) \
|
||||
KdbSymProcessSymbolFile(LOADBASE, FILENAME, LENGTH)
|
||||
/*#define KDB_CREATE_THREAD_HOOK(CONTEXT) \
|
||||
KdbCreateThreadHook(CONTEXT)
|
||||
#endif /* KDBG */
|
||||
*/
|
||||
VOID
|
||||
KdbSymLoadUserModuleSymbols(IN PLDR_MODULE LdrModule);
|
||||
|
||||
VOID
|
||||
KdbLdrLoadUserModuleSymbols(PLDR_MODULE LdrModule);
|
||||
KdbSymFreeProcessSymbols(IN PEPROCESS Process);
|
||||
|
||||
VOID
|
||||
KdbProcessSymbolFile(PVOID ModuleLoadBase, PCHAR FileName, ULONG Length);
|
||||
KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename,
|
||||
IN PMODULE_OBJECT Module);
|
||||
|
||||
VOID
|
||||
KdbLdrInit(MODULE_TEXT_SECTION* NtoskrnlTextSection,
|
||||
MODULE_TEXT_SECTION* LdrHalTextSection);
|
||||
KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject);
|
||||
|
||||
VOID
|
||||
KdbUnloadDriver(PMODULE_OBJECT ModuleObject);
|
||||
KdbSymProcessSymbolFile(IN PVOID ModuleLoadBase,
|
||||
IN PCHAR FileName,
|
||||
IN ULONG Length);
|
||||
|
||||
VOID
|
||||
KdbLoadDriver(PUNICODE_STRING Filename, PMODULE_OBJECT Module);
|
||||
VOID
|
||||
KdbFreeSymbolsProcess(PEPROCESS Process);
|
||||
KdbSymInit(IN PMODULE_TEXT_SECTION NtoskrnlTextSection,
|
||||
IN PMODULE_TEXT_SECTION LdrHalTextSection);
|
||||
|
||||
|
||||
BOOLEAN
|
||||
KdbPrintAddress(PVOID address);
|
||||
KdbSymPrintAddress(IN PVOID Address);
|
||||
|
||||
KD_CONTINUE_TYPE
|
||||
KdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
|
||||
PCONTEXT Context,
|
||||
PKTRAP_FRAME TrapFrame);
|
||||
|
||||
#endif /* KDBG */
|
||||
|
||||
VOID
|
||||
DebugLogDumpMessages(VOID);
|
||||
|
||||
|
|
|
@ -108,22 +108,4 @@ LdrUnloadModule(PMODULE_OBJECT ModuleObject);
|
|||
PMODULE_OBJECT
|
||||
LdrGetModuleObject(PUNICODE_STRING ModuleName);
|
||||
|
||||
NTSTATUS
|
||||
LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
|
||||
IN ULONG_PTR RelativeAddress,
|
||||
OUT PULONG LineNumber,
|
||||
OUT PCH FileName OPTIONAL,
|
||||
OUT PCH FunctionName OPTIONAL);
|
||||
|
||||
|
||||
#ifdef DBG
|
||||
|
||||
VOID
|
||||
LdrLoadUserModuleSymbols(PLDR_MODULE LdrModule);
|
||||
|
||||
VOID
|
||||
LdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo);
|
||||
|
||||
#endif /* DBG */
|
||||
|
||||
#endif /* __INCLUDE_INTERNAL_LDR_H */
|
||||
|
|
|
@ -115,8 +115,7 @@ static NTSTATUS ExceptionToNtStatus[] =
|
|||
BOOLEAN STDCALL
|
||||
KeRosPrintAddress(PVOID address)
|
||||
{
|
||||
KdbPrintAddress(address);
|
||||
return TRUE;
|
||||
return KdbSymPrintAddress(address);
|
||||
}
|
||||
#else /* KDBG */
|
||||
BOOLEAN STDCALL
|
||||
|
|
Loading…
Reference in a new issue