Move moxie stack out in memory.
[deliverable/binutils-gdb.git] / gdb / solib-darwin.c
CommitLineData
cf1061c0
TG
1/* Handle Darwin shared libraries for GDB, the GNU Debugger.
2
3 Copyright (C) 2009 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program 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
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21
22#include "symtab.h"
23#include "bfd.h"
24#include "symfile.h"
25#include "objfiles.h"
26#include "gdbcore.h"
27#include "target.h"
28#include "inferior.h"
29#include "gdbthread.h"
30
31#include "gdb_assert.h"
32
33#include "solist.h"
34#include "solib.h"
35#include "solib-svr4.h"
36
37#include "bfd-target.h"
38#include "elf-bfd.h"
39#include "exec.h"
40#include "auxv.h"
41#include "exceptions.h"
42#include "mach-o.h"
43
44struct gdb_dyld_image_info
45{
46 /* Base address (which corresponds to the Mach-O header). */
47 CORE_ADDR mach_header;
48 /* Image file path. */
49 CORE_ADDR file_path;
50 /* st.m_time of image file. */
51 unsigned long mtime;
52};
53
54/* Content of inferior dyld_all_image_infos structure. */
55struct gdb_dyld_all_image_infos
56{
57 /* Version (1). */
58 unsigned int version;
59 /* Number of images. */
60 unsigned int count;
61 /* Image description. */
62 CORE_ADDR info;
63 /* Notifier (function called when a library is added or removed). */
64 CORE_ADDR notifier;
65};
66
67/* Current all_image_infos version. */
68#define DYLD_VERSION 1
69
70/* Address of structure dyld_all_image_infos in inferior. */
71static CORE_ADDR dyld_all_image_addr;
72
73/* Gdb copy of dyld_all_info_infos. */
74static struct gdb_dyld_all_image_infos dyld_all_image;
75
76/* Read dyld_all_image from inferior. */
77static void
78darwin_load_image_infos (void)
79{
80 gdb_byte buf[24];
81 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
82 int len;
83
84 /* If the structure address is not known, don't continue. */
85 if (dyld_all_image_addr == 0)
86 return;
87
88 /* The structure has 4 fields: version (4 bytes), count (4 bytes),
89 info (pointer) and notifier (pointer). */
90 len = 4 + 4 + 2 * ptr_type->length;
91 gdb_assert (len <= sizeof (buf));
92 memset (&dyld_all_image, 0, sizeof (dyld_all_image));
93
94 /* Read structure raw bytes from target. */
95 if (target_read_memory (dyld_all_image_addr, buf, len))
96 return;
97
98 /* Extract the fields. */
99 dyld_all_image.version = extract_unsigned_integer (buf, 4);
100 if (dyld_all_image.version != DYLD_VERSION)
101 return;
102
103 dyld_all_image.count = extract_unsigned_integer (buf + 4, 4);
104 dyld_all_image.info = extract_typed_address (buf + 8, ptr_type);
105 dyld_all_image.notifier = extract_typed_address
106 (buf + 8 + ptr_type->length, ptr_type);
107}
108
109/* Link map info to include in an allocated so_list entry. */
110
111struct lm_info
112{
113 /* The target location of lm. */
114 CORE_ADDR lm_addr;
115};
116
117struct darwin_so_list
118{
119 /* Common field. */
120 struct so_list sl;
121 /* Darwin specific data. */
122 struct lm_info li;
123};
124
125/* Lookup the value for a specific symbol. */
126static CORE_ADDR
127lookup_symbol_from_bfd (bfd *abfd, char *symname)
128{
129 long storage_needed;
130 asymbol **symbol_table;
131 unsigned int number_of_symbols;
132 unsigned int i;
133 CORE_ADDR symaddr = 0;
134
135 storage_needed = bfd_get_symtab_upper_bound (abfd);
136
137 if (storage_needed <= 0)
138 return 0;
139
140 symbol_table = (asymbol **) xmalloc (storage_needed);
141 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
142
143 for (i = 0; i < number_of_symbols; i++)
144 {
145 asymbol *sym = symbol_table[i];
146 if (strcmp (sym->name, symname) == 0
147 && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
148 {
149 /* BFD symbols are section relative. */
150 symaddr = sym->value + sym->section->vma;
151 break;
152 }
153 }
154 xfree (symbol_table);
155
156 return symaddr;
157}
158
159/* Return program interpreter string. */
160static gdb_byte *
161find_program_interpreter (void)
162{
163 gdb_byte *buf = NULL;
164
165 /* If we have an exec_bfd, use its section table. */
166 if (exec_bfd)
167 {
168 struct bfd_section *dylinker_sect;
169
170 dylinker_sect = bfd_get_section_by_name (exec_bfd, "LC_LOAD_DYLINKER");
171 if (dylinker_sect != NULL)
172 {
173 int sect_size = bfd_section_size (exec_bfd, dylinker_sect);
174
175 buf = xmalloc (sect_size);
176 if (bfd_get_section_contents (exec_bfd, dylinker_sect,
177 buf, 0, sect_size))
178 return buf;
179 xfree (buf);
180 }
181 }
182
183 /* If we didn't find it, read from memory.
184 FIXME: todo. */
185 return buf;
186}
187
188/* Not used. I don't see how the main symbol file can be found: the
189 interpreter name is needed and it is known from the executable file.
190 Note that darwin-nat.c implements pid_to_exec_file. */
191static int
192open_symbol_file_object (void *from_ttyp)
193{
194 return 0;
195}
196
197/* Build a list of currently loaded shared objects. See solib-svr4.c */
198static struct so_list *
199darwin_current_sos (void)
200{
201 struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
202 int ptr_len = TYPE_LENGTH (ptr_type);
203 unsigned int image_info_size;
204 CORE_ADDR lm;
205 struct so_list *head = NULL;
206 struct so_list *tail = NULL;
207 int i;
208
209 /* Be sure image infos are loaded. */
210 darwin_load_image_infos ();
211
212 if (dyld_all_image.version != DYLD_VERSION)
213 return NULL;
214
215 image_info_size = ptr_len * 3;
216
217 /* Read infos for each solib.
218 This first entry is ignored as this is the executable itself. */
219 for (i = 1; i < dyld_all_image.count; i++)
220 {
221 CORE_ADDR info = dyld_all_image.info + i * image_info_size;
222 char buf[image_info_size];
223 CORE_ADDR load_addr;
224 CORE_ADDR path_addr;
225 char *file_path;
226 int errcode;
227 struct darwin_so_list *dnew;
228 struct so_list *new;
229 struct cleanup *old_chain;
230
231 /* Read image info from inferior. */
232 if (target_read_memory (info, buf, image_info_size))
233 break;
234
235 load_addr = extract_typed_address (buf, ptr_type);
236 path_addr = extract_typed_address (buf + ptr_len, ptr_type);
237
238 target_read_string (path_addr, &file_path,
239 SO_NAME_MAX_PATH_SIZE - 1, &errcode);
240 if (errcode)
241 break;
242
243 /* Create and fill the new so_list element. */
244 dnew = XZALLOC (struct darwin_so_list);
245 new = &dnew->sl;
246 old_chain = make_cleanup (xfree, dnew);
247
248 new->lm_info = &dnew->li;
249
250 strncpy (new->so_name, file_path, SO_NAME_MAX_PATH_SIZE - 1);
251 new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
252 strcpy (new->so_original_name, new->so_name);
253 xfree (file_path);
254 new->lm_info->lm_addr = load_addr;
255
256 if (head == NULL)
257 head = new;
258 else
259 tail->next = new;
260 tail = new;
261
262 discard_cleanups (old_chain);
263 }
264
265 return head;
266}
267
268/* Return 1 if PC lies in the dynamic symbol resolution code of the
269 run time loader. */
270int
271darwin_in_dynsym_resolve_code (CORE_ADDR pc)
272{
273 return 0;
274}
275
276
277/* No special symbol handling. */
278static void
279darwin_special_symbol_handling (void)
280{
281}
282
283/* Shared library startup support. See documentation in solib-svr4.c */
284static void
285darwin_solib_create_inferior_hook (void)
286{
287 struct minimal_symbol *msymbol;
288 char **bkpt_namep;
289 asection *interp_sect;
290 gdb_byte *interp_name;
291 CORE_ADDR sym_addr;
292 CORE_ADDR load_addr = 0;
293 int load_addr_found = 0;
294 int loader_found_in_list = 0;
295 struct so_list *so;
296 bfd *dyld_bfd = NULL;
297 struct inferior *inf = current_inferior ();
298
299 /* First, remove all the solib event breakpoints. Their addresses
300 may have changed since the last time we ran the program. */
301 remove_solib_event_breakpoints ();
302
303 /* Find the program interpreter. */
304 interp_name = find_program_interpreter ();
305 if (!interp_name)
306 return;
307
308 /* Create a bfd for the interpreter. */
309 sym_addr = 0;
310 dyld_bfd = bfd_openr (interp_name, gnutarget);
311 if (dyld_bfd)
312 {
313 bfd *sub;
314 sub = bfd_mach_o_fat_extract (dyld_bfd, bfd_object,
315 gdbarch_bfd_arch_info (current_gdbarch));
316 if (sub)
317 dyld_bfd = sub;
318 else
319 {
320 bfd_close (dyld_bfd);
321 dyld_bfd = NULL;
322 }
323 }
324 if (!dyld_bfd)
325 {
326 xfree (interp_name);
327 return;
328 }
329
330 if (!inf->attach_flag)
331 {
332 /* We find the dynamic linker's base address by examining
333 the current pc (which should point at the entry point for the
334 dynamic linker) and subtracting the offset of the entry point. */
335 load_addr = (read_pc () - bfd_get_start_address (dyld_bfd));
336 }
337 else
338 {
339 /* FIXME: todo.
340 Get address of __DATA.__dyld in exec_bfd, read address at offset 0
341 */
342 xfree (interp_name);
343 return;
344 }
345
346 /* Now try to set a breakpoint in the dynamic linker. */
347 dyld_all_image_addr =
348 lookup_symbol_from_bfd (dyld_bfd, "_dyld_all_image_infos");
349
350 bfd_close (dyld_bfd);
351 xfree (interp_name);
352
353 if (dyld_all_image_addr == 0)
354 return;
355
356 dyld_all_image_addr += load_addr;
357
358 darwin_load_image_infos ();
359
360 if (dyld_all_image.version == DYLD_VERSION)
361 create_solib_event_breakpoint (dyld_all_image.notifier);
362}
363
364static void
365darwin_clear_solib (void)
366{
367 dyld_all_image_addr = 0;
368 dyld_all_image.version = 0;
369}
370
371static void
372darwin_free_so (struct so_list *so)
373{
374}
375
376/* The section table is built from bfd sections using bfd VMAs.
377 Relocate these VMAs according to solib info. */
378static void
379darwin_relocate_section_addresses (struct so_list *so,
380 struct section_table *sec)
381{
382 sec->addr += so->lm_info->lm_addr;
383 sec->endaddr += so->lm_info->lm_addr;
384
385 /* Best effort to set addr_high/addr_low. This is used only by
386 'info sharedlibary'. */
387 if (so->addr_high == 0)
388 {
389 so->addr_low = sec->addr;
390 so->addr_high = sec->endaddr;
391 }
392 if (sec->endaddr > so->addr_high)
393 so->addr_high = sec->endaddr;
394 if (sec->addr < so->addr_low)
395 so->addr_low = sec->addr;
396}
397\f
398static struct symbol *
399darwin_lookup_lib_symbol (const struct objfile *objfile,
400 const char *name,
401 const char *linkage_name,
402 const domain_enum domain)
403{
404 return NULL;
405}
406
407static bfd *
408darwin_bfd_open (char *pathname)
409{
410 char *found_pathname;
411 int found_file;
412 bfd *abfd;
413 bfd *res;
414
415 /* Search for shared library file. */
416 found_pathname = solib_find (pathname, &found_file);
417 if (found_pathname == NULL)
418 perror_with_name (pathname);
419
420 /* Open bfd for shared library. */
421 abfd = solib_bfd_fopen (found_pathname, found_file);
422
423 res = bfd_mach_o_fat_extract (abfd, bfd_object,
424 gdbarch_bfd_arch_info (current_gdbarch));
425 if (!res)
426 {
427 bfd_close (abfd);
428 make_cleanup (xfree, found_pathname);
429 error (_("`%s': not a shared-library: %s"),
430 found_pathname, bfd_errmsg (bfd_get_error ()));
431 }
432 return res;
433}
434
435struct target_so_ops darwin_so_ops;
436
437void
438_initialize_darwin_solib (void)
439{
440 darwin_so_ops.relocate_section_addresses = darwin_relocate_section_addresses;
441 darwin_so_ops.free_so = darwin_free_so;
442 darwin_so_ops.clear_solib = darwin_clear_solib;
443 darwin_so_ops.solib_create_inferior_hook = darwin_solib_create_inferior_hook;
444 darwin_so_ops.special_symbol_handling = darwin_special_symbol_handling;
445 darwin_so_ops.current_sos = darwin_current_sos;
446 darwin_so_ops.open_symbol_file_object = open_symbol_file_object;
447 darwin_so_ops.in_dynsym_resolve_code = darwin_in_dynsym_resolve_code;
448 darwin_so_ops.lookup_lib_global_symbol = darwin_lookup_lib_symbol;
449 darwin_so_ops.bfd_open = darwin_bfd_open;
450}
This page took 0.061944 seconds and 4 git commands to generate.