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.
23 #include "../../dll/win32/dbghelp/compat.h"
34 #define MAX_SYM_NAME 2000
38 struct StringEntry
*Next
;
43 struct StringHashTable
46 struct StringEntry
**Table
;
49 /* This is the famous DJB hash */
51 ComputeDJBHash(const char *name
)
53 unsigned int val
= 5381;
56 for (i
= 0; name
[i
]; i
++)
58 val
= (33 * val
) + name
[i
];
65 AddStringToHash(struct StringHashTable
*StringTable
,
70 struct StringEntry
*entry
= calloc(1, sizeof(struct StringEntry
));
71 entry
->Offset
= Offset
;
72 entry
->String
= StringPtr
;
73 entry
->Next
= StringTable
->Table
[hash
];
74 StringTable
->Table
[hash
] = entry
;
78 StringHashTableInit(struct StringHashTable
*StringTable
,
82 char *Start
= StringsBase
;
83 char *End
= StringsBase
+ StringsLength
;
84 StringTable
->TableSize
= 1024;
85 StringTable
->Table
= calloc(1024, sizeof(struct StringEntry
*));
88 AddStringToHash(StringTable
,
89 ComputeDJBHash(Start
) % StringTable
->TableSize
,
92 Start
+= strlen(Start
) + 1;
97 StringHashTableFree(struct StringHashTable
*StringTable
)
100 struct StringEntry
*entry
;
101 for (i
= 0; i
< StringTable
->TableSize
; i
++)
103 while ((entry
= StringTable
->Table
[i
]))
106 free(StringTable
->Table
[i
]);
107 StringTable
->Table
[i
] = entry
;
110 free(StringTable
->Table
);
114 CompareSymEntry(const PROSSYM_ENTRY SymEntry1
, const PROSSYM_ENTRY SymEntry2
)
116 if (SymEntry1
->Address
< SymEntry2
->Address
)
121 if (SymEntry2
->Address
< SymEntry1
->Address
)
126 if (SymEntry2
->SourceLine
== 0)
131 if (SymEntry1
->SourceLine
== 0)
140 GetStabInfo(void *FileData
, PIMAGE_FILE_HEADER PEFileHeader
,
141 PIMAGE_SECTION_HEADER PESectionHeaders
,
142 ULONG
*StabSymbolsLength
, void **StabSymbolsBase
,
143 ULONG
*StabStringsLength
, void **StabStringsBase
)
147 /* Load .stab and .stabstr sections if available */
148 *StabSymbolsBase
= NULL
;
149 *StabSymbolsLength
= 0;
150 *StabStringsBase
= NULL
;
151 *StabStringsLength
= 0;
153 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
155 /* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */
156 if ((strncmp((char *) PESectionHeaders
[Idx
].Name
, ".stab", 5) == 0)
157 && (PESectionHeaders
[Idx
].Name
[5] == 0))
159 /* printf(".stab section found. Size %d\n", PESectionHeaders[Idx].SizeOfRawData); */
161 *StabSymbolsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
162 *StabSymbolsBase
= (void *)((char *) FileData
+ PESectionHeaders
[Idx
].PointerToRawData
);
165 if (strncmp((char *) PESectionHeaders
[Idx
].Name
, ".stabstr", 8) == 0)
167 /* printf(".stabstr section found. Size %d\n", PESectionHeaders[Idx].SizeOfRawData); */
169 *StabStringsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
170 *StabStringsBase
= (void *)((char *) FileData
+ PESectionHeaders
[Idx
].PointerToRawData
);
178 GetCoffInfo(void *FileData
, PIMAGE_FILE_HEADER PEFileHeader
,
179 PIMAGE_SECTION_HEADER PESectionHeaders
,
180 ULONG
*CoffSymbolsLength
, void **CoffSymbolsBase
,
181 ULONG
*CoffStringsLength
, void **CoffStringsBase
)
184 if (PEFileHeader
->PointerToSymbolTable
== 0 || PEFileHeader
->NumberOfSymbols
== 0)
186 /* No COFF symbol table */
187 *CoffSymbolsLength
= 0;
188 *CoffStringsLength
= 0;
192 *CoffSymbolsLength
= PEFileHeader
->NumberOfSymbols
* sizeof(COFF_SYMENT
);
193 *CoffSymbolsBase
= (void *)((char *) FileData
+ PEFileHeader
->PointerToSymbolTable
);
194 *CoffStringsLength
= *((ULONG
*) ((char *) *CoffSymbolsBase
+ *CoffSymbolsLength
));
195 *CoffStringsBase
= (void *)((char *) *CoffSymbolsBase
+ *CoffSymbolsLength
);
202 FindOrAddString(struct StringHashTable
*StringTable
,
204 ULONG
*StringsLength
,
207 unsigned int hash
= ComputeDJBHash(StringToFind
) % StringTable
->TableSize
;
208 struct StringEntry
*entry
= StringTable
->Table
[hash
];
210 while (entry
&& strcmp(entry
->String
, StringToFind
))
215 return entry
->Offset
;
219 char *End
= (char *)StringsBase
+ *StringsLength
;
221 strcpy(End
, StringToFind
);
222 *StringsLength
+= strlen(StringToFind
) + 1;
224 AddStringToHash(StringTable
, hash
, End
- (char *)StringsBase
, End
);
226 return End
- (char *)StringsBase
;
231 ConvertStabs(ULONG
*SymbolsCount
, PROSSYM_ENTRY
*SymbolsBase
,
232 ULONG
*StringsLength
, void *StringsBase
,
233 ULONG StabSymbolsLength
, void *StabSymbolsBase
,
234 ULONG StabStringsLength
, void *StabStringsBase
,
235 ULONG_PTR ImageBase
, PIMAGE_FILE_HEADER PEFileHeader
,
236 PIMAGE_SECTION_HEADER PESectionHeaders
)
238 PSTAB_ENTRY StabEntry
;
240 ULONG_PTR Address
, LastFunctionAddress
;
245 PROSSYM_ENTRY Current
;
246 struct StringHashTable StringHash
;
248 StabEntry
= StabSymbolsBase
;
249 Count
= StabSymbolsLength
/ sizeof(STAB_ENTRY
);
259 *SymbolsBase
= malloc(Count
* sizeof(ROSSYM_ENTRY
));
260 if (*SymbolsBase
== NULL
)
262 fprintf(stderr
, "Failed to allocate memory for converted .stab symbols\n");
265 Current
= *SymbolsBase
;
266 memset(Current
, 0, sizeof(*Current
));
268 StringHashTableInit(&StringHash
, *StringsLength
, (char *)StringsBase
);
270 LastFunctionAddress
= 0;
271 for (i
= 0; i
< Count
; i
++)
273 if (LastFunctionAddress
== 0)
275 Address
= StabEntry
[i
].n_value
- ImageBase
;
279 Address
= LastFunctionAddress
+ StabEntry
[i
].n_value
;
281 switch (StabEntry
[i
].n_type
)
286 Name
= (char *) StabStringsBase
+ StabEntry
[i
].n_strx
;
287 if (StabStringsLength
< StabEntry
[i
].n_strx
288 || *Name
== '\0' || Name
[strlen(Name
) - 1] == '/'
289 || Name
[strlen(Name
) - 1] == '\\'
290 || StabEntry
[i
].n_value
< ImageBase
)
294 if (First
|| Address
!= Current
->Address
)
298 memset(++Current
, 0, sizeof(*Current
));
299 Current
->FunctionOffset
= Current
[-1].FunctionOffset
;
303 Current
->Address
= Address
;
305 Current
->FileOffset
= FindOrAddString(&StringHash
,
306 (char *)StabStringsBase
+ StabEntry
[i
].n_strx
,
311 if (StabEntry
[i
].n_desc
== 0 || StabEntry
[i
].n_value
< ImageBase
)
313 LastFunctionAddress
= 0; /* line # 0 = end of function */
316 if (First
|| Address
!= Current
->Address
)
319 memset(++Current
, 0, sizeof(*Current
));
322 Current
->Address
= Address
;
323 Current
->FileOffset
= Current
[-1].FileOffset
;
325 Name
= (char *)StabStringsBase
+ StabEntry
[i
].n_strx
;
326 NameLen
= strcspn(Name
, ":");
327 if (sizeof(FuncName
) <= NameLen
)
330 fprintf(stderr
, "Function name too long\n");
333 memcpy(FuncName
, Name
, NameLen
);
334 FuncName
[NameLen
] = '\0';
335 Current
->FunctionOffset
= FindOrAddString(&StringHash
,
339 Current
->SourceLine
= 0;
340 LastFunctionAddress
= Address
;
343 if (First
|| Address
!= Current
->Address
)
347 memset(++Current
, 0, sizeof(*Current
));
348 Current
->FileOffset
= Current
[-1].FileOffset
;
349 Current
->FunctionOffset
= Current
[-1].FunctionOffset
;
353 Current
->Address
= Address
;
355 Current
->SourceLine
= StabEntry
[i
].n_desc
;
361 *SymbolsCount
= (Current
- *SymbolsBase
+ 1);
363 qsort(*SymbolsBase
, *SymbolsCount
, sizeof(ROSSYM_ENTRY
), (int (*)(const void *, const void *)) CompareSymEntry
);
365 StringHashTableFree(&StringHash
);
371 ConvertCoffs(ULONG
*SymbolsCount
, PROSSYM_ENTRY
*SymbolsBase
,
372 ULONG
*StringsLength
, void *StringsBase
,
373 ULONG CoffSymbolsLength
, void *CoffSymbolsBase
,
374 ULONG CoffStringsLength
, void *CoffStringsBase
,
375 ULONG_PTR ImageBase
, PIMAGE_FILE_HEADER PEFileHeader
,
376 PIMAGE_SECTION_HEADER PESectionHeaders
)
379 PCOFF_SYMENT CoffEntry
;
380 char FuncName
[256], FileName
[1024];
382 PROSSYM_ENTRY Current
;
383 struct StringHashTable StringHash
;
385 CoffEntry
= (PCOFF_SYMENT
) CoffSymbolsBase
;
386 Count
= CoffSymbolsLength
/ sizeof(COFF_SYMENT
);
388 *SymbolsBase
= malloc(Count
* sizeof(ROSSYM_ENTRY
));
389 if (*SymbolsBase
== NULL
)
391 fprintf(stderr
, "Unable to allocate memory for converted COFF symbols\n");
395 Current
= *SymbolsBase
;
397 StringHashTableInit(&StringHash
, *StringsLength
, (char*)StringsBase
);
399 for (i
= 0; i
< Count
; i
++)
401 if (ISFCN(CoffEntry
[i
].e_type
) || C_EXT
== CoffEntry
[i
].e_sclass
)
403 Current
->Address
= CoffEntry
[i
].e_value
;
404 if (CoffEntry
[i
].e_scnum
> 0)
406 if (PEFileHeader
->NumberOfSections
< CoffEntry
[i
].e_scnum
)
410 "Invalid section number %d in COFF symbols (only %d sections present)\n",
411 CoffEntry
[i
].e_scnum
,
412 PEFileHeader
->NumberOfSections
);
415 Current
->Address
+= PESectionHeaders
[CoffEntry
[i
].e_scnum
- 1].VirtualAddress
;
417 Current
->FileOffset
= 0;
418 if (CoffEntry
[i
].e
.e
.e_zeroes
== 0)
420 if (sizeof(FuncName
) <= strlen((char *) CoffStringsBase
+ CoffEntry
[i
].e
.e
.e_offset
))
423 fprintf(stderr
, "Function name too long\n");
424 StringHashTableFree(&StringHash
);
427 strcpy(FuncName
, (char *) CoffStringsBase
+ CoffEntry
[i
].e
.e
.e_offset
);
431 memcpy(FuncName
, CoffEntry
[i
].e
.e_name
, E_SYMNMLEN
);
432 FuncName
[E_SYMNMLEN
] = '\0';
435 /* Name demangling: stdcall */
436 p
= strrchr(FuncName
, '@');
441 p
= ('_' == FuncName
[0] || '@' == FuncName
[0] ? FuncName
+ 1 : FuncName
);
442 Current
->FunctionOffset
= FindOrAddString(&StringHash
,
446 Current
->SourceLine
= 0;
447 memset(++Current
, 0, sizeof(*Current
));
450 i
+= CoffEntry
[i
].e_numaux
;
453 *SymbolsCount
= (Current
- *SymbolsBase
+ 1);
454 qsort(*SymbolsBase
, *SymbolsCount
, sizeof(ROSSYM_ENTRY
), (int (*)(const void *, const void *)) CompareSymEntry
);
456 StringHashTableFree(&StringHash
);
461 struct DbgHelpLineEntry
{
468 struct DbgHelpStringTab
{
472 ULONG LineEntries
, CurLineEntries
;
473 struct DbgHelpLineEntry
*LineEntryData
;
478 struct DbgHelpLineEntry
*lastLineEntry
;
481 static struct DbgHelpLineEntry
*
482 DbgHelpAddLineEntry(struct DbgHelpStringTab
*tab
)
484 if (tab
->CurLineEntries
== tab
->LineEntries
)
486 struct DbgHelpLineEntry
*newEntries
= realloc(tab
->LineEntryData
,
487 tab
->LineEntries
* 2 * sizeof(struct DbgHelpLineEntry
));
492 tab
->LineEntryData
= newEntries
;
494 memset(tab
->LineEntryData
+ tab
->LineEntries
, 0, sizeof(struct DbgHelpLineEntry
) * tab
->LineEntries
);
495 tab
->LineEntries
*= 2;
498 return &tab
->LineEntryData
[tab
->CurLineEntries
++];
502 DbgHelpAddStringToTable(struct DbgHelpStringTab
*tab
, char *name
)
504 unsigned int bucket
= ComputeDJBHash(name
) % tab
->Length
;
505 char **tabEnt
= tab
->Table
[bucket
];
511 for (i
= 0; tabEnt
[i
] && strcmp(tabEnt
[i
], name
); i
++);
515 return (i
<< 10) | bucket
;
521 /* At this point, we need to insert */
522 tab
->Bytes
+= strlen(name
) + 1;
524 newBucket
= realloc(tab
->Table
[bucket
], (i
+2) * sizeof(char *));
528 fprintf(stderr
, "realloc failed!\n");
532 tab
->Table
[bucket
] = newBucket
;
533 tab
->Table
[bucket
][i
+1] = 0;
534 tab
->Table
[bucket
][i
] = name
;
535 return (i
<< 10) | bucket
;
539 DbgHelpGetString(struct DbgHelpStringTab
*tab
, int id
)
542 int bucket
= id
& 0x3ff;
543 return tab
->Table
[bucket
][i
];
546 /* Remove a prefix of PathChop if it exists and return a copy of the tail. */
548 StrDupShortenPath(char *PathChop
, char *FilePath
)
550 int pclen
= strlen(PathChop
);
551 if (!strncmp(FilePath
, PathChop
, pclen
))
553 return strdup(FilePath
+pclen
);
557 return strdup(FilePath
);
562 DbgHelpAddLineNumber(PSRCCODEINFO LineInfo
, void *UserContext
)
564 struct DbgHelpStringTab
*tab
= (struct DbgHelpStringTab
*)UserContext
;
566 int fileId
, functionId
;
567 PSYMBOL_INFO pSymbol
= malloc(FIELD_OFFSET(SYMBOL_INFO
, Name
[MAX_SYM_NAME
]));
568 if (!pSymbol
) return FALSE
;
569 memset(pSymbol
, 0, FIELD_OFFSET(SYMBOL_INFO
, Name
[MAX_SYM_NAME
]));
571 /* If any file can be opened by relative path up to a certain level, then
576 char *end
= strrchr(LineInfo
->FileName
, '/');
579 end
= strrchr(LineInfo
->FileName
, '\\');
583 for (i
= (end
- LineInfo
->FileName
) - 1; i
>= 0; i
--)
585 if (LineInfo
->FileName
[i
] == '/' || LineInfo
->FileName
[i
] == '\\')
587 char *synthname
= malloc(strlen(tab
->SourcePath
) +
588 strlen(LineInfo
->FileName
+ i
+ 1)
590 strcpy(synthname
, tab
->SourcePath
);
591 strcat(synthname
, "/");
592 strcat(synthname
, LineInfo
->FileName
+ i
+ 1);
593 FILE *f
= fopen(synthname
, "r");
603 i
++; /* Be in the string or past the next slash */
604 tab
->PathChop
= malloc(i
+ 1);
605 memcpy(tab
->PathChop
, LineInfo
->FileName
, i
);
606 tab
->PathChop
[i
] = 0;
610 fileId
= DbgHelpAddStringToTable(tab
,
611 StrDupShortenPath(tab
->PathChop
,
612 LineInfo
->FileName
));
614 pSymbol
->SizeOfStruct
= sizeof(SYMBOL_INFO
);
615 pSymbol
->MaxNameLen
= MAX_SYM_NAME
;
617 if (!SymFromAddr(tab
->process
, LineInfo
->Address
, &disp
, pSymbol
))
619 //fprintf(stderr, "SymFromAddr failed.\n");
624 functionId
= DbgHelpAddStringToTable(tab
, strdup(pSymbol
->Name
));
626 if (LineInfo
->Address
== 0)
627 fprintf(stderr
, "Address is 0.\n");
629 tab
->lastLineEntry
= DbgHelpAddLineEntry(tab
);
630 tab
->lastLineEntry
->vma
= LineInfo
->Address
- LineInfo
->ModBase
;
631 tab
->lastLineEntry
->functionId
= functionId
;
632 tab
->lastLineEntry
->fileId
= fileId
;
633 tab
->lastLineEntry
->line
= LineInfo
->LineNumber
;
640 ConvertDbgHelp(void *process
, DWORD module_base
, char *SourcePath
,
641 ULONG
*SymbolsCount
, PROSSYM_ENTRY
*SymbolsBase
,
642 ULONG
*StringsLength
, void **StringsBase
)
644 char *strings
, *strings_copy
;
645 int i
, j
, bucket
, entry
;
646 PROSSYM_ENTRY rossym
;
647 struct DbgHelpStringTab strtab
= { 0 };
649 strtab
.process
= process
;
650 strtab
.module_base
= module_base
;
652 strtab
.Length
= 1024;
653 strtab
.Table
= calloc(1024, sizeof(const char **));
654 strtab
.Table
[0] = calloc(2, sizeof(const char *));
655 strtab
.Table
[0][0] = strdup(""); // The zero string
656 strtab
.CurLineEntries
= 0;
657 strtab
.LineEntries
= 16384;
658 strtab
.LineEntryData
= calloc(strtab
.LineEntries
, sizeof(struct DbgHelpLineEntry
));
659 strtab
.PathChop
= NULL
;
660 strtab
.SourcePath
= SourcePath
? SourcePath
: "";
662 SymEnumLines(process
, module_base
, NULL
, NULL
, DbgHelpAddLineNumber
, &strtab
);
664 /* Transcribe necessary strings */
665 *StringsLength
= strtab
.Bytes
;
666 strings
= strings_copy
= ((char *)(*StringsBase
= malloc(strtab
.Bytes
)));
668 /* Copy in strings */
669 for (i
= 0; i
< strtab
.Length
; i
++)
671 for (j
= 0; strtab
.Table
[i
] && strtab
.Table
[i
][j
]; j
++)
673 /* Each entry is replaced by its corresponding entry in our string
674 section. We can substract the strings origin to get an offset. */
675 char *toFree
= strtab
.Table
[i
][j
];
676 strtab
.Table
[i
][j
] = strcpy(strings_copy
, strtab
.Table
[i
][j
]);
678 strings_copy
+= strlen(strings_copy
) + 1;
682 assert(strings_copy
== strings
+ strtab
.Bytes
);
684 *SymbolsBase
= calloc(strtab
.CurLineEntries
, sizeof(ROSSYM_ENTRY
));
685 *SymbolsCount
= strtab
.CurLineEntries
;
687 /* Copy symbols into rossym entries */
688 for (i
= 0; i
< strtab
.CurLineEntries
; i
++)
690 rossym
= &(*SymbolsBase
)[i
];
691 rossym
->Address
= strtab
.LineEntryData
[i
].vma
;
692 bucket
= strtab
.LineEntryData
[i
].fileId
& 0x3ff;
693 entry
= strtab
.LineEntryData
[i
].fileId
>> 10;
694 rossym
->FileOffset
= strtab
.Table
[bucket
][entry
] - strings
;
695 bucket
= strtab
.LineEntryData
[i
].functionId
& 0x3ff;
696 entry
= strtab
.LineEntryData
[i
].functionId
>> 10;
697 rossym
->FunctionOffset
= strtab
.Table
[bucket
][entry
] - strings
;
698 rossym
->SourceLine
= strtab
.LineEntryData
[i
].line
;
702 for (i
= 0; i
< strtab
.Length
; i
++)
704 free(strtab
.Table
[i
]);
707 free(strtab
.LineEntryData
);
708 free(strtab
.PathChop
);
710 qsort(*SymbolsBase
, *SymbolsCount
, sizeof(ROSSYM_ENTRY
), (int (*)(const void *, const void *))CompareSymEntry
);
716 MergeStabsAndCoffs(ULONG
*MergedSymbolCount
, PROSSYM_ENTRY
*MergedSymbols
,
717 ULONG StabSymbolsCount
, PROSSYM_ENTRY StabSymbols
,
718 ULONG CoffSymbolsCount
, PROSSYM_ENTRY CoffSymbols
)
722 ULONG_PTR StabFunctionStartAddress
;
723 ULONG StabFunctionStringOffset
, NewStabFunctionStringOffset
;
725 *MergedSymbolCount
= 0;
726 if (StabSymbolsCount
== 0)
728 *MergedSymbols
= NULL
;
731 *MergedSymbols
= malloc((StabSymbolsCount
+ CoffSymbolsCount
) * sizeof(ROSSYM_ENTRY
));
732 if (*MergedSymbols
== NULL
)
734 fprintf(stderr
, "Unable to allocate memory for merged symbols\n");
738 StabFunctionStartAddress
= 0;
739 StabFunctionStringOffset
= 0;
741 for (StabIndex
= 0; StabIndex
< StabSymbolsCount
; StabIndex
++)
743 (*MergedSymbols
)[*MergedSymbolCount
] = StabSymbols
[StabIndex
];
744 for (j
= StabIndex
+ 1;
745 j
< StabSymbolsCount
&& StabSymbols
[j
].Address
== StabSymbols
[StabIndex
].Address
;
748 if (StabSymbols
[j
].FileOffset
!= 0 && (*MergedSymbols
)[*MergedSymbolCount
].FileOffset
== 0)
750 (*MergedSymbols
)[*MergedSymbolCount
].FileOffset
= StabSymbols
[j
].FileOffset
;
752 if (StabSymbols
[j
].FunctionOffset
!= 0 && (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
== 0)
754 (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
= StabSymbols
[j
].FunctionOffset
;
756 if (StabSymbols
[j
].SourceLine
!= 0 && (*MergedSymbols
)[*MergedSymbolCount
].SourceLine
== 0)
758 (*MergedSymbols
)[*MergedSymbolCount
].SourceLine
= StabSymbols
[j
].SourceLine
;
763 while (CoffIndex
< CoffSymbolsCount
&&
764 CoffSymbols
[CoffIndex
+ 1].Address
<= (*MergedSymbols
)[*MergedSymbolCount
].Address
)
768 NewStabFunctionStringOffset
= (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
;
769 if (CoffSymbolsCount
> 0 &&
770 CoffSymbols
[CoffIndex
].Address
< (*MergedSymbols
)[*MergedSymbolCount
].Address
&&
771 StabFunctionStartAddress
< CoffSymbols
[CoffIndex
].Address
&&
772 CoffSymbols
[CoffIndex
].FunctionOffset
!= 0)
774 (*MergedSymbols
)[*MergedSymbolCount
].FunctionOffset
= CoffSymbols
[CoffIndex
].FunctionOffset
;
775 CoffSymbols
[CoffIndex
].FileOffset
= CoffSymbols
[CoffIndex
].FunctionOffset
= 0;
777 if (StabFunctionStringOffset
!= NewStabFunctionStringOffset
)
779 StabFunctionStartAddress
= (*MergedSymbols
)[*MergedSymbolCount
].Address
;
781 StabFunctionStringOffset
= NewStabFunctionStringOffset
;
782 (*MergedSymbolCount
)++;
784 /* Handle functions that have no analog in the upstream data */
785 for (CoffIndex
= 0; CoffIndex
< CoffSymbolsCount
; CoffIndex
++)
787 if (CoffSymbols
[CoffIndex
].Address
&&
788 CoffSymbols
[CoffIndex
].FunctionOffset
)
790 (*MergedSymbols
)[*MergedSymbolCount
] = CoffSymbols
[CoffIndex
];
791 (*MergedSymbolCount
)++;
795 qsort(*MergedSymbols
, *MergedSymbolCount
, sizeof(ROSSYM_ENTRY
), (int (*)(const void *, const void *)) CompareSymEntry
);
800 static PIMAGE_SECTION_HEADER
801 FindSectionForRVA(DWORD RVA
, unsigned NumberOfSections
, PIMAGE_SECTION_HEADER SectionHeaders
)
805 for (Section
= 0; Section
< NumberOfSections
; Section
++)
807 if (SectionHeaders
[Section
].VirtualAddress
<= RVA
&&
808 RVA
< SectionHeaders
[Section
].VirtualAddress
+ SectionHeaders
[Section
].Misc
.VirtualSize
)
810 return SectionHeaders
+ Section
;
818 ProcessRelocations(ULONG
*ProcessedRelocsLength
, void **ProcessedRelocs
,
819 void *RawData
, PIMAGE_OPTIONAL_HEADER OptHeader
,
820 unsigned NumberOfSections
, PIMAGE_SECTION_HEADER SectionHeaders
)
822 PIMAGE_SECTION_HEADER RelocSectionHeader
, TargetSectionHeader
;
823 PIMAGE_BASE_RELOCATION BaseReloc
, End
, AcceptedRelocs
;
826 if (OptHeader
->NumberOfRvaAndSizes
< IMAGE_DIRECTORY_ENTRY_BASERELOC
||
827 OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0)
829 /* No relocation entries */
830 *ProcessedRelocsLength
= 0;
831 *ProcessedRelocs
= NULL
;
835 RelocSectionHeader
= FindSectionForRVA(OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
,
836 NumberOfSections
, SectionHeaders
);
837 if (RelocSectionHeader
== NULL
)
839 fprintf(stderr
, "Can't find section header for relocation data\n");
843 *ProcessedRelocs
= malloc(RelocSectionHeader
->SizeOfRawData
);
844 if (*ProcessedRelocs
== NULL
)
847 "Failed to allocate %u bytes for relocations\n",
848 (unsigned int)RelocSectionHeader
->SizeOfRawData
);
851 *ProcessedRelocsLength
= 0;
853 BaseReloc
= (PIMAGE_BASE_RELOCATION
) ((char *) RawData
+
854 RelocSectionHeader
->PointerToRawData
+
855 (OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
-
856 RelocSectionHeader
->VirtualAddress
));
857 End
= (PIMAGE_BASE_RELOCATION
) ((char *) BaseReloc
+
858 OptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
);
860 while (BaseReloc
< End
&& BaseReloc
->SizeOfBlock
> 0)
862 TargetSectionHeader
= FindSectionForRVA(BaseReloc
->VirtualAddress
,
865 if (TargetSectionHeader
!= NULL
)
867 AcceptedRelocs
= *ProcessedRelocs
;
869 while (AcceptedRelocs
< (PIMAGE_BASE_RELOCATION
) ((char *) *ProcessedRelocs
+
870 *ProcessedRelocsLength
)
873 Found
= BaseReloc
->SizeOfBlock
== AcceptedRelocs
->SizeOfBlock
&&
874 memcmp(BaseReloc
, AcceptedRelocs
, AcceptedRelocs
->SizeOfBlock
) == 0;
875 AcceptedRelocs
= (PIMAGE_BASE_RELOCATION
) ((char *) AcceptedRelocs
+
876 AcceptedRelocs
->SizeOfBlock
);
880 memcpy((char *) *ProcessedRelocs
+ *ProcessedRelocsLength
,
882 BaseReloc
->SizeOfBlock
);
883 *ProcessedRelocsLength
+= BaseReloc
->SizeOfBlock
;
886 BaseReloc
= (PIMAGE_BASE_RELOCATION
)((char *) BaseReloc
+ BaseReloc
->SizeOfBlock
);
893 GetSectionName(void *StringsBase
, const BYTE
*SectionTitle
)
895 if (SectionTitle
[0] == '/')
897 int offset
= atoi((char*)SectionTitle
+1);
898 return ((BYTE
*)StringsBase
) + offset
;
905 CreateOutputFile(FILE *OutFile
, void *InData
,
906 PIMAGE_DOS_HEADER InDosHeader
, PIMAGE_FILE_HEADER InFileHeader
,
907 PIMAGE_OPTIONAL_HEADER InOptHeader
, PIMAGE_SECTION_HEADER InSectionHeaders
,
908 ULONG RosSymLength
, void *RosSymSection
)
910 ULONG StartOfRawData
;
912 void *OutHeader
, *ProcessedRelocs
, *PaddedRosSym
, *Data
;
913 unsigned char *PaddedStringTable
;
914 PIMAGE_DOS_HEADER OutDosHeader
;
915 PIMAGE_FILE_HEADER OutFileHeader
;
916 PIMAGE_OPTIONAL_HEADER OutOptHeader
;
917 PIMAGE_SECTION_HEADER OutSectionHeaders
, CurrentSectionHeader
;
920 ULONG ProcessedRelocsLength
;
921 ULONG RosSymOffset
, RosSymFileLength
;
922 ULONG PaddedStringTableLength
;
923 int InRelocSectionIndex
;
924 PIMAGE_SECTION_HEADER OutRelocSection
;
925 /* Each coff symbol is 18 bytes and the string table follows */
926 char *StringTable
= (char *)InData
+
927 InFileHeader
->PointerToSymbolTable
+ 18 * InFileHeader
->NumberOfSymbols
;
928 ULONG StringTableLength
= 0;
929 ULONG StringTableLocation
;
932 for (Section
= 0; Section
< InFileHeader
->NumberOfSections
; Section
++)
934 const BYTE
*SectionName
= GetSectionName(StringTable
,
935 InSectionHeaders
[Section
].Name
);
936 if (InSectionHeaders
[Section
].Name
[0] == '/')
938 StringTableLength
= atoi((const char *)InSectionHeaders
[Section
].Name
+ 1) +
939 strlen((const char *)SectionName
) + 1;
941 if ((StartOfRawData
== 0 || InSectionHeaders
[Section
].PointerToRawData
< StartOfRawData
)
942 && InSectionHeaders
[Section
].PointerToRawData
!= 0
943 && (strncmp((char *) SectionName
, ".stab", 5)) != 0
944 && (strncmp((char *) SectionName
, ".debug_", 7)) != 0)
946 StartOfRawData
= InSectionHeaders
[Section
].PointerToRawData
;
949 OutHeader
= malloc(StartOfRawData
);
950 if (OutHeader
== NULL
)
953 "Failed to allocate %u bytes for output file header\n",
954 (unsigned int)StartOfRawData
);
957 memset(OutHeader
, '\0', StartOfRawData
);
959 OutDosHeader
= (PIMAGE_DOS_HEADER
) OutHeader
;
960 memcpy(OutDosHeader
, InDosHeader
, InDosHeader
->e_lfanew
+ sizeof(ULONG
));
962 OutFileHeader
= (PIMAGE_FILE_HEADER
)((char *) OutHeader
+ OutDosHeader
->e_lfanew
+ sizeof(ULONG
));
963 memcpy(OutFileHeader
, InFileHeader
, sizeof(IMAGE_FILE_HEADER
));
964 OutFileHeader
->PointerToSymbolTable
= 0;
965 OutFileHeader
->NumberOfSymbols
= 0;
966 OutFileHeader
->Characteristics
&= ~(IMAGE_FILE_LINE_NUMS_STRIPPED
| IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
967 IMAGE_FILE_DEBUG_STRIPPED
);
969 OutOptHeader
= (PIMAGE_OPTIONAL_HEADER
)(OutFileHeader
+ 1);
970 memcpy(OutOptHeader
, InOptHeader
, sizeof(IMAGE_OPTIONAL_HEADER
));
971 OutOptHeader
->CheckSum
= 0;
973 OutSectionHeaders
= (PIMAGE_SECTION_HEADER
)((char *) OutOptHeader
+ OutFileHeader
->SizeOfOptionalHeader
);
975 if (ProcessRelocations(&ProcessedRelocsLength
,
979 InFileHeader
->NumberOfSections
,
984 if (InOptHeader
->NumberOfRvaAndSizes
< IMAGE_DIRECTORY_ENTRY_BASERELOC
||
985 InOptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0)
987 InRelocSectionIndex
= -1;
991 InRelocSectionIndex
= FindSectionForRVA(InOptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
,
992 InFileHeader
->NumberOfSections
, InSectionHeaders
) - InSectionHeaders
;
995 OutFileHeader
->NumberOfSections
= 0;
996 CurrentSectionHeader
= OutSectionHeaders
;
997 OutOptHeader
->SizeOfImage
= 0;
999 OutRelocSection
= NULL
;
1001 StringTableLocation
= StartOfRawData
;
1003 for (Section
= 0; Section
< InFileHeader
->NumberOfSections
; Section
++)
1005 const BYTE
*SectionName
= GetSectionName(StringTable
,
1006 InSectionHeaders
[Section
].Name
);
1007 if ((strncmp((char *) SectionName
, ".stab", 5) != 0) &&
1008 (strncmp((char *) SectionName
, ".debug_", 7)) != 0)
1010 *CurrentSectionHeader
= InSectionHeaders
[Section
];
1011 CurrentSectionHeader
->PointerToLinenumbers
= 0;
1012 CurrentSectionHeader
->NumberOfLinenumbers
= 0;
1013 if (OutOptHeader
->SizeOfImage
< CurrentSectionHeader
->VirtualAddress
+
1014 CurrentSectionHeader
->Misc
.VirtualSize
)
1016 OutOptHeader
->SizeOfImage
= ROUND_UP(CurrentSectionHeader
->VirtualAddress
+
1017 CurrentSectionHeader
->Misc
.VirtualSize
,
1018 OutOptHeader
->SectionAlignment
);
1020 if (RosSymOffset
< CurrentSectionHeader
->PointerToRawData
+ CurrentSectionHeader
->SizeOfRawData
)
1022 RosSymOffset
= CurrentSectionHeader
->PointerToRawData
+ CurrentSectionHeader
->SizeOfRawData
;
1024 if (Section
== (ULONG
)InRelocSectionIndex
)
1026 OutRelocSection
= CurrentSectionHeader
;
1028 StringTableLocation
= CurrentSectionHeader
->PointerToRawData
+ CurrentSectionHeader
->SizeOfRawData
;
1029 OutFileHeader
->NumberOfSections
++;
1030 CurrentSectionHeader
++;
1034 if (OutRelocSection
== CurrentSectionHeader
- 1)
1036 OutOptHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= ProcessedRelocsLength
;
1037 if (OutOptHeader
->SizeOfImage
== OutRelocSection
->VirtualAddress
+
1038 ROUND_UP(OutRelocSection
->Misc
.VirtualSize
,
1039 OutOptHeader
->SectionAlignment
))
1041 OutOptHeader
->SizeOfImage
= OutRelocSection
->VirtualAddress
+
1042 ROUND_UP(ProcessedRelocsLength
,
1043 OutOptHeader
->SectionAlignment
);
1045 OutRelocSection
->Misc
.VirtualSize
= ProcessedRelocsLength
;
1046 if (RosSymOffset
== OutRelocSection
->PointerToRawData
+
1047 OutRelocSection
->SizeOfRawData
)
1049 RosSymOffset
= OutRelocSection
->PointerToRawData
+
1050 ROUND_UP(ProcessedRelocsLength
,
1051 OutOptHeader
->FileAlignment
);
1053 OutRelocSection
->SizeOfRawData
= ROUND_UP(ProcessedRelocsLength
,
1054 OutOptHeader
->FileAlignment
);
1057 if (RosSymLength
> 0)
1059 RosSymFileLength
= ROUND_UP(RosSymLength
, OutOptHeader
->FileAlignment
);
1060 memcpy(CurrentSectionHeader
->Name
, ".rossym", 8); /* We're lucky: string is exactly 8 bytes long */
1061 CurrentSectionHeader
->Misc
.VirtualSize
= RosSymLength
;
1062 CurrentSectionHeader
->VirtualAddress
= OutOptHeader
->SizeOfImage
;
1063 CurrentSectionHeader
->SizeOfRawData
= RosSymFileLength
;
1064 CurrentSectionHeader
->PointerToRawData
= RosSymOffset
;
1065 CurrentSectionHeader
->PointerToRelocations
= 0;
1066 CurrentSectionHeader
->PointerToLinenumbers
= 0;
1067 CurrentSectionHeader
->NumberOfRelocations
= 0;
1068 CurrentSectionHeader
->NumberOfLinenumbers
= 0;
1069 CurrentSectionHeader
->Characteristics
= IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_DISCARDABLE
1070 | IMAGE_SCN_LNK_REMOVE
| IMAGE_SCN_TYPE_NOLOAD
;
1071 OutOptHeader
->SizeOfImage
= ROUND_UP(CurrentSectionHeader
->VirtualAddress
+ CurrentSectionHeader
->Misc
.VirtualSize
,
1072 OutOptHeader
->SectionAlignment
);
1073 OutFileHeader
->NumberOfSections
++;
1075 PaddedRosSym
= malloc(RosSymFileLength
);
1076 if (PaddedRosSym
== NULL
)
1079 "Failed to allocate %u bytes for padded .rossym\n",
1080 (unsigned int)RosSymFileLength
);
1083 memcpy(PaddedRosSym
, RosSymSection
, RosSymLength
);
1084 memset((char *) PaddedRosSym
+ RosSymLength
,
1086 RosSymFileLength
- RosSymLength
);
1088 /* Position the string table after our new section */
1089 StringTableLocation
= RosSymOffset
+ RosSymFileLength
;
1093 PaddedRosSym
= NULL
;
1096 /* Set the string table area in the header if we need it */
1097 if (StringTableLength
)
1099 OutFileHeader
->PointerToSymbolTable
= StringTableLocation
;
1100 OutFileHeader
->NumberOfSymbols
= 0;
1104 for (i
= 0; i
< StartOfRawData
/ 2; i
++)
1106 CheckSum
+= ((unsigned short*) OutHeader
)[i
];
1107 CheckSum
= 0xffff & (CheckSum
+ (CheckSum
>> 16));
1109 Length
= StartOfRawData
;
1110 for (Section
= 0; Section
< OutFileHeader
->NumberOfSections
; Section
++)
1112 DWORD SizeOfRawData
;
1113 if (OutRelocSection
== OutSectionHeaders
+ Section
)
1115 Data
= (void *) ProcessedRelocs
;
1116 SizeOfRawData
= ProcessedRelocsLength
;
1118 else if (RosSymLength
> 0 && Section
+ 1 == OutFileHeader
->NumberOfSections
)
1120 Data
= (void *) PaddedRosSym
;
1121 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
1125 Data
= (void *) ((char *) InData
+ OutSectionHeaders
[Section
].PointerToRawData
);
1126 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
1128 for (i
= 0; i
< SizeOfRawData
/ 2; i
++)
1130 CheckSum
+= ((unsigned short*) Data
)[i
];
1131 CheckSum
= 0xffff & (CheckSum
+ (CheckSum
>> 16));
1133 Length
+= OutSectionHeaders
[Section
].SizeOfRawData
;
1136 if (OutFileHeader
->PointerToSymbolTable
)
1138 int PaddingFrom
= (OutFileHeader
->PointerToSymbolTable
+ StringTableLength
) %
1139 OutOptHeader
->FileAlignment
;
1140 int PaddingSize
= PaddingFrom
? OutOptHeader
->FileAlignment
- PaddingFrom
: 0;
1142 PaddedStringTableLength
= StringTableLength
+ PaddingSize
;
1143 PaddedStringTable
= malloc(PaddedStringTableLength
);
1144 /* COFF string section is preceeded by a length */
1145 assert(sizeof(StringTableLength
) == 4);
1146 memcpy(PaddedStringTable
, &StringTableLength
, sizeof(StringTableLength
));
1147 /* We just copy enough of the string table to contain the strings we want
1148 The string table length technically counts as part of the string table
1150 memcpy(PaddedStringTable
+ 4, StringTable
+ 4, StringTableLength
- 4);
1151 memset(PaddedStringTable
+ StringTableLength
, 0, PaddingSize
);
1153 assert(OutFileHeader
->PointerToSymbolTable
% 2 == 0);
1154 for (i
= 0; i
< PaddedStringTableLength
/ 2; i
++)
1156 CheckSum
+= ((unsigned short*)PaddedStringTable
)[i
];
1157 CheckSum
= 0xffff & (CheckSum
+ (CheckSum
>> 16));
1159 Length
+= PaddedStringTableLength
;
1163 PaddedStringTable
= NULL
;
1167 OutOptHeader
->CheckSum
= CheckSum
;
1169 if (fwrite(OutHeader
, 1, StartOfRawData
, OutFile
) != StartOfRawData
)
1171 perror("Error writing output header\n");
1176 for (Section
= 0; Section
< OutFileHeader
->NumberOfSections
; Section
++)
1178 if (OutSectionHeaders
[Section
].SizeOfRawData
!= 0)
1180 DWORD SizeOfRawData
;
1181 fseek(OutFile
, OutSectionHeaders
[Section
].PointerToRawData
, SEEK_SET
);
1182 if (OutRelocSection
== OutSectionHeaders
+ Section
)
1184 Data
= (void *) ProcessedRelocs
;
1185 SizeOfRawData
= ProcessedRelocsLength
;
1187 else if (RosSymLength
> 0 && Section
+ 1 == OutFileHeader
->NumberOfSections
)
1189 Data
= (void *) PaddedRosSym
;
1190 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
1194 Data
= (void *) ((char *) InData
+ OutSectionHeaders
[Section
].PointerToRawData
);
1195 SizeOfRawData
= OutSectionHeaders
[Section
].SizeOfRawData
;
1197 if (fwrite(Data
, 1, SizeOfRawData
, OutFile
) != SizeOfRawData
)
1199 perror("Error writing section data\n");
1207 if (PaddedStringTable
)
1209 fseek(OutFile
, OutFileHeader
->PointerToSymbolTable
, SEEK_SET
);
1210 fwrite(PaddedStringTable
, 1, PaddedStringTableLength
, OutFile
);
1211 free(PaddedStringTable
);
1223 int main(int argc
, char* argv
[])
1225 PSYMBOLFILE_HEADER SymbolFileHeader
;
1226 PIMAGE_DOS_HEADER PEDosHeader
;
1227 PIMAGE_FILE_HEADER PEFileHeader
;
1228 PIMAGE_OPTIONAL_HEADER PEOptHeader
;
1229 PIMAGE_SECTION_HEADER PESectionHeaders
;
1233 void *StabStringBase
;
1234 ULONG StabStringsLength
;
1235 void *CoffBase
= NULL
;
1237 void *CoffStringBase
= NULL
;
1238 ULONG CoffStringsLength
;
1242 void *StringBase
= NULL
;
1243 ULONG StringsLength
= 0;
1244 ULONG StabSymbolsCount
= 0;
1245 PROSSYM_ENTRY StabSymbols
= NULL
;
1246 ULONG CoffSymbolsCount
= 0;
1247 PROSSYM_ENTRY CoffSymbols
= NULL
;
1248 ULONG MergedSymbolsCount
= 0;
1249 PROSSYM_ENTRY MergedSymbols
= NULL
;
1253 void *RosSymSection
;
1256 char elfhdr
[4] = { '\177', 'E', 'L', 'F' };
1257 BOOLEAN UseDbgHelp
= FALSE
;
1258 int arg
, argstate
= 0;
1259 char *SourcePath
= NULL
;
1261 for (arg
= 1; arg
< argc
; arg
++)
1270 if (!strcmp(argv
[arg
], "-s"))
1277 path1
= convert_path(argv
[arg
]);
1283 SourcePath
= strdup(argv
[arg
]);
1288 path2
= convert_path(argv
[arg
]);
1296 fprintf(stderr
, "Usage: rsym [-s <sources>] <input> <output>\n");
1300 FileData
= load_file(path1
, &FileSize
);
1303 fprintf(stderr
, "An error occured loading '%s'\n", path1
);
1307 file
= fopen(path1
, "rb");
1309 /* Check if MZ header exists */
1310 PEDosHeader
= (PIMAGE_DOS_HEADER
) FileData
;
1311 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
||
1312 PEDosHeader
->e_lfanew
== 0L)
1315 if (!memcmp(PEDosHeader
, elfhdr
, sizeof(elfhdr
)))
1317 perror("Input file is not a PE image.\n");
1322 /* Locate PE file header */
1323 /* sizeof(ULONG) = sizeof(MAGIC) */
1324 PEFileHeader
= (PIMAGE_FILE_HEADER
)((char *) FileData
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1326 /* Locate optional header */
1327 assert(sizeof(ULONG
) == 4);
1328 PEOptHeader
= (PIMAGE_OPTIONAL_HEADER
)(PEFileHeader
+ 1);
1329 ImageBase
= PEOptHeader
->ImageBase
;
1331 /* Locate PE section headers */
1332 PESectionHeaders
= (PIMAGE_SECTION_HEADER
)((char *) PEOptHeader
+ PEFileHeader
->SizeOfOptionalHeader
);
1334 if (GetStabInfo(FileData
,
1346 if (StabsLength
== 0)
1348 // SYMOPT_AUTO_PUBLICS
1349 // SYMOPT_FAVOR_COMPRESSED
1350 // SYMOPT_LOAD_ANYTHING
1351 // SYMOPT_LOAD_LINES
1352 SymSetOptions(0x10000 | 0x800000 | 0x40 | 0x10);
1353 SymInitialize(FileData
, ".", 0);
1355 module_base
= SymLoadModule(FileData
, file
, path1
, path1
, 0, FileSize
) & 0xffffffff;
1357 if (ConvertDbgHelp(FileData
,
1370 SymUnloadModule(FileData
, module_base
);
1371 SymCleanup(FileData
);
1374 if (GetCoffInfo(FileData
,
1388 StringBase
= malloc(1 + StringsLength
+ CoffStringsLength
+
1389 (CoffsLength
/ sizeof(ROSSYM_ENTRY
)) * (E_SYMNMLEN
+ 1));
1390 if (StringBase
== NULL
)
1393 fprintf(stderr
, "Failed to allocate memory for strings table\n");
1396 /* Make offset 0 into an empty string */
1397 *((char *) StringBase
) = '\0';
1400 if (ConvertStabs(&StabSymbolsCount
,
1414 fprintf(stderr
, "Failed to allocate memory for strings table\n");
1420 StringBase
= realloc(StringBase
, StringsLength
+ CoffStringsLength
);
1424 fprintf(stderr
, "Failed to allocate memory for strings table\n");
1429 if (ConvertCoffs(&CoffSymbolsCount
,
1450 if (MergeStabsAndCoffs(&MergedSymbolsCount
,
1478 if (MergedSymbolsCount
== 0)
1481 RosSymSection
= NULL
;
1485 RosSymLength
= sizeof(SYMBOLFILE_HEADER
) +
1486 MergedSymbolsCount
* sizeof(ROSSYM_ENTRY
) +
1489 RosSymSection
= malloc(RosSymLength
);
1490 if (RosSymSection
== NULL
)
1492 free(MergedSymbols
);
1495 fprintf(stderr
, "Unable to allocate memory for .rossym section\n");
1498 memset(RosSymSection
, '\0', RosSymLength
);
1500 SymbolFileHeader
= (PSYMBOLFILE_HEADER
)RosSymSection
;
1501 SymbolFileHeader
->SymbolsOffset
= sizeof(SYMBOLFILE_HEADER
);
1502 SymbolFileHeader
->SymbolsLength
= MergedSymbolsCount
* sizeof(ROSSYM_ENTRY
);
1503 SymbolFileHeader
->StringsOffset
= SymbolFileHeader
->SymbolsOffset
+
1504 SymbolFileHeader
->SymbolsLength
;
1505 SymbolFileHeader
->StringsLength
= StringsLength
;
1507 memcpy((char *) RosSymSection
+ SymbolFileHeader
->SymbolsOffset
,
1509 SymbolFileHeader
->SymbolsLength
);
1511 memcpy((char *) RosSymSection
+ SymbolFileHeader
->StringsOffset
,
1513 SymbolFileHeader
->StringsLength
);
1515 free(MergedSymbols
);
1519 out
= fopen(path2
, "wb");
1522 perror("Cannot open output file");
1523 free(RosSymSection
);
1528 if (CreateOutputFile(out
,
1540 free(RosSymSection
);
1549 free(RosSymSection
);