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 */ 161