ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pe_module.c
Go to the documentation of this file.
00001 /*
00002  * File pe_module.c - handle PE module information
00003  *
00004  * Copyright (C) 1996,      Eric Youngdale.
00005  * Copyright (C) 1999-2000, Ulrich Weigand.
00006  * Copyright (C) 2004-2007, Eric Pouech.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  *
00022  */
00023 
00024 #include "config.h"
00025 #include "wine/port.h"
00026 
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <assert.h>
00031 
00032 #include "dbghelp_private.h"
00033 #include "image_private.h"
00034 #include "winternl.h"
00035 #include "wine/debug.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
00038 
00039 struct pe_module_info
00040 {
00041     struct image_file_map       fmap;
00042 };
00043 
00044 static void* pe_map_full(struct image_file_map* fmap, IMAGE_NT_HEADERS** nth)
00045 {
00046     if (!fmap->u.pe.full_map)
00047     {
00048         fmap->u.pe.full_map = MapViewOfFile(fmap->u.pe.hMap, FILE_MAP_READ, 0, 0, 0);
00049     }
00050     if (fmap->u.pe.full_map)
00051     {
00052         if (nth) *nth = RtlImageNtHeader(fmap->u.pe.full_map);
00053         fmap->u.pe.full_count++;
00054         return fmap->u.pe.full_map;
00055     }
00056     return IMAGE_NO_MAP;
00057 }
00058 
00059 static void pe_unmap_full(struct image_file_map* fmap)
00060 {
00061     if (fmap->u.pe.full_count && !--fmap->u.pe.full_count)
00062     {
00063         UnmapViewOfFile(fmap->u.pe.full_map);
00064         fmap->u.pe.full_map = NULL;
00065     }
00066 }
00067 
00068 /******************************************************************
00069  *      pe_map_section
00070  *
00071  * Maps a single section into memory from an PE file
00072  */
00073 const char* pe_map_section(struct image_section_map* ism)
00074 {
00075     void*       mapping;
00076     struct pe_file_map* fmap = &ism->fmap->u.pe;
00077 
00078     if (ism->sidx >= 0 && ism->sidx < fmap->ntheader.FileHeader.NumberOfSections &&
00079         fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP)
00080     {
00081         IMAGE_NT_HEADERS*       nth;
00082 
00083         if (fmap->sect[ism->sidx].shdr.Misc.VirtualSize > fmap->sect[ism->sidx].shdr.SizeOfRawData)
00084         {
00085             FIXME("Section %ld: virtual (0x%x) > raw (0x%x) size - not supported\n",
00086                   ism->sidx, fmap->sect[ism->sidx].shdr.Misc.VirtualSize,
00087                   fmap->sect[ism->sidx].shdr.SizeOfRawData);
00088             return IMAGE_NO_MAP;
00089         }
00090         /* FIXME: that's rather drastic, but that will do for now
00091          * that's ok if the full file map exists, but we could be less aggressive otherwise and
00092          * only map the relevant section
00093          */
00094         if ((mapping = pe_map_full(ism->fmap, &nth)))
00095         {
00096             fmap->sect[ism->sidx].mapped = RtlImageRvaToVa(nth, mapping,
00097                                                            fmap->sect[ism->sidx].shdr.VirtualAddress,
00098                                                            NULL);
00099             return fmap->sect[ism->sidx].mapped;
00100         }
00101     }
00102     return IMAGE_NO_MAP;
00103 }
00104 
00105 /******************************************************************
00106  *      pe_find_section
00107  *
00108  * Finds a section by name (and type) into memory from an PE file
00109  * or its alternate if any
00110  */
00111 BOOL pe_find_section(struct image_file_map* fmap, const char* name,
00112                      struct image_section_map* ism)
00113 {
00114     const char*                 sectname;
00115     unsigned                    i;
00116     char                        tmp[IMAGE_SIZEOF_SHORT_NAME + 1];
00117 
00118     for (i = 0; i < fmap->u.pe.ntheader.FileHeader.NumberOfSections; i++)
00119     {
00120         sectname = (const char*)fmap->u.pe.sect[i].shdr.Name;
00121         /* long section names start with a '/' (at least on MinGW32) */
00122         if (sectname[0] == '/' && fmap->u.pe.strtable)
00123             sectname = fmap->u.pe.strtable + atoi(sectname + 1);
00124         else
00125         {
00126             /* the section name may not be null terminated */
00127             sectname = memcpy(tmp, sectname, IMAGE_SIZEOF_SHORT_NAME);
00128             tmp[IMAGE_SIZEOF_SHORT_NAME] = '\0';
00129         }
00130         if (!strcasecmp(sectname, name))
00131         {
00132             ism->fmap = fmap;
00133             ism->sidx = i;
00134             return TRUE;
00135         }
00136     }
00137     ism->fmap = NULL;
00138     ism->sidx = -1;
00139 
00140     return FALSE;
00141 }
00142 
00143 /******************************************************************
00144  *      pe_unmap_section
00145  *
00146  * Unmaps a single section from memory
00147  */
00148 void pe_unmap_section(struct image_section_map* ism)
00149 {
00150     if (ism->sidx >= 0 && ism->sidx < ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections &&
00151         ism->fmap->u.pe.sect[ism->sidx].mapped != IMAGE_NO_MAP)
00152     {
00153         pe_unmap_full(ism->fmap);
00154         ism->fmap->u.pe.sect[ism->sidx].mapped = IMAGE_NO_MAP;
00155     }
00156 }
00157 
00158 /******************************************************************
00159  *      pe_get_map_rva
00160  *
00161  * Get the RVA of an PE section
00162  */
00163 DWORD_PTR pe_get_map_rva(const struct image_section_map* ism)
00164 {
00165     if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections)
00166         return 0;
00167     return ism->fmap->u.pe.sect[ism->sidx].shdr.VirtualAddress;
00168 }
00169 
00170 /******************************************************************
00171  *      pe_get_map_size
00172  *
00173  * Get the size of a PE section
00174  */
00175 unsigned pe_get_map_size(const struct image_section_map* ism)
00176 {
00177     if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections)
00178         return 0;
00179     return ism->fmap->u.pe.sect[ism->sidx].shdr.Misc.VirtualSize;
00180 }
00181 
00182 /******************************************************************
00183  *      pe_is_valid_pointer_table
00184  *
00185  * Checks whether the PointerToSymbolTable and NumberOfSymbols in file_header contain
00186  * valid information.
00187  */
00188 static BOOL pe_is_valid_pointer_table(const IMAGE_NT_HEADERS* nthdr, const void* mapping, DWORD64 sz)
00189 {
00190     DWORD64     offset;
00191 
00192     /* is the iSym table inside file size ? (including first DWORD of string table, which is its size) */
00193     offset = (DWORD64)nthdr->FileHeader.PointerToSymbolTable;
00194     offset += (DWORD64)nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
00195     if (offset + sizeof(DWORD) > sz) return FALSE;
00196     /* is string table (following iSym table) inside file size ? */
00197     offset += *(DWORD*)((const char*)mapping + offset);
00198     return offset <= sz;
00199 }
00200 
00201 /******************************************************************
00202  *      pe_map_file
00203  *
00204  * Maps an PE file into memory (and checks it's a real PE file)
00205  */
00206 static BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt)
00207 {
00208     void*       mapping;
00209 
00210     fmap->modtype = mt;
00211     fmap->u.pe.hMap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
00212     if (fmap->u.pe.hMap == 0) return FALSE;
00213     fmap->u.pe.full_count = 0;
00214     fmap->u.pe.full_map = NULL;
00215     if (!(mapping = pe_map_full(fmap, NULL))) goto error;
00216 
00217     switch (mt)
00218     {
00219     case DMT_PE:
00220         {
00221             IMAGE_NT_HEADERS*       nthdr;
00222             IMAGE_SECTION_HEADER*   section;
00223             unsigned                i;
00224 
00225             if (!(nthdr = RtlImageNtHeader(mapping))) goto error;
00226             memcpy(&fmap->u.pe.ntheader, nthdr, sizeof(fmap->u.pe.ntheader));
00227             section = (IMAGE_SECTION_HEADER*)
00228                 ((char*)&nthdr->OptionalHeader + nthdr->FileHeader.SizeOfOptionalHeader);
00229             fmap->u.pe.sect = HeapAlloc(GetProcessHeap(), 0,
00230                                         nthdr->FileHeader.NumberOfSections * sizeof(fmap->u.pe.sect[0]));
00231             if (!fmap->u.pe.sect) goto error;
00232             for (i = 0; i < nthdr->FileHeader.NumberOfSections; i++)
00233             {
00234                 memcpy(&fmap->u.pe.sect[i].shdr, section + i, sizeof(IMAGE_SECTION_HEADER));
00235                 fmap->u.pe.sect[i].mapped = IMAGE_NO_MAP;
00236             }
00237             if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols)
00238             {
00239                 LARGE_INTEGER li;
00240 
00241                 if (GetFileSizeEx(file, &li) && pe_is_valid_pointer_table(nthdr, mapping, li.QuadPart))
00242                 {
00243                     /* FIXME ugly: should rather map the relevant content instead of copying it */
00244                     const char* src = (const char*)mapping +
00245                         nthdr->FileHeader.PointerToSymbolTable +
00246                         nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
00247                     char* dst;
00248                     DWORD sz = *(DWORD*)src;
00249 
00250                     if ((dst = HeapAlloc(GetProcessHeap(), 0, sz)))
00251                         memcpy(dst, src, sz);
00252                     fmap->u.pe.strtable = dst;
00253                 }
00254                 else
00255                 {
00256                     WARN("Bad coff table... wipping out\n");
00257                     /* we have bad information here, wipe it out */
00258                     fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable = 0;
00259                     fmap->u.pe.ntheader.FileHeader.NumberOfSymbols = 0;
00260                     fmap->u.pe.strtable = NULL;
00261                 }
00262             }
00263             else fmap->u.pe.strtable = NULL;
00264         }
00265         break;
00266     default: assert(0); goto error;
00267     }
00268     pe_unmap_full(fmap);
00269 
00270     return TRUE;
00271 error:
00272     pe_unmap_full(fmap);
00273     CloseHandle(fmap->u.pe.hMap);
00274     return FALSE;
00275 }
00276 
00277 /******************************************************************
00278  *      pe_unmap_file
00279  *
00280  * Unmaps an PE file from memory (previously mapped with pe_map_file)
00281  */
00282 static void pe_unmap_file(struct image_file_map* fmap)
00283 {
00284     if (fmap->u.pe.hMap != 0)
00285     {
00286         struct image_section_map  ism;
00287         ism.fmap = fmap;
00288         for (ism.sidx = 0; ism.sidx < fmap->u.pe.ntheader.FileHeader.NumberOfSections; ism.sidx++)
00289         {
00290             pe_unmap_section(&ism);
00291         }
00292         while (fmap->u.pe.full_count) pe_unmap_full(fmap);
00293         HeapFree(GetProcessHeap(), 0, fmap->u.pe.sect);
00294         HeapFree(GetProcessHeap(), 0, (void*)fmap->u.pe.strtable); /* FIXME ugly (see pe_map_file) */
00295         CloseHandle(fmap->u.pe.hMap);
00296         fmap->u.pe.hMap = NULL;
00297     }
00298 }
00299 
00300 /******************************************************************
00301  *      pe_map_directory
00302  *
00303  * Maps a directory content out of a PE file
00304  */
00305 const char* pe_map_directory(struct module* module, int dirno, DWORD* size)
00306 {
00307     IMAGE_NT_HEADERS*   nth;
00308     void*               mapping;
00309 
00310     if (module->type != DMT_PE || !module->format_info[DFI_PE]) return NULL;
00311     if (dirno >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES ||
00312         !(mapping = pe_map_full(&module->format_info[DFI_PE]->u.pe_info->fmap, &nth)))
00313         return NULL;
00314     if (size) *size = nth->OptionalHeader.DataDirectory[dirno].Size;
00315     return RtlImageRvaToVa(nth, mapping,
00316                            nth->OptionalHeader.DataDirectory[dirno].VirtualAddress, NULL);
00317 }
00318 
00319 /******************************************************************
00320  *      pe_unmap_directory
00321  *
00322  * Unmaps a directory content
00323  */
00324 void pe_unmap_directory(struct image_file_map* fmap, int dirno)
00325 {
00326     pe_unmap_full(fmap);
00327 }
00328 
00329 static void pe_module_remove(struct process* pcs, struct module_format* modfmt)
00330 {
00331     pe_unmap_file(&modfmt->u.pe_info->fmap);
00332     HeapFree(GetProcessHeap(), 0, modfmt);
00333 }
00334 
00335 /******************************************************************
00336  *      pe_locate_with_coff_symbol_table
00337  *
00338  * Use the COFF symbol table (if any) from the IMAGE_FILE_HEADER to set the absolute address
00339  * of global symbols.
00340  * Mingw32 requires this for stabs debug information as address for global variables isn't filled in
00341  * (this is similar to what is done in elf_module.c when using the .symtab ELF section)
00342  */
00343 static BOOL pe_locate_with_coff_symbol_table(struct module* module)
00344 {
00345     struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
00346     const IMAGE_SYMBOL* isym;
00347     int                 i, numsym, naux;
00348     char                tmp[9];
00349     const char*         name;
00350     struct hash_table_iter      hti;
00351     void*               ptr;
00352     struct symt_data*   sym;
00353     const char*         mapping;
00354 
00355     numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols;
00356     if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym)
00357         return TRUE;
00358     if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
00359     isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
00360 
00361     for (i = 0; i < numsym; i+= naux, isym += naux)
00362     {
00363         if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
00364             isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections)
00365         {
00366             if (isym->N.Name.Short)
00367             {
00368                 name = memcpy(tmp, isym->N.ShortName, 8);
00369                 tmp[8] = '\0';
00370             }
00371             else name = fmap->u.pe.strtable + isym->N.Name.Long;
00372             if (name[0] == '_') name++;
00373             hash_table_iter_init(&module->ht_symbols, &hti, name);
00374             while ((ptr = hash_table_iter_up(&hti)))
00375             {
00376                 sym = GET_ENTRY(ptr, struct symt_data, hash_elt);
00377                 if (sym->symt.tag == SymTagData &&
00378                     (sym->kind == DataIsGlobal || sym->kind == DataIsFileStatic) &&
00379                     sym->u.var.kind == loc_absolute &&
00380                     !strcmp(sym->hash_elt.name, name))
00381                 {
00382                     TRACE("Changing absolute address for %d.%s: %lx -> %s\n",
00383                           isym->SectionNumber, name, sym->u.var.offset,
00384                           wine_dbgstr_longlong(module->module.BaseOfImage +
00385                                                fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress +
00386                                                isym->Value));
00387                     sym->u.var.offset = module->module.BaseOfImage +
00388                         fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + isym->Value;
00389                     break;
00390                 }
00391             }
00392         }
00393         naux = isym->NumberOfAuxSymbols + 1;
00394     }
00395     pe_unmap_full(fmap);
00396     return TRUE;
00397 }
00398 
00399 /******************************************************************
00400  *      pe_load_coff_symbol_table
00401  *
00402  * Load public symbols out of the COFF symbol table (if any).
00403  */
00404 static BOOL pe_load_coff_symbol_table(struct module* module)
00405 {
00406     struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
00407     const IMAGE_SYMBOL* isym;
00408     int                 i, numsym, naux;
00409     const char*         strtable;
00410     char                tmp[9];
00411     const char*         name;
00412     const char*         lastfilename = NULL;
00413     struct symt_compiland*   compiland = NULL;
00414     const IMAGE_SECTION_HEADER* sect;
00415     const char*         mapping;
00416 
00417     numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols;
00418     if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym)
00419         return TRUE;
00420     if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
00421     isym = (const IMAGE_SYMBOL*)((const char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
00422     /* FIXME: no way to get strtable size */
00423     strtable = (const char*)&isym[numsym];
00424     sect = IMAGE_FIRST_SECTION(RtlImageNtHeader((HMODULE)mapping));
00425 
00426     for (i = 0; i < numsym; i+= naux, isym += naux)
00427     {
00428         if (isym->StorageClass == IMAGE_SYM_CLASS_FILE)
00429         {
00430             lastfilename = (const char*)(isym + 1);
00431             compiland = NULL;
00432         }
00433         if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
00434             isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections)
00435         {
00436             if (isym->N.Name.Short)
00437             {
00438                 name = memcpy(tmp, isym->N.ShortName, 8);
00439                 tmp[8] = '\0';
00440             }
00441             else name = strtable + isym->N.Name.Long;
00442             if (name[0] == '_') name++;
00443 
00444             if (!compiland && lastfilename)
00445                 compiland = symt_new_compiland(module, 0,
00446                                                source_new(module, NULL, lastfilename));
00447 
00448             if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
00449                 symt_new_public(module, compiland, name,
00450                                 module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress +
00451                                      isym->Value,
00452                                 1);
00453         }
00454         naux = isym->NumberOfAuxSymbols + 1;
00455     }
00456     module->module.SymType = SymCoff;
00457     module->module.LineNumbers = FALSE;
00458     module->module.GlobalSymbols = FALSE;
00459     module->module.TypeInfo = FALSE;
00460     module->module.SourceIndexed = FALSE;
00461     module->module.Publics = TRUE;
00462     pe_unmap_full(fmap);
00463 
00464     return TRUE;
00465 }
00466 
00467 /******************************************************************
00468  *      pe_load_stabs
00469  *
00470  * look for stabs information in PE header (it's how the mingw compiler provides 
00471  * its debugging information)
00472  */
00473 static BOOL pe_load_stabs(const struct process* pcs, struct module* module)
00474 {
00475     struct image_file_map*      fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
00476     struct image_section_map    sect_stabs, sect_stabstr;
00477     BOOL                        ret = FALSE;
00478 
00479     if (pe_find_section(fmap, ".stab", &sect_stabs) && pe_find_section(fmap, ".stabstr", &sect_stabstr))
00480     {
00481         const char* stab;
00482         const char* stabstr;
00483 
00484         stab = image_map_section(&sect_stabs);
00485         stabstr = image_map_section(&sect_stabstr);
00486         if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP)
00487         {
00488             ret = stabs_parse(module,
00489                               module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase,
00490                               stab, image_get_map_size(&sect_stabs),
00491                               stabstr, image_get_map_size(&sect_stabstr),
00492                               NULL, NULL);
00493         }
00494         image_unmap_section(&sect_stabs);
00495         image_unmap_section(&sect_stabstr);
00496         if (ret) pe_locate_with_coff_symbol_table(module);
00497     }
00498     TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
00499 
00500     return ret;
00501 }
00502 
00503 /******************************************************************
00504  *      pe_load_dwarf
00505  *
00506  * look for dwarf information in PE header (it's also a way for the mingw compiler
00507  * to provide its debugging information)
00508  */
00509 static BOOL pe_load_dwarf(struct module* module)
00510 {
00511     struct image_file_map*      fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
00512     BOOL                        ret = FALSE;
00513 
00514     ret = dwarf2_parse(module,
00515                        module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase,
00516                        NULL, /* FIXME: some thunks to deal with ? */
00517                        fmap);
00518     TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
00519 
00520     return ret;
00521 }
00522 
00523 /******************************************************************
00524  *      pe_load_dbg_file
00525  *
00526  * loads a .dbg file
00527  */
00528 static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
00529                              const char* dbg_name, DWORD timestamp)
00530 {
00531     char                                tmp[MAX_PATH];
00532     HANDLE                              hFile = INVALID_HANDLE_VALUE, hMap = 0;
00533     const BYTE*                         dbg_mapping = NULL;
00534     BOOL                                ret = FALSE;
00535 
00536     TRACE("Processing DBG file %s\n", debugstr_a(dbg_name));
00537 
00538     if (path_find_symbol_file(pcs, dbg_name, NULL, timestamp, 0, tmp, &module->module.DbgUnmatched) &&
00539         (hFile = CreateFileA(tmp, GENERIC_READ, FILE_SHARE_READ, NULL,
00540                              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE &&
00541         ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
00542         ((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
00543     {
00544         const IMAGE_SEPARATE_DEBUG_HEADER*      hdr;
00545         const IMAGE_SECTION_HEADER*             sectp;
00546         const IMAGE_DEBUG_DIRECTORY*            dbg;
00547 
00548         hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)dbg_mapping;
00549         /* section headers come immediately after debug header */
00550         sectp = (const IMAGE_SECTION_HEADER*)(hdr + 1);
00551         /* and after that and the exported names comes the debug directory */
00552         dbg = (const IMAGE_DEBUG_DIRECTORY*)
00553             (dbg_mapping + sizeof(*hdr) +
00554              hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
00555              hdr->ExportedNamesSize);
00556 
00557         ret = pe_load_debug_directory(pcs, module, dbg_mapping, sectp,
00558                                       hdr->NumberOfSections, dbg,
00559                                       hdr->DebugDirectorySize / sizeof(*dbg));
00560     }
00561     else
00562         ERR("Couldn't find .DBG file %s (%s)\n", debugstr_a(dbg_name), debugstr_a(tmp));
00563 
00564     if (dbg_mapping) UnmapViewOfFile(dbg_mapping);
00565     if (hMap) CloseHandle(hMap);
00566     if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
00567     return ret;
00568 }
00569 
00570 /******************************************************************
00571  *      pe_load_msc_debug_info
00572  *
00573  * Process MSC debug information in PE file.
00574  */
00575 static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* module)
00576 {
00577     struct image_file_map*      fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
00578     BOOL                        ret = FALSE;
00579     const IMAGE_DATA_DIRECTORY* dir;
00580     const IMAGE_DEBUG_DIRECTORY*dbg = NULL;
00581     int                         nDbg;
00582     void*                       mapping;
00583     IMAGE_NT_HEADERS*           nth;
00584 
00585     if (!(mapping = pe_map_full(fmap, &nth))) return FALSE;
00586     /* Read in debug directory */
00587     dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
00588     nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
00589     if (!nDbg) goto done;
00590 
00591     dbg = RtlImageRvaToVa(nth, mapping, dir->VirtualAddress, NULL);
00592 
00593     /* Parse debug directory */
00594     if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
00595     {
00596         /* Debug info is stripped to .DBG file */
00597         const IMAGE_DEBUG_MISC* misc = (const IMAGE_DEBUG_MISC*)
00598             ((const char*)mapping + dbg->PointerToRawData);
00599 
00600         if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
00601             misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
00602         {
00603             ERR("-Debug info stripped, but no .DBG file in module %s\n",
00604                 debugstr_w(module->module.ModuleName));
00605         }
00606         else
00607         {
00608             ret = pe_load_dbg_file(pcs, module, (const char*)misc->Data, nth->FileHeader.TimeDateStamp);
00609         }
00610     }
00611     else
00612     {
00613         const IMAGE_SECTION_HEADER *sectp = (const IMAGE_SECTION_HEADER*)((const char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
00614         /* Debug info is embedded into PE module */
00615         ret = pe_load_debug_directory(pcs, module, mapping, sectp,
00616                                       nth->FileHeader.NumberOfSections, dbg, nDbg);
00617     }
00618 done:
00619     pe_unmap_full(fmap);
00620     return ret;
00621 }
00622 
00623 /***********************************************************************
00624  *          pe_load_export_debug_info
00625  */
00626 static BOOL pe_load_export_debug_info(const struct process* pcs, struct module* module)
00627 {
00628     struct image_file_map*              fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
00629     unsigned int                i;
00630     const IMAGE_EXPORT_DIRECTORY*   exports;
00631     DWORD                   base = module->module.BaseOfImage;
00632     DWORD                               size;
00633     IMAGE_NT_HEADERS*                   nth;
00634     void*                               mapping;
00635 
00636     if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;
00637 
00638     if (!(mapping = pe_map_full(fmap, &nth))) return FALSE;
00639 #if 0
00640     /* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */
00641     /* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
00642     symt_new_public(module, NULL, module->module.ModuleName, base, 1);
00643 #endif
00644     
00645     /* Add entry point */
00646     symt_new_public(module, NULL, "EntryPoint", 
00647                     base + nth->OptionalHeader.AddressOfEntryPoint, 1);
00648 #if 0
00649     /* FIXME: we'd better store addresses linked to sections rather than 
00650        absolute values */
00651     IMAGE_SECTION_HEADER*       section;
00652     /* Add start of sections */
00653     section = (IMAGE_SECTION_HEADER*)
00654         ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
00655     for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++) 
00656     {
00657     symt_new_public(module, NULL, section->Name, 
00658                         RtlImageRvaToVa(nth, mapping, section->VirtualAddress, NULL), 1);
00659     }
00660 #endif
00661 
00662     /* Add exported functions */
00663     if ((exports = RtlImageDirectoryEntryToData(mapping, FALSE,
00664                                                 IMAGE_DIRECTORY_ENTRY_EXPORT, &size)))
00665     {
00666         const WORD*             ordinals = NULL;
00667         const DWORD_PTR*    functions = NULL;
00668         const DWORD*        names = NULL;
00669         unsigned int        j;
00670         char            buffer[16];
00671 
00672         functions = RtlImageRvaToVa(nth, mapping, exports->AddressOfFunctions, NULL);
00673         ordinals  = RtlImageRvaToVa(nth, mapping, exports->AddressOfNameOrdinals, NULL);
00674         names     = RtlImageRvaToVa(nth, mapping, exports->AddressOfNames, NULL);
00675 
00676         if (functions && ordinals && names)
00677         {
00678             for (i = 0; i < exports->NumberOfNames; i++)
00679             {
00680                 if (!names[i]) continue;
00681                 symt_new_public(module, NULL,
00682                                 RtlImageRvaToVa(nth, mapping, names[i], NULL),
00683                                 base + functions[ordinals[i]], 1);
00684             }
00685 
00686             for (i = 0; i < exports->NumberOfFunctions; i++)
00687             {
00688                 if (!functions[i]) continue;
00689                 /* Check if we already added it with a name */
00690                 for (j = 0; j < exports->NumberOfNames; j++)
00691                     if ((ordinals[j] == i) && names[j]) break;
00692                 if (j < exports->NumberOfNames) continue;
00693                 snprintf(buffer, sizeof(buffer), "%d", i + exports->Base);
00694                 symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 1);
00695             }
00696         }
00697     }
00698     /* no real debug info, only entry points */
00699     if (module->module.SymType == SymDeferred)
00700         module->module.SymType = SymExport;
00701     pe_unmap_full(fmap);
00702 
00703     return TRUE;
00704 }
00705 
00706 /******************************************************************
00707  *      pe_load_debug_info
00708  *
00709  */
00710 BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
00711 {
00712     BOOL                ret = FALSE;
00713 
00714     if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
00715     {
00716         ret = pe_load_stabs(pcs, module);
00717         ret = pe_load_dwarf(module) || ret;
00718         ret = pe_load_msc_debug_info(pcs, module) || ret;
00719         ret = ret || pe_load_coff_symbol_table(module); /* FIXME */
00720         /* if we still have no debug info (we could only get SymExport at this
00721          * point), then do the SymExport except if we have an ELF container,
00722          * in which case we'll rely on the export's on the ELF side
00723          */
00724     }
00725     /* FIXME shouldn't we check that? if (!module_get_debug(pcs, module)) */
00726     if (pe_load_export_debug_info(pcs, module) && !ret)
00727         ret = TRUE;
00728 
00729     return ret;
00730 }
00731 
00732 /******************************************************************
00733  *      pe_load_native_module
00734  *
00735  */
00736 struct module* pe_load_native_module(struct process* pcs, const WCHAR* name,
00737                                      HANDLE hFile, DWORD64 base, DWORD size)
00738 {
00739     struct module*              module = NULL;
00740     BOOL                        opened = FALSE;
00741     struct module_format*       modfmt;
00742     WCHAR                       loaded_name[MAX_PATH];
00743 
00744     loaded_name[0] = '\0';
00745     if (!hFile)
00746     {
00747         assert(name);
00748 
00749         if ((hFile = FindExecutableImageExW(name, pcs->search_path, loaded_name, NULL, NULL)) == NULL)
00750             return NULL;
00751         opened = TRUE;
00752     }
00753     else if (name) strcpyW(loaded_name, name);
00754     else if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
00755         FIXME("Trouble ahead (no module name passed in deferred mode)\n");
00756     if (!(modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct pe_module_info))))
00757         return NULL;
00758     modfmt->u.pe_info = (struct pe_module_info*)(modfmt + 1);
00759     if (pe_map_file(hFile, &modfmt->u.pe_info->fmap, DMT_PE))
00760     {
00761         if (!base) base = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.ImageBase;
00762         if (!size) size = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.SizeOfImage;
00763 
00764         module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size,
00765                             modfmt->u.pe_info->fmap.u.pe.ntheader.FileHeader.TimeDateStamp,
00766                             modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.CheckSum);
00767         if (module)
00768         {
00769             modfmt->module = module;
00770             modfmt->remove = pe_module_remove;
00771             modfmt->loc_compute = NULL;
00772 
00773             module->format_info[DFI_PE] = modfmt;
00774             if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
00775                 module->module.SymType = SymDeferred;
00776             else
00777                 pe_load_debug_info(pcs, module);
00778             module->reloc_delta = base - modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.ImageBase;
00779         }
00780         else
00781         {
00782             ERR("could not load the module '%s'\n", debugstr_w(loaded_name));
00783             pe_unmap_file(&modfmt->u.pe_info->fmap);
00784         }
00785     }
00786     if (!module) HeapFree(GetProcessHeap(), 0, modfmt);
00787 
00788     if (opened) CloseHandle(hFile);
00789 
00790     return module;
00791 }
00792 
00793 /******************************************************************
00794  *      pe_load_nt_header
00795  *
00796  */
00797 BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth)
00798 {
00799     IMAGE_DOS_HEADER    dos;
00800 
00801     return ReadProcessMemory(hProc, (char*)(DWORD_PTR)base, &dos, sizeof(dos), NULL) &&
00802         dos.e_magic == IMAGE_DOS_SIGNATURE &&
00803         ReadProcessMemory(hProc, (char*)(DWORD_PTR)(base + dos.e_lfanew),
00804                           nth, sizeof(*nth), NULL) &&
00805         nth->Signature == IMAGE_NT_SIGNATURE;
00806 }
00807 
00808 /******************************************************************
00809  *      pe_load_builtin_module
00810  *
00811  */
00812 struct module* pe_load_builtin_module(struct process* pcs, const WCHAR* name,
00813                                       DWORD64 base, DWORD64 size)
00814 {
00815     struct module*      module = NULL;
00816 
00817     if (base && pcs->dbg_hdr_addr)
00818     {
00819         IMAGE_NT_HEADERS    nth;
00820 
00821         if (pe_load_nt_header(pcs->handle, base, &nth))
00822         {
00823             if (!size) size = nth.OptionalHeader.SizeOfImage;
00824             module = module_new(pcs, name, DMT_PE, FALSE, base, size,
00825                                 nth.FileHeader.TimeDateStamp,
00826                                 nth.OptionalHeader.CheckSum);
00827         }
00828     }
00829     return module;
00830 }
00831 
00832 /***********************************************************************
00833  *           ImageDirectoryEntryToDataEx (DBGHELP.@)
00834  *
00835  * Search for specified directory in PE image
00836  *
00837  * PARAMS
00838  *
00839  *   base    [in]  Image base address
00840  *   image   [in]  TRUE - image has been loaded by loader, FALSE - raw file image
00841  *   dir     [in]  Target directory index
00842  *   size    [out] Receives directory size
00843  *   section [out] Receives pointer to section header of section containing directory data
00844  *
00845  * RETURNS
00846  *   Success: pointer to directory data
00847  *   Failure: NULL
00848  *
00849  */
00850 PVOID WINAPI ImageDirectoryEntryToDataEx( PVOID base, BOOLEAN image, USHORT dir, PULONG size, PIMAGE_SECTION_HEADER *section )
00851 {
00852     const IMAGE_NT_HEADERS *nt;
00853     DWORD addr;
00854 
00855     *size = 0;
00856     if (section) *section = NULL;
00857 
00858     if (!(nt = RtlImageNtHeader( base ))) return NULL;
00859     if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
00860     if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
00861 
00862     *size = nt->OptionalHeader.DataDirectory[dir].Size;
00863     if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)base + addr;
00864 
00865     return RtlImageRvaToVa( nt, base, addr, section );
00866 }
00867 
00868 /***********************************************************************
00869  *         ImageDirectoryEntryToData   (DBGHELP.@)
00870  *
00871  * NOTES
00872  *   See ImageDirectoryEntryToDataEx
00873  */
00874 PVOID WINAPI ImageDirectoryEntryToData( PVOID base, BOOLEAN image, USHORT dir, PULONG size )
00875 {
00876     return ImageDirectoryEntryToDataEx( base, image, dir, size, NULL );
00877 }

Generated on Sat May 26 2012 04:22:00 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.