2 * Usage: rsym input-file output-file
4 * There are two sources of information: the .stab/.stabstr
5 * sections of the executable and the COFF symbol table. Most
6 * of the information is in the .stab/.stabstr sections.
7 * However, most of our asm files don't contain .stab directives,
8 * so routines implemented in assembler won't show up in the
9 * .stab section. They are present in the COFF symbol table.
10 * So, we mostly use the .stab/.stabstr sections, but we augment
11 * the info there with info from the COFF symbol table when
14 * This is a tool and is compiled using the host compiler,
15 * i.e. on Linux gcc and not mingw-gcc (cross-compiler).
16 * Therefore we can't include SDK headers and we have to
17 * duplicate some definitions here.
18 * Also note that the internal functions are "old C-style",
19 * returning an int, where a return of 0 means success and
20 * non-zero is failure.
31 IsDebugSection(PIMAGE_SECTION_HEADER Section
)
33 /* This is a hack, but works for us */
34 return (Section
->Name
[0] == '/');
37 int main(int argc
, char* argv
[])
40 PSYMBOLFILE_HEADER SymbolFileHeader
;
41 PIMAGE_NT_HEADERS NtHeaders
;
42 PIMAGE_DOS_HEADER DosHeader
;
43 PIMAGE_FILE_HEADER FileHeader
;
44 PIMAGE_OPTIONAL_HEADER OptionalHeader
;
45 PIMAGE_SECTION_HEADER SectionHeaders
, LastSection
;
51 char elfhdr
[] = { '\377', 'E', 'L', 'F' };
55 fprintf(stderr
, "Usage: rsym <exefile> <symfile>\n");
59 path1
= convert_path(argv
[1]);
60 path2
= convert_path(argv
[2]);
62 /* Load the input file into memory */
63 FileData
= load_file( path1
, &FileSize
);
66 fprintf(stderr
, "An error occured loading '%s'\n", path1
);
70 /* Check if MZ header exists */
71 DosHeader
= (PIMAGE_DOS_HEADER
) FileData
;
72 if (DosHeader
->e_magic
!= IMAGE_DOS_MAGIC
|| DosHeader
->e_lfanew
== 0L)
75 if (!memcmp(DosHeader
, elfhdr
, sizeof(elfhdr
)))
77 perror("Input file is not a PE image.\n");
82 /* Locate the headers */
83 NtHeaders
= (PIMAGE_NT_HEADERS
)((char*)FileData
+ DosHeader
->e_lfanew
);
84 FileHeader
= &NtHeaders
->FileHeader
;
85 OptionalHeader
= &NtHeaders
->OptionalHeader
;
87 /* Locate PE section headers */
88 SectionHeaders
= (PIMAGE_SECTION_HEADER
)((char*)OptionalHeader
+
89 FileHeader
->SizeOfOptionalHeader
);
91 /* Loop all sections */
92 for (i
= 0; i
< FileHeader
->NumberOfSections
; i
++)
94 /* Check if this is a debug section */
95 if (IsDebugSection(&SectionHeaders
[i
]))
97 /* Make sure we have the correct characteristics */
98 SectionHeaders
[i
].Characteristics
|= IMAGE_SCN_CNT_INITIALIZED_DATA
;
99 SectionHeaders
[i
].Characteristics
&= ~(IMAGE_SCN_MEM_PURGEABLE
| IMAGE_SCN_MEM_DISCARDABLE
);
103 /* Get a pointer to the last section header */
104 LastSection
= &SectionHeaders
[FileHeader
->NumberOfSections
- 1];
106 /* Set the size of the last section to cover the rest of the PE */
107 LastSection
->SizeOfRawData
= FileSize
- LastSection
->PointerToRawData
;
109 /* Check if the virtual section size is smaller than the raw data */
110 if (LastSection
->Misc
.VirtualSize
< LastSection
->SizeOfRawData
)
112 /* Make sure the virtual size of the section cover the raw data */
113 LastSection
->Misc
.VirtualSize
= ROUND_UP(LastSection
->SizeOfRawData
,
114 OptionalHeader
->SectionAlignment
);
116 /* Fix up image size */
117 OptionalHeader
->SizeOfImage
= LastSection
->VirtualAddress
+
118 LastSection
->Misc
.VirtualSize
;
121 /* Open the output file */
122 out
= fopen(path2
, "wb");
125 perror("Cannot open output file");
130 /* Write the output file */
131 fwrite(FileData
, 1, FileSize
, out
);