2 * File pe_module.c - handle PE module information
4 * Copyright (C) 1996, Eric Youngdale.
5 * Copyright (C) 1999-2000, Ulrich Weigand.
6 * Copyright (C) 2004, Eric Pouech.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "dbghelp_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp
);
37 /******************************************************************
40 * look for stabs information in PE header (it's how the mingw compiler provides
41 * its debugging information)
43 static SYM_TYPE
pe_load_stabs(const struct process
* pcs
, struct module
* module
,
44 const void* mapping
, IMAGE_NT_HEADERS
* nth
)
46 IMAGE_SECTION_HEADER
* section
;
47 int i
, stabsize
= 0, stabstrsize
= 0;
48 unsigned int stabs
= 0, stabstr
= 0;
49 SYM_TYPE sym_type
= SymNone
;
51 section
= (IMAGE_SECTION_HEADER
*)
52 ((char*)&nth
->OptionalHeader
+ nth
->FileHeader
.SizeOfOptionalHeader
);
53 for (i
= 0; i
< nth
->FileHeader
.NumberOfSections
; i
++, section
++)
55 if (!strcasecmp(section
->Name
, ".stab"))
57 stabs
= section
->VirtualAddress
;
58 stabsize
= section
->SizeOfRawData
;
60 else if (!strncasecmp(section
->Name
, ".stabstr", 8))
62 stabstr
= section
->VirtualAddress
;
63 stabstrsize
= section
->SizeOfRawData
;
67 if (stabstrsize
&& stabsize
)
69 sym_type
= stabs_parse(module
, mapping
, module
->module
.BaseOfImage
,
70 stabs
, stabsize
, stabstr
, stabstrsize
);
75 /******************************************************************
80 static SYM_TYPE
pe_load_dbg_file(const struct process
* pcs
, struct module
* module
,
81 const char* dbg_name
, DWORD timestamp
)
84 HANDLE hFile
, hMap
= 0;
85 const BYTE
* dbg_mapping
= NULL
;
86 const IMAGE_SEPARATE_DEBUG_HEADER
* hdr
;
87 const IMAGE_DEBUG_DIRECTORY
* dbg
;
88 SYM_TYPE sym_type
= -1;
90 WINE_TRACE("Processing DBG file %s\n", dbg_name
);
92 if ((hFile
= FindDebugInfoFile((char*)dbg_name
, pcs
->search_path
, tmp
)) != NULL
&&
93 ((hMap
= CreateFileMappingA(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
)) != 0) &&
94 ((dbg_mapping
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) != NULL
))
96 hdr
= (const IMAGE_SEPARATE_DEBUG_HEADER
*)dbg_mapping
;
97 if (hdr
->TimeDateStamp
!= timestamp
)
99 WINE_ERR("Warning - %s has incorrect internal timestamp\n",
102 * Well, sometimes this happens to DBG files which ARE REALLY the
103 * right .DBG files but nonetheless this check fails. Anyway,
104 * WINDBG (debugger for Windows by Microsoft) loads debug symbols
105 * which have incorrect timestamps.
108 dbg
= (const IMAGE_DEBUG_DIRECTORY
*)
109 (dbg_mapping
+ sizeof(*hdr
) +
110 hdr
->NumberOfSections
* sizeof(IMAGE_SECTION_HEADER
) +
111 hdr
->ExportedNamesSize
);
113 sym_type
= pe_load_debug_directory(pcs
, module
, dbg_mapping
, dbg
,
114 hdr
->DebugDirectorySize
/ sizeof(*dbg
));
118 WINE_ERR("-Unable to peruse .DBG file %s (%s)\n",
119 dbg_name
, debugstr_a(tmp
));
121 if (dbg_mapping
) UnmapViewOfFile((void*)dbg_mapping
);
122 if (hMap
) CloseHandle(hMap
);
123 if (hFile
!= NULL
) CloseHandle(hFile
);
127 /******************************************************************
128 * pe_load_msc_debug_info
130 * Process MSC debug information in PE file.
132 static SYM_TYPE
pe_load_msc_debug_info(const struct process
* pcs
,
133 struct module
* module
,
134 const void* mapping
, IMAGE_NT_HEADERS
* nth
)
136 SYM_TYPE sym_type
= -1;
137 const IMAGE_DATA_DIRECTORY
* dir
;
138 const IMAGE_DEBUG_DIRECTORY
*dbg
= NULL
;
141 /* Read in debug directory */
142 dir
= nth
->OptionalHeader
.DataDirectory
+ IMAGE_DIRECTORY_ENTRY_DEBUG
;
143 nDbg
= dir
->Size
/ sizeof(IMAGE_DEBUG_DIRECTORY
);
144 if (!nDbg
) return sym_type
;
146 dbg
= (const IMAGE_DEBUG_DIRECTORY
*)((const char*)mapping
+ dir
->VirtualAddress
);
148 /* Parse debug directory */
149 if (nth
->FileHeader
.Characteristics
& IMAGE_FILE_DEBUG_STRIPPED
)
151 /* Debug info is stripped to .DBG file */
152 const IMAGE_DEBUG_MISC
* misc
= (const IMAGE_DEBUG_MISC
*)
153 ((const char*)mapping
+ dbg
->PointerToRawData
);
155 if (nDbg
!= 1 || dbg
->Type
!= IMAGE_DEBUG_TYPE_MISC
||
156 misc
->DataType
!= IMAGE_DEBUG_MISC_EXENAME
)
158 WINE_ERR("-Debug info stripped, but no .DBG file in module %s\n",
159 module
->module
.ModuleName
);
163 sym_type
= pe_load_dbg_file(pcs
, module
, misc
->Data
, nth
->FileHeader
.TimeDateStamp
);
168 /* Debug info is embedded into PE module */
169 sym_type
= pe_load_debug_directory(pcs
, module
, mapping
, dbg
, nDbg
);
175 /***********************************************************************
176 * pe_load_export_debug_info
178 static SYM_TYPE
pe_load_export_debug_info(const struct process
* pcs
,
179 struct module
* module
,
180 const void* mapping
, IMAGE_NT_HEADERS
* nth
)
183 IMAGE_DATA_DIRECTORY
* dir
;
184 DWORD base
= module
->module
.BaseOfImage
;
187 addr
.Mode
= AddrModeFlat
;
191 /* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */
192 /* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
193 symt_new_public(module
, NULL
, module
->module
.ModuleName
, base
, 0,
194 TRUE
/* FIXME */, TRUE
/* FIXME */);
197 /* Add entry point */
198 symt_new_public(module
, NULL
, "EntryPoint",
199 base
+ nth
->OptionalHeader
.AddressOfEntryPoint
, 0,
200 TRUE
/* FIXME */, TRUE
/* FIXME */);
203 /* FIXME: we'd better store addresses linked to sections rather than
205 IMAGE_SECTION_HEADER
* section
;
206 /* Add start of sections */
207 section
= (IMAGE_SECTION_HEADER
*)
208 ((char*)&nth
->OptionalHeader
+ nth
->FileHeader
.SizeOfOptionalHeader
);
209 for (i
= 0; i
< nth
->FileHeader
.NumberOfSections
; i
++, section
++)
211 symt_new_public(module
, NULL
, section
->Name
, base
+ section
->VirtualAddress
, 0,
212 TRUE
/* FIXME */, TRUE
/* FIXME */);
216 /* Add exported functions */
217 if ((dir
= RtlImageDirectoryEntryToData((void*)mapping
, TRUE
,
218 IMAGE_DIRECTORY_ENTRY_EXPORT
, NULL
)))
220 const IMAGE_EXPORT_DIRECTORY
* exports
;
221 const WORD
* ordinals
= NULL
;
222 const void* const* functions
= NULL
;
223 const DWORD
* names
= NULL
;
227 exports
= (const void*)((const char*)mapping
+ dir
->VirtualAddress
);
228 functions
= (const void*)((const char*)mapping
+ exports
->AddressOfFunctions
);
229 ordinals
= (const void*)((const char*)mapping
+ exports
->AddressOfNameOrdinals
);
230 names
= (const void*)((const char*)mapping
+ exports
->AddressOfNames
);
232 for (i
= 0; i
< exports
->NumberOfNames
; i
++)
234 if (!names
[i
]) continue;
235 symt_new_public(module
, NULL
, (const char*)base
+ names
[i
],
236 base
+ (DWORD
)functions
[ordinals
[i
]], 0,
237 TRUE
/* FIXME */, TRUE
/* FIXME */);
240 for (i
= 0; i
< exports
->NumberOfFunctions
; i
++)
242 if (!functions
[i
]) continue;
243 /* Check if we already added it with a name */
244 for (j
= 0; j
< exports
->NumberOfNames
; j
++)
245 if ((ordinals
[j
] == i
) && names
[j
]) break;
246 if (j
< exports
->NumberOfNames
) continue;
247 snprintf(buffer
, sizeof(buffer
), "%ld", i
+ exports
->Base
);
248 symt_new_public(module
, NULL
, buffer
, base
+ (DWORD
)functions
[i
], 0,
249 TRUE
/* FIXME */, TRUE
/* FIXME */);
252 /* no real debug info, only entry points */
253 return module
->module
.SymType
= SymExport
;
256 /******************************************************************
260 SYM_TYPE
pe_load_debug_info(const struct process
* pcs
, struct module
* module
)
262 SYM_TYPE sym_type
= -1;
266 IMAGE_NT_HEADERS
* nth
;
268 hFile
= CreateFileA(module
->module
.LoadedImageName
, GENERIC_READ
, FILE_SHARE_READ
,
269 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
270 if (hFile
== INVALID_HANDLE_VALUE
) return -1;
271 if ((hMap
= CreateFileMappingA(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
)) != 0)
273 if ((mapping
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) != NULL
)
275 nth
= RtlImageNtHeader(mapping
);
277 if (!(dbghelp_options
& SYMOPT_PUBLICS_ONLY
))
279 sym_type
= pe_load_stabs(pcs
, module
, mapping
, nth
);
280 if (sym_type
<= SymNone
)
281 sym_type
= pe_load_msc_debug_info(pcs
, module
, mapping
, nth
);
282 /* if we still have no debug info (we could only get SymExport at this
283 * point), then do the SymExport except if we have an ELF container,
284 * in which case we'll rely on the export's on the ELF side
287 if (sym_type
<= SymNone
&& !module_get_debug(pcs
, module
))
288 sym_type
= pe_load_export_debug_info(pcs
, module
, mapping
, nth
);
289 UnmapViewOfFile(mapping
);
295 module
->module
.SymType
= (sym_type
>= SymNone
) ? sym_type
: SymNone
;
299 /******************************************************************
303 struct module
* pe_load_module(struct process
* pcs
, char* name
,
304 HANDLE hFile
, DWORD base
, DWORD size
)
306 struct module
* module
= NULL
;
310 char loaded_name
[MAX_PATH
];
312 loaded_name
[0] = '\0';
317 /* FIXME SetLastError */
320 if ((hFile
= FindExecutableImage(name
, NULL
, loaded_name
)) == NULL
)
324 else if (name
) strcpy(loaded_name
, name
);
325 else if (dbghelp_options
& SYMOPT_DEFERRED_LOADS
)
326 FIXME("Trouble ahead (no module name passed in deferred mode)\n");
327 if ((hMap
= CreateFileMappingA(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
)) != 0)
329 if ((mapping
= MapViewOfFile(hMap
, FILE_MAP_READ
, 0, 0, 0)) != NULL
)
331 IMAGE_NT_HEADERS
* nth
= RtlImageNtHeader(mapping
);
335 if (!base
) base
= nth
->OptionalHeader
.ImageBase
;
336 if (!size
) size
= nth
->OptionalHeader
.SizeOfImage
;
338 module
= module_new(pcs
, loaded_name
, DMT_PE
, base
, size
,
339 nth
->FileHeader
.TimeDateStamp
,
340 nth
->OptionalHeader
.CheckSum
);
343 module
->module
.SymType
= (dbghelp_options
& SYMOPT_DEFERRED_LOADS
) ?
344 SymDeferred
: pe_load_debug_info(pcs
, module
);
347 UnmapViewOfFile(mapping
);
351 if (opened
) CloseHandle(hFile
);
356 /******************************************************************
357 * pe_load_module_from_pcs
360 struct module
* pe_load_module_from_pcs(struct process
* pcs
, const char* name
,
361 const char* mod_name
, DWORD base
, DWORD size
)
363 struct module
* module
;
366 if ((module
= module_find_by_name(pcs
, name
, DMT_PE
))) return module
;
367 if (mod_name
) ptr
= mod_name
;
370 for (ptr
= name
+ strlen(name
) - 1; ptr
>= name
; ptr
--)
372 if (*ptr
== '/' || *ptr
== '\\')
379 if (ptr
&& (module
= module_find_by_name(pcs
, ptr
, DMT_PE
))) return module
;
380 if (base
&& pcs
->dbg_hdr_addr
)
382 IMAGE_DOS_HEADER dos
;
383 IMAGE_NT_HEADERS nth
;
385 if (read_mem(pcs
->handle
, base
, &dos
, sizeof(dos
)) &&
386 dos
.e_magic
== IMAGE_DOS_SIGNATURE
&&
387 read_mem(pcs
->handle
, base
+ dos
.e_lfanew
, &nth
, sizeof(nth
)) &&
388 nth
.Signature
== IMAGE_NT_SIGNATURE
)
390 if (!size
) size
= nth
.OptionalHeader
.SizeOfImage
;
391 module
= module_new(pcs
, name
, DMT_PE
, base
, size
,
392 nth
.FileHeader
.TimeDateStamp
, nth
.OptionalHeader
.CheckSum
);