xref: /reactos/sdk/tools/rsym/rsym.cmake.c (revision c2c66aff)
1 /*
2  * Usage: rsym input-file output-file
3  *
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
12  * possible.
13  *
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.
21  */
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 
28 #include "rsym.h"
29 
30 int
IsDebugSection(PIMAGE_SECTION_HEADER Section)31 IsDebugSection(PIMAGE_SECTION_HEADER Section)
32 {
33     /* This is a hack, but works for us */
34     return (Section->Name[0] == '/');
35 }
36 
main(int argc,char * argv[])37 int main(int argc, char* argv[])
38 {
39     unsigned int i;
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;
46     char* path1;
47     char* path2;
48     FILE* out;
49     size_t FileSize;
50     void *FileData;
51     char elfhdr[] = { '\377', 'E', 'L', 'F' };
52 
53     if (argc != 3)
54     {
55         fprintf(stderr, "Usage: rsym <exefile> <symfile>\n");
56         exit(1);
57     }
58 
59     path1 = convert_path(argv[1]);
60     path2 = convert_path(argv[2]);
61 
62     /* Load the input file into memory */
63     FileData = load_file( path1, &FileSize);
64     if ( !FileData )
65     {
66         fprintf(stderr, "An error occured loading '%s'\n", path1);
67         exit(1);
68     }
69 
70     /* Check if MZ header exists  */
71     DosHeader = (PIMAGE_DOS_HEADER) FileData;
72     if (DosHeader->e_magic != IMAGE_DOS_MAGIC || DosHeader->e_lfanew == 0L)
73     {
74         /* Ignore elf */
75         if (!memcmp(DosHeader, elfhdr, sizeof(elfhdr)))
76             exit(0);
77         perror("Input file is not a PE image.\n");
78         free(FileData);
79         exit(1);
80     }
81 
82     /* Locate the headers */
83     NtHeaders = (PIMAGE_NT_HEADERS)((char*)FileData + DosHeader->e_lfanew);
84     FileHeader = &NtHeaders->FileHeader;
85     OptionalHeader = &NtHeaders->OptionalHeader;
86 
87     /* Locate PE section headers  */
88     SectionHeaders = (PIMAGE_SECTION_HEADER)((char*)OptionalHeader +
89                                              FileHeader->SizeOfOptionalHeader);
90 
91     /* Loop all sections */
92     for (i = 0; i < FileHeader->NumberOfSections; i++)
93     {
94         /* Check if this is a debug section */
95         if (IsDebugSection(&SectionHeaders[i]))
96         {
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);
100         }
101     }
102 
103     /* Get a pointer to the last section header */
104     LastSection = &SectionHeaders[FileHeader->NumberOfSections - 1];
105 
106     /* Set the size of the last section to cover the rest of the PE */
107     LastSection->SizeOfRawData = FileSize - LastSection->PointerToRawData;
108 
109     /* Check if the virtual section size is smaller than the raw data */
110     if (LastSection->Misc.VirtualSize < LastSection->SizeOfRawData)
111     {
112         /* Make sure the virtual size of the section cover the raw data */
113         LastSection->Misc.VirtualSize = ROUND_UP(LastSection->SizeOfRawData,
114                                                  OptionalHeader->SectionAlignment);
115 
116         /* Fix up image size */
117         OptionalHeader->SizeOfImage = LastSection->VirtualAddress +
118                                       LastSection->Misc.VirtualSize;
119     }
120 
121     /* Open the output file */
122     out = fopen(path2, "wb");
123     if (out == NULL)
124     {
125         perror("Cannot open output file");
126         free(FileData);
127         exit(1);
128     }
129 
130     /* Write the output file */
131     fwrite(FileData, 1, FileSize, out);
132     fclose(out);
133     free(FileData);
134 
135     return 0;
136 }
137 
138 /* EOF */
139