1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * File module.c - module handling for the wine debugger
5 * Copyright (C) 1993, Eric Youngdale.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 /***********************************************************************
31 * Creates and links a new module to the current process
34 static DBG_MODULE
* DEBUG_AddModule(const char* name
, enum DbgModuleType type
,
35 void* mod_addr
, unsigned long size
, HMODULE hmodule
)
39 if (!(wmod
= (DBG_MODULE
*)DBG_alloc(sizeof(*wmod
))))
42 memset(wmod
, 0, sizeof(*wmod
));
44 wmod
->dil
= DIL_DEFERRED
;
45 wmod
->main
= (DEBUG_CurrProcess
->num_modules
== 0);
47 wmod
->load_addr
= mod_addr
;
49 wmod
->handle
= hmodule
;
50 wmod
->dbg_index
= DEBUG_CurrProcess
->next_index
;
51 wmod
->module_name
= DBG_strdup(name
);
53 DEBUG_CurrProcess
->modules
= DBG_realloc(DEBUG_CurrProcess
->modules
,
54 ++DEBUG_CurrProcess
->num_modules
* sizeof(DBG_MODULE
*));
55 DEBUG_CurrProcess
->modules
[DEBUG_CurrProcess
->num_modules
- 1] = wmod
;
60 /***********************************************************************
61 * DEBUG_FindModuleByName
64 DBG_MODULE
* DEBUG_FindModuleByName(const char* name
, enum DbgModuleType type
)
67 DBG_MODULE
** amod
= DEBUG_CurrProcess
->modules
;
69 for (i
= 0; i
< DEBUG_CurrProcess
->num_modules
; i
++) {
70 if ((type
== DMT_UNKNOWN
|| type
== amod
[i
]->type
) &&
71 !strcasecmp(name
, amod
[i
]->module_name
))
77 /***********************************************************************
78 * DEBUG_FindModuleByAddr
80 * either the addr where module is loaded, or any address inside the
83 DBG_MODULE
* DEBUG_FindModuleByAddr(void* addr
, enum DbgModuleType type
)
86 DBG_MODULE
** amod
= DEBUG_CurrProcess
->modules
;
87 DBG_MODULE
* res
= NULL
;
89 for (i
= 0; i
< DEBUG_CurrProcess
->num_modules
; i
++) {
90 if ((type
== DMT_UNKNOWN
|| type
== amod
[i
]->type
) &&
91 (char *)addr
>= (char *)amod
[i
]->load_addr
&&
92 (char *)addr
< (char *)amod
[i
]->load_addr
+ amod
[i
]->size
) {
93 /* amod[i] contains it... check against res now */
94 if (!res
|| res
->load_addr
< amod
[i
]->load_addr
)
101 /***********************************************************************
102 * DEBUG_FindModuleByHandle
104 DBG_MODULE
* DEBUG_FindModuleByHandle(HANDLE handle
, enum DbgModuleType type
)
107 DBG_MODULE
** amod
= DEBUG_CurrProcess
->modules
;
109 for (i
= 0; i
< DEBUG_CurrProcess
->num_modules
; i
++) {
110 if ((type
== DMT_UNKNOWN
|| type
== amod
[i
]->type
) &&
111 handle
== amod
[i
]->handle
)
117 /***********************************************************************
118 * DEBUG_GetProcessMainModule
120 DBG_MODULE
* DEBUG_GetProcessMainModule(DBG_PROCESS
* process
)
122 if (!process
|| !process
->num_modules
) return NULL
;
124 /* main module is the first to be loaded on a given process, so it's the first
126 assert(process
->modules
[0]->main
);
127 return process
->modules
[0];
130 /***********************************************************************
131 * DEBUG_RegisterELFModule
133 * ELF modules are also entered into the list - this is so that we
134 * can make 'info shared' types of displays possible.
136 DBG_MODULE
* DEBUG_RegisterELFModule(void *load_addr
, unsigned long size
, const char* name
)
138 DBG_MODULE
* wmod
= DEBUG_AddModule(name
, DMT_ELF
, load_addr
, size
, 0);
140 if (!wmod
) return NULL
;
142 DEBUG_CurrProcess
->next_index
++;
147 /***********************************************************************
148 * DEBUG_RegisterPEModule
151 static DBG_MODULE
* DEBUG_RegisterPEModule(HMODULE hModule
, void *load_addr
,
152 unsigned long size
, const char *module_name
)
154 DBG_MODULE
* wmod
= DEBUG_AddModule(module_name
, DMT_PE
, load_addr
, size
, hModule
);
156 if (!wmod
) return NULL
;
158 DEBUG_CurrProcess
->next_index
++;
164 /***********************************************************************
165 * DEBUG_RegisterNEModule
168 static DBG_MODULE
* DEBUG_RegisterNEModule(HMODULE hModule
, void* load_addr
,
169 unsigned long size
, const char *module_name
)
171 DBG_MODULE
* wmod
= DEBUG_AddModule(module_name
, DMT_NE
, load_addr
, size
, hModule
);
173 if (!wmod
) return NULL
;
175 DEBUG_CurrProcess
->next_index
++;
179 /***********************************************************************
182 * Helper function fo DEBUG_LoadModuleEPs16:
183 * finds the address of a given entry point from a given module
185 static BOOL
DEBUG_GetEP16(char* moduleAddr
, const NE_MODULE
* module
,
186 WORD ordinal
, DBG_ADDR
* addr
)
193 bundle
.next
= module
->entry_table
;
197 idx
= moduleAddr
+ bundle
.next
;
198 if (!DEBUG_READ_MEM_VERBOSE(idx
, &bundle
, sizeof(bundle
)))
200 } while ((ordinal
< bundle
.first
+ 1) || (ordinal
> bundle
.last
));
202 if (!DEBUG_READ_MEM_VERBOSE((char*)idx
+ sizeof(ET_BUNDLE
) +
203 (ordinal
- bundle
.first
- 1) * sizeof(ET_ENTRY
),
204 &entry
, sizeof(ET_ENTRY
)))
207 addr
->seg
= entry
.segnum
;
208 addr
->off
= entry
.offs
;
210 if (addr
->seg
== 0xfe) addr
->seg
= 0xffff; /* constant entry */
212 if (!DEBUG_READ_MEM_VERBOSE(moduleAddr
+ module
->seg_table
+
213 sizeof(ste
) * (addr
->seg
- 1),
216 addr
->seg
= GlobalHandleToSel16(ste
.hSeg
);
221 /***********************************************************************
224 * Load the entry points of a Win16 module into the hash table.
226 static void DEBUG_LoadModule16(HMODULE hModule
, NE_MODULE
* module
, char* moduleAddr
, const char* name
)
229 BYTE buf
[1 + 256 + 2];
234 wmod
= DEBUG_RegisterNEModule(hModule
, moduleAddr
, name
);
237 value
.cookie
= DV_TARGET
;
241 cpnt
= moduleAddr
+ module
->name_table
;
243 /* First search the resident names */
245 /* skip module name */
246 if (!DEBUG_READ_MEM_VERBOSE(cpnt
, buf
, sizeof(buf
)) || !buf
[0])
248 cpnt
+= 1 + buf
[0] + sizeof(WORD
);
250 while (DEBUG_READ_MEM_VERBOSE(cpnt
, buf
, sizeof(buf
)) && buf
[0]) {
251 snprintf(epname
, sizeof(epname
), "%s.%.*s", name
, buf
[0], &buf
[1]);
252 if (DEBUG_GetEP16(moduleAddr
, module
, *(WORD
*)&buf
[1 + buf
[0]], &value
.addr
)) {
253 DEBUG_AddSymbol(epname
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
255 cpnt
+= buf
[0] + 1 + sizeof(WORD
);
258 /* Now search the non-resident names table */
259 if (!module
->nrname_handle
) return; /* No non-resident table */
260 cpnt
= (char *)GlobalLock16(module
->nrname_handle
);
261 while (DEBUG_READ_MEM_VERBOSE(cpnt
, buf
, sizeof(buf
)) && buf
[0]) {
262 snprintf(epname
, sizeof(epname
), "%s.%.*s", name
, buf
[0], &buf
[1]);
263 if (DEBUG_GetEP16(moduleAddr
, module
, *(WORD
*)&buf
[1 + buf
[0]], &value
.addr
)) {
264 DEBUG_AddSymbol(epname
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
266 cpnt
+= buf
[0] + 1 + sizeof(WORD
);
268 GlobalUnlock16(module
->nrname_handle
);
272 /***********************************************************************
275 void DEBUG_LoadModule32(const char* name
, HANDLE hFile
, void *base
)
277 IMAGE_NT_HEADERS pe_header
;
279 DBG_MODULE
* wmod
= NULL
;
281 IMAGE_SECTION_HEADER pe_seg
;
284 enum DbgInfoLoad dil
= DIL_ERROR
;
287 if (!DEBUG_READ_MEM_VERBOSE( (char *)base
+ OFFSET_OF(IMAGE_DOS_HEADER
, e_lfanew
),
288 &nth_ofs
, sizeof(nth_ofs
)) ||
289 !DEBUG_READ_MEM_VERBOSE( (char *)base
+ nth_ofs
, &pe_header
, sizeof(pe_header
)))
292 pe_seg_ofs
= nth_ofs
+ OFFSET_OF(IMAGE_NT_HEADERS
, OptionalHeader
) +
293 pe_header
.FileHeader
.SizeOfOptionalHeader
;
295 for (i
= 0; i
< pe_header
.FileHeader
.NumberOfSections
; i
++, pe_seg_ofs
+= sizeof(pe_seg
)) {
296 if (!DEBUG_READ_MEM_VERBOSE( (char *)base
+ pe_seg_ofs
, &pe_seg
, sizeof(pe_seg
)))
298 if (size
< pe_seg
.VirtualAddress
+ pe_seg
.SizeOfRawData
)
299 size
= pe_seg
.VirtualAddress
+ pe_seg
.SizeOfRawData
;
302 /* FIXME: we make the assumption that hModule == base */
303 wmod
= DEBUG_RegisterPEModule((HMODULE
)base
, base
, size
, name
);
305 dil
= DEBUG_RegisterStabsDebugInfo(wmod
, hFile
, &pe_header
, nth_ofs
);
306 if (dil
!= DIL_LOADED
)
307 dil
= DEBUG_RegisterMSCDebugInfo(wmod
, hFile
, &pe_header
, nth_ofs
);
308 if (dil
!= DIL_LOADED
)
309 dil
= DEBUG_RegisterPEDebugInfo(wmod
, hFile
, &pe_header
, nth_ofs
);
313 DEBUG_ReportDIL(dil
, "32bit DLL", name
, base
);
316 /***********************************************************************
317 * DEBUG_RegisterPEDebugInfo
319 enum DbgInfoLoad
DEBUG_RegisterPEDebugInfo(DBG_MODULE
* wmod
, HANDLE hFile
,
320 void* _nth
, unsigned long nth_ofs
)
326 IMAGE_SECTION_HEADER pe_seg
;
328 IMAGE_DATA_DIRECTORY dir
;
331 IMAGE_NT_HEADERS
* nth
= (PIMAGE_NT_HEADERS
)_nth
;
332 void * base
= wmod
->load_addr
;
335 value
.cookie
= DV_TARGET
;
339 /* Add start of DLL */
340 value
.addr
.off
= (unsigned long)base
;
341 if ((prefix
= strrchr(wmod
->module_name
, '\\' ))) prefix
++;
342 else prefix
= wmod
->module_name
;
344 DEBUG_AddSymbol(prefix
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
346 /* Add entry point */
347 snprintf(buffer
, sizeof(buffer
), "%s.EntryPoint", prefix
);
348 value
.addr
.off
= (unsigned long)base
+ nth
->OptionalHeader
.AddressOfEntryPoint
;
349 DEBUG_AddSymbol(buffer
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
351 /* Add start of sections */
352 pe_seg_ofs
= nth_ofs
+ OFFSET_OF(IMAGE_NT_HEADERS
, OptionalHeader
) +
353 nth
->FileHeader
.SizeOfOptionalHeader
;
355 for (i
= 0; i
< nth
->FileHeader
.NumberOfSections
; i
++, pe_seg_ofs
+= sizeof(pe_seg
)) {
356 if (!DEBUG_READ_MEM_VERBOSE( (char *)base
+ pe_seg_ofs
, &pe_seg
, sizeof(pe_seg
)))
358 snprintf(buffer
, sizeof(buffer
), "%s.%s", prefix
, pe_seg
.Name
);
359 value
.addr
.off
= (unsigned long)base
+ pe_seg
.VirtualAddress
;
360 DEBUG_AddSymbol(buffer
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
363 /* Add exported functions */
365 OFFSET_OF(IMAGE_NT_HEADERS
,
366 OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]);
367 if (DEBUG_READ_MEM_VERBOSE( (char *)base
+ dir_ofs
, &dir
, sizeof(dir
)) && dir
.Size
) {
368 IMAGE_EXPORT_DIRECTORY exports
;
369 WORD
* ordinals
= NULL
;
370 void** functions
= NULL
;
374 if (DEBUG_READ_MEM_VERBOSE( (char *)base
+ dir
.VirtualAddress
,
375 &exports
, sizeof(exports
)) &&
377 ((functions
= DBG_alloc(sizeof(functions
[0]) * exports
.NumberOfFunctions
))) &&
378 DEBUG_READ_MEM_VERBOSE( (char *)base
+ exports
.AddressOfFunctions
,
379 functions
, sizeof(functions
[0]) * exports
.NumberOfFunctions
) &&
381 ((ordinals
= DBG_alloc(sizeof(ordinals
[0]) * exports
.NumberOfNames
))) &&
382 DEBUG_READ_MEM_VERBOSE( (char *)base
+ (DWORD
)exports
.AddressOfNameOrdinals
,
383 ordinals
, sizeof(ordinals
[0]) * exports
.NumberOfNames
) &&
385 ((names
= DBG_alloc(sizeof(names
[0]) * exports
.NumberOfNames
))) &&
386 DEBUG_READ_MEM_VERBOSE( (char *)base
+ (DWORD
)exports
.AddressOfNames
,
387 names
, sizeof(names
[0]) * exports
.NumberOfNames
)) {
389 for (i
= 0; i
< exports
.NumberOfNames
; i
++) {
391 !DEBUG_READ_MEM_VERBOSE( (char *)base
+ names
[i
], bufstr
, sizeof(bufstr
)))
393 bufstr
[sizeof(bufstr
) - 1] = 0;
394 snprintf(buffer
, sizeof(buffer
), "%s.%s", prefix
, bufstr
);
395 value
.addr
.off
= (unsigned long)base
+ (DWORD
)functions
[ordinals
[i
]];
396 DEBUG_AddSymbol(buffer
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
399 for (i
= 0; i
< exports
.NumberOfFunctions
; i
++) {
400 if (!functions
[i
]) continue;
401 /* Check if we already added it with a name */
402 for (j
= 0; j
< exports
.NumberOfNames
; j
++)
403 if ((ordinals
[j
] == i
) && names
[j
]) break;
404 if (j
< exports
.NumberOfNames
) continue;
405 snprintf(buffer
, sizeof(buffer
), "%s.%ld", prefix
, i
+ exports
.Base
);
406 value
.addr
.off
= (unsigned long)base
+ (DWORD
)functions
[i
];
407 DEBUG_AddSymbol(buffer
, &value
, NULL
, SYM_WIN32
| SYM_FUNC
);
414 /* no real debug info, only entry points */
418 /***********************************************************************
419 * DEBUG_LoadEntryPoints
421 * Load the entry points of all the modules into the hash table.
423 int DEBUG_LoadEntryPoints(const char* pfx
)
426 /* FIXME: with address space separation in space, this is plain wrong
427 * it requires the 16 bit WOW debugging interface...
436 /* FIXME: we assume that a module is never removed from memory */
437 /* FIXME: this is (currently plain wrong when debugger is started by
438 * attaching to an existing program => the 16 bit modules will
439 * not be shared... not much to do on debugger side... sigh
441 if (ModuleFirst16(&entry
)) do {
442 if (DEBUG_FindModuleByName(entry
.szModule
, DM_TYPE_UNKNOWN
) ||
443 !(moduleAddr
= NE_GetPtr(entry
.hModule
)) ||
444 !DEBUG_READ_MEM_VERBOSE(moduleAddr
, &module
, sizeof(module
)) ||
445 (module
.flags
& NE_FFLAGS_WIN32
) /* NE module */)
448 if (pfx
) DEBUG_Printf(DBG_CHN_MESG
, pfx
);
449 DEBUG_Printf(DBG_CHN_MESG
, " ");
450 rowcount
= 3 + (pfx
? strlen(pfx
) : 0);
454 len
= strlen(entry
.szModule
);
455 if ((rowcount
+ len
) > 76) {
456 DEBUG_Printf(DBG_CHN_MESG
, "\n ");
459 DEBUG_Printf(DBG_CHN_MESG
, " %s", entry
.szModule
);
462 DEBUG_LoadModule16(entry
.hModule
, &module
, moduleAddr
, entry
.szModule
);
463 } while (ModuleNext16(&entry
));
466 if (first
) DEBUG_Printf(DBG_CHN_MESG
, "\n");
470 void DEBUG_ReportDIL(enum DbgInfoLoad dil
, const char* pfx
, const char* filename
, void *load_addr
)
476 fmt
= "Deferring debug information loading for %s '%s' (%p)\n";
479 fmt
= "Loaded debug information from %s '%s' (%p)\n";
482 fmt
= "No debug information in %s '%s' (%p)\n";
485 fmt
= "Can't find file for %s '%s' (%p)\n";
488 DEBUG_Printf(DBG_CHN_ERR
, "Oooocch (%d)\n", dil
);
492 DEBUG_Printf(DBG_CHN_MESG
, fmt
, pfx
, filename
, load_addr
);
495 static const char* DEBUG_GetModuleType(enum DbgModuleType type
)
498 case DMT_NE
: return "NE";
499 case DMT_PE
: return "PE";
500 case DMT_ELF
: return "ELF";
501 default: return "???";
505 static const char* DEBUG_GetDbgInfo(enum DbgInfoLoad dil
)
508 case DIL_LOADED
: return "loaded";
509 case DIL_DEFERRED
: return "deferred";
510 case DIL_NOINFO
: return "none";
511 case DIL_ERROR
: return "error";
516 /***********************************************************************
517 * DEBUG_ModuleCompare
519 * returns -1 is p1 < p2, 0 is p1 == p2, +1 if p1 > p2
520 * order used is order on load_addr of a module
522 static int DEBUG_ModuleCompare(const void* p1
, const void* p2
)
524 return (char*)(*((const DBG_MODULE
**)p1
))->load_addr
-
525 (char*)(*((const DBG_MODULE
**)p2
))->load_addr
;
528 /***********************************************************************
531 * returns TRUE is wmod_child is contained (inside bounds) of wmod_cntnr
533 static inline BOOL
DEBUG_IsContainer(const DBG_MODULE
* wmod_cntnr
,
534 const DBG_MODULE
* wmod_child
)
536 return wmod_cntnr
->load_addr
< wmod_child
->load_addr
&&
537 (DWORD
)wmod_cntnr
->load_addr
+ wmod_cntnr
->size
>
538 (DWORD
)wmod_child
->load_addr
+ wmod_child
->size
;
541 static void DEBUG_InfoShareModule(const DBG_MODULE
* module
, int ident
)
543 if (ident
) DEBUG_Printf(DBG_CHN_MESG
, " \\-");
544 DEBUG_Printf(DBG_CHN_MESG
, "%s\t0x%08lx-%08lx\t%s\n",
545 DEBUG_GetModuleType(module
->type
),
546 (DWORD
)module
->load_addr
, (DWORD
)module
->load_addr
+ module
->size
,
547 module
->module_name
);
550 /***********************************************************************
553 * Display shared libarary information.
555 void DEBUG_InfoShare(void)
560 ref
= DBG_alloc(sizeof(DBG_MODULE
*) * DEBUG_CurrProcess
->num_modules
);
563 DEBUG_Printf(DBG_CHN_MESG
, "Module\tAddress\t\t\tName\t%d modules\n",
564 DEBUG_CurrProcess
->num_modules
);
566 memcpy(ref
, DEBUG_CurrProcess
->modules
,
567 sizeof(DBG_MODULE
*) * DEBUG_CurrProcess
->num_modules
);
568 qsort(ref
, DEBUG_CurrProcess
->num_modules
, sizeof(DBG_MODULE
*),
569 DEBUG_ModuleCompare
);
570 for (i
= 0; i
< DEBUG_CurrProcess
->num_modules
; i
++) {
571 switch (ref
[i
]->type
) {
573 DEBUG_InfoShareModule(ref
[i
], 0);
574 for (j
= 0; j
< DEBUG_CurrProcess
->num_modules
; j
++) {
575 if (ref
[j
]->type
!= DMT_ELF
&& DEBUG_IsContainer(ref
[i
], ref
[j
]))
576 DEBUG_InfoShareModule(ref
[j
], 1);
581 /* check module is not in ELF */
582 for (j
= 0; j
< DEBUG_CurrProcess
->num_modules
; j
++) {
583 if (ref
[j
]->type
== DMT_ELF
&&
584 DEBUG_IsContainer(ref
[j
], ref
[i
]))
587 if (j
>= DEBUG_CurrProcess
->num_modules
)
588 DEBUG_InfoShareModule(ref
[i
], 0);
591 DEBUG_Printf(DBG_CHN_ERR
, "Unknown type (%d)\n", ref
[i
]->type
);
597 /***********************************************************************
599 * Display information about a given module (DLL or EXE)
601 void DEBUG_DumpModule(DWORD mod
)
605 if (!(wmod
= DEBUG_FindModuleByHandle((HANDLE
)mod
, DMT_UNKNOWN
)) &&
606 !(wmod
= DEBUG_FindModuleByAddr((void*)mod
, DMT_UNKNOWN
))) {
607 DEBUG_Printf(DBG_CHN_MESG
, "'0x%08lx' is not a valid module handle or address\n", mod
);
611 DEBUG_Printf(DBG_CHN_MESG
, "Module '%s' (handle=%p) 0x%08lx-0x%08lx (%s, debug info %s)\n",
612 wmod
->module_name
, wmod
->handle
, (DWORD
)wmod
->load_addr
,
613 (DWORD
)wmod
->load_addr
+ wmod
->size
,
614 DEBUG_GetModuleType(wmod
->type
), DEBUG_GetDbgInfo(wmod
->dil
));
617 /***********************************************************************
620 * Display information about all modules (DLLs and EXEs)
622 void DEBUG_WalkModules(void)
627 if (!DEBUG_CurrProcess
)
629 DEBUG_Printf(DBG_CHN_MESG
,
630 "Cannot walk classes while no process is loaded\n");
634 DEBUG_Printf(DBG_CHN_MESG
, "Address\t\t\tModule\tName\n");
636 amod
= DBG_alloc(sizeof(DBG_MODULE
*) * DEBUG_CurrProcess
->num_modules
);
639 memcpy(amod
, DEBUG_CurrProcess
->modules
,
640 sizeof(DBG_MODULE
*) * DEBUG_CurrProcess
->num_modules
);
641 qsort(amod
, DEBUG_CurrProcess
->num_modules
, sizeof(DBG_MODULE
*),
642 DEBUG_ModuleCompare
);
643 for (i
= 0; i
< DEBUG_CurrProcess
->num_modules
; i
++) {
644 if (amod
[i
]->type
== DMT_ELF
) continue;
646 DEBUG_Printf(DBG_CHN_MESG
, "0x%08lx-%08lx\t(%s)\t%s\n",
647 (DWORD
)amod
[i
]->load_addr
,
648 (DWORD
)amod
[i
]->load_addr
+ amod
[i
]->size
,
649 DEBUG_GetModuleType(amod
[i
]->type
), amod
[i
]->module_name
);