server: Don't round up the header size for image mappings.
[wine] / dlls / dbghelp / module.c
1 /*
2  * File module.c - module handling for the wine debugger
3  *
4  * Copyright (C) 1993,      Eric Youngdale.
5  *               2000-2004, Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "dbghelp_private.h"
29 #include "psapi.h"
30 #include "winreg.h"
31 #include "winternl.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
35
36 static const char* ext[] = {".acm", ".dll", ".drv", ".exe", ".ocx", ".vxd", NULL};
37
38 static int match_ext(const char* ptr, size_t len)
39 {
40     const char**e;
41     size_t      l;
42
43     for (e = ext; *e; e++)
44     {
45         l = strlen(*e);
46         if (l >= len) return FALSE;
47         if (strncasecmp(&ptr[len - l], *e, l)) continue;
48         return l;
49     }
50     return 0;
51 }
52         
53 static void module_fill_module(const char* in, char* out, size_t size)
54 {
55     const char  *ptr,*endptr;
56     size_t      len, l;
57
58     endptr = in + strlen(in);
59     for (ptr = endptr - 1;
60          ptr >= in && *ptr != '/' && *ptr != '\\';
61          ptr--);
62     ptr++;
63     len = min(endptr-ptr,size-1);
64     memcpy(out, ptr, len);
65     out[len] = '\0';
66     if (len > 4 && (l = match_ext(out, len)))
67         out[len - l] = '\0';
68     else if (len > 12 &&
69              (!strcasecmp(out + len - 12, "wine-pthread") || 
70               !strcasecmp(out + len - 12, "wine-kthread")))
71         lstrcpynA(out, "<wine-loader>", size);
72     else
73     {
74         if (len > 3 && !strcasecmp(&out[len - 3], ".so") &&
75             (l = match_ext(out, len - 3)))
76             strcpy(&out[len - l - 3], "<elf>");
77     }
78     while ((*out = tolower(*out))) out++;
79 }
80
81 static const char*      get_module_type(enum module_type type)
82 {
83     switch (type)
84     {
85     case DMT_ELF: return "ELF";
86     case DMT_PE: return "PE";
87     case DMT_VIRTUAL: return "Virtual";
88     default: return "---";
89     }
90 }
91
92 /***********************************************************************
93  * Creates and links a new module to a process 
94  */
95 struct module* module_new(struct process* pcs, const char* name, 
96                           enum module_type type, 
97                           unsigned long mod_addr, unsigned long size,
98                           unsigned long stamp, unsigned long checksum) 
99 {
100     struct module*      module;
101
102     assert(type == DMT_ELF || type == DMT_PE || type == DMT_VIRTUAL);
103     if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
104         return NULL;
105
106     memset(module, 0, sizeof(*module));
107
108     module->next = pcs->lmodules;
109     pcs->lmodules = module;
110
111     TRACE("=> %s %08lx-%08lx %s\n", 
112           get_module_type(type), mod_addr, mod_addr + size, name);
113
114     pool_init(&module->pool, 65536);
115     
116     module->module.SizeOfStruct = sizeof(module->module);
117     module->module.BaseOfImage = mod_addr;
118     module->module.ImageSize = size;
119     module_fill_module(name, module->module.ModuleName,
120                        sizeof(module->module.ModuleName));
121     module->module.ImageName[0] = '\0';
122     lstrcpynA(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName));
123     module->module.SymType = SymNone;
124     module->module.NumSyms = 0;
125     module->module.TimeDateStamp = stamp;
126     module->module.CheckSum = checksum;
127
128     module->type              = type;
129     module->sortlist_valid    = FALSE;
130     module->addr_sorttab      = NULL;
131     /* FIXME: this seems a bit too high (on a per module basis)
132      * need some statistics about this
133      */
134     hash_table_init(&module->pool, &module->ht_symbols, 4096);
135     hash_table_init(&module->pool, &module->ht_types,   4096);
136     vector_init(&module->vtypes, sizeof(struct symt*),  32);
137
138     module->sources_used      = 0;
139     module->sources_alloc     = 0;
140     module->sources           = 0;
141
142     return module;
143 }
144
145 /***********************************************************************
146  *      module_find_by_name
147  *
148  */
149 struct module* module_find_by_name(const struct process* pcs, 
150                                    const char* name, enum module_type type)
151 {
152     struct module*      module;
153
154     if (type == DMT_UNKNOWN)
155     {
156         if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
157             (module = module_find_by_name(pcs, name, DMT_ELF)) ||
158             (module = module_find_by_name(pcs, name, DMT_VIRTUAL)))
159             return module;
160     }
161     else
162     {
163         char                modname[MAX_PATH];
164
165         for (module = pcs->lmodules; module; module = module->next)
166         {
167             if (type == module->type &&
168                 !strcasecmp(name, module->module.LoadedImageName)) 
169                 return module;
170         }
171         module_fill_module(name, modname, sizeof(modname));
172         for (module = pcs->lmodules; module; module = module->next)
173         {
174             if (type == module->type &&
175                 !strcasecmp(modname, module->module.ModuleName)) 
176                 return module;
177         }
178     }
179     SetLastError(ERROR_INVALID_NAME);
180     return NULL;
181 }
182
183 /***********************************************************************
184  *           module_get_container
185  *
186  */
187 struct module* module_get_container(const struct process* pcs, 
188                                     const struct module* inner)
189 {
190     struct module*      module;
191      
192     for (module = pcs->lmodules; module; module = module->next)
193     {
194         if (module != inner &&
195             module->module.BaseOfImage <= inner->module.BaseOfImage &&
196             module->module.BaseOfImage + module->module.ImageSize >=
197             inner->module.BaseOfImage + inner->module.ImageSize)
198             return module;
199     }
200     return NULL;
201 }
202
203 /***********************************************************************
204  *           module_get_containee
205  *
206  */
207 struct module* module_get_containee(const struct process* pcs, 
208                                     const struct module* outter)
209 {
210     struct module*      module;
211      
212     for (module = pcs->lmodules; module; module = module->next)
213     {
214         if (module != outter &&
215             outter->module.BaseOfImage <= module->module.BaseOfImage &&
216             outter->module.BaseOfImage + outter->module.ImageSize >=
217             module->module.BaseOfImage + module->module.ImageSize)
218             return module;
219     }
220     return NULL;
221 }
222
223 /******************************************************************
224  *              module_get_debug
225  *
226  * get the debug information from a module:
227  * - if the module's type is deferred, then force loading of debug info (and return
228  *   the module itself)
229  * - if the module has no debug info and has an ELF container, then return the ELF
230  *   container (and also force the ELF container's debug info loading if deferred)
231  * - otherwise return the module itself if it has some debug info
232  */
233 struct module* module_get_debug(const struct process* pcs, struct module* module)
234 {
235     struct module*      parent;
236
237     if (!module) return NULL;
238     /* for a PE builtin, always get info from parent */
239     if ((parent = module_get_container(pcs, module)))
240         module = parent;
241     /* if deferred, force loading */
242     if (module->module.SymType == SymDeferred)
243     {
244         BOOL ret;
245
246         switch (module->type)
247         {
248         case DMT_ELF: ret = elf_load_debug_info(module, NULL);  break;
249         case DMT_PE:  ret = pe_load_debug_info(pcs, module);    break;
250         case DMT_VIRTUAL: /* fall through */
251         default:      ret = FALSE;                              break;
252         }
253         if (!ret) module->module.SymType = SymNone;
254         assert(module->module.SymType != SymDeferred);
255     }
256     return (module && module->module.SymType != SymNone) ? module : NULL;
257 }
258
259 /***********************************************************************
260  *      module_find_by_addr
261  *
262  * either the addr where module is loaded, or any address inside the 
263  * module
264  */
265 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
266                                    enum module_type type)
267 {
268     struct module*      module;
269     
270     if (type == DMT_UNKNOWN)
271     {
272         if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
273             (module = module_find_by_addr(pcs, addr, DMT_ELF)) ||
274             (module = module_find_by_addr(pcs, addr, DMT_VIRTUAL)))
275             return module;
276     }
277     else
278     {
279         for (module = pcs->lmodules; module; module = module->next)
280         {
281             if (type == module->type && addr >= module->module.BaseOfImage &&
282                 addr < module->module.BaseOfImage + module->module.ImageSize) 
283                 return module;
284         }
285     }
286     SetLastError(ERROR_INVALID_ADDRESS);
287     return module;
288 }
289
290 static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName,
291                                            const char* ModuleName)
292 {
293     char                buffer[MAX_PATH];
294     size_t              len;
295     struct module*      module;
296
297     if (!ModuleName)
298     {
299         module_fill_module(ImageName, buffer, sizeof(buffer));
300         ModuleName = buffer;
301     }
302     len = strlen(ModuleName);
303     for (module = pcs->lmodules; module; module = module->next)
304     {
305         if (!strncasecmp(module->module.ModuleName, ModuleName, len) &&
306             module->type == DMT_ELF &&
307             !strcmp(module->module.ModuleName + len, "<elf>"))
308             return TRUE;
309     }
310     return FALSE;
311 }
312
313 /******************************************************************
314  *              module_get_type_by_name
315  *
316  * Guesses a filename type from its extension
317  */
318 enum module_type module_get_type_by_name(const char* name)
319 {
320     const char* ptr;
321     int         len = strlen(name);
322
323     /* check for terminating .so or .so.[digit] */
324     ptr = strrchr(name, '.');
325     if (ptr)
326     {
327         if (!strcmp(ptr, ".so") ||
328             (isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, ".so", 3)))
329             return DMT_ELF;
330         else if (!strcasecmp(ptr, ".pdb"))
331             return DMT_PDB;
332     }
333     /* wine-[kp]thread is also an ELF module */
334     else if (((len > 12 && name[len - 13] == '/') || len == 12) && 
335              (!strcasecmp(name + len - 12, "wine-pthread") || 
336               !strcasecmp(name + len - 12, "wine-kthread")))
337     {
338         return DMT_ELF;
339     }
340     return DMT_PE;
341 }
342
343 /***********************************************************************
344  *                      SymLoadModule (DBGHELP.@)
345  */
346 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
347                            char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
348 {
349     struct process*     pcs;
350     struct module*      module = NULL;
351
352     TRACE("(%p %p %s %s %08lx %08lx)\n", 
353           hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 
354           BaseOfDll, SizeOfDll);
355
356     pcs = process_find_by_handle(hProcess);
357     if (!pcs) return FALSE;
358
359     /* force transparent ELF loading / unloading */
360     elf_synchronize_module_list(pcs);
361
362     /* this is a Wine extension to the API just to redo the synchronisation */
363     if (!ImageName && !hFile) return 0;
364
365     if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
366     {
367         /* force the loading of DLL as builtin */
368         if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
369                                               BaseOfDll, SizeOfDll)))
370             goto done;
371         WARN("Couldn't locate %s\n", ImageName);
372         return 0;
373     }
374     TRACE("Assuming %s as native DLL\n", ImageName);
375     if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
376     {
377         if (module_get_type_by_name(ImageName) == DMT_ELF &&
378             (module = elf_load_module(pcs, ImageName, BaseOfDll)))
379             goto done;
380         FIXME("Should have successfully loaded debug information for image %s\n",
381               ImageName);
382         if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
383                                               BaseOfDll, SizeOfDll)))
384             goto done;
385         WARN("Couldn't locate %s\n", ImageName);
386         return 0;
387     }
388
389 done:
390     /* by default pe_load_module fills module.ModuleName from a derivation 
391      * of ImageName. Overwrite it, if we have better information
392      */
393     if (ModuleName)
394         lstrcpynA(module->module.ModuleName, ModuleName, sizeof(module->module.ModuleName));
395     lstrcpynA(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
396
397     return module->module.BaseOfImage;
398 }
399
400 /***********************************************************************
401  *                      SymLoadModuleEx (DBGHELP.@)
402  */
403 DWORD64 WINAPI  SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
404                                 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize,
405                                 PMODLOAD_DATA Data, DWORD Flags)
406 {
407     if (Data)
408         FIXME("Unsupported load data parameter %p for %s\n", Data, ImageName);
409     if (!validate_addr64(BaseOfDll)) return FALSE;
410     if (Flags & SLMFLAG_VIRTUAL)
411     {
412         struct process* pcs = process_find_by_handle(hProcess);
413         struct module* module;
414         if (!pcs) return FALSE;
415
416         module = module_new(pcs, ImageName, DMT_VIRTUAL, (DWORD)BaseOfDll, DllSize, 0, 0);
417         if (!module) return FALSE;
418         if (ModuleName)
419             lstrcpynA(module->module.ModuleName, ModuleName, sizeof(module->module.ModuleName));
420
421         return TRUE;
422     }
423     if (Flags & ~(SLMFLAG_VIRTUAL))
424         FIXME("Unsupported Flags %08lx for %s\n", Flags, ImageName);
425
426     return SymLoadModule(hProcess, hFile, (char*)ImageName, (char*)ModuleName,
427                          (DWORD)BaseOfDll, DllSize);
428 }
429
430 /***********************************************************************
431  *                     SymLoadModule64 (DBGHELP.@)
432  */
433 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PSTR ImageName,
434                                PSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
435 {
436     if (!validate_addr64(BaseOfDll)) return FALSE;
437     return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll);
438 }
439
440 /******************************************************************
441  *              module_remove
442  *
443  */
444 BOOL module_remove(struct process* pcs, struct module* module)
445 {
446     struct module**     p;
447
448     TRACE("%s (%p)\n", module->module.ModuleName, module);
449     hash_table_destroy(&module->ht_symbols);
450     hash_table_destroy(&module->ht_types);
451     HeapFree(GetProcessHeap(), 0, (char*)module->sources);
452     HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
453     pool_destroy(&module->pool);
454
455     for (p = &pcs->lmodules; *p; p = &(*p)->next)
456     {
457         if (*p == module)
458         {
459             *p = module->next;
460             HeapFree(GetProcessHeap(), 0, module);
461             return TRUE;
462         }
463     }
464     FIXME("This shouldn't happen\n");
465     return FALSE;
466 }
467
468 /******************************************************************
469  *              SymUnloadModule (DBGHELP.@)
470  *
471  */
472 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
473 {
474     struct process*     pcs;
475     struct module*      module;
476
477     pcs = process_find_by_handle(hProcess);
478     if (!pcs) return FALSE;
479     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
480     if (!module) return FALSE;
481     return module_remove(pcs, module);
482 }
483
484 /******************************************************************
485  *              SymUnloadModule64 (DBGHELP.@)
486  *
487  */
488 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll)
489 {
490     struct process*     pcs;
491     struct module*      module;
492
493     pcs = process_find_by_handle(hProcess);
494     if (!pcs) return FALSE;
495     if (!validate_addr64(BaseOfDll)) return FALSE;
496     module = module_find_by_addr(pcs, (DWORD)BaseOfDll, DMT_UNKNOWN);
497     if (!module) return FALSE;
498     return module_remove(pcs, module);
499 }
500
501 /******************************************************************
502  *              SymEnumerateModules (DBGHELP.@)
503  *
504  */
505 BOOL  WINAPI SymEnumerateModules(HANDLE hProcess,
506                                  PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,  
507                                  PVOID UserContext)
508 {
509     struct process*     pcs = process_find_by_handle(hProcess);
510     struct module*      module;
511
512     if (!pcs) return FALSE;
513     
514     for (module = pcs->lmodules; module; module = module->next)
515     {
516         if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
517             continue;
518         if (!EnumModulesCallback(module->module.ModuleName, 
519                                  module->module.BaseOfImage, UserContext))
520             break;
521     }
522     return TRUE;
523 }
524
525 /******************************************************************
526  *              EnumerateLoadedModules (DBGHELP.@)
527  *
528  */
529 BOOL  WINAPI EnumerateLoadedModules(HANDLE hProcess,
530                                     PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
531                                     PVOID UserContext)
532 {
533     HMODULE*    hMods;
534     char        base[256], mod[256];
535     DWORD       i, sz;
536     MODULEINFO  mi;
537
538     hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0]));
539     if (!hMods) return FALSE;
540
541     if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
542     {
543         /* hProcess should also be a valid process handle !! */
544         FIXME("If this happens, bump the number in mod\n");
545         HeapFree(GetProcessHeap(), 0, hMods);
546         return FALSE;
547     }
548     sz /= sizeof(HMODULE);
549     for (i = 0; i < sz; i++)
550     {
551         if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
552             !GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
553             continue;
554         module_fill_module(base, mod, sizeof(mod));
555         EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage, 
556                                   UserContext);
557     }
558     HeapFree(GetProcessHeap(), 0, hMods);
559
560     return sz != 0 && i == sz;
561 }
562
563 /******************************************************************
564  *              SymGetModuleInfo (DBGHELP.@)
565  *
566  */
567 BOOL  WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 
568                               PIMAGEHLP_MODULE ModuleInfo)
569 {
570     struct process*     pcs = process_find_by_handle(hProcess);
571     struct module*      module;
572
573     if (!pcs) return FALSE;
574     if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
575     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
576     if (!module) return FALSE;
577
578     *ModuleInfo = module->module;
579     if (module->module.SymType == SymNone)
580     {
581         module = module_get_container(pcs, module);
582         if (module && module->module.SymType != SymNone)
583             ModuleInfo->SymType = module->module.SymType;
584     }
585
586     return TRUE;
587 }
588
589 /******************************************************************
590  *              SymGetModuleInfo64 (DBGHELP.@)
591  *
592  */
593 BOOL  WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, 
594                                 PIMAGEHLP_MODULE64 ModuleInfo)
595 {
596     struct process*     pcs = process_find_by_handle(hProcess);
597     struct module*      module;
598     DWORD               sz;
599     IMAGEHLP_MODULE64   mod;
600
601     TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo);
602
603     if (!pcs) return FALSE;
604     if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE;
605     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
606     if (!module) return FALSE;
607
608     mod.BaseOfImage = module->module.BaseOfImage;
609     mod.ImageSize = module->module.ImageSize;
610     mod.TimeDateStamp = module->module.TimeDateStamp;
611     mod.CheckSum = module->module.CheckSum;
612     mod.NumSyms = module->module.NumSyms;
613     mod.SymType = module->module.SymType;
614     strcpy(mod.ModuleName, module->module.ModuleName);
615     strcpy(mod.ImageName, module->module.ImageName);
616     strcpy(mod.LoadedImageName, module->module.LoadedImageName);
617     /* FIXME: all following attributes need to be set */
618     mod.LoadedPdbName[0] = '\0';
619     mod.CVSig = 0;
620     memset(mod.CVData, 0, sizeof(mod.CVData));
621     mod.PdbSig = 0;
622     memset(&mod.PdbSig70, 0, sizeof(mod.PdbSig70));
623     mod.PdbAge = 0;
624     mod.PdbUnmatched = 0;
625     mod.DbgUnmatched = 0;
626     mod.LineNumbers = 0;
627     mod.GlobalSymbols = 0;
628     mod.TypeInfo = 0;
629     mod.SourceIndexed = 0;
630     mod.Publics = 0;
631
632     if (module->module.SymType == SymNone)
633     {
634         module = module_get_container(pcs, module);
635         if (module && module->module.SymType != SymNone)
636             mod.SymType = module->module.SymType;
637     }
638     sz = ModuleInfo->SizeOfStruct;
639     memcpy(ModuleInfo, &mod, sz);
640     ModuleInfo->SizeOfStruct = sz;
641     return TRUE;
642 }
643
644 /***********************************************************************
645  *              SymGetModuleBase (DBGHELP.@)
646  */
647 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
648 {
649     struct process*     pcs = process_find_by_handle(hProcess);
650     struct module*      module;
651
652     if (!pcs) return 0;
653     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
654     if (!module) return 0;
655     return module->module.BaseOfImage;
656 }
657
658 /***********************************************************************
659  *              SymGetModuleBase64 (DBGHELP.@)
660  */
661 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
662 {
663     if (!validate_addr64(dwAddr)) return 0;
664     return SymGetModuleBase(hProcess, (DWORD)dwAddr);
665 }
666
667 /******************************************************************
668  *              module_reset_debug_info
669  * Removes any debug information linked to a given module.
670  */
671 void module_reset_debug_info(struct module* module)
672 {
673     module->sortlist_valid = TRUE;
674     module->addr_sorttab = NULL;
675     hash_table_destroy(&module->ht_symbols);
676     module->ht_symbols.num_buckets = 0;
677     module->ht_symbols.buckets = NULL;
678     hash_table_destroy(&module->ht_types);
679     module->ht_types.num_buckets = 0;
680     module->ht_types.buckets = NULL;
681     module->vtypes.num_elts = 0;
682     hash_table_destroy(&module->ht_symbols);
683     module->sources_used = module->sources_alloc = 0;
684     module->sources = NULL;
685 }