Added missing winestub dependency.
[wine] / debugger / module.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*
3  * File module.c - module handling for the wine debugger
4  *
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 "file.h"
16 #include "debugger.h"
17 #include "toolhelp.h"
18
19 /***********************************************************************
20  * Creates and links a new module to the current process 
21  *
22  */
23 DBG_MODULE*     DEBUG_AddModule(const char* name, int type, 
24                                 void* mod_addr, HMODULE hmodule)
25 {
26     DBG_MODULE* wmod;
27
28     if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
29         return NULL;
30
31     memset(wmod, 0, sizeof(*wmod));
32
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;
41
42     return wmod;
43 }
44
45 /***********************************************************************
46  *      DEBUG_FindModuleByName
47  *
48  */
49 DBG_MODULE*     DEBUG_FindModuleByName(const char* name, int type)
50 {
51     DBG_MODULE* wmod;
52     
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;
56     }
57     return wmod;
58 }
59
60 /***********************************************************************
61  *      DEBUG_FindModuleByAddr
62  *
63  * either the addr where module is loaded, or any address inside the 
64  * module
65  */
66 DBG_MODULE*     DEBUG_FindModuleByAddr(void* addr, int type)
67 {
68     DBG_MODULE* wmod;
69     DBG_MODULE* res = NULL;
70     
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;
76     }
77     return res;
78 }
79
80 /***********************************************************************
81  *              DEBUG_FindModuleByHandle
82  */
83 DBG_MODULE*     DEBUG_FindModuleByHandle(HANDLE handle, int type)
84 {
85     DBG_MODULE* wmod;
86     
87     for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
88         if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
89     }
90     return wmod;
91 }
92
93 /***********************************************************************
94  *                      DEBUG_RegisterELFModule
95  *
96  * ELF modules are also entered into the list - this is so that we
97  * can make 'info shared' types of displays possible.
98  */
99 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
100 {
101     DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
102
103     if (!wmod) return NULL;
104
105     wmod->status = DM_STATUS_LOADED;
106     DEBUG_CurrProcess->next_index++;
107
108     return wmod;
109 }
110
111 /***********************************************************************
112  *                      DEBUG_RegisterPEModule
113  *
114  */
115 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
116 {
117     DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
118
119     if (!wmod) return NULL;
120
121     DEBUG_CurrProcess->next_index++;
122
123     return wmod;
124 }
125
126 /***********************************************************************
127  *                      DEBUG_RegisterNEModule
128  *
129  */
130 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
131 {
132     DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
133
134     if (!wmod) return NULL;
135
136     wmod->status = DM_STATUS_LOADED;
137     DEBUG_CurrProcess->next_index++;
138     return wmod;
139 }
140
141 /***********************************************************************
142  *           DEBUG_GetEP16
143  *
144  * Helper function fo DEBUG_LoadModuleEPs16:
145  *      finds the address of a given entry point from a given module
146  */
147 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module, 
148                           WORD ordinal, DBG_ADDR* addr)
149 {
150     void*               idx;
151     ET_ENTRY            entry;
152     ET_BUNDLE           bundle;
153     SEGTABLEENTRY       ste;
154
155     bundle.next = module->entry_table;
156     do {
157         if (!bundle.next)
158             return FALSE;
159         idx = moduleAddr + bundle.next;
160         if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
161             return FALSE;
162     } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
163     
164     if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) + 
165                                 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY), 
166                                 &entry, sizeof(ET_ENTRY)))
167         return FALSE;
168     
169     addr->seg = entry.segnum;
170     addr->off = entry.offs;
171     
172     if (addr->seg == 0xfe) addr->seg = 0xffff;  /* constant entry */
173     else {
174         if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table + 
175                                     sizeof(ste) * (addr->seg - 1),
176                                     &ste, sizeof(ste)))
177             return FALSE;
178         addr->seg = GlobalHandleToSel16(ste.hSeg);
179     }
180     return TRUE;
181 }
182
183 /***********************************************************************
184  *           DEBUG_LoadModule16
185  *
186  * Load the entry points of a Win16 module into the hash table.
187  */
188 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
189 {
190     DBG_VALUE   value;
191     BYTE        buf[1 + 256 + 2];
192     char        epname[512];
193     char*       cpnt;
194     DBG_MODULE* wmod;
195
196     wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
197
198     value.type = NULL;
199     value.cookie = DV_TARGET;
200     value.addr.seg = 0;
201     value.addr.off = 0;
202     
203     cpnt = moduleAddr + module->name_table;
204     
205     /* First search the resident names */
206     
207     /* skip module name */
208     if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
209         return;
210     cpnt += 1 + buf[0] + sizeof(WORD);
211     
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);
216         }
217         cpnt += buf[0] + 1 + sizeof(WORD);
218     }
219     
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);
227         }
228         cpnt += buf[0] + 1 + sizeof(WORD);
229     }
230     GlobalUnlock16(module->nrname_handle);
231 }
232
233 /***********************************************************************
234  *                      DEBUG_LoadModule32
235  */
236 void    DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
237 {
238     DBG_VALUE                   value;
239     char                        buffer[256];
240     char                        bufstr[256];
241     int                         i;
242     IMAGE_NT_HEADERS            pe_header;
243     DWORD                       pe_header_ofs;
244     IMAGE_SECTION_HEADER        pe_seg;
245     DWORD                       pe_seg_ofs;
246     IMAGE_DATA_DIRECTORY        dir;
247     DWORD                       dir_ofs;
248     DBG_MODULE*                 wmod;
249
250     /* FIXME: we make the assumption that hModule == base */
251     wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
252
253     DEBUG_Printf(DBG_CHN_TRACE, "Registring 32bit DLL '%s' at %08lx\n", name, base);
254     
255     value.type = NULL;
256     value.cookie = DV_TARGET;
257     value.addr.seg = 0;
258     value.addr.off = 0;
259     
260     /* grab PE Header */
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)))
265         return;
266     
267     if (wmod) {
268         DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
269         DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);     
270     }
271
272     /* Add start of DLL */
273     value.addr.off = base;
274     DEBUG_AddSymbol(name, &value, NULL, SYM_WIN32 | SYM_FUNC);
275     
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);
280
281     /* Add start of sections */
282     pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
283         pe_header.FileHeader.SizeOfOptionalHeader;
284     
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)))
287             continue;
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);
291     }
292     
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;
301         DWORD*                  names = NULL;
302         int                     j;
303         
304         if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress), 
305                                    &exports, sizeof(exports)) &&
306             
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) &&
310             
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) &&
314             
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)) {
318             
319             for (i = 0; i < exports.NumberOfNames; i++) {
320                 if (!names[i] ||
321                     !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
322                     continue;
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);
327             }
328             
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);
338             }
339         }
340         DBG_free(functions);
341         DBG_free(ordinals);
342         DBG_free(names);
343     }
344 }
345
346 /***********************************************************************
347  *              DEBUG_LoadEntryPoints
348  *
349  * Load the entry points of all the modules into the hash table.
350  */
351 int DEBUG_LoadEntryPoints(const char* pfx)
352 {
353     MODULEENTRY entry;
354     NE_MODULE   module;
355     void*       moduleAddr;
356     int         first = 0;
357     int         rowcount = 0;
358     int         len;
359
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
364      */
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 */)
370             continue;
371         if (!first) {
372             if (pfx) DEBUG_Printf(DBG_CHN_MESG, pfx);
373             DEBUG_Printf(DBG_CHN_MESG, "   ");
374             rowcount = 3 + (pfx ? strlen(pfx) : 0);
375             first = 1;
376         }
377         
378         len = strlen(entry.szModule);
379         if ((rowcount + len) > 76) {
380             DEBUG_Printf(DBG_CHN_MESG, "\n   ");
381             rowcount = 3;
382         }
383         DEBUG_Printf(DBG_CHN_MESG, " %s", entry.szModule);
384         rowcount += len + 1;
385         
386         DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
387     } while (ModuleNext16(&entry));
388     
389     if (first) DEBUG_Printf(DBG_CHN_MESG, "\n"); 
390     return first;
391 }
392
393 /***********************************************************************
394  *           DEBUG_InfoShare
395  *
396  * Display shared libarary information.
397  */
398 void DEBUG_InfoShare(void)
399 {
400     DBG_MODULE* wmod;
401     const char* xtype;
402
403     DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
404
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;
411         }
412         DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
413                      xtype, wmod->module_name);
414     }
415 }
416
417 static const char*      DEBUG_GetModuleType(int type)
418 {
419     switch (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 "???";;
424     }
425 }
426
427 static const char*      DEBUG_GetModuleStatus(int status)
428 {
429     switch (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 "???"; 
434     }
435 }
436
437 /***********************************************************************
438  *           DEBUG_
439  * Display information about a given module (DLL or EXE)
440  */
441 void DEBUG_DumpModule(DWORD mod)
442 {
443     DBG_MODULE* wmod;
444
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);
448         return;
449     }
450
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));
454 }
455
456 /***********************************************************************
457  *           DEBUG_WalkModules
458  *
459  * Display information about all modules (DLLs and EXEs)
460  */
461 void DEBUG_WalkModules(void)
462 {
463     DBG_MODULE* wmod;
464     const char* xtype;
465
466     DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
467
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;
474         }
475         
476         DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", 
477                      (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type), 
478                      wmod->module_name);
479     }
480 }
481