OSDN Git Service

2009-12-03 Tristan Gingold <gingold@adacore.com>
[pf3gnuchains/pf3gnuchains3x.git] / gdb / machoread.c
1 /* Darwin support for GDB, the GNU debugger.
2    Copyright (C) 2008, 2009 Free Software Foundation, Inc.
3
4    Contributed by AdaCore.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "defs.h"
23 #include "symtab.h"
24 #include "gdbtypes.h"
25 #include "bfd.h"
26 #include "symfile.h"
27 #include "objfiles.h"
28 #include "buildsym.h"
29 #include "gdbcmd.h"
30 #include "gdbcore.h"
31 #include "mach-o.h"
32 #include "gdb_assert.h"
33 #include "aout/stab_gnu.h"
34 #include "vec.h"
35
36 #include <string.h>
37
38 /* If non-zero displays debugging message.  */
39 static int mach_o_debug_level = 0;
40
41 static void
42 macho_new_init (struct objfile *objfile)
43 {
44 }
45
46 static void
47 macho_symfile_init (struct objfile *objfile)
48 {
49   objfile->flags |= OBJF_REORDERED;
50   init_entry_point_info (objfile);
51 }
52
53 /* Dwarf debugging information are never in the final executable.  They stay
54    in object files and the executable contains the list of object files read
55    during the link.
56    Each time an oso (other source) is found in the executable, the reader
57    creates such a structure.  They are read after the processing of the
58    executable.
59 */
60 typedef struct oso_el
61 {
62   /* Object file name.  */
63   const char *name;
64
65   /* Associated time stamp.  */
66   unsigned long mtime;
67
68   /* Number of sections.  This is the length of SYMBOLS and OFFSETS array.  */
69   int num_sections;
70
71   /* Each seaction of the object file is represented by a symbol and its
72      offset.  */
73   asymbol **symbols;
74   bfd_vma *offsets;
75 }
76 oso_el;
77
78 /* Vector of object files to be read after the executable.  */
79 DEF_VEC_O (oso_el);
80 static VEC (oso_el) *oso_vector;
81
82 /*  Add a new OSO to the vector.  */
83
84 static void
85 macho_add_oso (const asymbol *oso_sym, int nbr_sections,
86                asymbol **symbols, bfd_vma *offsets)
87 {
88   oso_el el;
89
90   el.name = oso_sym->name;
91   el.mtime = oso_sym->value;
92   el.num_sections = nbr_sections;
93   el.symbols = symbols;
94   el.offsets = offsets;
95   VEC_safe_push (oso_el, oso_vector, &el);
96 }
97
98 /* Build the minimal symbol table from SYMBOL_TABLE of length
99    NUMBER_OF_SYMBOLS for OBJFILE.
100    Read OSO files at the end.  */
101
102 static void
103 macho_symtab_read (struct objfile *objfile,
104                    long number_of_symbols, asymbol **symbol_table)
105 {
106   struct gdbarch *gdbarch = get_objfile_arch (objfile);
107   long storage_needed;
108   long i, j;
109   CORE_ADDR offset;
110   enum minimal_symbol_type ms_type;
111   unsigned int nbr_sections = bfd_count_sections (objfile->obfd);
112   asymbol **first_symbol = NULL;
113   bfd_vma *first_offset = NULL;
114   const asymbol *oso_file = NULL;
115
116   for (i = 0; i < number_of_symbols; i++)
117     {
118       asymbol *sym = symbol_table[i];
119       bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym;
120
121       offset = ANOFFSET (objfile->section_offsets, sym->section->index);
122
123       if (sym->flags & BSF_DEBUGGING)
124         {
125           bfd_vma addr;
126
127           switch (mach_o_sym->n_type)
128             {
129             case N_SO:
130               if ((sym->name == NULL || sym->name[0] == 0)
131                   && oso_file != NULL)
132                 {
133                   macho_add_oso (oso_file, nbr_sections,
134                                  first_symbol, first_offset);
135                   first_symbol = NULL;
136                   first_offset = NULL;
137                   oso_file = NULL;
138                 }
139               break;
140             case N_FUN:
141             case N_STSYM:
142               if (sym->name == NULL || sym->name[0] == '\0')
143                 break;
144               /* Fall through.  */
145             case N_BNSYM:
146               gdb_assert (oso_file != NULL);
147               addr = sym->value 
148                 + bfd_get_section_vma (sym->section->bfd, sym->section);
149               if (addr != 0
150                   && first_symbol[sym->section->index] == NULL)
151                 {
152                   first_symbol[sym->section->index] = sym;
153                   first_offset[sym->section->index] = addr + offset;
154                 }
155               break;
156             case N_GSYM:
157               gdb_assert (oso_file != NULL);
158               if (first_symbol[sym->section->index] == NULL)
159                 first_symbol[sym->section->index] = sym;
160               break;
161             case N_OSO:
162               gdb_assert (oso_file == NULL);
163               first_symbol = (asymbol **)xmalloc (nbr_sections
164                                                   * sizeof (asymbol *));
165               first_offset = (bfd_vma *)xmalloc (nbr_sections
166                                                  * sizeof (bfd_vma));
167               for (j = 0; j < nbr_sections; j++)
168                 first_symbol[j] = NULL;
169               oso_file = sym;
170               break;
171             }
172           continue;
173         }
174
175       if (sym->name == NULL || *sym->name == '\0')
176         {
177           /* Skip names that don't exist (shouldn't happen), or names
178              that are null strings (may happen). */
179           continue;
180         }
181
182       if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
183         {
184           struct minimal_symbol *msym;
185           CORE_ADDR symaddr;
186
187           /* Bfd symbols are section relative. */
188           symaddr = sym->value + sym->section->vma;
189
190           /* Select global/local/weak symbols.  Note that bfd puts abs
191              symbols in their own section, so all symbols we are
192              interested in will have a section. */
193           /* Relocate all non-absolute and non-TLS symbols by the
194              section offset.  */
195           if (sym->section != &bfd_abs_section
196               && !(sym->section->flags & SEC_THREAD_LOCAL))
197             symaddr += offset;
198
199           if (sym->section == &bfd_abs_section)
200             ms_type = mst_abs;
201           else if (sym->section->flags & SEC_CODE)
202             {
203               if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
204                 ms_type = mst_text;
205               else
206                 ms_type = mst_file_text;
207             }
208           else if (sym->section->flags & SEC_ALLOC)
209             {
210               if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
211                 {
212                   if (sym->section->flags & SEC_LOAD)
213                     ms_type = mst_data;
214                   else
215                     ms_type = mst_bss;
216                 }
217               else if (sym->flags & BSF_LOCAL)
218                 {
219                   /* Not a special stabs-in-elf symbol, do regular
220                      symbol processing.  */
221                   if (sym->section->flags & SEC_LOAD)
222                     ms_type = mst_file_data;
223                   else
224                     ms_type = mst_file_bss;
225                 }
226               else
227                 ms_type = mst_unknown;
228             }
229           else
230             continue;   /* Skip this symbol. */
231
232           gdb_assert (sym->section->index < nbr_sections);
233           if (oso_file != NULL
234               && first_symbol[sym->section->index] == NULL)
235             {
236               first_symbol[sym->section->index] = sym;
237               first_offset[sym->section->index] = symaddr;
238             }
239
240           msym = prim_record_minimal_symbol_and_info
241             (sym->name, symaddr, ms_type, sym->section->index,
242              sym->section, objfile);
243         }
244     }
245
246   if (oso_file != NULL)
247     macho_add_oso (oso_file, nbr_sections, first_symbol, first_offset);
248 }
249
250 /* If NAME describes an archive member (ie: ARCHIVE '(' MEMBER ')'),
251    returns the length of the archive name.
252    Returns -1 otherwise.  */
253
254 static int
255 get_archive_prefix_len (const char *name)
256 {
257   char *lparen;
258   int name_len = strlen (name);
259
260   if (name_len == 0 || name[name_len - 1] != ')')
261     return -1;
262   
263   lparen = strrchr (name, '(');
264   if (lparen == NULL || lparen == name)
265     return -1;
266   return lparen - name;
267 }
268
269 static int
270 oso_el_compare_name (const void *vl, const void *vr)
271 {
272   const oso_el *l = (const oso_el *)vl;
273   const oso_el *r = (const oso_el *)vr;
274
275   return strcmp (l->name, r->name);
276 }
277
278 /* Add an oso file as a symbol file.  */
279
280 static void
281 macho_add_oso_symfile (oso_el *oso, bfd *abfd, struct objfile *main_objfile)
282 {
283   struct section_addr_info *addrs;
284   int len;
285   int i;
286   char leading_char;
287
288   if (mach_o_debug_level > 0)
289     printf_unfiltered (_("Loading symbols from oso: %s\n"), oso->name);
290       
291   if (!bfd_check_format (abfd, bfd_object))
292     {
293       warning (_("`%s': can't read symbols: %s."), oso->name,
294                bfd_errmsg (bfd_get_error ()));
295       bfd_close (abfd);
296       return;
297     }
298
299   bfd_set_cacheable (abfd, 1);
300   
301   /* Compute addr length.  */
302   len = 0;
303   for (i = 0; i < oso->num_sections; i++)
304     if (oso->symbols[i] != NULL)
305       len++;
306   
307   addrs = alloc_section_addr_info (len);
308
309   leading_char = bfd_get_symbol_leading_char (main_objfile->obfd);
310
311   len = 0;
312   for (i = 0; i < oso->num_sections; i++)
313     if (oso->symbols[i] != NULL)
314       {
315         if (oso->offsets[i])
316           addrs->other[len].addr = oso->offsets[i];
317         else
318           {
319             struct minimal_symbol *msym;
320             const char *name = oso->symbols[i]->name;
321             
322             if (name[0] == leading_char)
323               ++name;
324
325             if (mach_o_debug_level > 3)
326               printf_unfiltered (_("resolve sect %s with %s\n"),
327                                  oso->symbols[i]->section->name,
328                                  oso->symbols[i]->name);
329             msym = lookup_minimal_symbol (name, NULL, main_objfile);
330             if (msym == NULL)
331               {
332                 warning (_("can't find symbol '%s' in minsymtab"),
333                          oso->symbols[i]->name);
334                 addrs->other[len].addr = 0;
335               }
336             else
337               addrs->other[len].addr = SYMBOL_VALUE_ADDRESS (msym);
338           }
339         addrs->other[len].name = (char *)oso->symbols[i]->section->name;
340         len++;
341       }
342       
343   if (mach_o_debug_level > 1)
344     {
345       int j;
346       for (j = 0; j < addrs->num_sections; j++)
347         printf_unfiltered (_("  %s: %s\n"),
348                            core_addr_to_string (addrs->other[j].addr),
349                            addrs->other[j].name);
350     }
351
352   symbol_file_add_from_bfd (abfd, 0, addrs, 0);
353 }
354
355 /* Read symbols from the vector of oso files.  */
356
357 static void
358 macho_oso_symfile (struct objfile *main_objfile)
359 {
360   int ix;
361   VEC (oso_el) *vec;
362   oso_el *oso;
363
364   vec = oso_vector;
365   oso_vector = NULL;
366   
367   /* Sort oso by name so that files from libraries are gathered.  */
368   qsort (VEC_address (oso_el, vec), VEC_length (oso_el, vec),
369          sizeof (oso_el), oso_el_compare_name);
370
371   for (ix = 0; VEC_iterate (oso_el, vec, ix, oso);)
372     {
373       int pfx_len;
374       
375       /* Check if this is a library name.  */
376       pfx_len = get_archive_prefix_len (oso->name);
377       if (pfx_len > 0)
378         {
379           bfd *archive_bfd;
380           bfd *member_bfd;
381           char *archive_name = XNEWVEC (char, pfx_len + 1);
382           int last_ix;
383           oso_el *oso2;
384           int ix2;
385
386           memcpy (archive_name, oso->name, pfx_len);
387           archive_name[pfx_len] = '\0';
388
389           /* Compute number of oso for this archive.  */
390           for (last_ix = ix;
391                VEC_iterate (oso_el, vec, last_ix, oso2); last_ix++)
392             {
393               if (strncmp (oso2->name, archive_name, pfx_len) != 0)
394                 break;
395             }
396           
397           /* Open the archive and check the format.  */
398           archive_bfd = bfd_openr (archive_name, gnutarget);
399           if (archive_bfd == NULL)
400             {
401               warning (_("Could not open OSO archive file \"%s\""),
402                        archive_name);
403               ix = last_ix;
404               continue;
405             }
406           if (!bfd_check_format (archive_bfd, bfd_archive))
407             {
408               warning (_("OSO archive file \"%s\" not an archive."),
409                        archive_name);
410               bfd_close (archive_bfd);
411               ix = last_ix;
412               continue;
413             }
414           member_bfd = bfd_openr_next_archived_file (archive_bfd, NULL);
415           
416           if (member_bfd == NULL)
417             {
418               warning (_("Could not read archive members out of "
419                          "OSO archive \"%s\""), archive_name);
420               bfd_close (archive_bfd);
421               ix = last_ix;
422               continue;
423             }
424
425           /* Load all oso in this library.  */
426           while (member_bfd != NULL)
427             {
428               bfd *prev;
429               const char *member_name = member_bfd->filename;
430               int member_len = strlen (member_name);
431
432               /* If this member is referenced, add it as a symfile.  */
433               for (ix2 = ix; ix2 < last_ix; ix2++)
434                 {
435                   oso2 = VEC_index (oso_el, vec, ix2);
436
437                   if (oso2->name
438                       && strlen (oso2->name) == pfx_len + member_len + 2
439                       && !memcmp (member_name, oso2->name + pfx_len + 1,
440                                   member_len))
441                     {
442                       macho_add_oso_symfile (oso2, member_bfd, main_objfile);
443                       oso2->name = NULL;
444                       break;
445                     }
446                 }
447
448               prev = member_bfd;
449               member_bfd = bfd_openr_next_archived_file
450                 (archive_bfd, member_bfd);
451
452               /* Free previous member if not referenced by an oso.  */
453               if (ix2 >= last_ix)
454                 bfd_close (prev);
455             }
456           for (ix2 = ix; ix2 < last_ix; ix2++)
457             {
458               oso_el *oso2 = VEC_index (oso_el, vec, ix2);
459
460               if (oso2->name != NULL)
461                 warning (_("Could not find specified archive member "
462                            "for OSO name \"%s\""), oso->name);
463             }
464           ix = last_ix;
465         }
466       else
467         {
468           bfd *abfd;
469
470           abfd = bfd_openr (oso->name, gnutarget);
471           if (!abfd)
472             warning (_("`%s': can't open to read symbols: %s."), oso->name,
473                      bfd_errmsg (bfd_get_error ()));
474           else
475             macho_add_oso_symfile (oso, abfd, main_objfile);
476
477           ix++;
478         }
479     }
480
481   for (ix = 0; VEC_iterate (oso_el, vec, ix, oso); ix++)
482     {
483       xfree (oso->symbols);
484       xfree (oso->offsets);
485     }
486   VEC_free (oso_el, vec);
487 }
488
489 /* DSYM (debug symbols) files contain the debug info of an executable.
490    This is a separate file created by dsymutil(1) and is similar to debug
491    link feature on ELF.
492    DSYM files are located in a subdirectory.  Append DSYM_SUFFIX to the
493    executable name and the executable base name to get the DSYM file name.  */
494 #define DSYM_SUFFIX ".dSYM/Contents/Resources/DWARF/"
495
496 /* Check if a dsym file exists for OBJFILE.  If so, returns a bfd for it.
497    Return NULL if no valid dsym file is found.  */
498
499 static bfd *
500 macho_check_dsym (struct objfile *objfile)
501 {
502   size_t name_len = strlen (objfile->name);
503   size_t dsym_len = strlen (DSYM_SUFFIX);
504   const char *base_name = lbasename (objfile->name);
505   size_t base_len = strlen (base_name);
506   char *dsym_filename = alloca (name_len + dsym_len + base_len + 1);
507   bfd *dsym_bfd;
508   asection *sect;
509   bfd_byte main_uuid[16];
510   bfd_byte dsym_uuid[16];
511
512   strcpy (dsym_filename, objfile->name);
513   strcpy (dsym_filename + name_len, DSYM_SUFFIX);
514   strcpy (dsym_filename + name_len + dsym_len, base_name);
515
516   if (access (dsym_filename, R_OK) != 0)
517     return NULL;
518
519   sect = bfd_get_section_by_name (objfile->obfd, "LC_UUID");
520   if (sect == NULL)
521     {
522       warning (_("can't find UUID in %s"), objfile->name);
523       return NULL;
524     }
525   if (!bfd_get_section_contents (objfile->obfd, sect, main_uuid,
526                                  0, sizeof (main_uuid)))
527     {
528       warning (_("can't read UUID in %s"), objfile->name);
529       return NULL;
530     }
531
532   dsym_filename = xstrdup (dsym_filename);
533   dsym_bfd = bfd_openr (dsym_filename, gnutarget);
534   if (dsym_bfd == NULL)
535     {
536       warning (_("can't open dsym file %s"), dsym_filename);
537       xfree (dsym_filename);
538       return NULL;
539     }
540
541   if (!bfd_check_format (dsym_bfd, bfd_object))
542     {
543       bfd_close (dsym_bfd);
544       warning (_("bad dsym file format: %s"), bfd_errmsg (bfd_get_error ()));
545       xfree (dsym_filename);
546       return NULL;
547     }
548
549   sect = bfd_get_section_by_name (dsym_bfd, "LC_UUID");
550   if (sect == NULL)
551     {
552       warning (_("can't find UUID in %s"), dsym_filename);
553       bfd_close (dsym_bfd);
554       xfree (dsym_filename);
555       return NULL;
556     }
557   if (!bfd_get_section_contents (dsym_bfd, sect, dsym_uuid,
558                                  0, sizeof (dsym_uuid)))
559     {
560       warning (_("can't read UUID in %s"), dsym_filename);
561       bfd_close (dsym_bfd);
562       xfree (dsym_filename);
563       return NULL;
564     }
565   if (memcmp (dsym_uuid, main_uuid, sizeof (main_uuid)))
566     {
567       warning (_("dsym file UUID doesn't match the one in %s"), objfile->name);
568       bfd_close (dsym_bfd);
569       xfree (dsym_filename);
570       return NULL;
571     }
572   return dsym_bfd;
573
574 }
575
576 static void
577 macho_symfile_read (struct objfile *objfile, int symfile_flags)
578 {
579   bfd *abfd = objfile->obfd;
580   struct cleanup *back_to;
581   CORE_ADDR offset;
582   long storage_needed;
583   bfd *dsym_bfd;
584
585   init_minimal_symbol_collection ();
586   back_to = make_cleanup_discard_minimal_symbols ();
587
588   /* Get symbols from the symbol table only if the file is an executable.
589      The symbol table of object files is not relocated and is expected to
590      be in the executable.  */
591   if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC))
592     {
593       /* Process the normal symbol table first.  */
594       storage_needed = bfd_get_symtab_upper_bound (objfile->obfd);
595       if (storage_needed < 0)
596         error (_("Can't read symbols from %s: %s"),
597                bfd_get_filename (objfile->obfd),
598                bfd_errmsg (bfd_get_error ()));
599
600       if (storage_needed > 0)
601         {
602           asymbol **symbol_table;
603           long symcount;
604
605           symbol_table = (asymbol **) xmalloc (storage_needed);
606           make_cleanup (xfree, symbol_table);
607           symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
608           
609           if (symcount < 0)
610             error (_("Can't read symbols from %s: %s"),
611                    bfd_get_filename (objfile->obfd),
612                    bfd_errmsg (bfd_get_error ()));
613           
614           macho_symtab_read (objfile, symcount, symbol_table);
615         }
616       
617       install_minimal_symbols (objfile);
618
619       /* Try to read .eh_frame / .debug_frame.  */
620       /* First, locate these sections.  We ignore the result status
621          as it only checks for debug info.  */
622       dwarf2_has_info (objfile);
623       dwarf2_build_frame_info (objfile);
624       
625       /* Check for DSYM file.  */
626       dsym_bfd = macho_check_dsym (objfile);
627       if (dsym_bfd != NULL)
628         {
629           int ix;
630           oso_el *oso;
631
632           if (mach_o_debug_level > 0)
633             printf_unfiltered (_("dsym file found\n"));
634
635           /* Remove oso.  They won't be used.  */
636           for (ix = 0; VEC_iterate (oso_el, oso_vector, ix, oso); ix++)
637             {
638               xfree (oso->symbols);
639               xfree (oso->offsets);
640             }
641           VEC_free (oso_el, oso_vector);
642           oso_vector = NULL;
643
644           /* Add the dsym file as a separate file.  */
645           symbol_file_add_separate (dsym_bfd, symfile_flags, objfile);
646       
647           /* Don't try to read dwarf2 from main file or shared libraries.  */
648           return;
649         }
650     }
651
652   if (dwarf2_has_info (objfile))
653     {
654       /* DWARF 2 sections */
655       dwarf2_build_psymtabs (objfile);
656     }
657
658   /* Do not try to read .eh_frame/.debug_frame as they are not relocated
659      and dwarf2_build_frame_info cannot deal with unrelocated sections.  */
660
661   /* Then the oso.  */
662   if (oso_vector != NULL)
663     macho_oso_symfile (objfile);
664 }
665
666 static void
667 macho_symfile_finish (struct objfile *objfile)
668 {
669 }
670
671 static void
672 macho_symfile_offsets (struct objfile *objfile,
673                        struct section_addr_info *addrs)
674 {
675   unsigned int i;
676   unsigned int num_sections;
677   struct obj_section *osect;
678
679   /* Allocate section_offsets.  */
680   objfile->num_sections = bfd_count_sections (objfile->obfd);
681   objfile->section_offsets = (struct section_offsets *)
682     obstack_alloc (&objfile->objfile_obstack,
683                    SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
684   memset (objfile->section_offsets, 0,
685           SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
686
687   /* This code is run when we first add the objfile with
688      symfile_add_with_addrs_or_offsets, when "addrs" not "offsets" are
689      passed in.  The place in symfile.c where the addrs are applied
690      depends on the addrs having section names.  But in the dyld code
691      we build an anonymous array of addrs, so that code is a no-op.
692      Because of that, we have to apply the addrs to the sections here.
693      N.B. if an objfile slides after we've already created it, then it
694      goes through objfile_relocate.  */
695
696   for (i = 0; i < addrs->num_sections; i++)
697     {
698       if (addrs->other[i].name == NULL)
699         continue;
700
701       ALL_OBJFILE_OSECTIONS (objfile, osect)
702         {
703           const char *bfd_sect_name = osect->the_bfd_section->name;
704
705           if (strcmp (bfd_sect_name, addrs->other[i].name) == 0)
706             {
707               obj_section_offset (osect) = addrs->other[i].addr;
708               break;
709             }
710         }
711     }
712
713   objfile->sect_index_text = 0;
714
715   ALL_OBJFILE_OSECTIONS (objfile, osect)
716     {
717       const char *bfd_sect_name = osect->the_bfd_section->name;
718       int sect_index = osect->the_bfd_section->index;
719       
720       if (strncmp (bfd_sect_name, "LC_SEGMENT.", 11) == 0)
721         bfd_sect_name += 11;
722       if (strcmp (bfd_sect_name, "__TEXT") == 0
723           || strcmp (bfd_sect_name, "__TEXT.__text") == 0)
724         objfile->sect_index_text = sect_index;
725     }
726 }
727
728 static struct sym_fns macho_sym_fns = {
729   bfd_target_mach_o_flavour,
730
731   macho_new_init,               /* sym_new_init: init anything gbl to entire symtab */
732   macho_symfile_init,           /* sym_init: read initial info, setup for sym_read() */
733   macho_symfile_read,           /* sym_read: read a symbol file into symtab */
734   macho_symfile_finish,         /* sym_finish: finished with file, cleanup */
735   macho_symfile_offsets,        /* sym_offsets:  xlate external to internal form */
736   default_symfile_segments,     /* sym_segments: Get segment information from
737                                    a file.  */
738   NULL                          /* next: pointer to next struct sym_fns */
739 };
740
741 void
742 _initialize_machoread ()
743 {
744   add_symtab_fns (&macho_sym_fns);
745
746   add_setshow_zinteger_cmd ("mach-o", class_obscure,
747                             &mach_o_debug_level, _("\
748 Set if printing Mach-O symbols processing."), _("\
749 Show if printing Mach-O symbols processing."), NULL,
750                             NULL, NULL,
751                             &setdebuglist, &showdebuglist);
752 }