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