Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrsym.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
1.7.6.1
|