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