[CMAKE]
[reactos.git] / lib / rossym / fromfile.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/rossym/fromfile.c
5 * PURPOSE: Creating rossym info from a file
6 *
7 * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com)
8 */
9
10 #define NTOSAPI
11 #include <ntifs.h>
12 #include <ndk/ntndk.h>
13 #include <reactos/rossym.h>
14 #include "rossympriv.h"
15 #include "pe.h"
16 #include <ntimage.h>
17
18 #include "dwarf.h"
19
20 #define NDEBUG
21 #include <debug.h>
22
23 extern NTSTATUS RosSymStatus;
24
25 BOOLEAN
26 RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
27 {
28 IMAGE_DOS_HEADER DosHeader;
29 IMAGE_NT_HEADERS NtHeaders;
30 PIMAGE_SECTION_HEADER SectionHeaders;
31 unsigned SectionIndex;
32 unsigned SymbolTable, NumSymbols;
33
34 /* Load DOS header */
35 if (! RosSymSeekFile(FileContext, 0))
36 {
37 DPRINT1("Could not rewind file\n");
38 return FALSE;
39 }
40 if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
41 {
42 DPRINT1("Failed to read DOS header %x\n", RosSymStatus);
43 return FALSE;
44 }
45 if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader))
46 {
47 DPRINT1("Image doesn't have a valid DOS header\n");
48 return FALSE;
49 }
50
51 /* Load NT headers */
52 if (! RosSymSeekFile(FileContext, DosHeader.e_lfanew))
53 {
54 DPRINT1("Failed seeking to NT headers\n");
55 return FALSE;
56 }
57 if (! RosSymReadFile(FileContext, &NtHeaders, sizeof(IMAGE_NT_HEADERS)))
58 {
59 DPRINT1("Failed to read NT headers\n");
60 return FALSE;
61 }
62 if (! ROSSYM_IS_VALID_NT_HEADERS(&NtHeaders))
63 {
64 DPRINT1("Image doesn't have a valid PE header\n");
65 return FALSE;
66 }
67
68 SymbolTable = NtHeaders.FileHeader.PointerToSymbolTable;
69 NumSymbols = NtHeaders.FileHeader.NumberOfSymbols;
70
71 if (!NumSymbols)
72 {
73 DPRINT1("Image doesn't have debug symbols\n");
74 return FALSE;
75 }
76
77 DPRINT("SymbolTable %x NumSymbols %x\n", SymbolTable, NumSymbols);
78
79 /* Load section headers */
80 if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
81 (char *) &NtHeaders + DosHeader.e_lfanew))
82 {
83 DPRINT1("Failed seeking to section headers\n");
84 return FALSE;
85 }
86 DPRINT("Alloc section headers\n");
87 SectionHeaders = RosSymAllocMem(NtHeaders.FileHeader.NumberOfSections
88 * sizeof(IMAGE_SECTION_HEADER));
89 if (NULL == SectionHeaders)
90 {
91 DPRINT1("Failed to allocate memory for %u section headers\n",
92 NtHeaders.FileHeader.NumberOfSections);
93 return FALSE;
94 }
95 if (! RosSymReadFile(FileContext, SectionHeaders,
96 NtHeaders.FileHeader.NumberOfSections
97 * sizeof(IMAGE_SECTION_HEADER)))
98 {
99 RosSymFreeMem(SectionHeaders);
100 DPRINT1("Failed to read section headers\n");
101 return FALSE;
102 }
103
104 // Convert names to ANSI_STRINGs
105 for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
106 SectionIndex++)
107 {
108 ANSI_STRING astr;
109 if (SectionHeaders[SectionIndex].Name[0] != '/') {
110 DPRINT("Short name string %d, %s\n", SectionIndex, SectionHeaders[SectionIndex].Name);
111 astr.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
112 memcpy(astr.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
113 astr.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
114 astr.Length = GetStrnlen(astr.Buffer, IMAGE_SIZEOF_SHORT_NAME);
115 } else {
116 UNICODE_STRING intConv;
117 NTSTATUS Status;
118 ULONG StringOffset;
119
120 Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
121 if (!NT_SUCCESS(Status)) goto freeall;
122 Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
123 RtlFreeUnicodeString(&intConv);
124 if (!NT_SUCCESS(Status)) goto freeall;
125 if (!RosSymSeekFile(FileContext, SymbolTable + NumSymbols * SYMBOL_SIZE + StringOffset))
126 goto freeall;
127 astr.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
128 if (!RosSymReadFile(FileContext, astr.Buffer, MAXIMUM_DWARF_NAME_SIZE))
129 goto freeall;
130 astr.Length = GetStrnlen(astr.Buffer, MAXIMUM_DWARF_NAME_SIZE);
131 astr.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
132 DPRINT("Long name %d, %s\n", SectionIndex, astr.Buffer);
133 }
134 *ANSI_NAME_STRING(&SectionHeaders[SectionIndex]) = astr;
135 }
136
137 DPRINT("Done with sections\n");
138 Pe *pe = RosSymAllocMem(sizeof(*pe));
139 pe->fd = FileContext;
140 pe->e2 = peget2;
141 pe->e4 = peget4;
142 pe->e8 = peget8;
143 pe->nsections = NtHeaders.FileHeader.NumberOfSections;
144 pe->sect = SectionHeaders;
145 pe->nsymbols = NtHeaders.FileHeader.NumberOfSymbols;
146 pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
147 SYMENT SymbolData;
148 int i, j;
149 DPRINT("Getting symbol data\n");
150 ASSERT(sizeof(SymbolData) == 18);
151 for (i = 0, j = 0; i < pe->nsymbols; i++) {
152 if (!RosSymSeekFile
153 (FileContext,
154 NtHeaders.FileHeader.PointerToSymbolTable + i * sizeof(SymbolData)))
155 goto freeall;
156 if (!RosSymReadFile(FileContext, &SymbolData, sizeof(SymbolData)))
157 goto freeall;
158 if ((SymbolData.e_scnum < 1) ||
159 (SymbolData.e_sclass != C_EXT &&
160 SymbolData.e_sclass != C_STAT))
161 continue;
162 int section = SymbolData.e_scnum - 1;
163 if (SymbolData.e.e.e_zeroes) {
164 pe->symtab[j].name = malloc(sizeof(SymbolData.e.e_name)+1);
165 memcpy(pe->symtab[j].name, SymbolData.e.e_name, sizeof(SymbolData.e.e_name));
166 pe->symtab[j].name[sizeof(SymbolData.e.e_name)] = 0;
167 } else {
168 if (!RosSymSeekFile
169 (FileContext,
170 NtHeaders.FileHeader.PointerToSymbolTable +
171 (NtHeaders.FileHeader.NumberOfSymbols * 18) +
172 SymbolData.e.e.e_offset))
173 goto freeall;
174 pe->symtab[j].name = malloc(MAXIMUM_COFF_SYMBOL_LENGTH+1);
175 pe->symtab[j].name[MAXIMUM_COFF_SYMBOL_LENGTH] = 0;
176 // It's possible that we've got a string just at the end of the file
177 // we'll skip that symbol if needed
178 if (!RosSymReadFile(FileContext, pe->symtab[j].name, MAXIMUM_COFF_SYMBOL_LENGTH)) {
179 free(pe->symtab[j].name);
180 continue;
181 }
182 }
183 if (pe->symtab[j].name[0] == '.') {
184 free(pe->symtab[j].name);
185 continue;
186 }
187 pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData.e_value;
188 j++;
189 }
190 DPRINT("%d symbols\n", j);
191 pe->nsymbols = j;
192 pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
193 pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
194 pe->loadsection = loaddisksection;
195 DPRINT("do dwarfopen\n");
196 *RosSymInfo = dwarfopen(pe);
197 DPRINT("done %x\n", *RosSymInfo);
198
199 return TRUE;
200
201 freeall:
202 for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
203 SectionIndex++)
204 RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
205 RosSymFreeMem(SectionHeaders);
206
207 return FALSE;
208 }
209
210 /* EOF */