Add Connection Point support to OLE font objects.
[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 "module.h"
14 #include "file.h"
15 #include "debugger.h"
16 #include "toolhelp.h"
17 #include "wingdi.h"
18 #include "winuser.h"
19
20 /***********************************************************************
21  * Creates and links a new module to the current process 
22  *
23  */
24 DBG_MODULE*     DEBUG_AddModule(const char* name, int type, 
25                                 void* mod_addr, HMODULE hmodule)
26 {
27     DBG_MODULE* wmod;
28
29     if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
30         return NULL;
31
32     memset(wmod, 0, sizeof(*wmod));
33
34     wmod->next = DEBUG_CurrProcess->modules;
35     wmod->status = DM_STATUS_NEW;
36     wmod->type = type;
37     wmod->load_addr = mod_addr;
38     wmod->handle = hmodule;
39     wmod->dbg_index = DEBUG_CurrProcess->next_index;
40     wmod->module_name = DBG_strdup(name);
41     DEBUG_CurrProcess->modules = wmod;
42
43     return wmod;
44 }
45
46 /***********************************************************************
47  *      DEBUG_FindModuleByName
48  *
49  */
50 DBG_MODULE*     DEBUG_FindModuleByName(const char* name, int type)
51 {
52     DBG_MODULE* wmod;
53     
54     for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
55         if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
56             !strcasecmp(name, wmod->module_name)) break;
57     }
58     return wmod;
59 }
60
61 /***********************************************************************
62  *      DEBUG_FindModuleByAddr
63  *
64  * either the addr where module is loaded, or any address inside the 
65  * module
66  */
67 DBG_MODULE*     DEBUG_FindModuleByAddr(void* addr, int type)
68 {
69     DBG_MODULE* wmod;
70     DBG_MODULE* res = NULL;
71     
72     for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
73         if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
74             (u_long)addr >= (u_long)wmod->load_addr &&
75             (!res || res->load_addr < wmod->load_addr))
76             res = wmod;
77     }
78     return res;
79 }
80
81 /***********************************************************************
82  *              DEBUG_FindModuleByHandle
83  */
84 DBG_MODULE*     DEBUG_FindModuleByHandle(HANDLE handle, int type)
85 {
86     DBG_MODULE* wmod;
87     
88     for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
89         if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
90     }
91     return wmod;
92 }
93
94 /***********************************************************************
95  *              DEBUG_GetProcessMainModule
96  */
97 DBG_MODULE*     DEBUG_GetProcessMainModule(DBG_PROCESS* process)
98 {
99     DBG_MODULE* wmod;
100
101     if (!process) return NULL;
102
103     /* main module is the first to be loaded on a given process, so it's the last on
104      * the list */
105     for (wmod = process->modules; wmod && wmod->next; wmod = wmod->next);
106     return wmod;
107 }
108
109 /***********************************************************************
110  *                      DEBUG_RegisterELFModule
111  *
112  * ELF modules are also entered into the list - this is so that we
113  * can make 'info shared' types of displays possible.
114  */
115 DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
116 {
117     DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
118
119     if (!wmod) return NULL;
120
121     wmod->status = DM_STATUS_LOADED;
122     DEBUG_CurrProcess->next_index++;
123
124     return wmod;
125 }
126
127 /***********************************************************************
128  *                      DEBUG_RegisterPEModule
129  *
130  */
131 DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
132 {
133     DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
134
135     if (!wmod) return NULL;
136
137     DEBUG_CurrProcess->next_index++;
138
139     return wmod;
140 }
141
142 /***********************************************************************
143  *                      DEBUG_RegisterNEModule
144  *
145  */
146 DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
147 {
148     DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
149
150     if (!wmod) return NULL;
151
152     wmod->status = DM_STATUS_LOADED;
153     DEBUG_CurrProcess->next_index++;
154     return wmod;
155 }
156
157 #if 0
158 /***********************************************************************
159  *           DEBUG_GetEP16
160  *
161  * Helper function fo DEBUG_LoadModuleEPs16:
162  *      finds the address of a given entry point from a given module
163  */
164 static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module, 
165                           WORD ordinal, DBG_ADDR* addr)
166 {
167     void*               idx;
168     ET_ENTRY            entry;
169     ET_BUNDLE           bundle;
170     SEGTABLEENTRY       ste;
171
172     bundle.next = module->entry_table;
173     do {
174         if (!bundle.next)
175             return FALSE;
176         idx = moduleAddr + bundle.next;
177         if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
178             return FALSE;
179     } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
180     
181     if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) + 
182                                 (ordinal - bundle.first - 1) * sizeof(ET_ENTRY), 
183                                 &entry, sizeof(ET_ENTRY)))
184         return FALSE;
185     
186     addr->seg = entry.segnum;
187     addr->off = entry.offs;
188     
189     if (addr->seg == 0xfe) addr->seg = 0xffff;  /* constant entry */
190     else {
191         if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table + 
192                                     sizeof(ste) * (addr->seg - 1),
193                                     &ste, sizeof(ste)))
194             return FALSE;
195         addr->seg = GlobalHandleToSel16(ste.hSeg);
196     }
197     return TRUE;
198 }
199
200 /***********************************************************************
201  *           DEBUG_LoadModule16
202  *
203  * Load the entry points of a Win16 module into the hash table.
204  */
205 static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
206 {
207     DBG_VALUE   value;
208     BYTE        buf[1 + 256 + 2];
209     char        epname[512];
210     char*       cpnt;
211     DBG_MODULE* wmod;
212
213     wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
214
215     value.type = NULL;
216     value.cookie = DV_TARGET;
217     value.addr.seg = 0;
218     value.addr.off = 0;
219     
220     cpnt = moduleAddr + module->name_table;
221     
222     /* First search the resident names */
223     
224     /* skip module name */
225     if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
226         return;
227     cpnt += 1 + buf[0] + sizeof(WORD);
228     
229     while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
230         sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
231         if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
232             DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
233         }
234         cpnt += buf[0] + 1 + sizeof(WORD);
235     }
236     
237     /* Now search the non-resident names table */
238     if (!module->nrname_handle) return;  /* No non-resident table */
239     cpnt = (char *)GlobalLock16(module->nrname_handle);
240     while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
241         sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
242         if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
243             DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
244         }
245         cpnt += buf[0] + 1 + sizeof(WORD);
246     }
247     GlobalUnlock16(module->nrname_handle);
248 }
249 #endif
250
251 /***********************************************************************
252  *                      DEBUG_LoadModule32
253  */
254 void    DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
255 {
256     DBG_VALUE                   value;
257     char                        buffer[512];
258     char                        bufstr[256];
259     int                         i;
260     IMAGE_NT_HEADERS            pe_header;
261     DWORD                       pe_header_ofs;
262     IMAGE_SECTION_HEADER        pe_seg;
263     DWORD                       pe_seg_ofs;
264     IMAGE_DATA_DIRECTORY        dir;
265     DWORD                       dir_ofs;
266     DBG_MODULE*                 wmod;
267     const char *prefix;
268
269     /* FIXME: we make the assumption that hModule == base */
270     wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
271
272     DEBUG_Printf(DBG_CHN_TRACE, "Registring 32bit DLL '%s' at %08lx\n", name, base);
273     
274     value.type = NULL;
275     value.cookie = DV_TARGET;
276     value.addr.seg = 0;
277     value.addr.off = 0;
278     
279     /* grab PE Header */
280     if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
281                                 &pe_header_ofs, sizeof(pe_header_ofs)) ||
282         !DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs), 
283                                 &pe_header, sizeof(pe_header)))
284         return;
285     
286     if (wmod) {
287         DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
288         DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);     
289     }
290
291     /* Add start of DLL */
292     value.addr.off = base;
293     if ((prefix = strrchr( name, '\\' ))) prefix++;
294     else prefix = name;
295
296     DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
297     
298     /* Add entry point */
299     wsnprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
300     value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
301     DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
302
303     /* Add start of sections */
304     pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
305         pe_header.FileHeader.SizeOfOptionalHeader;
306     
307     for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
308         if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
309             continue;
310         wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
311         value.addr.off = base + pe_seg.VirtualAddress;
312         DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
313     }
314     
315     /* Add exported functions */
316     dir_ofs = pe_header_ofs + 
317         OFFSET_OF(IMAGE_NT_HEADERS, 
318                   OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
319     if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
320         IMAGE_EXPORT_DIRECTORY  exports;
321         WORD*                   ordinals = NULL;
322         void**                  functions = NULL;
323         DWORD*                  names = NULL;
324         int                     j;
325         
326         if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress), 
327                                    &exports, sizeof(exports)) &&
328             
329             ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
330             DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
331                                    functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
332             
333             ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
334             DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
335                                    ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
336             
337             ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
338             DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
339                                    names, sizeof(names[0]) * exports.NumberOfNames)) {
340             
341             for (i = 0; i < exports.NumberOfNames; i++) {
342                 if (!names[i] ||
343                     !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
344                     continue;
345                 bufstr[sizeof(bufstr) - 1] = 0;
346                 wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, bufstr);
347                 value.addr.off = base + (DWORD)functions[ordinals[i]];
348                 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
349             }
350             
351             for (i = 0; i < exports.NumberOfFunctions; i++) {
352                 if (!functions[i]) continue;
353                 /* Check if we already added it with a name */
354                 for (j = 0; j < exports.NumberOfNames; j++)
355                     if ((ordinals[j] == i) && names[j]) break;
356                 if (j < exports.NumberOfNames) continue;
357                 wsnprintf(buffer, sizeof(buffer), "%s.%ld", prefix, i + exports.Base);
358                 value.addr.off = base + (DWORD)functions[i];
359                 DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
360             }
361         }
362         DBG_free(functions);
363         DBG_free(ordinals);
364         DBG_free(names);
365     }
366 }
367
368 /***********************************************************************
369  *              DEBUG_LoadEntryPoints
370  *
371  * Load the entry points of all the modules into the hash table.
372  */
373 int DEBUG_LoadEntryPoints(const char* pfx)
374 {
375     int         first = 0;
376     /* FIXME: with address space separation in space, this is plain wrong
377      *        it requires the 16 bit WOW debugging interface...
378      */
379 #if 0
380     MODULEENTRY entry;
381     NE_MODULE   module;
382     void*       moduleAddr;
383     int         rowcount = 0;
384     int         len;
385
386     /* FIXME: we assume that a module is never removed from memory */
387     /* FIXME: this is (currently plain wrong when debugger is started by
388      *        attaching to an existing program => the 16 bit modules will
389      *        not be shared... not much to do on debugger side... sigh
390      */
391     if (ModuleFirst16(&entry)) do {
392         if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
393             !(moduleAddr = NE_GetPtr(entry.hModule)) ||
394             !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
395             (module.flags & NE_FFLAGS_WIN32) /* NE module */)
396             continue;
397         if (!first) {
398             if (pfx) DEBUG_Printf(DBG_CHN_MESG, pfx);
399             DEBUG_Printf(DBG_CHN_MESG, "   ");
400             rowcount = 3 + (pfx ? strlen(pfx) : 0);
401             first = 1;
402         }
403         
404         len = strlen(entry.szModule);
405         if ((rowcount + len) > 76) {
406             DEBUG_Printf(DBG_CHN_MESG, "\n   ");
407             rowcount = 3;
408         }
409         DEBUG_Printf(DBG_CHN_MESG, " %s", entry.szModule);
410         rowcount += len + 1;
411         
412         DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
413     } while (ModuleNext16(&entry));
414 #endif
415     
416     if (first) DEBUG_Printf(DBG_CHN_MESG, "\n"); 
417     return first;
418 }
419
420 /***********************************************************************
421  *           DEBUG_InfoShare
422  *
423  * Display shared libarary information.
424  */
425 void DEBUG_InfoShare(void)
426 {
427     DBG_MODULE* wmod;
428     const char* xtype;
429
430     DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
431
432     for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
433         switch (wmod->type) {
434         case DM_TYPE_NE:        xtype = "NE"; break;
435         case DM_TYPE_PE:        xtype = "PE"; break;
436         case DM_TYPE_ELF:       xtype = "ELF"; break;
437         default:                xtype = "???"; break;
438         }
439         DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
440                      xtype, wmod->module_name);
441     }
442 }
443
444 static const char*      DEBUG_GetModuleType(int type)
445 {
446     switch (type) {
447     case DM_TYPE_NE:    return "NE";
448     case DM_TYPE_PE:    return "PE";
449     case DM_TYPE_ELF:   return "ELF";
450     default:            return "???";;
451     }
452 }
453
454 static const char*      DEBUG_GetModuleStatus(int status)
455 {
456     switch (status) {
457     case DM_STATUS_NEW:         return "deferred"; 
458     case DM_STATUS_LOADED:      return "ok"; 
459     case DM_STATUS_ERROR:       return "error"; 
460     default:                    return "???"; 
461     }
462 }
463
464 /***********************************************************************
465  *           DEBUG_
466  * Display information about a given module (DLL or EXE)
467  */
468 void DEBUG_DumpModule(DWORD mod)
469 {
470     DBG_MODULE* wmod;
471
472     if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
473         !(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
474         DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
475         return;
476     }
477
478     DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
479                  wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
480                  DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
481 }
482
483 /***********************************************************************
484  *           DEBUG_WalkModules
485  *
486  * Display information about all modules (DLLs and EXEs)
487  */
488 void DEBUG_WalkModules(void)
489 {
490     DBG_MODULE* wmod;
491     const char* xtype;
492
493     DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
494
495     for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
496         switch (wmod->type) {
497         case DM_TYPE_NE:        xtype = "NE"; break;
498         case DM_TYPE_PE:        xtype = "PE"; break;
499         case DM_TYPE_ELF:       continue;
500         default:                xtype = "???"; break;
501         }
502         
503         DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n", 
504                      (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type), 
505                      wmod->module_name);
506     }
507 }
508