Misc fixes for QueryPathOfRegTypeLib, TLB_ReadTypeLib,
[wine.git] / debugger / module.c
blobee7c2d13120173d21199317c020e56ff5105dee6
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 "debugger.h"
13 #include "toolhelp.h"
14 #include "wingdi.h"
15 #include "winuser.h"
17 /***********************************************************************
18 * Creates and links a new module to the current process
21 DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
22 void* mod_addr, u_long size, HMODULE hmodule)
24 DBG_MODULE* wmod;
26 if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
27 return NULL;
29 memset(wmod, 0, sizeof(*wmod));
31 wmod->dil = DIL_DEFERRED;
32 wmod->main = (DEBUG_CurrProcess->num_modules == 0);
33 wmod->type = type;
34 wmod->load_addr = mod_addr;
35 wmod->size = size;
36 wmod->handle = hmodule;
37 wmod->dbg_index = DEBUG_CurrProcess->next_index;
38 wmod->module_name = DBG_strdup(name);
40 DEBUG_CurrProcess->modules = DBG_realloc(DEBUG_CurrProcess->modules,
41 ++DEBUG_CurrProcess->num_modules * sizeof(DBG_MODULE*));
42 DEBUG_CurrProcess->modules[DEBUG_CurrProcess->num_modules - 1] = wmod;
44 return wmod;
47 /***********************************************************************
48 * DEBUG_FindModuleByName
51 DBG_MODULE* DEBUG_FindModuleByName(const char* name, enum DbgModuleType type)
53 int i;
54 DBG_MODULE** amod = DEBUG_CurrProcess->modules;
56 for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
57 if ((type == DMT_UNKNOWN || type == amod[i]->type) &&
58 !strcasecmp(name, amod[i]->module_name))
59 return amod[i];
61 return NULL;
64 /***********************************************************************
65 * DEBUG_FindModuleByAddr
67 * either the addr where module is loaded, or any address inside the
68 * module
70 DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, enum DbgModuleType type)
72 int i;
73 DBG_MODULE** amod = DEBUG_CurrProcess->modules;
74 DBG_MODULE* res = NULL;
76 for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
77 if ((type == DMT_UNKNOWN || type == amod[i]->type) &&
78 (u_long)addr >= (u_long)amod[i]->load_addr &&
79 (!res || res->load_addr < amod[i]->load_addr))
80 res = amod[i];
82 return res;
85 /***********************************************************************
86 * DEBUG_FindModuleByHandle
88 DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, enum DbgModuleType type)
90 int i;
91 DBG_MODULE** amod = DEBUG_CurrProcess->modules;
93 for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
94 if ((type == DMT_UNKNOWN || type == amod[i]->type) &&
95 handle == amod[i]->handle)
96 return amod[i];
98 return NULL;
101 /***********************************************************************
102 * DEBUG_GetProcessMainModule
104 DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
106 if (!process || !process->num_modules) return NULL;
108 /* main module is the first to be loaded on a given process, so it's the first
109 * in the array */
110 assert(process->modules[0]->main);
111 return process->modules[0];
114 /***********************************************************************
115 * DEBUG_RegisterELFModule
117 * ELF modules are also entered into the list - this is so that we
118 * can make 'info shared' types of displays possible.
120 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, u_long size, const char* name)
122 DBG_MODULE* wmod = DEBUG_AddModule(name, DMT_ELF, (void*)load_addr, size, 0);
124 if (!wmod) return NULL;
126 DEBUG_CurrProcess->next_index++;
128 return wmod;
131 /***********************************************************************
132 * DEBUG_RegisterPEModule
135 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, u_long size, const char *module_name)
137 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DMT_PE, (void*)load_addr, size, hModule);
139 if (!wmod) return NULL;
141 DEBUG_CurrProcess->next_index++;
143 return wmod;
146 /***********************************************************************
147 * DEBUG_RegisterNEModule
150 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, u_long size, const char *module_name)
152 DBG_MODULE* wmod = DEBUG_AddModule(module_name, DMT_NE, load_addr, size, hModule);
154 if (!wmod) return NULL;
156 DEBUG_CurrProcess->next_index++;
157 return wmod;
160 #if 0
161 /***********************************************************************
162 * DEBUG_GetEP16
164 * Helper function fo DEBUG_LoadModuleEPs16:
165 * finds the address of a given entry point from a given module
167 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module,
168 WORD ordinal, DBG_ADDR* addr)
170 void* idx;
171 ET_ENTRY entry;
172 ET_BUNDLE bundle;
173 SEGTABLEENTRY ste;
175 bundle.next = module->entry_table;
176 do {
177 if (!bundle.next)
178 return FALSE;
179 idx = moduleAddr + bundle.next;
180 if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
181 return FALSE;
182 } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
184 if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) +
185 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY),
186 &entry, sizeof(ET_ENTRY)))
187 return FALSE;
189 addr->seg = entry.segnum;
190 addr->off = entry.offs;
192 if (addr->seg == 0xfe) addr->seg = 0xffff; /* constant entry */
193 else {
194 if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table +
195 sizeof(ste) * (addr->seg - 1),
196 &ste, sizeof(ste)))
197 return FALSE;
198 addr->seg = GlobalHandleToSel16(ste.hSeg);
200 return TRUE;
203 /***********************************************************************
204 * DEBUG_LoadModule16
206 * Load the entry points of a Win16 module into the hash table.
208 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
210 DBG_VALUE value;
211 BYTE buf[1 + 256 + 2];
212 char epname[512];
213 char* cpnt;
214 DBG_MODULE* wmod;
216 wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
218 value.type = NULL;
219 value.cookie = DV_TARGET;
220 value.addr.seg = 0;
221 value.addr.off = 0;
223 cpnt = moduleAddr + module->name_table;
225 /* First search the resident names */
227 /* skip module name */
228 if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
229 return;
230 cpnt += 1 + buf[0] + sizeof(WORD);
232 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
233 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
234 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
235 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
237 cpnt += buf[0] + 1 + sizeof(WORD);
240 /* Now search the non-resident names table */
241 if (!module->nrname_handle) return; /* No non-resident table */
242 cpnt = (char *)GlobalLock16(module->nrname_handle);
243 while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
244 sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
245 if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
246 DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
248 cpnt += buf[0] + 1 + sizeof(WORD);
250 GlobalUnlock16(module->nrname_handle);
252 #endif
254 /***********************************************************************
255 * DEBUG_LoadModule32
257 void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
259 IMAGE_NT_HEADERS pe_header;
260 DWORD nth_ofs;
261 DBG_MODULE* wmod = NULL;
262 int i;
263 IMAGE_SECTION_HEADER pe_seg;
264 DWORD pe_seg_ofs;
265 DWORD size = 0;
266 enum DbgInfoLoad dil = DIL_ERROR;
268 /* grab PE Header */
269 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
270 &nth_ofs, sizeof(nth_ofs)) ||
271 !DEBUG_READ_MEM_VERBOSE((void*)(base + nth_ofs), &pe_header, sizeof(pe_header)))
272 return;
274 pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
275 pe_header.FileHeader.SizeOfOptionalHeader;
277 for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
278 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
279 continue;
280 if (size < pe_seg.VirtualAddress + pe_seg.SizeOfRawData)
281 size = pe_seg.VirtualAddress + pe_seg.SizeOfRawData;
284 /* FIXME: we make the assumption that hModule == base */
285 wmod = DEBUG_RegisterPEModule((HMODULE)base, base, size, name);
286 if (wmod) {
287 dil = DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, nth_ofs);
288 if (dil != DIL_LOADED)
289 dil = DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, nth_ofs);
290 if (dil != DIL_LOADED)
291 dil = DEBUG_RegisterPEDebugInfo(wmod, hFile, &pe_header, nth_ofs);
294 if (wmod) wmod->dil = dil;
295 DEBUG_ReportDIL(dil, "32bit DLL", name, base);
298 /***********************************************************************
299 * DEBUG_RegisterPEDebugInfo
301 enum DbgInfoLoad DEBUG_RegisterPEDebugInfo(DBG_MODULE* wmod, HANDLE hFile,
302 void* _nth, unsigned long nth_ofs)
304 DBG_VALUE value;
305 char buffer[512];
306 char bufstr[256];
307 int i;
308 IMAGE_SECTION_HEADER pe_seg;
309 DWORD pe_seg_ofs;
310 IMAGE_DATA_DIRECTORY dir;
311 DWORD dir_ofs;
312 const char* prefix;
313 IMAGE_NT_HEADERS* nth = (PIMAGE_NT_HEADERS)_nth;
314 DWORD base = (u_long)wmod->load_addr;
316 value.type = NULL;
317 value.cookie = DV_TARGET;
318 value.addr.seg = 0;
319 value.addr.off = 0;
321 /* Add start of DLL */
322 value.addr.off = base;
323 if ((prefix = strrchr(wmod->module_name, '\\' ))) prefix++;
324 else prefix = wmod->module_name;
326 DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
328 /* Add entry point */
329 snprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
330 value.addr.off = base + nth->OptionalHeader.AddressOfEntryPoint;
331 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
333 /* Add start of sections */
334 pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
335 nth->FileHeader.SizeOfOptionalHeader;
337 for (i = 0; i < nth->FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
338 if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
339 continue;
340 snprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
341 value.addr.off = base + pe_seg.VirtualAddress;
342 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
345 /* Add exported functions */
346 dir_ofs = nth_ofs +
347 OFFSET_OF(IMAGE_NT_HEADERS,
348 OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
349 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
350 IMAGE_EXPORT_DIRECTORY exports;
351 WORD* ordinals = NULL;
352 void** functions = NULL;
353 DWORD* names = NULL;
354 int j;
356 if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress),
357 &exports, sizeof(exports)) &&
359 ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
360 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
361 functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
363 ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
364 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
365 ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
367 ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
368 DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
369 names, sizeof(names[0]) * exports.NumberOfNames)) {
371 for (i = 0; i < exports.NumberOfNames; i++) {
372 if (!names[i] ||
373 !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
374 continue;
375 bufstr[sizeof(bufstr) - 1] = 0;
376 snprintf(buffer, sizeof(buffer), "%s.%s", prefix, bufstr);
377 value.addr.off = base + (DWORD)functions[ordinals[i]];
378 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
381 for (i = 0; i < exports.NumberOfFunctions; i++) {
382 if (!functions[i]) continue;
383 /* Check if we already added it with a name */
384 for (j = 0; j < exports.NumberOfNames; j++)
385 if ((ordinals[j] == i) && names[j]) break;
386 if (j < exports.NumberOfNames) continue;
387 snprintf(buffer, sizeof(buffer), "%s.%ld", prefix, i + exports.Base);
388 value.addr.off = base + (DWORD)functions[i];
389 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
392 DBG_free(functions);
393 DBG_free(ordinals);
394 DBG_free(names);
396 /* no real debug info, only entry points */
397 return DIL_NOINFO;
400 /***********************************************************************
401 * DEBUG_LoadEntryPoints
403 * Load the entry points of all the modules into the hash table.
405 int DEBUG_LoadEntryPoints(const char* pfx)
407 int first = 0;
408 /* FIXME: with address space separation in space, this is plain wrong
409 * it requires the 16 bit WOW debugging interface...
411 #if 0
412 MODULEENTRY entry;
413 NE_MODULE module;
414 void* moduleAddr;
415 int rowcount = 0;
416 int len;
418 /* FIXME: we assume that a module is never removed from memory */
419 /* FIXME: this is (currently plain wrong when debugger is started by
420 * attaching to an existing program => the 16 bit modules will
421 * not be shared... not much to do on debugger side... sigh
423 if (ModuleFirst16(&entry)) do {
424 if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
425 !(moduleAddr = NE_GetPtr(entry.hModule)) ||
426 !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
427 (module.flags & NE_FFLAGS_WIN32) /* NE module */)
428 continue;
429 if (!first) {
430 if (pfx) DEBUG_Printf(DBG_CHN_MESG, pfx);
431 DEBUG_Printf(DBG_CHN_MESG, " ");
432 rowcount = 3 + (pfx ? strlen(pfx) : 0);
433 first = 1;
436 len = strlen(entry.szModule);
437 if ((rowcount + len) > 76) {
438 DEBUG_Printf(DBG_CHN_MESG, "\n ");
439 rowcount = 3;
441 DEBUG_Printf(DBG_CHN_MESG, " %s", entry.szModule);
442 rowcount += len + 1;
444 DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
445 } while (ModuleNext16(&entry));
446 #endif
448 if (first) DEBUG_Printf(DBG_CHN_MESG, "\n");
449 return first;
452 void DEBUG_ReportDIL(enum DbgInfoLoad dil, const char* pfx, const char* filename, DWORD load_addr)
454 const char* fmt;
456 switch (dil) {
457 case DIL_DEFERRED:
458 fmt = "Deferring debug information loading for %s '%s' (0x%08x)\n";
459 break;
460 case DIL_LOADED:
461 fmt = "Loaded debug information from %s '%s' (0x%08x)\n";
462 break;
463 case DIL_NOINFO:
464 fmt = "No debug information in %s '%s' (0x%08x)\n";
465 break;
466 case DIL_ERROR:
467 fmt = "Can't find file for %s '%s' (0x%08x)\n";
468 break;
469 default:
470 DEBUG_Printf(DBG_CHN_ERR, "Oooocch (%d)\n", dil);
471 return;
474 DEBUG_Printf(DBG_CHN_MESG, fmt, pfx, filename, load_addr);
477 static const char* DEBUG_GetModuleType(enum DbgModuleType type)
479 switch (type) {
480 case DMT_NE: return "NE";
481 case DMT_PE: return "PE";
482 case DMT_ELF: return "ELF";
483 default: return "???";;
487 static const char* DEBUG_GetDbgInfo(enum DbgInfoLoad dil)
489 switch (dil) {
490 case DIL_LOADED: return "loaded";
491 case DIL_DEFERRED: return "deferred";
492 case DIL_NOINFO: return "none";
493 case DIL_ERROR: return "error";
494 default: return "?";
498 /***********************************************************************
499 * DEBUG_ModuleCompare
501 * returns -1 is p1 < p2, 0 is p1 == p2, +1 if p1 > p2
502 * order used is order on load_addr of a module
504 static int DEBUG_ModuleCompare(const void* p1, const void* p2)
506 return (*((const DBG_MODULE**)p1))->load_addr -
507 (*((const DBG_MODULE**)p2))->load_addr;
510 /***********************************************************************
511 * DEBUG_IsContainer
513 * returns TRUE is wmod_child is contained (inside bounds) of wmod_cntnr
515 static BOOL inline DEBUG_IsContainer(const DBG_MODULE* wmod_cntnr,
516 const DBG_MODULE* wmod_child)
518 return wmod_cntnr->load_addr < wmod_child->load_addr &&
519 (DWORD)wmod_cntnr->load_addr + wmod_cntnr->size >
520 (DWORD)wmod_child->load_addr + wmod_child->size;
523 static void DEBUG_InfoShareModule(const DBG_MODULE* module, int ident)
525 if (ident) DEBUG_Printf(DBG_CHN_MESG, " \\-");
526 DEBUG_Printf(DBG_CHN_MESG, "%s\t0x%08lx-%08lx\t%s\n",
527 DEBUG_GetModuleType(module->type),
528 (DWORD)module->load_addr, (DWORD)module->load_addr + module->size,
529 module->module_name);
532 /***********************************************************************
533 * DEBUG_InfoShare
535 * Display shared libarary information.
537 void DEBUG_InfoShare(void)
539 DBG_MODULE** ref;
540 int i, j;
542 ref = DBG_alloc(sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
543 if (!ref) return;
545 DEBUG_Printf(DBG_CHN_MESG, "Module\tAddress\t\t\tName\t%d modules\n",
546 DEBUG_CurrProcess->num_modules);
548 memcpy(ref, DEBUG_CurrProcess->modules,
549 sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
550 qsort(ref, DEBUG_CurrProcess->num_modules, sizeof(DBG_MODULE*),
551 DEBUG_ModuleCompare);
552 for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
553 switch (ref[i]->type) {
554 case DMT_ELF:
555 DEBUG_InfoShareModule(ref[i], 0);
556 for (j = 0; j < DEBUG_CurrProcess->num_modules; j++) {
557 if (ref[j]->type != DMT_ELF && DEBUG_IsContainer(ref[i], ref[j]))
558 DEBUG_InfoShareModule(ref[j], 1);
560 break;
561 case DMT_NE:
562 case DMT_PE:
563 /* check module is not in ELF */
564 for (j = 0; j < DEBUG_CurrProcess->num_modules; j++) {
565 if (ref[j]->type == DMT_ELF &&
566 DEBUG_IsContainer(ref[j], ref[i]))
567 break;
569 if (j >= DEBUG_CurrProcess->num_modules)
570 DEBUG_InfoShareModule(ref[i], 0);
571 break;
572 default:
573 DEBUG_Printf(DBG_CHN_ERR, "Unknown type (%d)\n", ref[i]->type);
576 DBG_free(ref);
579 /***********************************************************************
580 * DEBUG_DumpModule
581 * Display information about a given module (DLL or EXE)
583 void DEBUG_DumpModule(DWORD mod)
585 DBG_MODULE* wmod;
587 if (!(wmod = DEBUG_FindModuleByHandle(mod, DMT_UNKNOWN)) &&
588 !(wmod = DEBUG_FindModuleByAddr((void*)mod, DMT_UNKNOWN))) {
589 DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
590 return;
593 DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) 0x%08lx-0x%08lx (%s, debug info %s)\n",
594 wmod->module_name, wmod->handle, (DWORD)wmod->load_addr,
595 (DWORD)wmod->load_addr + wmod->size,
596 DEBUG_GetModuleType(wmod->type), DEBUG_GetDbgInfo(wmod->dil));
599 /***********************************************************************
600 * DEBUG_WalkModules
602 * Display information about all modules (DLLs and EXEs)
604 void DEBUG_WalkModules(void)
606 DBG_MODULE** amod;
607 int i;
609 DEBUG_Printf(DBG_CHN_MESG, "Address\t\t\tModule\tName\n");
611 amod = DBG_alloc(sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
612 if (!amod) return;
614 memcpy(amod, DEBUG_CurrProcess->modules,
615 sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
616 qsort(amod, DEBUG_CurrProcess->num_modules, sizeof(DBG_MODULE*),
617 DEBUG_ModuleCompare);
618 for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
619 if (amod[i]->type == DMT_ELF) continue;
621 DEBUG_Printf(DBG_CHN_MESG, "0x%08lx-%08lx\t(%s)\t%s\n",
622 (DWORD)amod[i]->load_addr,
623 (DWORD)amod[i]->load_addr + amod[i]->size,
624 DEBUG_GetModuleType(amod[i]->type), amod[i]->module_name);
626 DBG_free(amod);