Protect the backslashes we mean to have show from groff.
[wine.git] / debugger / module.c
blob793455e4f053bd9e05224c6320c921eef7cd9e4c
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 "file.h"
14 #include "debugger.h"
15 #include "toolhelp.h"
16 #include "wingdi.h"
17 #include "winuser.h"
19 /***********************************************************************
20 * Creates and links a new module to the current process
23 DBG_MODULE* DEBUG_AddModule(const char* name, int type,
24 void* mod_addr, HMODULE hmodule)
26 DBG_MODULE* wmod;
28 if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
29 return NULL;
31 memset(wmod, 0, sizeof(*wmod));
33 wmod->next = DEBUG_CurrProcess->modules;
34 wmod->status = DM_STATUS_NEW;
35 wmod->type = type;
36 wmod->load_addr = mod_addr;
37 wmod->handle = hmodule;
38 wmod->dbg_index = DEBUG_CurrProcess->next_index;
39 wmod->module_name = DBG_strdup(name);
40 DEBUG_CurrProcess->modules = wmod;
42 return wmod;
45 /***********************************************************************
46 * DEBUG_FindModuleByName
49 DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type)
51 DBG_MODULE* wmod;
53 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
54 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
55 !strcasecmp(name, wmod->module_name)) break;
57 return wmod;
60 /***********************************************************************
61 * DEBUG_FindModuleByAddr
63 * either the addr where module is loaded, or any address inside the
64 * module
66 DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, int type)
68 DBG_MODULE* wmod;
69 DBG_MODULE* res = NULL;
71 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
72 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
73 (u_long)addr >= (u_long)wmod->load_addr &&
74 (!res || res->load_addr < wmod->load_addr))
75 res = wmod;
77 return res;
80 /***********************************************************************
81 * DEBUG_FindModuleByHandle
83 DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
85 DBG_MODULE* wmod;
87 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
88 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
90 return wmod;
93 /***********************************************************************
94 * DEBUG_GetProcessMainModule
96 DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
98 DBG_MODULE* wmod;
100 if (!process) return NULL;
102 /* main module is the first to be loaded on a given process, so it's the last on
103 * the list */
104 for (wmod = process->modules; wmod && wmod->next; wmod = wmod->next);
105 return wmod;
108 /***********************************************************************
109 * DEBUG_RegisterELFModule
111 * ELF modules are also entered into the list - this is so that we
112 * can make 'info shared' types of displays possible.
114 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
116 DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
118 if (!wmod) return NULL;
120 wmod->status = DM_STATUS_LOADED;
121 DEBUG_CurrProcess->next_index++;
123 return wmod;
126 /***********************************************************************
127 * DEBUG_RegisterPEModule
130 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
132 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
134 if (!wmod) return NULL;
136 DEBUG_CurrProcess->next_index++;
138 return wmod;
141 /***********************************************************************
142 * DEBUG_RegisterNEModule
145 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
147 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
149 if (!wmod) return NULL;
151 wmod->status = DM_STATUS_LOADED;
152 DEBUG_CurrProcess->next_index++;
153 return wmod;
156 #if 0
157 /***********************************************************************
158 * DEBUG_GetEP16
160 * Helper function fo DEBUG_LoadModuleEPs16:
161 * finds the address of a given entry point from a given module
163 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module,
164 WORD ordinal, DBG_ADDR* addr)
166 void* idx;
167 ET_ENTRY entry;
168 ET_BUNDLE bundle;
169 SEGTABLEENTRY ste;
171 bundle.next = module->entry_table;
172 do {
173 if (!bundle.next)
174 return FALSE;
175 idx = moduleAddr + bundle.next;
176 if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
177 return FALSE;
178 } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
180 if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) +
181 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY),
182 &entry, sizeof(ET_ENTRY)))
183 return FALSE;
185 addr->seg = entry.segnum;
186 addr->off = entry.offs;
188 if (addr->seg == 0xfe) addr->seg = 0xffff; /* constant entry */
189 else {
190 if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table +
191 sizeof(ste) * (addr->seg - 1),
192 &ste, sizeof(ste)))
193 return FALSE;
194 addr->seg = GlobalHandleToSel16(ste.hSeg);
196 return TRUE;
199 /***********************************************************************
200 * DEBUG_LoadModule16
202 * Load the entry points of a Win16 module into the hash table.
204 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
206 DBG_VALUE value;
207 BYTE buf[1 + 256 + 2];
208 char epname[512];
209 char* cpnt;
210 DBG_MODULE* wmod;
212 wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
214 value.type = NULL;
215 value.cookie = DV_TARGET;
216 value.addr.seg = 0;
217 value.addr.off = 0;
219 cpnt = moduleAddr + module->name_table;
221 /* First search the resident names */
223 /* skip module name */
224 if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
225 return;
226 cpnt += 1 + buf[0] + sizeof(WORD);
228 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
229 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
230 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
231 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
233 cpnt += buf[0] + 1 + sizeof(WORD);
236 /* Now search the non-resident names table */
237 if (!module->nrname_handle) return; /* No non-resident table */
238 cpnt = (char *)GlobalLock16(module->nrname_handle);
239 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
240 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
241 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
242 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
244 cpnt += buf[0] + 1 + sizeof(WORD);
246 GlobalUnlock16(module->nrname_handle);
248 #endif
250 /***********************************************************************
251 * DEBUG_LoadModule32
253 void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
255 DBG_VALUE value;
256 char buffer[512];
257 char bufstr[256];
258 int i;
259 IMAGE_NT_HEADERS pe_header;
260 DWORD pe_header_ofs;
261 IMAGE_SECTION_HEADER pe_seg;
262 DWORD pe_seg_ofs;
263 IMAGE_DATA_DIRECTORY dir;
264 DWORD dir_ofs;
265 DBG_MODULE* wmod;
266 const char *prefix;
268 /* FIXME: we make the assumption that hModule == base */
269 wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
271 DEBUG_Printf(DBG_CHN_TRACE, "Registring 32bit DLL '%s' at %08lx\n", name, base);
273 value.type = NULL;
274 value.cookie = DV_TARGET;
275 value.addr.seg = 0;
276 value.addr.off = 0;
278 /* grab PE Header */
279 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
280 &pe_header_ofs, sizeof(pe_header_ofs)) ||
281 !DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs),
282 &pe_header, sizeof(pe_header)))
283 return;
285 if (wmod) {
286 DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
287 DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
290 /* Add start of DLL */
291 value.addr.off = base;
292 if ((prefix = strrchr( name, '\\' ))) prefix++;
293 else prefix = name;
295 DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
297 /* Add entry point */
298 wsnprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
299 value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
300 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
302 /* Add start of sections */
303 pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
304 pe_header.FileHeader.SizeOfOptionalHeader;
306 for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
307 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
308 continue;
309 wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
310 value.addr.off = base + pe_seg.VirtualAddress;
311 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
314 /* Add exported functions */
315 dir_ofs = pe_header_ofs +
316 OFFSET_OF(IMAGE_NT_HEADERS,
317 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
318 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
319 IMAGE_EXPORT_DIRECTORY exports;
320 WORD* ordinals = NULL;
321 void** functions = NULL;
322 DWORD* names = NULL;
323 int j;
325 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress),
326 &exports, sizeof(exports)) &&
328 ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
329 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
330 functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
332 ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
333 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
334 ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
336 ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
337 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
338 names, sizeof(names[0]) * exports.NumberOfNames)) {
340 for (i = 0; i < exports.NumberOfNames; i++) {
341 if (!names[i] ||
342 !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
343 continue;
344 bufstr[sizeof(bufstr) - 1] = 0;
345 wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, bufstr);
346 value.addr.off = base + (DWORD)functions[ordinals[i]];
347 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
350 for (i = 0; i < exports.NumberOfFunctions; i++) {
351 if (!functions[i]) continue;
352 /* Check if we already added it with a name */
353 for (j = 0; j < exports.NumberOfNames; j++)
354 if ((ordinals[j] == i) && names[j]) break;
355 if (j < exports.NumberOfNames) continue;
356 wsnprintf(buffer, sizeof(buffer), "%s.%ld", prefix, i + exports.Base);
357 value.addr.off = base + (DWORD)functions[i];
358 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
361 DBG_free(functions);
362 DBG_free(ordinals);
363 DBG_free(names);
367 /***********************************************************************
368 * DEBUG_LoadEntryPoints
370 * Load the entry points of all the modules into the hash table.
372 int DEBUG_LoadEntryPoints(const char* pfx)
374 int first = 0;
375 /* FIXME: with address space separation in space, this is plain wrong
376 * it requires the 16 bit WOW debugging interface...
378 #if 0
379 MODULEENTRY entry;
380 NE_MODULE module;
381 void* moduleAddr;
382 int rowcount = 0;
383 int len;
385 /* FIXME: we assume that a module is never removed from memory */
386 /* FIXME: this is (currently plain wrong when debugger is started by
387 * attaching to an existing program => the 16 bit modules will
388 * not be shared... not much to do on debugger side... sigh
390 if (ModuleFirst16(&entry)) do {
391 if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
392 !(moduleAddr = NE_GetPtr(entry.hModule)) ||
393 !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
394 (module.flags & NE_FFLAGS_WIN32) /* NE module */)
395 continue;
396 if (!first) {
397 if (pfx) DEBUG_Printf(DBG_CHN_MESG, pfx);
398 DEBUG_Printf(DBG_CHN_MESG, " ");
399 rowcount = 3 + (pfx ? strlen(pfx) : 0);
400 first = 1;
403 len = strlen(entry.szModule);
404 if ((rowcount + len) > 76) {
405 DEBUG_Printf(DBG_CHN_MESG, "\n ");
406 rowcount = 3;
408 DEBUG_Printf(DBG_CHN_MESG, " %s", entry.szModule);
409 rowcount += len + 1;
411 DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
412 } while (ModuleNext16(&entry));
413 #endif
415 if (first) DEBUG_Printf(DBG_CHN_MESG, "\n");
416 return first;
419 /***********************************************************************
420 * DEBUG_InfoShare
422 * Display shared libarary information.
424 void DEBUG_InfoShare(void)
426 DBG_MODULE* wmod;
427 const char* xtype;
429 DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
431 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
432 switch (wmod->type) {
433 case DM_TYPE_NE: xtype = "NE"; break;
434 case DM_TYPE_PE: xtype = "PE"; break;
435 case DM_TYPE_ELF: xtype = "ELF"; break;
436 default: xtype = "???"; break;
438 DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
439 xtype, wmod->module_name);
443 static const char* DEBUG_GetModuleType(int type)
445 switch (type) {
446 case DM_TYPE_NE: return "NE";
447 case DM_TYPE_PE: return "PE";
448 case DM_TYPE_ELF: return "ELF";
449 default: return "???";;
453 static const char* DEBUG_GetModuleStatus(int status)
455 switch (status) {
456 case DM_STATUS_NEW: return "deferred";
457 case DM_STATUS_LOADED: return "ok";
458 case DM_STATUS_ERROR: return "error";
459 default: return "???";
463 /***********************************************************************
464 * DEBUG_
465 * Display information about a given module (DLL or EXE)
467 void DEBUG_DumpModule(DWORD mod)
469 DBG_MODULE* wmod;
471 if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
472 !(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
473 DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
474 return;
477 DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
478 wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
479 DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
482 /***********************************************************************
483 * DEBUG_WalkModules
485 * Display information about all modules (DLLs and EXEs)
487 void DEBUG_WalkModules(void)
489 DBG_MODULE* wmod;
490 const char* xtype;
492 DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
494 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
495 switch (wmod->type) {
496 case DM_TYPE_NE: xtype = "NE"; break;
497 case DM_TYPE_PE: xtype = "PE"; break;
498 case DM_TYPE_ELF: continue;
499 default: xtype = "???"; break;
502 DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n",
503 (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type),
504 wmod->module_name);