2 * Usage: rsym input-file output-file
8 #define NULL ((void*)0)
10 #define IMAGE_DOS_MAGIC 0x5a4d
11 #define IMAGE_PE_MAGIC 0x00004550
13 #define IMAGE_SIZEOF_SHORT_NAME 8
15 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
18 typedef unsigned char BYTE;
19 typedef unsigned short WORD;
20 typedef unsigned long DWORD;
21 typedef signed long LONG;
22 typedef unsigned long ULONG;
25 typedef struct _IMAGE_DOS_HEADER {
45 } IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
48 typedef struct _IMAGE_DATA_DIRECTORY {
51 } IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
52 typedef struct _IMAGE_OPTIONAL_HEADER {
54 BYTE MajorLinkerVersion;
55 BYTE MinorLinkerVersion;
57 DWORD SizeOfInitializedData;
58 DWORD SizeOfUninitializedData;
59 DWORD AddressOfEntryPoint;
63 DWORD SectionAlignment;
65 WORD MajorOperatingSystemVersion;
66 WORD MinorOperatingSystemVersion;
67 WORD MajorImageVersion;
68 WORD MinorImageVersion;
69 WORD MajorSubsystemVersion;
70 WORD MinorSubsystemVersion;
76 WORD DllCharacteristics;
77 DWORD SizeOfStackReserve;
78 DWORD SizeOfStackCommit;
79 DWORD SizeOfHeapReserve;
80 DWORD SizeOfHeapCommit;
82 DWORD NumberOfRvaAndSizes;
83 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
84 } IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
85 typedef struct _IMAGE_FILE_HEADER {
87 WORD NumberOfSections;
89 DWORD PointerToSymbolTable;
90 DWORD NumberOfSymbols;
91 WORD SizeOfOptionalHeader;
93 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
94 typedef struct _IMAGE_SECTION_HEADER {
95 BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
97 DWORD PhysicalAddress;
100 DWORD VirtualAddress;
102 DWORD PointerToRawData;
103 DWORD PointerToRelocations;
104 DWORD PointerToLinenumbers;
105 WORD NumberOfRelocations;
106 WORD NumberOfLinenumbers;
107 DWORD Characteristics;
108 } IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
111 typedef struct _SYMBOLFILE_HEADER {
112 unsigned long StabsOffset;
113 unsigned long StabsLength;
114 unsigned long StabstrOffset;
115 unsigned long StabstrLength;
116 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
119 char* convert_path(char* origpath)
124 newpath = strdup(origpath);
127 while (newpath[i] != 0)
130 if (newpath[i] == '\\')
136 if (newpath[i] == '/')
147 #define TRANSFER_SIZE (65536)
149 int main(int argc, char* argv[])
151 SYMBOLFILE_HEADER SymbolFileHeader;
152 IMAGE_DOS_HEADER PEDosHeader;
153 IMAGE_FILE_HEADER PEFileHeader;
154 PIMAGE_SECTION_HEADER PESectionHeaders;
157 PVOID SymbolStringsBase;
158 ULONG SymbolStringsLength;
170 fprintf(stderr, "Too many arguments\n");
174 path1 = convert_path(argv[1]);
175 path2 = convert_path(argv[2]);
177 in = fopen(path1, "rb");
180 perror("Cannot open input file");
184 out = fopen(path2, "wb");
187 perror("Cannot open output file");
192 /* Check if MZ header exists */
193 n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in);
194 if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L)
196 perror("Input file is not a PE image.\n");
199 /* Read PE file header */
200 /* sizeof(ULONG) = sizeof(MAGIC) */
201 fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
202 n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in);
204 /* Read PE section headers */
205 PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
206 fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)
207 + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET);
208 n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in);
210 /* Copy .stab and .stabstr sections if available */
213 SymbolStringsBase = NULL;
214 SymbolStringsLength = 0;
216 for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++)
218 //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
219 if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0)
220 && (PESectionHeaders[Idx].Name[5] == 0))
222 //printf(".stab section found. Size %d\n",
223 // PESectionHeaders[Idx].SizeOfRawData);
225 SymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
226 SymbolsBase = malloc(SymbolsLength);
228 fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
229 n_in = fread(SymbolsBase, 1, SymbolsLength, in);
232 if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
234 //printf(".stabstr section found. Size %d\n",
235 // PESectionHeaders[Idx].SizeOfRawData);
237 SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData;
238 SymbolStringsBase = malloc(SymbolStringsLength);
240 fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
241 n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in);
245 SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
246 SymbolFileHeader.StabsLength = SymbolsLength;
247 SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength;
248 SymbolFileHeader.StabstrLength = SymbolStringsLength;
250 n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
251 n_out = fwrite(SymbolsBase, 1, SymbolsLength, out);
252 n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out);