2 * Usage: rsym input-file output-file
8 #define IMAGE_DOS_MAGIC 0x5a4d
9 #define IMAGE_PE_MAGIC 0x00004550
11 #define IMAGE_SIZEOF_SHORT_NAME 8
13 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
16 typedef unsigned char BYTE
;
17 typedef unsigned short WORD
;
18 typedef unsigned long DWORD
;
19 typedef signed long LONG
;
20 typedef unsigned long ULONG
;
23 typedef struct _IMAGE_DOS_HEADER
{
43 } IMAGE_DOS_HEADER
,*PIMAGE_DOS_HEADER
;
46 typedef struct _IMAGE_DATA_DIRECTORY
{
49 } IMAGE_DATA_DIRECTORY
,*PIMAGE_DATA_DIRECTORY
;
50 typedef struct _IMAGE_OPTIONAL_HEADER
{
52 BYTE MajorLinkerVersion
;
53 BYTE MinorLinkerVersion
;
55 DWORD SizeOfInitializedData
;
56 DWORD SizeOfUninitializedData
;
57 DWORD AddressOfEntryPoint
;
61 DWORD SectionAlignment
;
63 WORD MajorOperatingSystemVersion
;
64 WORD MinorOperatingSystemVersion
;
65 WORD MajorImageVersion
;
66 WORD MinorImageVersion
;
67 WORD MajorSubsystemVersion
;
68 WORD MinorSubsystemVersion
;
74 WORD DllCharacteristics
;
75 DWORD SizeOfStackReserve
;
76 DWORD SizeOfStackCommit
;
77 DWORD SizeOfHeapReserve
;
78 DWORD SizeOfHeapCommit
;
80 DWORD NumberOfRvaAndSizes
;
81 IMAGE_DATA_DIRECTORY DataDirectory
[IMAGE_NUMBEROF_DIRECTORY_ENTRIES
];
82 } IMAGE_OPTIONAL_HEADER
,*PIMAGE_OPTIONAL_HEADER
;
83 typedef struct _IMAGE_FILE_HEADER
{
85 WORD NumberOfSections
;
87 DWORD PointerToSymbolTable
;
88 DWORD NumberOfSymbols
;
89 WORD SizeOfOptionalHeader
;
91 } IMAGE_FILE_HEADER
, *PIMAGE_FILE_HEADER
;
92 typedef struct _IMAGE_SECTION_HEADER
{
93 BYTE Name
[IMAGE_SIZEOF_SHORT_NAME
];
95 DWORD PhysicalAddress
;
100 DWORD PointerToRawData
;
101 DWORD PointerToRelocations
;
102 DWORD PointerToLinenumbers
;
103 WORD NumberOfRelocations
;
104 WORD NumberOfLinenumbers
;
105 DWORD Characteristics
;
106 } IMAGE_SECTION_HEADER
,*PIMAGE_SECTION_HEADER
;
109 typedef struct _SYMBOLFILE_HEADER
{
110 unsigned long StabsOffset
;
111 unsigned long StabsLength
;
112 unsigned long StabstrOffset
;
113 unsigned long StabstrLength
;
114 } SYMBOLFILE_HEADER
, *PSYMBOLFILE_HEADER
;
116 typedef struct _STAB_ENTRY
{
117 unsigned long n_strx
; /* index into string table of name */
118 unsigned char n_type
; /* type of symbol */
119 unsigned char n_other
; /* misc info (usually empty) */
120 unsigned short n_desc
; /* description field */
121 unsigned long n_value
; /* value of symbol */
122 } STAB_ENTRY
, *PSTAB_ENTRY
;
130 unsigned long OldOffset
;
131 unsigned long NewOffset
;
133 unsigned long Length
;
134 } STR_ENTRY
, *PSTR_ENTRY
;
136 char* convert_path(char* origpath
)
141 newpath
= strdup(origpath
);
144 while (newpath
[i
] != 0)
147 if (newpath
[i
] == '\\')
153 if (newpath
[i
] == '/')
164 #define TRANSFER_SIZE (65536)
166 int main(int argc
, char* argv
[])
168 SYMBOLFILE_HEADER SymbolFileHeader
;
169 IMAGE_DOS_HEADER PEDosHeader
;
170 IMAGE_FILE_HEADER PEFileHeader
;
171 PIMAGE_OPTIONAL_HEADER PEOptHeader
;
172 PIMAGE_SECTION_HEADER PESectionHeaders
;
176 PVOID SymbolStringsBase
;
177 ULONG SymbolStringsLength
;
185 PSTAB_ENTRY StabEntry
;
195 fprintf(stderr
, "Too many arguments\n");
199 path1
= convert_path(argv
[1]);
200 path2
= convert_path(argv
[2]);
202 in
= fopen(path1
, "rb");
205 perror("Cannot open input file");
209 out
= fopen(path2
, "wb");
212 perror("Cannot open output file");
217 /* Check if MZ header exists */
218 n_in
= fread(&PEDosHeader
, 1, sizeof(PEDosHeader
), in
);
219 if (PEDosHeader
.e_magic
!= IMAGE_DOS_MAGIC
&& PEDosHeader
.e_lfanew
!= 0L)
221 perror("Input file is not a PE image.\n");
224 /* Read PE file header */
225 /* sizeof(ULONG) = sizeof(MAGIC) */
226 fseek(in
, PEDosHeader
.e_lfanew
+ sizeof(ULONG
), SEEK_SET
);
227 n_in
= fread(&PEFileHeader
, 1, sizeof(PEFileHeader
), in
);
229 /* Read optional header */
230 PEOptHeader
= malloc(PEFileHeader
.SizeOfOptionalHeader
);
231 fread ( PEOptHeader
, 1, PEFileHeader
.SizeOfOptionalHeader
, in
);
232 ImageBase
= PEOptHeader
->ImageBase
;
234 /* Read PE section headers */
235 PESectionHeaders
= malloc(PEFileHeader
.NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
));
236 fseek(in
, PEDosHeader
.e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
)
237 + sizeof(IMAGE_OPTIONAL_HEADER
), SEEK_SET
);
238 n_in
= fread(PESectionHeaders
, 1, PEFileHeader
.NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
), in
);
240 /* Copy .stab and .stabstr sections if available */
243 SymbolStringsBase
= NULL
;
244 SymbolStringsLength
= 0;
246 for (Idx
= 0; Idx
< PEFileHeader
.NumberOfSections
; Idx
++)
248 //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
249 if ((strncmp(PESectionHeaders
[Idx
].Name
, ".stab", 5) == 0)
250 && (PESectionHeaders
[Idx
].Name
[5] == 0))
252 //printf(".stab section found. Size %d\n",
253 // PESectionHeaders[Idx].SizeOfRawData);
255 SymbolsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
256 SymbolsBase
= malloc(SymbolsLength
);
258 fseek(in
, PESectionHeaders
[Idx
].PointerToRawData
, SEEK_SET
);
259 n_in
= fread(SymbolsBase
, 1, SymbolsLength
, in
);
262 if (strncmp(PESectionHeaders
[Idx
].Name
, ".stabstr", 8) == 0)
264 //printf(".stabstr section found. Size %d\n",
265 // PESectionHeaders[Idx].SizeOfRawData);
267 SymbolStringsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
268 SymbolStringsBase
= malloc(SymbolStringsLength
);
270 fseek(in
, PESectionHeaders
[Idx
].PointerToRawData
, SEEK_SET
);
271 n_in
= fread(SymbolStringsBase
, 1, SymbolStringsLength
, in
);
275 StabEntry
= SymbolsBase
;
276 SymbolsCount
= SymbolsLength
/ sizeof(STAB_ENTRY
);
279 for (i
= 0; i
< SymbolsCount
; i
++)
281 if (StabEntry
[i
].n_type
== N_FUN
||
282 StabEntry
[i
].n_type
== N_SLINE
||
283 StabEntry
[i
].n_type
== N_SO
)
285 memmove(&StabEntry
[Count
], &StabEntry
[i
], sizeof(STAB_ENTRY
));
286 if ( StabEntry
[Count
].n_value
>= ImageBase
)
287 StabEntry
[Count
].n_value
-= ImageBase
;
292 StrEntry
= malloc(sizeof(STR_ENTRY
) * Count
);
295 for (i
= 0; i
< Count
; i
++)
297 for (j
= 0; j
< StrCount
; j
++)
299 if (StabEntry
[i
].n_strx
== StrEntry
[j
].OldOffset
)
301 StabEntry
[i
].n_strx
= StrEntry
[j
].NewOffset
;
307 StrEntry
[StrCount
].OldOffset
= StabEntry
[i
].n_strx
;
308 StrEntry
[StrCount
].Name
= (char*)SymbolStringsBase
+ StrEntry
[StrCount
].OldOffset
;
309 StrEntry
[StrCount
].Length
= strlen(StrEntry
[StrCount
].Name
) + 1;
312 StrEntry
[StrCount
].NewOffset
= 0;
316 StrEntry
[StrCount
].NewOffset
= StrEntry
[StrCount
-1].NewOffset
+ StrEntry
[StrCount
-1].Length
;
318 StabEntry
[i
].n_strx
= StrEntry
[StrCount
].NewOffset
;
323 SymbolFileHeader
.StabsOffset
= sizeof(SYMBOLFILE_HEADER
);
324 SymbolFileHeader
.StabsLength
= Count
* sizeof(STAB_ENTRY
);
325 SymbolFileHeader
.StabstrOffset
= SymbolFileHeader
.StabsOffset
+ SymbolFileHeader
.StabsLength
;
326 SymbolFileHeader
.StabstrLength
= StrEntry
[StrCount
-1].NewOffset
+ StrEntry
[StrCount
-1].Length
;
328 n_out
= fwrite(&SymbolFileHeader
, 1, sizeof(SYMBOLFILE_HEADER
), out
);
329 n_out
= fwrite(SymbolsBase
, 1, SymbolFileHeader
.StabsLength
, out
);
330 for (i
= 0; i
< StrCount
; i
++)
332 fwrite(StrEntry
[i
].Name
, 1, StrEntry
[i
].Length
, out
);