/* * Usage: rsym input-file output-file */ #include #include #include #define IMAGE_DOS_MAGIC 0x5a4d #define IMAGE_PE_MAGIC 0x00004550 #define IMAGE_SIZEOF_SHORT_NAME 8 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 typedef void* PVOID; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef signed long LONG; typedef unsigned long ULONG; #pragma pack(push,2) typedef struct _IMAGE_DOS_HEADER { WORD e_magic; WORD e_cblp; WORD e_cp; WORD e_crlc; WORD e_cparhdr; WORD e_minalloc; WORD e_maxalloc; WORD e_ss; WORD e_sp; WORD e_csum; WORD e_ip; WORD e_cs; WORD e_lfarlc; WORD e_ovno; WORD e_res[4]; WORD e_oemid; WORD e_oeminfo; WORD e_res2[10]; LONG e_lfanew; } IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; #pragma pack(pop) #pragma pack(push,4) typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Reserved1; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; #pragma pack(pop) typedef struct _SYMBOLFILE_HEADER { unsigned long StabsOffset; unsigned long StabsLength; unsigned long StabstrOffset; unsigned long StabstrLength; } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; char* convert_path(char* origpath) { char* newpath; int i; newpath = strdup(origpath); i = 0; while (newpath[i] != 0) { #ifdef UNIX_PATHS if (newpath[i] == '\\') { newpath[i] = '/'; } #else #ifdef DOS_PATHS if (newpath[i] == '/') { newpath[i] = '\\'; } #endif #endif i++; } return(newpath); } #define TRANSFER_SIZE (65536) int main(int argc, char* argv[]) { SYMBOLFILE_HEADER SymbolFileHeader; IMAGE_DOS_HEADER PEDosHeader; IMAGE_FILE_HEADER PEFileHeader; PIMAGE_SECTION_HEADER PESectionHeaders; PVOID SymbolsBase; ULONG SymbolsLength; PVOID SymbolStringsBase; ULONG SymbolStringsLength; ULONG Idx; char* path1; char* path2; FILE* in; FILE* out; char* buf; int n_in; int n_out; if (argc != 3) { fprintf(stderr, "Too many arguments\n"); exit(1); } path1 = convert_path(argv[1]); path2 = convert_path(argv[2]); in = fopen(path1, "rb"); if (in == NULL) { perror("Cannot open input file"); exit(1); } out = fopen(path2, "wb"); if (out == NULL) { perror("Cannot open output file"); fclose(in); exit(1); } /* Check if MZ header exists */ n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in); if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L) { perror("Input file is not a PE image.\n"); } /* Read PE file header */ /* sizeof(ULONG) = sizeof(MAGIC) */ fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET); n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in); /* Read PE section headers */ PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)); fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET); n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in); /* Copy .stab and .stabstr sections if available */ SymbolsBase = NULL; SymbolsLength = 0; SymbolStringsBase = NULL; SymbolStringsLength = 0; for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++) { //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0) && (PESectionHeaders[Idx].Name[5] == 0)) { //printf(".stab section found. Size %d\n", // PESectionHeaders[Idx].SizeOfRawData); SymbolsLength = PESectionHeaders[Idx].SizeOfRawData; SymbolsBase = malloc(SymbolsLength); fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET); n_in = fread(SymbolsBase, 1, SymbolsLength, in); } if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0) { //printf(".stabstr section found. Size %d\n", // PESectionHeaders[Idx].SizeOfRawData); SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData; SymbolStringsBase = malloc(SymbolStringsLength); fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET); n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in); } } SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER); SymbolFileHeader.StabsLength = SymbolsLength; SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength; SymbolFileHeader.StabstrLength = SymbolStringsLength; n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out); n_out = fwrite(SymbolsBase, 1, SymbolsLength, out); n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out); exit(0); }