| 1 | /* Copyright (C) 2002-2015 Free Software Foundation, Inc. |
| 2 | |
| 3 | This file is part of GDB. |
| 4 | |
| 5 | This program is free software; you can redistribute it and/or modify |
| 6 | it under the terms of the GNU General Public License as published by |
| 7 | the Free Software Foundation; either version 3 of the License, or |
| 8 | (at your option) any later version. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | GNU General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU General Public License |
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 17 | |
| 18 | #include "server.h" |
| 19 | #include "dll.h" |
| 20 | |
| 21 | #define get_dll(inf) ((struct dll_info *)(inf)) |
| 22 | |
| 23 | /* An "unspecified" CORE_ADDR, for match_dll. */ |
| 24 | #define UNSPECIFIED_CORE_ADDR (~(CORE_ADDR) 0) |
| 25 | |
| 26 | struct inferior_list all_dlls; |
| 27 | int dlls_changed; |
| 28 | |
| 29 | static void |
| 30 | free_one_dll (struct inferior_list_entry *inf) |
| 31 | { |
| 32 | struct dll_info *dll = get_dll (inf); |
| 33 | if (dll->name != NULL) |
| 34 | free (dll->name); |
| 35 | free (dll); |
| 36 | } |
| 37 | |
| 38 | /* Find a DLL with the same name and/or base address. A NULL name in |
| 39 | the key is ignored; so is an all-ones base address. */ |
| 40 | |
| 41 | static int |
| 42 | match_dll (struct inferior_list_entry *inf, void *arg) |
| 43 | { |
| 44 | struct dll_info *iter = (struct dll_info *) inf; |
| 45 | struct dll_info *key = (struct dll_info *) arg; |
| 46 | |
| 47 | if (key->base_addr != UNSPECIFIED_CORE_ADDR |
| 48 | && iter->base_addr == key->base_addr) |
| 49 | return 1; |
| 50 | else if (key->name != NULL |
| 51 | && iter->name != NULL |
| 52 | && strcmp (key->name, iter->name) == 0) |
| 53 | return 1; |
| 54 | |
| 55 | return 0; |
| 56 | } |
| 57 | |
| 58 | /* Record a newly loaded DLL at BASE_ADDR. */ |
| 59 | |
| 60 | void |
| 61 | loaded_dll (const char *name, CORE_ADDR base_addr) |
| 62 | { |
| 63 | struct dll_info *new_dll = XCNEW (struct dll_info); |
| 64 | |
| 65 | new_dll->entry.id = minus_one_ptid; |
| 66 | |
| 67 | new_dll->name = xstrdup (name); |
| 68 | new_dll->base_addr = base_addr; |
| 69 | |
| 70 | add_inferior_to_list (&all_dlls, &new_dll->entry); |
| 71 | dlls_changed = 1; |
| 72 | } |
| 73 | |
| 74 | /* Record that the DLL with NAME and BASE_ADDR has been unloaded. */ |
| 75 | |
| 76 | void |
| 77 | unloaded_dll (const char *name, CORE_ADDR base_addr) |
| 78 | { |
| 79 | struct dll_info *dll; |
| 80 | struct dll_info key_dll; |
| 81 | |
| 82 | /* Be careful not to put the key DLL in any list. */ |
| 83 | key_dll.name = (char *) name; |
| 84 | key_dll.base_addr = base_addr; |
| 85 | |
| 86 | dll = (struct dll_info *) find_inferior (&all_dlls, match_dll, &key_dll); |
| 87 | |
| 88 | if (dll == NULL) |
| 89 | /* For some inferiors we might get unloaded_dll events without having |
| 90 | a corresponding loaded_dll. In that case, the dll cannot be found |
| 91 | in ALL_DLL, and there is nothing further for us to do. |
| 92 | |
| 93 | This has been observed when running 32bit executables on Windows64 |
| 94 | (i.e. through WOW64, the interface between the 32bits and 64bits |
| 95 | worlds). In that case, the inferior always does some strange |
| 96 | unloading of unnamed dll. */ |
| 97 | return; |
| 98 | else |
| 99 | { |
| 100 | /* DLL has been found so remove the entry and free associated |
| 101 | resources. */ |
| 102 | remove_inferior (&all_dlls, &dll->entry); |
| 103 | free_one_dll (&dll->entry); |
| 104 | dlls_changed = 1; |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | void |
| 109 | clear_dlls (void) |
| 110 | { |
| 111 | for_each_inferior (&all_dlls, free_one_dll); |
| 112 | clear_inferior_list (&all_dlls); |
| 113 | } |