- 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:
Amine Khaldi 2010-12-02 23:20:22 +00:00
parent 3ddfc0b355
commit b7f44d1892
31 changed files with 3349 additions and 318 deletions

View file

@ -274,31 +274,31 @@ VOID LoadReactOSSetup2(VOID)
UseRealHeap = TRUE; UseRealHeap = TRUE;
LoaderBlock->ConfigurationRoot = MachHwDetect(); LoaderBlock->ConfigurationRoot = MachHwDetect();
strcpy(FileName, "\\ArcName\\");
/* Load kernel */ /* Load kernel */
strcpy(FileName, BootPath); strcpy(FileName+strlen("\\ArcName\\"), BootPath);
strcat(FileName, "NTOSKRNL.EXE"); strcat(FileName, "NTOSKRNL.EXE");
Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase); Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderSystemCode, &NtosBase);
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase); DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
FileName, NtosBase, &KernelDTE);
/* Load HAL */ /* Load HAL */
strcpy(FileName, BootPath); strcpy(FileName+strlen("\\ArcName\\"), BootPath);
strcat(FileName, "HAL.DLL"); strcat(FileName, "HAL.DLL");
Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase); Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderHalCode, &HalBase);
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase); DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
FileName, HalBase, &HalDTE);
/* Load kernel-debugger support dll */ /* Load kernel-debugger support dll */
strcpy(FileName, BootPath); strcpy(FileName+strlen("\\ArcName\\"), BootPath);
strcat(FileName, "KDCOM.DLL"); strcat(FileName, "KDCOM.DLL");
Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase); Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderBootDriver, &KdComBase);
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase); DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
/* Allocate data table entries for above-loaded modules */
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
"NTOSKRNL.EXE", NtosBase, &KernelDTE);
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
"HAL.DLL", HalBase, &HalDTE);
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll", WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
"KDCOM.DLL", KdComBase, &KdComDTE); FileName, KdComBase, &KdComDTE);
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */ /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
strcpy(SearchPath, BootPath); strcpy(SearchPath, BootPath);

View file

@ -39,11 +39,6 @@ extern BOOLEAN UseRealHeap;
extern ULONG LoaderPagesSpanned; extern ULONG LoaderPagesSpanned;
extern BOOLEAN AcpiPresent; extern BOOLEAN AcpiPresent;
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
extern BOOLEAN WinLdrTerminalConnected;
extern void WinLdrSetupEms(IN PCHAR BootOptions);
BOOLEAN BOOLEAN
WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
IN PCH DllName, IN PCH DllName,
@ -211,6 +206,8 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
#ifndef _M_ARM #ifndef _M_ARM
/* Set headless block pointer */ /* Set headless block pointer */
extern HEADLESS_LOADER_BLOCK LoaderRedirectionInformation;
extern BOOLEAN WinLdrTerminalConnected;
if (WinLdrTerminalConnected) if (WinLdrTerminalConnected)
{ {
Extension->HeadlessLoaderBlock = MmHeapAlloc(sizeof(HEADLESS_LOADER_BLOCK)); Extension->HeadlessLoaderBlock = MmHeapAlloc(sizeof(HEADLESS_LOADER_BLOCK));
@ -285,13 +282,14 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
} }
// It's not loaded, we have to load it // It's not loaded, we have to load it
_snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath); strcpy(FullPath, "\\ArcName\\");
Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase); _snprintf(FullPath+strlen("\\ArcName\\"), sizeof(FullPath), "%s%wZ", BootPath, FilePath);
Status = WinLdrLoadImage(FullPath+strlen("\\ArcName\\"), LoaderBootDriver, &DriverBase);
if (!Status) if (!Status)
return FALSE; return FALSE;
// Allocate a DTE for it // Allocate a DTE for it
Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE); Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, FullPath, DriverBase, DriverDTE);
if (!Status) if (!Status)
{ {
DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n"); DPRINTM(DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n");
@ -540,6 +538,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
#ifndef _M_ARM #ifndef _M_ARM
/* Setup redirection support */ /* Setup redirection support */
extern void WinLdrSetupEms(IN PCHAR BootOptions);
WinLdrSetupEms(BootOptions); WinLdrSetupEms(BootOptions);
#endif #endif
/* Detect hardware */ /* Detect hardware */
@ -553,36 +552,33 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
if (OperatingSystemVersion == 0) if (OperatingSystemVersion == 0)
OperatingSystemVersion = WinLdrDetectVersion(); OperatingSystemVersion = WinLdrDetectVersion();
strcpy(FileName, "\\ArcName\\");
/* Load kernel */ /* Load kernel */
strcpy(FileName, BootPath); strcpy(FileName+strlen("\\ArcName\\"), BootPath);
strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE"); strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase); Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderSystemCode, &NtosBase);
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase); DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
FileName, NtosBase, &KernelDTE);
/* Load HAL */ /* Load HAL */
strcpy(FileName, BootPath); strcpy(FileName+strlen("\\ArcName\\"), BootPath);
strcat(FileName, "SYSTEM32\\HAL.DLL"); strcat(FileName, "SYSTEM32\\HAL.DLL");
Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase); Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderHalCode, &HalBase);
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase); DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
FileName, HalBase, &HalDTE);
/* Load kernel-debugger support dll */ /* Load kernel-debugger support dll */
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K) if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
{ {
strcpy(FileName, BootPath); strcpy(FileName+strlen("\\ArcName\\"), BootPath);
strcat(FileName, "SYSTEM32\\KDCOM.DLL"); strcat(FileName, "SYSTEM32\\KDCOM.DLL");
Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase); Status = WinLdrLoadImage(FileName+strlen("\\ArcName\\"), LoaderBootDriver, &KdComBase);
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase); DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
}
/* Allocate data table entries for above-loaded modules */
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
"WINDOWS\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
"WINDOWS\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE);
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
{
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll", WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
"WINDOWS\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE); FileName, KdComBase, &KdComDTE);
} }
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */ /* Load all referenced DLLs for kernel, HAL and kdcom.dll */

View file

@ -10,15 +10,6 @@
#ifndef REACTOS_ROSSYM_H_INCLUDED #ifndef REACTOS_ROSSYM_H_INCLUDED
#define REACTOS_ROSSYM_H_INCLUDED #define REACTOS_ROSSYM_H_INCLUDED
#define ROSSYM_SECTION_NAME ".rossym"
typedef struct _ROSSYM_HEADER {
unsigned long SymbolsOffset;
unsigned long SymbolsLength;
unsigned long StringsOffset;
unsigned long StringsLength;
} ROSSYM_HEADER, *PROSSYM_HEADER;
typedef struct _ROSSYM_ENTRY { typedef struct _ROSSYM_ENTRY {
ULONG_PTR Address; ULONG_PTR Address;
ULONG FunctionOffset; ULONG FunctionOffset;
@ -33,19 +24,16 @@ typedef struct _ROSSYM_CALLBACKS {
BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position); BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position);
} ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS; } ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS;
typedef struct _ROSSYM_INFO *PROSSYM_INFO; struct Dwarf;
typedef struct Dwarf *PROSSYM_INFO;
VOID RosSymInit(PROSSYM_CALLBACKS Callbacks); VOID RosSymInit(PROSSYM_CALLBACKS Callbacks);
VOID RosSymInitKernelMode(VOID); VOID RosSymInitKernelMode(VOID);
VOID RosSymInitUserMode(VOID); VOID RosSymInitUserMode(VOID);
BOOLEAN RosSymCreateFromRaw(PVOID RawData, ULONG_PTR DataSize,
PROSSYM_INFO *RosSymInfo);
BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize,
PROSSYM_INFO *RosSymInfo); PROSSYM_INFO *RosSymInfo);
BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo); BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo);
ULONG RosSymGetRawDataLength(PROSSYM_INFO RosSymInfo);
VOID RosSymGetRawData(PROSSYM_INFO RosSymInfo, PVOID RawData);
BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
ULONG_PTR RelativeAddress, ULONG_PTR RelativeAddress,
ULONG *LineNumber, ULONG *LineNumber,

View file

@ -2,14 +2,21 @@
add_definitions(-D_NTSYSTEM_) add_definitions(-D_NTSYSTEM_)
list(APPEND SOURCE list(APPEND SOURCE
delete.c delete.c
dwarf386.c
dwarfabbrev.c
dwarfaranges.c
dwarfcfa.c
dwarfinfo.c
dwarfget.c
dwarfopen.c
dwarfpc.c
dwarfpubnames.c
find.c find.c
fromfile.c fromfile.c
frommem.c
fromraw.c
getraw.c
init.c init.c
initkm.c initkm.c
initum.c initum.c
pe.c
zwfile.c) zwfile.c)
add_library(rossym ${SOURCE}) add_library(rossym ${SOURCE})
add_dependencies(rossym psdk) add_dependencies(rossym psdk)

41
lib/rossym/compat.h Normal file
View 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_*/

View file

@ -10,15 +10,24 @@
#define NTOSAPI #define NTOSAPI
#include <ntddk.h> #include <ntddk.h>
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include <ntimage.h>
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
#include "rossympriv.h"
#include "pe.h"
#include "dwarf.h"
VOID VOID
RosSymDelete(PROSSYM_INFO RosSymInfo) RosSymDelete(PROSSYM_INFO RosSymInfo)
{ {
RosSymFreeMem(RosSymInfo); int i;
for (i = 0; i < RosSymInfo->pe->nsections; i++) {
RtlFreeAnsiString(ANSI_NAME_STRING(&RosSymInfo->pe->sect[i]));
}
RosSymFreeMem(RosSymInfo->pe->sect);
dwarfclose(RosSymInfo);
} }
/* EOF */ /* EOF */

471
lib/rossym/dwarf.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

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

View file

@ -39,56 +39,12 @@
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
static PROSSYM_ENTRY #include "rossym.h"
FindEntry(IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress) #include "dwarf.h"
{ #include "pe.h"
/*
* Perform a binary search.
*
* The code below is a bit sneaky. After a comparison fails, we
* divide the work in half by moving either left or right. If lim
* is odd, moving left simply involves halving lim: e.g., when lim
* is 5 we look at item 2, so we change lim to 2 so that we will
* look at items 0 & 1. If lim is even, the same applies. If lim
* is odd, moving right again involes halving lim, this time moving
* the base up one item past p: e.g., when lim is 5 we change base
* to item 3 and make lim 2 so that we will look at items 3 and 4.
* If lim is even, however, we have to shrink it by one before
* halving: e.g., when lim is 4, we still looked at item 2, so we
* have to make lim 3, then halve, obtaining 1, so that we will only
* look at item 3.
*/
PROSSYM_ENTRY Base = RosSymInfo->Symbols;
ULONG Lim;
PROSSYM_ENTRY Mid, Low;
if (RelativeAddress < Base->Address)
{
return NULL;
}
Low = Base;
for (Lim = RosSymInfo->SymbolsCount; Lim != 0; Lim >>= 1)
{
Mid = Base + (Lim >> 1);
if (RelativeAddress == Mid->Address)
{
return Mid;
}
if (Mid->Address < RelativeAddress) /* key > mid: move right */
{
Low = Mid;
Base = Mid + 1;
Lim--;
} /* else move left */
}
return Low;
}
BOOLEAN BOOLEAN
RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
@ -97,52 +53,34 @@ RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
char *FileName, char *FileName,
char *FunctionName) char *FunctionName)
{ {
PROSSYM_ENTRY RosSymEntry; char *cdir, *dir, *file, *function;
ulong line, mtime, length;
DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress); int res = dwarfpctoline
(RosSymInfo,
if (RosSymInfo->Symbols == NULL || RosSymInfo->SymbolsCount == 0 || RelativeAddress + RosSymInfo->pe->imagebase,
RosSymInfo->Strings == NULL || RosSymInfo->StringsLength == 0) &cdir,
{ &dir,
DPRINT1("Uninitialized RosSymInfo\n"); &file,
return FALSE; &function,
} &line,
&mtime,
ASSERT(LineNumber || FileName || FunctionName); &length);
if (res != -1) {
/* find symbol entry for function */ *LineNumber = line;
RosSymEntry = FindEntry(RosSymInfo, RelativeAddress); FileName[0] = 0;
if (dir) {
if (NULL == RosSymEntry) strcpy(FileName, dir);
{ strcat(FileName, "/");
DPRINT("None of the requested information was found!\n"); }
return FALSE; if (file)
} strcat(FileName, file);
FunctionName[0] = 0;
if (LineNumber != NULL) if (function)
{ strcpy(FunctionName, function);
*LineNumber = RosSymEntry->SourceLine; return TRUE;
} } else {
if (FileName != NULL) return FALSE;
{ }
PCSTR Name = "";
if (RosSymEntry->FileOffset != 0)
{
Name = (PCHAR) RosSymInfo->Strings + RosSymEntry->FileOffset;
}
strcpy(FileName, Name);
}
if (FunctionName != NULL)
{
PCSTR Name = "";
if (RosSymEntry->FunctionOffset != 0)
{
Name = (PCHAR) RosSymInfo->Strings + RosSymEntry->FunctionOffset;
}
strcpy(FunctionName, Name);
}
return TRUE;
} }
/* EOF */ /* EOF */

View file

@ -8,12 +8,16 @@
*/ */
#define NTOSAPI #define NTOSAPI
#include <ntddk.h> #include <ntifs.h>
#include <ndk/ntndk.h>
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#include "pe.h"
#include <ntimage.h> #include <ntimage.h>
#define NDEBUG #include "dwarf.h"
//#define NDEBUG
#include <debug.h> #include <debug.h>
BOOLEAN BOOLEAN
@ -21,12 +25,12 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
{ {
IMAGE_DOS_HEADER DosHeader; IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeaders; IMAGE_NT_HEADERS NtHeaders;
PIMAGE_SECTION_HEADER SectionHeaders, SectionHeader; PIMAGE_SECTION_HEADER SectionHeaders;
unsigned SectionIndex; unsigned SectionIndex;
char SectionName[IMAGE_SIZEOF_SHORT_NAME]; unsigned SymbolTable, NumSymbols;
ROSSYM_HEADER RosSymHeader;
/* Load DOS header */ /* Load DOS header */
DPRINT("About to read file\n");
if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER))) if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
{ {
DPRINT1("Failed to read DOS header\n"); DPRINT1("Failed to read DOS header\n");
@ -55,6 +59,10 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
return FALSE; return FALSE;
} }
SymbolTable = NtHeaders.FileHeader.PointerToSymbolTable;
NumSymbols = NtHeaders.FileHeader.NumberOfSymbols;
DPRINT("SymbolTable %x NumSymbols %x\n", SymbolTable, NumSymbols);
/* Load section headers */ /* Load section headers */
if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) - if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
(char *) &NtHeaders + DosHeader.e_lfanew)) (char *) &NtHeaders + DosHeader.e_lfanew))
@ -79,69 +87,108 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
return FALSE; return FALSE;
} }
/* Search for the section header */ // Convert names to ANSI_STRINGs
strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME); for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
SectionHeader = SectionHeaders; SectionIndex++)
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections; SectionIndex++) {
{ ANSI_STRING astr;
if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME)) if (SectionHeaders[SectionIndex].Name[0] != '/') {
{ DPRINT("Short name string %d, %s\n", SectionIndex, SectionHeaders[SectionIndex].Name);
break; astr.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
} memcpy(astr.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
SectionHeader++; astr.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
} astr.Length = GetStrnlen(astr.Buffer, IMAGE_SIZEOF_SHORT_NAME);
if (NtHeaders.FileHeader.NumberOfSections <= SectionIndex) } else {
{ UNICODE_STRING intConv;
RosSymFreeMem(SectionHeaders); NTSTATUS Status;
DPRINT("No %s section found\n", ROSSYM_SECTION_NAME); ULONG StringOffset;
return FALSE;
}
/* Load rossym header */ Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
if (! RosSymSeekFile(FileContext, SectionHeader->PointerToRawData)) if (!NT_SUCCESS(Status)) goto freeall;
{ Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
RosSymFreeMem(SectionHeaders); RtlFreeUnicodeString(&intConv);
DPRINT1("Failed seeking to section data\n"); if (!NT_SUCCESS(Status)) goto freeall;
return FALSE; if (!RosSymSeekFile(FileContext, SymbolTable + NumSymbols * SYMBOL_SIZE + StringOffset))
} goto freeall;
RosSymFreeMem(SectionHeaders); astr.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
if (! RosSymReadFile(FileContext, &RosSymHeader, sizeof(ROSSYM_HEADER))) if (!RosSymReadFile(FileContext, astr.Buffer, MAXIMUM_DWARF_NAME_SIZE))
{ goto freeall;
DPRINT1("Failed to read rossym header\n"); astr.Length = GetStrnlen(astr.Buffer, MAXIMUM_DWARF_NAME_SIZE);
return FALSE; astr.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
} DPRINT("Long name %d, %s\n", SectionIndex, astr.Buffer);
if (RosSymHeader.SymbolsOffset < sizeof(ROSSYM_HEADER) }
|| RosSymHeader.StringsOffset < RosSymHeader.SymbolsOffset + RosSymHeader.SymbolsLength *ANSI_NAME_STRING(&SectionHeaders[SectionIndex]) = astr;
|| 0 != (RosSymHeader.SymbolsLength % sizeof(ROSSYM_ENTRY))) }
{
DPRINT1("Invalid ROSSYM_HEADER\n");
return FALSE;
}
*RosSymInfo = RosSymAllocMem(sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER) DPRINT("Done with sections\n");
+ RosSymHeader.StringsOffset + RosSymHeader.StringsLength + 1); Pe *pe = RosSymAllocMem(sizeof(*pe));
if (NULL == *RosSymInfo) pe->fd = FileContext;
{ pe->e2 = peget2;
DPRINT1("Failed to allocate memory for rossym\n"); pe->e4 = peget4;
return FALSE; pe->e8 = peget8;
} pe->nsections = NtHeaders.FileHeader.NumberOfSections;
(*RosSymInfo)->Symbols = (PROSSYM_ENTRY)((char *) *RosSymInfo + sizeof(ROSSYM_INFO) pe->sect = SectionHeaders;
- sizeof(ROSSYM_HEADER) + RosSymHeader.SymbolsOffset); pe->nsymbols = NtHeaders.FileHeader.NumberOfSymbols;
(*RosSymInfo)->SymbolsCount = RosSymHeader.SymbolsLength / sizeof(ROSSYM_ENTRY); pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
(*RosSymInfo)->Strings = (PCHAR) *RosSymInfo + sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER) SYMENT SymbolData;
+ RosSymHeader.StringsOffset; int i, j;
(*RosSymInfo)->StringsLength = RosSymHeader.StringsLength; DPRINT("Getting symbol data\n");
if (! RosSymReadFile(FileContext, *RosSymInfo + 1, ASSERT(sizeof(SymbolData) == 18);
RosSymHeader.StringsOffset + RosSymHeader.StringsLength for (i = 0, j = 0; i < pe->nsymbols; i++) {
- sizeof(ROSSYM_HEADER))) if (!RosSymSeekFile
{ (FileContext,
DPRINT1("Failed to read rossym headers\n"); NtHeaders.FileHeader.PointerToSymbolTable + i * sizeof(SymbolData)))
return FALSE; goto freeall;
} if (!RosSymReadFile(FileContext, &SymbolData, sizeof(SymbolData)))
/* Make sure the last string is null terminated, we allocated an extra byte for that */ goto freeall;
(*RosSymInfo)->Strings[(*RosSymInfo)->StringsLength] = '\0'; if ((SymbolData.e_scnum < 1) ||
(SymbolData.e_sclass != C_EXT &&
SymbolData.e_sclass != C_STAT))
continue;
int section = SymbolData.e_scnum - 1;
if (SymbolData.e.e.e_zeroes) {
pe->symtab[j].name = malloc(sizeof(SymbolData.e.e_name)+1);
memcpy(pe->symtab[j].name, SymbolData.e.e_name, sizeof(SymbolData.e.e_name));
pe->symtab[j].name[sizeof(SymbolData.e.e_name)] = 0;
} else {
if (!RosSymSeekFile
(FileContext,
NtHeaders.FileHeader.PointerToSymbolTable +
(NtHeaders.FileHeader.NumberOfSymbols * 18) +
SymbolData.e.e.e_offset))
goto freeall;
pe->symtab[j].name = malloc(MAXIMUM_COFF_SYMBOL_LENGTH+1);
pe->symtab[j].name[MAXIMUM_COFF_SYMBOL_LENGTH] = 0;
// It's possible that we've got a string just at the end of the file
// we'll skip that symbol if needed
if (!RosSymReadFile(FileContext, pe->symtab[j].name, MAXIMUM_COFF_SYMBOL_LENGTH)) {
free(pe->symtab[j].name);
continue;
}
}
if (pe->symtab[j].name[0] == '.') {
free(pe->symtab[j].name);
continue;
}
pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData.e_value;
j++;
}
DPRINT("%d symbols\n", j);
pe->nsymbols = j;
pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
pe->loadsection = loaddisksection;
*RosSymInfo = dwarfopen(pe);
return TRUE; return TRUE;
freeall:
for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
SectionIndex++)
RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
RosSymFreeMem(SectionHeaders);
return FALSE;
} }
/* EOF */ /* EOF */

View file

@ -8,84 +8,153 @@
*/ */
#define NTOSAPI #define NTOSAPI
#include <ntddk.h> #include <ntifs.h>
#include <ndk/ntndk.h>
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#include <ntimage.h> #include <ntimage.h>
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
#include "dwarf.h"
#include "pe.h"
BOOLEAN BOOLEAN
RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo) RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo)
{ {
PIMAGE_DOS_HEADER DosHeader; ANSI_STRING AnsiNameString = { };
PIMAGE_NT_HEADERS NtHeaders; PIMAGE_DOS_HEADER DosHeader;
PIMAGE_SECTION_HEADER SectionHeader; PIMAGE_NT_HEADERS NtHeaders;
ULONG SectionIndex; PIMAGE_SECTION_HEADER SectionHeaders;
BOOLEAN RosSymSectionFound = FALSE; ULONG SectionIndex;
CHAR SectionName[IMAGE_SIZEOF_SHORT_NAME]; unsigned SymbolTable, NumSymbols;
/* Check if MZ header is valid */ /* Check if MZ header is valid */
DosHeader = (PIMAGE_DOS_HEADER) ImageStart; DosHeader = (PIMAGE_DOS_HEADER) ImageStart;
if (ImageSize < sizeof(IMAGE_DOS_HEADER) if (ImageSize < sizeof(IMAGE_DOS_HEADER)
|| ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader)) || ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader))
{ {
DPRINT1("Image doesn't have a valid DOS header\n"); DPRINT1("Image doesn't have a valid DOS header\n");
return FALSE; return FALSE;
} }
/* Locate NT header */ /* Locate NT header */
NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew); NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew);
if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
|| ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders)) || ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders))
{ {
DPRINT1("Image doesn't have a valid PE header\n"); DPRINT1("Image doesn't have a valid PE header\n");
return FALSE; return FALSE;
} }
/* Search for the section header */ SymbolTable = NtHeaders->FileHeader.PointerToSymbolTable;
SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); NumSymbols = NtHeaders->FileHeader.NumberOfSymbols;
if (ImageSize < (ULONG_PTR)((char *) (SectionHeader + NtHeaders->FileHeader.NumberOfSections)
- (char *) ImageStart))
{
DPRINT1("Image doesn't have valid section headers\n");
return FALSE;
}
strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME);
for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections; SectionIndex++)
{
if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME))
{
RosSymSectionFound = TRUE;
break;
}
SectionHeader++;
}
if (!RosSymSectionFound) /* Search for the section header */
{ ULONG SectionHeaderSize = NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
DPRINT("No %s section found\n", ROSSYM_SECTION_NAME); SectionHeaders = RosSymAllocMem(SectionHeaderSize);
return FALSE; RtlCopyMemory(SectionHeaders, IMAGE_FIRST_SECTION(NtHeaders), SectionHeaderSize);
}
/* Locate the section itself */ // Convert names to ANSI_STRINGs
if (ImageSize < SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
|| SectionHeader->SizeOfRawData < sizeof(ROSSYM_HEADER)) SectionIndex++)
{ {
DPRINT("Invalid %s section\n", ROSSYM_SECTION_NAME); if (SectionHeaders[SectionIndex].Name[0] != '/') {
return FALSE; AnsiNameString.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
} RtlCopyMemory(AnsiNameString.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
AnsiNameString.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
AnsiNameString.Length = GetStrnlen(AnsiNameString.Buffer, IMAGE_SIZEOF_SHORT_NAME);
} else {
UNICODE_STRING intConv;
NTSTATUS Status;
ULONG StringOffset;
if (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize > ImageSize) Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
{ if (!NT_SUCCESS(Status)) goto freeall;
DPRINT("Bad %s section virtual size!\n", ROSSYM_SECTION_NAME); Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
return FALSE; RtlFreeUnicodeString(&intConv);
} if (!NT_SUCCESS(Status)) goto freeall;
ULONG VirtualOffset = pefindrva(SectionHeaders, NtHeaders->FileHeader.NumberOfSections, SymbolTable+(NumSymbols*SYMBOL_SIZE)+StringOffset);
if (!VirtualOffset) goto freeall;
AnsiNameString.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
if (!AnsiNameString.Buffer) goto freeall;
PCHAR StringTarget = ((PCHAR)ImageStart)+VirtualOffset;
PCHAR EndOfImage = ((PCHAR)ImageStart) + NtHeaders->OptionalHeader.SizeOfImage;
if (StringTarget >= EndOfImage) goto freeall;
ULONG PossibleStringLength = EndOfImage - StringTarget;
if (PossibleStringLength > MAXIMUM_DWARF_NAME_SIZE)
PossibleStringLength = MAXIMUM_DWARF_NAME_SIZE;
RtlCopyMemory(AnsiNameString.Buffer, StringTarget, PossibleStringLength);
AnsiNameString.Length = strlen(AnsiNameString.Buffer);
AnsiNameString.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
}
memcpy
(&SectionHeaders[SectionIndex],
&AnsiNameString,
sizeof(AnsiNameString));
}
/* Load it */ Pe *pe = RosSymAllocMem(sizeof(*pe));
return RosSymCreateFromRaw((char *) ImageStart + SectionHeader->VirtualAddress, pe->fd = ImageStart;
SectionHeader->SizeOfRawData, RosSymInfo); pe->e2 = peget2;
pe->e4 = peget4;
pe->e8 = peget8;
pe->loadbase = (ULONG)ImageStart;
pe->imagebase = NtHeaders->OptionalHeader.ImageBase;
pe->imagesize = NtHeaders->OptionalHeader.SizeOfImage;
pe->nsections = NtHeaders->FileHeader.NumberOfSections;
pe->sect = SectionHeaders;
pe->nsymbols = NtHeaders->FileHeader.NumberOfSymbols;
pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
PSYMENT SymbolData = (PSYMENT)
(((PCHAR)ImageStart) +
pefindrva
(pe->sect,
pe->nsections,
NtHeaders->FileHeader.PointerToSymbolTable));
int i, j;
for (i = 0, j = 0; i < pe->nsymbols; i++) {
if ((SymbolData[i].e_scnum < 1) ||
(SymbolData[i].e_sclass != C_EXT &&
SymbolData[i].e_sclass != C_STAT))
continue;
int section = SymbolData[i].e_scnum - 1;
if (SymbolData[i].e.e.e_zeroes) {
pe->symtab[j].name = malloc(sizeof(SymbolData[i].e.e_name)+1);
strcpy(pe->symtab[j].name, SymbolData[i].e.e_name);
} else {
PCHAR SymbolName = ((PCHAR)ImageStart) +
pefindrva
(pe->sect,
pe->nsections,
NtHeaders->FileHeader.PointerToSymbolTable +
(NtHeaders->FileHeader.NumberOfSymbols * 18) +
SymbolData[i].e.e.e_offset);
pe->symtab[j].name = malloc(strlen(SymbolName)+1);
strcpy(pe->symtab[j].name, SymbolName);
}
if (pe->symtab[j].name[0] == '.') {
free(pe->symtab[j].name);
continue;
}
pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData[i].e_value;
j++;
}
pe->nsymbols = j;
pe->loadsection = loadmemsection;
*RosSymInfo = dwarfopen(pe);
return !!*RosSymInfo;
freeall:
if (AnsiNameString.Buffer) RosSymFreeMem(AnsiNameString.Buffer);
for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
SectionIndex++)
RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
RosSymFreeMem(SectionHeaders);
return FALSE;
} }
/* EOF */ /* EOF */

View file

@ -12,7 +12,7 @@
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
BOOLEAN BOOLEAN

View file

@ -12,7 +12,7 @@
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
ULONG ULONG

View file

@ -14,7 +14,7 @@
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
#define TAG_ROSSYM 'MYSR' #define TAG_ROSSYM 'MYSR'

View file

@ -11,7 +11,7 @@
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
static PVOID static PVOID

138
lib/rossym/pe.c Normal file
View 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
View 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_*/

View file

@ -9,13 +9,6 @@
#pragma once #pragma once
typedef struct _ROSSYM_INFO {
PROSSYM_ENTRY Symbols;
ULONG SymbolsCount;
PCHAR Strings;
ULONG StringsLength;
} ROSSYM_INFO;
extern ROSSYM_CALLBACKS RosSymCallbacks; extern ROSSYM_CALLBACKS RosSymCallbacks;
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size) #define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)

View file

@ -12,7 +12,7 @@
#include <reactos/rossym.h> #include <reactos/rossym.h>
#include "rossympriv.h" #include "rossympriv.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
BOOLEAN BOOLEAN

View file

@ -401,23 +401,11 @@ KdbSymProcessSymbols(
if (LdrEntry->PatchInformation) if (LdrEntry->PatchInformation)
KdbpSymRemoveCachedFile(LdrEntry->PatchInformation); KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
/* Load new symbol information */ /* Error loading symbol info, try to load it from file */
if (! RosSymCreateFromMem(LdrEntry->DllBase, KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
LdrEntry->SizeOfImage,
(PROSSYM_INFO*)&LdrEntry->PatchInformation))
{
/* Error loading symbol info, try to load it from file */
KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
(PROSSYM_INFO*)&LdrEntry->PatchInformation); (PROSSYM_INFO*)&LdrEntry->PatchInformation);
/* It already added symbols to cache */ /* It already added symbols to cache */
}
else
{
/* Add file to cache */
KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation);
}
DPRINT("Installed symbols: %wZ@%p-%p %p\n", DPRINT("Installed symbols: %wZ@%p-%p %p\n",
&LdrEntry->BaseDllName, &LdrEntry->BaseDllName,
LdrEntry->DllBase, LdrEntry->DllBase,
@ -522,7 +510,7 @@ KdbInitialize(
RosSymInitKernelMode(); RosSymInitKernelMode();
} }
else if (BootPhase == 1) else if (BootPhase == 3)
{ {
/* Load symbols for NTOSKRNL.EXE. /* Load symbols for NTOSKRNL.EXE.
It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */ It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */

View file

@ -44,13 +44,6 @@ SECTIONS
{ {
*(.edata) *(.edata)
} }
/DISCARD/ :
{
*(.debug$S)
*(.debug$T)
*(.debug$F)
*(.drectve)
}
.idata BLOCK(__section_alignment__) : .idata BLOCK(__section_alignment__) :
{ {
@ -87,13 +80,41 @@ SECTIONS
/* These zeroes mark the end of the reloc section. */ /* These zeroes mark the end of the reloc section. */
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
} }
.stab BLOCK(__section_alignment__) (NOLOAD) : .debug_aranges BLOCK(__section_alignment__) :
{ {
[ .stab ] *(.debug_aranges)
} }
.stabstr BLOCK(__section_alignment__) (NOLOAD) : .debug_abbrev BLOCK(__section_alignment__) :
{ {
[ .stabstr ] *(.debug_abbrev)
}
.debug_frame BLOCK(__section_alignment__) :
{
*(.debug_frame)
}
.debug_info BLOCK(__section_alignment__) :
{
*(.debug_info)
}
.debug_line BLOCK(__section_alignment__) :
{
*(.debug_line)
}
.debug_loc BLOCK(__section_alignment__) :
{
*(.debug_loc)
}
.debug_pubnames BLOCK(__section_alignment__) :
{
*(.debug_pubnames)
}
.debug_ranges BLOCK(__section_alignment__) :
{
*(.debug_ranges)
}
.debug_str BLOCK(__section_alignment__) :
{
*(.debug_str)
} }
INIT BLOCK(__section_alignment__) : INIT BLOCK(__section_alignment__) :
{ {