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;
168 fprintf(stderr, "Too many arguments\n");
172 path1 = convert_path(argv[1]);
173 path2 = convert_path(argv[2]);
175 in = fopen(path1, "rb");
178 perror("Cannot open input file");
182 out = fopen(path2, "wb");
185 perror("Cannot open output file");
190 /* Check if MZ header exists */
191 n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in);
192 if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L)
194 perror("Input file is not a PE image.\n");
197 /* Read PE file header */
198 /* sizeof(ULONG) = sizeof(MAGIC) */
199 fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
200 n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in);
202 /* Read PE section headers */
203 PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
204 fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)
205 + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET);
206 n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in);
208 /* Copy .stab and .stabstr sections if available */
211 SymbolStringsBase = NULL;
212 SymbolStringsLength = 0;
214 for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++)
216 //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
217 if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0)
218 && (PESectionHeaders[Idx].Name[5] == 0))
220 //printf(".stab section found. Size %d\n",
221 // PESectionHeaders[Idx].SizeOfRawData);
223 SymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
224 SymbolsBase = malloc(SymbolsLength);
226 fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
227 n_in = fread(SymbolsBase, 1, SymbolsLength, in);
230 if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
232 //printf(".stabstr section found. Size %d\n",
233 // PESectionHeaders[Idx].SizeOfRawData);
235 SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData;
236 SymbolStringsBase = malloc(SymbolStringsLength);
238 fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
239 n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in);
243 SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
244 SymbolFileHeader.StabsLength = SymbolsLength;
245 SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength;
246 SymbolFileHeader.StabstrLength = SymbolStringsLength;
248 n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
249 n_out = fwrite(SymbolsBase, 1, SymbolsLength, out);
250 n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out);