* Shared libaray/corefile changes from Peter Schauer:
[binutils-gdb.git] / gdb / solib.c
1 /* Copyright (C) 1990 Free Software Foundation, Inc.
2
3 This file is part of GDB.
4
5 GDB 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 1, or (at your option)
8 any later version.
9
10 GDB 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 GDB; see the file COPYING. If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19 /*
20 ** symbol definitions
21 */
22 #include <sys/types.h>
23 #include <string.h>
24 #include <link.h>
25 #include <sys/param.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include "defs.h"
29 #include "param.h"
30 #include "symtab.h"
31 #include "gdbcore.h"
32 #include "command.h"
33 #include "target.h"
34
35 /*
36 ** local data declarations
37 */
38 #define MAX_PATH_SIZE 256
39 struct so_list {
40 struct link_map inferior_lm; /* inferior link map */
41 struct link_map *inferior_lm_add;
42 long ld_text;
43 char inferior_so_name[MAX_PATH_SIZE]; /* Shared Object Library Name */
44 struct so_list *next; /* Next Structure */
45 int symbols_loaded;
46 bfd *so_bfd;
47 struct section_table *so_sections;
48 struct section_table *so_sections_end;
49 };
50
51 static struct so_list *so_list_head = 0;
52
53 /*
54 ** Build a section map for a shared library, record its text size in
55 ** the so_list structure and set up the text section of the shared lib.
56 */
57 static void
58 solib_map_sections(so)
59 struct so_list *so;
60 {
61 char *filename;
62 char *scratch_pathname;
63 int scratch_chan;
64 struct section_table *p;
65
66 filename = tilde_expand (so->inferior_so_name);
67 make_cleanup (free, filename);
68
69 scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
70 &scratch_pathname);
71 if (scratch_chan < 0)
72 scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename, O_RDONLY, 0,
73 &scratch_pathname);
74 if (scratch_chan < 0)
75 perror_with_name (filename);
76
77 so->so_bfd = bfd_fdopenr (scratch_pathname, NULL, scratch_chan);
78 if (!so->so_bfd)
79 error ("Could not open `%s' as an executable file: %s",
80 scratch_pathname, bfd_errmsg (bfd_error));
81 if (!bfd_check_format (so->so_bfd, bfd_object))
82 error ("\"%s\": not in executable format: %s.",
83 scratch_pathname, bfd_errmsg (bfd_error));
84 if (build_section_table (so->so_bfd, &so->so_sections, &so->so_sections_end))
85 error ("Can't find the file sections in `%s': %s",
86 exec_bfd->filename, bfd_errmsg (bfd_error));
87
88 for (p = so->so_sections; p < so->so_sections_end; p++)
89 {
90 if (strcmp (bfd_section_name (so->so_bfd, p->sec_ptr), ".text") == 0)
91 {
92 /* Determine length of text section and relocate it. */
93 so->ld_text = p->endaddr - p->addr;
94 p->addr += (CORE_ADDR)so->inferior_lm.lm_addr;
95 p->endaddr += (CORE_ADDR)so->inferior_lm.lm_addr;
96 }
97 else
98 /* All other sections are ignored for now. */
99 p->addr = p->endaddr = 0;
100 }
101 }
102
103 /*=======================================================================*/
104
105 /* find_solib
106 **
107 **Description:
108 **
109 ** This module contains the routine which finds the names of any loaded
110 ** "images" in the current process. The argument in must be NULL on the
111 ** first call, and then the returned value must be passed in on
112 ** subsequent calls. This provides the capability to "step" down the
113 ** list of loaded objects. On the last object, a NULL value is returned.
114 ** The arg and return value are "struct link_map" pointers, as defined
115 ** in <link.h>.
116 **
117 ** NOTE: This only works under SunOS4.0.
118 */
119
120 struct so_list *find_solib(so_list_ptr)
121 struct so_list *so_list_ptr; /* so_list_head position ptr */
122 {
123 struct so_list *so_list_next = 0;
124 CORE_ADDR inferior_dynamic_ptr = 0;
125 struct link_map *inferior_lm = 0;
126 struct link_dynamic inferior_dynamic_cpy;
127 struct link_dynamic_2 inferior_ld_2_cpy;
128 struct so_list *new;
129 int i;
130
131 if (!so_list_ptr) {
132 if (!(so_list_next = so_list_head)) {
133 for (i = 0; i < misc_function_count; i++) {
134 if (!strcmp (misc_function_vector[i].name, "_DYNAMIC")) {
135 inferior_dynamic_ptr = misc_function_vector[i].address;
136 break;
137 }
138 }
139 if (inferior_dynamic_ptr) {
140 read_memory(inferior_dynamic_ptr, &inferior_dynamic_cpy, sizeof(struct link_dynamic));
141 if (inferior_dynamic_cpy.ld_version == 3) {
142 read_memory((CORE_ADDR)inferior_dynamic_cpy.ld_un.ld_2,
143 &inferior_ld_2_cpy,
144 sizeof(struct link_dynamic_2));
145 inferior_lm = inferior_ld_2_cpy.ld_loaded;
146 }
147 }
148 }
149 } else {
150 /*
151 ** Advance to next local abbreviated load_map structure
152 */
153 if (!(inferior_lm = so_list_ptr->inferior_lm.lm_next)) {
154 /* See if any were added, but be quiet if we can't read
155 from the target any more. */
156 int status;
157
158 status = target_read_memory (
159 (CORE_ADDR)so_list_ptr->inferior_lm_add,
160 &so_list_ptr->inferior_lm,
161 sizeof(struct link_map));
162 if (status == 0)
163 inferior_lm = so_list_ptr->inferior_lm.lm_next;
164 else
165 inferior_lm = 0;
166 }
167 so_list_next = so_list_ptr->next;
168 }
169 if ((!so_list_next) && inferior_lm) {
170 /*
171 ** Get Next LM Structure from inferior image and build
172 ** an local abbreviated load_map structure
173 */
174 new = (struct so_list *) xmalloc(sizeof(struct so_list));
175 new->inferior_lm_add = inferior_lm;
176 read_memory((CORE_ADDR)inferior_lm,
177 &new->inferior_lm,
178 sizeof(struct link_map));
179
180 read_memory((CORE_ADDR)new->inferior_lm.lm_name,
181 new->inferior_so_name,
182 MAX_PATH_SIZE - 1);
183 new->inferior_so_name[MAX_PATH_SIZE - 1] = 0;
184 /* Zero everything after the first terminating null */
185 strncpy(new->inferior_so_name, new->inferior_so_name, MAX_PATH_SIZE);
186
187 #if 0
188 /* This doesn't work for core files, so instead get ld_text
189 using solib_map_sections (below). */
190 read_memory((CORE_ADDR)new->inferior_lm.lm_ld,
191 &inferior_dynamic_cpy,
192 sizeof(struct link_dynamic));
193 read_memory((CORE_ADDR)inferior_dynamic_cpy.ld_un.ld_2,
194 &inferior_ld_2_cpy,
195 sizeof(struct link_dynamic_2));
196 new->ld_text = inferior_ld_2_cpy.ld_text;
197 #endif
198
199 new->next = 0;
200 new->symbols_loaded = 0;
201 new->so_bfd = NULL;
202 new->so_sections = NULL;
203 if (so_list_ptr)
204 so_list_ptr->next = new;
205 else
206 so_list_head = new;
207
208 solib_map_sections (new);
209
210 so_list_next = new;
211 }
212 return(so_list_next);
213 }
214
215 /*
216 ** Called by core_xfer_memory if the transfer form the core file failed.
217 ** We try to satisfy the request from the text sections of the shared libs.
218 */
219 int
220 solib_xfer_memory (memaddr, myaddr, len, write)
221 CORE_ADDR memaddr;
222 char *myaddr;
223 int len;
224 int write;
225 {
226 int res;
227 register struct so_list *so = 0;
228
229 while (so = find_solib(so))
230 {
231 res = xfer_memory (memaddr, myaddr, len, write,
232 so->so_bfd, so->so_sections, so->so_sections_end);
233 if (res)
234 return res;
235 }
236 return 0;
237 }
238 /*=======================================================================*/
239
240 void solib_add(arg_string, from_tty)
241 char *arg_string;
242 int from_tty;
243 {
244 register struct so_list *so = 0; /* link map state variable */
245 char *val;
246
247 if (arg_string == 0)
248 re_comp (".");
249 else if (val = (char *) re_comp (arg_string)) {
250 error ("Invalid regexp: %s", val);
251 }
252
253 printf_filtered ("All shared libraries");
254 if (arg_string)
255 printf_filtered (" matching regular expresion \"%s\"", arg_string);
256 printf_filtered (":\n");
257
258 dont_repeat();
259
260 while (so = find_solib(so)) {
261 if (re_exec(so->inferior_so_name)) {
262 if (so->symbols_loaded) {
263 printf("Symbols already loaded for %s\n", so->inferior_so_name);
264 } else {
265 symbol_file_add (so->inferior_so_name, from_tty,
266 (unsigned int)so->inferior_lm.lm_addr, 0);
267 so->symbols_loaded = 1;
268 }
269 }
270 }
271 }
272 /*=======================================================================*/
273
274 static void solib_info()
275 {
276 register struct so_list *so = 0; /* link map state variable */
277
278 while (so = find_solib(so)) {
279 if (so == so_list_head) {
280 printf(" Address Range Symbols Shared Object Library\n");
281 }
282 printf(" 0x%08x - 0x%08x %s %s\n",
283 so->inferior_lm.lm_addr,
284 so->inferior_lm.lm_addr + so->ld_text - 1,
285 (so->symbols_loaded ? "Yes" : "No "),
286 so->inferior_so_name);
287 }
288 if (!so_list_head) {
289 printf("No shared libraries loaded at this time.\n");
290 }
291 }
292
293 /*
294 ** Called by Insert Breakpoint to see if Address is Shared Library Address
295 */
296 int
297 solib_address(address)
298 CORE_ADDR address;
299 {
300 register struct so_list *so = 0; /* link map state variable */
301
302 while (so = find_solib(so)) {
303 if ((address >= (CORE_ADDR) so->inferior_lm.lm_addr) &&
304 (address < (CORE_ADDR) so->inferior_lm.lm_addr + so->ld_text))
305 return 1;
306 }
307 return 0;
308 }
309
310 /*
311 ** Called by free_all_symtabs
312 */
313 void
314 clear_solib()
315 {
316 struct so_list *next;
317
318 while (so_list_head) {
319 if (so_list_head->so_sections)
320 free (so_list_head->so_sections);
321 if (so_list_head->so_bfd)
322 bfd_close (so_list_head->so_bfd);
323 next = so_list_head->next;
324 free(so_list_head);
325 so_list_head = next;
326 }
327
328 }
329
330 void
331 _initialize_solib()
332 {
333
334 add_com("sharedlibrary", class_files, solib_add,
335 "Load shared object library symbols for files matching REGEXP.");
336 add_info("sharedlibrary", solib_info,
337 "Status of loaded shared object libraries");
338
339 }