-/* $Id: loader.c,v 1.114 2002/06/27 17:52:32 ekohl Exp $
+/* $Id: loader.c,v 1.115 2002/07/13 12:44:08 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* GLOBALS *******************************************************************/
+#ifdef DBG
+
+typedef struct _SYMBOLFILE_HEADER {
+ unsigned long StabsOffset;
+ unsigned long StabsLength;
+ unsigned long StabstrOffset;
+ unsigned long StabstrLength;
+} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
+
+typedef struct _IMAGE_SYMBOL_INFO_CACHE {
+ LIST_ENTRY ListEntry;
+ UNICODE_STRING FullName;
+ PVOID FileBuffer;
+ PVOID SymbolsBase;
+ ULONG SymbolsLength;
+ PVOID SymbolStringsBase;
+ ULONG SymbolStringsLength;
+} IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
+
+
+typedef struct _STAB_ENTRY {
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ unsigned long n_value; /* value of symbol */
+} _STAB_ENTRY, *PSTAB_ENTRY;
+
+/*
+ * Desc - Line number
+ * Value - Relative virtual address
+ */
+#define N_FUN 0x24
+
+/*
+ * Desc - Line number
+ * Value - Relative virtual address
+ */
+#define N_SLINE 0x44
+
+/*
+ * String - First containing a '/' is the compillation directory (CD)
+ * Not containing a '/' is a source file relative to CD
+ */
+#define N_SO 0x64
+
+LIST_ENTRY SymbolListHead;
+
+#endif /* DBG */
+
LIST_ENTRY ModuleListHead;
KSPIN_LOCK ModuleListLock;
ULONG_PTR LdrHalBase;
#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
-#define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
/* FORWARD DECLARATIONS ******************************************************/
{
return;
}
-
- current->SymbolsBase = (PVOID)Module->ModStart;
- current->SymbolsLength = Module->ModEnd - Module->ModStart;
}
VOID
NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
SectionList[0].VirtualAddress;
NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
- NtoskrnlTextSection.SymbolsBase = NULL;
- NtoskrnlTextSection.SymbolsLength = 0;
+#ifdef DBG
+ RtlZeroMemory(&NtoskrnlTextSection.SymbolInfo, sizeof(NtoskrnlTextSection.SymbolInfo));
+ NtoskrnlTextSection.SymbolInfo.ImageBase = OptionalHeader->ImageBase;
+ NtoskrnlTextSection.SymbolInfo.ImageSize = NtoskrnlTextSection.Length;
+#endif
InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
/* Setup hal.dll text section */
LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
SectionList[0].VirtualAddress;
LdrHalTextSection.Name = HAL_MODULE_NAME;
- LdrHalTextSection.SymbolsBase = NULL;
- LdrHalTextSection.SymbolsLength = 0;
+#ifdef DBG
+ RtlZeroMemory(&LdrHalTextSection.SymbolInfo, sizeof(LdrHalTextSection.SymbolInfo));
+ LdrHalTextSection.SymbolInfo.ImageBase = OptionalHeader->ImageBase;
+ LdrHalTextSection.SymbolInfo.ImageSize = LdrHalTextSection.Length;
+#endif
InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
+
+#ifdef DBG
+ InitializeListHead(&SymbolListHead);
+#endif
}
&ModuleObject->ListEntry);
}
+#ifdef DBG
-#ifdef KDBG
-
-BOOLEAN LdrpReadLine(PCHAR Line,
- ULONG LineSize,
- PVOID *Buffer,
- PULONG Size)
+VOID
+LdrpParseImageSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
+/* Note: It is important that the symbol strings buffer not be released after
+ this function is called because the strings are still referenced */
{
- CHAR ch;
- PCHAR Block;
- ULONG Count;
+ PSYMBOL CurrentFileNameSymbol;
+ PSYMBOL CurrentFunctionSymbol;
+ PSYMBOL CurrentLineNumberSymbol;
+ PSYMBOL Symbol;
+ PSTAB_ENTRY StabEntry;
+ PVOID StabsEnd;
+ PCHAR String;
+ ULONG_PTR FunRelativeAddress;
+ ULONG FunLineNumber;
+ ULONG_PTR ImageBase;
+
+ assert(SymbolInfo);
+
+ DPRINT("Parsing symbols.\n");
+
+ SymbolInfo->FileNameSymbols.SymbolCount = 0;
+ SymbolInfo->FileNameSymbols.Symbols = NULL;
+ SymbolInfo->FunctionSymbols.SymbolCount = 0;
+ SymbolInfo->FunctionSymbols.Symbols = NULL;
+ SymbolInfo->LineNumberSymbols.SymbolCount = 0;
+ SymbolInfo->LineNumberSymbols.Symbols = NULL;
+ StabsEnd = SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength;
+ StabEntry = (PSTAB_ENTRY) SymbolInfo->SymbolsBase;
+ ImageBase = SymbolInfo->ImageBase;
+ FunRelativeAddress = 0;
+ FunLineNumber = 0;
+ CurrentFileNameSymbol = NULL;
+ CurrentFunctionSymbol = NULL;
+ CurrentLineNumberSymbol = NULL;
+ while ((ULONG_PTR) StabEntry < (ULONG_PTR) StabsEnd)
+ {
+ Symbol = NULL;
+
+ if (StabEntry->n_type == N_FUN)
+ {
+ if (StabEntry->n_desc > 0)
+ {
+ assert(StabEntry->n_value >= ImageBase);
+
+ FunRelativeAddress = StabEntry->n_value - ImageBase;
+ FunLineNumber = StabEntry->n_desc;
+
+ Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
+ assert(Symbol);
+ Symbol->Next = NULL;
+ Symbol->SymbolType = ST_FUNCTION;
+ Symbol->RelativeAddress = FunRelativeAddress;
+ Symbol->LineNumber = FunLineNumber;
+ String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
+ RtlInitAnsiString(&Symbol->Name, String);
+
+ DPRINT("FUN found. '%s' %d @ %x\n",
+ Symbol->Name.Buffer, FunLineNumber, FunRelativeAddress);
+ }
+ }
+ else if (StabEntry->n_type == N_SLINE)
+ {
+ Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
+ assert(Symbol);
+ Symbol->Next = NULL;
+ Symbol->SymbolType = ST_LINENUMBER;
+ Symbol->RelativeAddress = FunRelativeAddress + StabEntry->n_value;
+ Symbol->LineNumber = StabEntry->n_desc;
+
+ DPRINT("SLINE found. %d @ %x\n",
+ Symbol->LineNumber, Symbol->RelativeAddress);
+ }
+ else if (StabEntry->n_type == N_SO)
+ {
+ Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
+ assert(Symbol);
+ Symbol->Next = NULL;
+ Symbol->SymbolType = ST_FILENAME;
+ Symbol->RelativeAddress = StabEntry->n_value - ImageBase;
+ Symbol->LineNumber = 0;
+ String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
+ RtlInitAnsiString(&Symbol->Name, String);
+
+ DPRINT("SO found. '%s' @ %x\n",
+ Symbol->Name.Buffer, Symbol->RelativeAddress);
+ }
- if (*Size == 0)
- return FALSE;
+ if (Symbol != NULL)
+ {
+ switch (Symbol->SymbolType)
+ {
+ case ST_FILENAME:
+ if (SymbolInfo->FileNameSymbols.Symbols == NULL)
+ SymbolInfo->FileNameSymbols.Symbols = Symbol;
+ else
+ CurrentFileNameSymbol->Next = Symbol;
- ch = ' ';
- Count = 0;
- Block = *Buffer;
- while ((*Size > 0) && (Count < LineSize) && ((ch = *Block) != (CHAR)13))
- {
- *Line = ch;
- Line++;
- Block++;
- Count++;
- *Size -= 1;
- }
- *Line = (CHAR)0;
+ CurrentFileNameSymbol = Symbol;
- if (ch == (CHAR)13)
- {
- Block++;
- *Size -= 1;
- }
+ SymbolInfo->FileNameSymbols.SymbolCount++;
+ break;
+ case ST_FUNCTION:
+ if (SymbolInfo->FunctionSymbols.Symbols == NULL)
+ SymbolInfo->FunctionSymbols.Symbols = Symbol;
+ else
+ CurrentFunctionSymbol->Next = Symbol;
- if ((*Size > 0) && (*Block == (CHAR)10))
- {
- Block++;
- *Size -= 1;
- }
+ CurrentFunctionSymbol = Symbol;
+
+ SymbolInfo->FunctionSymbols.SymbolCount++;
+ break;
+ case ST_LINENUMBER:
+ if (SymbolInfo->LineNumberSymbols.Symbols == NULL)
+ SymbolInfo->LineNumberSymbols.Symbols = Symbol;
+ else
+ CurrentLineNumberSymbol->Next = Symbol;
- *Buffer = Block;
+ CurrentLineNumberSymbol = Symbol;
- return TRUE;
-}
+ SymbolInfo->LineNumberSymbols.SymbolCount++;
+ break;
+ }
+ }
-ULONG HexL(PCHAR Buffer)
-{
- CHAR ch;
- UINT i, j;
- ULONG Value;
-
- j = 32;
- i = 0;
- Value = 0;
- while ((j > 0) && ((ch = Buffer[i]) != ' '))
- {
- j -= 4;
- if ((ch >= '0') && (ch <= '9'))
- Value |= ((ch - '0') << j);
- if ((ch >= 'A') && (ch <= 'F'))
- Value |= ((10 + (ch - 'A')) << j);
- else
- if ((ch >= 'a') && (ch <= 'f'))
- Value |= ((10 + (ch - 'a')) << j);
- i++;
- }
- return Value;
+ StabEntry++;
+ }
}
-PSYMBOL LdrpParseLine(PCHAR Line,
- PULONG TextBase,
- PBOOLEAN TextBaseValid,
- PULONG Alignment)
-/*
- Line format: [ADDRESS] <TYPE> <NAME>
- TYPE:
- U = ?
- A = Image information
- t = Symbol in text segment
- T = Symbol in text segment
- d = Symbol in data segment
- D = Symbol in data segment
- b = Symbol in BSS segment
- B = Symbol in BSS segment
- ? = Unknown segment or symbol in unknown segment
-*/
+static NTSTATUS
+LdrpGetFileName(IN PIMAGE_SYMBOL_INFO SymbolInfo,
+ IN ULONG_PTR RelativeAddress,
+ OUT PCH FileName)
{
- ANSI_STRING AnsiString;
- CHAR Buffer[128];
+ PSYMBOL NextSymbol;
+ ULONG_PTR NextAddress;
PSYMBOL Symbol;
- ULONG Address;
- PCHAR Str;
- CHAR Type;
- if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
- return NULL;
+ Symbol = SymbolInfo->FileNameSymbols.Symbols;
+ while (Symbol != NULL)
+ {
+ NextSymbol = Symbol->Next;
+ if (NextSymbol != NULL)
+ NextAddress = NextSymbol->RelativeAddress;
+ else
+ NextAddress = SymbolInfo->ImageSize;
- Address = HexL(Line);
+ DPRINT("FN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
+ Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
- Line = strchr(Line, ' ');
- if (Line == NULL)
- return NULL;
+ if ((Symbol->SymbolType == ST_FILENAME) &&
+ (RelativeAddress >= Symbol->RelativeAddress) &&
+ (RelativeAddress < NextAddress))
+ {
+ DPRINT("FN found\n");
+ strcpy(FileName, Symbol->Name.Buffer);
+ return STATUS_SUCCESS;
+ }
+ Symbol = NextSymbol;
+ }
- Line++;
- Type = *Line;
+ DPRINT("FN not found\n");
- Line = strchr(Line, ' ');
- if (Line == NULL)
- return NULL;
+ return STATUS_UNSUCCESSFUL;
+}
- Line++;
- Str = strchr(Line, ' ');
- if (Str == NULL)
- strcpy((char*)&Buffer, Line);
- else
- strncpy((char*)&Buffer, Line, Str - Line);
+static NTSTATUS
+LdrpGetFunctionName(IN PIMAGE_SYMBOL_INFO SymbolInfo,
+ IN ULONG_PTR RelativeAddress,
+ OUT PCH FunctionName)
+{
+ PSYMBOL NextSymbol;
+ ULONG_PTR NextAddress;
+ PSYMBOL Symbol;
- if ((Type == 'A') && (strcmp((char*)&Buffer, "__section_alignment__")) == 0)
+ Symbol = SymbolInfo->FunctionSymbols.Symbols;
+ while (Symbol != NULL)
{
- *Alignment = Address;
- return NULL;
- }
-
- /* We only want symbols in the .text segment */
- if ((Type != 't') && (Type != 'T'))
- return NULL;
-
- /* Discard other symbols we can't use */
- if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
- return NULL;
+ NextSymbol = Symbol->Next;
+ if (NextSymbol != NULL)
+ NextAddress = NextSymbol->RelativeAddress;
+ else
+ NextAddress = SymbolInfo->ImageSize;
- Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
- if (!Symbol)
- return NULL;
+ DPRINT("FUN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
+ Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
- Symbol->Next = NULL;
+ if ((Symbol->SymbolType == ST_FUNCTION) &&
+ (RelativeAddress >= Symbol->RelativeAddress) &&
+ (RelativeAddress < NextAddress))
+ {
+ PCHAR ExtraInfo;
+ ULONG Length;
- Symbol->RelativeAddress = Address;
+ DPRINT("FUN found\n");
- RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
- RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
+ /* Remove the extra information from the function name */
+ ExtraInfo = strchr(Symbol->Name.Buffer, ':');
+ if (ExtraInfo != NULL)
+ Length = ExtraInfo - Symbol->Name.Buffer;
+ else
+ Length = strlen(Symbol->Name.Buffer);
- if (!(*TextBaseValid))
- {
- *TextBase = Address - *Alignment;
- *TextBaseValid = TRUE;
+ strncpy(FunctionName, Symbol->Name.Buffer, Length);
+ return STATUS_SUCCESS;
+ }
+ Symbol = NextSymbol;
}
- return Symbol;
+ DPRINT("FUN not found\n");
+
+ return STATUS_UNSUCCESSFUL;
}
-VOID
-LdrpLoadModuleSymbolsFromBuffer(PMODULE_OBJECT ModuleObject,
- PVOID Buffer,
- ULONG Length)
-/*
- Symbols must be sorted by address, e.g.
- "nm --numeric-sort module.sys > module.sym"
- */
+static NTSTATUS
+LdrpGetLineNumber(IN PIMAGE_SYMBOL_INFO SymbolInfo,
+ IN ULONG_PTR RelativeAddress,
+ OUT PULONG LineNumber)
{
- PSYMBOL Symbol, CurrentSymbol = NULL;
- BOOLEAN TextBaseValid;
- BOOLEAN Valid;
- ULONG TextBase = 0;
- ULONG Alignment = 0;
- CHAR Line[256];
- ULONG Tmp;
-
- assert(ModuleObject);
-
- if (ModuleObject->TextSection == NULL)
- {
- ModuleObject->TextSection = &NtoskrnlTextSection;
- }
+ PSYMBOL NextSymbol;
+ ULONG_PTR NextAddress;
+ PSYMBOL Symbol;
- if (ModuleObject->TextSection->Symbols.SymbolCount > 0)
+ Symbol = SymbolInfo->LineNumberSymbols.Symbols;
+ while (Symbol != NULL)
{
- CPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseName);
- return;
- }
+ NextSymbol = Symbol->Next;
+ if (NextSymbol != NULL)
+ NextAddress = NextSymbol->RelativeAddress;
+ else
+ NextAddress = SymbolInfo->ImageSize;
- ModuleObject->TextSection->Symbols.SymbolCount = 0;
- ModuleObject->TextSection->Symbols.Symbols = NULL;
- TextBaseValid = FALSE;
- Valid = FALSE;
- while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
- {
- Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &Alignment);
+ DPRINT("LN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
+ Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
- if ((Valid) && (!TextBaseValid))
+ if ((Symbol->SymbolType == ST_LINENUMBER) &&
+ (RelativeAddress >= Symbol->RelativeAddress) &&
+ (RelativeAddress < NextAddress))
{
- TextBase = Tmp;
- TextBaseValid = TRUE;
+ DPRINT("LN found\n");
+ *LineNumber = Symbol->LineNumber;
+ return STATUS_SUCCESS;
}
+ Symbol = NextSymbol;
+ }
- if (Symbol != NULL)
- {
- Symbol->RelativeAddress -= TextBase;
-
- if (ModuleObject->TextSection->Symbols.Symbols == NULL)
- ModuleObject->TextSection->Symbols.Symbols = Symbol;
- else
- CurrentSymbol->Next = Symbol;
-
- CurrentSymbol = Symbol;
+ DPRINT("LN not found\n");
- ModuleObject->TextSection->Symbols.SymbolCount++;
- }
- }
+ return STATUS_UNSUCCESSFUL;
}
-
-VOID
-LdrpLoadUserModuleSymbolsFromBuffer(PLDR_MODULE ModuleObject,
- PVOID Buffer,
- ULONG Length)
-/*
- Symbols must be sorted by address, e.g.
- "nm --numeric-sort module.dll > module.sym"
- */
+NTSTATUS
+LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
+ IN ULONG_PTR RelativeAddress,
+ OUT PULONG LineNumber,
+ OUT PCH FileName OPTIONAL,
+ OUT PCH FunctionName OPTIONAL)
{
- PSYMBOL Symbol, CurrentSymbol = NULL;
- BOOLEAN TextBaseValid;
- BOOLEAN Valid;
- ULONG TextBase = 0;
- ULONG Alignment = 0;
- CHAR Line[256];
- ULONG Tmp;
+ NTSTATUS Status;
+
+ *LineNumber = 0;
+
+ DPRINT("RelativeAddress %p\n", RelativeAddress);
- if (ModuleObject->Symbols.SymbolCount > 0)
+ if (RelativeAddress >= SymbolInfo->ImageSize)
{
- DPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseDllName);
- return;
+ DPRINT("Address is not within .text section. RelativeAddress %p Length 0x%x\n",
+ RelativeAddress, SymbolInfo->ImageSize);
+ return STATUS_UNSUCCESSFUL;
}
- ModuleObject->Symbols.SymbolCount = 0;
- ModuleObject->Symbols.Symbols = NULL;
- TextBaseValid = FALSE;
- Valid = FALSE;
- while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
+ if (!AreSymbolsParsed(SymbolInfo))
{
- Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &Alignment);
-
- if ((Valid) && (!TextBaseValid))
- {
- TextBase = Tmp;
- TextBaseValid = TRUE;
- }
+ LdrpParseImageSymbols(SymbolInfo);
+ }
- if (Symbol != NULL)
- {
- Symbol->RelativeAddress -= TextBase;
+ Status = LdrpGetLineNumber(SymbolInfo, RelativeAddress, LineNumber);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- if (ModuleObject->Symbols.Symbols == NULL)
- ModuleObject->Symbols.Symbols = Symbol;
- else
- CurrentSymbol->Next = Symbol;
+ if (FileName)
+ {
+ Status = LdrpGetFileName(SymbolInfo, RelativeAddress, FileName);
+ if (!NT_SUCCESS(Status))
+ {
+ strcpy(FileName, "");
+ }
+ }
- CurrentSymbol = Symbol;
+ if (FunctionName)
+ {
+ Status = LdrpGetFunctionName(SymbolInfo, RelativeAddress, FunctionName);
+ if (!NT_SUCCESS(Status))
+ {
+ strcpy(FunctionName, "");
+ }
+ }
- ModuleObject->Symbols.SymbolCount++;
- }
- }
+ return STATUS_SUCCESS;
}
-
VOID
-LdrpLoadModuleSymbols(PMODULE_OBJECT ModuleObject)
+LdrpLoadModuleSymbols(PUNICODE_STRING FileName,
+ PIMAGE_SYMBOL_INFO SymbolInfo)
{
FILE_STANDARD_INFORMATION FileStdInfo;
OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR TmpFileName[MAX_PATH];
- UNICODE_STRING Filename;
+ UNICODE_STRING SymFileName;
LPWSTR Start, Ext;
HANDLE FileHandle;
PVOID FileBuffer;
NTSTATUS Status;
ULONG Length;
IO_STATUS_BLOCK IoStatusBlock;
-
- ModuleObject->TextSection->Symbols.SymbolCount = 0;
- ModuleObject->TextSection->Symbols.Symbols = NULL;
+ PSYMBOLFILE_HEADER SymbolFileHeader;
/* Get the path to the symbol store */
wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
/* Get the symbol filename from the module name */
- Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
+ Start = wcsrchr(FileName->Buffer, L'\\');
if (Start == NULL)
- Start = ModuleObject->BaseName.Buffer;
+ Start = FileName->Buffer;
else
Start++;
- Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
+ Ext = wcsrchr(FileName->Buffer, L'.');
if (Ext != NULL)
Length = Ext - Start;
else
wcsncat(TmpFileName, Start, Length);
wcscat(TmpFileName, L".sym");
- RtlInitUnicodeString(&Filename, TmpFileName);
+ RtlInitUnicodeString(&SymFileName, TmpFileName);
/* Open the file */
InitializeObjectAttributes(&ObjectAttributes,
- &Filename,
+ &SymFileName,
0,
NULL,
NULL);
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("Could not open symbol file: %wZ\n", &Filename);
+ DPRINT("Could not open symbol file: %wZ\n", &SymFileName);
return;
}
- CPRINT("Loading symbols from %wZ...\n", &Filename);
+ CPRINT("Loading symbols from %wZ...\n", &SymFileName);
/* Get the size of the file */
Status = ZwQueryInformationFile(FileHandle,
if (!NT_SUCCESS(Status))
{
DPRINT("Could not get file size\n");
+ ZwClose(FileHandle);
return;
}
if (FileBuffer == NULL)
{
DPRINT("Could not allocate memory for symbol file\n");
+ ZwClose(FileHandle);
return;
}
0, 0);
if (!NT_SUCCESS(Status))
{
- DPRINT("Could not read symbol file into memory\n");
+ DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status);
ExFreePool(FileBuffer);
+ ZwClose(FileHandle);
return;
}
ZwClose(FileHandle);
- LdrpLoadModuleSymbolsFromBuffer(ModuleObject,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart);
-
- ExFreePool(FileBuffer);
+ SymbolFileHeader = (PSYMBOLFILE_HEADER) FileBuffer;
+ SymbolInfo->FileBuffer = FileBuffer;
+ SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->StabsOffset;
+ SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
+ SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset;
+ SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
}
VOID
-LdrLoadUserModuleSymbols(PLDR_MODULE ModuleObject)
+LdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
{
- FILE_STANDARD_INFORMATION FileStdInfo;
- OBJECT_ATTRIBUTES ObjectAttributes;
- WCHAR TmpFileName[MAX_PATH];
- UNICODE_STRING Filename;
- LPWSTR Start, Ext;
- HANDLE FileHandle;
- PVOID FileBuffer;
- NTSTATUS Status;
- ULONG Length;
- IO_STATUS_BLOCK IoStatusBlock;
+ PSYMBOL NextSymbol;
+ PSYMBOL Symbol;
- ModuleObject->Symbols.SymbolCount = 0;
- ModuleObject->Symbols.Symbols = NULL;
+ DPRINT("Unloading symbols\n");
- /* Get the path to the symbol store */
- wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
+ if (SymbolInfo != NULL)
+ {
+ Symbol = SymbolInfo->FileNameSymbols.Symbols;
+ while (Symbol != NULL)
+ {
+ NextSymbol = Symbol->Next;
+ RtlFreeAnsiString(&Symbol->Name);
+ ExFreePool(Symbol);
+ Symbol = NextSymbol;
+ }
- /* Get the symbol filename from the module name */
- Start = wcsrchr(ModuleObject->BaseDllName.Buffer, L'\\');
- if (Start == NULL)
- Start = ModuleObject->BaseDllName.Buffer;
- else
- Start++;
+ SymbolInfo->FileNameSymbols.SymbolCount = 0;
+ SymbolInfo->FileNameSymbols.Symbols = NULL;
- Ext = wcsrchr(ModuleObject->BaseDllName.Buffer, L'.');
- if (Ext != NULL)
- Length = Ext - Start;
- else
- Length = wcslen(Start);
+ Symbol = SymbolInfo->FunctionSymbols.Symbols;
+ while (Symbol != NULL)
+ {
+ NextSymbol = Symbol->Next;
+ RtlFreeAnsiString(&Symbol->Name);
+ ExFreePool(Symbol);
+ Symbol = NextSymbol;
+ }
- wcsncat(TmpFileName, Start, Length);
- wcscat(TmpFileName, L".sym");
- RtlInitUnicodeString(&Filename, TmpFileName);
+ SymbolInfo->FunctionSymbols.SymbolCount = 0;
+ SymbolInfo->FunctionSymbols.Symbols = NULL;
- /* Open the file */
- InitializeObjectAttributes(&ObjectAttributes,
- &Filename,
- 0,
- NULL,
- NULL);
+ Symbol = SymbolInfo->LineNumberSymbols.Symbols;
+ while (Symbol != NULL)
+ {
+ NextSymbol = Symbol->Next;
+ RtlFreeAnsiString(&Symbol->Name);
+ ExFreePool(Symbol);
+ Symbol = NextSymbol;
+ }
- Status = ZwOpenFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatusBlock,
- 0,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not open symbol file: %wZ\n", &Filename);
- return;
+ SymbolInfo->LineNumberSymbols.SymbolCount = 0;
+ SymbolInfo->LineNumberSymbols.Symbols = NULL;
+#if 0
+ /* Don't free buffers because we cache symbol buffers
+ (eg. they are shared across processes) */
+ /* FIXME: We can free them if we do reference counting */
+ if (SymbolInfo->FileBuffer != NULL)
+ {
+ ExFreePool(SymbolInfo->FileBuffer);
+ SymbolInfo->FileBuffer = NULL;
+ SymbolInfo->SymbolsBase = NULL;
+ SymbolInfo->SymbolsLength = 0;
+ }
+#endif
}
+}
- CPRINT("Loading symbols from %wZ...\n", &Filename);
- /* Get the size of the file */
- Status = ZwQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Could not get file size\n");
- return;
- }
+PIMAGE_SYMBOL_INFO_CACHE
+LdrpLookupUserSymbolInfo(PLDR_MODULE LdrModule)
+{
+ PIMAGE_SYMBOL_INFO_CACHE Current;
+ PLIST_ENTRY CurrentEntry;
+ KIRQL Irql;
- /* Allocate nonpageable memory for symbol file */
- FileBuffer = ExAllocatePool(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart);
+ DPRINT("Searching symbols for %S\n", LdrModule->FullDllName.Buffer);
- if (FileBuffer == NULL)
- {
- DPRINT("Could not allocate memory for symbol file\n");
- return;
- }
-
- /* Load file into memory chunk */
- Status = ZwReadFile(FileHandle,
- 0, 0, 0,
- &IoStatusBlock,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart,
- 0, 0);
- if (!NT_SUCCESS(Status))
+ KeAcquireSpinLock(&ModuleListLock,&Irql);
+
+ CurrentEntry = SymbolListHead.Flink;
+ while (CurrentEntry != (&SymbolListHead))
{
- DPRINT("Could not read symbol file into memory\n");
- ExFreePool(FileBuffer);
- return;
- }
+ Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
- ZwClose(FileHandle);
+ if (RtlEqualUnicodeString(&Current->FullName, &LdrModule->FullDllName, TRUE))
+ {
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+ return Current;
+ }
- LdrpLoadUserModuleSymbolsFromBuffer(ModuleObject,
- FileBuffer,
- FileStdInfo.EndOfFile.u.LowPart);
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ KeReleaseSpinLock(&ModuleListLock, Irql);
- ExFreePool(FileBuffer);
+ return(NULL);
}
VOID
-LdrpUnloadModuleSymbols(PMODULE_OBJECT ModuleObject)
+LdrLoadUserModuleSymbols(PLDR_MODULE LdrModule)
{
- /* FIXME: implement me! */
+ PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
+
+ DPRINT("LdrModule %p\n", LdrModule);
+
+ RtlZeroMemory(&LdrModule->SymbolInfo, sizeof(LdrModule->SymbolInfo));
+ LdrModule->SymbolInfo.ImageBase = (ULONG_PTR) LdrModule->BaseAddress;
+ LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage;
+
+ CacheEntry = LdrpLookupUserSymbolInfo(LdrModule);
+ if (CacheEntry != NULL)
+ {
+ DPRINT("Symbol cache hit for %S\n", CacheEntry->FullName.Buffer);
+
+ LdrModule->SymbolInfo.FileBuffer = CacheEntry->FileBuffer;
+ LdrModule->SymbolInfo.SymbolsBase = CacheEntry->SymbolsBase;
+ LdrModule->SymbolInfo.SymbolsLength = CacheEntry->SymbolsLength;
+ LdrModule->SymbolInfo.SymbolStringsBase = CacheEntry->SymbolStringsBase;
+ LdrModule->SymbolInfo.SymbolStringsLength = CacheEntry->SymbolStringsLength;
+ }
+ else
+ {
+ CacheEntry = ExAllocatePool(NonPagedPool, sizeof(IMAGE_SYMBOL_INFO_CACHE));
+ assert(CacheEntry);
+ RtlZeroMemory(CacheEntry, sizeof(IMAGE_SYMBOL_INFO_CACHE));
+ RtlCreateUnicodeString(&CacheEntry->FullName, LdrModule->FullDllName.Buffer);
+ assert(CacheEntry->FullName.Buffer);
+ LdrpLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo);
+ InsertTailList(&SymbolListHead, &CacheEntry->ListEntry);
+ }
}
-#endif /* KDBG */
+#endif /* DBG */
NTSTATUS
/* Cleanup */
ExFreePool(ModuleLoadBase);
-#ifdef KDBG
-
- /* Load symbols for module if available */
- LdrpLoadModuleSymbols(Module);
-
-#endif /* KDBG */
+#ifdef DBG
+ /* Load symbols for the image if available */
+ LdrpLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo);
+#endif /* DBG */
*ModuleObject = Module;
RemoveEntryList(&ModuleObject->ListEntry);
KeReleaseSpinLock(&ModuleListLock, Irql);
-#ifdef KDBG
+#ifdef DBG
/* Unload symbols for module if available */
- LdrpUnloadModuleSymbols(ModuleObject);
-#endif /* KDBG */
+ LdrUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo);
+#endif /* DBG */
/* Free text section */
if (ModuleObject->TextSection != NULL)
PCHAR FileName,
ULONG ModuleLength)
{
+#ifdef DBG
+ PSYMBOLFILE_HEADER SymbolFileHeader;
+ PIMAGE_SYMBOL_INFO SymbolInfo;
+#endif /* DBG */
PMODULE_OBJECT ModuleObject;
UNICODE_STRING ModuleName;
PDEVICE_NODE DeviceNode;
ULONG Length;
LPWSTR Start;
LPWSTR Ext;
+ PCHAR FileExt;
CHAR TextBuffer [256];
ULONG x, y, cx, cy;
-#ifdef KDBG
+#ifdef DBG
CHAR TmpBaseName[MAX_PATH];
CHAR TmpFileName[MAX_PATH];
ANSI_STRING AnsiString;
- PCHAR FileExt;
-#endif
+#endif /* DBG */
HalQueryDisplayParameters(&x, &y, &cx, &cy);
RtlFillMemory(TextBuffer, x, ' ');
HalDisplayString(TextBuffer);
HalSetDisplayParameters(cx, cy);
-#ifdef KDBG
/* Split the filename into base name and extension */
FileExt = strrchr(FileName, '.');
if (FileExt != NULL)
else
Length = strlen(FileName);
+#ifdef DBG
+
if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
{
DPRINT("Module %s is a symbol file\n", FileName);
strcat(TmpFileName, ".sys");
RtlInitAnsiString(&AnsiString, TmpFileName);
- DPRINT("dasdsad: %s\n", TmpFileName);
-
RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
ModuleObject = LdrGetModuleObject(&ModuleName);
RtlFreeUnicodeString(&ModuleName);
}
if (ModuleObject != NULL)
{
- LdrpLoadModuleSymbolsFromBuffer(ModuleObject,
- ModuleLoadBase,
- ModuleLength);
+ SymbolInfo = (PIMAGE_SYMBOL_INFO) &ModuleObject->TextSection->SymbolInfo;
+ SymbolFileHeader = (PSYMBOLFILE_HEADER) ModuleLoadBase;
+ SymbolInfo->FileBuffer = ModuleLoadBase;
+ SymbolInfo->SymbolsBase = ModuleLoadBase + SymbolFileHeader->StabsOffset;
+ SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
+ SymbolInfo->SymbolStringsBase = ModuleLoadBase + SymbolFileHeader->StabstrOffset;
+ SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
}
+
return(STATUS_SUCCESS);
}
else
{
- DPRINT("Module %s is executable\n", FileName);
+ DPRINT("Module %s is non-symbol file\n", FileName);
+ }
+
+#endif /* !DBG */
+
+ if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
+ {
+ CPRINT("Ignoring non-driver file %s\n", FileName);
+ return STATUS_SUCCESS;
}
-#endif /* KDBG */
/* Use IopRootDeviceNode for now */
Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
PESectionHeaders[Idx].VirtualAddress + DriverBase);
memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
(PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
- PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
+ PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
+ ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
}
else
{
ModuleTextSection = ExAllocatePool(NonPagedPool,
sizeof(MODULE_TEXT_SECTION));
+ assert(ModuleTextSection);
+ RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
ModuleTextSection->Base = (ULONG)DriverBase;
ModuleTextSection->Length = DriverSize;
- ModuleTextSection->SymbolsBase = NULL;
- ModuleTextSection->SymbolsLength = 0;
+#ifdef DBG
+ RtlZeroMemory(&ModuleTextSection->SymbolInfo, sizeof(ModuleTextSection->SymbolInfo));
+ ModuleTextSection->SymbolInfo.ImageBase = PEOptionalHeader->ImageBase;
+ ModuleTextSection->SymbolInfo.ImageSize = ModuleTextSection->Length;
+#endif /* DBG */
ModuleTextSection->Name =
ExAllocatePool(NonPagedPool,
(wcslen(NameBuffer) + 1) * sizeof(WCHAR));
if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
{
- DbgPrint("Module %wZ loaded at 0x%.08x.\n",
- FileName, CreatedModuleObject->Base);
+ DPRINT("Module %wZ loaded at 0x%.08x.\n",
+ FileName, CreatedModuleObject->Base);
}
return STATUS_SUCCESS;
--- /dev/null
+/*
+ * Usage: rsym input-file output-file
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NULL ((void*)0)
+
+#define IMAGE_DOS_MAGIC 0x5a4d
+#define IMAGE_PE_MAGIC 0x00004550
+
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+
+typedef void* PVOID;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef signed long LONG;
+typedef unsigned long ULONG;
+
+#pragma pack(push,2)
+typedef struct _IMAGE_DOS_HEADER {
+ WORD e_magic;
+ WORD e_cblp;
+ WORD e_cp;
+ WORD e_crlc;
+ WORD e_cparhdr;
+ WORD e_minalloc;
+ WORD e_maxalloc;
+ WORD e_ss;
+ WORD e_sp;
+ WORD e_csum;
+ WORD e_ip;
+ WORD e_cs;
+ WORD e_lfarlc;
+ WORD e_ovno;
+ WORD e_res[4];
+ WORD e_oemid;
+ WORD e_oeminfo;
+ WORD e_res2[10];
+ LONG e_lfanew;
+} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
+#pragma pack(pop)
+#pragma pack(push,4)
+typedef struct _IMAGE_DATA_DIRECTORY {
+ DWORD VirtualAddress;
+ DWORD Size;
+} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
+typedef struct _IMAGE_OPTIONAL_HEADER {
+ WORD Magic;
+ BYTE MajorLinkerVersion;
+ BYTE MinorLinkerVersion;
+ DWORD SizeOfCode;
+ DWORD SizeOfInitializedData;
+ DWORD SizeOfUninitializedData;
+ DWORD AddressOfEntryPoint;
+ DWORD BaseOfCode;
+ DWORD BaseOfData;
+ DWORD ImageBase;
+ DWORD SectionAlignment;
+ DWORD FileAlignment;
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Reserved1;
+ DWORD SizeOfImage;
+ DWORD SizeOfHeaders;
+ DWORD CheckSum;
+ WORD Subsystem;
+ WORD DllCharacteristics;
+ DWORD SizeOfStackReserve;
+ DWORD SizeOfStackCommit;
+ DWORD SizeOfHeapReserve;
+ DWORD SizeOfHeapCommit;
+ DWORD LoaderFlags;
+ DWORD NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
+typedef struct _IMAGE_FILE_HEADER {
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+typedef struct _IMAGE_SECTION_HEADER {
+ BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ DWORD PhysicalAddress;
+ DWORD VirtualSize;
+ } Misc;
+ DWORD VirtualAddress;
+ DWORD SizeOfRawData;
+ DWORD PointerToRawData;
+ DWORD PointerToRelocations;
+ DWORD PointerToLinenumbers;
+ WORD NumberOfRelocations;
+ WORD NumberOfLinenumbers;
+ DWORD Characteristics;
+} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
+#pragma pack(pop)
+
+typedef struct _SYMBOLFILE_HEADER {
+ unsigned long StabsOffset;
+ unsigned long StabsLength;
+ unsigned long StabstrOffset;
+ unsigned long StabstrLength;
+} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
+
+
+char* convert_path(char* origpath)
+{
+ char* newpath;
+ int i;
+
+ newpath = strdup(origpath);
+
+ i = 0;
+ while (newpath[i] != 0)
+ {
+#ifdef UNIX_PATHS
+ if (newpath[i] == '\\')
+ {
+ newpath[i] = '/';
+ }
+#else
+#ifdef DOS_PATHS
+ if (newpath[i] == '/')
+ {
+ newpath[i] = '\\';
+ }
+#endif
+#endif
+ i++;
+ }
+ return(newpath);
+}
+
+#define TRANSFER_SIZE (65536)
+
+int main(int argc, char* argv[])
+{
+ SYMBOLFILE_HEADER SymbolFileHeader;
+ IMAGE_DOS_HEADER PEDosHeader;
+ IMAGE_FILE_HEADER PEFileHeader;
+ PIMAGE_SECTION_HEADER PESectionHeaders;
+ PVOID SymbolsBase;
+ ULONG SymbolsLength;
+ PVOID SymbolStringsBase;
+ ULONG SymbolStringsLength;
+ ULONG Idx;
+ char* path1;
+ char* path2;
+ FILE* in;
+ FILE* out;
+ char* buf;
+ int n_in;
+ int n_out;
+
+ if (argc != 3)
+ {
+ fprintf(stderr, "Too many arguments\n");
+ exit(1);
+ }
+
+ path1 = convert_path(argv[1]);
+ path2 = convert_path(argv[2]);
+
+ in = fopen(path1, "rb");
+ if (in == NULL)
+ {
+ perror("Cannot open input file");
+ exit(1);
+ }
+
+ out = fopen(path2, "wb");
+ if (out == NULL)
+ {
+ perror("Cannot open output file");
+ fclose(in);
+ exit(1);
+ }
+
+ /* Check if MZ header exists */
+ n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in);
+ if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L)
+ {
+ perror("Input file is not a PE image.\n");
+ }
+
+ /* Read PE file header */
+ /* sizeof(ULONG) = sizeof(MAGIC) */
+ fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
+ n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in);
+
+ /* Read PE section headers */
+ PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
+ fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)
+ + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET);
+ n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in);
+
+ /* Copy .stab and .stabstr sections if available */
+ SymbolsBase = NULL;
+ SymbolsLength = 0;
+ SymbolStringsBase = NULL;
+ SymbolStringsLength = 0;
+
+ for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++)
+ {
+ //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
+ if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0)
+ && (PESectionHeaders[Idx].Name[5] == 0))
+ {
+ //printf(".stab section found. Size %d\n",
+ // PESectionHeaders[Idx].SizeOfRawData);
+
+ SymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
+ SymbolsBase = malloc(SymbolsLength);
+
+ fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
+ n_in = fread(SymbolsBase, 1, SymbolsLength, in);
+ }
+
+ if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
+ {
+ //printf(".stabstr section found. Size %d\n",
+ // PESectionHeaders[Idx].SizeOfRawData);
+
+ SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData;
+ SymbolStringsBase = malloc(SymbolStringsLength);
+
+ fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
+ n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in);
+ }
+ }
+
+ SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
+ SymbolFileHeader.StabsLength = SymbolsLength;
+ SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength;
+ SymbolFileHeader.StabstrLength = SymbolStringsLength;
+
+ n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
+ n_out = fwrite(SymbolsBase, 1, SymbolsLength, out);
+ n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out);
+
+ exit(0);
+}