--- trunk/reactos/ntoskrnl/dbg/kdb_symbols.c 2005-01-08 23:36:03 UTC (rev 12894)
+++ trunk/reactos/ntoskrnl/dbg/kdb_symbols.c 2005-01-09 00:00:31 UTC (rev 12895)
@@ -17,6 +17,34 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
+ * Parts of this file based on work Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/dbg/kdb_symbols.c
* PURPOSE: Getting symbol information...
@@ -41,6 +69,7 @@
#include <internal/safe.h>
#include <internal/kd.h>
#include <rosrtl/string.h>
+#include <coff.h>
#define NDEBUG
#include <internal/debug.h>
@@ -55,6 +84,10 @@
ULONG StabsLength;
ULONG StabstrOffset;
ULONG StabstrLength;
+ ULONG SymbolsOffset;
+ ULONG SymbolsLength;
+ ULONG SymbolstrOffset;
+ ULONG SymbolstrLength;
} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
typedef struct _IMAGE_SYMBOL_INFO_CACHE {
@@ -62,6 +95,10 @@
ULONG RefCount;
UNICODE_STRING FileName;
PVOID FileBuffer;
+ PVOID StabsBase;
+ ULONG StabsLength;
+ PVOID StabStringsBase;
+ ULONG StabStringsLength;
PVOID SymbolsBase;
ULONG SymbolsLength;
PVOID SymbolStringsBase;
@@ -282,7 +319,68 @@
return TRUE;
}
+/*! \brief Find a COFF symbol entry...
+ *
+ * Finds the COFF symbol as close as possible before the specified address
+ *
+ * \param SymbolInfo Pointer to the symbol info.
+ * \param RelativeAddress Relative address of address to look for.
+ *
+ * \returns Pointer to a external_syment
+ * \retval NULL No entry found.
+ */
+static struct external_syment *
+KdbpSymbolsFindEntry(IN PIMAGE_SYMBOL_INFO SymbolInfo,
+ 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.
+ */
+ struct external_syment *Base = (struct external_syment *) SymbolInfo->SymbolsBase;
+ ULONG Lim;
+ struct external_syment *Mid, *Low;
+ if (SymbolInfo->SymbolsLength < sizeof(struct external_syment)
+ || RelativeAddress < Base->e_value)
+ {
+ return NULL;
+ }
+
+ Low = Base;
+ for (Lim = SymbolInfo->SymbolsLength / sizeof(struct external_syment); Lim != 0; Lim >>= 1)
+ {
+ Mid = Base + (Lim >> 1);
+ if (RelativeAddress == Mid->e_value)
+ {
+ return Mid;
+ }
+ if (Mid->e_value < RelativeAddress) /* key > mid: move right */
+ {
+ Low = Mid;
+ Base = Mid + 1;
+ Lim--;
+ } /* else move left */
+ }
+
+ ASSERT(Low->e_value < RelativeAddress);
+
+ return Low;
+}
+
+
/*! \brief Get information for an address (source file, line number,
* function name)
*
@@ -306,12 +404,13 @@
OUT PCH FileName OPTIONAL,
OUT PCH FunctionName OPTIONAL)
{
- PSTAB_ENTRY FunctionEntry = NULL, FileEntry = NULL, LineEntry = NULL;
+ PSTAB_ENTRY StabsFunctionEntry = NULL, FileEntry = NULL, LineEntry = NULL;
+ struct external_syment *SymbolsFunctionEntry = NULL;
DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress);
- if (SymbolInfo->SymbolsBase == NULL || SymbolInfo->SymbolsLength == 0 ||
- SymbolInfo->SymbolStringsBase == NULL || SymbolInfo->SymbolStringsLength == 0)
+ if (SymbolInfo->StabsBase == NULL || SymbolInfo->StabsLength == 0 ||
+ SymbolInfo->StabStringsBase == NULL || SymbolInfo->StabStringsLength == 0)
{
return STATUS_UNSUCCESSFUL;
}
@@ -330,24 +429,24 @@
if (LineNumber != NULL || FunctionName != NULL)
{
/* find stab entry for function */
- FunctionEntry = KdbpStabFindEntry(SymbolInfo, N_FUN, (PVOID)RelativeAddress, NULL);
- if (FunctionEntry == NULL)
+ StabsFunctionEntry = KdbpStabFindEntry(SymbolInfo, N_FUN, (PVOID)RelativeAddress, NULL);
+ if (StabsFunctionEntry == NULL)
{
DPRINT("No function stab entry found. RelativeAddress %p\n", RelativeAddress);
}
- if (LineNumber != NULL && FunctionEntry != NULL)
+ if (LineNumber != NULL && StabsFunctionEntry != NULL)
{
/* find stab entry for line number */
- ULONG_PTR FunctionRelativeAddress = RelativeAddress - FunctionEntry->n_value;
+ ULONG_PTR FunctionRelativeAddress = RelativeAddress - StabsFunctionEntry->n_value;
ULONG_PTR AddrFound = 0;
PSTAB_ENTRY NextLineEntry;
- LineEntry = NextLineEntry = FunctionEntry;
+ LineEntry = NextLineEntry = StabsFunctionEntry;
while (NextLineEntry != NULL)
{
NextLineEntry++;
- if ((ULONG_PTR)NextLineEntry >= ((ULONG_PTR)SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength))
+ if ((ULONG_PTR)NextLineEntry >= ((ULONG_PTR)SymbolInfo->StabsBase + SymbolInfo->StabsLength))
break;
if (NextLineEntry->n_type == N_FUN)
break;
@@ -364,6 +463,14 @@
}
}
+ if (FunctionName != NULL
+ && SymbolInfo->SymbolsBase != NULL && SymbolInfo->SymbolsLength != 0
+ && SymbolInfo->SymbolStringsBase != NULL && SymbolInfo->SymbolStringsLength != 0)
+ {
+ /* find symbol entry for function */
+ SymbolsFunctionEntry = KdbpSymbolsFindEntry(SymbolInfo, RelativeAddress);
+ }
+
if (FileName != NULL)
{
/* find stab entry for file name */
@@ -373,7 +480,7 @@
FileEntry = KdbpStabFindEntry(SymbolInfo, N_SO, (PVOID)RelativeAddress, NULL);
if (FileEntry != NULL)
{
- p = (PCHAR)SymbolInfo->SymbolStringsBase + FileEntry->n_strx;
+ p = (PCHAR)SymbolInfo->StabStringsBase + FileEntry->n_strx;
Length = strlen(p);
if (p[Length - 1] == '/' || p[Length - 1] == '\\') /* source dir */
FileEntry = KdbpStabFindEntry(SymbolInfo, N_SO, (PVOID)RelativeAddress, FileEntry + 1);
@@ -384,9 +491,10 @@
}
}
- if (((LineNumber != NULL && LineEntry == NULL) || LineNumber == NULL) &&
- ((FileName != NULL && FileEntry == NULL) || FileName == NULL) &&
- ((FunctionName != NULL && FunctionEntry == NULL) || FunctionName == NULL))
+ if (((LineNumber != NULL && LineEntry == NULL) || LineNumber == NULL) &&
+ ((FileName != NULL && FileEntry == NULL) || FileName == NULL) &&
+ ((FunctionName != NULL && StabsFunctionEntry == NULL && SymbolsFunctionEntry == NULL) ||
+ FunctionName == NULL))
{
DPRINT("None of the requested information was found!\n");
return STATUS_UNSUCCESSFUL;
@@ -403,18 +511,56 @@
PCHAR Name = "";
if (FileEntry != NULL)
{
- Name = (PCHAR)SymbolInfo->SymbolStringsBase + FileEntry->n_strx;
+ Name = (PCHAR)SymbolInfo->StabStringsBase + FileEntry->n_strx;
}
strcpy(FileName, Name);
}
if (FunctionName != NULL)
{
PCHAR Name = "", p;
- if (FunctionEntry != NULL)
- Name = (PCHAR)SymbolInfo->SymbolStringsBase + FunctionEntry->n_strx;
- strcpy(FunctionName, Name);
- if ((p = strchr(FunctionName, ':')) != NULL) /* remove extra info from function name */
- *p = '\0';
+ if (StabsFunctionEntry != NULL)
+ {
+ if (SymbolsFunctionEntry == NULL ||
+ SymbolsFunctionEntry->e_value <= StabsFunctionEntry->n_value)
+ {
+ Name = (PCHAR)SymbolInfo->StabStringsBase + StabsFunctionEntry->n_strx;
+ strcpy(FunctionName, Name);
+ if ((p = strchr(FunctionName, ':')) != NULL) /* remove extra info from function name */
+ {
+ *p = '\0';
+ }
+ }
+ else if (SymbolsFunctionEntry != NULL)
+ {
+ if (SymbolsFunctionEntry->e.e.e_zeroes == 0)
+ {
+ Name = (PCHAR) SymbolInfo->SymbolStringsBase + SymbolsFunctionEntry->e.e.e_offset;
+ strcpy(FunctionName, Name);
+ }
+ else
+ {
+ memcpy(FunctionName, SymbolsFunctionEntry->e.e_name, E_SYMNMLEN);
+ FunctionName[E_SYMNMLEN] = '\0';
+ }
+ }
+ }
+ else if (SymbolsFunctionEntry != NULL)
+ {
+ if (SymbolsFunctionEntry->e.e.e_zeroes == 0)
+ {
+ Name = (PCHAR) SymbolInfo->SymbolStringsBase + SymbolsFunctionEntry->e.e.e_offset;
+ strcpy(FunctionName, Name);
+ }
+ else
+ {
+ memcpy(FunctionName, SymbolsFunctionEntry->e.e_name, E_SYMNMLEN);
+ FunctionName[E_SYMNMLEN] = '\0';
+ }
+ }
+ else
+ {
+ FunctionName[0] = '\0';
+ }
}
return STATUS_SUCCESS;
@@ -449,14 +595,14 @@
FileNameLength = strlen(FileName);
FuncNameLength = strlen(FuncName);
- for (Entry = SymbolInfo->SymbolsBase;
- (ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength);
+ for (Entry = SymbolInfo->StabsBase;
+ (ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->StabsBase + SymbolInfo->StabsLength);
Entry++)
{
if (Entry->n_type != N_SO)
continue;
- SymbolName = (PCHAR)SymbolInfo->SymbolStringsBase + Entry->n_strx;
+ SymbolName = (PCHAR)SymbolInfo->StabStringsBase + Entry->n_strx;
Length = strlen(SymbolName);
if (SymbolName[Length - 1] == '/' ||
SymbolName[Length - 1] == '\\')
@@ -473,7 +619,7 @@
continue;
Entry++;
- for (;(ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength);
+ for (;(ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->StabsBase + SymbolInfo->StabsLength);
Entry++)
{
if (Entry->n_type == N_FUN)
@@ -487,7 +633,7 @@
continue;
else /* if (FunctionName != NULL) */
{
- SymbolName = (PCHAR)SymbolInfo->SymbolStringsBase + Entry->n_strx;
+ SymbolName = (PCHAR)SymbolInfo->StabStringsBase + Entry->n_strx;
p = strchr(SymbolName, ':');
if (p == NULL)
return FALSE;
@@ -589,6 +735,10 @@
ASSERT(CacheEntry->FileName.Buffer);
CacheEntry->RefCount = 1;
CacheEntry->FileBuffer = SymbolInfo->FileBuffer;
+ CacheEntry->StabsBase = SymbolInfo->StabsBase;
+ CacheEntry->StabsLength = SymbolInfo->StabsLength;
+ CacheEntry->StabStringsBase = SymbolInfo->StabStringsBase;
+ CacheEntry->StabStringsLength = SymbolInfo->StabStringsLength;
CacheEntry->SymbolsBase = SymbolInfo->SymbolsBase;
CacheEntry->SymbolsLength = SymbolInfo->SymbolsLength;
CacheEntry->SymbolStringsBase = SymbolInfo->SymbolStringsBase;
@@ -692,6 +842,10 @@
{
DPRINT("Found cached symbol file %wZ\n", &SymFileName);
SymbolInfo->FileBuffer = CachedSymbolFile->FileBuffer;
+ SymbolInfo->StabsBase = CachedSymbolFile->StabsBase;
+ SymbolInfo->StabsLength = CachedSymbolFile->StabsLength;
+ SymbolInfo->StabStringsBase = CachedSymbolFile->StabStringsBase;
+ SymbolInfo->StabStringsLength = CachedSymbolFile->StabStringsLength;
SymbolInfo->SymbolsBase = CachedSymbolFile->SymbolsBase;
SymbolInfo->SymbolsLength = CachedSymbolFile->SymbolsLength;
SymbolInfo->SymbolStringsBase = CachedSymbolFile->SymbolStringsBase;
@@ -769,16 +923,23 @@
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;
+ SymbolInfo->StabsBase = FileBuffer + SymbolFileHeader->StabsOffset;
+ SymbolInfo->StabsLength = SymbolFileHeader->StabsLength;
+ SymbolInfo->StabStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset;
+ SymbolInfo->StabStringsLength = SymbolFileHeader->StabstrLength;
+ SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->SymbolsOffset;
+ SymbolInfo->SymbolsLength = SymbolFileHeader->SymbolsLength;
+ SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->SymbolstrOffset;
+ SymbolInfo->SymbolStringsLength = SymbolFileHeader->SymbolstrLength;
/* add file to cache */
KdbpSymAddCachedFile(&SymFileName, SymbolInfo);
- DPRINT("Installed stabs: %wZ (%08x-%08x,%08x)\n",
+ DPRINT("Installed stabs: %wZ (%08x-%08x,%08x) (%08x-%08x,%08x)\n",
FileName,
+ SymbolInfo->StabsBase,
+ SymbolInfo->StabsLength + SymbolInfo->StabsBase,
+ SymbolInfo->StabStringsBase,
SymbolInfo->SymbolsBase,
SymbolInfo->SymbolsLength + SymbolInfo->SymbolsBase,
SymbolInfo->SymbolStringsBase);
@@ -800,6 +961,8 @@
{
KdbpSymRemoveCachedFile(SymbolInfo);
SymbolInfo->FileBuffer = NULL;
+ SymbolInfo->StabsBase = NULL;
+ SymbolInfo->StabsLength = 0;
SymbolInfo->SymbolsBase = NULL;
SymbolInfo->SymbolsLength = 0;
}
@@ -955,10 +1118,14 @@
KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
SymbolInfo->FileBuffer = SymbolFileHeader;
- SymbolInfo->SymbolsBase = (PVOID)SymbolFileHeader + SymbolFileHeader->StabsOffset;
- SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
- SymbolInfo->SymbolStringsBase = (PVOID)SymbolFileHeader + SymbolFileHeader->StabstrOffset;
- SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
+ SymbolInfo->StabsBase = (PVOID)SymbolFileHeader + SymbolFileHeader->StabsOffset;
+ SymbolInfo->StabsLength = SymbolFileHeader->StabsLength;
+ SymbolInfo->StabStringsBase = (PVOID)SymbolFileHeader + SymbolFileHeader->StabstrOffset;
+ SymbolInfo->StabStringsLength = SymbolFileHeader->StabstrLength;
+ SymbolInfo->SymbolsBase = (PVOID)SymbolFileHeader + SymbolFileHeader->SymbolsOffset;
+ SymbolInfo->SymbolsLength = SymbolFileHeader->SymbolsLength;
+ SymbolInfo->SymbolStringsBase = (PVOID)SymbolFileHeader + SymbolFileHeader->SymbolstrOffset;
+ SymbolInfo->SymbolStringsLength = SymbolFileHeader->SymbolstrLength;
/* add file to cache */
RtlInitAnsiString(&AnsiString, SymbolName);
@@ -966,10 +1133,13 @@
KdbpSymAddCachedFile(&UnicodeString, SymbolInfo);
RtlFreeUnicodeString(&UnicodeString);
- DPRINT("Installed stabs: %s@%08x-%08x (%08x-%08x,%08x)\n",
+ DPRINT("Installed stabs: %s@%08x-%08x (%08x-%08x,%08x) (%08x-%08x,%08x)\n",
FileName,
ModuleObject->Base,
ModuleObject->Length + ModuleObject->Base,
+ SymbolInfo->StabsBase,
+ SymbolInfo->StabsLength + SymbolInfo->StabsBase,
+ SymbolInfo->StabStringsBase,
SymbolInfo->SymbolsBase,
SymbolInfo->SymbolsLength + SymbolInfo->SymbolsBase,
SymbolInfo->SymbolStringsBase);
--- trunk/reactos/tools/rsym.c 2005-01-08 23:36:03 UTC (rev 12894)
+++ trunk/reactos/tools/rsym.c 2005-01-09 00:00:31 UTC (rev 12895)
@@ -111,6 +111,10 @@
unsigned long StabsLength;
unsigned long StabstrOffset;
unsigned long StabstrLength;
+ unsigned long SymbolsOffset;
+ unsigned long SymbolsLength;
+ unsigned long SymbolstrOffset;
+ unsigned long SymbolstrLength;
} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
typedef struct _STAB_ENTRY {
@@ -133,6 +137,83 @@
unsigned long Length;
} STR_ENTRY, *PSTR_ENTRY;
+/* COFF symbol table */
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+/* derived types, in e_type */
+#define DT_NON (0) /* no derived type */
+#define DT_PTR (1) /* pointer */
+#define DT_FCN (2) /* function */
+#define DT_ARY (3) /* array */
+
+#define BTYPE(x) ((x) & N_BTMASK)
+
+#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
+#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
+#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
+#define ISTAG(x) ((x)==C_STRTAG||(x)==C_UNTAG||(x)==C_ENTAG)
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+
+#define C_EFCN 0xff /* physical end of function */
+#define C_NULL 0
+#define C_AUTO 1 /* automatic variable */
+#define C_EXT 2 /* external symbol */
+#define C_STAT 3 /* static */
+#define C_REG 4 /* register variable */
+#define C_EXTDEF 5 /* external definition */
+#define C_LABEL 6 /* label */
+#define C_ULABEL 7 /* undefined label */
+#define C_MOS 8 /* member of structure */
+#define C_ARG 9 /* function argument */
+#define C_STRTAG 10 /* structure tag */
+#define C_MOU 11 /* member of union */
+#define C_UNTAG 12 /* union tag */
+#define C_TPDEF 13 /* type definition */
+#define C_USTATIC 14 /* undefined static */
+#define C_ENTAG 15 /* enumeration tag */
+#define C_MOE 16 /* member of enumeration */
+#define C_REGPARM 17 /* register parameter */
+#define C_FIELD 18 /* bit field */
+#define C_AUTOARG 19 /* auto argument */
+#define C_LASTENT 20 /* dummy entry (end of block) */
+#define C_BLOCK 100 /* ".bb" or ".eb" */
+#define C_FCN 101 /* ".bf" or ".ef" */
+#define C_EOS 102 /* end of structure */
+#define C_FILE 103 /* file name */
+#define C_LINE 104 /* line # reformatted as symbol table entry */
+#define C_ALIAS 105 /* duplicate tag */
+#define C_HIDDEN 106 /* ext symbol in dmert public lib */
+
+#pragma pack(push,1)
+typedef struct _EXTERNAL_SYMENT
+{
+ 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;
+} EXTERNAL_SYMENT, *PEXTERNAL_SYMENT;
+#pragma pack(pop)
+
char* convert_path(char* origpath)
{
char* newpath;
@@ -161,6 +242,52 @@
return(newpath);
}
+static void
+RelocateString(ULONG *Offset, PSTR_ENTRY StrEntry, ULONG *StrCount, PVOID SymbolStringsBase)
+{
+ ULONG i;
+
+ for (i = 0; i < *StrCount; i++)
+ {
+ if (*Offset == StrEntry[i].OldOffset)
+ {
+ *Offset = StrEntry[i].NewOffset;
+ return;
+ }
+ }
+
+ StrEntry[*StrCount].OldOffset = *Offset;
+ StrEntry[*StrCount].Name = (char*) SymbolStringsBase + StrEntry[*StrCount].OldOffset;
+ StrEntry[*StrCount].Length = strlen(StrEntry[*StrCount].Name) + 1;
+ if (*StrCount == 0)
+ {
+ StrEntry[*StrCount].NewOffset = 0;
+ }
+ else
+ {
+ StrEntry[*StrCount].NewOffset = StrEntry[*StrCount - 1].NewOffset
+ + StrEntry[*StrCount - 1].Length;
+ }
+ *Offset = StrEntry[*StrCount].NewOffset;
+ (*StrCount)++;
+}
+
+static int
+CompareSyment(const PEXTERNAL_SYMENT SymEntry1, const PEXTERNAL_SYMENT SymEntry2)
+{
+ if (SymEntry1->e_value < SymEntry2->e_value)
+ {
+ return -1;
+ }
+
+ if (SymEntry2->e_value < SymEntry1->e_value)
+ {
+ return +1;
+ }
+
+ return 0;
+}
+
#define TRANSFER_SIZE (65536)
int main(int argc, char* argv[])
@@ -175,6 +302,10 @@
ULONG SymbolsLength;
PVOID SymbolStringsBase;
ULONG SymbolStringsLength;
+ PVOID CoffSymbolsBase;
+ ULONG CoffSymbolsLength;
+ PVOID CoffSymbolStringsBase;
+ ULONG CoffSymbolStringsLength;
ULONG Idx;
char* path1;
char* path2;
@@ -188,31 +319,34 @@
ULONG SymbolsCount;
PSTR_ENTRY StrEntry;
ULONG StrCount;
- ULONG j;
+ PSTR_ENTRY CoffStrEntry;
+ ULONG CoffStrCount;
+ PEXTERNAL_SYMENT SymEntry;
+ unsigned NumAux;
- if (argc != 3)
- {
- fprintf(stderr, "Too many arguments\n");
- exit(1);
- }
+ if (argc != 3)
+ {
+ fprintf(stderr, "Too many arguments\n");
+ exit(1);
+ }
- path1 = convert_path(argv[1]);
- path2 = convert_path(argv[2]);
+ path1 = convert_path(argv[1]);
+ path2 = convert_path(argv[2]);
- in = fopen(path1, "rb");
- if (in == NULL)
- {
- perror("Cannot open input file");
- exit(1);
- }
+ 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);
- }
+ 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);
@@ -302,30 +436,7 @@
for (i = 0; i < Count; i++)
{
- for (j = 0; j < StrCount; j++)
- {
- if (StabEntry[i].n_strx == StrEntry[j].OldOffset)
- {
- StabEntry[i].n_strx = StrEntry[j].NewOffset;
- break;
- }
- }
- if (j >= StrCount)
- {
- StrEntry[StrCount].OldOffset = StabEntry[i].n_strx;
- StrEntry[StrCount].Name = (char*)SymbolStringsBase + StrEntry[StrCount].OldOffset;
- StrEntry[StrCount].Length = strlen(StrEntry[StrCount].Name) + 1;
- if (StrCount == 0)
- {
- StrEntry[StrCount].NewOffset = 0;
- }
- else
- {
- StrEntry[StrCount].NewOffset = StrEntry[StrCount-1].NewOffset + StrEntry[StrCount-1].Length;
- }
- StabEntry[i].n_strx = StrEntry[StrCount].NewOffset;
- StrCount++;
- }
+ RelocateString(&StabEntry[i].n_strx, StrEntry, &StrCount, SymbolStringsBase);
}
SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
@@ -333,12 +444,93 @@
SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolFileHeader.StabsLength;
SymbolFileHeader.StabstrLength = StrEntry[StrCount-1].NewOffset + StrEntry[StrCount-1].Length;
+ if (0 == PEFileHeader.PointerToSymbolTable || 0 == PEFileHeader.NumberOfSymbols)
+ {
+ /* No COFF symbol table */
+ SymbolFileHeader.SymbolsOffset = 0;
+ SymbolFileHeader.SymbolsLength = 0;
+ SymbolFileHeader.SymbolstrOffset = 0;
+ SymbolFileHeader.SymbolstrLength = 0;
+ }
+ else
+ {
+ CoffSymbolsLength = PEFileHeader.NumberOfSymbols * sizeof(EXTERNAL_SYMENT);
+ CoffSymbolsBase = malloc(CoffSymbolsLength);
+ if (NULL == CoffSymbolsBase)
+ {
+ fprintf(stderr, "Unable to allocate %u bytes for COFF symbols\n",
+ (unsigned) CoffSymbolsLength);
+ exit(1);
+ }
+ fseek(in, PEFileHeader.PointerToSymbolTable, SEEK_SET);
+ n_in = fread(CoffSymbolsBase, 1, CoffSymbolsLength, in);
+
+ SymEntry = CoffSymbolsBase;
+ Count = 0;
+ for (i = 0; i < PEFileHeader.NumberOfSymbols; i++)
+ {
+ NumAux = SymEntry[i].e_numaux;
+ if (ISFCN(SymEntry[i].e_type))
+ {
+ SymEntry[Count] = SymEntry[i];
+ if (0 < SymEntry[Count].e_scnum)
+ {
+ if (PEFileHeader.NumberOfSections < SymEntry[Count].e_scnum)
+ {
+ fprintf(stderr, "Invalid section number %d in COFF symbols (only %d sections present)\n",
+ SymEntry[Count].e_scnum, PEFileHeader.NumberOfSections);
+ exit(1);
+ }
+ SymEntry[Count].e_value += PESectionHeaders[SymEntry[Count].e_scnum - 1].VirtualAddress;
+ SymEntry[Count].e_scnum = -3;
+ SymEntry[Count].e_numaux = 0;
+ }
+ Count++;
+ }
+ i += NumAux;
+ }
+
+ qsort(CoffSymbolsBase, Count, sizeof(EXTERNAL_SYMENT), (int (*)(const void *, const void *)) CompareSyment);
+
+ n_in = fread(&CoffSymbolStringsLength, 1, sizeof(ULONG), in);
+ CoffSymbolStringsBase = malloc(CoffSymbolStringsLength);
+ if (NULL == CoffSymbolStringsBase)
+ {
+ fprintf(stderr, "Unable to allocate %u bytes for COFF symbol strings\n",
+ (unsigned) CoffSymbolStringsLength);
+ exit(1);
+ }
+ n_in = fread((char *) CoffSymbolStringsBase + sizeof(ULONG), 1, CoffSymbolStringsLength - 4, in);
+
+ CoffStrEntry = malloc(sizeof(STR_ENTRY) * Count);
+ CoffStrCount = 0;
+
+ for (i = 0; i < Count; i++)
+ {
+ if (0 == SymEntry[i].e.e.e_zeroes)
+ {
+ RelocateString(&SymEntry[i].e.e.e_offset, CoffStrEntry, &CoffStrCount, CoffSymbolStringsBase);
+ }
+ }
+
+ SymbolFileHeader.SymbolsOffset = SymbolFileHeader.StabstrOffset + SymbolFileHeader.StabstrLength;
+ SymbolFileHeader.SymbolsLength = Count * sizeof(EXTERNAL_SYMENT);
+ SymbolFileHeader.SymbolstrOffset = SymbolFileHeader.SymbolsOffset + SymbolFileHeader.SymbolsLength;
+ SymbolFileHeader.SymbolstrLength = CoffStrEntry[CoffStrCount - 1].NewOffset
+ + CoffStrEntry[CoffStrCount - 1].Length;
+ }
+
n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
n_out = fwrite(SymbolsBase, 1, SymbolFileHeader.StabsLength, out);
for (i = 0; i < StrCount; i++)
{
fwrite(StrEntry[i].Name, 1, StrEntry[i].Length, out);
}
+ n_out = fwrite(CoffSymbolsBase, 1, SymbolFileHeader.SymbolsLength, out);
+ for (i = 0; i < CoffStrCount; i++)
+ {
+ fwrite(CoffStrEntry[i].Name, 1, CoffStrEntry[i].Length, out);
+ }
fclose(out);
exit(0);