ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rsym.c
Go to the documentation of this file.
00001 /*
00002  * Usage: rsym input-file output-file
00003  *
00004  * There are two sources of information: the .stab/.stabstr
00005  * sections of the executable and the COFF symbol table. Most
00006  * of the information is in the .stab/.stabstr sections.
00007  * However, most of our asm files don't contain .stab directives,
00008  * so routines implemented in assembler won't show up in the
00009  * .stab section. They are present in the COFF symbol table.
00010  * So, we mostly use the .stab/.stabstr sections, but we augment
00011  * the info there with info from the COFF symbol table when
00012  * possible.
00013  *
00014  * This is a tool and is compiled using the host compiler,
00015  * i.e. on Linux gcc and not mingw-gcc (cross-compiler).
00016  * Therefore we can't include SDK headers and we have to
00017  * duplicate some definitions here.
00018  * Also note that the internal functions are "old C-style",
00019  * returning an int, where a return of 0 means success and
00020  * non-zero is failure.
00021  */
00022 
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include <assert.h>
00027 
00028 #include "rsym.h"
00029 
00030 static int
00031 CompareSymEntry(const PROSSYM_ENTRY SymEntry1, const PROSSYM_ENTRY SymEntry2)
00032 {
00033   if (SymEntry1->Address < SymEntry2->Address)
00034     {
00035       return -1;
00036     }
00037 
00038   if (SymEntry2->Address < SymEntry1->Address)
00039     {
00040       return +1;
00041     }
00042 
00043   return 0;
00044 }
00045 
00046 static int
00047 GetStabInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader,
00048             PIMAGE_SECTION_HEADER PESectionHeaders,
00049             ULONG *StabSymbolsLength, void **StabSymbolsBase,
00050             ULONG *StabStringsLength, void **StabStringsBase)
00051 {
00052   ULONG Idx;
00053 
00054   /* Load .stab and .stabstr sections if available */
00055   *StabSymbolsBase = NULL;
00056   *StabSymbolsLength = 0;
00057   *StabStringsBase = NULL;
00058   *StabStringsLength = 0;
00059 
00060   for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
00061     {
00062       /* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */
00063       if ((strncmp((char*)PESectionHeaders[Idx].Name, ".stab", 5) == 0)
00064         && (PESectionHeaders[Idx].Name[5] == 0))
00065         {
00066            /* printf(".stab section found. Size %d\n",
00067                PESectionHeaders[Idx].SizeOfRawData); */
00068 
00069            *StabSymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
00070            *StabSymbolsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData);
00071         }
00072 
00073       if (strncmp((char*)PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
00074         {
00075            /* printf(".stabstr section found. Size %d\n",
00076                PESectionHeaders[Idx].SizeOfRawData); */
00077 
00078            *StabStringsLength = PESectionHeaders[Idx].SizeOfRawData;
00079            *StabStringsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData);
00080         }
00081     }
00082 
00083   return 0;
00084 }
00085 
00086 static int
00087 GetCoffInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader,
00088             PIMAGE_SECTION_HEADER PESectionHeaders,
00089             ULONG *CoffSymbolsLength, void **CoffSymbolsBase,
00090             ULONG *CoffStringsLength, void **CoffStringsBase)
00091 {
00092 
00093   if (0 == PEFileHeader->PointerToSymbolTable || 0 == PEFileHeader->NumberOfSymbols)
00094     {
00095       /* No COFF symbol table */
00096       *CoffSymbolsLength = 0;
00097       *CoffStringsLength = 0;
00098     }
00099   else
00100     {
00101       *CoffSymbolsLength = PEFileHeader->NumberOfSymbols * sizeof(COFF_SYMENT);
00102       *CoffSymbolsBase = (void *)((char *) FileData + PEFileHeader->PointerToSymbolTable);
00103       *CoffStringsLength = *((ULONG *) ((char *) *CoffSymbolsBase + *CoffSymbolsLength));
00104       *CoffStringsBase = (void *)((char *) *CoffSymbolsBase + *CoffSymbolsLength);
00105     }
00106 
00107   return 0;
00108 }
00109 
00110 static ULONG
00111 FindOrAddString(char *StringToFind, ULONG *StringsLength, void *StringsBase)
00112 {
00113   char *Search, *End;
00114 
00115   Search = (char *) StringsBase;
00116   End = Search + *StringsLength;
00117 
00118   while (Search < End)
00119     {
00120       if (0 == strcmp(Search, StringToFind))
00121         {
00122           return Search - (char *) StringsBase;
00123         }
00124       Search += strlen(Search) + 1;
00125     }
00126 
00127   strcpy(Search, StringToFind);
00128   *StringsLength += strlen(StringToFind) + 1;
00129 
00130   return Search - (char *) StringsBase;
00131 }
00132 
00133 static int
00134 ConvertStabs(ULONG *SymbolsCount, PROSSYM_ENTRY *SymbolsBase,
00135              ULONG *StringsLength, void *StringsBase,
00136              ULONG StabSymbolsLength, void *StabSymbolsBase,
00137              ULONG StabStringsLength, void *StabStringsBase,
00138              ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader,
00139              PIMAGE_SECTION_HEADER PESectionHeaders)
00140 {
00141   PSTAB_ENTRY StabEntry;
00142   ULONG Count, i;
00143   ULONG_PTR Address, LastFunctionAddress;
00144   int First = 1;
00145   char *Name;
00146   ULONG NameLen;
00147   char FuncName[256];
00148   PROSSYM_ENTRY Current;
00149 
00150   StabEntry = StabSymbolsBase;
00151   Count = StabSymbolsLength / sizeof(STAB_ENTRY);
00152   *SymbolsCount = 0;
00153   if (Count == 0)
00154     {
00155       /* No symbol info */
00156       *SymbolsBase = NULL;
00157       return 0;
00158     }
00159 
00160   *SymbolsBase = malloc(Count * sizeof(ROSSYM_ENTRY));
00161   if (NULL == *SymbolsBase)
00162     {
00163       fprintf(stderr, "Failed to allocate memory for converted .stab symbols\n");
00164       return 1;
00165     }
00166   Current = *SymbolsBase;
00167   memset ( Current, 0, sizeof(*Current) );
00168 
00169   LastFunctionAddress = 0;
00170   for (i = 0; i < Count; i++)
00171     {
00172       if ( 0 == LastFunctionAddress )
00173         {
00174           Address = StabEntry[i].n_value - ImageBase;
00175         }
00176       else
00177         {
00178           Address = LastFunctionAddress + StabEntry[i].n_value;
00179         }
00180       switch (StabEntry[i].n_type)
00181         {
00182           case N_SO:
00183           case N_SOL:
00184           case N_BINCL:
00185             Name = (char *) StabStringsBase + StabEntry[i].n_strx;
00186             if (StabStringsLength < StabEntry[i].n_strx
00187                 ||'\0' == *Name || '/' == Name[strlen(Name) - 1]
00188                 || '\\' == Name[strlen(Name) - 1]
00189                 || StabEntry[i].n_value < ImageBase)
00190               {
00191                 continue;
00192               }
00193             if ( First || Address != Current->Address )
00194               {
00195                 if ( !First )
00196                   {
00197                     memset ( ++Current, 0, sizeof(*Current) );
00198                     Current->FunctionOffset = Current[-1].FunctionOffset;
00199                   }
00200                 else
00201                   First = 0;
00202                 Current->Address = Address;
00203               }
00204             Current->FileOffset = FindOrAddString((char *)StabStringsBase
00205                                                   + StabEntry[i].n_strx,
00206                                                   StringsLength,
00207                                                   StringsBase);
00208             break;
00209           case N_FUN:
00210             if (0 == StabEntry[i].n_desc || StabEntry[i].n_value < ImageBase)
00211               {
00212                 LastFunctionAddress = 0; /* line # 0 = end of function */
00213                 continue;
00214               }
00215             if ( First || Address != Current->Address )
00216               {
00217                 if ( !First )
00218                   memset ( ++Current, 0, sizeof(*Current) );
00219                 else
00220                   First = 0;
00221                 Current->Address = Address;
00222                 Current->FileOffset = Current[-1].FileOffset;
00223               }
00224             Name = (char *) StabStringsBase + StabEntry[i].n_strx;
00225             NameLen = strcspn(Name, ":");
00226             if (sizeof(FuncName) <= NameLen)
00227               {
00228                 free(*SymbolsBase);
00229                 fprintf(stderr, "Function name too long\n");
00230                 return 1;
00231               }
00232             memcpy(FuncName, Name, NameLen);
00233             FuncName[NameLen] = '\0';
00234             Current->FunctionOffset = FindOrAddString(FuncName,
00235                                                       StringsLength,
00236                                                       StringsBase);
00237             Current->SourceLine = 0;
00238             LastFunctionAddress = Address;
00239             break;
00240           case N_SLINE:
00241             if ( First || Address != Current->Address )
00242               {
00243                 if ( !First )
00244                   {
00245                     memset ( ++Current, 0, sizeof(*Current) );
00246                     Current->FileOffset = Current[-1].FileOffset;
00247                     Current->FunctionOffset = Current[-1].FunctionOffset;
00248                   }
00249                 else
00250                   First = 0;
00251                 Current->Address = Address;
00252               }
00253             Current->SourceLine = StabEntry[i].n_desc;
00254             break;
00255           default:
00256             continue;
00257         }
00258     }
00259   *SymbolsCount = (Current - *SymbolsBase + 1);
00260 
00261   qsort(*SymbolsBase, *SymbolsCount, sizeof(ROSSYM_ENTRY), (int (*)(const void *, const void *)) CompareSymEntry);
00262 
00263   return 0;
00264 }
00265 
00266 static int
00267 ConvertCoffs(ULONG *SymbolsCount, PROSSYM_ENTRY *SymbolsBase,
00268              ULONG *StringsLength, void *StringsBase,
00269              ULONG CoffSymbolsLength, void *CoffSymbolsBase,
00270              ULONG CoffStringsLength, void *CoffStringsBase,
00271              ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader,
00272              PIMAGE_SECTION_HEADER PESectionHeaders)
00273 {
00274   ULONG Count, i;
00275   PCOFF_SYMENT CoffEntry;
00276   char FuncName[256];
00277   char *p;
00278   PROSSYM_ENTRY Current;
00279 
00280   CoffEntry = (PCOFF_SYMENT) CoffSymbolsBase;
00281   Count = CoffSymbolsLength / sizeof(COFF_SYMENT);
00282   *SymbolsBase = malloc(Count * sizeof(ROSSYM_ENTRY));
00283   if (NULL == *SymbolsBase)
00284     {
00285       fprintf(stderr, "Unable to allocate memory for converted COFF symbols\n");
00286       return 1;
00287     }
00288   *SymbolsCount = 0;
00289   Current = *SymbolsBase;
00290 
00291   for (i = 0; i < Count; i++)
00292     {
00293       if (ISFCN(CoffEntry[i].e_type) || C_EXT == CoffEntry[i].e_sclass)
00294         {
00295           Current->Address = CoffEntry[i].e_value;
00296           if (0 < CoffEntry[i].e_scnum)
00297             {
00298               if (PEFileHeader->NumberOfSections < CoffEntry[i].e_scnum)
00299                 {
00300                   free(*SymbolsBase);
00301                   fprintf(stderr, "Invalid section number %d in COFF symbols (only %d sections present)\n",
00302                           CoffEntry[i].e_scnum, PEFileHeader->NumberOfSections);
00303                   return 1;
00304                 }
00305               Current->Address += PESectionHeaders[CoffEntry[i].e_scnum - 1].VirtualAddress;
00306             }
00307           Current->FileOffset = 0;
00308           if (0 == CoffEntry[i].e.e.e_zeroes)
00309             {
00310               if (sizeof(FuncName) <= strlen((char *) CoffStringsBase + CoffEntry[i].e.e.e_offset))
00311                 {
00312                   free(*SymbolsBase);
00313                   fprintf(stderr, "Function name too long\n");
00314                   return 1;
00315                 }
00316               strcpy(FuncName, (char *) CoffStringsBase + CoffEntry[i].e.e.e_offset);
00317             }
00318           else
00319             {
00320               memcpy(FuncName, CoffEntry[i].e.e_name, E_SYMNMLEN);
00321               FuncName[E_SYMNMLEN] = '\0';
00322             }
00323 
00324           /* Name demangling: stdcall */
00325           p = strrchr(FuncName, '@');
00326           if (NULL != p)
00327             {
00328               *p = '\0';
00329             }
00330           p = ('_' == FuncName[0] || '@' == FuncName[0] ? FuncName + 1 : FuncName);
00331           Current->FunctionOffset = FindOrAddString(p,
00332                                                                          StringsLength,
00333                                                                          StringsBase);
00334           Current->SourceLine = 0;
00335           memset ( ++Current, 0, sizeof(*Current) );
00336         }
00337       i += CoffEntry[i].e_numaux;
00338     }
00339 
00340   *SymbolsCount = (Current - *SymbolsBase + 1);
00341   qsort(*SymbolsBase, *SymbolsCount, sizeof(ROSSYM_ENTRY), (int (*)(const void *, const void *)) CompareSymEntry);
00342 
00343   return 0;
00344 }
00345 
00346 static int
00347 MergeStabsAndCoffs(ULONG *MergedSymbolCount, PROSSYM_ENTRY *MergedSymbols,
00348                    ULONG StabSymbolsCount, PROSSYM_ENTRY StabSymbols,
00349                    ULONG CoffSymbolsCount, PROSSYM_ENTRY CoffSymbols)
00350 {
00351   ULONG StabIndex, j;
00352   ULONG CoffIndex;
00353   ULONG_PTR StabFunctionStartAddress;
00354   ULONG StabFunctionStringOffset, NewStabFunctionStringOffset;
00355 
00356   *MergedSymbolCount = 0;
00357   if (StabSymbolsCount == 0)
00358     {
00359       *MergedSymbols = NULL;
00360       return 0;
00361     }
00362   *MergedSymbols = malloc(StabSymbolsCount * sizeof(ROSSYM_ENTRY));
00363   if (NULL == *MergedSymbols)
00364     {
00365       fprintf(stderr, "Unable to allocate memory for merged symbols\n");
00366       return 1;
00367     }
00368 
00369   StabFunctionStartAddress = 0;
00370   StabFunctionStringOffset = 0;
00371   CoffIndex = 0;
00372   for (StabIndex = 0; StabIndex < StabSymbolsCount; StabIndex++)
00373     {
00374       (*MergedSymbols)[*MergedSymbolCount] = StabSymbols[StabIndex];
00375       for (j = StabIndex + 1;
00376            j < StabSymbolsCount && StabSymbols[j].Address == StabSymbols[StabIndex].Address;
00377            j++)
00378         {
00379           if (0 != StabSymbols[j].FileOffset && 0 == (*MergedSymbols)[*MergedSymbolCount].FileOffset)
00380             {
00381               (*MergedSymbols)[*MergedSymbolCount].FileOffset = StabSymbols[j].FileOffset;
00382             }
00383           if (0 != StabSymbols[j].FunctionOffset && 0 == (*MergedSymbols)[*MergedSymbolCount].FunctionOffset)
00384             {
00385               (*MergedSymbols)[*MergedSymbolCount].FunctionOffset = StabSymbols[j].FunctionOffset;
00386             }
00387           if (0 != StabSymbols[j].SourceLine && 0 == (*MergedSymbols)[*MergedSymbolCount].SourceLine)
00388             {
00389               (*MergedSymbols)[*MergedSymbolCount].SourceLine = StabSymbols[j].SourceLine;
00390             }
00391         }
00392       StabIndex = j - 1;
00393       while (CoffIndex < CoffSymbolsCount
00394           && CoffSymbols[CoffIndex + 1].Address <= (*MergedSymbols)[*MergedSymbolCount].Address)
00395         {
00396           CoffIndex++;
00397         }
00398       NewStabFunctionStringOffset = (*MergedSymbols)[*MergedSymbolCount].FunctionOffset;
00399       if (CoffSymbolsCount > 0 &&
00400           CoffSymbols[CoffIndex].Address < (*MergedSymbols)[*MergedSymbolCount].Address
00401           && StabFunctionStartAddress < CoffSymbols[CoffIndex].Address
00402           && 0 != CoffSymbols[CoffIndex].FunctionOffset)
00403         {
00404           (*MergedSymbols)[*MergedSymbolCount].FunctionOffset = CoffSymbols[CoffIndex].FunctionOffset;
00405         }
00406       if (StabFunctionStringOffset != NewStabFunctionStringOffset)
00407         {
00408           StabFunctionStartAddress = (*MergedSymbols)[*MergedSymbolCount].Address;
00409         }
00410       StabFunctionStringOffset = NewStabFunctionStringOffset;
00411       (*MergedSymbolCount)++;
00412     }
00413 
00414   return 0;
00415 }
00416 
00417 static PIMAGE_SECTION_HEADER
00418 FindSectionForRVA(DWORD RVA, unsigned NumberOfSections, PIMAGE_SECTION_HEADER SectionHeaders)
00419 {
00420   unsigned Section;
00421 
00422   for (Section = 0; Section < NumberOfSections; Section++)
00423     {
00424       if (SectionHeaders[Section].VirtualAddress <= RVA &&
00425           RVA < SectionHeaders[Section].VirtualAddress + SectionHeaders[Section].Misc.VirtualSize)
00426         {
00427           return SectionHeaders + Section;
00428         }
00429     }
00430 
00431   return NULL;
00432 }
00433 
00434 static int
00435 ProcessRelocations(ULONG *ProcessedRelocsLength, void **ProcessedRelocs,
00436                    void *RawData, PIMAGE_OPTIONAL_HEADER OptHeader,
00437                    unsigned NumberOfSections, PIMAGE_SECTION_HEADER SectionHeaders)
00438 {
00439   PIMAGE_SECTION_HEADER RelocSectionHeader, TargetSectionHeader;
00440   PIMAGE_BASE_RELOCATION BaseReloc, End, AcceptedRelocs;
00441   int Found;
00442 
00443   if (OptHeader->NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_BASERELOC
00444       || 0 == OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
00445     {
00446       /* No relocation entries */
00447       *ProcessedRelocsLength = 0;
00448       *ProcessedRelocs = NULL;
00449       return 0;
00450     }
00451 
00452   RelocSectionHeader = FindSectionForRVA(OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
00453                                          NumberOfSections, SectionHeaders);
00454   if (NULL == RelocSectionHeader)
00455     {
00456       fprintf(stderr, "Can't find section header for relocation data\n");
00457       return 1;
00458     }
00459 
00460   *ProcessedRelocs = malloc(RelocSectionHeader->SizeOfRawData);
00461   if (NULL == *ProcessedRelocs)
00462     {
00463       fprintf(stderr, "Failed to allocate %u bytes for relocations\n", (unsigned int)RelocSectionHeader->SizeOfRawData);
00464       return 1;
00465     }
00466   *ProcessedRelocsLength = 0;
00467 
00468   BaseReloc = (PIMAGE_BASE_RELOCATION) ((char *) RawData
00469                                         + RelocSectionHeader->PointerToRawData
00470                                         + (OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress -
00471                                            RelocSectionHeader->VirtualAddress));
00472   End = (PIMAGE_BASE_RELOCATION) ((char *) BaseReloc
00473                                   + OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
00474 
00475   while (BaseReloc < End && 0 < BaseReloc->SizeOfBlock)
00476     {
00477       TargetSectionHeader = FindSectionForRVA(BaseReloc->VirtualAddress, NumberOfSections,
00478                                               SectionHeaders);
00479       if (NULL != TargetSectionHeader)
00480         {
00481           AcceptedRelocs = *ProcessedRelocs;
00482           Found = 0;
00483           while (AcceptedRelocs < (PIMAGE_BASE_RELOCATION) ((char *) *ProcessedRelocs +
00484                                                             *ProcessedRelocsLength)
00485                  && ! Found)
00486             {
00487               Found = BaseReloc->SizeOfBlock == AcceptedRelocs->SizeOfBlock
00488                       && 0 == memcmp(BaseReloc, AcceptedRelocs, AcceptedRelocs->SizeOfBlock);
00489               AcceptedRelocs= (PIMAGE_BASE_RELOCATION) ((char *) AcceptedRelocs +
00490                                                         AcceptedRelocs->SizeOfBlock);
00491             }
00492           if (! Found)
00493             {
00494               memcpy((char *) *ProcessedRelocs + *ProcessedRelocsLength,
00495                      BaseReloc, BaseReloc->SizeOfBlock);
00496               *ProcessedRelocsLength += BaseReloc->SizeOfBlock;
00497             }
00498         }
00499       BaseReloc = (PIMAGE_BASE_RELOCATION)((char *) BaseReloc + BaseReloc->SizeOfBlock);
00500     }
00501 
00502   return 0;
00503 }
00504 
00505 static int
00506 CreateOutputFile(FILE *OutFile, void *InData,
00507                  PIMAGE_DOS_HEADER InDosHeader, PIMAGE_FILE_HEADER InFileHeader,
00508                  PIMAGE_OPTIONAL_HEADER InOptHeader, PIMAGE_SECTION_HEADER InSectionHeaders,
00509                  ULONG RosSymLength, void *RosSymSection)
00510 {
00511   ULONG StartOfRawData;
00512   unsigned Section;
00513   void *OutHeader, *ProcessedRelocs, *PaddedRosSym, *Data;
00514   PIMAGE_DOS_HEADER OutDosHeader;
00515   PIMAGE_FILE_HEADER OutFileHeader;
00516   PIMAGE_OPTIONAL_HEADER OutOptHeader;
00517   PIMAGE_SECTION_HEADER OutSectionHeaders, CurrentSectionHeader;
00518   DWORD CheckSum;
00519   ULONG Length, i;
00520   ULONG ProcessedRelocsLength;
00521   ULONG RosSymOffset, RosSymFileLength;
00522   int InRelocSectionIndex;
00523   PIMAGE_SECTION_HEADER OutRelocSection;
00524 
00525   StartOfRawData = 0;
00526   for (Section = 0; Section < InFileHeader->NumberOfSections; Section++)
00527     {
00528       if ((0 == StartOfRawData
00529            || InSectionHeaders[Section].PointerToRawData < StartOfRawData)
00530           && 0 != InSectionHeaders[Section].PointerToRawData
00531           && 0 != (strncmp(InSectionHeaders[Section].Name, ".stab", 5)))
00532         {
00533           StartOfRawData = InSectionHeaders[Section].PointerToRawData;
00534         }
00535     }
00536   OutHeader = malloc(StartOfRawData);
00537   if (NULL == OutHeader)
00538     {
00539       fprintf(stderr, "Failed to allocate %u bytes for output file header\n", (unsigned int)StartOfRawData);
00540       return 1;
00541     }
00542   memset(OutHeader, '\0', StartOfRawData);
00543 
00544   OutDosHeader = (PIMAGE_DOS_HEADER) OutHeader;
00545   memcpy(OutDosHeader, InDosHeader, InDosHeader->e_lfanew + sizeof(ULONG));
00546 
00547   OutFileHeader = (PIMAGE_FILE_HEADER)((char *) OutHeader + OutDosHeader->e_lfanew + sizeof(ULONG));
00548   memcpy(OutFileHeader, InFileHeader, sizeof(IMAGE_FILE_HEADER));
00549   OutFileHeader->PointerToSymbolTable = 0;
00550   OutFileHeader->NumberOfSymbols = 0;
00551   OutFileHeader->Characteristics &= ~(IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
00552                                       IMAGE_FILE_DEBUG_STRIPPED);
00553 
00554   OutOptHeader = (PIMAGE_OPTIONAL_HEADER)(OutFileHeader + 1);
00555   memcpy(OutOptHeader, InOptHeader, sizeof(IMAGE_OPTIONAL_HEADER));
00556   OutOptHeader->CheckSum = 0;
00557 
00558   OutSectionHeaders = (PIMAGE_SECTION_HEADER)((char *) OutOptHeader + OutFileHeader->SizeOfOptionalHeader);
00559 
00560   if (ProcessRelocations(&ProcessedRelocsLength, &ProcessedRelocs, InData, InOptHeader,
00561                          InFileHeader->NumberOfSections, InSectionHeaders))
00562     {
00563       return 1;
00564     }
00565   if (InOptHeader->NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_BASERELOC
00566       || 0 == InOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
00567     {
00568       InRelocSectionIndex = -1;
00569     }
00570   else
00571     {
00572       InRelocSectionIndex = FindSectionForRVA(InOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
00573                                               InFileHeader->NumberOfSections, InSectionHeaders) - InSectionHeaders;
00574     }
00575 
00576   OutFileHeader->NumberOfSections = 0;
00577   CurrentSectionHeader = OutSectionHeaders;
00578   OutOptHeader->SizeOfImage = 0;
00579   RosSymOffset = 0;
00580   OutRelocSection = NULL;
00581   for (Section = 0; Section < InFileHeader->NumberOfSections; Section++)
00582     {
00583       if (0 != (strncmp(InSectionHeaders[Section].Name, ".stab", 5)))
00584         {
00585           *CurrentSectionHeader = InSectionHeaders[Section];
00586           CurrentSectionHeader->PointerToLinenumbers = 0;
00587           CurrentSectionHeader->NumberOfLinenumbers = 0;
00588           if (OutOptHeader->SizeOfImage < CurrentSectionHeader->VirtualAddress +
00589                                           CurrentSectionHeader->Misc.VirtualSize)
00590             {
00591               OutOptHeader->SizeOfImage = ROUND_UP(CurrentSectionHeader->VirtualAddress +
00592                                                    CurrentSectionHeader->Misc.VirtualSize,
00593                                                    OutOptHeader->SectionAlignment);
00594             }
00595           if (RosSymOffset < CurrentSectionHeader->PointerToRawData + CurrentSectionHeader->SizeOfRawData)
00596             {
00597               RosSymOffset = CurrentSectionHeader->PointerToRawData + CurrentSectionHeader->SizeOfRawData;
00598             }
00599           if (Section == (ULONG)InRelocSectionIndex)
00600             {
00601               OutRelocSection = CurrentSectionHeader;
00602             }
00603           (OutFileHeader->NumberOfSections) ++;
00604           CurrentSectionHeader++;
00605         }
00606     }
00607 
00608   if (OutRelocSection == CurrentSectionHeader - 1)
00609     {
00610       OutOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = ProcessedRelocsLength;
00611       if (OutOptHeader->SizeOfImage == OutRelocSection->VirtualAddress +
00612                                        ROUND_UP(OutRelocSection->Misc.VirtualSize,
00613                                                 OutOptHeader->SectionAlignment))
00614         {
00615           OutOptHeader->SizeOfImage = OutRelocSection->VirtualAddress +
00616                                       ROUND_UP(ProcessedRelocsLength,
00617                                                OutOptHeader->SectionAlignment);
00618         }
00619       OutRelocSection->Misc.VirtualSize = ProcessedRelocsLength;
00620       if (RosSymOffset == OutRelocSection->PointerToRawData
00621                           + OutRelocSection->SizeOfRawData)
00622         {
00623           RosSymOffset = OutRelocSection->PointerToRawData +
00624                          ROUND_UP(ProcessedRelocsLength, OutOptHeader->FileAlignment);
00625         }
00626       OutRelocSection->SizeOfRawData = ROUND_UP(ProcessedRelocsLength,
00627                                                 OutOptHeader->FileAlignment);
00628     }
00629 
00630   if (RosSymLength > 0)
00631     {
00632       RosSymFileLength = ROUND_UP(RosSymLength, OutOptHeader->FileAlignment);
00633       memcpy(CurrentSectionHeader->Name, ".rossym", 8); /* We're lucky: string is exactly 8 bytes long */
00634       CurrentSectionHeader->Misc.VirtualSize = RosSymLength;
00635       CurrentSectionHeader->VirtualAddress = OutOptHeader->SizeOfImage;
00636       CurrentSectionHeader->SizeOfRawData = RosSymFileLength;
00637       CurrentSectionHeader->PointerToRawData = RosSymOffset;
00638       CurrentSectionHeader->PointerToRelocations = 0;
00639       CurrentSectionHeader->PointerToLinenumbers = 0;
00640       CurrentSectionHeader->NumberOfRelocations = 0;
00641       CurrentSectionHeader->NumberOfLinenumbers = 0;
00642       CurrentSectionHeader->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
00643                                               | IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_TYPE_NOLOAD;
00644       OutOptHeader->SizeOfImage = ROUND_UP(CurrentSectionHeader->VirtualAddress +
00645                                            CurrentSectionHeader->Misc.VirtualSize,
00646                                        OutOptHeader->SectionAlignment);
00647       (OutFileHeader->NumberOfSections)++;
00648 
00649       PaddedRosSym = malloc(RosSymFileLength);
00650       if (NULL == PaddedRosSym)
00651         {
00652           fprintf(stderr, "Failed to allocate %u bytes for padded .rossym\n", (unsigned int)RosSymFileLength);
00653           return 1;
00654         }
00655       memcpy(PaddedRosSym, RosSymSection, RosSymLength);
00656       memset((char *) PaddedRosSym + RosSymLength, '\0', RosSymFileLength - RosSymLength);
00657     }
00658   else
00659     {
00660       PaddedRosSym = NULL;
00661     }
00662   CheckSum = 0;
00663   for (i = 0; i < StartOfRawData / 2; i++)
00664    {
00665       CheckSum += ((unsigned short*) OutHeader)[i];
00666       CheckSum = 0xffff & (CheckSum + (CheckSum >> 16));
00667    }
00668   Length = StartOfRawData;
00669   for (Section = 0; Section < OutFileHeader->NumberOfSections; Section++)
00670     {
00671       DWORD SizeOfRawData;
00672       if (OutRelocSection == OutSectionHeaders + Section)
00673         {
00674           Data = (void *) ProcessedRelocs;
00675       SizeOfRawData = ProcessedRelocsLength;
00676         }
00677       else if (RosSymLength > 0 && Section + 1 == OutFileHeader->NumberOfSections)
00678         {
00679           Data = (void *) PaddedRosSym;
00680       SizeOfRawData = OutSectionHeaders[Section].SizeOfRawData;
00681         }
00682       else
00683         {
00684           Data = (void *) ((char *) InData + OutSectionHeaders[Section].PointerToRawData);
00685       SizeOfRawData = OutSectionHeaders[Section].SizeOfRawData;
00686         }
00687       for (i = 0; i < SizeOfRawData / 2; i++)
00688         {
00689           CheckSum += ((unsigned short*) Data)[i];
00690           CheckSum = 0xffff & (CheckSum + (CheckSum >> 16));
00691         }
00692       Length += OutSectionHeaders[Section].SizeOfRawData;
00693     }
00694   CheckSum += Length;
00695   OutOptHeader->CheckSum = CheckSum;
00696 
00697   if (fwrite(OutHeader, 1, StartOfRawData, OutFile) != StartOfRawData)
00698     {
00699       perror("Error writing output header\n");
00700       free(OutHeader);
00701       return 1;
00702     }
00703 
00704   for (Section = 0; Section < OutFileHeader->NumberOfSections; Section++)
00705     {
00706       if (0 != OutSectionHeaders[Section].SizeOfRawData)
00707         {
00708       DWORD SizeOfRawData;
00709           fseek(OutFile, OutSectionHeaders[Section].PointerToRawData, SEEK_SET);
00710           if (OutRelocSection == OutSectionHeaders + Section)
00711             {
00712               Data = (void *) ProcessedRelocs;
00713           SizeOfRawData = ProcessedRelocsLength;
00714             }
00715           else if (RosSymLength > 0 && Section + 1 == OutFileHeader->NumberOfSections)
00716             {
00717               Data = (void *) PaddedRosSym;
00718           SizeOfRawData = OutSectionHeaders[Section].SizeOfRawData;
00719             }
00720           else
00721             {
00722               Data = (void *) ((char *) InData + OutSectionHeaders[Section].PointerToRawData);
00723           SizeOfRawData = OutSectionHeaders[Section].SizeOfRawData;
00724             }
00725           if (fwrite(Data, 1, SizeOfRawData, OutFile) != SizeOfRawData)
00726             {
00727               perror("Error writing section data\n");
00728               free(PaddedRosSym);
00729               free(OutHeader);
00730               return 1;
00731             }
00732         }
00733    }
00734 
00735   if (PaddedRosSym)
00736     {
00737       free(PaddedRosSym);
00738     }
00739   free(OutHeader);
00740 
00741   return 0;
00742 }
00743 
00744 int main(int argc, char* argv[])
00745 {
00746   PSYMBOLFILE_HEADER SymbolFileHeader;
00747   PIMAGE_DOS_HEADER PEDosHeader;
00748   PIMAGE_FILE_HEADER PEFileHeader;
00749   PIMAGE_OPTIONAL_HEADER PEOptHeader;
00750   PIMAGE_SECTION_HEADER PESectionHeaders;
00751   ULONG ImageBase;
00752   void *StabBase;
00753   ULONG StabsLength;
00754   void *StabStringBase;
00755   ULONG StabStringsLength;
00756   void *CoffBase = NULL;
00757   ULONG CoffsLength;
00758   void *CoffStringBase = NULL;
00759   ULONG CoffStringsLength;
00760   char* path1;
00761   char* path2;
00762   FILE* out;
00763   void *StringBase;
00764   ULONG StringsLength;
00765   ULONG StabSymbolsCount;
00766   PROSSYM_ENTRY StabSymbols;
00767   ULONG CoffSymbolsCount;
00768   PROSSYM_ENTRY CoffSymbols;
00769   ULONG MergedSymbolsCount;
00770   PROSSYM_ENTRY MergedSymbols;
00771   size_t FileSize;
00772   void *FileData;
00773   ULONG RosSymLength;
00774   void *RosSymSection;
00775   char elfhdr[4] = { '\177', 'E', 'L', 'F' };
00776 
00777   if (3 != argc)
00778     {
00779       fprintf(stderr, "Usage: rsym <exefile> <symfile>\n");
00780       exit(1);
00781     }
00782 
00783   path1 = convert_path(argv[1]);
00784   path2 = convert_path(argv[2]);
00785 
00786   FileData = load_file ( path1, &FileSize );
00787   if ( !FileData )
00788   {
00789     fprintf ( stderr, "An error occured loading '%s'\n", path1 );
00790     exit(1);
00791   }
00792 
00793   /* Check if MZ header exists  */
00794   PEDosHeader = (PIMAGE_DOS_HEADER) FileData;
00795   if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L)
00796     {
00797       /* Ignore elf */
00798       if (!memcmp(PEDosHeader, elfhdr, sizeof(elfhdr)))
00799     exit(0);
00800       perror("Input file is not a PE image.\n");
00801       free(FileData);
00802       exit(1);
00803     }
00804 
00805   /* Locate PE file header  */
00806   /* sizeof(ULONG) = sizeof(MAGIC) */
00807   PEFileHeader = (PIMAGE_FILE_HEADER)((char *) FileData + PEDosHeader->e_lfanew + sizeof(ULONG));
00808 
00809   /* Locate optional header */
00810   assert(sizeof(ULONG) == 4);
00811   PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1);
00812   ImageBase = PEOptHeader->ImageBase;
00813 
00814   /* Locate PE section headers  */
00815   PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader);
00816 
00817   if (GetStabInfo(FileData, PEFileHeader, PESectionHeaders, &StabsLength, &StabBase,
00818                   &StabStringsLength, &StabStringBase))
00819     {
00820       free(FileData);
00821       exit(1);
00822     }
00823 
00824   if (GetCoffInfo(FileData, PEFileHeader, PESectionHeaders, &CoffsLength, &CoffBase,
00825                   &CoffStringsLength, &CoffStringBase))
00826     {
00827       free(FileData);
00828       exit(1);
00829     }
00830 
00831   StringBase = malloc(1 + StabStringsLength + CoffStringsLength +
00832                       (CoffsLength / sizeof(ROSSYM_ENTRY)) * (E_SYMNMLEN + 1));
00833   if (NULL == StringBase)
00834     {
00835       free(FileData);
00836       fprintf(stderr, "Failed to allocate memory for strings table\n");
00837       exit(1);
00838     }
00839   /* Make offset 0 into an empty string */
00840   *((char *) StringBase) = '\0';
00841   StringsLength = 1;
00842 
00843   if (ConvertStabs(&StabSymbolsCount, &StabSymbols, &StringsLength, StringBase,
00844                    StabsLength, StabBase, StabStringsLength, StabStringBase,
00845                    ImageBase, PEFileHeader, PESectionHeaders))
00846     {
00847       free(StringBase);
00848       free(FileData);
00849       fprintf(stderr, "Failed to allocate memory for strings table\n");
00850       exit(1);
00851     }
00852 
00853   if (ConvertCoffs(&CoffSymbolsCount, &CoffSymbols, &StringsLength, StringBase,
00854                    CoffsLength, CoffBase, CoffStringsLength, CoffStringBase,
00855                    ImageBase, PEFileHeader, PESectionHeaders))
00856     {
00857       if (StabSymbols)
00858         {
00859           free(StabSymbols);
00860         }
00861       free(StringBase);
00862       free(FileData);
00863       exit(1);
00864     }
00865 
00866   if (MergeStabsAndCoffs(&MergedSymbolsCount, &MergedSymbols,
00867                          StabSymbolsCount, StabSymbols,
00868                          CoffSymbolsCount, CoffSymbols))
00869     {
00870       if (CoffSymbols)
00871         {
00872          free(CoffSymbols);
00873         }
00874       if (StabSymbols)
00875         {
00876           free(StabSymbols);
00877         }
00878       free(StringBase);
00879       free(FileData);
00880       exit(1);
00881     }
00882 
00883   if (CoffSymbols)
00884     {
00885       free(CoffSymbols);
00886     }
00887   if (StabSymbols)
00888     {
00889       free(StabSymbols);
00890     }
00891   if (MergedSymbolsCount == 0)
00892     {
00893       RosSymLength = 0;
00894       RosSymSection = NULL;
00895     }
00896   else
00897     {
00898       RosSymLength = sizeof(SYMBOLFILE_HEADER) + MergedSymbolsCount * sizeof(ROSSYM_ENTRY)
00899                             + StringsLength;
00900       RosSymSection = malloc(RosSymLength);
00901       if (NULL == RosSymSection)
00902         {
00903           free(MergedSymbols);
00904           free(StringBase);
00905           free(FileData);
00906           fprintf(stderr, "Unable to allocate memory for .rossym section\n");
00907           exit(1);
00908         }
00909       memset(RosSymSection, '\0', RosSymLength);
00910 
00911       SymbolFileHeader = (PSYMBOLFILE_HEADER) RosSymSection;
00912       SymbolFileHeader->SymbolsOffset = sizeof(SYMBOLFILE_HEADER);
00913       SymbolFileHeader->SymbolsLength = MergedSymbolsCount * sizeof(ROSSYM_ENTRY);
00914       SymbolFileHeader->StringsOffset = SymbolFileHeader->SymbolsOffset + SymbolFileHeader->SymbolsLength;
00915       SymbolFileHeader->StringsLength = StringsLength;
00916 
00917       memcpy((char *) RosSymSection + SymbolFileHeader->SymbolsOffset, MergedSymbols,
00918              SymbolFileHeader->SymbolsLength);
00919       memcpy((char *) RosSymSection + SymbolFileHeader->StringsOffset, StringBase,
00920              SymbolFileHeader->StringsLength);
00921 
00922       free(MergedSymbols);
00923     }
00924   free(StringBase);
00925   out = fopen(path2, "wb");
00926   if (out == NULL)
00927     {
00928       perror("Cannot open output file");
00929       free(RosSymSection);
00930       free(FileData);
00931       exit(1);
00932     }
00933 
00934   if (CreateOutputFile(out, FileData, PEDosHeader, PEFileHeader, PEOptHeader,
00935                        PESectionHeaders, RosSymLength, RosSymSection))
00936     {
00937       fclose(out);
00938       if (RosSymSection)
00939         {
00940           free(RosSymSection);
00941         }
00942       free(FileData);
00943       exit(1);
00944     }
00945 
00946   fclose(out);
00947   if (RosSymSection)
00948     {
00949       free(RosSymSection);
00950     }
00951   free(FileData);
00952 
00953   return 0;
00954 }
00955 
00956 /* EOF */

Generated on Fri May 25 2012 04:36:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.