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