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 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