1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * File module.c - module handling for the wine debugger
5 * Copyright (C) 1993, Eric Youngdale.
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)
28 if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
31 memset(wmod, 0, sizeof(*wmod));
33 wmod->next = DEBUG_CurrProcess->modules;
34 wmod->status = DM_STATUS_NEW;
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;
45 /***********************************************************************
46 * DEBUG_FindModuleByName
49 DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type)
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;
60 /***********************************************************************
61 * DEBUG_FindModuleByAddr
63 * either the addr where module is loaded, or any address inside the
66 DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, int type)
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))
80 /***********************************************************************
81 * DEBUG_FindModuleByHandle
83 DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
87 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
88 if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
93 /***********************************************************************
94 * DEBUG_RegisterELFModule
96 * ELF modules are also entered into the list - this is so that we
97 * can make 'info shared' types of displays possible.
99 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
101 DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
103 if (!wmod) return NULL;
105 wmod->status = DM_STATUS_LOADED;
106 DEBUG_CurrProcess->next_index++;
111 /***********************************************************************
112 * DEBUG_RegisterPEModule
115 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
117 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
119 if (!wmod) return NULL;
121 DEBUG_CurrProcess->next_index++;
126 /***********************************************************************
127 * DEBUG_RegisterNEModule
130 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
132 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
134 if (!wmod) return NULL;
136 wmod->status = DM_STATUS_LOADED;
137 DEBUG_CurrProcess->next_index++;
141 /***********************************************************************
144 * Helper function fo DEBUG_LoadModuleEPs16:
145 * finds the address of a given entry point from a given module
147 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module,
148 WORD ordinal, DBG_ADDR* addr)
155 bundle.next = module->entry_table;
159 idx = moduleAddr + bundle.next;
160 if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
162 } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
164 if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) +
165 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY),
166 &entry, sizeof(ET_ENTRY)))
169 addr->seg = entry.segnum;
170 addr->off = entry.offs;
172 if (addr->seg == 0xfe) addr->seg = 0xffff; /* constant entry */
174 if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table +
175 sizeof(ste) * (addr->seg - 1),
178 addr->seg = GlobalHandleToSel16(ste.hSeg);
183 /***********************************************************************
186 * Load the entry points of a Win16 module into the hash table.
188 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
191 BYTE buf[1 + 256 + 2];
196 wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
199 value.cookie = DV_TARGET;
203 cpnt = moduleAddr + module->name_table;
205 /* First search the resident names */
207 /* skip module name */
208 if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
210 cpnt += 1 + buf[0] + sizeof(WORD);
212 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
213 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
214 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
215 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
217 cpnt += buf[0] + 1 + sizeof(WORD);
220 /* Now search the non-resident names table */
221 if (!module->nrname_handle) return; /* No non-resident table */
222 cpnt = (char *)GlobalLock16(module->nrname_handle);
223 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
224 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
225 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
226 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
228 cpnt += buf[0] + 1 + sizeof(WORD);
230 GlobalUnlock16(module->nrname_handle);
233 /***********************************************************************
236 void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
242 IMAGE_NT_HEADERS pe_header;
244 IMAGE_SECTION_HEADER pe_seg;
246 IMAGE_DATA_DIRECTORY dir;
250 /* FIXME: we make the assumption that hModule == base */
251 wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
253 DEBUG_Printf(DBG_CHN_TRACE, "Registring 32bit DLL '%s' at %08lx\n", name, base);
256 value.cookie = DV_TARGET;
261 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
262 &pe_header_ofs, sizeof(pe_header_ofs)) ||
263 !DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs),
264 &pe_header, sizeof(pe_header)))
268 DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
269 DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
272 /* Add start of DLL */
273 value.addr.off = base;
274 DEBUG_AddSymbol(name, &value, NULL, SYM_WIN32 | SYM_FUNC);
276 /* Add entry point */
277 sprintf(buffer, "%s.EntryPoint", name);
278 value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
279 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
281 /* Add start of sections */
282 pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
283 pe_header.FileHeader.SizeOfOptionalHeader;
285 for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
286 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
288 sprintf(buffer, "%s.%s", name, pe_seg.Name);
289 value.addr.off = base + pe_seg.VirtualAddress;
290 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
293 /* Add exported functions */
294 dir_ofs = pe_header_ofs +
295 OFFSET_OF(IMAGE_NT_HEADERS,
296 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
297 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
298 IMAGE_EXPORT_DIRECTORY exports;
299 WORD* ordinals = NULL;
300 void** functions = NULL;
304 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress),
305 &exports, sizeof(exports)) &&
307 ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
308 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
309 functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
311 ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
312 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
313 ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
315 ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
316 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
317 names, sizeof(names[0]) * exports.NumberOfNames)) {
319 for (i = 0; i < exports.NumberOfNames; i++) {
321 !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
323 bufstr[sizeof(bufstr) - 1] = 0;
324 sprintf(buffer, "%s.%s", name, bufstr);
325 value.addr.off = base + (DWORD)functions[ordinals[i]];
326 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
329 for (i = 0; i < exports.NumberOfFunctions; i++) {
330 if (!functions[i]) continue;
331 /* Check if we already added it with a name */
332 for (j = 0; j < exports.NumberOfNames; j++)
333 if ((ordinals[j] == i) && names[j]) break;
334 if (j < exports.NumberOfNames) continue;
335 sprintf(buffer, "%s.%ld", name, i + exports.Base);
336 value.addr.off = base + (DWORD)functions[i];
337 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
346 /***********************************************************************
347 * DEBUG_LoadEntryPoints
349 * Load the entry points of all the modules into the hash table.
351 int DEBUG_LoadEntryPoints(const char* pfx)
360 /* FIXME: we assume that a module is never removed from memory */
361 /* FIXME: this is (currently plain wrong when debugger is started by
362 * attaching to an existing program => the 16 bit modules will
363 * not be shared... not much to do on debugger side... sigh
365 if (ModuleFirst16(&entry)) do {
366 if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
367 !(moduleAddr = NE_GetPtr(entry.hModule)) ||
368 !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
369 (module.flags & NE_FFLAGS_WIN32) /* NE module */)
372 if (pfx) DEBUG_Printf(DBG_CHN_MESG, pfx);
373 DEBUG_Printf(DBG_CHN_MESG, " ");
374 rowcount = 3 + (pfx ? strlen(pfx) : 0);
378 len = strlen(entry.szModule);
379 if ((rowcount + len) > 76) {
380 DEBUG_Printf(DBG_CHN_MESG, "\n ");
383 DEBUG_Printf(DBG_CHN_MESG, " %s", entry.szModule);
386 DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
387 } while (ModuleNext16(&entry));
389 if (first) DEBUG_Printf(DBG_CHN_MESG, "\n");
393 /***********************************************************************
396 * Display shared libarary information.
398 void DEBUG_InfoShare(void)
403 DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
405 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
406 switch (wmod->type) {
407 case DM_TYPE_NE: xtype = "NE"; break;
408 case DM_TYPE_PE: xtype = "PE"; break;
409 case DM_TYPE_ELF: xtype = "ELF"; break;
410 default: xtype = "???"; break;
412 DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
413 xtype, wmod->module_name);
417 static const char* DEBUG_GetModuleType(int type)
420 case DM_TYPE_NE: return "NE";
421 case DM_TYPE_PE: return "PE";
422 case DM_TYPE_ELF: return "ELF";
423 default: return "???";;
427 static const char* DEBUG_GetModuleStatus(int status)
430 case DM_STATUS_NEW: return "deferred";
431 case DM_STATUS_LOADED: return "ok";
432 case DM_STATUS_ERROR: return "error";
433 default: return "???";
437 /***********************************************************************
439 * Display information about a given module (DLL or EXE)
441 void DEBUG_DumpModule(DWORD mod)
445 if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
446 !(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
447 DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
451 DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
452 wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
453 DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
456 /***********************************************************************
459 * Display information about all modules (DLLs and EXEs)
461 void DEBUG_WalkModules(void)
466 DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
468 for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
469 switch (wmod->type) {
470 case DM_TYPE_NE: xtype = "NE"; break;
471 case DM_TYPE_PE: xtype = "PE"; break;
472 case DM_TYPE_ELF: continue;
473 default: xtype = "???"; break;
476 DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n",
477 (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type),