2 * Usage: rsym input-file output-file
4 * There are two sources of information: the .stab/.stabstr
5 * sections of the executable and the COFF symbol table. Most
6 * of the information is in the .stab/.stabstr sections.
7 * However, most of our asm files don't contain .stab directives,
8 * so routines implemented in assembler won't show up in the
9 * .stab section. They are present in the COFF symbol table.
10 * So, we mostly use the .stab/.stabstr sections, but we augment
11 * the info there with info from the COFF symbol table when
14 * This is a tool and is compiled using the host compiler,
15 * i.e. on Linux gcc and not mingw-gcc (cross-compiler).
16 * Therefore we can't include SDK headers and we have to
17 * duplicate some definitions here.
18 * Also note that the internal functions are "old C-style",
19 * returning an int, where a return of 0 means success and
20 * non-zero is failure.
31 CompareSymEntry(const PROSSYM_ENTRY SymEntry1
, const PROSSYM_ENTRY SymEntry2
)
33 if (SymEntry1
->Address
< SymEntry2
->Address
)
38 if (SymEntry2
->Address
< SymEntry1
->Address
)
47 GetStabInfo(void *FileData
, PIMAGE_FILE_HEADER PEFileHeader
,
48 PIMAGE_SECTION_HEADER PESectionHeaders
,
49 ULONG
*StabSymbolsLength
, void **StabSymbolsBase
,
50 ULONG
*StabStringsLength
, void **StabStringsBase
)
54 /* Load .stab and .stabstr sections if available */
55 *StabSymbolsBase
= NULL
;
56 *StabSymbolsLength
= 0;
57 *StabStringsBase
= NULL
;
58 *StabStringsLength
= 0;
60 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
62 /* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */
63 if ((strncmp((char*)PESectionHeaders
[Idx
].Name
, ".stab", 5) == 0)
64 && (PESectionHeaders
[Idx
].Name
[5] == 0))
66 /* printf(".stab section found. Size %d\n",
67 PESectionHeaders[Idx].SizeOfRawData); */
69 *StabSymbolsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
70 *StabSymbolsBase
= (void *)((char *) FileData
+ PESectionHeaders
[Idx
].PointerToRawData
);
73 if (strncmp((char*)PESectionHeaders
[Idx
].Name
, ".stabstr", 8) == 0)
75 /* printf(".stabstr section found. Size %d\n",
76 PESectionHeaders[Idx].SizeOfRawData); */
78 *StabStringsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
79 *StabStringsBase
= (void *)((char *) FileData
+ PESectionHeaders
[Idx
].PointerToRawData
);
87 GetCoffInfo(void *FileData
, PIMAGE_FILE_HEADER PEFileHeader
,
88 PIMAGE_SECTION_HEADER PESectionHeaders
,
89 ULONG
*CoffSymbolsLength
, void **CoffSymbolsBase
,
90 ULONG
*CoffStringsLength
, void **CoffStringsBase
)
93 if (0 == PEFileHeader
->PointerToSymbolTable
|| 0 == PEFileHeader
->NumberOfSymbols
)
95 /* No COFF symbol table */
96 *CoffSymbolsLength
= 0;
97 *CoffStringsLength
= 0;
101 *CoffSymbolsLength
= PEFileHeader
->NumberOfSymbols
* sizeof(COFF_SYMENT
);
102 *CoffSymbolsBase
= (void *)((char *) FileData
+ PEFileHeader
->PointerToSymbolTable
);
103 *CoffStringsLength
= *((ULONG
*) ((char *) *CoffSymbolsBase
+ *CoffSymbolsLength
));
104 *CoffStringsBase
= (void *)((char *) *CoffSymbolsBase
+ *CoffSymbolsLength
);
111 FindOrAddString(char *StringToFind
, ULONG
*StringsLength
, void *StringsBase
)
115 Search
= (char *) StringsBase
;
116 End
= Search
+ *StringsLength
;
120 if (0 == strcmp(Search
, StringToFind
))
122 return Search
- (char *) StringsBase
;
124 Search
+= strlen(Search
) + 1;
127 strcpy(Search
, StringToFind
);
128 *StringsLength
+= strlen(StringToFind
) + 1;
130 return Search
- (char *) StringsBase
;
134 ConvertStabs(ULONG
*SymbolsCount
, PROSSYM_ENTRY
*SymbolsBase
,
135 ULONG
*StringsLength
, void *StringsBase
,
136 ULONG StabSymbolsLength
, void *StabSymbolsBase
,
137 ULONG StabStringsLength
, void *StabStringsBase
,
138 ULONG_PTR ImageBase
, PIMAGE_FILE_HEADER PEFileHeader
,
139 PIMAGE_SECTION_HEADER PESectionHeaders
)
141 PSTAB_ENTRY StabEntry
;
143 ULONG_PTR Address
, LastFunctionAddress
;
148 PROSSYM_ENTRY Current
;
150 StabEntry
= StabSymbolsBase
;
151 Count
= StabSymbolsLength
/ sizeof(STAB_ENTRY
);
160 *SymbolsBase
= malloc(Count
* sizeof(ROSSYM_ENTRY
));
161 if (NULL
== *SymbolsBase
)
163 fprintf(stderr
, "Failed to allocate memory for converted .stab symbols\n");
166 Current
= *SymbolsBase
;
167 memset ( Current
, 0, sizeof(*Current
) );
169 LastFunctionAddress
= 0;
170 for (i
= 0; i
< Count
; i
++)
172 if ( 0 == LastFunctionAddress
)
174 Address
= StabEntry
[i
].n_value
- ImageBase
;
178 Address
= LastFunctionAddress
+ StabEntry
[i
].n_value
;
180 switch (StabEntry
[i
].n_type
)
185 Name
= (char *) StabStringsBase
+ StabEntry
[i
].n_strx
;
186 if (StabStringsLength
< StabEntry
[i
].n_strx
187 ||'\0' == *Name
|| '/' == Name
[strlen(Name
) - 1]
188 || '\\' == Name
[strlen(Name
) - 1]
189 || StabEntry
[i
].n_value
< ImageBase
)
193 if ( First
|| Address
!= Current
->Address
)
197 memset ( ++Current
, 0, sizeof(*Current
) );
198 Current
->FunctionOffset
= Current
[-1].FunctionOffset
;
202 Current
->Address
= Address
;
204 Current
->FileOffset
= FindOrAddString((char *)StabStringsBase
205 + StabEntry
[i
].n_strx
,
210 if (0 == StabEntry
[i
].n_desc
|| StabEntry
[i
].n_value
< ImageBase
)
212 LastFunctionAddress
= 0; /* line # 0 = end of function */
215 if ( First
|| Address
!= Current
->Address
)
218 memset ( ++Current
, 0, sizeof(*Current
) );
221 Current
->Address
= Address
;
222 Current
->FileOffset
= Current
[-1].FileOffset
;
224 Name
= (char *) StabStringsBase
+ StabEntry
[i
].n_strx
;
225 NameLen
= strcspn(Name
, ":");
226 if (sizeof(FuncName
) <= NameLen
)
229 fprintf(stderr
, "Function name too long\n");
232 memcpy(FuncName
, Name
, NameLen
);
233 FuncName
[NameLen
] = '\0';
234 Current
->FunctionOffset
= FindOrAddString(FuncName
,
237 Current
->SourceLine
= 0;
238 LastFunctionAddress
= Address
;
241 if ( First
|| Address
!= Current
->Address
)
245 memset ( ++Current
, 0, sizeof(*Current
) );
246 Current
->FileOffset
= Current
[-1].FileOffset
;
247 Current
->FunctionOffset
= Current
[-1].FunctionOffset
;
251 Current
->Address
= Address
;
253 Current
->SourceLine
= StabEntry
[i
].n_desc
;
259 *SymbolsCount
= (Current
- *SymbolsBase
+ 1);
261 qsort(*SymbolsBase
, *SymbolsCount
, sizeof(ROSSYM_ENTRY
), (int (*)(const void *, const void *)) CompareSymEntry
);
267 ConvertCoffs(ULONG
*SymbolsCount
, PROSSYM_ENTRY
*SymbolsBase
,
268 ULONG
*StringsLength
, void *StringsBase
,
269 ULONG CoffSymbolsLength
, void *CoffSymbolsBase
,
270 ULONG CoffStringsLength
, void *CoffStringsBase
,
271 ULONG_PTR ImageBase
, PIMAGE_FILE_HEADER PEFileHeader
,
272 PIMAGE_SECTION_HEADER PESectionHeaders
)
275 PCOFF_SYMENT CoffEntry
;
278 PROSSYM_ENTRY Current
;
280 CoffEntry
= (PCOFF_SYMENT
) CoffSymbolsBase
;
281 Count
= CoffSymbolsLength
/ sizeof(COFF_SYMENT
);
282 *SymbolsBase
= malloc(Count
* sizeof(ROSSYM_ENTRY
));
283 if (NULL
== *SymbolsBase
)
285 fprintf(stderr
, "Unable to allocate memory for converted COFF symbols\n");
289 Current
= *SymbolsBase
;
291 for (i
= 0; i
< Count
; i
++)
293 if (ISFCN(CoffEntry
[i
].e_type
) || C_EXT
== CoffEntry
[i
].e_sclass
)
295 Current
->Address
= CoffEntry
[i
].e_value
;
296 if (0 < CoffEntry
[i
].e_scnum
)
298 if (PEFileHeader
->NumberOfSections
< CoffEntry
[i
].e_scnum
)
301 fprintf(stderr
, "Invalid section number %d in COFF symbols (only %d sections present)\n",
302 CoffEntry
[i
].e_scnum
, PEFileHeader
->NumberOfSections
);
305 Current
->Address
+= PESectionHeaders
[CoffEntry
[i
].e_scnum
- 1].VirtualAddress
;
307 Current
->FileOffset
= 0;
308 if (0 == CoffEntry
[i
].e
.e
.e_zeroes
)
310 if (sizeof(FuncName
) <= strlen((char *) CoffStringsBase
+ CoffEntry
[i
].e
.e
.e_offset
))
313 fprintf(stderr
, "Function name too long\n");
316 strcpy(FuncName
, (char *) CoffStringsBase
+ CoffEntry
[i
].e
.e
.e_offset
);
320 memcpy(FuncName
, CoffEntry
[i
].e
.e_name
, E_SYMNMLEN
);
321 FuncName
[E_SYMNMLEN
] = '\0';
324 /* Name demangling: stdcall */
325 p
= strrchr(FuncName
, '@');
330 p
= ('_' == FuncName
[0] || '@' == FuncName
[0] ? FuncName
+ 1 : FuncName
);
331 Current
->FunctionOffset
= FindOrAddString(p
,
334 Current
->SourceLine
= 0;
335 memset ( ++Current
, 0, sizeof(*Current
) );
337 i
+= CoffEntry
[i
].e_numaux
;
340 *SymbolsCount
= (Current
- *SymbolsBase
+ 1);
341 qsort(*SymbolsBase
, *SymbolsCount
, sizeof(ROSSYM_ENTRY
), (int (*)(const void *, const void *)) CompareSymEntry
);
347 MergeStabsAndCoffs(ULONG
*MergedSymbolCount
, PROSSYM_ENTRY
*MergedSymbols
,
348 ULONG StabSymbolsCount
, PROSSYM_ENTRY StabSymbols
,
349 ULONG CoffSymbolsCount
, PROSSYM_ENTRY CoffSymbols
)
353 ULONG_PTR StabFunctionStartAddress
;
354 ULONG StabFunctionStringOffset
, NewStabFunctionStringOffset
;
356 *MergedSymbolCount
= 0;
357 if (StabSymbolsCount
== 0)
359 *MergedSymbols
= NULL
;
362 *MergedSymbols
= malloc(StabSymbolsCount
* sizeof(ROSSYM_ENTRY
));
363 if (NULL
== *MergedSymbols
)
365 fprintf(stderr
, "Unable to allocate memory for merged symbols\n");
369 StabFunctionStartAddress
= 0;
370 StabFunctionStringOffset
= 0;
372 for (StabIndex
= 0; StabIndex
< StabSymbolsCount
; StabIndex
++)
374 (*MergedSymbols
)[*MergedSymbolCount
] = StabSymbols
[StabIndex
];
375 for (j
= StabIndex
+ 1;
376 j
< StabSymbolsCount
&& StabSymbols
[j
].Address
== StabSymbols
[StabIndex
].Address
;
379 if (0 != StabSymbols
[j
].FileOffset
&& 0 == (*MergedSymbols
)[*MergedSymbolCount
].FileOffset
)
381 (*MergedSymbols
)[*MergedSymbolCount
].FileOffset
= StabSymbols
[j
].FileOffset
;
383 if (0 != StabSymbols
[j
].FunctionOffset
&& 0 == (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
)
385 (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
= StabSymbols
[j
].FunctionOffset
;
387 if (0 != StabSymbols
[j
].SourceLine
&& 0 == (*MergedSymbols
)[*MergedSymbolCount
].SourceLine
)
389 (*MergedSymbols
)[*MergedSymbolCount
].SourceLine
= StabSymbols
[j
].SourceLine
;
393 while (CoffIndex
< CoffSymbolsCount
394 && CoffSymbols
[CoffIndex
+ 1].Address
<= (*MergedSymbols
)[*MergedSymbolCount
].Address
)
398 NewStabFunctionStringOffset
= (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
;
399 if (CoffSymbolsCount
> 0 &&
400 CoffSymbols
[CoffIndex
].Address
< (*MergedSymbols
)[*MergedSymbolCount
].Address
401 && StabFunctionStartAddress
< CoffSymbols
[CoffIndex
].Address
402 && 0 != CoffSymbols
[CoffIndex
].FunctionOffset
)
404 (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
= CoffSymbols
[CoffIndex
].FunctionOffset
;
406 if (StabFunctionStringOffset
!= NewStabFunctionStringOffset
)
408 StabFunctionStartAddress
= (*MergedSymbols
)[*MergedSymbolCount
].Address
;
410 StabFunctionStringOffset
= NewStabFunctionStringOffset
;
411 (*MergedSymbolCount
)++;
417 static PIMAGE_SECTION_HEADER
418 FindSectionForRVA(DWORD RVA
, unsigned NumberOfSections
, PIMAGE_SECTION_HEADER SectionHeaders
)
422 for (Section
= 0; Section
< NumberOfSections
; Section
++)
424 if (SectionHeaders
[Section
].VirtualAddress
<= RVA
&&
425 RVA
< SectionHeaders
[Section
].VirtualAddress
+ SectionHeaders
[Section
].Misc
.VirtualSize
)
427 return SectionHeaders
+ Section
;
435 IncludeRelocationsForSection(PIMAGE_SECTION_HEADER SectionHeader
)
437 static char *BlacklistedSections
[] =
443 char SectionName
[IMAGE_SIZEOF_SHORT_NAME
];
446 if (0 != (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
))
451 for (i
= 0; i
< sizeof(BlacklistedSections
) / sizeof(BlacklistedSections
[0]); i
++)
453 strncpy(SectionName
, BlacklistedSections
[i
], IMAGE_SIZEOF_SHORT_NAME
);
454 if (0 == memcmp(SectionName
, SectionHeader
->Name
, IMAGE_SIZEOF_SHORT_NAME
))
464 ProcessRelocations(ULONG
*ProcessedRelocsLength
, void **ProcessedRelocs
,
465 void *RawData
, PIMAGE_OPTIONAL_HEADER OptHeader
,
466 unsigned NumberOfSections
, PIMAGE_SECTION_HEADER SectionHeaders
)
468 PIMAGE_SECTION_HEADER RelocSectionHeader
, TargetSectionHeader
;
469 PIMAGE_BASE_RELOCATION BaseReloc
, End
, AcceptedRelocs
;
472 if (OptHeader
->NumberOfRvaAndSizes
< IMAGE_DIRECTORY_ENTRY_BASERELOC
473 || 0 == OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
)
475 /* No relocation entries */
476 *ProcessedRelocsLength
= 0;
477 *ProcessedRelocs
= NULL
;
481 RelocSectionHeader
= FindSectionForRVA(OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
,
482 NumberOfSections
, SectionHeaders
);
483 if (NULL
== RelocSectionHeader
)
485 fprintf(stderr
, "Can't find section header for relocation data\n");
489 *ProcessedRelocs
= malloc(RelocSectionHeader
->SizeOfRawData
);
490 if (NULL
== *ProcessedRelocs
)
492 fprintf(stderr
, "Failed to allocate %u bytes for relocations\n", (unsigned int)RelocSectionHeader
->SizeOfRawData
);
495 *ProcessedRelocsLength
= 0;
497 BaseReloc
= (PIMAGE_BASE_RELOCATION
) ((char *) RawData
498 + RelocSectionHeader
->PointerToRawData
499 + (OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
-
500 RelocSectionHeader
->VirtualAddress
));
501 End
= (PIMAGE_BASE_RELOCATION
) ((char *) BaseReloc
502 + OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
);
504 while (BaseReloc
< End
&& 0 < BaseReloc
->SizeOfBlock
)
506 TargetSectionHeader
= FindSectionForRVA(BaseReloc
->VirtualAddress
, NumberOfSections
,
508 if (NULL
!= TargetSectionHeader
&& IncludeRelocationsForSection(TargetSectionHeader
))
510 AcceptedRelocs
= *ProcessedRelocs
;
512 while (AcceptedRelocs
< (PIMAGE_BASE_RELOCATION
) ((char *) *ProcessedRelocs
+
513 *ProcessedRelocsLength
)
516 Found
= BaseReloc
->SizeOfBlock
== AcceptedRelocs
->SizeOfBlock
517 && 0 == memcmp(BaseReloc
, AcceptedRelocs
, AcceptedRelocs
->SizeOfBlock
);
518 AcceptedRelocs
= (PIMAGE_BASE_RELOCATION
) ((char *) AcceptedRelocs
+
519 AcceptedRelocs
->SizeOfBlock
);
523 memcpy((char *) *ProcessedRelocs
+ *ProcessedRelocsLength
,
524 BaseReloc
, BaseReloc
->SizeOfBlock
);
525 *ProcessedRelocsLength
+= BaseReloc
->SizeOfBlock
;
528 BaseReloc
= (PIMAGE_BASE_RELOCATION
)((char *) BaseReloc
+ BaseReloc
->SizeOfBlock
);
535 CreateOutputFile(FILE *OutFile
, void *InData
,
536 PIMAGE_DOS_HEADER InDosHeader
, PIMAGE_FILE_HEADER InFileHeader
,
537 PIMAGE_OPTIONAL_HEADER InOptHeader
, PIMAGE_SECTION_HEADER InSectionHeaders
,
538 ULONG RosSymLength
, void *RosSymSection
)
540 ULONG StartOfRawData
;
542 void *OutHeader
, *ProcessedRelocs
, *PaddedRosSym
, *Data
;
543 PIMAGE_DOS_HEADER OutDosHeader
;
544 PIMAGE_FILE_HEADER OutFileHeader
;
545 PIMAGE_OPTIONAL_HEADER OutOptHeader
;
546 PIMAGE_SECTION_HEADER OutSectionHeaders
, CurrentSectionHeader
;
549 ULONG ProcessedRelocsLength
;
550 ULONG RosSymOffset
, RosSymFileLength
;
551 int InRelocSectionIndex
;
552 PIMAGE_SECTION_HEADER OutRelocSection
;
555 for (Section
= 0; Section
< InFileHeader
->NumberOfSections
; Section
++)
557 if ((0 == StartOfRawData
558 || InSectionHeaders
[Section
].PointerToRawData
< StartOfRawData
)
559 && 0 != InSectionHeaders
[Section
].PointerToRawData
560 && 0 == (InSectionHeaders
[Section
].Characteristics
& IMAGE_SCN_LNK_REMOVE
))
562 StartOfRawData
= InSectionHeaders
[Section
].PointerToRawData
;
565 OutHeader
= malloc(StartOfRawData
);
566 if (NULL
== OutHeader
)
568 fprintf(stderr
, "Failed to allocate %u bytes for output file header\n", (unsigned int)StartOfRawData
);
571 memset(OutHeader
, '\0', StartOfRawData
);
573 OutDosHeader
= (PIMAGE_DOS_HEADER
) OutHeader
;
574 memcpy(OutDosHeader
, InDosHeader
, InDosHeader
->e_lfanew
+ sizeof(ULONG
));
576 OutFileHeader
= (PIMAGE_FILE_HEADER
)((char *) OutHeader
+ OutDosHeader
->e_lfanew
+ sizeof(ULONG
));
577 memcpy(OutFileHeader
, InFileHeader
, sizeof(IMAGE_FILE_HEADER
));
578 OutFileHeader
->PointerToSymbolTable
= 0;
579 OutFileHeader
->NumberOfSymbols
= 0;
580 OutFileHeader
->Characteristics
&= ~(IMAGE_FILE_LINE_NUMS_STRIPPED
| IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
581 IMAGE_FILE_DEBUG_STRIPPED
);
583 OutOptHeader
= (PIMAGE_OPTIONAL_HEADER
)(OutFileHeader
+ 1);
584 memcpy(OutOptHeader
, InOptHeader
, sizeof(IMAGE_OPTIONAL_HEADER
));
585 OutOptHeader
->CheckSum
= 0;
587 OutSectionHeaders
= (PIMAGE_SECTION_HEADER
)((char *) OutOptHeader
+ OutFileHeader
->SizeOfOptionalHeader
);
589 if (ProcessRelocations(&ProcessedRelocsLength
, &ProcessedRelocs
, InData
, InOptHeader
,
590 InFileHeader
->NumberOfSections
, InSectionHeaders
))
594 if (InOptHeader
->NumberOfRvaAndSizes
< IMAGE_DIRECTORY_ENTRY_BASERELOC
595 || 0 == InOptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
)
597 InRelocSectionIndex
= -1;
601 InRelocSectionIndex
= FindSectionForRVA(InOptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
,
602 InFileHeader
->NumberOfSections
, InSectionHeaders
) - InSectionHeaders
;
605 OutFileHeader
->NumberOfSections
= 0;
606 CurrentSectionHeader
= OutSectionHeaders
;
607 OutOptHeader
->SizeOfImage
= 0;
609 OutRelocSection
= NULL
;
610 for (Section
= 0; Section
< InFileHeader
->NumberOfSections
; Section
++)
612 if (0 == (InSectionHeaders
[Section
].Characteristics
& IMAGE_SCN_LNK_REMOVE
))
614 *CurrentSectionHeader
= InSectionHeaders
[Section
];
615 CurrentSectionHeader
->PointerToLinenumbers
= 0;
616 CurrentSectionHeader
->NumberOfLinenumbers
= 0;
617 if (OutOptHeader
->SizeOfImage
< CurrentSectionHeader
->VirtualAddress
+
618 CurrentSectionHeader
->Misc
.VirtualSize
)
620 OutOptHeader
->SizeOfImage
= ROUND_UP(CurrentSectionHeader
->VirtualAddress
+
621 CurrentSectionHeader
->Misc
.VirtualSize
,
622 OutOptHeader
->SectionAlignment
);
624 if (RosSymOffset
< CurrentSectionHeader
->PointerToRawData
+ CurrentSectionHeader
->SizeOfRawData
)
626 RosSymOffset
= CurrentSectionHeader
->PointerToRawData
+ CurrentSectionHeader
->SizeOfRawData
;
628 if (Section
== (ULONG
)InRelocSectionIndex
)
630 OutRelocSection
= CurrentSectionHeader
;
632 (OutFileHeader
->NumberOfSections
) ++;
633 CurrentSectionHeader
++;
637 if (OutRelocSection
== CurrentSectionHeader
- 1)
639 OutOptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= ProcessedRelocsLength
;
640 if (OutOptHeader
->SizeOfImage
== OutRelocSection
->VirtualAddress
+
641 ROUND_UP(OutRelocSection
->Misc
.VirtualSize
,
642 OutOptHeader
->SectionAlignment
))
644 OutOptHeader
->SizeOfImage
= OutRelocSection
->VirtualAddress
+
645 ROUND_UP(ProcessedRelocsLength
,
646 OutOptHeader
->SectionAlignment
);
648 OutRelocSection
->Misc
.VirtualSize
= ProcessedRelocsLength
;
649 if (RosSymOffset
== OutRelocSection
->PointerToRawData
650 + OutRelocSection
->SizeOfRawData
)
652 RosSymOffset
= OutRelocSection
->PointerToRawData
+
653 ROUND_UP(ProcessedRelocsLength
, OutOptHeader
->FileAlignment
);
655 OutRelocSection
->SizeOfRawData
= ROUND_UP(ProcessedRelocsLength
,
656 OutOptHeader
->FileAlignment
);
659 if (RosSymLength
> 0)
661 RosSymFileLength
= ROUND_UP(RosSymLength
, OutOptHeader
->FileAlignment
);
662 memcpy(CurrentSectionHeader
->Name
, ".rossym", 8); /* We're lucky: string is exactly 8 bytes long */
663 CurrentSectionHeader
->Misc
.VirtualSize
= RosSymLength
;
664 CurrentSectionHeader
->VirtualAddress
= OutOptHeader
->SizeOfImage
;
665 CurrentSectionHeader
->SizeOfRawData
= RosSymFileLength
;
666 CurrentSectionHeader
->PointerToRawData
= RosSymOffset
;
667 CurrentSectionHeader
->PointerToRelocations
= 0;
668 CurrentSectionHeader
->PointerToLinenumbers
= 0;
669 CurrentSectionHeader
->NumberOfRelocations
= 0;
670 CurrentSectionHeader
->NumberOfLinenumbers
= 0;
671 CurrentSectionHeader
->Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_DISCARDABLE
672 | IMAGE_SCN_LNK_REMOVE
| IMAGE_SCN_TYPE_NOLOAD
;
673 OutOptHeader
->SizeOfImage
= ROUND_UP(CurrentSectionHeader
->VirtualAddress
+
674 CurrentSectionHeader
->Misc
.VirtualSize
,
675 OutOptHeader
->SectionAlignment
);
676 (OutFileHeader
->NumberOfSections
)++;
678 PaddedRosSym
= malloc(RosSymFileLength
);
679 if (NULL
== PaddedRosSym
)
681 fprintf(stderr
, "Failed to allocate %u bytes for padded .rossym\n", (unsigned int)RosSymFileLength
);
684 memcpy(PaddedRosSym
, RosSymSection
, RosSymLength
);
685 memset((char *) PaddedRosSym
+ RosSymLength
, '\0', RosSymFileLength
- RosSymLength
);
692 for (i
= 0; i
< StartOfRawData
/ 2; i
++)
694 CheckSum
+= ((unsigned short*) OutHeader
)[i
];
695 CheckSum
= 0xffff & (CheckSum
+ (CheckSum
>> 16));
697 Length
= StartOfRawData
;
698 for (Section
= 0; Section
< OutFileHeader
->NumberOfSections
; Section
++)
701 if (OutRelocSection
== OutSectionHeaders
+ Section
)
703 Data
= (void *) ProcessedRelocs
;
704 SizeOfRawData
= ProcessedRelocsLength
;
706 else if (RosSymLength
> 0 && Section
+ 1 == OutFileHeader
->NumberOfSections
)
708 Data
= (void *) PaddedRosSym
;
709 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
713 Data
= (void *) ((char *) InData
+ OutSectionHeaders
[Section
].PointerToRawData
);
714 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
716 for (i
= 0; i
< SizeOfRawData
/ 2; i
++)
718 CheckSum
+= ((unsigned short*) Data
)[i
];
719 CheckSum
= 0xffff & (CheckSum
+ (CheckSum
>> 16));
721 Length
+= OutSectionHeaders
[Section
].SizeOfRawData
;
724 OutOptHeader
->CheckSum
= CheckSum
;
726 if (fwrite(OutHeader
, 1, StartOfRawData
, OutFile
) != StartOfRawData
)
728 perror("Error writing output header\n");
733 for (Section
= 0; Section
< OutFileHeader
->NumberOfSections
; Section
++)
735 if (0 != OutSectionHeaders
[Section
].SizeOfRawData
)
738 fseek(OutFile
, OutSectionHeaders
[Section
].PointerToRawData
, SEEK_SET
);
739 if (OutRelocSection
== OutSectionHeaders
+ Section
)
741 Data
= (void *) ProcessedRelocs
;
742 SizeOfRawData
= ProcessedRelocsLength
;
744 else if (RosSymLength
> 0 && Section
+ 1 == OutFileHeader
->NumberOfSections
)
746 Data
= (void *) PaddedRosSym
;
747 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
751 Data
= (void *) ((char *) InData
+ OutSectionHeaders
[Section
].PointerToRawData
);
752 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
754 if (fwrite(Data
, 1, SizeOfRawData
, OutFile
) != SizeOfRawData
)
756 perror("Error writing section data\n");
773 int main(int argc
, char* argv
[])
775 PSYMBOLFILE_HEADER SymbolFileHeader
;
776 PIMAGE_DOS_HEADER PEDosHeader
;
777 PIMAGE_FILE_HEADER PEFileHeader
;
778 PIMAGE_OPTIONAL_HEADER PEOptHeader
;
779 PIMAGE_SECTION_HEADER PESectionHeaders
;
783 void *StabStringBase
;
784 ULONG StabStringsLength
;
785 void *CoffBase
= NULL
;
787 void *CoffStringBase
= NULL
;
788 ULONG CoffStringsLength
;
794 ULONG StabSymbolsCount
;
795 PROSSYM_ENTRY StabSymbols
;
796 ULONG CoffSymbolsCount
;
797 PROSSYM_ENTRY CoffSymbols
;
798 ULONG MergedSymbolsCount
;
799 PROSSYM_ENTRY MergedSymbols
;
804 char elfhdr
[4] = { '\177', 'E', 'L', 'F' };
808 fprintf(stderr
, "Usage: rsym <exefile> <symfile>\n");
812 path1
= convert_path(argv
[1]);
813 path2
= convert_path(argv
[2]);
815 FileData
= load_file ( path1
, &FileSize
);
818 fprintf ( stderr
, "An error occured loading '%s'\n", path1
);
822 /* Check if MZ header exists */
823 PEDosHeader
= (PIMAGE_DOS_HEADER
) FileData
;
824 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
|| PEDosHeader
->e_lfanew
== 0L)
827 if (!memcmp(PEDosHeader
, elfhdr
, sizeof(elfhdr
)))
829 perror("Input file is not a PE image.\n");
834 /* Locate PE file header */
835 /* sizeof(ULONG) = sizeof(MAGIC) */
836 PEFileHeader
= (PIMAGE_FILE_HEADER
)((char *) FileData
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
838 /* Locate optional header */
839 assert(sizeof(ULONG
) == 4);
840 PEOptHeader
= (PIMAGE_OPTIONAL_HEADER
)(PEFileHeader
+ 1);
841 ImageBase
= PEOptHeader
->ImageBase
;
843 /* Locate PE section headers */
844 PESectionHeaders
= (PIMAGE_SECTION_HEADER
)((char *) PEOptHeader
+ PEFileHeader
->SizeOfOptionalHeader
);
846 if (GetStabInfo(FileData
, PEFileHeader
, PESectionHeaders
, &StabsLength
, &StabBase
,
847 &StabStringsLength
, &StabStringBase
))
853 if (GetCoffInfo(FileData
, PEFileHeader
, PESectionHeaders
, &CoffsLength
, &CoffBase
,
854 &CoffStringsLength
, &CoffStringBase
))
860 StringBase
= malloc(1 + StabStringsLength
+ CoffStringsLength
+
861 (CoffsLength
/ sizeof(ROSSYM_ENTRY
)) * (E_SYMNMLEN
+ 1));
862 if (NULL
== StringBase
)
865 fprintf(stderr
, "Failed to allocate memory for strings table\n");
868 /* Make offset 0 into an empty string */
869 *((char *) StringBase
) = '\0';
872 if (ConvertStabs(&StabSymbolsCount
, &StabSymbols
, &StringsLength
, StringBase
,
873 StabsLength
, StabBase
, StabStringsLength
, StabStringBase
,
874 ImageBase
, PEFileHeader
, PESectionHeaders
))
878 fprintf(stderr
, "Failed to allocate memory for strings table\n");
882 if (ConvertCoffs(&CoffSymbolsCount
, &CoffSymbols
, &StringsLength
, StringBase
,
883 CoffsLength
, CoffBase
, CoffStringsLength
, CoffStringBase
,
884 ImageBase
, PEFileHeader
, PESectionHeaders
))
895 if (MergeStabsAndCoffs(&MergedSymbolsCount
, &MergedSymbols
,
896 StabSymbolsCount
, StabSymbols
,
897 CoffSymbolsCount
, CoffSymbols
))
920 if (MergedSymbolsCount
== 0)
923 RosSymSection
= NULL
;
927 RosSymLength
= sizeof(SYMBOLFILE_HEADER
) + MergedSymbolsCount
* sizeof(ROSSYM_ENTRY
)
929 RosSymSection
= malloc(RosSymLength
);
930 if (NULL
== RosSymSection
)
935 fprintf(stderr
, "Unable to allocate memory for .rossym section\n");
938 memset(RosSymSection
, '\0', RosSymLength
);
940 SymbolFileHeader
= (PSYMBOLFILE_HEADER
) RosSymSection
;
941 SymbolFileHeader
->SymbolsOffset
= sizeof(SYMBOLFILE_HEADER
);
942 SymbolFileHeader
->SymbolsLength
= MergedSymbolsCount
* sizeof(ROSSYM_ENTRY
);
943 SymbolFileHeader
->StringsOffset
= SymbolFileHeader
->SymbolsOffset
+ SymbolFileHeader
->SymbolsLength
;
944 SymbolFileHeader
->StringsLength
= StringsLength
;
946 memcpy((char *) RosSymSection
+ SymbolFileHeader
->SymbolsOffset
, MergedSymbols
,
947 SymbolFileHeader
->SymbolsLength
);
948 memcpy((char *) RosSymSection
+ SymbolFileHeader
->StringsOffset
, StringBase
,
949 SymbolFileHeader
->StringsLength
);
954 out
= fopen(path2
, "wb");
957 perror("Cannot open output file");
963 if (CreateOutputFile(out
, FileData
, PEDosHeader
, PEFileHeader
, PEOptHeader
,
964 PESectionHeaders
, RosSymLength
, RosSymSection
))