filter out invalid S_FUN entries
[reactos.git] / reactos / tools / rsym.c
index 5971dcf..b9e7dbb 100644 (file)
@@ -113,14 +113,33 @@ typedef struct _SYMBOLFILE_HEADER {
   unsigned long StabstrLength;
 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
 
+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;
+
+#define N_FUN 0x24
+#define N_SLINE 0x44
+#define N_SO 0x64
+
+typedef struct
+{
+   unsigned long OldOffset;
+   unsigned long NewOffset;
+   char* Name;
+   unsigned long Length;
+} STR_ENTRY, *PSTR_ENTRY;
 
 char* convert_path(char* origpath)
 {
    char* newpath;
    int i;
-   
+
    newpath = strdup(origpath);
-   
+
    i = 0;
    while (newpath[i] != 0)
      {
@@ -135,8 +154,8 @@ char* convert_path(char* origpath)
          {
             newpath[i] = '\\';
          }
-#endif 
-#endif 
+#endif
+#endif
        i++;
      }
    return(newpath);
@@ -149,7 +168,9 @@ int main(int argc, char* argv[])
   SYMBOLFILE_HEADER SymbolFileHeader;
   IMAGE_DOS_HEADER PEDosHeader;
   IMAGE_FILE_HEADER PEFileHeader;
+  PIMAGE_OPTIONAL_HEADER PEOptHeader;
   PIMAGE_SECTION_HEADER PESectionHeaders;
+  ULONG ImageBase;
   PVOID SymbolsBase;
   ULONG SymbolsLength;
   PVOID SymbolStringsBase;
@@ -161,16 +182,23 @@ int main(int argc, char* argv[])
   FILE* out;
   int n_in;
   int n_out;
-   
+  PSTAB_ENTRY StabEntry;
+  ULONG Count;
+  ULONG i;
+  ULONG SymbolsCount;
+  PSTR_ENTRY StrEntry;
+  ULONG StrCount;
+  ULONG j;
+
    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)
      {
@@ -198,6 +226,11 @@ int main(int argc, char* argv[])
   fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
   n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in);
 
+  /* Read optional header */
+  PEOptHeader = malloc(PEFileHeader.SizeOfOptionalHeader);
+  fread ( PEOptHeader, 1, PEFileHeader.SizeOfOptionalHeader, in );
+  ImageBase = PEOptHeader->ImageBase;
+
   /* Read PE section headers  */
   PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
   fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)
@@ -216,7 +249,7 @@ int main(int argc, char* argv[])
       if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0)
         && (PESectionHeaders[Idx].Name[5] == 0))
         {
-          //printf(".stab section found. Size %d\n", 
+          //printf(".stab section found. Size %d\n",
            //  PESectionHeaders[Idx].SizeOfRawData);
 
            SymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
@@ -228,7 +261,7 @@ int main(int argc, char* argv[])
 
       if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
         {
-          //printf(".stabstr section found. Size %d\n", 
+          //printf(".stabstr section found. Size %d\n",
            //  PESectionHeaders[Idx].SizeOfRawData);
 
            SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData;
@@ -239,14 +272,74 @@ int main(int argc, char* argv[])
         }
     }
 
+  StabEntry = SymbolsBase;
+  SymbolsCount = SymbolsLength / sizeof(STAB_ENTRY);
+  Count = 0;
+
+  for (i = 0; i < SymbolsCount; i++)
+    {
+      switch ( StabEntry[i].n_type )
+      {
+      case N_FUN:
+       if ( StabEntry[i].n_desc == 0 ) // line # 0 isn't valid
+         continue;
+       break;
+      case N_SLINE:
+       break;
+      case N_SO:
+       break;
+      default:
+       continue;
+      }
+      memmove(&StabEntry[Count], &StabEntry[i], sizeof(STAB_ENTRY));
+      if ( StabEntry[Count].n_value >= ImageBase )
+           StabEntry[Count].n_value -= ImageBase;
+      Count++;
+    }
+
+  StrEntry = malloc(sizeof(STR_ENTRY) * Count);
+  StrCount = 0;
+
+  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++;
+       }
+    }
+
   SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
-  SymbolFileHeader.StabsLength = SymbolsLength;
-  SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength;
-  SymbolFileHeader.StabstrLength = SymbolStringsLength;
+  SymbolFileHeader.StabsLength = Count * sizeof(STAB_ENTRY);
+  SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolFileHeader.StabsLength;
+  SymbolFileHeader.StabstrLength = StrEntry[StrCount-1].NewOffset + StrEntry[StrCount-1].Length;
 
   n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
-  n_out = fwrite(SymbolsBase, 1, SymbolsLength, out);
-  n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out);
+  n_out = fwrite(SymbolsBase, 1, SymbolFileHeader.StabsLength, out);
+  for (i = 0; i < StrCount; i++)
+    {
+      fwrite(StrEntry[i].Name, 1, StrEntry[i].Length, out);
+    }
 
+  fclose(out);
   exit(0);
 }