mirror of
https://github.com/reactos/reactos.git
synced 2024-08-04 02:20:54 +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
|
@ -274,31 +274,31 @@ VOID LoadReactOSSetup2(VOID)
|
|||
UseRealHeap = TRUE;
|
||||
LoaderBlock->ConfigurationRoot = MachHwDetect();
|
||||
|
||||
strcpy(FileName, "\\ArcName\\");
|
||||
|
||||
/* Load kernel */
|
||||
strcpy(FileName, BootPath);
|
||||
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||
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);
|
||||
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
||||
FileName, NtosBase, &KernelDTE);
|
||||
|
||||
/* Load HAL */
|
||||
strcpy(FileName, BootPath);
|
||||
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||
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);
|
||||
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
||||
FileName, HalBase, &HalDTE);
|
||||
|
||||
/* Load kernel-debugger support dll */
|
||||
strcpy(FileName, BootPath);
|
||||
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||
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);
|
||||
|
||||
/* 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",
|
||||
"KDCOM.DLL", KdComBase, &KdComDTE);
|
||||
FileName, KdComBase, &KdComDTE);
|
||||
|
||||
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
||||
strcpy(SearchPath, BootPath);
|
||||
|
|
|
@ -39,11 +39,6 @@ extern BOOLEAN UseRealHeap;
|
|||
extern ULONG LoaderPagesSpanned;
|
||||
extern BOOLEAN AcpiPresent;
|
||||
|
||||
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
|
||||
extern BOOLEAN WinLdrTerminalConnected;
|
||||
|
||||
extern void WinLdrSetupEms(IN PCHAR BootOptions);
|
||||
|
||||
BOOLEAN
|
||||
WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
|
||||
IN PCH DllName,
|
||||
|
@ -211,6 +206,8 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|||
|
||||
#ifndef _M_ARM
|
||||
/* Set headless block pointer */
|
||||
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
|
||||
extern BOOLEAN WinLdrTerminalConnected;
|
||||
if (WinLdrTerminalConnected)
|
||||
{
|
||||
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
|
||||
_snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
|
||||
Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
|
||||
strcpy(FullPath, "\\ArcName\\");
|
||||
_snprintf(FullPath+strlen("\\ArcName\\"), sizeof(FullPath), "%s%wZ", BootPath, FilePath);
|
||||
Status = WinLdrLoadImage(FullPath+strlen("\\ArcName\\"), LoaderBootDriver, &DriverBase);
|
||||
if (!Status)
|
||||
return FALSE;
|
||||
|
||||
// Allocate a DTE for it
|
||||
Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE);
|
||||
Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, FullPath, DriverBase, DriverDTE);
|
||||
if (!Status)
|
||||
{
|
||||
DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n");
|
||||
|
@ -540,6 +538,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
|||
|
||||
#ifndef _M_ARM
|
||||
/* Setup redirection support */
|
||||
extern void WinLdrSetupEms(IN PCHAR BootOptions);
|
||||
WinLdrSetupEms(BootOptions);
|
||||
#endif
|
||||
/* Detect hardware */
|
||||
|
@ -553,36 +552,33 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
|||
if (OperatingSystemVersion == 0)
|
||||
OperatingSystemVersion = WinLdrDetectVersion();
|
||||
|
||||
strcpy(FileName, "\\ArcName\\");
|
||||
|
||||
/* Load kernel */
|
||||
strcpy(FileName, BootPath);
|
||||
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||
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);
|
||||
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
||||
FileName, NtosBase, &KernelDTE);
|
||||
|
||||
/* Load HAL */
|
||||
strcpy(FileName, BootPath);
|
||||
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||
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);
|
||||
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
||||
FileName, HalBase, &HalDTE);
|
||||
|
||||
/* Load kernel-debugger support dll */
|
||||
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
|
||||
{
|
||||
strcpy(FileName, BootPath);
|
||||
strcpy(FileName+strlen("\\ArcName\\"), BootPath);
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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",
|
||||
"WINDOWS\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);
|
||||
FileName, KdComBase, &KdComDTE);
|
||||
}
|
||||
|
||||
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
||||
|
|
|
@ -10,15 +10,6 @@
|
|||
#ifndef 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 {
|
||||
ULONG_PTR Address;
|
||||
ULONG FunctionOffset;
|
||||
|
@ -33,19 +24,16 @@ typedef struct _ROSSYM_CALLBACKS {
|
|||
BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position);
|
||||
} ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS;
|
||||
|
||||
typedef struct _ROSSYM_INFO *PROSSYM_INFO;
|
||||
struct Dwarf;
|
||||
typedef struct Dwarf *PROSSYM_INFO;
|
||||
|
||||
VOID RosSymInit(PROSSYM_CALLBACKS Callbacks);
|
||||
VOID RosSymInitKernelMode(VOID);
|
||||
VOID RosSymInitUserMode(VOID);
|
||||
|
||||
BOOLEAN RosSymCreateFromRaw(PVOID RawData, ULONG_PTR DataSize,
|
||||
PROSSYM_INFO *RosSymInfo);
|
||||
BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize,
|
||||
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,
|
||||
ULONG_PTR RelativeAddress,
|
||||
ULONG *LineNumber,
|
||||
|
|
|
@ -2,14 +2,21 @@
|
|||
add_definitions(-D_NTSYSTEM_)
|
||||
list(APPEND SOURCE
|
||||
delete.c
|
||||
dwarf386.c
|
||||
dwarfabbrev.c
|
||||
dwarfaranges.c
|
||||
dwarfcfa.c
|
||||
dwarfinfo.c
|
||||
dwarfget.c
|
||||
dwarfopen.c
|
||||
dwarfpc.c
|
||||
dwarfpubnames.c
|
||||
find.c
|
||||
fromfile.c
|
||||
frommem.c
|
||||
fromraw.c
|
||||
getraw.c
|
||||
init.c
|
||||
initkm.c
|
||||
initum.c
|
||||
pe.c
|
||||
zwfile.c)
|
||||
add_library(rossym ${SOURCE})
|
||||
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
|
||||
#include <ntddk.h>
|
||||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
#include <ntimage.h>
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "rossympriv.h"
|
||||
#include "pe.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
VOID
|
||||
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 */
|
||||
|
|
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 "rossympriv.h"
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
static PROSSYM_ENTRY
|
||||
FindEntry(IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
#include "rossym.h"
|
||||
#include "dwarf.h"
|
||||
#include "pe.h"
|
||||
|
||||
BOOLEAN
|
||||
RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
||||
|
@ -97,52 +53,34 @@ RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
|||
char *FileName,
|
||||
char *FunctionName)
|
||||
{
|
||||
PROSSYM_ENTRY RosSymEntry;
|
||||
|
||||
DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress);
|
||||
|
||||
if (RosSymInfo->Symbols == NULL || RosSymInfo->SymbolsCount == 0 ||
|
||||
RosSymInfo->Strings == NULL || RosSymInfo->StringsLength == 0)
|
||||
{
|
||||
DPRINT1("Uninitialized RosSymInfo\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ASSERT(LineNumber || FileName || FunctionName);
|
||||
|
||||
/* find symbol entry for function */
|
||||
RosSymEntry = FindEntry(RosSymInfo, RelativeAddress);
|
||||
|
||||
if (NULL == RosSymEntry)
|
||||
{
|
||||
DPRINT("None of the requested information was found!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (LineNumber != NULL)
|
||||
{
|
||||
*LineNumber = RosSymEntry->SourceLine;
|
||||
}
|
||||
if (FileName != NULL)
|
||||
{
|
||||
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;
|
||||
char *cdir, *dir, *file, *function;
|
||||
ulong line, mtime, length;
|
||||
int res = dwarfpctoline
|
||||
(RosSymInfo,
|
||||
RelativeAddress + RosSymInfo->pe->imagebase,
|
||||
&cdir,
|
||||
&dir,
|
||||
&file,
|
||||
&function,
|
||||
&line,
|
||||
&mtime,
|
||||
&length);
|
||||
if (res != -1) {
|
||||
*LineNumber = line;
|
||||
FileName[0] = 0;
|
||||
if (dir) {
|
||||
strcpy(FileName, dir);
|
||||
strcat(FileName, "/");
|
||||
}
|
||||
if (file)
|
||||
strcat(FileName, file);
|
||||
FunctionName[0] = 0;
|
||||
if (function)
|
||||
strcpy(FunctionName, function);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -8,12 +8,16 @@
|
|||
*/
|
||||
|
||||
#define NTOSAPI
|
||||
#include <ntddk.h>
|
||||
#include <ntifs.h>
|
||||
#include <ndk/ntndk.h>
|
||||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
#include "pe.h"
|
||||
#include <ntimage.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include "dwarf.h"
|
||||
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
BOOLEAN
|
||||
|
@ -21,12 +25,12 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
{
|
||||
IMAGE_DOS_HEADER DosHeader;
|
||||
IMAGE_NT_HEADERS NtHeaders;
|
||||
PIMAGE_SECTION_HEADER SectionHeaders, SectionHeader;
|
||||
PIMAGE_SECTION_HEADER SectionHeaders;
|
||||
unsigned SectionIndex;
|
||||
char SectionName[IMAGE_SIZEOF_SHORT_NAME];
|
||||
ROSSYM_HEADER RosSymHeader;
|
||||
unsigned SymbolTable, NumSymbols;
|
||||
|
||||
/* Load DOS header */
|
||||
DPRINT("About to read file\n");
|
||||
if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
|
||||
{
|
||||
DPRINT1("Failed to read DOS header\n");
|
||||
|
@ -55,6 +59,10 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
SymbolTable = NtHeaders.FileHeader.PointerToSymbolTable;
|
||||
NumSymbols = NtHeaders.FileHeader.NumberOfSymbols;
|
||||
DPRINT("SymbolTable %x NumSymbols %x\n", SymbolTable, NumSymbols);
|
||||
|
||||
/* Load section headers */
|
||||
if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
|
||||
(char *) &NtHeaders + DosHeader.e_lfanew))
|
||||
|
@ -79,69 +87,108 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Search for the section header */
|
||||
strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionHeader = SectionHeaders;
|
||||
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections; SectionIndex++)
|
||||
{
|
||||
if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME))
|
||||
{
|
||||
break;
|
||||
}
|
||||
SectionHeader++;
|
||||
}
|
||||
if (NtHeaders.FileHeader.NumberOfSections <= SectionIndex)
|
||||
{
|
||||
RosSymFreeMem(SectionHeaders);
|
||||
DPRINT("No %s section found\n", ROSSYM_SECTION_NAME);
|
||||
return FALSE;
|
||||
}
|
||||
// Convert names to ANSI_STRINGs
|
||||
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
|
||||
SectionIndex++)
|
||||
{
|
||||
ANSI_STRING astr;
|
||||
if (SectionHeaders[SectionIndex].Name[0] != '/') {
|
||||
DPRINT("Short name string %d, %s\n", SectionIndex, SectionHeaders[SectionIndex].Name);
|
||||
astr.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
|
||||
memcpy(astr.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
|
||||
astr.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
|
||||
astr.Length = GetStrnlen(astr.Buffer, IMAGE_SIZEOF_SHORT_NAME);
|
||||
} else {
|
||||
UNICODE_STRING intConv;
|
||||
NTSTATUS Status;
|
||||
ULONG StringOffset;
|
||||
|
||||
/* Load rossym header */
|
||||
if (! RosSymSeekFile(FileContext, SectionHeader->PointerToRawData))
|
||||
{
|
||||
RosSymFreeMem(SectionHeaders);
|
||||
DPRINT1("Failed seeking to section data\n");
|
||||
return FALSE;
|
||||
}
|
||||
RosSymFreeMem(SectionHeaders);
|
||||
if (! RosSymReadFile(FileContext, &RosSymHeader, sizeof(ROSSYM_HEADER)))
|
||||
{
|
||||
DPRINT1("Failed to read rossym header\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (RosSymHeader.SymbolsOffset < sizeof(ROSSYM_HEADER)
|
||||
|| RosSymHeader.StringsOffset < RosSymHeader.SymbolsOffset + RosSymHeader.SymbolsLength
|
||||
|| 0 != (RosSymHeader.SymbolsLength % sizeof(ROSSYM_ENTRY)))
|
||||
{
|
||||
DPRINT1("Invalid ROSSYM_HEADER\n");
|
||||
return FALSE;
|
||||
}
|
||||
Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
|
||||
if (!NT_SUCCESS(Status)) goto freeall;
|
||||
Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
|
||||
RtlFreeUnicodeString(&intConv);
|
||||
if (!NT_SUCCESS(Status)) goto freeall;
|
||||
if (!RosSymSeekFile(FileContext, SymbolTable + NumSymbols * SYMBOL_SIZE + StringOffset))
|
||||
goto freeall;
|
||||
astr.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
|
||||
if (!RosSymReadFile(FileContext, astr.Buffer, MAXIMUM_DWARF_NAME_SIZE))
|
||||
goto freeall;
|
||||
astr.Length = GetStrnlen(astr.Buffer, MAXIMUM_DWARF_NAME_SIZE);
|
||||
astr.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
|
||||
DPRINT("Long name %d, %s\n", SectionIndex, astr.Buffer);
|
||||
}
|
||||
*ANSI_NAME_STRING(&SectionHeaders[SectionIndex]) = astr;
|
||||
}
|
||||
|
||||
*RosSymInfo = RosSymAllocMem(sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER)
|
||||
+ RosSymHeader.StringsOffset + RosSymHeader.StringsLength + 1);
|
||||
if (NULL == *RosSymInfo)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory for rossym\n");
|
||||
return FALSE;
|
||||
}
|
||||
(*RosSymInfo)->Symbols = (PROSSYM_ENTRY)((char *) *RosSymInfo + sizeof(ROSSYM_INFO)
|
||||
- sizeof(ROSSYM_HEADER) + RosSymHeader.SymbolsOffset);
|
||||
(*RosSymInfo)->SymbolsCount = RosSymHeader.SymbolsLength / sizeof(ROSSYM_ENTRY);
|
||||
(*RosSymInfo)->Strings = (PCHAR) *RosSymInfo + sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER)
|
||||
+ RosSymHeader.StringsOffset;
|
||||
(*RosSymInfo)->StringsLength = RosSymHeader.StringsLength;
|
||||
if (! RosSymReadFile(FileContext, *RosSymInfo + 1,
|
||||
RosSymHeader.StringsOffset + RosSymHeader.StringsLength
|
||||
- sizeof(ROSSYM_HEADER)))
|
||||
{
|
||||
DPRINT1("Failed to read rossym headers\n");
|
||||
return FALSE;
|
||||
}
|
||||
/* Make sure the last string is null terminated, we allocated an extra byte for that */
|
||||
(*RosSymInfo)->Strings[(*RosSymInfo)->StringsLength] = '\0';
|
||||
DPRINT("Done with sections\n");
|
||||
Pe *pe = RosSymAllocMem(sizeof(*pe));
|
||||
pe->fd = FileContext;
|
||||
pe->e2 = peget2;
|
||||
pe->e4 = peget4;
|
||||
pe->e8 = peget8;
|
||||
pe->nsections = NtHeaders.FileHeader.NumberOfSections;
|
||||
pe->sect = SectionHeaders;
|
||||
pe->nsymbols = NtHeaders.FileHeader.NumberOfSymbols;
|
||||
pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
|
||||
SYMENT SymbolData;
|
||||
int i, j;
|
||||
DPRINT("Getting symbol data\n");
|
||||
ASSERT(sizeof(SymbolData) == 18);
|
||||
for (i = 0, j = 0; i < pe->nsymbols; i++) {
|
||||
if (!RosSymSeekFile
|
||||
(FileContext,
|
||||
NtHeaders.FileHeader.PointerToSymbolTable + i * sizeof(SymbolData)))
|
||||
goto freeall;
|
||||
if (!RosSymReadFile(FileContext, &SymbolData, sizeof(SymbolData)))
|
||||
goto freeall;
|
||||
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;
|
||||
|
||||
freeall:
|
||||
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
|
||||
SectionIndex++)
|
||||
RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
|
||||
RosSymFreeMem(SectionHeaders);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -8,84 +8,153 @@
|
|||
*/
|
||||
|
||||
#define NTOSAPI
|
||||
#include <ntddk.h>
|
||||
#include <ntifs.h>
|
||||
#include <ndk/ntndk.h>
|
||||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
#include <ntimage.h>
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "dwarf.h"
|
||||
#include "pe.h"
|
||||
|
||||
BOOLEAN
|
||||
RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo)
|
||||
{
|
||||
PIMAGE_DOS_HEADER DosHeader;
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
PIMAGE_SECTION_HEADER SectionHeader;
|
||||
ULONG SectionIndex;
|
||||
BOOLEAN RosSymSectionFound = FALSE;
|
||||
CHAR SectionName[IMAGE_SIZEOF_SHORT_NAME];
|
||||
|
||||
/* Check if MZ header is valid */
|
||||
DosHeader = (PIMAGE_DOS_HEADER) ImageStart;
|
||||
if (ImageSize < sizeof(IMAGE_DOS_HEADER)
|
||||
|| ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader))
|
||||
ANSI_STRING AnsiNameString = { };
|
||||
PIMAGE_DOS_HEADER DosHeader;
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
PIMAGE_SECTION_HEADER SectionHeaders;
|
||||
ULONG SectionIndex;
|
||||
unsigned SymbolTable, NumSymbols;
|
||||
|
||||
/* Check if MZ header is valid */
|
||||
DosHeader = (PIMAGE_DOS_HEADER) ImageStart;
|
||||
if (ImageSize < sizeof(IMAGE_DOS_HEADER)
|
||||
|| ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader))
|
||||
{
|
||||
DPRINT1("Image doesn't have a valid DOS header\n");
|
||||
return FALSE;
|
||||
DPRINT1("Image doesn't have a valid DOS header\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Locate NT header */
|
||||
NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew);
|
||||
if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
|
||||
|| ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders))
|
||||
|
||||
/* Locate NT header */
|
||||
NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew);
|
||||
if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
|
||||
|| ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders))
|
||||
{
|
||||
DPRINT1("Image doesn't have a valid PE header\n");
|
||||
return FALSE;
|
||||
DPRINT1("Image doesn't have a valid PE header\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SymbolTable = NtHeaders->FileHeader.PointerToSymbolTable;
|
||||
NumSymbols = NtHeaders->FileHeader.NumberOfSymbols;
|
||||
|
||||
/* Search for the section header */
|
||||
ULONG SectionHeaderSize = NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||
SectionHeaders = RosSymAllocMem(SectionHeaderSize);
|
||||
RtlCopyMemory(SectionHeaders, IMAGE_FIRST_SECTION(NtHeaders), SectionHeaderSize);
|
||||
|
||||
// Convert names to ANSI_STRINGs
|
||||
for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
|
||||
SectionIndex++)
|
||||
{
|
||||
if (SectionHeaders[SectionIndex].Name[0] != '/') {
|
||||
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;
|
||||
|
||||
Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
|
||||
if (!NT_SUCCESS(Status)) goto freeall;
|
||||
Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
|
||||
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));
|
||||
}
|
||||
|
||||
Pe *pe = RosSymAllocMem(sizeof(*pe));
|
||||
pe->fd = ImageStart;
|
||||
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);
|
||||
|
||||
/* Search for the section header */
|
||||
SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
|
||||
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)
|
||||
{
|
||||
DPRINT("No %s section found\n", ROSSYM_SECTION_NAME);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Locate the section itself */
|
||||
if (ImageSize < SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData
|
||||
|| SectionHeader->SizeOfRawData < sizeof(ROSSYM_HEADER))
|
||||
{
|
||||
DPRINT("Invalid %s section\n", ROSSYM_SECTION_NAME);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize > ImageSize)
|
||||
{
|
||||
DPRINT("Bad %s section virtual size!\n", ROSSYM_SECTION_NAME);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Load it */
|
||||
return RosSymCreateFromRaw((char *) ImageStart + SectionHeader->VirtualAddress,
|
||||
SectionHeader->SizeOfRawData, RosSymInfo);
|
||||
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 */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
BOOLEAN
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
ULONG
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define TAG_ROSSYM 'MYSR'
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
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
|
||||
|
||||
typedef struct _ROSSYM_INFO {
|
||||
PROSSYM_ENTRY Symbols;
|
||||
ULONG SymbolsCount;
|
||||
PCHAR Strings;
|
||||
ULONG StringsLength;
|
||||
} ROSSYM_INFO;
|
||||
|
||||
extern ROSSYM_CALLBACKS RosSymCallbacks;
|
||||
|
||||
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <reactos/rossym.h>
|
||||
#include "rossympriv.h"
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
BOOLEAN
|
||||
|
|
|
@ -401,23 +401,11 @@ KdbSymProcessSymbols(
|
|||
if (LdrEntry->PatchInformation)
|
||||
KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
|
||||
|
||||
/* Load new symbol information */
|
||||
if (! RosSymCreateFromMem(LdrEntry->DllBase,
|
||||
LdrEntry->SizeOfImage,
|
||||
(PROSSYM_INFO*)&LdrEntry->PatchInformation))
|
||||
{
|
||||
/* Error loading symbol info, try to load it from file */
|
||||
KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
|
||||
/* Error loading symbol info, try to load it from file */
|
||||
KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
|
||||
(PROSSYM_INFO*)&LdrEntry->PatchInformation);
|
||||
|
||||
/* It already added symbols to cache */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add file to cache */
|
||||
KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation);
|
||||
}
|
||||
|
||||
/* It already added symbols to cache */
|
||||
DPRINT("Installed symbols: %wZ@%p-%p %p\n",
|
||||
&LdrEntry->BaseDllName,
|
||||
LdrEntry->DllBase,
|
||||
|
@ -522,7 +510,7 @@ KdbInitialize(
|
|||
|
||||
RosSymInitKernelMode();
|
||||
}
|
||||
else if (BootPhase == 1)
|
||||
else if (BootPhase == 3)
|
||||
{
|
||||
/* 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. */
|
||||
|
|
|
@ -44,13 +44,6 @@ SECTIONS
|
|||
{
|
||||
*(.edata)
|
||||
}
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.debug$S)
|
||||
*(.debug$T)
|
||||
*(.debug$F)
|
||||
*(.drectve)
|
||||
}
|
||||
|
||||
.idata BLOCK(__section_alignment__) :
|
||||
{
|
||||
|
@ -87,13 +80,41 @@ SECTIONS
|
|||
/* These zeroes mark the end of the reloc section. */
|
||||
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__) :
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue