Sync with trunk r63192.
[reactos.git] / lib / rossym_new / frommem.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/rossym/frommem.c
5 * PURPOSE: Creating rossym info from an in-memory image
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 <ntimage.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20 #include "dwarf.h"
21 #include "pe.h"
22
23 BOOLEAN
24 RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo)
25 {
26 ANSI_STRING AnsiNameString = { };
27 PIMAGE_DOS_HEADER DosHeader;
28 PIMAGE_NT_HEADERS NtHeaders;
29 PIMAGE_SECTION_HEADER SectionHeaders;
30 ULONG SectionIndex;
31 unsigned SymbolTable, NumSymbols;
32
33 /* Check if MZ header is valid */
34 DosHeader = (PIMAGE_DOS_HEADER) ImageStart;
35 if (ImageSize < sizeof(IMAGE_DOS_HEADER)
36 || ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader))
37 {
38 DPRINT1("Image doesn't have a valid DOS header\n");
39 return FALSE;
40 }
41
42 /* Locate NT header */
43 NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew);
44 if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
45 || ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders))
46 {
47 DPRINT1("Image doesn't have a valid PE header\n");
48 return FALSE;
49 }
50
51 SymbolTable = NtHeaders->FileHeader.PointerToSymbolTable;
52 NumSymbols = NtHeaders->FileHeader.NumberOfSymbols;
53
54 /* Search for the section header */
55 ULONG SectionHeaderSize = NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
56 SectionHeaders = RosSymAllocMem(SectionHeaderSize);
57 RtlCopyMemory(SectionHeaders, IMAGE_FIRST_SECTION(NtHeaders), SectionHeaderSize);
58
59 // Convert names to ANSI_STRINGs
60 for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
61 SectionIndex++)
62 {
63 if (SectionHeaders[SectionIndex].Name[0] != '/') {
64 AnsiNameString.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
65 RtlCopyMemory(AnsiNameString.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
66 AnsiNameString.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
67 AnsiNameString.Length = GetStrnlen(AnsiNameString.Buffer, IMAGE_SIZEOF_SHORT_NAME);
68 } else {
69 UNICODE_STRING intConv;
70 NTSTATUS Status;
71 ULONG StringOffset;
72
73 if (!RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1))
74 goto freeall;
75 Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
76 RtlFreeUnicodeString(&intConv);
77 if (!NT_SUCCESS(Status)) goto freeall;
78 ULONG VirtualOffset = pefindrva(SectionHeaders, NtHeaders->FileHeader.NumberOfSections, SymbolTable+(NumSymbols*SYMBOL_SIZE)+StringOffset);
79 if (!VirtualOffset) goto freeall;
80 AnsiNameString.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
81 if (!AnsiNameString.Buffer) goto freeall;
82 PCHAR StringTarget = ((PCHAR)ImageStart)+VirtualOffset;
83 PCHAR EndOfImage = ((PCHAR)ImageStart) + NtHeaders->OptionalHeader.SizeOfImage;
84 if (StringTarget >= EndOfImage) goto freeall;
85 ULONG PossibleStringLength = EndOfImage - StringTarget;
86 if (PossibleStringLength > MAXIMUM_DWARF_NAME_SIZE)
87 PossibleStringLength = MAXIMUM_DWARF_NAME_SIZE;
88 RtlCopyMemory(AnsiNameString.Buffer, StringTarget, PossibleStringLength);
89 AnsiNameString.Length = strlen(AnsiNameString.Buffer);
90 AnsiNameString.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;
91 }
92 memcpy
93 (&SectionHeaders[SectionIndex],
94 &AnsiNameString,
95 sizeof(AnsiNameString));
96 }
97
98 Pe *pe = RosSymAllocMem(sizeof(*pe));
99 pe->fd = ImageStart;
100 pe->e2 = peget2;
101 pe->e4 = peget4;
102 pe->e8 = peget8;
103 pe->loadbase = (ULONG)ImageStart;
104 pe->imagebase = NtHeaders->OptionalHeader.ImageBase;
105 pe->imagesize = NtHeaders->OptionalHeader.SizeOfImage;
106 pe->nsections = NtHeaders->FileHeader.NumberOfSections;
107 pe->sect = SectionHeaders;
108 pe->nsymbols = NtHeaders->FileHeader.NumberOfSymbols;
109 pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
110 PSYMENT SymbolData = (PSYMENT)
111 (((PCHAR)ImageStart) +
112 pefindrva
113 (pe->sect,
114 pe->nsections,
115 NtHeaders->FileHeader.PointerToSymbolTable));
116 int i, j;
117 for (i = 0, j = 0; i < pe->nsymbols; i++) {
118 if ((SymbolData[i].e_scnum < 1) ||
119 (SymbolData[i].e_sclass != C_EXT &&
120 SymbolData[i].e_sclass != C_STAT))
121 continue;
122 int section = SymbolData[i].e_scnum - 1;
123 if (SymbolData[i].e.e.e_zeroes) {
124 pe->symtab[j].name = malloc(sizeof(SymbolData[i].e.e_name)+1);
125 strcpy(pe->symtab[j].name, SymbolData[i].e.e_name);
126 } else {
127 PCHAR SymbolName = ((PCHAR)ImageStart) +
128 pefindrva
129 (pe->sect,
130 pe->nsections,
131 NtHeaders->FileHeader.PointerToSymbolTable +
132 (NtHeaders->FileHeader.NumberOfSymbols * 18) +
133 SymbolData[i].e.e.e_offset);
134 pe->symtab[j].name = malloc(strlen(SymbolName)+1);
135 strcpy(pe->symtab[j].name, SymbolName);
136 }
137 if (pe->symtab[j].name[0] == '.') {
138 free(pe->symtab[j].name);
139 continue;
140 }
141 pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData[i].e_value;
142 j++;
143 }
144 pe->nsymbols = j;
145 pe->loadsection = loadmemsection;
146 *RosSymInfo = dwarfopen(pe);
147
148 return !!*RosSymInfo;
149
150 freeall:
151 if (AnsiNameString.Buffer) RosSymFreeMem(AnsiNameString.Buffer);
152 for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections;
153 SectionIndex++)
154 RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
155 RosSymFreeMem(SectionHeaders);
156
157 return FALSE;
158 }
159
160 /* EOF */