Create directories that don't contain a Makefile.
[wine/multimedia.git] / debugger / module.c
blobf73dfb294a1eeef3c26ccf21d73042f0dca12096
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 "peexe.h"
14 #include "module.h"
15 #include "debugger.h"
16 #include "toolhelp.h"
18 /***********************************************************************
19 * Creates and links a new module to the current process
22 DBG_MODULE* DEBUG_AddModule(const char* name, int type,
23 void* mod_addr, HMODULE hmodule)
25 DBG_MODULE* wmod;
27 if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
28 return NULL;
30 memset(wmod, 0, sizeof(*wmod));
32 wmod->next = DEBUG_CurrProcess->modules;
33 wmod->status = DM_STATUS_NEW;
34 wmod->type = type;
35 wmod->load_addr = mod_addr;
36 wmod->handle = hmodule;
37 wmod->dbg_index = DEBUG_CurrProcess->next_index;
38 wmod->module_name = DBG_strdup(name);
39 DEBUG_CurrProcess->modules = wmod;
41 return wmod;
44 /***********************************************************************
45 * DEBUG_FindModuleByName
48 DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type)
50 DBG_MODULE* wmod;
52 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
53 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
54 !strcasecmp(name, wmod->module_name)) break;
56 return wmod;
59 /***********************************************************************
60 * DEBUG_FindModuleByAddr
62 * either the addr where module is loaded, or any address inside the
63 * module
65 DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, int type)
67 DBG_MODULE* wmod;
68 DBG_MODULE* res = NULL;
70 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
71 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
72 (u_long)addr >= (u_long)wmod->load_addr &&
73 (!res || res->load_addr < wmod->load_addr))
74 res = wmod;
76 return res;
79 /***********************************************************************
80 * DEBUG_FindModuleByHandle
82 DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
84 DBG_MODULE* wmod;
86 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
87 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
89 return wmod;
92 /***********************************************************************
93 * DEBUG_RegisterELFModule
95 * ELF modules are also entered into the list - this is so that we
96 * can make 'info shared' types of displays possible.
98 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
100 DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
102 if (!wmod) return NULL;
104 wmod->status = DM_STATUS_LOADED;
105 DEBUG_CurrProcess->next_index++;
107 return wmod;
110 /***********************************************************************
111 * DEBUG_RegisterPEModule
114 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
116 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
118 if (!wmod) return NULL;
120 DEBUG_CurrProcess->next_index++;
122 return wmod;
125 /***********************************************************************
126 * DEBUG_RegisterNEModule
129 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
131 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
133 if (!wmod) return NULL;
135 wmod->status = DM_STATUS_LOADED;
136 DEBUG_CurrProcess->next_index++;
137 return wmod;
140 /***********************************************************************
141 * DEBUG_GetEP16
143 * Helper function fo DEBUG_LoadModuleEPs16:
144 * finds the address of a given entry point from a given module
146 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module,
147 WORD ordinal, DBG_ADDR* addr)
149 void* idx;
150 ET_ENTRY entry;
151 ET_BUNDLE bundle;
152 SEGTABLEENTRY ste;
154 bundle.next = module->entry_table;
155 do {
156 if (!bundle.next)
157 return FALSE;
158 idx = moduleAddr + bundle.next;
159 if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
160 return FALSE;
161 } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
163 if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) +
164 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY),
165 &entry, sizeof(ET_ENTRY)))
166 return FALSE;
168 addr->seg = entry.segnum;
169 addr->off = entry.offs;
171 if (addr->seg == 0xfe) addr->seg = 0xffff; /* constant entry */
172 else {
173 if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table +
174 sizeof(ste) * (addr->seg - 1),
175 &ste, sizeof(ste)))
176 return FALSE;
177 addr->seg = GlobalHandleToSel16(ste.hSeg);
179 return TRUE;
182 /***********************************************************************
183 * DEBUG_LoadModule16
185 * Load the entry points of a Win16 module into the hash table.
187 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
189 DBG_VALUE value;
190 BYTE buf[1 + 256 + 2];
191 char epname[512];
192 char* cpnt;
193 DBG_MODULE* wmod;
195 wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
197 value.type = NULL;
198 value.cookie = DV_TARGET;
199 value.addr.seg = 0;
200 value.addr.off = 0;
202 cpnt = moduleAddr + module->name_table;
204 /* First search the resident names */
206 /* skip module name */
207 if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
208 return;
209 cpnt += 1 + buf[0] + sizeof(WORD);
211 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
212 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
213 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
214 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
216 cpnt += buf[0] + 1 + sizeof(WORD);
219 /* Now search the non-resident names table */
220 if (!module->nrname_handle) return; /* No non-resident table */
221 cpnt = (char *)GlobalLock16(module->nrname_handle);
222 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
223 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
224 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
225 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
227 cpnt += buf[0] + 1 + sizeof(WORD);
229 GlobalUnlock16(module->nrname_handle);
232 /***********************************************************************
233 * DEBUG_LoadModule32
235 void DEBUG_LoadModule32(const char* name, DWORD base)
237 DBG_VALUE value;
238 char buffer[256];
239 char bufstr[256];
240 int i;
241 IMAGE_NT_HEADERS pe_header;
242 DWORD pe_header_ofs;
243 IMAGE_SECTION_HEADER pe_seg;
244 DWORD pe_seg_ofs;
245 IMAGE_DATA_DIRECTORY dir;
246 DWORD dir_ofs;
247 DBG_MODULE* wmod;
249 /* FIXME: we make the assumption that hModule == base */
250 wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
252 fprintf(stderr, "Registring 32bit DLL '%s' at %08lx\n", name, base);
254 value.type = NULL;
255 value.cookie = DV_TARGET;
256 value.addr.seg = 0;
257 value.addr.off = 0;
259 /* grab PE Header */
260 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
261 &pe_header_ofs, sizeof(pe_header_ofs)) ||
262 !DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs),
263 &pe_header, sizeof(pe_header)))
264 return;
266 if (wmod) {
267 DEBUG_RegisterMSCDebugInfo(wmod, &pe_header, pe_header_ofs);
268 DEBUG_RegisterStabsDebugInfo(wmod, &pe_header, pe_header_ofs);
271 /* Add start of DLL */
272 value.addr.off = base;
273 DEBUG_AddSymbol(name, &value, NULL, SYM_WIN32 | SYM_FUNC);
275 /* Add entry point */
276 sprintf(buffer, "%s.EntryPoint", name);
277 value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
278 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
280 /* Add start of sections */
281 pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
282 pe_header.FileHeader.SizeOfOptionalHeader;
284 for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
285 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)) ||
286 !DEBUG_READ_MEM_VERBOSE((void*)pe_seg.Name, bufstr, sizeof(bufstr)))
287 continue;
288 bufstr[sizeof(bufstr) - 1] = 0;
289 sprintf(buffer, "%s.%s", name, bufstr);
290 value.addr.off = base + pe_seg.VirtualAddress;
291 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
294 /* Add exported functions */
295 dir_ofs = pe_header_ofs +
296 OFFSET_OF(IMAGE_NT_HEADERS,
297 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
298 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
299 IMAGE_EXPORT_DIRECTORY exports;
300 WORD* ordinals = NULL;
301 void** functions = NULL;
302 DWORD* names = NULL;
303 int j;
305 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress),
306 &exports, sizeof(exports)) &&
308 ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
309 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
310 functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
312 ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
313 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
314 ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
316 ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
317 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
318 names, sizeof(names[0]) * exports.NumberOfNames)) {
320 for (i = 0; i < exports.NumberOfNames; i++) {
321 if (!names[i] ||
322 !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
323 continue;
324 bufstr[sizeof(bufstr) - 1] = 0;
325 sprintf(buffer, "%s.%s", name, bufstr);
326 value.addr.off = base + (DWORD)functions[ordinals[i]];
327 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
330 for (i = 0; i < exports.NumberOfFunctions; i++) {
331 if (!functions[i]) continue;
332 /* Check if we already added it with a name */
333 for (j = 0; j < exports.NumberOfNames; j++)
334 if ((ordinals[j] == i) && names[j]) break;
335 if (j < exports.NumberOfNames) continue;
336 sprintf(buffer, "%s.%ld", name, i + exports.Base);
337 value.addr.off = base + (DWORD)functions[i];
338 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
341 DBG_free(functions);
342 DBG_free(ordinals);
343 DBG_free(names);
347 /***********************************************************************
348 * DEBUG_LoadEntryPoints
350 * Load the entry points of all the modules into the hash table.
352 int DEBUG_LoadEntryPoints(const char* pfx)
354 MODULEENTRY entry;
355 NE_MODULE module;
356 void* moduleAddr;
357 int first = 0;
358 int rowcount = 0;
359 int len;
361 /* FIXME: we assume that a module is never removed from memory */
362 if (ModuleFirst16(&entry)) do {
363 if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
364 !(moduleAddr = NE_GetPtr(entry.hModule)) ||
365 !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
366 (module.flags & NE_FFLAGS_WIN32) /* NE module */)
367 continue;
368 if (!first) {
369 if (pfx) fprintf(stderr, pfx);
370 fprintf(stderr, " ");
371 rowcount = 3 + (pfx ? strlen(pfx) : 0);
372 first = 1;
375 len = strlen(entry.szModule);
376 if ((rowcount + len) > 76) {
377 fprintf(stderr, "\n ");
378 rowcount = 3;
380 fprintf(stderr, " %s", entry.szModule);
381 rowcount += len + 1;
383 DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
384 } while (ModuleNext16(&entry));
386 if (first) fprintf(stderr, "\n");
387 return first;
390 /***********************************************************************
391 * DEBUG_ProcessDeferredDebug
394 int DEBUG_ProcessDeferredDebug(void)
396 DBG_MODULE* wmod;
397 int sts;
398 int last_proc = -1;
399 int need_print = 0;
400 int rowcount = 0;
401 int len;
403 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
404 if (wmod->status != DM_STATUS_NEW) continue;
406 if (last_proc != wmod->dbg_index) {
407 if (!need_print) {
408 fprintf(stderr, "DeferredDebug for:");
409 rowcount = 18;
410 need_print = 1;
412 if (rowcount + (len = strlen(wmod->module_name)) > 76) {
413 rowcount = 0;
414 fprintf(stderr, "\n");
415 } else {
416 fprintf(stderr, " ");
417 rowcount++;
419 rowcount += len;
420 fprintf(stderr, wmod->module_name);
421 last_proc = wmod->dbg_index;
424 sts = (wmod->extra_info) ? DEBUG_ProcessMSCDebugInfo(wmod) : TRUE;
425 wmod->status = (sts) ? DM_STATUS_LOADED : DM_STATUS_ERROR;
427 if (need_print) fprintf(stderr, "\n");
428 return TRUE;
431 /***********************************************************************
432 * DEBUG_InfoShare
434 * Display shared libarary information.
436 void DEBUG_InfoShare(void)
438 DBG_MODULE* wmod;
439 const char* xtype;
441 fprintf(stderr, "Address\t\tModule\tName\n");
443 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
444 switch (wmod->type) {
445 case DM_TYPE_NE: xtype = "NE"; break;
446 case DM_TYPE_PE: xtype = "PE"; break;
447 case DM_TYPE_ELF: xtype = "ELF"; break;
448 default: xtype = "???"; break;
450 fprintf(stderr, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
451 xtype, wmod->module_name);
455 static const char* DEBUG_GetModuleType(int type)
457 switch (type) {
458 case DM_TYPE_NE: return "NE";
459 case DM_TYPE_PE: return "PE";
460 case DM_TYPE_ELF: return "ELF";
461 default: return "???";;
465 static const char* DEBUG_GetModuleStatus(int status)
467 switch (status) {
468 case DM_STATUS_NEW: return "deferred";
469 case DM_STATUS_LOADED: return "ok";
470 case DM_STATUS_ERROR: return "error";
471 default: return "???";
475 /***********************************************************************
476 * DEBUG_
477 * Display information about a given module (DLL or EXE)
479 void DEBUG_DumpModule(DWORD mod)
481 DBG_MODULE* wmod;
483 if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
484 !(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
485 fprintf(stderr, "'0x%08lx' is not a valid module handle or address\n", mod);
486 return;
489 fprintf(stderr, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
490 wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
491 DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
494 /***********************************************************************
495 * DEBUG_WalkModules
497 * Display information about all modules (DLLs and EXEs)
499 void DEBUG_WalkModules(void)
501 DBG_MODULE* wmod;
502 const char* xtype;
504 fprintf(stderr, "Address\t\tModule\tName\n");
506 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
507 switch (wmod->type) {
508 case DM_TYPE_NE: xtype = "NE"; break;
509 case DM_TYPE_PE: xtype = "PE"; break;
510 case DM_TYPE_ELF: continue;
511 default: xtype = "???"; break;
514 fprintf(stderr, "0x%8.8x\t(%s)\t%s\n",
515 (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type),
516 wmod->module_name);