CreateSpoolFile is called with a dos name, we have to make sure that
[wine.git] / debugger / module.c
blob5ab651acad3bf97fd2906665608f1b40afb82f64
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*
3 * File module.c - module handling for the wine debugger
5 * Copyright (C) 1993, Eric Youngdale.
6 * 2000, Eric Pouech
7 */
8 #include "config.h"
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "neexe.h"
13 #include "module.h"
14 #include "file.h"
15 #include "debugger.h"
16 #include "toolhelp.h"
17 #include "wingdi.h"
18 #include "winuser.h"
20 /***********************************************************************
21 * Creates and links a new module to the current process
24 DBG_MODULE* DEBUG_AddModule(const char* name, int type,
25 void* mod_addr, HMODULE hmodule)
27 DBG_MODULE* wmod;
29 if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
30 return NULL;
32 memset(wmod, 0, sizeof(*wmod));
34 wmod->next = DEBUG_CurrProcess->modules;
35 wmod->status = DM_STATUS_NEW;
36 wmod->type = type;
37 wmod->load_addr = mod_addr;
38 wmod->handle = hmodule;
39 wmod->dbg_index = DEBUG_CurrProcess->next_index;
40 wmod->module_name = DBG_strdup(name);
41 DEBUG_CurrProcess->modules = wmod;
43 return wmod;
46 /***********************************************************************
47 * DEBUG_FindModuleByName
50 DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type)
52 DBG_MODULE* wmod;
54 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
55 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
56 !strcasecmp(name, wmod->module_name)) break;
58 return wmod;
61 /***********************************************************************
62 * DEBUG_FindModuleByAddr
64 * either the addr where module is loaded, or any address inside the
65 * module
67 DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, int type)
69 DBG_MODULE* wmod;
70 DBG_MODULE* res = NULL;
72 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
73 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
74 (u_long)addr >= (u_long)wmod->load_addr &&
75 (!res || res->load_addr < wmod->load_addr))
76 res = wmod;
78 return res;
81 /***********************************************************************
82 * DEBUG_FindModuleByHandle
84 DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
86 DBG_MODULE* wmod;
88 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
89 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
91 return wmod;
94 /***********************************************************************
95 * DEBUG_RegisterELFModule
97 * ELF modules are also entered into the list - this is so that we
98 * can make 'info shared' types of displays possible.
100 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
102 DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
104 if (!wmod) return NULL;
106 wmod->status = DM_STATUS_LOADED;
107 DEBUG_CurrProcess->next_index++;
109 return wmod;
112 /***********************************************************************
113 * DEBUG_RegisterPEModule
116 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
118 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
120 if (!wmod) return NULL;
122 DEBUG_CurrProcess->next_index++;
124 return wmod;
127 /***********************************************************************
128 * DEBUG_RegisterNEModule
131 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
133 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
135 if (!wmod) return NULL;
137 wmod->status = DM_STATUS_LOADED;
138 DEBUG_CurrProcess->next_index++;
139 return wmod;
142 /***********************************************************************
143 * DEBUG_GetEP16
145 * Helper function fo DEBUG_LoadModuleEPs16:
146 * finds the address of a given entry point from a given module
148 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module,
149 WORD ordinal, DBG_ADDR* addr)
151 void* idx;
152 ET_ENTRY entry;
153 ET_BUNDLE bundle;
154 SEGTABLEENTRY ste;
156 bundle.next = module->entry_table;
157 do {
158 if (!bundle.next)
159 return FALSE;
160 idx = moduleAddr + bundle.next;
161 if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
162 return FALSE;
163 } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
165 if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) +
166 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY),
167 &entry, sizeof(ET_ENTRY)))
168 return FALSE;
170 addr->seg = entry.segnum;
171 addr->off = entry.offs;
173 if (addr->seg == 0xfe) addr->seg = 0xffff; /* constant entry */
174 else {
175 if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table +
176 sizeof(ste) * (addr->seg - 1),
177 &ste, sizeof(ste)))
178 return FALSE;
179 addr->seg = GlobalHandleToSel16(ste.hSeg);
181 return TRUE;
184 /***********************************************************************
185 * DEBUG_LoadModule16
187 * Load the entry points of a Win16 module into the hash table.
189 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
191 DBG_VALUE value;
192 BYTE buf[1 + 256 + 2];
193 char epname[512];
194 char* cpnt;
195 DBG_MODULE* wmod;
197 wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
199 value.type = NULL;
200 value.cookie = DV_TARGET;
201 value.addr.seg = 0;
202 value.addr.off = 0;
204 cpnt = moduleAddr + module->name_table;
206 /* First search the resident names */
208 /* skip module name */
209 if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
210 return;
211 cpnt += 1 + buf[0] + sizeof(WORD);
213 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
214 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
215 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
216 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
218 cpnt += buf[0] + 1 + sizeof(WORD);
221 /* Now search the non-resident names table */
222 if (!module->nrname_handle) return; /* No non-resident table */
223 cpnt = (char *)GlobalLock16(module->nrname_handle);
224 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
225 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
226 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
227 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
229 cpnt += buf[0] + 1 + sizeof(WORD);
231 GlobalUnlock16(module->nrname_handle);
234 /***********************************************************************
235 * DEBUG_LoadModule32
237 void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
239 DBG_VALUE value;
240 char buffer[512];
241 char bufstr[256];
242 int i;
243 IMAGE_NT_HEADERS pe_header;
244 DWORD pe_header_ofs;
245 IMAGE_SECTION_HEADER pe_seg;
246 DWORD pe_seg_ofs;
247 IMAGE_DATA_DIRECTORY dir;
248 DWORD dir_ofs;
249 DBG_MODULE* wmod;
250 const char *prefix;
252 /* FIXME: we make the assumption that hModule == base */
253 wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
255 DEBUG_Printf(DBG_CHN_TRACE, "Registring 32bit DLL '%s' at %08lx\n", name, base);
257 value.type = NULL;
258 value.cookie = DV_TARGET;
259 value.addr.seg = 0;
260 value.addr.off = 0;
262 /* grab PE Header */
263 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
264 &pe_header_ofs, sizeof(pe_header_ofs)) ||
265 !DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs),
266 &pe_header, sizeof(pe_header)))
267 return;
269 if (wmod) {
270 DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
271 DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
274 /* Add start of DLL */
275 value.addr.off = base;
276 if ((prefix = strrchr( name, '\\' ))) prefix++;
277 else prefix = name;
279 DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
281 /* Add entry point */
282 wsnprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
283 value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
284 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
286 /* Add start of sections */
287 pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
288 pe_header.FileHeader.SizeOfOptionalHeader;
290 for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
291 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
292 continue;
293 wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
294 value.addr.off = base + pe_seg.VirtualAddress;
295 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
298 /* Add exported functions */
299 dir_ofs = pe_header_ofs +
300 OFFSET_OF(IMAGE_NT_HEADERS,
301 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
302 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
303 IMAGE_EXPORT_DIRECTORY exports;
304 WORD* ordinals = NULL;
305 void** functions = NULL;
306 DWORD* names = NULL;
307 int j;
309 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress),
310 &exports, sizeof(exports)) &&
312 ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
313 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
314 functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
316 ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
317 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
318 ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
320 ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
321 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
322 names, sizeof(names[0]) * exports.NumberOfNames)) {
324 for (i = 0; i < exports.NumberOfNames; i++) {
325 if (!names[i] ||
326 !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
327 continue;
328 bufstr[sizeof(bufstr) - 1] = 0;
329 wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, bufstr);
330 value.addr.off = base + (DWORD)functions[ordinals[i]];
331 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
334 for (i = 0; i < exports.NumberOfFunctions; i++) {
335 if (!functions[i]) continue;
336 /* Check if we already added it with a name */
337 for (j = 0; j < exports.NumberOfNames; j++)
338 if ((ordinals[j] == i) && names[j]) break;
339 if (j < exports.NumberOfNames) continue;
340 wsnprintf(buffer, sizeof(buffer), "%s.%ld", prefix, i + exports.Base);
341 value.addr.off = base + (DWORD)functions[i];
342 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
345 DBG_free(functions);
346 DBG_free(ordinals);
347 DBG_free(names);
351 /***********************************************************************
352 * DEBUG_LoadEntryPoints
354 * Load the entry points of all the modules into the hash table.
356 int DEBUG_LoadEntryPoints(const char* pfx)
358 MODULEENTRY entry;
359 NE_MODULE module;
360 void* moduleAddr;
361 int first = 0;
362 int rowcount = 0;
363 int len;
365 /* FIXME: we assume that a module is never removed from memory */
366 /* FIXME: this is (currently plain wrong when debugger is started by
367 * attaching to an existing program => the 16 bit modules will
368 * not be shared... not much to do on debugger side... sigh
370 if (ModuleFirst16(&entry)) do {
371 if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
372 !(moduleAddr = NE_GetPtr(entry.hModule)) ||
373 !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
374 (module.flags & NE_FFLAGS_WIN32) /* NE module */)
375 continue;
376 if (!first) {
377 if (pfx) DEBUG_Printf(DBG_CHN_MESG, pfx);
378 DEBUG_Printf(DBG_CHN_MESG, " ");
379 rowcount = 3 + (pfx ? strlen(pfx) : 0);
380 first = 1;
383 len = strlen(entry.szModule);
384 if ((rowcount + len) > 76) {
385 DEBUG_Printf(DBG_CHN_MESG, "\n ");
386 rowcount = 3;
388 DEBUG_Printf(DBG_CHN_MESG, " %s", entry.szModule);
389 rowcount += len + 1;
391 DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
392 } while (ModuleNext16(&entry));
394 if (first) DEBUG_Printf(DBG_CHN_MESG, "\n");
395 return first;
398 /***********************************************************************
399 * DEBUG_InfoShare
401 * Display shared libarary information.
403 void DEBUG_InfoShare(void)
405 DBG_MODULE* wmod;
406 const char* xtype;
408 DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
410 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
411 switch (wmod->type) {
412 case DM_TYPE_NE: xtype = "NE"; break;
413 case DM_TYPE_PE: xtype = "PE"; break;
414 case DM_TYPE_ELF: xtype = "ELF"; break;
415 default: xtype = "???"; break;
417 DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
418 xtype, wmod->module_name);
422 static const char* DEBUG_GetModuleType(int type)
424 switch (type) {
425 case DM_TYPE_NE: return "NE";
426 case DM_TYPE_PE: return "PE";
427 case DM_TYPE_ELF: return "ELF";
428 default: return "???";;
432 static const char* DEBUG_GetModuleStatus(int status)
434 switch (status) {
435 case DM_STATUS_NEW: return "deferred";
436 case DM_STATUS_LOADED: return "ok";
437 case DM_STATUS_ERROR: return "error";
438 default: return "???";
442 /***********************************************************************
443 * DEBUG_
444 * Display information about a given module (DLL or EXE)
446 void DEBUG_DumpModule(DWORD mod)
448 DBG_MODULE* wmod;
450 if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
451 !(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
452 DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
453 return;
456 DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
457 wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
458 DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
461 /***********************************************************************
462 * DEBUG_WalkModules
464 * Display information about all modules (DLLs and EXEs)
466 void DEBUG_WalkModules(void)
468 DBG_MODULE* wmod;
469 const char* xtype;
471 DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
473 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
474 switch (wmod->type) {
475 case DM_TYPE_NE: xtype = "NE"; break;
476 case DM_TYPE_PE: xtype = "PE"; break;
477 case DM_TYPE_ELF: continue;
478 default: xtype = "???"; break;
481 DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n",
482 (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type),
483 wmod->module_name);