mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:25:52 +00:00
[CMAKE]
- WIP: Make rossym and its users rely on dwarf debug info. Brought to you by the Arty. svn path=/branches/cmake-bringup/; revision=49906
This commit is contained in:
parent
3ddfc0b355
commit
b7f44d1892
31 changed files with 3349 additions and 318 deletions
|
@ -274,31 +274,31 @@ VOID LoadReactOSSetup2(VOID)
|
||||||
UseRealHeap = TRUE;
|
UseRealHeap = TRUE;
|
||||||
LoaderBlock->ConfigurationRoot = MachHwDetect();
|
LoaderBlock->ConfigurationRoot = MachHwDetect();
|
||||||
|
|
||||||
|
strcpy(FileName, "\\ArcName\\");
|
||||||
|
|
||||||
/* Load kernel */
|
/* Load kernel */
|
||||||
strcpy(FileName, BootPath);
|
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||||
strcat(FileName, "NTOSKRNL.EXE");
|
strcat(FileName, "NTOSKRNL.EXE");
|
||||||
Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
|
Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderSystemCode, &NtosBase);
|
||||||
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
|
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
|
||||||
|
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
||||||
|
FileName, NtosBase, &KernelDTE);
|
||||||
|
|
||||||
/* Load HAL */
|
/* Load HAL */
|
||||||
strcpy(FileName, BootPath);
|
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||||
strcat(FileName, "HAL.DLL");
|
strcat(FileName, "HAL.DLL");
|
||||||
Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
|
Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderHalCode, &HalBase);
|
||||||
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
|
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
|
||||||
|
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
||||||
|
FileName, HalBase, &HalDTE);
|
||||||
|
|
||||||
/* Load kernel-debugger support dll */
|
/* Load kernel-debugger support dll */
|
||||||
strcpy(FileName, BootPath);
|
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||||
strcat(FileName, "KDCOM.DLL");
|
strcat(FileName, "KDCOM.DLL");
|
||||||
Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
|
Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderBootDriver, &KdComBase);
|
||||||
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
|
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
|
||||||
|
|
||||||
/* Allocate data table entries for above-loaded modules */
|
|
||||||
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
|
||||||
"NTOSKRNL.EXE", NtosBase, &KernelDTE);
|
|
||||||
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
|
||||||
"HAL.DLL", HalBase, &HalDTE);
|
|
||||||
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
|
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
|
||||||
"KDCOM.DLL", KdComBase, &KdComDTE);
|
FileName, KdComBase, &KdComDTE);
|
||||||
|
|
||||||
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
||||||
strcpy(SearchPath, BootPath);
|
strcpy(SearchPath, BootPath);
|
||||||
|
|
|
@ -39,11 +39,6 @@ extern BOOLEAN UseRealHeap;
|
||||||
extern ULONG LoaderPagesSpanned;
|
extern ULONG LoaderPagesSpanned;
|
||||||
extern BOOLEAN AcpiPresent;
|
extern BOOLEAN AcpiPresent;
|
||||||
|
|
||||||
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
|
|
||||||
extern BOOLEAN WinLdrTerminalConnected;
|
|
||||||
|
|
||||||
extern void WinLdrSetupEms(IN PCHAR BootOptions);
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
|
WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
|
||||||
IN PCH DllName,
|
IN PCH DllName,
|
||||||
|
@ -211,6 +206,8 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
|
|
||||||
#ifndef _M_ARM
|
#ifndef _M_ARM
|
||||||
/* Set headless block pointer */
|
/* Set headless block pointer */
|
||||||
|
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
|
||||||
|
extern BOOLEAN WinLdrTerminalConnected;
|
||||||
if (WinLdrTerminalConnected)
|
if (WinLdrTerminalConnected)
|
||||||
{
|
{
|
||||||
Extension->HeadlessLoaderBlock = MmHeapAlloc(sizeof(HEADLESS_LOADER_BLOCK));
|
Extension->HeadlessLoaderBlock = MmHeapAlloc(sizeof(HEADLESS_LOADER_BLOCK));
|
||||||
|
@ -285,13 +282,14 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's not loaded, we have to load it
|
// It's not loaded, we have to load it
|
||||||
_snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
|
strcpy(FullPath, "\\ArcName\\");
|
||||||
Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
|
_snprintf(FullPath+strlen("\\ArcName\\"), sizeof(FullPath), "%s%wZ", BootPath, FilePath);
|
||||||
|
Status = WinLdrLoadImage(FullPath+strlen("\\ArcName\\"), LoaderBootDriver, &DriverBase);
|
||||||
if (!Status)
|
if (!Status)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Allocate a DTE for it
|
// Allocate a DTE for it
|
||||||
Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE);
|
Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, FullPath, DriverBase, DriverDTE);
|
||||||
if (!Status)
|
if (!Status)
|
||||||
{
|
{
|
||||||
DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n");
|
DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n");
|
||||||
|
@ -540,6 +538,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
||||||
|
|
||||||
#ifndef _M_ARM
|
#ifndef _M_ARM
|
||||||
/* Setup redirection support */
|
/* Setup redirection support */
|
||||||
|
extern void WinLdrSetupEms(IN PCHAR BootOptions);
|
||||||
WinLdrSetupEms(BootOptions);
|
WinLdrSetupEms(BootOptions);
|
||||||
#endif
|
#endif
|
||||||
/* Detect hardware */
|
/* Detect hardware */
|
||||||
|
@ -553,36 +552,33 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
||||||
if (OperatingSystemVersion == 0)
|
if (OperatingSystemVersion == 0)
|
||||||
OperatingSystemVersion = WinLdrDetectVersion();
|
OperatingSystemVersion = WinLdrDetectVersion();
|
||||||
|
|
||||||
|
strcpy(FileName, "\\ArcName\\");
|
||||||
|
|
||||||
/* Load kernel */
|
/* Load kernel */
|
||||||
strcpy(FileName, BootPath);
|
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||||
strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
|
strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
|
||||||
Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
|
Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderSystemCode, &NtosBase);
|
||||||
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
|
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
|
||||||
|
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
||||||
|
FileName, NtosBase, &KernelDTE);
|
||||||
|
|
||||||
/* Load HAL */
|
/* Load HAL */
|
||||||
strcpy(FileName, BootPath);
|
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||||
strcat(FileName, "SYSTEM32\\HAL.DLL");
|
strcat(FileName, "SYSTEM32\\HAL.DLL");
|
||||||
Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
|
Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderHalCode, &HalBase);
|
||||||
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
|
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
|
||||||
|
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
||||||
|
FileName, HalBase, &HalDTE);
|
||||||
|
|
||||||
/* Load kernel-debugger support dll */
|
/* Load kernel-debugger support dll */
|
||||||
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
|
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
|
||||||
{
|
{
|
||||||
strcpy(FileName, BootPath);
|
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||||
strcat(FileName, "SYSTEM32\\KDCOM.DLL");
|
strcat(FileName, "SYSTEM32\\KDCOM.DLL");
|
||||||
Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
|
Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderBootDriver, &KdComBase);
|
||||||
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
|
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate data table entries for above-loaded modules */
|
|
||||||
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
|
||||||
"WINDOWS\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);
|
|
||||||
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
|
||||||
"WINDOWS\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE);
|
|
||||||
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
|
|
||||||
{
|
|
||||||
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
|
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
|
||||||
"WINDOWS\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);
|
FileName, KdComBase, &KdComDTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
||||||
|
|
|
@ -10,15 +10,6 @@
|
||||||
#ifndef REACTOS_ROSSYM_H_INCLUDED
|
#ifndef REACTOS_ROSSYM_H_INCLUDED
|
||||||
#define REACTOS_ROSSYM_H_INCLUDED
|
#define REACTOS_ROSSYM_H_INCLUDED
|
||||||
|
|
||||||
#define ROSSYM_SECTION_NAME ".rossym"
|
|
||||||
|
|
||||||
typedef struct _ROSSYM_HEADER {
|
|
||||||
unsigned long SymbolsOffset;
|
|
||||||
unsigned long SymbolsLength;
|
|
||||||
unsigned long StringsOffset;
|
|
||||||
unsigned long StringsLength;
|
|
||||||
} ROSSYM_HEADER, *PROSSYM_HEADER;
|
|
||||||
|
|
||||||
typedef struct _ROSSYM_ENTRY {
|
typedef struct _ROSSYM_ENTRY {
|
||||||
ULONG_PTR Address;
|
ULONG_PTR Address;
|
||||||
ULONG FunctionOffset;
|
ULONG FunctionOffset;
|
||||||
|
@ -33,19 +24,16 @@ typedef struct _ROSSYM_CALLBACKS {
|
||||||
BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position);
|
BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position);
|
||||||
} ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS;
|
} ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS;
|
||||||
|
|
||||||
typedef struct _ROSSYM_INFO *PROSSYM_INFO;
|
struct Dwarf;
|
||||||
|
typedef struct Dwarf *PROSSYM_INFO;
|
||||||
|
|
||||||
VOID RosSymInit(PROSSYM_CALLBACKS Callbacks);
|
VOID RosSymInit(PROSSYM_CALLBACKS Callbacks);
|
||||||
VOID RosSymInitKernelMode(VOID);
|
VOID RosSymInitKernelMode(VOID);
|
||||||
VOID RosSymInitUserMode(VOID);
|
VOID RosSymInitUserMode(VOID);
|
||||||
|
|
||||||
BOOLEAN RosSymCreateFromRaw(PVOID RawData, ULONG_PTR DataSize,
|
|
||||||
PROSSYM_INFO *RosSymInfo);
|
|
||||||
BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize,
|
BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize,
|
||||||
PROSSYM_INFO *RosSymInfo);
|
PROSSYM_INFO *RosSymInfo);
|
||||||
BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo);
|
BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo);
|
||||||
ULONG RosSymGetRawDataLength(PROSSYM_INFO RosSymInfo);
|
|
||||||
VOID RosSymGetRawData(PROSSYM_INFO RosSymInfo, PVOID RawData);
|
|
||||||
BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
||||||
ULONG_PTR RelativeAddress,
|
ULONG_PTR RelativeAddress,
|
||||||
ULONG *LineNumber,
|
ULONG *LineNumber,
|
||||||
|
|
|
@ -2,14 +2,21 @@
|
||||||
add_definitions(-D_NTSYSTEM_)
|
add_definitions(-D_NTSYSTEM_)
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
delete.c
|
delete.c
|
||||||
|
dwarf386.c
|
||||||
|
dwarfabbrev.c
|
||||||
|
dwarfaranges.c
|
||||||
|
dwarfcfa.c
|
||||||
|
dwarfinfo.c
|
||||||
|
dwarfget.c
|
||||||
|
dwarfopen.c
|
||||||
|
dwarfpc.c
|
||||||
|
dwarfpubnames.c
|
||||||
find.c
|
find.c
|
||||||
fromfile.c
|
fromfile.c
|
||||||
frommem.c
|
|
||||||
fromraw.c
|
|
||||||
getraw.c
|
|
||||||
init.c
|
init.c
|
||||||
initkm.c
|
initkm.c
|
||||||
initum.c
|
initum.c
|
||||||
|
pe.c
|
||||||
zwfile.c)
|
zwfile.c)
|
||||||
add_library(rossym ${SOURCE})
|
add_library(rossym ${SOURCE})
|
||||||
add_dependencies(rossym psdk)
|
add_dependencies(rossym psdk)
|
41
lib/rossym/compat.h
Normal file
41
lib/rossym/compat.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef _LIBMACH_COMPAT_H_
|
||||||
|
#define _LIBMACH_COMPAT_H_
|
||||||
|
|
||||||
|
/* BSD like types */
|
||||||
|
typedef signed char schar;
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
typedef unsigned long long uvlong;
|
||||||
|
|
||||||
|
typedef unsigned short u16int;
|
||||||
|
typedef short s16int;
|
||||||
|
typedef unsigned int u32int;
|
||||||
|
typedef int s32int;
|
||||||
|
typedef unsigned long long u64int;
|
||||||
|
typedef long long s64int;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
typedef ulong size_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define offsetof(x,y) FIELD_OFFSET(x,y)
|
||||||
|
#define nil (0)
|
||||||
|
|
||||||
|
#define nelem(arr) (sizeof((arr)[0]) / sizeof((arr)))
|
||||||
|
|
||||||
|
int readn(void *fd, char *buf, ulong len);
|
||||||
|
int seek(void *fd, ulong off, int mode);
|
||||||
|
|
||||||
|
void *RosSymAllocMemZero(ulong num, ulong size);
|
||||||
|
void *RosSymRealloc(void *mem, ulong newsize);
|
||||||
|
void xfree(void *v);
|
||||||
|
|
||||||
|
#define werrstr(str, ...) DPRINT(str "\n" ,##__VA_ARGS__)
|
||||||
|
#define malloc(x) RosSymAllocMem(x)
|
||||||
|
#define mallocz(x,y) RosSymAllocMemZero(x,y)
|
||||||
|
#define free(x) xfree(x)
|
||||||
|
#define USED(x) (*((char *)&(x)) ^= 0)
|
||||||
|
#define memset(x,y,z) RtlZeroMemory(x,z)
|
||||||
|
|
||||||
|
#endif/*_LIBMACH_COMPAT_H_*/
|
|
@ -10,15 +10,24 @@
|
||||||
#define NTOSAPI
|
#define NTOSAPI
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include <ntimage.h>
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include "pe.h"
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
RosSymDelete(PROSSYM_INFO RosSymInfo)
|
RosSymDelete(PROSSYM_INFO RosSymInfo)
|
||||||
{
|
{
|
||||||
RosSymFreeMem(RosSymInfo);
|
int i;
|
||||||
|
for (i = 0; i < RosSymInfo->pe->nsections; i++) {
|
||||||
|
RtlFreeAnsiString(ANSI_NAME_STRING(&RosSymInfo->pe->sect[i]));
|
||||||
|
}
|
||||||
|
RosSymFreeMem(RosSymInfo->pe->sect);
|
||||||
|
dwarfclose(RosSymInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
471
lib/rossym/dwarf.h
Normal file
471
lib/rossym/dwarf.h
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
typedef struct Dwarf Dwarf;
|
||||||
|
typedef struct DwarfAttrs DwarfAttrs;
|
||||||
|
typedef struct DwarfBlock DwarfBlock;
|
||||||
|
typedef struct DwarfBuf DwarfBuf;
|
||||||
|
typedef struct DwarfExpr DwarfExpr;
|
||||||
|
typedef struct DwarfSym DwarfSym;
|
||||||
|
typedef union DwarfVal DwarfVal;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TagArrayType = 0x01,
|
||||||
|
TagClassType = 0x02,
|
||||||
|
TagEntryPoint = 0x03,
|
||||||
|
TagEnumerationType = 0x04,
|
||||||
|
TagFormalParameter = 0x05,
|
||||||
|
TagImportedDeclaration = 0x08,
|
||||||
|
TagLabel = 0x0A,
|
||||||
|
TagLexDwarfBlock = 0x0B,
|
||||||
|
TagMember = 0x0D,
|
||||||
|
TagPointerType = 0x0F,
|
||||||
|
TagReferenceType = 0x10,
|
||||||
|
TagCompileUnit = 0x11,
|
||||||
|
TagStringType = 0x12,
|
||||||
|
TagStructType = 0x13,
|
||||||
|
TagSubroutineType = 0x15,
|
||||||
|
TagTypedef = 0x16,
|
||||||
|
TagUnionType = 0x17,
|
||||||
|
TagUnspecifiedParameters = 0x18,
|
||||||
|
TagVariant = 0x19,
|
||||||
|
TagCommonDwarfBlock = 0x1A,
|
||||||
|
TagCommonInclusion = 0x1B,
|
||||||
|
TagInheritance = 0x1C,
|
||||||
|
TagInlinedSubroutine = 0x1D,
|
||||||
|
TagModule = 0x1E,
|
||||||
|
TagPtrToMemberType = 0x1F,
|
||||||
|
TagSetType = 0x20,
|
||||||
|
TagSubrangeType = 0x21,
|
||||||
|
TagWithStmt = 0x22,
|
||||||
|
TagAccessDeclaration = 0x23,
|
||||||
|
TagBaseType = 0x24,
|
||||||
|
TagCatchDwarfBlock = 0x25,
|
||||||
|
TagConstType = 0x26,
|
||||||
|
TagConstant = 0x27,
|
||||||
|
TagEnumerator = 0x28,
|
||||||
|
TagFileType = 0x29,
|
||||||
|
TagFriend = 0x2A,
|
||||||
|
TagNamelist = 0x2B,
|
||||||
|
TagNamelistItem = 0x2C,
|
||||||
|
TagPackedType = 0x2D,
|
||||||
|
TagSubprogram = 0x2E,
|
||||||
|
TagTemplateTypeParameter = 0x2F,
|
||||||
|
TagTemplateValueParameter = 0x30,
|
||||||
|
TagThrownType = 0x31,
|
||||||
|
TagTryDwarfBlock = 0x32,
|
||||||
|
TagVariantPart = 0x33,
|
||||||
|
TagVariable = 0x34,
|
||||||
|
TagVolatileType = 0x35,
|
||||||
|
TagDwarfProcedure = 0x36,
|
||||||
|
TagRestrictType = 0x37,
|
||||||
|
TagInterfaceType = 0x38,
|
||||||
|
TagNamespace = 0x39,
|
||||||
|
TagImportedModule = 0x3A,
|
||||||
|
TagUnspecifiedType = 0x3B,
|
||||||
|
TagPartialUnit = 0x3C,
|
||||||
|
TagImportedUnit = 0x3D,
|
||||||
|
TagMutableType = 0x3E,
|
||||||
|
|
||||||
|
TypeAddress = 0x01,
|
||||||
|
TypeBoolean = 0x02,
|
||||||
|
TypeComplexFloat = 0x03,
|
||||||
|
TypeFloat = 0x04,
|
||||||
|
TypeSigned = 0x05,
|
||||||
|
TypeSignedChar = 0x06,
|
||||||
|
TypeUnsigned = 0x07,
|
||||||
|
TypeUnsignedChar = 0x08,
|
||||||
|
TypeImaginaryFloat = 0x09,
|
||||||
|
|
||||||
|
AccessPublic = 0x01,
|
||||||
|
AccessProtected = 0x02,
|
||||||
|
AccessPrivate = 0x03,
|
||||||
|
|
||||||
|
VisLocal = 0x01,
|
||||||
|
VisExported = 0x02,
|
||||||
|
VisQualified = 0x03,
|
||||||
|
|
||||||
|
VirtNone = 0x00,
|
||||||
|
VirtVirtual = 0x01,
|
||||||
|
VirtPureVirtual = 0x02,
|
||||||
|
|
||||||
|
LangC89 = 0x0001,
|
||||||
|
LangC = 0x0002,
|
||||||
|
LangAda83 = 0x0003,
|
||||||
|
LangCplusplus = 0x0004,
|
||||||
|
LangCobol74 = 0x0005,
|
||||||
|
LangCobol85 = 0x0006,
|
||||||
|
LangFortran77 = 0x0007,
|
||||||
|
LangFortran90 = 0x0008,
|
||||||
|
LangPascal83 = 0x0009,
|
||||||
|
LangModula2 = 0x000A,
|
||||||
|
LangJava = 0x000B,
|
||||||
|
LangC99 = 0x000C,
|
||||||
|
LangAda95 = 0x000D,
|
||||||
|
LangFortran95 = 0x000E,
|
||||||
|
LangPLI = 0x000F,
|
||||||
|
/* 0x8000-0xFFFF reserved */
|
||||||
|
|
||||||
|
IdCaseSensitive = 0x00,
|
||||||
|
IdCaseUpper = 0x01,
|
||||||
|
IdCaseLower = 0x02,
|
||||||
|
IdCaseInsensitive = 0x03,
|
||||||
|
|
||||||
|
CallingNormal = 0x01,
|
||||||
|
CallingProgram = 0x02,
|
||||||
|
CallingNocall = 0x03,
|
||||||
|
/* 0x40-0xFF reserved */
|
||||||
|
|
||||||
|
InNone = 0x00,
|
||||||
|
InInlined = 0x01,
|
||||||
|
InDeclaredNotInlined = 0x02,
|
||||||
|
InDeclaredInlined = 0x03,
|
||||||
|
|
||||||
|
OrderRowMajor = 0x00,
|
||||||
|
OrderColumnMajor = 0x01,
|
||||||
|
|
||||||
|
DiscLabel = 0x00,
|
||||||
|
DiscRange = 0x01,
|
||||||
|
|
||||||
|
TReference = 1<<0,
|
||||||
|
TBlock = 1<<1,
|
||||||
|
TConstant = 1<<2,
|
||||||
|
TString = 1<<3,
|
||||||
|
TFlag = 1<<4,
|
||||||
|
TAddress = 1<<5,
|
||||||
|
|
||||||
|
OpAddr = 0x03, /* 1 op, const addr */
|
||||||
|
OpDeref = 0x06,
|
||||||
|
OpConst1u = 0x08, /* 1 op, 1 byte const */
|
||||||
|
OpConst1s = 0x09, /* " signed */
|
||||||
|
OpConst2u = 0x0A, /* 1 op, 2 byte const */
|
||||||
|
OpConst2s = 0x0B, /* " signed */
|
||||||
|
OpConst4u = 0x0C, /* 1 op, 4 byte const */
|
||||||
|
OpConst4s = 0x0D, /* " signed */
|
||||||
|
OpConst8u = 0x0E, /* 1 op, 8 byte const */
|
||||||
|
OpConst8s = 0x0F, /* " signed */
|
||||||
|
OpConstu = 0x10, /* 1 op, LEB128 const */
|
||||||
|
OpConsts = 0x11, /* " signed */
|
||||||
|
OpDup = 0x12,
|
||||||
|
OpDrop = 0x13,
|
||||||
|
OpOver = 0x14,
|
||||||
|
OpPick = 0x15, /* 1 op, 1 byte stack index */
|
||||||
|
OpSwap = 0x16,
|
||||||
|
OpRot = 0x17,
|
||||||
|
OpXderef = 0x18,
|
||||||
|
OpAbs = 0x19,
|
||||||
|
OpAnd = 0x1A,
|
||||||
|
OpDiv = 0x1B,
|
||||||
|
OpMinus = 0x1C,
|
||||||
|
OpMod = 0x1D,
|
||||||
|
OpMul = 0x1E,
|
||||||
|
OpNeg = 0x1F,
|
||||||
|
OpNot = 0x20,
|
||||||
|
OpOr = 0x21,
|
||||||
|
OpPlus = 0x22,
|
||||||
|
OpPlusUconst = 0x23, /* 1 op, ULEB128 addend */
|
||||||
|
OpShl = 0x24,
|
||||||
|
OpShr = 0x25,
|
||||||
|
OpShra = 0x26,
|
||||||
|
OpXor = 0x27,
|
||||||
|
OpSkip = 0x2F, /* 1 op, signed 2-byte constant */
|
||||||
|
OpBra = 0x28, /* 1 op, signed 2-byte constant */
|
||||||
|
OpEq = 0x29,
|
||||||
|
OpGe = 0x2A,
|
||||||
|
OpGt = 0x2B,
|
||||||
|
OpLe = 0x2C,
|
||||||
|
OpLt = 0x2D,
|
||||||
|
OpNe = 0x2E,
|
||||||
|
OpLit0 = 0x30,
|
||||||
|
/* OpLitN = OpLit0 + N for N = 0..31 */
|
||||||
|
OpReg0 = 0x50,
|
||||||
|
/* OpRegN = OpReg0 + N for N = 0..31 */
|
||||||
|
OpBreg0 = 0x70, /* 1 op, signed LEB128 constant */
|
||||||
|
/* OpBregN = OpBreg0 + N for N = 0..31 */
|
||||||
|
OpRegx = 0x90, /* 1 op, ULEB128 register */
|
||||||
|
OpFbreg = 0x91, /* 1 op, SLEB128 offset */
|
||||||
|
OpBregx = 0x92, /* 2 op, ULEB128 reg, SLEB128 off */
|
||||||
|
OpPiece = 0x93, /* 1 op, ULEB128 size of piece */
|
||||||
|
OpDerefSize = 0x94, /* 1-byte size of data retrieved */
|
||||||
|
OpXderefSize = 0x95, /* 1-byte size of data retrieved */
|
||||||
|
OpNop = 0x96,
|
||||||
|
/* next four new in Dwarf v3 */
|
||||||
|
OpPushObjAddr = 0x97,
|
||||||
|
OpCall2 = 0x98, /* 2-byte offset of DIE */
|
||||||
|
OpCall4 = 0x99, /* 4-byte offset of DIE */
|
||||||
|
OpCallRef = 0x9A /* 4- or 8- byte offset of DIE */
|
||||||
|
/* 0xE0-0xFF reserved for user-specific */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DwarfBlock
|
||||||
|
{
|
||||||
|
uchar *data;
|
||||||
|
ulong len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* not for consumer use */
|
||||||
|
struct DwarfBuf
|
||||||
|
{
|
||||||
|
Dwarf *d;
|
||||||
|
uchar *p;
|
||||||
|
uchar *ep;
|
||||||
|
uint addrsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
union DwarfVal
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
ulong c;
|
||||||
|
ulong r;
|
||||||
|
DwarfBlock b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DwarfAttrs
|
||||||
|
{
|
||||||
|
ulong tag;
|
||||||
|
uchar haskids;
|
||||||
|
|
||||||
|
/* whether we have it, along with type */
|
||||||
|
struct {
|
||||||
|
uchar abstractorigin;
|
||||||
|
uchar accessibility;
|
||||||
|
uchar addrclass;
|
||||||
|
uchar basetypes;
|
||||||
|
uchar bitoffset;
|
||||||
|
uchar bitsize;
|
||||||
|
uchar bytesize;
|
||||||
|
uchar calling;
|
||||||
|
uchar commonref;
|
||||||
|
uchar compdir;
|
||||||
|
uchar constvalue;
|
||||||
|
uchar containingtype;
|
||||||
|
uchar count;
|
||||||
|
uchar datamemberloc;
|
||||||
|
uchar declcolumn;
|
||||||
|
uchar declfile;
|
||||||
|
uchar declline;
|
||||||
|
uchar defaultvalue;
|
||||||
|
uchar discr;
|
||||||
|
uchar discrlist;
|
||||||
|
uchar discrvalue;
|
||||||
|
uchar encoding;
|
||||||
|
uchar framebase;
|
||||||
|
uchar friend;
|
||||||
|
uchar highpc;
|
||||||
|
uchar entrypc;
|
||||||
|
uchar identifiercase;
|
||||||
|
uchar import;
|
||||||
|
uchar inlined;
|
||||||
|
uchar isartificial;
|
||||||
|
uchar isdeclaration;
|
||||||
|
uchar isexternal;
|
||||||
|
uchar isoptional;
|
||||||
|
uchar isprototyped;
|
||||||
|
uchar isvarparam;
|
||||||
|
uchar language;
|
||||||
|
uchar location;
|
||||||
|
uchar lowerbound;
|
||||||
|
uchar lowpc;
|
||||||
|
uchar macroinfo;
|
||||||
|
uchar name;
|
||||||
|
uchar namelistitem;
|
||||||
|
uchar ordering;
|
||||||
|
uchar priority;
|
||||||
|
uchar producer;
|
||||||
|
uchar ranges;
|
||||||
|
uchar returnaddr;
|
||||||
|
uchar segment;
|
||||||
|
uchar sibling;
|
||||||
|
uchar specification;
|
||||||
|
uchar startscope;
|
||||||
|
uchar staticlink;
|
||||||
|
uchar stmtlist;
|
||||||
|
uchar stridesize;
|
||||||
|
uchar stringlength;
|
||||||
|
uchar type;
|
||||||
|
uchar upperbound;
|
||||||
|
uchar uselocation;
|
||||||
|
uchar virtuality;
|
||||||
|
uchar visibility;
|
||||||
|
uchar vtableelemloc;
|
||||||
|
} have;
|
||||||
|
|
||||||
|
ulong abstractorigin;
|
||||||
|
ulong accessibility;
|
||||||
|
ulong addrclass;
|
||||||
|
ulong basetypes;
|
||||||
|
ulong bitoffset;
|
||||||
|
ulong bitsize;
|
||||||
|
ulong bytesize;
|
||||||
|
ulong calling;
|
||||||
|
ulong commonref;
|
||||||
|
char* compdir;
|
||||||
|
DwarfVal constvalue;
|
||||||
|
ulong containingtype;
|
||||||
|
ulong count;
|
||||||
|
DwarfVal datamemberloc;
|
||||||
|
ulong declcolumn;
|
||||||
|
ulong declfile;
|
||||||
|
ulong declline;
|
||||||
|
ulong defaultvalue;
|
||||||
|
ulong discr;
|
||||||
|
DwarfBlock discrlist;
|
||||||
|
ulong discrvalue;
|
||||||
|
ulong encoding;
|
||||||
|
DwarfVal framebase;
|
||||||
|
ulong friend;
|
||||||
|
ulong highpc;
|
||||||
|
ulong entrypc;
|
||||||
|
ulong identifiercase;
|
||||||
|
ulong import;
|
||||||
|
ulong inlined;
|
||||||
|
uchar isartificial;
|
||||||
|
uchar isdeclaration;
|
||||||
|
uchar isexternal;
|
||||||
|
uchar isoptional;
|
||||||
|
uchar isprototyped;
|
||||||
|
uchar isvarparam;
|
||||||
|
ulong language;
|
||||||
|
DwarfVal location;
|
||||||
|
ulong lowerbound;
|
||||||
|
ulong lowpc;
|
||||||
|
ulong macroinfo;
|
||||||
|
char* name;
|
||||||
|
DwarfBlock namelistitem;
|
||||||
|
ulong ordering;
|
||||||
|
ulong priority;
|
||||||
|
char* producer;
|
||||||
|
ulong ranges;
|
||||||
|
DwarfVal returnaddr;
|
||||||
|
DwarfVal segment;
|
||||||
|
ulong sibling;
|
||||||
|
ulong specification;
|
||||||
|
ulong startscope;
|
||||||
|
DwarfVal staticlink;
|
||||||
|
ulong stmtlist;
|
||||||
|
ulong stridesize;
|
||||||
|
DwarfVal stringlength;
|
||||||
|
ulong type;
|
||||||
|
ulong upperbound;
|
||||||
|
DwarfVal uselocation;
|
||||||
|
ulong virtuality;
|
||||||
|
ulong visibility;
|
||||||
|
DwarfVal vtableelemloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RuleUndef,
|
||||||
|
RuleSame,
|
||||||
|
RuleCfaOffset,
|
||||||
|
RuleRegister,
|
||||||
|
RuleRegOff,
|
||||||
|
RuleLocation
|
||||||
|
};
|
||||||
|
struct DwarfExpr
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
long offset;
|
||||||
|
ulong reg;
|
||||||
|
DwarfBlock loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DwarfSym
|
||||||
|
{
|
||||||
|
DwarfAttrs attrs;
|
||||||
|
|
||||||
|
/* not for consumer use... */
|
||||||
|
DwarfBuf b;
|
||||||
|
ulong unit;
|
||||||
|
uint uoff;
|
||||||
|
ulong aoff;
|
||||||
|
int depth;
|
||||||
|
int allunits;
|
||||||
|
ulong nextunit;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct _Pe;
|
||||||
|
Dwarf *dwarfopen(struct _Pe *elf);
|
||||||
|
void dwarfclose(Dwarf*);
|
||||||
|
int dwarfaddrtounit(Dwarf*, ulong, ulong*);
|
||||||
|
int dwarflookupfn(Dwarf*, ulong, ulong, DwarfSym*);
|
||||||
|
int dwarflookupname(Dwarf*, char*, DwarfSym*);
|
||||||
|
int dwarflookupnameinunit(Dwarf*, ulong, char*, DwarfSym*);
|
||||||
|
int dwarflookupsubname(Dwarf*, DwarfSym*, char*, DwarfSym*);
|
||||||
|
int dwarflookuptag(Dwarf*, ulong, ulong, DwarfSym*);
|
||||||
|
int dwarfenumunit(Dwarf*, ulong, DwarfSym*);
|
||||||
|
int dwarfseeksym(Dwarf*, ulong, ulong, DwarfSym*);
|
||||||
|
int dwarfenum(Dwarf*, DwarfSym*);
|
||||||
|
int dwarfnextsym(Dwarf*, DwarfSym*);
|
||||||
|
int dwarfnextsymat(Dwarf*, DwarfSym*, int);
|
||||||
|
int dwarfpctoline(Dwarf*, ulong, char**, char**, char**, char **, ulong*, ulong*, ulong*);
|
||||||
|
int dwarfunwind(Dwarf*, ulong, DwarfExpr*, DwarfExpr*, DwarfExpr*, int);
|
||||||
|
ulong dwarfget1(DwarfBuf*);
|
||||||
|
ulong dwarfget2(DwarfBuf*);
|
||||||
|
ulong dwarfget4(DwarfBuf*);
|
||||||
|
uvlong dwarfget8(DwarfBuf*);
|
||||||
|
ulong dwarfget128(DwarfBuf*);
|
||||||
|
long dwarfget128s(DwarfBuf*);
|
||||||
|
ulong dwarfgetaddr(DwarfBuf*);
|
||||||
|
int dwarfgetn(DwarfBuf*, uchar*, int);
|
||||||
|
uchar *dwarfgetnref(DwarfBuf*, ulong);
|
||||||
|
char *dwarfgetstring(DwarfBuf*);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct DwarfAbbrev DwarfAbbrev;
|
||||||
|
typedef struct DwarfAttr DwarfAttr;
|
||||||
|
|
||||||
|
struct DwarfAttr
|
||||||
|
{
|
||||||
|
ulong name;
|
||||||
|
ulong form;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DwarfAbbrev
|
||||||
|
{
|
||||||
|
ulong num;
|
||||||
|
ulong tag;
|
||||||
|
uchar haskids;
|
||||||
|
DwarfAttr *attr;
|
||||||
|
int nattr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Pe;
|
||||||
|
|
||||||
|
struct Dwarf
|
||||||
|
{
|
||||||
|
struct _Pe *pe;
|
||||||
|
|
||||||
|
char **reg;
|
||||||
|
int nreg;
|
||||||
|
int addrsize;
|
||||||
|
DwarfBlock abbrev;
|
||||||
|
DwarfBlock aranges;
|
||||||
|
DwarfBlock frame;
|
||||||
|
DwarfBlock info;
|
||||||
|
DwarfBlock line;
|
||||||
|
DwarfBlock pubnames;
|
||||||
|
DwarfBlock pubtypes;
|
||||||
|
DwarfBlock ranges;
|
||||||
|
DwarfBlock str;
|
||||||
|
|
||||||
|
/* little cache */
|
||||||
|
struct {
|
||||||
|
DwarfAbbrev *a;
|
||||||
|
int na;
|
||||||
|
ulong off;
|
||||||
|
} acache;
|
||||||
|
};
|
||||||
|
|
||||||
|
DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
|
||||||
|
|
||||||
|
int dwarfgetinfounit(Dwarf*, ulong, DwarfBlock*);
|
||||||
|
|
||||||
|
extern int dwarf386nregs;
|
||||||
|
extern char *dwarf386regs[];
|
||||||
|
extern char *dwarf386fp;
|
||||||
|
|
||||||
|
#define SYMBOL_SIZE 18
|
||||||
|
#define MAXIMUM_DWARF_NAME_SIZE 64
|
||||||
|
#define MAXIMUM_COFF_SYMBOL_LENGTH 256
|
25
lib/rossym/dwarf386.c
Normal file
25
lib/rossym/dwarf386.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#if 0
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#include "elf.h"
|
||||||
|
#endif
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
|
char*
|
||||||
|
dwarf386regs[] =
|
||||||
|
{
|
||||||
|
"AX",
|
||||||
|
"CX",
|
||||||
|
"DX",
|
||||||
|
"BX",
|
||||||
|
"SP",
|
||||||
|
"BP",
|
||||||
|
"SI",
|
||||||
|
"DI",
|
||||||
|
};
|
||||||
|
|
||||||
|
int dwarf386nregs = nelem(dwarf386regs);
|
||||||
|
|
||||||
|
|
||||||
|
|
141
lib/rossym/dwarfabbrev.c
Normal file
141
lib/rossym/dwarfabbrev.c
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Dwarf abbreviation parsing code.
|
||||||
|
*
|
||||||
|
* The convention here is that calling dwarfgetabbrevs relinquishes
|
||||||
|
* access to any abbrevs returned previously. Will have to add
|
||||||
|
* explicit reference counting if this turns out not to be acceptable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "rossym.h"
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
|
static int parseabbrevs(Dwarf*, ulong, DwarfAbbrev*, DwarfAttr*, int*, int*);
|
||||||
|
DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
|
||||||
|
|
||||||
|
static int
|
||||||
|
loadabbrevs(Dwarf *d, ulong off, DwarfAbbrev **aa)
|
||||||
|
{
|
||||||
|
int nattr, nabbrev;
|
||||||
|
DwarfAbbrev *abbrev;
|
||||||
|
DwarfAttr *attr;
|
||||||
|
|
||||||
|
if(d->acache.off == off && d->acache.na){
|
||||||
|
*aa = d->acache.a;
|
||||||
|
return d->acache.na;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* two passes - once to count, then allocate, then a second to copy */
|
||||||
|
if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbrev = malloc(nabbrev*sizeof(DwarfAbbrev) + nattr*sizeof(DwarfAttr));
|
||||||
|
attr = (DwarfAttr*)(abbrev+nabbrev);
|
||||||
|
|
||||||
|
if(parseabbrevs(d, off, abbrev, attr, nil, nil) < 0){
|
||||||
|
free(abbrev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(d->acache.a);
|
||||||
|
d->acache.a = abbrev;
|
||||||
|
d->acache.na = nabbrev;
|
||||||
|
d->acache.off = off;
|
||||||
|
|
||||||
|
*aa = abbrev;
|
||||||
|
return nabbrev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pnabbrev, int *pnattr)
|
||||||
|
{
|
||||||
|
int i, nabbrev, nattr, haskids;
|
||||||
|
ulong num, tag, name, form;
|
||||||
|
DwarfBuf b;
|
||||||
|
|
||||||
|
if(off >= d->abbrev.len){
|
||||||
|
werrstr("bad abbrev section offset 0x%lux >= 0x%lux\n", off, d->abbrev.len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&b, 0, sizeof b);
|
||||||
|
b.p = d->abbrev.data + off;
|
||||||
|
b.ep = d->abbrev.data + d->abbrev.len;
|
||||||
|
|
||||||
|
nabbrev = 0;
|
||||||
|
nattr = 0;
|
||||||
|
for(;;){
|
||||||
|
if(b.p == nil){
|
||||||
|
werrstr("malformed abbrev data");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
num = dwarfget128(&b);
|
||||||
|
if(num == 0)
|
||||||
|
break;
|
||||||
|
tag = dwarfget128(&b);
|
||||||
|
haskids = dwarfget1(&b);
|
||||||
|
for(i=0;; i++){
|
||||||
|
name = dwarfget128(&b);
|
||||||
|
form = dwarfget128(&b);
|
||||||
|
if(name == 0 && form == 0)
|
||||||
|
break;
|
||||||
|
if(attr){
|
||||||
|
attr[i].name = name;
|
||||||
|
attr[i].form = form;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(abbrev){
|
||||||
|
abbrev->num = num;
|
||||||
|
abbrev->tag = tag;
|
||||||
|
abbrev->haskids = haskids;
|
||||||
|
abbrev->attr = attr;
|
||||||
|
abbrev->nattr = i;
|
||||||
|
abbrev++;
|
||||||
|
attr += i;
|
||||||
|
}
|
||||||
|
nabbrev++;
|
||||||
|
nattr += i;
|
||||||
|
}
|
||||||
|
if(pnabbrev)
|
||||||
|
*pnabbrev = nabbrev;
|
||||||
|
if(pnattr)
|
||||||
|
*pnattr = nattr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DwarfAbbrev*
|
||||||
|
findabbrev(DwarfAbbrev *a, int na, ulong num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<na; i++)
|
||||||
|
if(a[i].num == num)
|
||||||
|
return &a[i];
|
||||||
|
werrstr("abbrev not found");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
DwarfAbbrev*
|
||||||
|
dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
|
||||||
|
{
|
||||||
|
DwarfAbbrev *a;
|
||||||
|
int na;
|
||||||
|
|
||||||
|
if((na = loadabbrevs(d, off, &a)) < 0){
|
||||||
|
werrstr("loadabbrevs: %r");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return findabbrev(a, na, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
71
lib/rossym/dwarfaranges.c
Normal file
71
lib/rossym/dwarfaranges.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Dwarf address ranges parsing code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfaddrtounit(Dwarf *d, ulong addr, ulong *unit)
|
||||||
|
{
|
||||||
|
DwarfBuf b;
|
||||||
|
int segsize, i;
|
||||||
|
ulong len, id, off, base, size;
|
||||||
|
uchar *start, *end;
|
||||||
|
|
||||||
|
memset(&b, 0, sizeof b);
|
||||||
|
b.d = d;
|
||||||
|
b.p = d->aranges.data;
|
||||||
|
b.ep = b.p + d->aranges.len;
|
||||||
|
|
||||||
|
while(b.p < b.ep){
|
||||||
|
start = b.p;
|
||||||
|
len = dwarfget4(&b);
|
||||||
|
if (!len) { b.ep = b.p - 4; return -1; }
|
||||||
|
if((id = dwarfget2(&b)) != 2){
|
||||||
|
if(b.p == nil){
|
||||||
|
underflow:
|
||||||
|
werrstr("buffer underflow reading address ranges header");
|
||||||
|
}else
|
||||||
|
werrstr("bad dwarf version 0x%x in address ranges header", id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
off = dwarfget4(&b);
|
||||||
|
b.addrsize = dwarfget1(&b);
|
||||||
|
if(d->addrsize == 0)
|
||||||
|
d->addrsize = b.addrsize;
|
||||||
|
segsize = dwarfget1(&b);
|
||||||
|
USED(segsize); /* what am i supposed to do with this? */
|
||||||
|
if(b.p == nil)
|
||||||
|
goto underflow;
|
||||||
|
if((i = (b.p-start) % (2*b.addrsize)) != 0)
|
||||||
|
b.p += 2*b.addrsize - i;
|
||||||
|
end = start+4+len;
|
||||||
|
while(b.p!=nil && b.p<end){
|
||||||
|
base = dwarfgetaddr(&b);
|
||||||
|
size = dwarfgetaddr(&b);
|
||||||
|
if (!size) continue;
|
||||||
|
if(b.p == nil)
|
||||||
|
goto underflow;
|
||||||
|
if(base <= addr && addr < base+size){
|
||||||
|
*unit = off;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(b.p == nil)
|
||||||
|
goto underflow;
|
||||||
|
b.p = end;
|
||||||
|
}
|
||||||
|
werrstr("address 0x%lux is not listed in dwarf debugging symbols", addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
407
lib/rossym/dwarfcfa.c
Normal file
407
lib/rossym/dwarfcfa.c
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
/*
|
||||||
|
* Dwarf call frame unwinding.
|
||||||
|
*
|
||||||
|
* The call frame unwinding values are encoded using a state machine
|
||||||
|
* like the pc<->line mapping, but it's a different machine.
|
||||||
|
* The expressions to generate the old values are similar in function to the
|
||||||
|
* ``dwarf expressions'' used for locations in the code, but of course not
|
||||||
|
* the same encoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
|
#define trace 0
|
||||||
|
|
||||||
|
typedef struct State State;
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
ulong loc;
|
||||||
|
ulong endloc;
|
||||||
|
ulong iquantum;
|
||||||
|
ulong dquantum;
|
||||||
|
char *augmentation;
|
||||||
|
int version;
|
||||||
|
ulong rareg;
|
||||||
|
DwarfBuf init;
|
||||||
|
DwarfExpr *cfa;
|
||||||
|
DwarfExpr *ra;
|
||||||
|
DwarfExpr *r;
|
||||||
|
DwarfExpr *initr;
|
||||||
|
int nr;
|
||||||
|
DwarfExpr **stack;
|
||||||
|
int nstack;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int findfde(Dwarf*, ulong, State*, DwarfBuf*);
|
||||||
|
static int dexec(DwarfBuf*, State*, int);
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int nr)
|
||||||
|
{
|
||||||
|
int i, ret;
|
||||||
|
DwarfBuf fde, b;
|
||||||
|
DwarfExpr *initr;
|
||||||
|
State s;
|
||||||
|
|
||||||
|
initr = mallocz(nr*sizeof(initr[0]), 1);
|
||||||
|
if(initr == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memset(&s, 0, sizeof s);
|
||||||
|
s.loc = 0;
|
||||||
|
s.cfa = cfa;
|
||||||
|
s.ra = ra;
|
||||||
|
s.r = r;
|
||||||
|
s.nr = nr;
|
||||||
|
|
||||||
|
if(findfde(d, pc, &s, &fde) < 0){
|
||||||
|
free(initr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(r, 0, nr*sizeof(r[0]));
|
||||||
|
for(i=0; i<nr; i++)
|
||||||
|
r[i].type = RuleSame;
|
||||||
|
if(trace) werrstr("s.init %p-%p, fde %p-%p\n", s.init.p, s.init.ep, fde.p, fde.ep);
|
||||||
|
b = s.init;
|
||||||
|
if(dexec(&b, &s, 0) < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
s.initr = initr;
|
||||||
|
memmove(initr, r, nr*sizeof(initr[0]));
|
||||||
|
|
||||||
|
if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
|
||||||
|
while(s.loc < pc){
|
||||||
|
if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
|
||||||
|
if(dexec(&fde, &s, 1) < 0)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
*ra = s.r[s.rareg];
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err:
|
||||||
|
ret = -1;
|
||||||
|
out:
|
||||||
|
free(initr);
|
||||||
|
for(i=0; i<s.nstack; i++)
|
||||||
|
free(s.stack[i]);
|
||||||
|
free(s.stack);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX This turns out to be much more expensive than the actual
|
||||||
|
* running of the machine in dexec. It probably makes sense to
|
||||||
|
* cache the last 10 or so fde's we've found, since stack traces
|
||||||
|
* will keep asking for the same info over and over.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
|
||||||
|
{
|
||||||
|
static int nbad;
|
||||||
|
char *aug;
|
||||||
|
uchar *next;
|
||||||
|
int i, vers;
|
||||||
|
ulong len, id, base, size;
|
||||||
|
DwarfBuf b;
|
||||||
|
|
||||||
|
if(d->frame.data == nil){
|
||||||
|
werrstr("no frame debugging information");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
b.d = d;
|
||||||
|
b.p = d->frame.data;
|
||||||
|
b.ep = b.p + d->frame.len;
|
||||||
|
b.addrsize = d->addrsize;
|
||||||
|
if(b.addrsize == 0)
|
||||||
|
b.addrsize = 4; /* where should i find this? */
|
||||||
|
|
||||||
|
for(; b.p < b.ep; b.p = next){
|
||||||
|
if((i = (b.p - d->frame.data) % b.addrsize))
|
||||||
|
b.p += b.addrsize - i;
|
||||||
|
len = dwarfget4(&b);
|
||||||
|
if(len > b.ep-b.p){
|
||||||
|
werrstr("bad length in cie/fde header");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
next = b.p+len;
|
||||||
|
id = dwarfget4(&b);
|
||||||
|
if(id == 0xFFFFFFFF){ /* CIE */
|
||||||
|
vers = dwarfget1(&b);
|
||||||
|
if(vers != 1 && vers != 2 && vers != 3){
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("unknown cie version %d (wanted 1-3)\n", vers);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
aug = dwarfgetstring(&b);
|
||||||
|
if(aug && *aug){
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("unknown augmentation: %s\n", aug);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s->iquantum = dwarfget128(&b);
|
||||||
|
s->dquantum = dwarfget128s(&b);
|
||||||
|
s->rareg = dwarfget128(&b);
|
||||||
|
if(s->rareg > s->nr){
|
||||||
|
werrstr("return address is register %d but only have %d registers",
|
||||||
|
s->rareg, s->nr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->init.p = b.p;
|
||||||
|
s->init.ep = next;
|
||||||
|
}else{ /* FDE */
|
||||||
|
base = dwarfgetaddr(&b);
|
||||||
|
size = dwarfgetaddr(&b);
|
||||||
|
fde->p = b.p;
|
||||||
|
fde->ep = next;
|
||||||
|
s->loc = base;
|
||||||
|
s->endloc = base+size;
|
||||||
|
if(base <= pc && pc < base+size)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
werrstr("cannot find call frame information for pc 0x%lux", pc);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
checkreg(State *s, long r)
|
||||||
|
{
|
||||||
|
if(r < 0 || r >= s->nr){
|
||||||
|
werrstr("bad register number 0x%lux", r);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dexec(DwarfBuf *b, State *s, int locstop)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
long arg1, arg2;
|
||||||
|
DwarfExpr *e, **p;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
if(b->p == b->ep){
|
||||||
|
if(s->initr)
|
||||||
|
s->loc = s->endloc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
c = dwarfget1(b);
|
||||||
|
if(b->p == nil){
|
||||||
|
werrstr("ran out of instructions during cfa program");
|
||||||
|
if(trace) werrstr("%r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(trace) werrstr("+ loc=0x%lux op 0x%ux ", s->loc, c);
|
||||||
|
switch(c>>6){
|
||||||
|
case 1: /* advance location */
|
||||||
|
arg1 = c&0x3F;
|
||||||
|
advance:
|
||||||
|
if(trace) werrstr("loc += %ld\n", arg1*s->iquantum);
|
||||||
|
s->loc += arg1 * s->iquantum;
|
||||||
|
if(locstop)
|
||||||
|
return 0;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 2: /* offset rule */
|
||||||
|
arg1 = c&0x3F;
|
||||||
|
arg2 = dwarfget128(b);
|
||||||
|
offset:
|
||||||
|
if(trace) werrstr("r%ld += %ld\n", arg1, arg2*s->dquantum);
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->r[arg1].type = RuleCfaOffset;
|
||||||
|
s->r[arg1].offset = arg2 * s->dquantum;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 3: /* restore initial setting */
|
||||||
|
arg1 = c&0x3F;
|
||||||
|
restore:
|
||||||
|
if(trace) werrstr("r%ld = init\n", arg1);
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->r[arg1] = s->initr[arg1];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(c){
|
||||||
|
case 0: /* nop */
|
||||||
|
if(trace) werrstr("nop\n");
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x01: /* set location */
|
||||||
|
s->loc = dwarfgetaddr(b);
|
||||||
|
if(trace) werrstr("loc = 0x%lux\n", s->loc);
|
||||||
|
if(locstop)
|
||||||
|
return 0;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x02: /* advance loc1 */
|
||||||
|
arg1 = dwarfget1(b);
|
||||||
|
goto advance;
|
||||||
|
|
||||||
|
case 0x03: /* advance loc2 */
|
||||||
|
arg1 = dwarfget2(b);
|
||||||
|
goto advance;
|
||||||
|
|
||||||
|
case 0x04: /* advance loc4 */
|
||||||
|
arg1 = dwarfget4(b);
|
||||||
|
goto advance;
|
||||||
|
|
||||||
|
case 0x05: /* offset extended */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
arg2 = dwarfget128(b);
|
||||||
|
goto offset;
|
||||||
|
|
||||||
|
case 0x06: /* restore extended */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
goto restore;
|
||||||
|
|
||||||
|
case 0x07: /* undefined */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
if(trace) werrstr("r%ld = undef\n", arg1);
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->r[arg1].type = RuleUndef;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x08: /* same value */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
if(trace) werrstr("r%ld = same\n", arg1);
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->r[arg1].type = RuleSame;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x09: /* register */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
arg2 = dwarfget128(b);
|
||||||
|
if(trace) werrstr("r%ld = r%ld\n", arg1, arg2);
|
||||||
|
if(checkreg(s, arg1) < 0 || checkreg(s, arg2) < 0)
|
||||||
|
return -1;
|
||||||
|
s->r[arg1].type = RuleRegister;
|
||||||
|
s->r[arg1].reg = arg2;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x0A: /* remember state */
|
||||||
|
e = malloc(s->nr*sizeof(e[0]));
|
||||||
|
if(trace) werrstr("push\n");
|
||||||
|
if(e == nil)
|
||||||
|
return -1;
|
||||||
|
void *newstack = malloc(s->nstack*sizeof(s->stack[0]));
|
||||||
|
RtlMoveMemory(newstack, s->stack, s->nstack*sizeof(s->stack[0]));
|
||||||
|
if (newstack) {
|
||||||
|
free(s->stack);
|
||||||
|
s->stack = newstack;
|
||||||
|
} else {
|
||||||
|
free(e);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(p == nil){
|
||||||
|
free(e);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->stack[s->nstack++] = e;
|
||||||
|
memmove(e, s->r, s->nr*sizeof(e[0]));
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x0B: /* restore state */
|
||||||
|
if(trace) werrstr("pop\n");
|
||||||
|
if(s->nstack == 0){
|
||||||
|
werrstr("restore state underflow");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
e = s->stack[s->nstack-1];
|
||||||
|
memmove(s->r, e, s->nr*sizeof(e[0]));
|
||||||
|
free(e);
|
||||||
|
s->nstack--;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x0C: /* def cfa */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
arg2 = dwarfget128(b);
|
||||||
|
defcfa:
|
||||||
|
if(trace) werrstr("cfa %ld(r%ld)\n", arg2, arg1);
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->cfa->type = RuleRegOff;
|
||||||
|
s->cfa->reg = arg1;
|
||||||
|
s->cfa->offset = arg2;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x0D: /* def cfa register */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
if(trace) werrstr("cfa reg r%ld\n", arg1);
|
||||||
|
if(s->cfa->type != RuleRegOff){
|
||||||
|
werrstr("change CFA register but CFA not in register+offset form");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->cfa->reg = arg1;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x0E: /* def cfa offset */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
cfaoffset:
|
||||||
|
if(trace) werrstr("cfa off %ld\n", arg1);
|
||||||
|
if(s->cfa->type != RuleRegOff){
|
||||||
|
werrstr("change CFA offset but CFA not in register+offset form");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->cfa->offset = arg1;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x0F: /* def cfa expression */
|
||||||
|
if(trace) werrstr("cfa expr\n");
|
||||||
|
s->cfa->type = RuleLocation;
|
||||||
|
s->cfa->loc.len = dwarfget128(b);
|
||||||
|
s->cfa->loc.data = dwarfgetnref(b, s->cfa->loc.len);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x10: /* def reg expression */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
if(trace) werrstr("reg expr r%ld\n", arg1);
|
||||||
|
if(checkreg(s, arg1) < 0)
|
||||||
|
return -1;
|
||||||
|
s->r[arg1].type = RuleLocation;
|
||||||
|
s->r[arg1].loc.len = dwarfget128(b);
|
||||||
|
s->r[arg1].loc.data = dwarfgetnref(b, s->r[arg1].loc.len);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 0x11: /* offset extended */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
arg2 = dwarfget128s(b);
|
||||||
|
goto offset;
|
||||||
|
|
||||||
|
case 0x12: /* cfa sf */
|
||||||
|
arg1 = dwarfget128(b);
|
||||||
|
arg2 = dwarfget128s(b);
|
||||||
|
goto defcfa;
|
||||||
|
|
||||||
|
case 0x13: /* cfa offset sf */
|
||||||
|
arg1 = dwarfget128s(b);
|
||||||
|
goto cfaoffset;
|
||||||
|
|
||||||
|
default: /* unknown */
|
||||||
|
werrstr("unknown opcode 0x%ux in cfa program", c);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* not reached */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
143
lib/rossym/dwarfdump.c
Normal file
143
lib/rossym/dwarfdump.c
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#if 0
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include "elf.h"
|
||||||
|
#endif
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "pe.h"
|
||||||
|
|
||||||
|
void printrules(Dwarf *d, ulong pc);
|
||||||
|
//int exprfmt(Fmt*);
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprint(2, "usage: dwarfdump file\n");
|
||||||
|
exits("usage");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
Pe *pe;
|
||||||
|
Dwarf *d;
|
||||||
|
DwarfSym s;
|
||||||
|
char *cdir, *dir, *file;
|
||||||
|
ulong line, mtime, length;
|
||||||
|
|
||||||
|
if(argc != 2)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fmtinstall('R', exprfmt);
|
||||||
|
fmtinstall('H', encodefmt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((pe = peopen(argv[1])) == nil)
|
||||||
|
sysfatal("elfopen %s: %r", argv[1]);
|
||||||
|
if((d=dwarfopen(pe)) == nil)
|
||||||
|
sysfatal("dwarfopen: %r");
|
||||||
|
|
||||||
|
if(dwarfenum(d, &s) < 0)
|
||||||
|
sysfatal("dwarfenumall: %r");
|
||||||
|
|
||||||
|
while(dwarfnextsym(d, &s) == 1){
|
||||||
|
switch(s.attrs.tag){
|
||||||
|
case TagCompileUnit:
|
||||||
|
print("compileunit %s\n", s.attrs.name);
|
||||||
|
break;
|
||||||
|
case TagSubprogram:
|
||||||
|
c = 't';
|
||||||
|
goto sym;
|
||||||
|
case TagVariable:
|
||||||
|
c = 'd';
|
||||||
|
goto sym;
|
||||||
|
case TagConstant:
|
||||||
|
c = 'c';
|
||||||
|
goto sym;
|
||||||
|
case TagFormalParameter:
|
||||||
|
if(!s.attrs.name)
|
||||||
|
break;
|
||||||
|
c = 'p';
|
||||||
|
sym:
|
||||||
|
if(s.attrs.isexternal)
|
||||||
|
c += 'A' - 'a';
|
||||||
|
print("%c %s", c, s.attrs.name);
|
||||||
|
if(s.attrs.have.lowpc)
|
||||||
|
print(" 0x%lux-0x%lux", s.attrs.lowpc, s.attrs.highpc);
|
||||||
|
switch(s.attrs.have.location){
|
||||||
|
case TBlock:
|
||||||
|
print(" @ %.*H", s.attrs.location.b.len, s.attrs.location.b.data);
|
||||||
|
break;
|
||||||
|
case TConstant:
|
||||||
|
print(" @ 0x%lux", s.attrs.location.c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(s.attrs.have.ranges)
|
||||||
|
print(" ranges@0x%lux", s.attrs.ranges);
|
||||||
|
print("\n");
|
||||||
|
if(s.attrs.have.lowpc){
|
||||||
|
if(dwarfpctoline(d, s.attrs.lowpc, &cdir, &dir, &file, &line, &mtime, &length) < 0)
|
||||||
|
print("\tcould not find source: %r\n");
|
||||||
|
else if(dir == nil)
|
||||||
|
print("\t%s/%s:%lud mtime=%lud length=%lud\n",
|
||||||
|
cdir, file, line, mtime, length);
|
||||||
|
else
|
||||||
|
print("\t%s/%s/%s:%lud mtime=%lud length=%lud\n",
|
||||||
|
cdir, dir, file, line, mtime, length);
|
||||||
|
|
||||||
|
if(0) printrules(d, s.attrs.lowpc);
|
||||||
|
if(0) printrules(d, (s.attrs.lowpc+s.attrs.highpc)/2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printrules(Dwarf *d, ulong pc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DwarfExpr r[10];
|
||||||
|
DwarfExpr cfa, ra;
|
||||||
|
|
||||||
|
if(dwarfunwind(d, pc, &cfa, &ra, r, nelem(r)) < 0)
|
||||||
|
print("\tcannot unwind from pc 0x%lux: %r\n", pc);
|
||||||
|
|
||||||
|
print("\tpc=0x%lux cfa=%R ra=%R", pc, &cfa, &ra);
|
||||||
|
for(i=0; i<nelem(r); i++)
|
||||||
|
if(r[i].type != RuleSame)
|
||||||
|
print(" r%d=%R", i, &r[i]);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int
|
||||||
|
exprfmt(Fmt *fmt)
|
||||||
|
{
|
||||||
|
DwarfExpr *e;
|
||||||
|
|
||||||
|
if((e = va_arg(fmt->args, DwarfExpr*)) == nil)
|
||||||
|
return fmtstrcpy(fmt, "<nil>");
|
||||||
|
|
||||||
|
switch(e->type){
|
||||||
|
case RuleUndef:
|
||||||
|
return fmtstrcpy(fmt, "undef");
|
||||||
|
case RuleSame:
|
||||||
|
return fmtstrcpy(fmt, "same");
|
||||||
|
case RuleCfaOffset:
|
||||||
|
return fmtprint(fmt, "%ld(cfa)", e->offset);
|
||||||
|
case RuleRegister:
|
||||||
|
return fmtprint(fmt, "r%ld", e->reg);
|
||||||
|
case RuleRegOff:
|
||||||
|
return fmtprint(fmt, "%ld(r%ld)", e->offset, e->reg);
|
||||||
|
case RuleLocation:
|
||||||
|
return fmtprint(fmt, "l.%.*H", e->loc.len, e->loc.data);
|
||||||
|
default:
|
||||||
|
return fmtprint(fmt, "?%d", e->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
61
lib/rossym/dwarfeval.c
Normal file
61
lib/rossym/dwarfeval.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
OpAddr = 0x03, /* 1 op, const addr */
|
||||||
|
OpDeref = 0x06,
|
||||||
|
OpConst1u = 0x08, /* 1 op, 1 byte const */
|
||||||
|
OpConst1s = 0x09, /* " signed */
|
||||||
|
OpConst2u = 0x0A, /* 1 op, 2 byte const */
|
||||||
|
OpConst2s = 0x0B, /* " signed */
|
||||||
|
OpConst4u = 0x0C, /* 1 op, 4 byte const */
|
||||||
|
OpConst4s = 0x0D, /* " signed */
|
||||||
|
OpConst8u = 0x0E, /* 1 op, 8 byte const */
|
||||||
|
OpConst8s = 0x0F, /* " signed */
|
||||||
|
OpConstu = 0x10, /* 1 op, LEB128 const */
|
||||||
|
OpConsts = 0x11, /* " signed */
|
||||||
|
OpDup = 0x12,
|
||||||
|
OpDrop = 0x13,
|
||||||
|
OpOver = 0x14,
|
||||||
|
OpPick = 0x15, /* 1 op, 1 byte stack index */
|
||||||
|
OpSwap = 0x16,
|
||||||
|
OpRot = 0x17,
|
||||||
|
OpXderef = 0x18,
|
||||||
|
OpAbs = 0x19,
|
||||||
|
OpAnd = 0x1A,
|
||||||
|
OpDiv = 0x1B,
|
||||||
|
OpMinus = 0x1C,
|
||||||
|
OpMod = 0x1D,
|
||||||
|
OpMul = 0x1E,
|
||||||
|
OpNeg = 0x1F,
|
||||||
|
OpNot = 0x20,
|
||||||
|
OpOr = 0x21,
|
||||||
|
OpPlus = 0x22,
|
||||||
|
OpPlusUconst = 0x23, /* 1 op, ULEB128 addend */
|
||||||
|
OpShl = 0x24,
|
||||||
|
OpShr = 0x25,
|
||||||
|
OpShra = 0x26,
|
||||||
|
OpXor = 0x27,
|
||||||
|
OpSkip = 0x2F, /* 1 op, signed 2-byte constant */
|
||||||
|
OpBra = 0x28, /* 1 op, signed 2-byte constant */
|
||||||
|
OpEq = 0x29,
|
||||||
|
OpGe = 0x2A,
|
||||||
|
OpGt = 0x2B,
|
||||||
|
OpLe = 0x2C,
|
||||||
|
OpLt = 0x2D,
|
||||||
|
OpNe = 0x2E,
|
||||||
|
OpLit0 = 0x30,
|
||||||
|
/* OpLitN = OpLit0 + N for N = 0..31 */
|
||||||
|
OpReg0 = 0x50,
|
||||||
|
/* OpRegN = OpReg0 + N for N = 0..31 */
|
||||||
|
OpBreg0 = 0x70, /* 1 op, signed LEB128 constant */
|
||||||
|
/* OpBregN = OpBreg0 + N for N = 0..31 */
|
||||||
|
OpRegx = 0x90, /* 1 op, ULEB128 register */
|
||||||
|
OpFbreg = 0x91, /* 1 op, SLEB128 offset */
|
||||||
|
OpBregx = 0x92, /* 2 op, ULEB128 reg, SLEB128 off */
|
||||||
|
OpPiece = 0x93, /* 1 op, ULEB128 size of piece */
|
||||||
|
OpDerefSize = 0x94, /* 1-byte size of data retrieved */
|
||||||
|
OpXderefSize = 0x95, /* 1-byte size of data retrieved */
|
||||||
|
OpNop = 0x96,
|
||||||
|
/* next four new in Dwarf v3 */
|
||||||
|
OpPushObjAddr = 0x97,
|
||||||
|
OpCall2 = 0x98, /* 2-byte offset of DIE */
|
||||||
|
OpCall4 = 0x99, /* 4-byte offset of DIE */
|
||||||
|
OpCallRef = 0x9A, /* 4- or 8- byte offset of DIE */
|
||||||
|
/* 0xE0-0xFF reserved for user-specific */
|
225
lib/rossym/dwarfget.c
Normal file
225
lib/rossym/dwarfget.c
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* Dwarf data format parsing routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "pe.h"
|
||||||
|
|
||||||
|
ulong
|
||||||
|
dwarfget1(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
if(b->p==nil || b->p+1 > b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return *b->p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfgetn(DwarfBuf *b, uchar *a, int n)
|
||||||
|
{
|
||||||
|
if(b->p==nil || b->p+n > b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
memset(a, 0, n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memmove(a, b->p, n);
|
||||||
|
b->p += n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar*
|
||||||
|
dwarfgetnref(DwarfBuf *b, ulong n)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
|
||||||
|
if(b->p==nil || b->p+n > b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
p = b->p;
|
||||||
|
b->p += n;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
dwarfgetstring(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if(b->p == nil)
|
||||||
|
return nil;
|
||||||
|
s = (char*)b->p;
|
||||||
|
while(b->p < b->ep && *b->p)
|
||||||
|
b->p++;
|
||||||
|
if(b->p >= b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
b->p++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dwarfskip(DwarfBuf *b, int n)
|
||||||
|
{
|
||||||
|
if(b->p==nil || b->p+n > b->ep)
|
||||||
|
b->p = nil;
|
||||||
|
else
|
||||||
|
b->p += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong
|
||||||
|
dwarfget2(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
|
||||||
|
if(b->p==nil || b->p+2 > b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
v = b->d->pe->e2(b->p);
|
||||||
|
b->p += 2;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong
|
||||||
|
dwarfget4(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
|
||||||
|
if(b->p==nil || b->p+4 > b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
v = b->d->pe->e4(b->p);
|
||||||
|
b->p += 4;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uvlong
|
||||||
|
dwarfget8(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
uvlong v;
|
||||||
|
|
||||||
|
if(b->p==nil || b->p+8 > b->ep){
|
||||||
|
b->p = nil;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
v = b->d->pe->e8(b->p);
|
||||||
|
b->p += 8;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong
|
||||||
|
dwarfgetaddr(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
static int nbad;
|
||||||
|
|
||||||
|
if(b->addrsize == 0)
|
||||||
|
b->addrsize = b->d->addrsize;
|
||||||
|
|
||||||
|
switch(b->addrsize){
|
||||||
|
case 1:
|
||||||
|
return dwarfget1(b);
|
||||||
|
case 2:
|
||||||
|
return dwarfget2(b);
|
||||||
|
case 4:
|
||||||
|
return dwarfget4(b);
|
||||||
|
case 8:
|
||||||
|
return dwarfget8(b);
|
||||||
|
default:
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("dwarf: unexpected address size %lud in dwarfgetaddr\n", b->addrsize);
|
||||||
|
b->p = nil;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int n1, n2, n3, n4, n5;
|
||||||
|
|
||||||
|
/* An inline function picks off the calls to dwarfget128 for 1-byte encodings,
|
||||||
|
* more than by far the common case (99.999% on most binaries!). */
|
||||||
|
ulong
|
||||||
|
dwarfget128(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
static int nbad;
|
||||||
|
ulong c, d;
|
||||||
|
|
||||||
|
if(b->p == nil)
|
||||||
|
return 0;
|
||||||
|
c = *b->p++;
|
||||||
|
if(!(c&0x80))
|
||||||
|
{n1++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
c &= ~0x80;
|
||||||
|
d = *b->p++;
|
||||||
|
c |= (d&0x7F)<<7;
|
||||||
|
if(!(d&0x80))
|
||||||
|
{n2++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
d = *b->p++;
|
||||||
|
c |= (d&0x7F)<<14;
|
||||||
|
if(!(d&0x80))
|
||||||
|
{n3++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
d = *b->p++;
|
||||||
|
c |= (d&0x7F)<<21;
|
||||||
|
if(!(d&0x80))
|
||||||
|
{n4++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
d = *b->p++;
|
||||||
|
c |= (d&0x7F)<<28;
|
||||||
|
if(!(d&0x80))
|
||||||
|
{n5++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
while(b->p<b->ep && *b->p&0x80)
|
||||||
|
b->p++;
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("dwarf: overflow during parsing of uleb128 integer\n");
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
dwarfget128s(DwarfBuf *b)
|
||||||
|
{
|
||||||
|
int nb, c;
|
||||||
|
ulong v;
|
||||||
|
static int nbad;
|
||||||
|
|
||||||
|
v = 0;
|
||||||
|
nb = 0;
|
||||||
|
if(b->p==nil)
|
||||||
|
return 0;
|
||||||
|
while(b->p<b->ep){
|
||||||
|
c = *b->p++;
|
||||||
|
v |= (c & 0x7F)<<nb;
|
||||||
|
nb += 7;
|
||||||
|
if(!(c&0x80))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(v&(1<<(nb-1)))
|
||||||
|
v |= ~(((ulong)1<<nb)-1);
|
||||||
|
if(nb > 8*sizeof(ulong)){
|
||||||
|
if(0)
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("dwarf: overflow during parsing of sleb128 integer: got %d bits", nb);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
661
lib/rossym/dwarfinfo.c
Normal file
661
lib/rossym/dwarfinfo.c
Normal file
|
@ -0,0 +1,661 @@
|
||||||
|
/*
|
||||||
|
* Dwarf info parse and search.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntifs.h>
|
||||||
|
#include <ndk/ntndk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include <windef.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DwarfAttrSibling = 0x01,
|
||||||
|
DwarfAttrLocation = 0x02,
|
||||||
|
DwarfAttrName = 0x03,
|
||||||
|
DwarfAttrOrdering = 0x09,
|
||||||
|
DwarfAttrByteSize = 0x0B,
|
||||||
|
DwarfAttrBitOffset = 0x0C,
|
||||||
|
DwarfAttrBitSize = 0x0D,
|
||||||
|
DwarfAttrStmtList = 0x10,
|
||||||
|
DwarfAttrLowpc = 0x11,
|
||||||
|
DwarfAttrHighpc = 0x12,
|
||||||
|
DwarfAttrLanguage = 0x13,
|
||||||
|
DwarfAttrDiscr = 0x15,
|
||||||
|
DwarfAttrDiscrValue = 0x16,
|
||||||
|
DwarfAttrVisibility = 0x17,
|
||||||
|
DwarfAttrImport = 0x18,
|
||||||
|
DwarfAttrStringLength = 0x19,
|
||||||
|
DwarfAttrCommonRef = 0x1A,
|
||||||
|
DwarfAttrCompDir = 0x1B,
|
||||||
|
DwarfAttrConstValue = 0x1C,
|
||||||
|
DwarfAttrContainingType = 0x1D,
|
||||||
|
DwarfAttrDefaultValue = 0x1E,
|
||||||
|
DwarfAttrInline = 0x20,
|
||||||
|
DwarfAttrIsOptional = 0x21,
|
||||||
|
DwarfAttrLowerBound = 0x22,
|
||||||
|
DwarfAttrProducer = 0x25,
|
||||||
|
DwarfAttrPrototyped = 0x27,
|
||||||
|
DwarfAttrReturnAddr = 0x2A,
|
||||||
|
DwarfAttrStartScope = 0x2C,
|
||||||
|
DwarfAttrStrideSize = 0x2E,
|
||||||
|
DwarfAttrUpperBound = 0x2F,
|
||||||
|
DwarfAttrAbstractOrigin = 0x31,
|
||||||
|
DwarfAttrAccessibility = 0x32,
|
||||||
|
DwarfAttrAddrClass = 0x33,
|
||||||
|
DwarfAttrArtificial = 0x34,
|
||||||
|
DwarfAttrBaseTypes = 0x35,
|
||||||
|
DwarfAttrCalling = 0x36,
|
||||||
|
DwarfAttrCount = 0x37,
|
||||||
|
DwarfAttrDataMemberLoc = 0x38,
|
||||||
|
DwarfAttrDeclColumn = 0x39,
|
||||||
|
DwarfAttrDeclFile = 0x3A,
|
||||||
|
DwarfAttrDeclLine = 0x3B,
|
||||||
|
DwarfAttrDeclaration = 0x3C,
|
||||||
|
DwarfAttrDiscrList = 0x3D,
|
||||||
|
DwarfAttrEncoding = 0x3E,
|
||||||
|
DwarfAttrExternal = 0x3F,
|
||||||
|
DwarfAttrFrameBase = 0x40,
|
||||||
|
DwarfAttrFriend = 0x41,
|
||||||
|
DwarfAttrIdentifierCase = 0x42,
|
||||||
|
DwarfAttrMacroInfo = 0x43,
|
||||||
|
DwarfAttrNamelistItem = 0x44,
|
||||||
|
DwarfAttrPriority = 0x45,
|
||||||
|
DwarfAttrSegment = 0x46,
|
||||||
|
DwarfAttrSpecification = 0x47,
|
||||||
|
DwarfAttrStaticLink = 0x48,
|
||||||
|
DwarfAttrType = 0x49,
|
||||||
|
DwarfAttrUseLocation = 0x4A,
|
||||||
|
DwarfAttrVarParam = 0x4B,
|
||||||
|
DwarfAttrVirtuality = 0x4C,
|
||||||
|
DwarfAttrVtableElemLoc = 0x4D,
|
||||||
|
DwarfAttrAllocated = 0x4E,
|
||||||
|
DwarfAttrAssociated = 0x4F,
|
||||||
|
DwarfAttrDataLocation = 0x50,
|
||||||
|
DwarfAttrStride = 0x51,
|
||||||
|
DwarfAttrEntrypc = 0x52,
|
||||||
|
DwarfAttrUseUTF8 = 0x53,
|
||||||
|
DwarfAttrExtension = 0x54,
|
||||||
|
DwarfAttrRanges = 0x55,
|
||||||
|
DwarfAttrTrampoline = 0x56,
|
||||||
|
DwarfAttrCallColumn = 0x57,
|
||||||
|
DwarfAttrCallFile = 0x58,
|
||||||
|
DwarfAttrCallLine = 0x59,
|
||||||
|
DwarfAttrDescription = 0x5A,
|
||||||
|
DwarfAttrMax,
|
||||||
|
|
||||||
|
FormAddr = 0x01,
|
||||||
|
FormDwarfBlock2 = 0x03,
|
||||||
|
FormDwarfBlock4 = 0x04,
|
||||||
|
FormData2 = 0x05,
|
||||||
|
FormData4 = 0x06,
|
||||||
|
FormData8 = 0x07,
|
||||||
|
FormString = 0x08,
|
||||||
|
FormDwarfBlock = 0x09,
|
||||||
|
FormDwarfBlock1 = 0x0A,
|
||||||
|
FormData1 = 0x0B,
|
||||||
|
FormFlag = 0x0C,
|
||||||
|
FormSdata = 0x0D,
|
||||||
|
FormStrp = 0x0E,
|
||||||
|
FormUdata = 0x0F,
|
||||||
|
FormRefAddr = 0x10,
|
||||||
|
FormRef1 = 0x11,
|
||||||
|
FormRef2 = 0x12,
|
||||||
|
FormRef4 = 0x13,
|
||||||
|
FormRef8 = 0x14,
|
||||||
|
FormRefUdata = 0x15,
|
||||||
|
FormIndirect = 0x16
|
||||||
|
};
|
||||||
|
|
||||||
|
static int parseattrs(DwarfBuf*, ulong, DwarfAbbrev*, DwarfAttrs*);
|
||||||
|
static int getulong(DwarfBuf*, int, ulong, ulong*, int*);
|
||||||
|
static int getuchar(DwarfBuf*, int, uchar*);
|
||||||
|
static int getstring(DwarfBuf*, int, char**);
|
||||||
|
static int getblock(DwarfBuf*, int, DwarfBlock*);
|
||||||
|
static int skipform(DwarfBuf*, int);
|
||||||
|
static int constblock(Dwarf*, DwarfBlock*, ulong*);
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s)
|
||||||
|
{
|
||||||
|
if(dwarfenumunit(d, unit, s) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
|
||||||
|
while(dwarfnextsymat(d, s, 1) == 1)
|
||||||
|
if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
|
||||||
|
return 0;
|
||||||
|
werrstr("symbol '%s' not found", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s)
|
||||||
|
{
|
||||||
|
*s = *parent;
|
||||||
|
while(dwarfnextsymat(d, s, parent->depth+1))
|
||||||
|
if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
|
||||||
|
return 0;
|
||||||
|
werrstr("symbol '%s' not found", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
|
||||||
|
{
|
||||||
|
if(dwarfenumunit(d, unit, s) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
|
||||||
|
if(s->attrs.tag == tag) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while(dwarfnextsymat(d, s, 1) == 1)
|
||||||
|
if(s->attrs.tag == tag) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
werrstr("symbol with tag 0x%lux not found", tag);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
|
||||||
|
{
|
||||||
|
if(dwarfenumunit(d, unit, s) < 0)
|
||||||
|
return -1;
|
||||||
|
s->b.p = d->info.data + unit + off;
|
||||||
|
if(dwarfnextsymat(d, s, 0) != 1)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s)
|
||||||
|
{
|
||||||
|
if(dwarfenumunit(d, unit, s) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(dwarfnextsymat(d, s, 0) != 1)
|
||||||
|
return -1;
|
||||||
|
/* s is now the CompileUnit */
|
||||||
|
|
||||||
|
while(dwarfnextsymat(d, s, 1) == 1){
|
||||||
|
if(s->attrs.tag != TagSubprogram)
|
||||||
|
continue;
|
||||||
|
if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
werrstr("fn containing pc 0x%lux not found", pc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
ulong aoff, len;
|
||||||
|
|
||||||
|
if(unit >= d->info.len){
|
||||||
|
werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(s, 0, sizeof *s);
|
||||||
|
memset(&s->b, 0, sizeof s->b);
|
||||||
|
|
||||||
|
s->b.d = d;
|
||||||
|
s->b.p = d->info.data + unit;
|
||||||
|
s->b.ep = d->info.data + d->info.len;
|
||||||
|
len = dwarfget4(&s->b);
|
||||||
|
s->nextunit = unit + 4 + len;
|
||||||
|
|
||||||
|
if(s->b.ep - s->b.p < len){
|
||||||
|
badheader:
|
||||||
|
werrstr("bad dwarf unit header at unit 0x%lux", unit);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->b.ep = s->b.p+len;
|
||||||
|
if((i=dwarfget2(&s->b)) != 2)
|
||||||
|
goto badheader;
|
||||||
|
aoff = dwarfget4(&s->b);
|
||||||
|
s->b.addrsize = dwarfget1(&s->b);
|
||||||
|
if(d->addrsize == 0)
|
||||||
|
d->addrsize = s->b.addrsize;
|
||||||
|
if(s->b.p == nil)
|
||||||
|
goto badheader;
|
||||||
|
|
||||||
|
s->aoff = aoff;
|
||||||
|
s->unit = unit;
|
||||||
|
s->depth = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfenum(Dwarf *d, DwarfSym *s)
|
||||||
|
{
|
||||||
|
if(dwarfenumunit(d, 0, s) < 0)
|
||||||
|
return -1;
|
||||||
|
s->allunits = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfnextsym(Dwarf *d, DwarfSym *s)
|
||||||
|
{
|
||||||
|
ulong num;
|
||||||
|
DwarfAbbrev *a;
|
||||||
|
|
||||||
|
if(s->attrs.haskids)
|
||||||
|
s->depth++;
|
||||||
|
top:
|
||||||
|
if(s->b.p >= s->b.ep){
|
||||||
|
if(s->allunits && s->nextunit < d->info.len){
|
||||||
|
if(dwarfenumunit(d, s->nextunit, s) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->allunits = 1;
|
||||||
|
goto top;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->uoff = s->b.p - (d->info.data+s->unit);
|
||||||
|
num = dwarfget128(&s->b);
|
||||||
|
if(num == 0){
|
||||||
|
if(s->depth == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(s->depth > 0)
|
||||||
|
s->depth--;
|
||||||
|
goto top;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = dwarfgetabbrev(d, s->aoff, num);
|
||||||
|
if(a == nil){
|
||||||
|
werrstr("getabbrev %ud %ud for %ud,%ud: %r\n", s->aoff, num, s->unit, s->uoff);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
DwarfSym t;
|
||||||
|
uint sib;
|
||||||
|
|
||||||
|
if(s->depth == depth && s->attrs.have.sibling){
|
||||||
|
sib = s->attrs.sibling;
|
||||||
|
if(sib < d->info.len && d->info.data+sib >= s->b.p)
|
||||||
|
s->b.p = d->info.data+sib;
|
||||||
|
s->attrs.haskids = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The funny game with t and s make sure that
|
||||||
|
* if we get to the end of a run of a particular
|
||||||
|
* depth, we leave s so that a call to nextsymat with depth-1
|
||||||
|
* will actually produce the desired guy. We could change
|
||||||
|
* the interface to dwarfnextsym instead, but I'm scared
|
||||||
|
* to touch it.
|
||||||
|
*/
|
||||||
|
t = *s;
|
||||||
|
for(;;){
|
||||||
|
if((r = dwarfnextsym(d, &t)) != 1) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if(t.depth < depth){
|
||||||
|
/* went too far - nothing to see */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*s = t;
|
||||||
|
if(t.depth == depth) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct Parse Parse;
|
||||||
|
struct Parse {
|
||||||
|
int name;
|
||||||
|
int off;
|
||||||
|
int haveoff;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
|
||||||
|
|
||||||
|
static Parse plist[] = { /* Font Tab 4 */
|
||||||
|
{ DwarfAttrAbstractOrigin, OFFSET(abstractorigin), TReference },
|
||||||
|
{ DwarfAttrAccessibility, OFFSET(accessibility), TConstant },
|
||||||
|
{ DwarfAttrAddrClass, OFFSET(addrclass), TConstant },
|
||||||
|
{ DwarfAttrArtificial, OFFSET(isartificial), TFlag },
|
||||||
|
{ DwarfAttrBaseTypes, OFFSET(basetypes), TReference },
|
||||||
|
{ DwarfAttrBitOffset, OFFSET(bitoffset), TConstant },
|
||||||
|
{ DwarfAttrBitSize, OFFSET(bitsize), TConstant },
|
||||||
|
{ DwarfAttrByteSize, OFFSET(bytesize), TConstant },
|
||||||
|
{ DwarfAttrCalling, OFFSET(calling), TConstant },
|
||||||
|
{ DwarfAttrCommonRef, OFFSET(commonref), TReference },
|
||||||
|
{ DwarfAttrCompDir, OFFSET(compdir), TString },
|
||||||
|
{ DwarfAttrConstValue, OFFSET(constvalue), TString|TConstant|TBlock },
|
||||||
|
{ DwarfAttrContainingType, OFFSET(containingtype), TReference },
|
||||||
|
{ DwarfAttrCount, OFFSET(count), TConstant|TReference },
|
||||||
|
{ DwarfAttrDataMemberLoc, OFFSET(datamemberloc), TBlock|TConstant|TReference },
|
||||||
|
{ DwarfAttrDeclColumn, OFFSET(declcolumn), TConstant },
|
||||||
|
{ DwarfAttrDeclFile, OFFSET(declfile), TConstant },
|
||||||
|
{ DwarfAttrDeclLine, OFFSET(declline), TConstant },
|
||||||
|
{ DwarfAttrDeclaration, OFFSET(isdeclaration), TFlag },
|
||||||
|
{ DwarfAttrDefaultValue, OFFSET(defaultvalue), TReference },
|
||||||
|
{ DwarfAttrDiscr, OFFSET(discr), TReference },
|
||||||
|
{ DwarfAttrDiscrList, OFFSET(discrlist), TBlock },
|
||||||
|
{ DwarfAttrDiscrValue, OFFSET(discrvalue), TConstant },
|
||||||
|
{ DwarfAttrEncoding, OFFSET(encoding), TConstant },
|
||||||
|
{ DwarfAttrExternal, OFFSET(isexternal), TFlag },
|
||||||
|
{ DwarfAttrFrameBase, OFFSET(framebase), TBlock|TConstant },
|
||||||
|
{ DwarfAttrFriend, OFFSET(friend), TReference },
|
||||||
|
{ DwarfAttrHighpc, OFFSET(highpc), TAddress },
|
||||||
|
{ DwarfAttrEntrypc, OFFSET(entrypc), TAddress },
|
||||||
|
{ DwarfAttrIdentifierCase, OFFSET(identifiercase), TConstant },
|
||||||
|
{ DwarfAttrImport, OFFSET(import), TReference },
|
||||||
|
{ DwarfAttrInline, OFFSET(inlined), TConstant },
|
||||||
|
{ DwarfAttrIsOptional, OFFSET(isoptional), TFlag },
|
||||||
|
{ DwarfAttrLanguage, OFFSET(language), TConstant },
|
||||||
|
{ DwarfAttrLocation, OFFSET(location), TBlock|TConstant },
|
||||||
|
{ DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference },
|
||||||
|
{ DwarfAttrLowpc, OFFSET(lowpc), TAddress },
|
||||||
|
{ DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant },
|
||||||
|
{ DwarfAttrName, OFFSET(name), TString },
|
||||||
|
{ DwarfAttrNamelistItem, OFFSET(namelistitem), TBlock },
|
||||||
|
{ DwarfAttrOrdering, OFFSET(ordering), TConstant },
|
||||||
|
{ DwarfAttrPriority, OFFSET(priority), TReference },
|
||||||
|
{ DwarfAttrProducer, OFFSET(producer), TString },
|
||||||
|
{ DwarfAttrPrototyped, OFFSET(isprototyped), TFlag },
|
||||||
|
{ DwarfAttrRanges, OFFSET(ranges), TReference },
|
||||||
|
{ DwarfAttrReturnAddr, OFFSET(returnaddr), TBlock|TConstant },
|
||||||
|
{ DwarfAttrSegment, OFFSET(segment), TBlock|TConstant },
|
||||||
|
{ DwarfAttrSibling, OFFSET(sibling), TReference },
|
||||||
|
{ DwarfAttrSpecification, OFFSET(specification), TReference },
|
||||||
|
{ DwarfAttrStartScope, OFFSET(startscope), TConstant },
|
||||||
|
{ DwarfAttrStaticLink, OFFSET(staticlink), TBlock|TConstant },
|
||||||
|
{ DwarfAttrStmtList, OFFSET(stmtlist), TConstant },
|
||||||
|
{ DwarfAttrStrideSize, OFFSET(stridesize), TConstant },
|
||||||
|
{ DwarfAttrStringLength, OFFSET(stringlength), TBlock|TConstant },
|
||||||
|
{ DwarfAttrType, OFFSET(type), TReference },
|
||||||
|
{ DwarfAttrUpperBound, OFFSET(upperbound), TConstant|TReference },
|
||||||
|
{ DwarfAttrUseLocation, OFFSET(uselocation), TBlock|TConstant },
|
||||||
|
{ DwarfAttrVarParam, OFFSET(isvarparam), TFlag },
|
||||||
|
{ DwarfAttrVirtuality, OFFSET(virtuality), TConstant },
|
||||||
|
{ DwarfAttrVisibility, OFFSET(visibility), TConstant },
|
||||||
|
{ DwarfAttrVtableElemLoc, OFFSET(vtableelemloc), TBlock|TReference },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static Parse ptab[DwarfAttrMax];
|
||||||
|
|
||||||
|
static int
|
||||||
|
parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
|
||||||
|
{
|
||||||
|
int i, f, n, got;
|
||||||
|
static int nbad;
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
/* initialize ptab first time through for quick access */
|
||||||
|
if(ptab[DwarfAttrName].name != DwarfAttrName)
|
||||||
|
for(i=0; plist[i].name; i++)
|
||||||
|
ptab[plist[i].name] = plist[i];
|
||||||
|
|
||||||
|
memset(attrs, 0, sizeof *attrs);
|
||||||
|
attrs->tag = a->tag;
|
||||||
|
attrs->haskids = a->haskids;
|
||||||
|
|
||||||
|
for(i=0; i<a->nattr; i++){
|
||||||
|
n = a->attr[i].name;
|
||||||
|
f = a->attr[i].form;
|
||||||
|
if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0){
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n);
|
||||||
|
continue; //return -1;
|
||||||
|
}
|
||||||
|
v = (char*)attrs + ptab[n].off;
|
||||||
|
got = 0;
|
||||||
|
if(f == FormIndirect)
|
||||||
|
f = dwarfget128(b);
|
||||||
|
if((ptab[n].type&(TConstant|TReference|TAddress))
|
||||||
|
&& getulong(b, f, unit, v, &got) >= 0)
|
||||||
|
;
|
||||||
|
else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
|
||||||
|
got = TFlag;
|
||||||
|
else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
|
||||||
|
got = TString;
|
||||||
|
else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
|
||||||
|
got = TBlock;
|
||||||
|
else{
|
||||||
|
if(skipform(b, f) < 0){
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("dwarf parse attrs: cannot skip form %d", f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(got == TBlock && (ptab[n].type&TConstant))
|
||||||
|
got = constblock(b->d, v, v);
|
||||||
|
*((uchar*)attrs+ptab[n].haveoff) = got;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
|
||||||
|
{
|
||||||
|
static int nbad;
|
||||||
|
uvlong uv;
|
||||||
|
|
||||||
|
switch(form){
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* addresses */
|
||||||
|
case FormAddr:
|
||||||
|
*type = TAddress;
|
||||||
|
*u = dwarfgetaddr(b);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* references */
|
||||||
|
case FormRefAddr:
|
||||||
|
/* absolute ref in .debug_info */
|
||||||
|
*type = TReference;
|
||||||
|
*u = dwarfgetaddr(b);
|
||||||
|
return 0;
|
||||||
|
case FormRef1:
|
||||||
|
*u = dwarfget1(b);
|
||||||
|
goto relativeref;
|
||||||
|
case FormRef2:
|
||||||
|
*u = dwarfget2(b);
|
||||||
|
goto relativeref;
|
||||||
|
case FormRef4:
|
||||||
|
*u = dwarfget4(b);
|
||||||
|
goto relativeref;
|
||||||
|
case FormRef8:
|
||||||
|
*u = dwarfget8(b);
|
||||||
|
goto relativeref;
|
||||||
|
case FormRefUdata:
|
||||||
|
*u = dwarfget128(b);
|
||||||
|
relativeref:
|
||||||
|
*u += unit;
|
||||||
|
*type = TReference;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
case FormData1:
|
||||||
|
*u = dwarfget1(b);
|
||||||
|
goto constant;
|
||||||
|
case FormData2:
|
||||||
|
*u = dwarfget2(b);
|
||||||
|
goto constant;
|
||||||
|
case FormData4:
|
||||||
|
*u = dwarfget4(b);
|
||||||
|
goto constant;
|
||||||
|
case FormData8:
|
||||||
|
uv = dwarfget8(b);
|
||||||
|
*u = uv;
|
||||||
|
if(uv != *u && ++nbad == 1)
|
||||||
|
werrstr("dwarf: truncating 64-bit attribute constants");
|
||||||
|
goto constant;
|
||||||
|
case FormSdata:
|
||||||
|
*u = dwarfget128s(b);
|
||||||
|
goto constant;
|
||||||
|
case FormUdata:
|
||||||
|
*u = dwarfget128(b);
|
||||||
|
constant:
|
||||||
|
*type = TConstant;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getuchar(DwarfBuf *b, int form, uchar *u)
|
||||||
|
{
|
||||||
|
switch(form){
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case FormFlag:
|
||||||
|
*u = dwarfget1(b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getstring(DwarfBuf *b, int form, char **s)
|
||||||
|
{
|
||||||
|
static int nbad;
|
||||||
|
ulong u;
|
||||||
|
|
||||||
|
switch(form){
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case FormString:
|
||||||
|
*s = dwarfgetstring(b);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case FormStrp:
|
||||||
|
u = dwarfget4(b);
|
||||||
|
if(u >= b->d->str.len){
|
||||||
|
if(++nbad == 1)
|
||||||
|
werrstr("dwarf: bad string pointer 0x%lux in attribute", u);
|
||||||
|
/* don't return error - maybe can proceed */
|
||||||
|
*s = nil;
|
||||||
|
}else
|
||||||
|
*s = (char*)b->d->str.data + u;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getblock(DwarfBuf *b, int form, DwarfBlock *bl)
|
||||||
|
{
|
||||||
|
ulong n;
|
||||||
|
|
||||||
|
switch(form){
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
case FormDwarfBlock:
|
||||||
|
n = dwarfget128(b);
|
||||||
|
goto copyn;
|
||||||
|
case FormDwarfBlock1:
|
||||||
|
n = dwarfget1(b);
|
||||||
|
goto copyn;
|
||||||
|
case FormDwarfBlock2:
|
||||||
|
n = dwarfget2(b);
|
||||||
|
goto copyn;
|
||||||
|
case FormDwarfBlock4:
|
||||||
|
n = dwarfget4(b);
|
||||||
|
copyn:
|
||||||
|
bl->data = dwarfgetnref(b, n);
|
||||||
|
bl->len = n;
|
||||||
|
if(bl->data == nil)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
|
||||||
|
{
|
||||||
|
DwarfBuf b;
|
||||||
|
|
||||||
|
memset(&b, 0, sizeof b);
|
||||||
|
b.p = bl->data;
|
||||||
|
b.ep = bl->data+bl->len;
|
||||||
|
b.d = d;
|
||||||
|
|
||||||
|
switch(dwarfget1(&b)){
|
||||||
|
case OpAddr:
|
||||||
|
*pval = dwarfgetaddr(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst1u:
|
||||||
|
*pval = dwarfget1(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst1s:
|
||||||
|
*pval = (schar)dwarfget1(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst2u:
|
||||||
|
*pval = dwarfget2(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst2s:
|
||||||
|
*pval = (s16int)dwarfget2(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst4u:
|
||||||
|
*pval = dwarfget4(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst4s:
|
||||||
|
*pval = (s32int)dwarfget4(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst8u:
|
||||||
|
*pval = (u64int)dwarfget8(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConst8s:
|
||||||
|
*pval = (s64int)dwarfget8(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConstu:
|
||||||
|
*pval = dwarfget128(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpConsts:
|
||||||
|
*pval = dwarfget128s(&b);
|
||||||
|
return TConstant;
|
||||||
|
case OpPlusUconst:
|
||||||
|
*pval = dwarfget128(&b);
|
||||||
|
return TConstant;
|
||||||
|
default:
|
||||||
|
return TBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* last resort */
|
||||||
|
static int
|
||||||
|
skipform(DwarfBuf *b, int form)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
DwarfVal val;
|
||||||
|
|
||||||
|
if(getulong(b, form, 0, &val.c, &type) < 0
|
||||||
|
&& getuchar(b, form, (uchar*)&val) < 0
|
||||||
|
&& getstring(b, form, &val.s) < 0
|
||||||
|
&& getblock(b, form, &val.b) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
69
lib/rossym/dwarfopen.c
Normal file
69
lib/rossym/dwarfopen.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "pe.h"
|
||||||
|
|
||||||
|
/* Adapted for PE */
|
||||||
|
|
||||||
|
Dwarf*
|
||||||
|
dwarfopen(Pe *pe)
|
||||||
|
{
|
||||||
|
Dwarf *d;
|
||||||
|
|
||||||
|
if(pe == nil){
|
||||||
|
werrstr("nil pe passed to dwarfopen");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = mallocz(sizeof(Dwarf), 1);
|
||||||
|
if(d == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
d->pe = pe;
|
||||||
|
if(pe->loadsection(pe, ".debug_abbrev", &d->abbrev) < 0
|
||||||
|
|| pe->loadsection(pe, ".debug_aranges", &d->aranges) < 0
|
||||||
|
|| pe->loadsection(pe, ".debug_line", &d->line) < 0
|
||||||
|
|| pe->loadsection(pe, ".debug_pubnames", &d->pubnames) < 0
|
||||||
|
|| pe->loadsection(pe, ".debug_info", &d->info) < 0)
|
||||||
|
goto err;
|
||||||
|
pe->loadsection(pe, ".debug_frame", &d->frame);
|
||||||
|
pe->loadsection(pe, ".debug_ranges", &d->ranges);
|
||||||
|
pe->loadsection(pe, ".debug_str", &d->str);
|
||||||
|
|
||||||
|
return d;
|
||||||
|
|
||||||
|
err:
|
||||||
|
free(d->abbrev.data);
|
||||||
|
free(d->aranges.data);
|
||||||
|
free(d->frame.data);
|
||||||
|
free(d->line.data);
|
||||||
|
free(d->pubnames.data);
|
||||||
|
free(d->ranges.data);
|
||||||
|
free(d->str.data);
|
||||||
|
free(d->info.data);
|
||||||
|
free(d);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dwarfclose(Dwarf *d)
|
||||||
|
{
|
||||||
|
free(d->abbrev.data);
|
||||||
|
free(d->aranges.data);
|
||||||
|
free(d->frame.data);
|
||||||
|
free(d->line.data);
|
||||||
|
free(d->pubnames.data);
|
||||||
|
free(d->ranges.data);
|
||||||
|
free(d->str.data);
|
||||||
|
free(d->info.data);
|
||||||
|
pefree(d->pe);
|
||||||
|
free(d);
|
||||||
|
}
|
||||||
|
|
380
lib/rossym/dwarfpc.c
Normal file
380
lib/rossym/dwarfpc.c
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
/*
|
||||||
|
* Dwarf pc to source line conversion.
|
||||||
|
*
|
||||||
|
* Maybe should do the reverse here, but what should the interface look like?
|
||||||
|
* One possibility is to use the Plan 9 line2addr interface:
|
||||||
|
*
|
||||||
|
* long line2addr(ulong line, ulong basepc)
|
||||||
|
*
|
||||||
|
* which returns the smallest pc > basepc with line number line (ignoring file name).
|
||||||
|
*
|
||||||
|
* The encoding may be small, but it sure isn't simple!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "pe.h"
|
||||||
|
|
||||||
|
#define trace 0
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Isstmt = 1<<0,
|
||||||
|
BasicDwarfBlock = 1<<1,
|
||||||
|
EndSequence = 1<<2,
|
||||||
|
PrologueEnd = 1<<3,
|
||||||
|
EpilogueBegin = 1<<4
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct State State;
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
ulong addr;
|
||||||
|
ulong file;
|
||||||
|
ulong line;
|
||||||
|
ulong column;
|
||||||
|
ulong flags;
|
||||||
|
ulong isa;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **function, ulong *line, ulong *mtime, ulong *length)
|
||||||
|
{
|
||||||
|
uchar *prog, *opcount, *end, *dirs;
|
||||||
|
ulong off, unit, len, vers, x, start, lastline;
|
||||||
|
int i, first, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
|
||||||
|
char *files, *s;
|
||||||
|
DwarfBuf b;
|
||||||
|
DwarfSym sym;
|
||||||
|
State emit, cur, reset;
|
||||||
|
uchar **f, **newf;
|
||||||
|
|
||||||
|
f = nil;
|
||||||
|
|
||||||
|
if(dwarfaddrtounit(d, pc, &unit) < 0
|
||||||
|
|| dwarflookuptag(d, unit, TagCompileUnit, &sym) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(!sym.attrs.have.stmtlist){
|
||||||
|
werrstr("no line mapping information for 0x%x", pc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
off = sym.attrs.stmtlist;
|
||||||
|
if(off >= d->line.len){
|
||||||
|
werrstr("bad stmtlist\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trace) werrstr("unit 0x%x stmtlist 0x%x", unit, sym.attrs.stmtlist);
|
||||||
|
|
||||||
|
memset(&b, 0, sizeof b);
|
||||||
|
b.d = d;
|
||||||
|
b.p = d->line.data + off;
|
||||||
|
b.ep = b.p + d->line.len;
|
||||||
|
b.addrsize = sym.b.addrsize; /* should i get this from somewhere else? */
|
||||||
|
|
||||||
|
len = dwarfget4(&b);
|
||||||
|
if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
|
||||||
|
werrstr("bad len\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ep = b.p+len;
|
||||||
|
vers = dwarfget2(&b);
|
||||||
|
if(vers != 2){
|
||||||
|
werrstr("bad dwarf version 0x%x", vers);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = dwarfget4(&b);
|
||||||
|
if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
|
||||||
|
werrstr("another bad len\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
prog = b.p+len;
|
||||||
|
|
||||||
|
quantum = dwarfget1(&b);
|
||||||
|
isstmt = dwarfget1(&b);
|
||||||
|
linebase = (schar)dwarfget1(&b);
|
||||||
|
linerange = (schar)dwarfget1(&b);
|
||||||
|
opcodebase = dwarfget1(&b);
|
||||||
|
|
||||||
|
opcount = b.p-1;
|
||||||
|
dwarfgetnref(&b, opcodebase-1);
|
||||||
|
if(b.p == nil){
|
||||||
|
werrstr("bad opcode chart\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* just skip the files and dirs for now; we'll come back */
|
||||||
|
dirs = b.p;
|
||||||
|
while (b.p && *b.p)
|
||||||
|
dwarfgetstring(&b);
|
||||||
|
dwarfget1(&b);
|
||||||
|
|
||||||
|
files = (char*)b.p;
|
||||||
|
while(b.p!=nil && *b.p!=0){
|
||||||
|
dwarfgetstring(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
}
|
||||||
|
dwarfget1(&b);
|
||||||
|
|
||||||
|
/* move on to the program */
|
||||||
|
if(b.p == nil || b.p > prog){
|
||||||
|
werrstr("bad header\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
b.p = prog;
|
||||||
|
|
||||||
|
reset.addr = 0;
|
||||||
|
reset.file = 1;
|
||||||
|
reset.line = 1;
|
||||||
|
reset.column = 0;
|
||||||
|
reset.flags = isstmt ? Isstmt : 0;
|
||||||
|
reset.isa = 0;
|
||||||
|
|
||||||
|
cur = reset;
|
||||||
|
emit = reset;
|
||||||
|
nf = 0;
|
||||||
|
start = 0;
|
||||||
|
if(trace) werrstr("program @ %lu ... %.*H opbase = %d\n", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
|
||||||
|
first = 1;
|
||||||
|
while(b.p != nil){
|
||||||
|
op = dwarfget1(&b);
|
||||||
|
if(trace) werrstr("\tline %lu, addr 0x%x, op %d %.10H", cur.line, cur.addr, op, b.p);
|
||||||
|
if(op >= opcodebase){
|
||||||
|
a = (op - opcodebase) / linerange;
|
||||||
|
l = (op - opcodebase) % linerange + linebase;
|
||||||
|
cur.line += l;
|
||||||
|
cur.addr += a * quantum;
|
||||||
|
if(trace) werrstr(" +%d,%d\n", a, l);
|
||||||
|
emit:
|
||||||
|
if(first){
|
||||||
|
if(cur.addr > pc){
|
||||||
|
werrstr("found wrong line mapping 0x%x for pc 0x%x", cur.addr, pc);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
first = 0;
|
||||||
|
start = cur.addr;
|
||||||
|
}
|
||||||
|
if(cur.addr > pc)
|
||||||
|
break;
|
||||||
|
if(b.p == nil){
|
||||||
|
werrstr("buffer underflow in line mapping");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
emit = cur;
|
||||||
|
if(emit.flags & EndSequence){
|
||||||
|
werrstr("found wrong line mapping 0x%x-0x%x for pc 0x%x", start, cur.addr, pc);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
cur.flags &= ~(BasicDwarfBlock|PrologueEnd|EpilogueBegin);
|
||||||
|
}else{
|
||||||
|
switch(op){
|
||||||
|
case 0: /* extended op code */
|
||||||
|
if(trace) werrstr(" ext");
|
||||||
|
len = dwarfget128(&b);
|
||||||
|
end = b.p+len;
|
||||||
|
if(b.p == nil || end > b.ep || end < b.p || len < 1)
|
||||||
|
goto bad;
|
||||||
|
switch(dwarfget1(&b)){
|
||||||
|
case 1: /* end sequence */
|
||||||
|
if(trace) werrstr(" end\n");
|
||||||
|
cur.flags |= EndSequence;
|
||||||
|
goto emit;
|
||||||
|
case 2: /* set address */
|
||||||
|
cur.addr = dwarfgetaddr(&b);
|
||||||
|
if(trace) werrstr(" set pc 0x%x\n", cur.addr);
|
||||||
|
break;
|
||||||
|
case 3: /* define file */
|
||||||
|
newf = malloc(nf+1*sizeof(f[0]));
|
||||||
|
if (newf)
|
||||||
|
RtlMoveMemory(newf, f, nf*sizeof(f[0]));
|
||||||
|
if(newf == nil)
|
||||||
|
goto out;
|
||||||
|
f[nf++] = b.p;
|
||||||
|
s = dwarfgetstring(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
if(trace) werrstr(" def file %s\n", s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(b.p == nil || b.p > end)
|
||||||
|
goto bad;
|
||||||
|
b.p = end;
|
||||||
|
break;
|
||||||
|
case 1: /* emit */
|
||||||
|
if(trace) werrstr(" emit\n");
|
||||||
|
goto emit;
|
||||||
|
case 2: /* advance pc */
|
||||||
|
a = dwarfget128(&b);
|
||||||
|
if(trace) werrstr(" advance pc + %lu\n", a*quantum);
|
||||||
|
cur.addr += a * quantum;
|
||||||
|
break;
|
||||||
|
case 3: /* advance line */
|
||||||
|
l = dwarfget128s(&b);
|
||||||
|
if(trace) werrstr(" advance line + %ld\n", l);
|
||||||
|
cur.line += l;
|
||||||
|
break;
|
||||||
|
case 4: /* set file */
|
||||||
|
if(trace) werrstr(" set file\n");
|
||||||
|
cur.file = dwarfget128s(&b);
|
||||||
|
break;
|
||||||
|
case 5: /* set column */
|
||||||
|
if(trace) werrstr(" set column\n");
|
||||||
|
cur.column = dwarfget128(&b);
|
||||||
|
break;
|
||||||
|
case 6: /* negate stmt */
|
||||||
|
if(trace) werrstr(" negate stmt\n");
|
||||||
|
cur.flags ^= Isstmt;
|
||||||
|
break;
|
||||||
|
case 7: /* set basic block */
|
||||||
|
if(trace) werrstr(" set basic block\n");
|
||||||
|
cur.flags |= BasicDwarfBlock;
|
||||||
|
break;
|
||||||
|
case 8: /* const add pc */
|
||||||
|
a = (255 - opcodebase) / linerange * quantum;
|
||||||
|
if(trace) werrstr(" const add pc + %d\n", a);
|
||||||
|
cur.addr += a;
|
||||||
|
break;
|
||||||
|
case 9: /* fixed advance pc */
|
||||||
|
a = dwarfget2(&b);
|
||||||
|
if(trace) werrstr(" fixed advance pc + %d\n", a);
|
||||||
|
cur.addr += a;
|
||||||
|
break;
|
||||||
|
case 10: /* set prologue end */
|
||||||
|
if(trace) werrstr(" set prologue end\n");
|
||||||
|
cur.flags |= PrologueEnd;
|
||||||
|
break;
|
||||||
|
case 11: /* set epilogue begin */
|
||||||
|
if(trace) werrstr(" set epilogue begin\n");
|
||||||
|
cur.flags |= EpilogueBegin;
|
||||||
|
break;
|
||||||
|
case 12: /* set isa */
|
||||||
|
if(trace) werrstr(" set isa\n");
|
||||||
|
cur.isa = dwarfget128(&b);
|
||||||
|
break;
|
||||||
|
default: /* something new - skip it */
|
||||||
|
if(trace) werrstr(" unknown %d\n", opcount[op]);
|
||||||
|
for(i=0; i<opcount[op]; i++)
|
||||||
|
dwarfget128(&b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(b.p == nil)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
/* finally! the data we seek is in "emit" */
|
||||||
|
|
||||||
|
if(emit.file == 0){
|
||||||
|
werrstr("invalid file index in mapping data");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(line)
|
||||||
|
*line = emit.line;
|
||||||
|
|
||||||
|
/* skip over first emit.file-2 guys */
|
||||||
|
b.p = (uchar*)files;
|
||||||
|
for(i=emit.file-1; i > 0 && b.p!=nil && *b.p!=0; i--){
|
||||||
|
dwarfgetstring(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
dwarfget128(&b);
|
||||||
|
}
|
||||||
|
if(b.p == nil){
|
||||||
|
werrstr("problem parsing file data second time (cannot happen)");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if(*b.p == 0){
|
||||||
|
if(i >= nf){
|
||||||
|
werrstr("bad file index in mapping data");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
b.p = f[i];
|
||||||
|
}
|
||||||
|
s = dwarfgetstring(&b);
|
||||||
|
if(file)
|
||||||
|
*file = s;
|
||||||
|
i = dwarfget128(&b); /* directory */
|
||||||
|
x = dwarfget128(&b);
|
||||||
|
if(mtime)
|
||||||
|
*mtime = x;
|
||||||
|
x = dwarfget128(&b);
|
||||||
|
if(length)
|
||||||
|
*length = x;
|
||||||
|
|
||||||
|
/* fetch dir name */
|
||||||
|
if(cdir)
|
||||||
|
*cdir = sym.attrs.compdir;
|
||||||
|
|
||||||
|
if(dir){
|
||||||
|
*dir = nil;
|
||||||
|
b.p = dirs;
|
||||||
|
for (x = 1; b.p && *b.p; x++)
|
||||||
|
if (x == i) {
|
||||||
|
*dir = dwarfgetstring(&b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*function = nil;
|
||||||
|
lastline = 0;
|
||||||
|
#if 0
|
||||||
|
if (dwarfenumunit(d, unit, &proc) >= 0) {
|
||||||
|
dwarfnextsymat(d, &proc, 0);
|
||||||
|
while (dwarfnextsymat(d, &proc, 1) == 1) {
|
||||||
|
if (proc.attrs.tag == TagSubprogram &&
|
||||||
|
proc.attrs.have.name &&
|
||||||
|
proc.attrs.declfile == emit.file &&
|
||||||
|
proc.attrs.declline <= *line &&
|
||||||
|
proc.attrs.declline > lastline) {
|
||||||
|
lastline = proc.attrs.declline;
|
||||||
|
free(*function);
|
||||||
|
*function = malloc(strlen(proc.attrs.name)+1);
|
||||||
|
strcpy(*function, proc.attrs.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif 1
|
||||||
|
ulong lastaddr = 0;
|
||||||
|
*function = NULL;
|
||||||
|
for (i = 0; i < d->pe->nsymbols; i++) {
|
||||||
|
if (d->pe->symtab[i].address > lastaddr &&
|
||||||
|
d->pe->symtab[i].address <= pc - d->pe->imagebase &&
|
||||||
|
d->pe->symtab[i].address < d->pe->imagesize) {
|
||||||
|
lastaddr = d->pe->symtab[i].address;
|
||||||
|
*function = d->pe->symtab[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// *sigh* we get unrelocated low_pc and high_pc because the dwarf symbols
|
||||||
|
// are not 'loaded' in the PE sense.
|
||||||
|
if (dwarflookupfn(d, unit, pc, &proc) >= 0) {
|
||||||
|
*function = malloc(strlen(proc.attrs.name)+1);
|
||||||
|
strcpy(*function, proc.attrs.name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* free at last, free at last */
|
||||||
|
free(f);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
werrstr("corrupted line mapping for 0x%x", pc);
|
||||||
|
out:
|
||||||
|
free(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
81
lib/rossym/dwarfpubnames.c
Normal file
81
lib/rossym/dwarfpubnames.c
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
_dwarfnametounit(Dwarf *d, char *name, DwarfBlock *bl, DwarfSym *s)
|
||||||
|
{
|
||||||
|
int vers;
|
||||||
|
ulong len, unit, off;
|
||||||
|
uchar *next;
|
||||||
|
char *str;
|
||||||
|
DwarfBuf b;
|
||||||
|
|
||||||
|
b.d = d;
|
||||||
|
b.p = bl->data;
|
||||||
|
b.ep = b.p + bl->len;
|
||||||
|
|
||||||
|
while(b.p < b.ep){
|
||||||
|
len = dwarfget4(&b);
|
||||||
|
if(len > b.ep-b.p){
|
||||||
|
werrstr("bad length in dwarf name header");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
next = b.p + len;
|
||||||
|
vers = dwarfget2(&b);
|
||||||
|
if(vers != 1 && vers != 2){
|
||||||
|
werrstr("bad version %d in dwarf name header", vers);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unit = dwarfget4(&b);
|
||||||
|
dwarfget4(&b); /* unit length */
|
||||||
|
while(b.p < next){
|
||||||
|
off = dwarfget4(&b);
|
||||||
|
if(off == 0)
|
||||||
|
break;
|
||||||
|
str = dwarfgetstring(&b);
|
||||||
|
if(strcmp(str, name) == 0){
|
||||||
|
if(dwarfenumunit(d, unit, s) < 0)
|
||||||
|
return -1;
|
||||||
|
if(unit + off >= s->b.ep - d->info.data){
|
||||||
|
werrstr("bad offset in name entry");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->b.p = d->info.data + unit + off;
|
||||||
|
if(dwarfnextsym(d, s) < 0)
|
||||||
|
return -1;
|
||||||
|
if(s->attrs.name==nil || strcmp(s->attrs.name, name)!=0){
|
||||||
|
werrstr("unexpected name %#q in lookup for %#q", s->attrs.name, name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.p = next;
|
||||||
|
}
|
||||||
|
werrstr("unknown name '%s'", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarflookupname(Dwarf *d, char *name, DwarfSym *sym)
|
||||||
|
{
|
||||||
|
return _dwarfnametounit(d, name, &d->pubnames, sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
int
|
||||||
|
dwarflookuptype(Dwarf *d, char *name, DwarfSym *sym)
|
||||||
|
{
|
||||||
|
return _dwarfnametounit(d, name, &d->pubtypes, sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
|
@ -39,56 +39,12 @@
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
static PROSSYM_ENTRY
|
#include "rossym.h"
|
||||||
FindEntry(IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress)
|
#include "dwarf.h"
|
||||||
{
|
#include "pe.h"
|
||||||
/*
|
|
||||||
* Perform a binary search.
|
|
||||||
*
|
|
||||||
* The code below is a bit sneaky. After a comparison fails, we
|
|
||||||
* divide the work in half by moving either left or right. If lim
|
|
||||||
* is odd, moving left simply involves halving lim: e.g., when lim
|
|
||||||
* is 5 we look at item 2, so we change lim to 2 so that we will
|
|
||||||
* look at items 0 & 1. If lim is even, the same applies. If lim
|
|
||||||
* is odd, moving right again involes halving lim, this time moving
|
|
||||||
* the base up one item past p: e.g., when lim is 5 we change base
|
|
||||||
* to item 3 and make lim 2 so that we will look at items 3 and 4.
|
|
||||||
* If lim is even, however, we have to shrink it by one before
|
|
||||||
* halving: e.g., when lim is 4, we still looked at item 2, so we
|
|
||||||
* have to make lim 3, then halve, obtaining 1, so that we will only
|
|
||||||
* look at item 3.
|
|
||||||
*/
|
|
||||||
PROSSYM_ENTRY Base = RosSymInfo->Symbols;
|
|
||||||
ULONG Lim;
|
|
||||||
PROSSYM_ENTRY Mid, Low;
|
|
||||||
|
|
||||||
if (RelativeAddress < Base->Address)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Low = Base;
|
|
||||||
for (Lim = RosSymInfo->SymbolsCount; Lim != 0; Lim >>= 1)
|
|
||||||
{
|
|
||||||
Mid = Base + (Lim >> 1);
|
|
||||||
if (RelativeAddress == Mid->Address)
|
|
||||||
{
|
|
||||||
return Mid;
|
|
||||||
}
|
|
||||||
if (Mid->Address < RelativeAddress) /* key > mid: move right */
|
|
||||||
{
|
|
||||||
Low = Mid;
|
|
||||||
Base = Mid + 1;
|
|
||||||
Lim--;
|
|
||||||
} /* else move left */
|
|
||||||
}
|
|
||||||
|
|
||||||
return Low;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
||||||
|
@ -97,52 +53,34 @@ RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
||||||
char *FileName,
|
char *FileName,
|
||||||
char *FunctionName)
|
char *FunctionName)
|
||||||
{
|
{
|
||||||
PROSSYM_ENTRY RosSymEntry;
|
char *cdir, *dir, *file, *function;
|
||||||
|
ulong line, mtime, length;
|
||||||
DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress);
|
int res = dwarfpctoline
|
||||||
|
(RosSymInfo,
|
||||||
if (RosSymInfo->Symbols == NULL || RosSymInfo->SymbolsCount == 0 ||
|
RelativeAddress + RosSymInfo->pe->imagebase,
|
||||||
RosSymInfo->Strings == NULL || RosSymInfo->StringsLength == 0)
|
&cdir,
|
||||||
{
|
&dir,
|
||||||
DPRINT1("Uninitialized RosSymInfo\n");
|
&file,
|
||||||
return FALSE;
|
&function,
|
||||||
}
|
&line,
|
||||||
|
&mtime,
|
||||||
ASSERT(LineNumber || FileName || FunctionName);
|
&length);
|
||||||
|
if (res != -1) {
|
||||||
/* find symbol entry for function */
|
*LineNumber = line;
|
||||||
RosSymEntry = FindEntry(RosSymInfo, RelativeAddress);
|
FileName[0] = 0;
|
||||||
|
if (dir) {
|
||||||
if (NULL == RosSymEntry)
|
strcpy(FileName, dir);
|
||||||
{
|
strcat(FileName, "/");
|
||||||
DPRINT("None of the requested information was found!\n");
|
}
|
||||||
return FALSE;
|
if (file)
|
||||||
}
|
strcat(FileName, file);
|
||||||
|
FunctionName[0] = 0;
|
||||||
if (LineNumber != NULL)
|
if (function)
|
||||||
{
|
strcpy(FunctionName, function);
|
||||||
*LineNumber = RosSymEntry->SourceLine;
|
return TRUE;
|
||||||
}
|
} else {
|
||||||
if (FileName != NULL)
|
return FALSE;
|
||||||
{
|
}
|
||||||
PCSTR Name = "";
|
|
||||||
if (RosSymEntry->FileOffset != 0)
|
|
||||||
{
|
|
||||||
Name = (PCHAR) RosSymInfo->Strings + RosSymEntry->FileOffset;
|
|
||||||
}
|
|
||||||
strcpy(FileName, Name);
|
|
||||||
}
|
|
||||||
if (FunctionName != NULL)
|
|
||||||
{
|
|
||||||
PCSTR Name = "";
|
|
||||||
if (RosSymEntry->FunctionOffset != 0)
|
|
||||||
{
|
|
||||||
Name = (PCHAR) RosSymInfo->Strings + RosSymEntry->FunctionOffset;
|
|
||||||
}
|
|
||||||
strcpy(FunctionName, Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -8,12 +8,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NTOSAPI
|
#define NTOSAPI
|
||||||
#include <ntddk.h>
|
#include <ntifs.h>
|
||||||
|
#include <ndk/ntndk.h>
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
#include "pe.h"
|
||||||
#include <ntimage.h>
|
#include <ntimage.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#include "dwarf.h"
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -21,12 +25,12 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
||||||
{
|
{
|
||||||
IMAGE_DOS_HEADER DosHeader;
|
IMAGE_DOS_HEADER DosHeader;
|
||||||
IMAGE_NT_HEADERS NtHeaders;
|
IMAGE_NT_HEADERS NtHeaders;
|
||||||
PIMAGE_SECTION_HEADER SectionHeaders, SectionHeader;
|
PIMAGE_SECTION_HEADER SectionHeaders;
|
||||||
unsigned SectionIndex;
|
unsigned SectionIndex;
|
||||||
char SectionName[IMAGE_SIZEOF_SHORT_NAME];
|
unsigned SymbolTable, NumSymbols;
|
||||||
ROSSYM_HEADER RosSymHeader;
|
|
||||||
|
|
||||||
/* Load DOS header */
|
/* Load DOS header */
|
||||||
|
DPRINT("About to read file\n");
|
||||||
if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
|
if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to read DOS header\n");
|
DPRINT1("Failed to read DOS header\n");
|
||||||
|
@ -55,6 +59,10 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolTable = NtHeaders.FileHeader.PointerToSymbolTable;
|
||||||
|
NumSymbols = NtHeaders.FileHeader.NumberOfSymbols;
|
||||||
|
DPRINT("SymbolTable %x NumSymbols %x\n", SymbolTable, NumSymbols);
|
||||||
|
|
||||||
/* Load section headers */
|
/* Load section headers */
|
||||||
if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
|
if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
|
||||||
(char *) &NtHeaders + DosHeader.e_lfanew))
|
(char *) &NtHeaders + DosHeader.e_lfanew))
|
||||||
|
@ -79,69 +87,108 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search for the section header */
|
// Convert names to ANSI_STRINGs
|
||||||
strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME);
|
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
|
||||||
SectionHeader = SectionHeaders;
|
SectionIndex++)
|
||||||
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections; SectionIndex++)
|
{
|
||||||
{
|
ANSI_STRING astr;
|
||||||
if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME))
|
if (SectionHeaders[SectionIndex].Name[0] != '/') {
|
||||||
{
|
DPRINT("Short name string %d, %s\n", SectionIndex, SectionHeaders[SectionIndex].Name);
|
||||||
break;
|
astr.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
|
||||||
}
|
memcpy(astr.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
|
||||||
SectionHeader++;
|
astr.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
|
||||||
}
|
astr.Length = GetStrnlen(astr.Buffer, IMAGE_SIZEOF_SHORT_NAME);
|
||||||
if (NtHeaders.FileHeader.NumberOfSections <= SectionIndex)
|
} else {
|
||||||
{
|
UNICODE_STRING intConv;
|
||||||
RosSymFreeMem(SectionHeaders);
|
NTSTATUS Status;
|
||||||
DPRINT("No %s section found\n", ROSSYM_SECTION_NAME);
|
ULONG StringOffset;
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load rossym header */
|
Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
|
||||||
if (! RosSymSeekFile(FileContext, SectionHeader->PointerToRawData))
|
if (!NT_SUCCESS(Status)) goto freeall;
|
||||||
{
|
Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
|
||||||
RosSymFreeMem(SectionHeaders);
|
RtlFreeUnicodeString(&intConv);
|
||||||
DPRINT1("Failed seeking to section data\n");
|
if (!NT_SUCCESS(Status)) goto freeall;
|
||||||
return FALSE;
|
if (!RosSymSeekFile(FileContext, SymbolTable + NumSymbols * SYMBOL_SIZE + StringOffset))
|
||||||
}
|
goto freeall;
|
||||||
RosSymFreeMem(SectionHeaders);
|
astr.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
|
||||||
if (! RosSymReadFile(FileContext, &RosSymHeader, sizeof(ROSSYM_HEADER)))
|
if (!RosSymReadFile(FileContext, astr.Buffer, MAXIMUM_DWARF_NAME_SIZE))
|
||||||
{
|
goto freeall;
|
||||||
DPRINT1("Failed to read rossym header\n");
|
astr.Length = GetStrnlen(astr.Buffer, MAXIMUM_DWARF_NAME_SIZE);
|
||||||
return FALSE;
|
astr.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
|
||||||
}
|
DPRINT("Long name %d, %s\n", SectionIndex, astr.Buffer);
|
||||||
if (RosSymHeader.SymbolsOffset < sizeof(ROSSYM_HEADER)
|
}
|
||||||
|| RosSymHeader.StringsOffset < RosSymHeader.SymbolsOffset + RosSymHeader.SymbolsLength
|
*ANSI_NAME_STRING(&SectionHeaders[SectionIndex]) = astr;
|
||||||
|| 0 != (RosSymHeader.SymbolsLength % sizeof(ROSSYM_ENTRY)))
|
}
|
||||||
{
|
|
||||||
DPRINT1("Invalid ROSSYM_HEADER\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*RosSymInfo = RosSymAllocMem(sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER)
|
DPRINT("Done with sections\n");
|
||||||
+ RosSymHeader.StringsOffset + RosSymHeader.StringsLength + 1);
|
Pe *pe = RosSymAllocMem(sizeof(*pe));
|
||||||
if (NULL == *RosSymInfo)
|
pe->fd = FileContext;
|
||||||
{
|
pe->e2 = peget2;
|
||||||
DPRINT1("Failed to allocate memory for rossym\n");
|
pe->e4 = peget4;
|
||||||
return FALSE;
|
pe->e8 = peget8;
|
||||||
}
|
pe->nsections = NtHeaders.FileHeader.NumberOfSections;
|
||||||
(*RosSymInfo)->Symbols = (PROSSYM_ENTRY)((char *) *RosSymInfo + sizeof(ROSSYM_INFO)
|
pe->sect = SectionHeaders;
|
||||||
- sizeof(ROSSYM_HEADER) + RosSymHeader.SymbolsOffset);
|
pe->nsymbols = NtHeaders.FileHeader.NumberOfSymbols;
|
||||||
(*RosSymInfo)->SymbolsCount = RosSymHeader.SymbolsLength / sizeof(ROSSYM_ENTRY);
|
pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
|
||||||
(*RosSymInfo)->Strings = (PCHAR) *RosSymInfo + sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER)
|
SYMENT SymbolData;
|
||||||
+ RosSymHeader.StringsOffset;
|
int i, j;
|
||||||
(*RosSymInfo)->StringsLength = RosSymHeader.StringsLength;
|
DPRINT("Getting symbol data\n");
|
||||||
if (! RosSymReadFile(FileContext, *RosSymInfo + 1,
|
ASSERT(sizeof(SymbolData) == 18);
|
||||||
RosSymHeader.StringsOffset + RosSymHeader.StringsLength
|
for (i = 0, j = 0; i < pe->nsymbols; i++) {
|
||||||
- sizeof(ROSSYM_HEADER)))
|
if (!RosSymSeekFile
|
||||||
{
|
(FileContext,
|
||||||
DPRINT1("Failed to read rossym headers\n");
|
NtHeaders.FileHeader.PointerToSymbolTable + i * sizeof(SymbolData)))
|
||||||
return FALSE;
|
goto freeall;
|
||||||
}
|
if (!RosSymReadFile(FileContext, &SymbolData, sizeof(SymbolData)))
|
||||||
/* Make sure the last string is null terminated, we allocated an extra byte for that */
|
goto freeall;
|
||||||
(*RosSymInfo)->Strings[(*RosSymInfo)->StringsLength] = '\0';
|
if ((SymbolData.e_scnum < 1) ||
|
||||||
|
(SymbolData.e_sclass != C_EXT &&
|
||||||
|
SymbolData.e_sclass != C_STAT))
|
||||||
|
continue;
|
||||||
|
int section = SymbolData.e_scnum - 1;
|
||||||
|
if (SymbolData.e.e.e_zeroes) {
|
||||||
|
pe->symtab[j].name = malloc(sizeof(SymbolData.e.e_name)+1);
|
||||||
|
memcpy(pe->symtab[j].name, SymbolData.e.e_name, sizeof(SymbolData.e.e_name));
|
||||||
|
pe->symtab[j].name[sizeof(SymbolData.e.e_name)] = 0;
|
||||||
|
} else {
|
||||||
|
if (!RosSymSeekFile
|
||||||
|
(FileContext,
|
||||||
|
NtHeaders.FileHeader.PointerToSymbolTable +
|
||||||
|
(NtHeaders.FileHeader.NumberOfSymbols * 18) +
|
||||||
|
SymbolData.e.e.e_offset))
|
||||||
|
goto freeall;
|
||||||
|
pe->symtab[j].name = malloc(MAXIMUM_COFF_SYMBOL_LENGTH+1);
|
||||||
|
pe->symtab[j].name[MAXIMUM_COFF_SYMBOL_LENGTH] = 0;
|
||||||
|
// It's possible that we've got a string just at the end of the file
|
||||||
|
// we'll skip that symbol if needed
|
||||||
|
if (!RosSymReadFile(FileContext, pe->symtab[j].name, MAXIMUM_COFF_SYMBOL_LENGTH)) {
|
||||||
|
free(pe->symtab[j].name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pe->symtab[j].name[0] == '.') {
|
||||||
|
free(pe->symtab[j].name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData.e_value;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
DPRINT("%d symbols\n", j);
|
||||||
|
pe->nsymbols = j;
|
||||||
|
pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
|
||||||
|
pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
|
||||||
|
pe->loadsection = loaddisksection;
|
||||||
|
*RosSymInfo = dwarfopen(pe);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
freeall:
|
||||||
|
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
|
||||||
|
SectionIndex++)
|
||||||
|
RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
|
||||||
|
RosSymFreeMem(SectionHeaders);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -8,84 +8,153 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NTOSAPI
|
#define NTOSAPI
|
||||||
#include <ntddk.h>
|
#include <ntifs.h>
|
||||||
|
#include <ndk/ntndk.h>
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
#include <ntimage.h>
|
#include <ntimage.h>
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "pe.h"
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo)
|
RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo)
|
||||||
{
|
{
|
||||||
PIMAGE_DOS_HEADER DosHeader;
|
ANSI_STRING AnsiNameString = { };
|
||||||
PIMAGE_NT_HEADERS NtHeaders;
|
PIMAGE_DOS_HEADER DosHeader;
|
||||||
PIMAGE_SECTION_HEADER SectionHeader;
|
PIMAGE_NT_HEADERS NtHeaders;
|
||||||
ULONG SectionIndex;
|
PIMAGE_SECTION_HEADER SectionHeaders;
|
||||||
BOOLEAN RosSymSectionFound = FALSE;
|
ULONG SectionIndex;
|
||||||
CHAR SectionName[IMAGE_SIZEOF_SHORT_NAME];
|
unsigned SymbolTable, NumSymbols;
|
||||||
|
|
||||||
/* Check if MZ header is valid */
|
/* Check if MZ header is valid */
|
||||||
DosHeader = (PIMAGE_DOS_HEADER) ImageStart;
|
DosHeader = (PIMAGE_DOS_HEADER) ImageStart;
|
||||||
if (ImageSize < sizeof(IMAGE_DOS_HEADER)
|
if (ImageSize < sizeof(IMAGE_DOS_HEADER)
|
||||||
|| ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader))
|
|| ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader))
|
||||||
{
|
{
|
||||||
DPRINT1("Image doesn't have a valid DOS header\n");
|
DPRINT1("Image doesn't have a valid DOS header\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate NT header */
|
/* Locate NT header */
|
||||||
NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew);
|
NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew);
|
||||||
if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
|
if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
|
||||||
|| ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders))
|
|| ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders))
|
||||||
{
|
{
|
||||||
DPRINT1("Image doesn't have a valid PE header\n");
|
DPRINT1("Image doesn't have a valid PE header\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search for the section header */
|
SymbolTable = NtHeaders->FileHeader.PointerToSymbolTable;
|
||||||
SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
|
NumSymbols = NtHeaders->FileHeader.NumberOfSymbols;
|
||||||
if (ImageSize < (ULONG_PTR)((char *) (SectionHeader + NtHeaders->FileHeader.NumberOfSections)
|
|
||||||
- (char *) ImageStart))
|
|
||||||
{
|
|
||||||
DPRINT1("Image doesn't have valid section headers\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME);
|
|
||||||
for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections; SectionIndex++)
|
|
||||||
{
|
|
||||||
if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME))
|
|
||||||
{
|
|
||||||
RosSymSectionFound = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SectionHeader++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RosSymSectionFound)
|
/* Search for the section header */
|
||||||
{
|
ULONG SectionHeaderSize = NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||||
DPRINT("No %s section found\n", ROSSYM_SECTION_NAME);
|
SectionHeaders = RosSymAllocMem(SectionHeaderSize);
|
||||||
return FALSE;
|
RtlCopyMemory(SectionHeaders, IMAGE_FIRST_SECTION(NtHeaders), SectionHeaderSize);
|
||||||
}
|
|
||||||
|
|
||||||
/* Locate the section itself */
|
// Convert names to ANSI_STRINGs
|
||||||
if (ImageSize < SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData
|
for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
|
||||||
|| SectionHeader->SizeOfRawData < sizeof(ROSSYM_HEADER))
|
SectionIndex++)
|
||||||
{
|
{
|
||||||
DPRINT("Invalid %s section\n", ROSSYM_SECTION_NAME);
|
if (SectionHeaders[SectionIndex].Name[0] != '/') {
|
||||||
return FALSE;
|
AnsiNameString.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
|
||||||
}
|
RtlCopyMemory(AnsiNameString.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
|
||||||
|
AnsiNameString.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
|
||||||
|
AnsiNameString.Length = GetStrnlen(AnsiNameString.Buffer, IMAGE_SIZEOF_SHORT_NAME);
|
||||||
|
} else {
|
||||||
|
UNICODE_STRING intConv;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG StringOffset;
|
||||||
|
|
||||||
if (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize > ImageSize)
|
Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
|
||||||
{
|
if (!NT_SUCCESS(Status)) goto freeall;
|
||||||
DPRINT("Bad %s section virtual size!\n", ROSSYM_SECTION_NAME);
|
Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
|
||||||
return FALSE;
|
RtlFreeUnicodeString(&intConv);
|
||||||
}
|
if (!NT_SUCCESS(Status)) goto freeall;
|
||||||
|
ULONG VirtualOffset = pefindrva(SectionHeaders, NtHeaders->FileHeader.NumberOfSections, SymbolTable+(NumSymbols*SYMBOL_SIZE)+StringOffset);
|
||||||
|
if (!VirtualOffset) goto freeall;
|
||||||
|
AnsiNameString.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
|
||||||
|
if (!AnsiNameString.Buffer) goto freeall;
|
||||||
|
PCHAR StringTarget = ((PCHAR)ImageStart)+VirtualOffset;
|
||||||
|
PCHAR EndOfImage = ((PCHAR)ImageStart) + NtHeaders->OptionalHeader.SizeOfImage;
|
||||||
|
if (StringTarget >= EndOfImage) goto freeall;
|
||||||
|
ULONG PossibleStringLength = EndOfImage - StringTarget;
|
||||||
|
if (PossibleStringLength > MAXIMUM_DWARF_NAME_SIZE)
|
||||||
|
PossibleStringLength = MAXIMUM_DWARF_NAME_SIZE;
|
||||||
|
RtlCopyMemory(AnsiNameString.Buffer, StringTarget, PossibleStringLength);
|
||||||
|
AnsiNameString.Length = strlen(AnsiNameString.Buffer);
|
||||||
|
AnsiNameString.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
|
||||||
|
}
|
||||||
|
memcpy
|
||||||
|
(&SectionHeaders[SectionIndex],
|
||||||
|
&AnsiNameString,
|
||||||
|
sizeof(AnsiNameString));
|
||||||
|
}
|
||||||
|
|
||||||
/* Load it */
|
Pe *pe = RosSymAllocMem(sizeof(*pe));
|
||||||
return RosSymCreateFromRaw((char *) ImageStart + SectionHeader->VirtualAddress,
|
pe->fd = ImageStart;
|
||||||
SectionHeader->SizeOfRawData, RosSymInfo);
|
pe->e2 = peget2;
|
||||||
|
pe->e4 = peget4;
|
||||||
|
pe->e8 = peget8;
|
||||||
|
pe->loadbase = (ULONG)ImageStart;
|
||||||
|
pe->imagebase = NtHeaders->OptionalHeader.ImageBase;
|
||||||
|
pe->imagesize = NtHeaders->OptionalHeader.SizeOfImage;
|
||||||
|
pe->nsections = NtHeaders->FileHeader.NumberOfSections;
|
||||||
|
pe->sect = SectionHeaders;
|
||||||
|
pe->nsymbols = NtHeaders->FileHeader.NumberOfSymbols;
|
||||||
|
pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
|
||||||
|
PSYMENT SymbolData = (PSYMENT)
|
||||||
|
(((PCHAR)ImageStart) +
|
||||||
|
pefindrva
|
||||||
|
(pe->sect,
|
||||||
|
pe->nsections,
|
||||||
|
NtHeaders->FileHeader.PointerToSymbolTable));
|
||||||
|
int i, j;
|
||||||
|
for (i = 0, j = 0; i < pe->nsymbols; i++) {
|
||||||
|
if ((SymbolData[i].e_scnum < 1) ||
|
||||||
|
(SymbolData[i].e_sclass != C_EXT &&
|
||||||
|
SymbolData[i].e_sclass != C_STAT))
|
||||||
|
continue;
|
||||||
|
int section = SymbolData[i].e_scnum - 1;
|
||||||
|
if (SymbolData[i].e.e.e_zeroes) {
|
||||||
|
pe->symtab[j].name = malloc(sizeof(SymbolData[i].e.e_name)+1);
|
||||||
|
strcpy(pe->symtab[j].name, SymbolData[i].e.e_name);
|
||||||
|
} else {
|
||||||
|
PCHAR SymbolName = ((PCHAR)ImageStart) +
|
||||||
|
pefindrva
|
||||||
|
(pe->sect,
|
||||||
|
pe->nsections,
|
||||||
|
NtHeaders->FileHeader.PointerToSymbolTable +
|
||||||
|
(NtHeaders->FileHeader.NumberOfSymbols * 18) +
|
||||||
|
SymbolData[i].e.e.e_offset);
|
||||||
|
pe->symtab[j].name = malloc(strlen(SymbolName)+1);
|
||||||
|
strcpy(pe->symtab[j].name, SymbolName);
|
||||||
|
}
|
||||||
|
if (pe->symtab[j].name[0] == '.') {
|
||||||
|
free(pe->symtab[j].name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData[i].e_value;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
pe->nsymbols = j;
|
||||||
|
pe->loadsection = loadmemsection;
|
||||||
|
*RosSymInfo = dwarfopen(pe);
|
||||||
|
|
||||||
|
return !!*RosSymInfo;
|
||||||
|
|
||||||
|
freeall:
|
||||||
|
if (AnsiNameString.Buffer) RosSymFreeMem(AnsiNameString.Buffer);
|
||||||
|
for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
|
||||||
|
SectionIndex++)
|
||||||
|
RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
|
||||||
|
RosSymFreeMem(SectionHeaders);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#define TAG_ROSSYM 'MYSR'
|
#define TAG_ROSSYM 'MYSR'
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
static PVOID
|
static PVOID
|
||||||
|
|
138
lib/rossym/pe.c
Normal file
138
lib/rossym/pe.c
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
#define NTOSAPI
|
||||||
|
#include <ntifs.h>
|
||||||
|
#include <ndk/ntndk.h>
|
||||||
|
#include <reactos/rossym.h>
|
||||||
|
#include "rossympriv.h"
|
||||||
|
#include <ntimage.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "pe.h"
|
||||||
|
#include "rossympriv.h"
|
||||||
|
|
||||||
|
PeSect *pesection(Pe *pe, const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
ANSI_STRING WantName;
|
||||||
|
RtlInitAnsiString(&WantName, name);
|
||||||
|
DPRINT("Searching for section %s\n", name);
|
||||||
|
for (i = 0; i < pe->nsections; i++) {
|
||||||
|
PANSI_STRING AnsiString = ANSI_NAME_STRING(&pe->sect[i]);
|
||||||
|
if (WantName.Length == AnsiString->Length &&
|
||||||
|
!memcmp(AnsiString->Buffer, name, WantName.Length)) {
|
||||||
|
DPRINT("Found %s (%d) @ %x (%x)\n", name, i,
|
||||||
|
((PCHAR)pe->imagebase)+pe->sect[i].VirtualAddress,
|
||||||
|
pe->sect[i].SizeOfRawData);
|
||||||
|
return &pe->sect[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DPRINT("%s not found\n", name);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16int peget2(const unsigned char *ptr) {
|
||||||
|
return *((u16int*)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32int peget4(const unsigned char *ptr) {
|
||||||
|
return *((u32int*)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64int peget8(const unsigned char *ptr) {
|
||||||
|
return *((u64int*)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readn(void *filectx, char *buffer, ulong size) {
|
||||||
|
return RosSymReadFile(filectx, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int seek(void *filectx, ulong position, int origin) {
|
||||||
|
assert(origin == 0);
|
||||||
|
return RosSymSeekFile(filectx, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
readblock(void *fd, DwarfBlock *b, ulong off, ulong len)
|
||||||
|
{
|
||||||
|
b->data = malloc(len);
|
||||||
|
if(b->data == nil)
|
||||||
|
return -1;
|
||||||
|
if(!seek(fd, off, 0) || !readn(fd, (char *)b->data, len)){
|
||||||
|
free(b->data);
|
||||||
|
b->data = nil;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
b->len = len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loaddisksection(Pe *pe, char *name, DwarfBlock *b)
|
||||||
|
{
|
||||||
|
PeSect *s;
|
||||||
|
if((s = pesection(pe, name)) == nil)
|
||||||
|
return -1;
|
||||||
|
return readblock(pe->fd, b, s->PointerToRawData, s->SizeOfRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loadmemsection(Pe *pe, char *name, DwarfBlock *b)
|
||||||
|
{
|
||||||
|
PeSect *s;
|
||||||
|
|
||||||
|
if((s = pesection(pe, name)) == nil)
|
||||||
|
return -1;
|
||||||
|
DPRINT("Loading section %s (ImageBase %x RVA %x)\n", name, pe->fd, s->VirtualAddress);
|
||||||
|
b->data = RosSymAllocMem(s->SizeOfRawData);
|
||||||
|
b->len = s->SizeOfRawData;
|
||||||
|
PCHAR DataSource = ((char *)pe->fd) + s->VirtualAddress;
|
||||||
|
DPRINT("Copying to %x from %x (%x)\n", DataSource, b->data, b->len);
|
||||||
|
RtlCopyMemory(b->data, DataSource, s->SizeOfRawData);
|
||||||
|
|
||||||
|
return s->SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *RosSymAllocMemZero(ulong size, ulong count) {
|
||||||
|
void *res = RosSymAllocMem(size * count);
|
||||||
|
if (res) memset(res, 0, size * count);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetStrnlen(const char *string, int maxlen) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < maxlen && string[i]; i++);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pefree(Pe *pe) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < pe->nsections; i++) {
|
||||||
|
RtlFreeAnsiString(ANSI_NAME_STRING(&pe->sect[i]));
|
||||||
|
}
|
||||||
|
free(pe->sect);
|
||||||
|
free(pe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xfree(void *v) {
|
||||||
|
if (v) RosSymFreeMem(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong pefindrva(struct _IMAGE_SECTION_HEADER *SectionHeaders, int NumberOfSections, ulong TargetPhysical) {
|
||||||
|
int i;
|
||||||
|
DPRINT("Finding RVA for Physical %x\n", TargetPhysical);
|
||||||
|
for (i = 0; i < NumberOfSections; i++) {
|
||||||
|
DPRINT("Section %d name %s Raw %x Virt %x\n",
|
||||||
|
i,
|
||||||
|
ANSI_NAME_STRING(&SectionHeaders[i])->Buffer,
|
||||||
|
SectionHeaders[i].PointerToRawData,
|
||||||
|
SectionHeaders[i].VirtualAddress);
|
||||||
|
if (TargetPhysical >= SectionHeaders[i].PointerToRawData &&
|
||||||
|
TargetPhysical < SectionHeaders[i].PointerToRawData + SectionHeaders[i].SizeOfRawData) {
|
||||||
|
DPRINT("RVA %x\n", TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress);
|
||||||
|
return TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
61
lib/rossym/pe.h
Normal file
61
lib/rossym/pe.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#ifndef _LIBMACH_PE_H_
|
||||||
|
#define _LIBMACH_PE_H_
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
struct DwarfBlock;
|
||||||
|
typedef struct _IMAGE_SECTION_HEADER PeSect;
|
||||||
|
|
||||||
|
typedef struct _CoffSymbol {
|
||||||
|
ulong address;
|
||||||
|
char *name;
|
||||||
|
} CoffSymbol;
|
||||||
|
|
||||||
|
typedef struct _Pe {
|
||||||
|
void *fd;
|
||||||
|
u16int (*e2)(const unsigned char *data);
|
||||||
|
u32int (*e4)(const unsigned char *data);
|
||||||
|
u64int (*e8)(const unsigned char *data);
|
||||||
|
ulong imagebase, imagesize, loadbase;
|
||||||
|
ulong nsymbols;
|
||||||
|
CoffSymbol *symtab;
|
||||||
|
int (*loadsection)(struct _Pe *pe, char *name, struct DwarfBlock *b);
|
||||||
|
int nsections;
|
||||||
|
struct _IMAGE_SECTION_HEADER *sect;
|
||||||
|
} Pe;
|
||||||
|
|
||||||
|
#define E_SYMNMLEN 8
|
||||||
|
#include <pshpack1.h>
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
char e_name[E_SYMNMLEN];
|
||||||
|
struct {
|
||||||
|
unsigned long e_zeroes;
|
||||||
|
unsigned long e_offset;
|
||||||
|
} e;
|
||||||
|
} e;
|
||||||
|
unsigned long e_value;
|
||||||
|
short e_scnum;
|
||||||
|
unsigned short e_type;
|
||||||
|
unsigned char e_sclass;
|
||||||
|
unsigned char e_numaux;
|
||||||
|
} SYMENT, *PSYMENT;
|
||||||
|
#include <poppack.h>
|
||||||
|
|
||||||
|
#define C_EXT 2
|
||||||
|
#define C_STAT 3
|
||||||
|
#define DT_FCN 0x40
|
||||||
|
|
||||||
|
Pe *peopen(const char *name);
|
||||||
|
int loaddisksection(struct _Pe *pe, char *name, struct DwarfBlock *b);
|
||||||
|
int loadmemsection(struct _Pe *pe, char *name, struct DwarfBlock *b);
|
||||||
|
u16int peget2(const unsigned char *ptr);
|
||||||
|
u32int peget4(const unsigned char *ptr);
|
||||||
|
u64int peget8(const unsigned char *ptr);
|
||||||
|
void pefree(struct _Pe *pe);
|
||||||
|
ulong pefindrva(struct _IMAGE_SECTION_HEADER *SectionHeader, int NumberOfSections, ulong TargetPhysical);
|
||||||
|
int GetStrnlen(const char *string, int maxlen);
|
||||||
|
|
||||||
|
#define ANSI_NAME_STRING(s) ((PANSI_STRING)((s)->Name))
|
||||||
|
|
||||||
|
#endif/*_LIBMACH_PE_H_*/
|
|
@ -9,13 +9,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef struct _ROSSYM_INFO {
|
|
||||||
PROSSYM_ENTRY Symbols;
|
|
||||||
ULONG SymbolsCount;
|
|
||||||
PCHAR Strings;
|
|
||||||
ULONG StringsLength;
|
|
||||||
} ROSSYM_INFO;
|
|
||||||
|
|
||||||
extern ROSSYM_CALLBACKS RosSymCallbacks;
|
extern ROSSYM_CALLBACKS RosSymCallbacks;
|
||||||
|
|
||||||
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)
|
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <reactos/rossym.h>
|
#include <reactos/rossym.h>
|
||||||
#include "rossympriv.h"
|
#include "rossympriv.h"
|
||||||
|
|
||||||
#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
|
|
@ -401,23 +401,11 @@ KdbSymProcessSymbols(
|
||||||
if (LdrEntry->PatchInformation)
|
if (LdrEntry->PatchInformation)
|
||||||
KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
|
KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
|
||||||
|
|
||||||
/* Load new symbol information */
|
/* Error loading symbol info, try to load it from file */
|
||||||
if (! RosSymCreateFromMem(LdrEntry->DllBase,
|
KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
|
||||||
LdrEntry->SizeOfImage,
|
|
||||||
(PROSSYM_INFO*)&LdrEntry->PatchInformation))
|
|
||||||
{
|
|
||||||
/* Error loading symbol info, try to load it from file */
|
|
||||||
KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
|
|
||||||
(PROSSYM_INFO*)&LdrEntry->PatchInformation);
|
(PROSSYM_INFO*)&LdrEntry->PatchInformation);
|
||||||
|
|
||||||
/* It already added symbols to cache */
|
/* It already added symbols to cache */
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Add file to cache */
|
|
||||||
KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Installed symbols: %wZ@%p-%p %p\n",
|
DPRINT("Installed symbols: %wZ@%p-%p %p\n",
|
||||||
&LdrEntry->BaseDllName,
|
&LdrEntry->BaseDllName,
|
||||||
LdrEntry->DllBase,
|
LdrEntry->DllBase,
|
||||||
|
@ -522,7 +510,7 @@ KdbInitialize(
|
||||||
|
|
||||||
RosSymInitKernelMode();
|
RosSymInitKernelMode();
|
||||||
}
|
}
|
||||||
else if (BootPhase == 1)
|
else if (BootPhase == 3)
|
||||||
{
|
{
|
||||||
/* Load symbols for NTOSKRNL.EXE.
|
/* Load symbols for NTOSKRNL.EXE.
|
||||||
It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */
|
It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */
|
||||||
|
|
|
@ -44,13 +44,6 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.edata)
|
*(.edata)
|
||||||
}
|
}
|
||||||
/DISCARD/ :
|
|
||||||
{
|
|
||||||
*(.debug$S)
|
|
||||||
*(.debug$T)
|
|
||||||
*(.debug$F)
|
|
||||||
*(.drectve)
|
|
||||||
}
|
|
||||||
|
|
||||||
.idata BLOCK(__section_alignment__) :
|
.idata BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
|
@ -87,13 +80,41 @@ SECTIONS
|
||||||
/* These zeroes mark the end of the reloc section. */
|
/* These zeroes mark the end of the reloc section. */
|
||||||
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
||||||
}
|
}
|
||||||
.stab BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_aranges BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
[ .stab ]
|
*(.debug_aranges)
|
||||||
}
|
}
|
||||||
.stabstr BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_abbrev BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
[ .stabstr ]
|
*(.debug_abbrev)
|
||||||
|
}
|
||||||
|
.debug_frame BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_frame)
|
||||||
|
}
|
||||||
|
.debug_info BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_info)
|
||||||
|
}
|
||||||
|
.debug_line BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_line)
|
||||||
|
}
|
||||||
|
.debug_loc BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_loc)
|
||||||
|
}
|
||||||
|
.debug_pubnames BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_pubnames)
|
||||||
|
}
|
||||||
|
.debug_ranges BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_ranges)
|
||||||
|
}
|
||||||
|
.debug_str BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.debug_str)
|
||||||
}
|
}
|
||||||
INIT BLOCK(__section_alignment__) :
|
INIT BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue