Include COFF symbols in our .sym files
Modified: trunk/reactos/include/coff.h
Modified: trunk/reactos/include/ntos/kdbgsyms.h
Modified: trunk/reactos/ntoskrnl/dbg/kdb_stabs.c
Modified: trunk/reactos/ntoskrnl/dbg/kdb_symbols.c
Modified: trunk/reactos/tools/rsym.c

Modified: trunk/reactos/include/coff.h
--- trunk/reactos/include/coff.h	2005-01-08 23:36:03 UTC (rev 12894)
+++ trunk/reactos/include/coff.h	2005-01-09 00:00:31 UTC (rev 12895)
@@ -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 @@
 /* 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
 }

Modified: trunk/reactos/include/ntos/kdbgsyms.h
--- trunk/reactos/include/ntos/kdbgsyms.h	2005-01-08 23:36:03 UTC (rev 12894)
+++ trunk/reactos/include/ntos/kdbgsyms.h	2005-01-09 00:00:31 UTC (rev 12895)
@@ -8,6 +8,10 @@
   ULONG_PTR ImageBase;
   ULONG_PTR ImageSize;
   PVOID FileBuffer;
+  PVOID StabsBase;
+  ULONG StabsLength;
+  PVOID StabStringsBase;
+  ULONG StabStringsLength;
   PVOID SymbolsBase;
   ULONG SymbolsLength;
   PVOID SymbolStringsBase;

Modified: trunk/reactos/ntoskrnl/dbg/kdb_stabs.c
--- trunk/reactos/ntoskrnl/dbg/kdb_stabs.c	2005-01-08 23:36:03 UTC (rev 12894)
+++ trunk/reactos/ntoskrnl/dbg/kdb_stabs.c	2005-01-09 00:00:31 UTC (rev 12895)
@@ -69,8 +69,8 @@
   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);

Modified: trunk/reactos/ntoskrnl/dbg/kdb_symbols.c
--- 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);

Modified: trunk/reactos/tools/rsym.c
--- 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);