Include COFF symbols in our .sym files

svn path=/trunk/; revision=12895
This commit is contained in:
Gé van Geldorp 2005-01-09 00:00:31 +00:00
parent ad6ee8a5e1
commit 5637b9f123
5 changed files with 447 additions and 94 deletions

View file

@ -6,12 +6,6 @@
extern "C" {
#endif
/*
* #ifndef __dj_ENFORCE_ANSI_FREESTANDING
* #ifndef __STRICT_ANSI__
* #ifndef _POSIX_SOURCE
*/
/*** coff information for Intel 386/486. */
/********************** FILE HEADER **********************/
@ -329,13 +323,6 @@ struct external_reloc {
/* For new sections we havn't heard of before */
#define DEFAULT_SECTION_ALIGNMENT 4
/*
* #endif /* !_POSIX_SOURCE */
* #endif /* !__STRICT_ANSI__ */
* #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */
*/
#ifndef __dj_ENFORCE_FUNCTION_CALLS
#endif /* !__dj_ENFORCE_FUNCTION_CALLS */
#ifdef __cplusplus
}

View file

@ -8,6 +8,10 @@ typedef struct _IMAGE_SYMBOL_INFO
ULONG_PTR ImageBase;
ULONG_PTR ImageSize;
PVOID FileBuffer;
PVOID StabsBase;
ULONG StabsLength;
PVOID StabStringsBase;
ULONG StabStringsLength;
PVOID SymbolsBase;
ULONG SymbolsLength;
PVOID SymbolStringsBase;

View file

@ -69,8 +69,8 @@ KdbpStabFindEntry(IN PIMAGE_SYMBOL_INFO SymbolInfo,
PVOID StabsEnd;
ULONG_PTR AddrFound = 0;
StabEntry = SymbolInfo->SymbolsBase;
StabsEnd = (PVOID)((ULONG_PTR)SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength);
StabEntry = SymbolInfo->StabsBase;
StabsEnd = (PVOID)((ULONG_PTR)SymbolInfo->StabsBase + SymbolInfo->StabsLength);
if (StartEntry != NULL)
{
ASSERT((ULONG_PTR)StartEntry >= (ULONG_PTR)StabEntry);

View file

@ -16,6 +16,34 @@
* along with this program; if not, write to the Free Software
* 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
@ -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 @@ typedef struct _SYMBOLFILE_HEADER {
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 @@ typedef struct _IMAGE_SYMBOL_INFO_CACHE {
ULONG RefCount;
UNICODE_STRING FileName;
PVOID FileBuffer;
PVOID StabsBase;
ULONG StabsLength;
PVOID StabStringsBase;
ULONG StabStringsLength;
PVOID SymbolsBase;
ULONG SymbolsLength;
PVOID SymbolStringsBase;
@ -282,6 +319,67 @@ KdbSymPrintAddress(IN PVOID Address)
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 @@ KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
}
}
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 @@ KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
}
}
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 @@ KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo,
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 @@ KdbpSymAddCachedFile(IN PUNICODE_STRING FileName,
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 @@ KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName,
{
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 @@ KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName,
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 @@ KdbpSymUnloadModuleSymbols(IN PIMAGE_SYMBOL_INFO SymbolInfo)
{
KdbpSymRemoveCachedFile(SymbolInfo);
SymbolInfo->FileBuffer = NULL;
SymbolInfo->StabsBase = NULL;
SymbolInfo->StabsLength = 0;
SymbolInfo->SymbolsBase = NULL;
SymbolInfo->SymbolsLength = 0;
}
@ -955,10 +1118,14 @@ KdbSymProcessBootSymbols(IN PCHAR FileName)
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 @@ KdbSymProcessBootSymbols(IN PCHAR FileName)
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);

View file

@ -111,6 +111,10 @@ typedef struct _SYMBOLFILE_HEADER {
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 @@ typedef struct
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 @@ char* convert_path(char* origpath)
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 @@ int main(int argc, char* argv[])
ULONG SymbolsLength;
PVOID SymbolStringsBase;
ULONG SymbolStringsLength;
PVOID CoffSymbolsBase;
ULONG CoffSymbolsLength;
PVOID CoffSymbolStringsBase;
ULONG CoffSymbolStringsLength;
ULONG Idx;
char* path1;
char* path2;
@ -188,31 +319,34 @@ int main(int argc, char* argv[])
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 @@ int main(int argc, char* argv[])
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 @@ int main(int argc, char* argv[])
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);