]> git.ipfire.org Git - thirdparty/gcc.git/blame - libbacktrace/macho.c
Update copyright years.
[thirdparty/gcc.git] / libbacktrace / macho.c
CommitLineData
dea40c94 1/* elf.c -- Get debug data from a Mach-O file for backtraces.
a945c346 2 Copyright (C) 2020-2024 Free Software Foundation, Inc.
dea40c94
ILT
3 Written by Ian Lance Taylor, Google.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 (2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 (3) The name of the author may not be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
35#include <sys/types.h>
36#include <dirent.h>
37#include <stdlib.h>
38#include <string.h>
39
40#ifdef HAVE_MACH_O_DYLD_H
41#include <mach-o/dyld.h>
42#endif
43
44#include "backtrace.h"
45#include "internal.h"
46
47/* Mach-O file header for a 32-bit executable. */
48
49struct macho_header_32
50{
51 uint32_t magic; /* Magic number (MACH_O_MAGIC_32) */
52 uint32_t cputype; /* CPU type */
53 uint32_t cpusubtype; /* CPU subtype */
54 uint32_t filetype; /* Type of file (object, executable) */
55 uint32_t ncmds; /* Number of load commands */
56 uint32_t sizeofcmds; /* Total size of load commands */
57 uint32_t flags; /* Flags for special features */
58};
59
60/* Mach-O file header for a 64-bit executable. */
61
62struct macho_header_64
63{
64 uint32_t magic; /* Magic number (MACH_O_MAGIC_64) */
65 uint32_t cputype; /* CPU type */
66 uint32_t cpusubtype; /* CPU subtype */
67 uint32_t filetype; /* Type of file (object, executable) */
68 uint32_t ncmds; /* Number of load commands */
69 uint32_t sizeofcmds; /* Total size of load commands */
70 uint32_t flags; /* Flags for special features */
71 uint32_t reserved; /* Reserved */
72};
73
74/* Mach-O file header for a fat executable. */
75
76struct macho_header_fat
77{
74c176ca 78 uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */
dea40c94
ILT
79 uint32_t nfat_arch; /* Number of components */
80};
81
82/* Values for the header magic field. */
83
84#define MACH_O_MH_MAGIC_32 0xfeedface
85#define MACH_O_MH_MAGIC_64 0xfeedfacf
86#define MACH_O_MH_MAGIC_FAT 0xcafebabe
87#define MACH_O_MH_CIGAM_FAT 0xbebafeca
74c176ca
ILT
88#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf
89#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca
dea40c94
ILT
90
91/* Value for the header filetype field. */
92
93#define MACH_O_MH_EXECUTE 0x02
94#define MACH_O_MH_DYLIB 0x06
95#define MACH_O_MH_DSYM 0x0a
96
97/* A component of a fat file. A fat file starts with a
98 macho_header_fat followed by nfat_arch instances of this
99 struct. */
100
101struct macho_fat_arch
102{
103 uint32_t cputype; /* CPU type */
104 uint32_t cpusubtype; /* CPU subtype */
105 uint32_t offset; /* File offset of this entry */
106 uint32_t size; /* Size of this entry */
107 uint32_t align; /* Alignment of this entry */
108};
109
74c176ca
ILT
110/* A component of a 64-bit fat file. This is used if the magic field
111 is MAGIC_FAT_64. This is only used when some file size or file
112 offset is too large to represent in the 32-bit format. */
113
114struct macho_fat_arch_64
115{
116 uint32_t cputype; /* CPU type */
117 uint32_t cpusubtype; /* CPU subtype */
118 uint64_t offset; /* File offset of this entry */
119 uint64_t size; /* Size of this entry */
120 uint32_t align; /* Alignment of this entry */
121 uint32_t reserved; /* Reserved */
122};
123
dea40c94
ILT
124/* Values for the fat_arch cputype field (and the header cputype
125 field). */
126
127#define MACH_O_CPU_ARCH_ABI64 0x01000000
128
129#define MACH_O_CPU_TYPE_X86 7
130#define MACH_O_CPU_TYPE_ARM 12
d1339b51 131#define MACH_O_CPU_TYPE_PPC 18
dea40c94
ILT
132
133#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)
134#define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)
d1339b51 135#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)
dea40c94
ILT
136
137/* The header of a load command. */
138
139struct macho_load_command
140{
141 uint32_t cmd; /* The type of load command */
142 uint32_t cmdsize; /* Size in bytes of the entire command */
143};
144
145/* Values for the load_command cmd field. */
146
147#define MACH_O_LC_SEGMENT 0x01
148#define MACH_O_LC_SYMTAB 0x02
149#define MACH_O_LC_SEGMENT_64 0x19
150#define MACH_O_LC_UUID 0x1b
151
152/* The length of a section of segment name. */
153
154#define MACH_O_NAMELEN (16)
155
156/* LC_SEGMENT load command. */
157
158struct macho_segment_command
159{
160 uint32_t cmd; /* The type of load command (LC_SEGMENT) */
161 uint32_t cmdsize; /* Size in bytes of the entire command */
162 char segname[MACH_O_NAMELEN]; /* Segment name */
163 uint32_t vmaddr; /* Virtual memory address */
164 uint32_t vmsize; /* Virtual memory size */
165 uint32_t fileoff; /* Offset of data to be mapped */
166 uint32_t filesize; /* Size of data in file */
167 uint32_t maxprot; /* Maximum permitted virtual protection */
168 uint32_t initprot; /* Initial virtual memory protection */
169 uint32_t nsects; /* Number of sections in this segment */
170 uint32_t flags; /* Flags */
171};
172
173/* LC_SEGMENT_64 load command. */
174
175struct macho_segment_64_command
176{
177 uint32_t cmd; /* The type of load command (LC_SEGMENT) */
178 uint32_t cmdsize; /* Size in bytes of the entire command */
179 char segname[MACH_O_NAMELEN]; /* Segment name */
180 uint64_t vmaddr; /* Virtual memory address */
181 uint64_t vmsize; /* Virtual memory size */
182 uint64_t fileoff; /* Offset of data to be mapped */
183 uint64_t filesize; /* Size of data in file */
184 uint32_t maxprot; /* Maximum permitted virtual protection */
185 uint32_t initprot; /* Initial virtual memory protection */
186 uint32_t nsects; /* Number of sections in this segment */
187 uint32_t flags; /* Flags */
188};
189
190/* LC_SYMTAB load command. */
191
192struct macho_symtab_command
193{
194 uint32_t cmd; /* The type of load command (LC_SEGMENT) */
195 uint32_t cmdsize; /* Size in bytes of the entire command */
196 uint32_t symoff; /* File offset of symbol table */
197 uint32_t nsyms; /* Number of symbols */
198 uint32_t stroff; /* File offset of string table */
199 uint32_t strsize; /* String table size */
200};
201
202/* The length of a Mach-O uuid. */
203
204#define MACH_O_UUID_LEN (16)
205
206/* LC_UUID load command. */
207
208struct macho_uuid_command
209{
210 uint32_t cmd; /* Type of load command (LC_UUID) */
211 uint32_t cmdsize; /* Size in bytes of command */
212 unsigned char uuid[MACH_O_UUID_LEN]; /* UUID */
213};
214
215/* 32-bit section header within a LC_SEGMENT segment. */
216
217struct macho_section
218{
219 char sectname[MACH_O_NAMELEN]; /* Section name */
220 char segment[MACH_O_NAMELEN]; /* Segment of this section */
221 uint32_t addr; /* Address in memory */
222 uint32_t size; /* Section size */
223 uint32_t offset; /* File offset */
224 uint32_t align; /* Log2 of section alignment */
225 uint32_t reloff; /* File offset of relocations */
226 uint32_t nreloc; /* Number of relocs for this section */
227 uint32_t flags; /* Flags */
228 uint32_t reserved1;
229 uint32_t reserved2;
230};
231
232/* 64-bit section header within a LC_SEGMENT_64 segment. */
233
234struct macho_section_64
235{
236 char sectname[MACH_O_NAMELEN]; /* Section name */
237 char segment[MACH_O_NAMELEN]; /* Segment of this section */
238 uint64_t addr; /* Address in memory */
239 uint64_t size; /* Section size */
240 uint32_t offset; /* File offset */
241 uint32_t align; /* Log2 of section alignment */
242 uint32_t reloff; /* File offset of section relocations */
243 uint32_t nreloc; /* Number of relocs for this section */
244 uint32_t flags; /* Flags */
245 uint32_t reserved1;
246 uint32_t reserved2;
247 uint32_t reserved3;
248};
249
250/* 32-bit symbol data. */
251
252struct macho_nlist
253{
254 uint32_t n_strx; /* Index of name in string table */
255 uint8_t n_type; /* Type flag */
256 uint8_t n_sect; /* Section number */
257 uint16_t n_desc; /* Stabs description field */
258 uint32_t n_value; /* Value */
259};
260
261/* 64-bit symbol data. */
262
263struct macho_nlist_64
264{
265 uint32_t n_strx; /* Index of name in string table */
266 uint8_t n_type; /* Type flag */
267 uint8_t n_sect; /* Section number */
268 uint16_t n_desc; /* Stabs description field */
269 uint64_t n_value; /* Value */
270};
271
272/* Value found in nlist n_type field. */
273
274#define MACH_O_N_EXT 0x01 /* Extern symbol */
275#define MACH_O_N_ABS 0x02 /* Absolute symbol */
276#define MACH_O_N_SECT 0x0e /* Defined in section */
277
278#define MACH_O_N_TYPE 0x0e /* Mask for type bits */
279#define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
280
281/* Information we keep for a Mach-O symbol. */
282
283struct macho_symbol
284{
285 const char *name; /* Symbol name */
286 uintptr_t address; /* Symbol address */
287};
288
289/* Information to pass to macho_syminfo. */
290
291struct macho_syminfo_data
292{
293 struct macho_syminfo_data *next; /* Next module */
294 struct macho_symbol *symbols; /* Symbols sorted by address */
295 size_t count; /* Number of symbols */
296};
297
298/* Names of sections, indexed by enum dwarf_section in internal.h. */
299
300static const char * const dwarf_section_names[DEBUG_MAX] =
301{
302 "__debug_info",
303 "__debug_line",
304 "__debug_abbrev",
305 "__debug_ranges",
306 "__debug_str",
307 "", /* DEBUG_ADDR */
308 "__debug_str_offs",
309 "", /* DEBUG_LINE_STR */
310 "__debug_rnglists"
311};
312
313/* Forward declaration. */
314
315static int macho_add (struct backtrace_state *, const char *, int, off_t,
316 const unsigned char *, uintptr_t, int,
317 backtrace_error_callback, void *, fileline *, int *);
318
319/* A dummy callback function used when we can't find any debug info. */
320
321static int
322macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
323 uintptr_t pc ATTRIBUTE_UNUSED,
324 backtrace_full_callback callback ATTRIBUTE_UNUSED,
325 backtrace_error_callback error_callback, void *data)
326{
327 error_callback (data, "no debug info in Mach-O executable", -1);
328 return 0;
329}
330
331/* A dummy callback function used when we can't find a symbol
332 table. */
333
334static void
335macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
336 uintptr_t addr ATTRIBUTE_UNUSED,
337 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
338 backtrace_error_callback error_callback, void *data)
339{
340 error_callback (data, "no symbol table in Mach-O executable", -1);
341}
342
343/* Add a single DWARF section to DWARF_SECTIONS, if we need the
344 section. Returns 1 on success, 0 on failure. */
345
346static int
347macho_add_dwarf_section (struct backtrace_state *state, int descriptor,
348 const char *sectname, uint32_t offset, uint64_t size,
349 backtrace_error_callback error_callback, void *data,
350 struct dwarf_sections *dwarf_sections)
351{
352 int i;
353
354 for (i = 0; i < (int) DEBUG_MAX; ++i)
355 {
356 if (dwarf_section_names[i][0] != '\0'
357 && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)
358 {
359 struct backtrace_view section_view;
360
361 /* FIXME: Perhaps it would be better to try to use a single
362 view to read all the DWARF data, as we try to do for
363 ELF. */
364
365 if (!backtrace_get_view (state, descriptor, offset, size,
366 error_callback, data, &section_view))
367 return 0;
368 dwarf_sections->data[i] = (const unsigned char *) section_view.data;
369 dwarf_sections->size[i] = size;
370 break;
371 }
372 }
373 return 1;
374}
375
376/* Collect DWARF sections from a DWARF segment. Returns 1 on success,
377 0 on failure. */
378
379static int
380macho_add_dwarf_segment (struct backtrace_state *state, int descriptor,
381 off_t offset, unsigned int cmd, const char *psecs,
382 size_t sizesecs, unsigned int nsects,
383 backtrace_error_callback error_callback, void *data,
384 struct dwarf_sections *dwarf_sections)
385{
386 size_t sec_header_size;
387 size_t secoffset;
388 unsigned int i;
389
390 switch (cmd)
391 {
392 case MACH_O_LC_SEGMENT:
393 sec_header_size = sizeof (struct macho_section);
394 break;
395 case MACH_O_LC_SEGMENT_64:
396 sec_header_size = sizeof (struct macho_section_64);
397 break;
398 default:
399 abort ();
400 }
401
402 secoffset = 0;
403 for (i = 0; i < nsects; ++i)
404 {
405 if (secoffset + sec_header_size > sizesecs)
406 {
407 error_callback (data, "section overflow withing segment", 0);
408 return 0;
409 }
410
411 switch (cmd)
412 {
413 case MACH_O_LC_SEGMENT:
414 {
415 struct macho_section section;
416
417 memcpy (&section, psecs + secoffset, sizeof section);
418 macho_add_dwarf_section (state, descriptor, section.sectname,
419 offset + section.offset, section.size,
420 error_callback, data, dwarf_sections);
421 }
422 break;
423
424 case MACH_O_LC_SEGMENT_64:
425 {
426 struct macho_section_64 section;
427
428 memcpy (&section, psecs + secoffset, sizeof section);
429 macho_add_dwarf_section (state, descriptor, section.sectname,
430 offset + section.offset, section.size,
431 error_callback, data, dwarf_sections);
432 }
433 break;
434
435 default:
436 abort ();
437 }
438
439 secoffset += sec_header_size;
440 }
441
442 return 1;
443}
444
445/* Compare struct macho_symbol for qsort. */
446
447static int
448macho_symbol_compare (const void *v1, const void *v2)
449{
450 const struct macho_symbol *m1 = (const struct macho_symbol *) v1;
451 const struct macho_symbol *m2 = (const struct macho_symbol *) v2;
452
453 if (m1->address < m2->address)
454 return -1;
455 else if (m1->address > m2->address)
456 return 1;
457 else
458 return 0;
459}
460
461/* Compare an address against a macho_symbol for bsearch. We allocate
462 one extra entry in the array so that this can safely look at the
463 next entry. */
464
465static int
466macho_symbol_search (const void *vkey, const void *ventry)
467{
468 const uintptr_t *key = (const uintptr_t *) vkey;
469 const struct macho_symbol *entry = (const struct macho_symbol *) ventry;
470 uintptr_t addr;
471
472 addr = *key;
473 if (addr < entry->address)
474 return -1;
475 else if (entry->name[0] == '\0'
476 && entry->address == ~(uintptr_t) 0)
477 return -1;
478 else if ((entry + 1)->name[0] == '\0'
479 && (entry + 1)->address == ~(uintptr_t) 0)
480 return -1;
481 else if (addr >= (entry + 1)->address)
482 return 1;
483 else
484 return 0;
485}
486
487/* Return whether the symbol type field indicates a symbol table entry
488 that we care about: a function or data symbol. */
489
490static int
491macho_defined_symbol (uint8_t type)
492{
493 if ((type & MACH_O_N_STAB) != 0)
494 return 0;
495 if ((type & MACH_O_N_EXT) != 0)
496 return 0;
497 switch (type & MACH_O_N_TYPE)
498 {
499 case MACH_O_N_ABS:
500 return 1;
501 case MACH_O_N_SECT:
502 return 1;
503 default:
504 return 0;
505 }
506}
507
508/* Add symbol table information for a Mach-O file. */
509
510static int
511macho_add_symtab (struct backtrace_state *state, int descriptor,
512 uintptr_t base_address, int is_64,
513 off_t symoff, unsigned int nsyms, off_t stroff,
514 unsigned int strsize,
515 backtrace_error_callback error_callback, void *data)
516{
517 size_t symsize;
518 struct backtrace_view sym_view;
519 int sym_view_valid;
520 struct backtrace_view str_view;
521 int str_view_valid;
522 size_t ndefs;
523 size_t symtaboff;
524 unsigned int i;
525 size_t macho_symbol_size;
526 struct macho_symbol *macho_symbols;
527 unsigned int j;
528 struct macho_syminfo_data *sdata;
529
530 sym_view_valid = 0;
531 str_view_valid = 0;
532 macho_symbol_size = 0;
533 macho_symbols = NULL;
534
535 if (is_64)
536 symsize = sizeof (struct macho_nlist_64);
537 else
538 symsize = sizeof (struct macho_nlist);
539
540 if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,
541 error_callback, data, &sym_view))
542 goto fail;
543 sym_view_valid = 1;
544
545 if (!backtrace_get_view (state, descriptor, stroff, strsize,
546 error_callback, data, &str_view))
547 return 0;
548 str_view_valid = 1;
549
550 ndefs = 0;
551 symtaboff = 0;
552 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
553 {
554 if (is_64)
555 {
556 struct macho_nlist_64 nlist;
557
558 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
559 sizeof nlist);
560 if (macho_defined_symbol (nlist.n_type))
561 ++ndefs;
562 }
563 else
564 {
565 struct macho_nlist nlist;
566
567 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
568 sizeof nlist);
569 if (macho_defined_symbol (nlist.n_type))
570 ++ndefs;
571 }
572 }
573
574 /* Add 1 to ndefs to make room for a sentinel. */
575 macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);
576 macho_symbols = ((struct macho_symbol *)
577 backtrace_alloc (state, macho_symbol_size, error_callback,
578 data));
579 if (macho_symbols == NULL)
580 goto fail;
581
582 j = 0;
583 symtaboff = 0;
584 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
585 {
586 uint32_t strx;
587 uint64_t value;
588 const char *name;
589
590 strx = 0;
591 value = 0;
592 if (is_64)
593 {
594 struct macho_nlist_64 nlist;
595
596 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
597 sizeof nlist);
598 if (!macho_defined_symbol (nlist.n_type))
599 continue;
600
601 strx = nlist.n_strx;
602 value = nlist.n_value;
603 }
604 else
605 {
606 struct macho_nlist nlist;
607
608 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
609 sizeof nlist);
610 if (!macho_defined_symbol (nlist.n_type))
611 continue;
612
613 strx = nlist.n_strx;
614 value = nlist.n_value;
615 }
616
617 if (strx >= strsize)
618 {
619 error_callback (data, "symbol string index out of range", 0);
620 goto fail;
621 }
622
623 name = (const char *) str_view.data + strx;
624 if (name[0] == '_')
625 ++name;
626 macho_symbols[j].name = name;
627 macho_symbols[j].address = value + base_address;
628 ++j;
629 }
630
631 sdata = ((struct macho_syminfo_data *)
632 backtrace_alloc (state, sizeof *sdata, error_callback, data));
633 if (sdata == NULL)
634 goto fail;
635
636 /* We need to keep the string table since it holds the names, but we
637 can release the symbol table. */
638
639 backtrace_release_view (state, &sym_view, error_callback, data);
640 sym_view_valid = 0;
641 str_view_valid = 0;
642
643 /* Add a trailing sentinel symbol. */
644 macho_symbols[j].name = "";
645 macho_symbols[j].address = ~(uintptr_t) 0;
646
647 backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),
648 macho_symbol_compare);
649
650 sdata->next = NULL;
651 sdata->symbols = macho_symbols;
652 sdata->count = ndefs;
653
654 if (!state->threaded)
655 {
656 struct macho_syminfo_data **pp;
657
658 for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
659 *pp != NULL;
660 pp = &(*pp)->next)
661 ;
662 *pp = sdata;
663 }
664 else
665 {
666 while (1)
667 {
668 struct macho_syminfo_data **pp;
669
670 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
671
672 while (1)
673 {
674 struct macho_syminfo_data *p;
675
676 p = backtrace_atomic_load_pointer (pp);
677
678 if (p == NULL)
679 break;
680
681 pp = &p->next;
682 }
683
684 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
685 break;
686 }
687 }
688
689 return 1;
690
691 fail:
692 if (macho_symbols != NULL)
693 backtrace_free (state, macho_symbols, macho_symbol_size,
694 error_callback, data);
695 if (sym_view_valid)
696 backtrace_release_view (state, &sym_view, error_callback, data);
697 if (str_view_valid)
698 backtrace_release_view (state, &str_view, error_callback, data);
699 return 0;
700}
701
702/* Return the symbol name and value for an ADDR. */
703
704static void
705macho_syminfo (struct backtrace_state *state, uintptr_t addr,
706 backtrace_syminfo_callback callback,
707 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
708 void *data)
709{
710 struct macho_syminfo_data *sdata;
711 struct macho_symbol *sym;
712
713 sym = NULL;
714 if (!state->threaded)
715 {
716 for (sdata = (struct macho_syminfo_data *) state->syminfo_data;
717 sdata != NULL;
718 sdata = sdata->next)
719 {
720 sym = ((struct macho_symbol *)
721 bsearch (&addr, sdata->symbols, sdata->count,
722 sizeof (struct macho_symbol), macho_symbol_search));
723 if (sym != NULL)
724 break;
725 }
726 }
727 else
728 {
729 struct macho_syminfo_data **pp;
730
731 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
732 while (1)
733 {
734 sdata = backtrace_atomic_load_pointer (pp);
735 if (sdata == NULL)
736 break;
737
738 sym = ((struct macho_symbol *)
739 bsearch (&addr, sdata->symbols, sdata->count,
740 sizeof (struct macho_symbol), macho_symbol_search));
741 if (sym != NULL)
742 break;
743
744 pp = &sdata->next;
745 }
746 }
747
748 if (sym == NULL)
749 callback (data, addr, NULL, 0, 0);
750 else
751 callback (data, addr, sym->name, sym->address, 0);
752}
753
754/* Look through a fat file to find the relevant executable. Returns 1
755 on success, 0 on failure (in both cases descriptor is closed). */
756
757static int
758macho_add_fat (struct backtrace_state *state, const char *filename,
759 int descriptor, int swapped, off_t offset,
760 const unsigned char *match_uuid, uintptr_t base_address,
74c176ca 761 int skip_symtab, uint32_t nfat_arch, int is_64,
dea40c94
ILT
762 backtrace_error_callback error_callback, void *data,
763 fileline *fileline_fn, int *found_sym)
764{
765 int arch_view_valid;
766 unsigned int cputype;
74c176ca 767 size_t arch_size;
dea40c94 768 struct backtrace_view arch_view;
dea40c94
ILT
769 unsigned int i;
770
771 arch_view_valid = 0;
772
773#if defined (__x86_64__)
774 cputype = MACH_O_CPU_TYPE_X86_64;
775#elif defined (__i386__)
776 cputype = MACH_O_CPU_TYPE_X86;
777#elif defined (__aarch64__)
778 cputype = MACH_O_CPU_TYPE_ARM64;
779#elif defined (__arm__)
780 cputype = MACH_O_CPU_TYPE_ARM;
d1339b51
IS
781#elif defined (__ppc__)
782 cputype = MACH_O_CPU_TYPE_PPC;
783#elif defined (__ppc64__)
784 cputype = MACH_O_CPU_TYPE_PPC64;
dea40c94
ILT
785#else
786 error_callback (data, "unknown Mach-O architecture", 0);
787 goto fail;
788#endif
789
74c176ca
ILT
790 if (is_64)
791 arch_size = sizeof (struct macho_fat_arch_64);
792 else
793 arch_size = sizeof (struct macho_fat_arch);
794
dea40c94 795 if (!backtrace_get_view (state, descriptor, offset,
74c176ca 796 nfat_arch * arch_size,
dea40c94
ILT
797 error_callback, data, &arch_view))
798 goto fail;
799
dea40c94
ILT
800 for (i = 0; i < nfat_arch; ++i)
801 {
dea40c94 802 uint32_t fcputype;
488e3333 803 uint64_t foffset;
dea40c94 804
74c176ca 805 if (is_64)
488e3333
ILT
806 {
807 struct macho_fat_arch_64 fat_arch_64;
808
809 memcpy (&fat_arch_64,
810 (const char *) arch_view.data + i * arch_size,
811 arch_size);
812 fcputype = fat_arch_64.cputype;
813 foffset = fat_arch_64.offset;
814 if (swapped)
815 {
816 fcputype = __builtin_bswap32 (fcputype);
817 foffset = __builtin_bswap64 (foffset);
818 }
819 }
74c176ca
ILT
820 else
821 {
822 struct macho_fat_arch fat_arch_32;
823
824 memcpy (&fat_arch_32,
825 (const char *) arch_view.data + i * arch_size,
826 arch_size);
488e3333
ILT
827 fcputype = fat_arch_32.cputype;
828 foffset = (uint64_t) fat_arch_32.offset;
829 if (swapped)
830 {
831 fcputype = __builtin_bswap32 (fcputype);
832 foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);
833 }
74c176ca 834 }
dea40c94 835
dea40c94
ILT
836 if (fcputype == cputype)
837 {
dea40c94 838 /* FIXME: What about cpusubtype? */
dea40c94
ILT
839 backtrace_release_view (state, &arch_view, error_callback, data);
840 return macho_add (state, filename, descriptor, foffset, match_uuid,
841 base_address, skip_symtab, error_callback, data,
842 fileline_fn, found_sym);
843 }
dea40c94
ILT
844 }
845
846 error_callback (data, "could not find executable in fat file", 0);
847
848 fail:
849 if (arch_view_valid)
850 backtrace_release_view (state, &arch_view, error_callback, data);
851 if (descriptor != -1)
852 backtrace_close (descriptor, error_callback, data);
853 return 0;
854}
855
856/* Look for the dsym file for FILENAME. This is called if FILENAME
857 does not have debug info or a symbol table. Returns 1 on success,
858 0 on failure. */
859
860static int
861macho_add_dsym (struct backtrace_state *state, const char *filename,
862 uintptr_t base_address, const unsigned char *uuid,
863 backtrace_error_callback error_callback, void *data,
864 fileline* fileline_fn)
865{
866 const char *p;
867 const char *dirname;
868 char *diralc;
869 size_t dirnamelen;
870 const char *basename;
871 size_t basenamelen;
872 const char *dsymsuffixdir;
873 size_t dsymsuffixdirlen;
874 size_t dsymlen;
875 char *dsym;
876 char *ps;
877 int d;
878 int does_not_exist;
879 int dummy_found_sym;
880
881 diralc = NULL;
882 dirnamelen = 0;
883 dsym = NULL;
884 dsymlen = 0;
885
886 p = strrchr (filename, '/');
887 if (p == NULL)
888 {
889 dirname = ".";
890 dirnamelen = 1;
891 basename = filename;
892 basenamelen = strlen (basename);
893 diralc = NULL;
894 }
895 else
896 {
897 dirnamelen = p - filename;
898 diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);
899 if (diralc == NULL)
900 goto fail;
901 memcpy (diralc, filename, dirnamelen);
902 diralc[dirnamelen] = '\0';
903 dirname = diralc;
904 basename = p + 1;
905 basenamelen = strlen (basename);
906 }
907
908 dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";
909 dsymsuffixdirlen = strlen (dsymsuffixdir);
910
911 dsymlen = (dirnamelen
a8a7a97b 912 + 1
dea40c94
ILT
913 + basenamelen
914 + dsymsuffixdirlen
915 + basenamelen
916 + 1);
917 dsym = backtrace_alloc (state, dsymlen, error_callback, data);
918 if (dsym == NULL)
919 goto fail;
920
921 ps = dsym;
922 memcpy (ps, dirname, dirnamelen);
923 ps += dirnamelen;
924 *ps++ = '/';
925 memcpy (ps, basename, basenamelen);
926 ps += basenamelen;
927 memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
928 ps += dsymsuffixdirlen;
929 memcpy (ps, basename, basenamelen);
930 ps += basenamelen;
931 *ps = '\0';
932
933 if (diralc != NULL)
934 {
a8a7a97b 935 backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);
dea40c94
ILT
936 diralc = NULL;
937 }
938
939 d = backtrace_open (dsym, error_callback, data, &does_not_exist);
940 if (d < 0)
941 {
942 /* The file does not exist, so we can't read the debug info.
943 Just return success. */
944 backtrace_free (state, dsym, dsymlen, error_callback, data);
945 return 1;
946 }
947
948 if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,
949 error_callback, data, fileline_fn, &dummy_found_sym))
950 goto fail;
951
952 backtrace_free (state, dsym, dsymlen, error_callback, data);
953
954 return 1;
955
956 fail:
957 if (dsym != NULL)
958 backtrace_free (state, dsym, dsymlen, error_callback, data);
959 if (diralc != NULL)
960 backtrace_free (state, diralc, dirnamelen, error_callback, data);
961 return 0;
962}
963
964/* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
965 on failure (in both cases descriptor is closed).
966
967 FILENAME: the name of the executable.
968 DESCRIPTOR: an open descriptor for the executable, closed here.
969 OFFSET: the offset within the file of this executable, for fat files.
970 MATCH_UUID: if not NULL, UUID that must match.
971 BASE_ADDRESS: the load address of the executable.
972 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
973 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
974 FOUND_SYM: set to non-zero if we found the symbol table.
975*/
976
977static int
978macho_add (struct backtrace_state *state, const char *filename, int descriptor,
979 off_t offset, const unsigned char *match_uuid,
980 uintptr_t base_address, int skip_symtab,
981 backtrace_error_callback error_callback, void *data,
982 fileline *fileline_fn, int *found_sym)
983{
984 struct backtrace_view header_view;
985 struct macho_header_32 header;
986 off_t hdroffset;
987 int is_64;
988 struct backtrace_view cmds_view;
989 int cmds_view_valid;
990 struct dwarf_sections dwarf_sections;
991 int have_dwarf;
992 unsigned char uuid[MACH_O_UUID_LEN];
993 int have_uuid;
994 size_t cmdoffset;
995 unsigned int i;
996
997 *found_sym = 0;
998
999 cmds_view_valid = 0;
1000
1001 /* The 32-bit and 64-bit file headers start out the same, so we can
1002 just always read the 32-bit version. A fat header is shorter but
1003 it will always be followed by data, so it's OK to read extra. */
1004
1005 if (!backtrace_get_view (state, descriptor, offset,
1006 sizeof (struct macho_header_32),
1007 error_callback, data, &header_view))
1008 goto fail;
1009
1010 memcpy (&header, header_view.data, sizeof header);
1011
1012 backtrace_release_view (state, &header_view, error_callback, data);
1013
1014 switch (header.magic)
1015 {
1016 case MACH_O_MH_MAGIC_32:
1017 is_64 = 0;
1018 hdroffset = offset + sizeof (struct macho_header_32);
1019 break;
1020 case MACH_O_MH_MAGIC_64:
1021 is_64 = 1;
1022 hdroffset = offset + sizeof (struct macho_header_64);
1023 break;
1024 case MACH_O_MH_MAGIC_FAT:
74c176ca 1025 case MACH_O_MH_MAGIC_FAT_64:
dea40c94
ILT
1026 {
1027 struct macho_header_fat fat_header;
1028
1029 hdroffset = offset + sizeof (struct macho_header_fat);
1030 memcpy (&fat_header, &header, sizeof fat_header);
1031 return macho_add_fat (state, filename, descriptor, 0, hdroffset,
1032 match_uuid, base_address, skip_symtab,
74c176ca
ILT
1033 fat_header.nfat_arch,
1034 header.magic == MACH_O_MH_MAGIC_FAT_64,
1035 error_callback, data, fileline_fn, found_sym);
dea40c94
ILT
1036 }
1037 case MACH_O_MH_CIGAM_FAT:
74c176ca 1038 case MACH_O_MH_CIGAM_FAT_64:
dea40c94
ILT
1039 {
1040 struct macho_header_fat fat_header;
1041 uint32_t nfat_arch;
1042
1043 hdroffset = offset + sizeof (struct macho_header_fat);
1044 memcpy (&fat_header, &header, sizeof fat_header);
1045 nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
1046 return macho_add_fat (state, filename, descriptor, 1, hdroffset,
1047 match_uuid, base_address, skip_symtab,
74c176ca
ILT
1048 nfat_arch,
1049 header.magic == MACH_O_MH_CIGAM_FAT_64,
1050 error_callback, data, fileline_fn, found_sym);
dea40c94
ILT
1051 }
1052 default:
1053 error_callback (data, "executable file is not in Mach-O format", 0);
1054 goto fail;
1055 }
1056
1057 switch (header.filetype)
1058 {
1059 case MACH_O_MH_EXECUTE:
1060 case MACH_O_MH_DYLIB:
1061 case MACH_O_MH_DSYM:
1062 break;
1063 default:
1064 error_callback (data, "executable file is not an executable", 0);
1065 goto fail;
1066 }
1067
1068 if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,
1069 error_callback, data, &cmds_view))
1070 goto fail;
1071 cmds_view_valid = 1;
1072
1073 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1074 have_dwarf = 0;
1075 memset (&uuid, 0, sizeof uuid);
1076 have_uuid = 0;
1077
1078 cmdoffset = 0;
1079 for (i = 0; i < header.ncmds; ++i)
1080 {
1081 const char *pcmd;
1082 struct macho_load_command load_command;
1083
1084 if (cmdoffset + sizeof load_command > header.sizeofcmds)
1085 break;
1086
1087 pcmd = (const char *) cmds_view.data + cmdoffset;
1088 memcpy (&load_command, pcmd, sizeof load_command);
1089
1090 switch (load_command.cmd)
1091 {
1092 case MACH_O_LC_SEGMENT:
1093 {
1094 struct macho_segment_command segcmd;
1095
1096 memcpy (&segcmd, pcmd, sizeof segcmd);
1097 if (memcmp (segcmd.segname,
1098 "__DWARF\0\0\0\0\0\0\0\0\0",
1099 MACH_O_NAMELEN) == 0)
1100 {
1101 if (!macho_add_dwarf_segment (state, descriptor, offset,
1102 load_command.cmd,
1103 pcmd + sizeof segcmd,
1104 (load_command.cmdsize
1105 - sizeof segcmd),
1106 segcmd.nsects, error_callback,
1107 data, &dwarf_sections))
1108 goto fail;
1109 have_dwarf = 1;
1110 }
1111 }
1112 break;
1113
1114 case MACH_O_LC_SEGMENT_64:
1115 {
1116 struct macho_segment_64_command segcmd;
1117
1118 memcpy (&segcmd, pcmd, sizeof segcmd);
1119 if (memcmp (segcmd.segname,
1120 "__DWARF\0\0\0\0\0\0\0\0\0",
1121 MACH_O_NAMELEN) == 0)
1122 {
1123 if (!macho_add_dwarf_segment (state, descriptor, offset,
1124 load_command.cmd,
1125 pcmd + sizeof segcmd,
1126 (load_command.cmdsize
1127 - sizeof segcmd),
1128 segcmd.nsects, error_callback,
1129 data, &dwarf_sections))
1130 goto fail;
1131 have_dwarf = 1;
1132 }
1133 }
1134 break;
1135
1136 case MACH_O_LC_SYMTAB:
1137 if (!skip_symtab)
1138 {
1139 struct macho_symtab_command symcmd;
1140
1141 memcpy (&symcmd, pcmd, sizeof symcmd);
1142 if (!macho_add_symtab (state, descriptor, base_address, is_64,
1143 offset + symcmd.symoff, symcmd.nsyms,
1144 offset + symcmd.stroff, symcmd.strsize,
1145 error_callback, data))
1146 goto fail;
1147
1148 *found_sym = 1;
1149 }
1150 break;
1151
1152 case MACH_O_LC_UUID:
1153 {
1154 struct macho_uuid_command uuidcmd;
1155
1156 memcpy (&uuidcmd, pcmd, sizeof uuidcmd);
1157 memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);
1158 have_uuid = 1;
1159 }
1160 break;
1161
1162 default:
1163 break;
1164 }
1165
1166 cmdoffset += load_command.cmdsize;
1167 }
1168
1169 if (!backtrace_close (descriptor, error_callback, data))
1170 goto fail;
1171 descriptor = -1;
1172
1173 backtrace_release_view (state, &cmds_view, error_callback, data);
1174 cmds_view_valid = 0;
1175
1176 if (match_uuid != NULL)
1177 {
1178 /* If we don't have a UUID, or it doesn't match, just ignore
1179 this file. */
1180 if (!have_uuid
1181 || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)
1182 return 1;
1183 }
1184
1185 if (have_dwarf)
1186 {
1187 int is_big_endian;
1188
1189 is_big_endian = 0;
1190#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1191#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1192 is_big_endian = 1;
1193#endif
1194#endif
1195
1196 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1197 is_big_endian, NULL, error_callback, data,
1198 fileline_fn, NULL))
1199 goto fail;
1200 }
1201
1202 if (!have_dwarf && have_uuid)
1203 {
1204 if (!macho_add_dsym (state, filename, base_address, &uuid[0],
1205 error_callback, data, fileline_fn))
1206 goto fail;
1207 }
1208
1209 return 1;
1210
1211 fail:
1212 if (cmds_view_valid)
1213 backtrace_release_view (state, &cmds_view, error_callback, data);
1214 if (descriptor != -1)
1215 backtrace_close (descriptor, error_callback, data);
1216 return 0;
1217}
1218
1219#ifdef HAVE_MACH_O_DYLD_H
1220
1221/* Initialize the backtrace data we need from a Mach-O executable
1222 using the dyld support functions. This closes descriptor. */
1223
1224int
1225backtrace_initialize (struct backtrace_state *state, const char *filename,
1226 int descriptor, backtrace_error_callback error_callback,
1227 void *data, fileline *fileline_fn)
1228{
1229 uint32_t c;
1230 uint32_t i;
1231 int closed_descriptor;
1232 int found_sym;
1233 fileline macho_fileline_fn;
1234
1235 closed_descriptor = 0;
1236 found_sym = 0;
1237 macho_fileline_fn = macho_nodebug;
1238
1239 c = _dyld_image_count ();
1240 for (i = 0; i < c; ++i)
1241 {
1242 uintptr_t base_address;
1243 const char *name;
1244 int d;
1245 fileline mff;
1246 int mfs;
1247
1248 name = _dyld_get_image_name (i);
1249 if (name == NULL)
1250 continue;
1251
1252 if (strcmp (name, filename) == 0 && !closed_descriptor)
1253 {
1254 d = descriptor;
1255 closed_descriptor = 1;
1256 }
1257 else
1258 {
1259 int does_not_exist;
1260
1261 d = backtrace_open (name, error_callback, data, &does_not_exist);
1262 if (d < 0)
1263 continue;
1264 }
1265
1266 base_address = _dyld_get_image_vmaddr_slide (i);
1267
1268 mff = macho_nodebug;
1269 if (!macho_add (state, name, d, 0, NULL, base_address, 0,
1270 error_callback, data, &mff, &mfs))
d8ddf1fa 1271 continue;
dea40c94
ILT
1272
1273 if (mff != macho_nodebug)
1274 macho_fileline_fn = mff;
1275 if (mfs)
1276 found_sym = 1;
1277 }
1278
1279 if (!closed_descriptor)
1280 backtrace_close (descriptor, error_callback, data);
1281
1282 if (!state->threaded)
1283 {
1284 if (found_sym)
1285 state->syminfo_fn = macho_syminfo;
1286 else if (state->syminfo_fn == NULL)
1287 state->syminfo_fn = macho_nosyms;
1288 }
1289 else
1290 {
1291 if (found_sym)
1292 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1293 else
1294 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1295 macho_nosyms);
1296 }
1297
1298 if (!state->threaded)
1299 *fileline_fn = state->fileline_fn;
1300 else
1301 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1302
1303 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1304 *fileline_fn = macho_fileline_fn;
1305
1306 return 1;
1307}
1308
1309#else /* !defined (HAVE_MACH_O_DYLD_H) */
1310
1311/* Initialize the backtrace data we need from a Mach-O executable
1312 without using the dyld support functions. This closes
1313 descriptor. */
1314
1315int
1316backtrace_initialize (struct backtrace_state *state, const char *filename,
1317 int descriptor, backtrace_error_callback error_callback,
1318 void *data, fileline *fileline_fn)
1319{
1320 fileline macho_fileline_fn;
1321 int found_sym;
1322
1323 macho_fileline_fn = macho_nodebug;
1324 if (!macho_add (state, filename, descriptor, 0, NULL, 0, 0,
1325 error_callback, data, &macho_fileline_fn, &found_sym))
1326 return 0;
1327
1328 if (!state->threaded)
1329 {
1330 if (found_sym)
1331 state->syminfo_fn = macho_syminfo;
1332 else if (state->syminfo_fn == NULL)
1333 state->syminfo_fn = macho_nosyms;
1334 }
1335 else
1336 {
1337 if (found_sym)
1338 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1339 else
1340 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1341 macho_nosyms);
1342 }
1343
1344 if (!state->threaded)
1345 *fileline_fn = state->fileline_fn;
1346 else
1347 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1348
1349 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1350 *fileline_fn = macho_fileline_fn;
1351
1352 return 1;
1353}
1354
1355#endif /* !defined (HAVE_MACH_O_DYLD_H) */