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

View file

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

View file

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

View file

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

41
lib/rossym/compat.h Normal file
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
#include <ntddk.h>
#include <reactos/rossym.h>
#include "rossympriv.h"
#include <ntimage.h>
#define NDEBUG
//#define NDEBUG
#include <debug.h>
#include "rossympriv.h"
#include "pe.h"
#include "dwarf.h"
VOID
RosSymDelete(PROSSYM_INFO RosSymInfo)
{
RosSymFreeMem(RosSymInfo);
int i;
for (i = 0; i < RosSymInfo->pe->nsections; i++) {
RtlFreeAnsiString(ANSI_NAME_STRING(&RosSymInfo->pe->sect[i]));
}
RosSymFreeMem(RosSymInfo->pe->sect);
dwarfclose(RosSymInfo);
}
/* EOF */

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

138
lib/rossym/pe.c Normal file
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
typedef struct _ROSSYM_INFO {
PROSSYM_ENTRY Symbols;
ULONG SymbolsCount;
PCHAR Strings;
ULONG StringsLength;
} ROSSYM_INFO;
extern ROSSYM_CALLBACKS RosSymCallbacks;
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)

View file

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

View file

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

View file

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