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
;
117 char* convert_path(char* origpath
)
122 newpath
= strdup(origpath
);
125 while (newpath
[i
] != 0)
128 if (newpath
[i
] == '\\')
134 if (newpath
[i
] == '/')
145 #define TRANSFER_SIZE (65536)
147 int main(int argc
, char* argv
[])
149 SYMBOLFILE_HEADER SymbolFileHeader
;
150 IMAGE_DOS_HEADER PEDosHeader
;
151 IMAGE_FILE_HEADER PEFileHeader
;
152 PIMAGE_SECTION_HEADER PESectionHeaders
;
155 PVOID SymbolStringsBase
;
156 ULONG SymbolStringsLength
;
167 fprintf(stderr
, "Too many arguments\n");
171 path1
= convert_path(argv
[1]);
172 path2
= convert_path(argv
[2]);
174 in
= fopen(path1
, "rb");
177 perror("Cannot open input file");
181 out
= fopen(path2
, "wb");
184 perror("Cannot open output file");
189 /* Check if MZ header exists */
190 n_in
= fread(&PEDosHeader
, 1, sizeof(PEDosHeader
), in
);
191 if (PEDosHeader
.e_magic
!= IMAGE_DOS_MAGIC
&& PEDosHeader
.e_lfanew
!= 0L)
193 perror("Input file is not a PE image.\n");
196 /* Read PE file header */
197 /* sizeof(ULONG) = sizeof(MAGIC) */
198 fseek(in
, PEDosHeader
.e_lfanew
+ sizeof(ULONG
), SEEK_SET
);
199 n_in
= fread(&PEFileHeader
, 1, sizeof(PEFileHeader
), in
);
201 /* Read PE section headers */
202 PESectionHeaders
= malloc(PEFileHeader
.NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
));
203 fseek(in
, PEDosHeader
.e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
)
204 + sizeof(IMAGE_OPTIONAL_HEADER
), SEEK_SET
);
205 n_in
= fread(PESectionHeaders
, 1, PEFileHeader
.NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
), in
);
207 /* Copy .stab and .stabstr sections if available */
210 SymbolStringsBase
= NULL
;
211 SymbolStringsLength
= 0;
213 for (Idx
= 0; Idx
< PEFileHeader
.NumberOfSections
; Idx
++)
215 //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
216 if ((strncmp(PESectionHeaders
[Idx
].Name
, ".stab", 5) == 0)
217 && (PESectionHeaders
[Idx
].Name
[5] == 0))
219 //printf(".stab section found. Size %d\n",
220 // PESectionHeaders[Idx].SizeOfRawData);
222 SymbolsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
223 SymbolsBase
= malloc(SymbolsLength
);
225 fseek(in
, PESectionHeaders
[Idx
].PointerToRawData
, SEEK_SET
);
226 n_in
= fread(SymbolsBase
, 1, SymbolsLength
, in
);
229 if (strncmp(PESectionHeaders
[Idx
].Name
, ".stabstr", 8) == 0)
231 //printf(".stabstr section found. Size %d\n",
232 // PESectionHeaders[Idx].SizeOfRawData);
234 SymbolStringsLength
= PESectionHeaders
[Idx
].SizeOfRawData
;
235 SymbolStringsBase
= malloc(SymbolStringsLength
);
237 fseek(in
, PESectionHeaders
[Idx
].PointerToRawData
, SEEK_SET
);
238 n_in
= fread(SymbolStringsBase
, 1, SymbolStringsLength
, in
);
242 SymbolFileHeader
.StabsOffset
= sizeof(SYMBOLFILE_HEADER
);
243 SymbolFileHeader
.StabsLength
= SymbolsLength
;
244 SymbolFileHeader
.StabstrOffset
= SymbolFileHeader
.StabsOffset
+ SymbolsLength
;
245 SymbolFileHeader
.StabstrLength
= SymbolStringsLength
;
247 n_out
= fwrite(&SymbolFileHeader
, 1, sizeof(SYMBOLFILE_HEADER
), out
);
248 n_out
= fwrite(SymbolsBase
, 1, SymbolsLength
, out
);
249 n_out
= fwrite(SymbolStringsBase
, 1, SymbolStringsLength
, out
);