The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
macho.c
Go to the documentation of this file.
1/* elf.c -- Get debug data from a Mach-O file for backtraces.
2 Copyright (C) 2020-2024 Free Software Foundation, Inc.
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
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
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
77{
78 uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */
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
88#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf
89#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca
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
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
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
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
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
131#define MACH_O_CPU_TYPE_PPC 18
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)
135#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)
136
137/* The header of a load command. */
138
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
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
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
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
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
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 */
230};
231
232/* 64-bit section header within a LC_SEGMENT_64 segment. */
233
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 */
248};
249
250/* 32-bit symbol data. */
251
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
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_STAB 0xe0 /* Stabs debugging symbol */
275#define MACH_O_N_TYPE 0x0e /* Mask for type bits */
276
277/* Values found after masking with MACH_O_N_TYPE. */
278#define MACH_O_N_UNDF 0x00 /* Undefined symbol */
279#define MACH_O_N_ABS 0x02 /* Absolute symbol */
280#define MACH_O_N_SECT 0x0e /* Defined in section from n_sect field */
281
282
283/* Information we keep for a Mach-O symbol. */
284
286{
287 const char *name; /* Symbol name */
288 uintptr_t address; /* Symbol address */
289};
290
291/* Information to pass to macho_syminfo. */
292
294{
295 struct macho_syminfo_data *next; /* Next module */
296 struct macho_symbol *symbols; /* Symbols sorted by address */
297 size_t count; /* Number of symbols */
298};
299
300/* Names of sections, indexed by enum dwarf_section in internal.h. */
301
302static const char * const dwarf_section_names[DEBUG_MAX] =
303{
304 "__debug_info",
305 "__debug_line",
306 "__debug_abbrev",
307 "__debug_ranges",
308 "__debug_str",
309 "__debug_addr",
310 "__debug_str_offs",
311 "__debug_line_str",
312 "__debug_rnglists"
313};
314
315/* Forward declaration. */
316
317static int macho_add (struct backtrace_state *, const char *, int, off_t,
318 const unsigned char *, struct libbacktrace_base_address,
319 int, backtrace_error_callback, void *, fileline *,
320 int *);
321
322/* A dummy callback function used when we can't find any debug info. */
323
324static int
326 uintptr_t pc ATTRIBUTE_UNUSED,
329{
330 error_callback (data, "no debug info in Mach-O executable (make sure to compile with -g; may need to run dsymutil)", -1);
331 return 0;
332}
333
334/* A dummy callback function used when we can't find a symbol
335 table. */
336
337static void
339 uintptr_t addr ATTRIBUTE_UNUSED,
342{
343 error_callback (data, "no symbol table in Mach-O executable", -1);
344}
345
346/* Add a single DWARF section to DWARF_SECTIONS, if we need the
347 section. Returns 1 on success, 0 on failure. */
348
349static int
351 const char *sectname, uint32_t offset, uint64_t size,
354{
355 int i;
356
357 for (i = 0; i < (int) DEBUG_MAX; ++i)
358 {
359 if (dwarf_section_names[i][0] != '\0'
360 && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)
361 {
362 struct backtrace_view section_view;
363
364 /* FIXME: Perhaps it would be better to try to use a single
365 view to read all the DWARF data, as we try to do for
366 ELF. */
367
368 if (!backtrace_get_view (state, descriptor, offset, size,
369 error_callback, data, &section_view))
370 return 0;
371 dwarf_sections->data[i] = (const unsigned char *) section_view.data;
372 dwarf_sections->size[i] = size;
373 break;
374 }
375 }
376 return 1;
377}
378
379/* Collect DWARF sections from a DWARF segment. Returns 1 on success,
380 0 on failure. */
381
382static int
384 off_t offset, unsigned int cmd, const char *psecs,
385 size_t sizesecs, unsigned int nsects,
388{
389 size_t sec_header_size;
390 size_t secoffset;
391 unsigned int i;
392
393 switch (cmd)
394 {
396 sec_header_size = sizeof (struct macho_section);
397 break;
399 sec_header_size = sizeof (struct macho_section_64);
400 break;
401 default:
402 abort ();
403 }
404
405 secoffset = 0;
406 for (i = 0; i < nsects; ++i)
407 {
408 if (secoffset + sec_header_size > sizesecs)
409 {
410 error_callback (data, "section overflow withing segment", 0);
411 return 0;
412 }
413
414 switch (cmd)
415 {
417 {
418 struct macho_section section;
419
420 memcpy (&section, psecs + secoffset, sizeof section);
421 macho_add_dwarf_section (state, descriptor, section.sectname,
422 offset + section.offset, section.size,
424 }
425 break;
426
428 {
429 struct macho_section_64 section;
430
431 memcpy (&section, psecs + secoffset, sizeof section);
432 macho_add_dwarf_section (state, descriptor, section.sectname,
433 offset + section.offset, section.size,
435 }
436 break;
437
438 default:
439 abort ();
440 }
441
442 secoffset += sec_header_size;
443 }
444
445 return 1;
446}
447
448/* Compare struct macho_symbol for qsort. */
449
450static int
451macho_symbol_compare (const void *v1, const void *v2)
452{
453 const struct macho_symbol *m1 = (const struct macho_symbol *) v1;
454 const struct macho_symbol *m2 = (const struct macho_symbol *) v2;
455
456 if (m1->address < m2->address)
457 return -1;
458 else if (m1->address > m2->address)
459 return 1;
460 else
461 return 0;
462}
463
464/* Compare an address against a macho_symbol for bsearch. We allocate
465 one extra entry in the array so that this can safely look at the
466 next entry. */
467
468static int
469macho_symbol_search (const void *vkey, const void *ventry)
470{
471 const uintptr_t *key = (const uintptr_t *) vkey;
472 const struct macho_symbol *entry = (const struct macho_symbol *) ventry;
473 uintptr_t addr;
474
475 addr = *key;
476 if (addr < entry->address)
477 return -1;
478 else if (entry->name[0] == '\0'
479 && entry->address == ~(uintptr_t) 0)
480 return -1;
481 else if ((entry + 1)->name[0] == '\0'
482 && (entry + 1)->address == ~(uintptr_t) 0)
483 return -1;
484 else if (addr >= (entry + 1)->address)
485 return 1;
486 else
487 return 0;
488}
489
490/* Return whether the symbol type field indicates a symbol table entry
491 that we care about: a function or data symbol. */
492
493static int
495{
496 if ((type & MACH_O_N_STAB) != 0)
497 return 0;
498 switch (type & MACH_O_N_TYPE)
499 {
500 case MACH_O_N_UNDF:
501 return 0;
502 case MACH_O_N_ABS:
503 return 1;
504 case MACH_O_N_SECT:
505 return 1;
506 default:
507 return 0;
508 }
509}
510
511/* Add symbol table information for a Mach-O file. */
512
513static int
514macho_add_symtab (struct backtrace_state *state, int descriptor,
515 struct libbacktrace_base_address base_address, int is_64,
516 off_t symoff, unsigned int nsyms, off_t stroff,
517 unsigned int strsize,
519{
520 size_t symsize;
521 struct backtrace_view sym_view;
522 int sym_view_valid;
523 struct backtrace_view str_view;
524 int str_view_valid;
525 size_t ndefs;
526 size_t symtaboff;
527 unsigned int i;
528 size_t macho_symbol_size;
529 struct macho_symbol *macho_symbols;
530 unsigned int j;
532
533 sym_view_valid = 0;
534 str_view_valid = 0;
535 macho_symbol_size = 0;
536 macho_symbols = NULL;
537
538 if (is_64)
539 symsize = sizeof (struct macho_nlist_64);
540 else
541 symsize = sizeof (struct macho_nlist);
542
543 if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,
544 error_callback, data, &sym_view))
545 goto fail;
546 sym_view_valid = 1;
547
548 if (!backtrace_get_view (state, descriptor, stroff, strsize,
549 error_callback, data, &str_view))
550 return 0;
551 str_view_valid = 1;
552
553 ndefs = 0;
554 symtaboff = 0;
555 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
556 {
557 if (is_64)
558 {
559 struct macho_nlist_64 nlist;
560
561 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
562 sizeof nlist);
563 if (macho_defined_symbol (nlist.n_type))
564 ++ndefs;
565 }
566 else
567 {
568 struct macho_nlist nlist;
569
570 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
571 sizeof nlist);
572 if (macho_defined_symbol (nlist.n_type))
573 ++ndefs;
574 }
575 }
576
577 /* Add 1 to ndefs to make room for a sentinel. */
578 macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);
579 macho_symbols = ((struct macho_symbol *)
580 backtrace_alloc (state, macho_symbol_size, error_callback,
581 data));
582 if (macho_symbols == NULL)
583 goto fail;
584
585 j = 0;
586 symtaboff = 0;
587 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
588 {
589 uint32_t strx;
590 uint64_t value;
591 const char *name;
592
593 strx = 0;
594 value = 0;
595 if (is_64)
596 {
597 struct macho_nlist_64 nlist;
598
599 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
600 sizeof nlist);
601 if (!macho_defined_symbol (nlist.n_type))
602 continue;
603
604 strx = nlist.n_strx;
605 value = nlist.n_value;
606 }
607 else
608 {
609 struct macho_nlist nlist;
610
611 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
612 sizeof nlist);
613 if (!macho_defined_symbol (nlist.n_type))
614 continue;
615
616 strx = nlist.n_strx;
617 value = nlist.n_value;
618 }
619
620 if (strx >= strsize)
621 {
622 error_callback (data, "symbol string index out of range", 0);
623 goto fail;
624 }
625
626 name = (const char *) str_view.data + strx;
627 if (name[0] == '_')
628 ++name;
629 macho_symbols[j].name = name;
630 macho_symbols[j].address = libbacktrace_add_base (value, base_address);
631 ++j;
632 }
633
634 sdata = ((struct macho_syminfo_data *)
636 if (sdata == NULL)
637 goto fail;
638
639 /* We need to keep the string table since it holds the names, but we
640 can release the symbol table. */
641
643 sym_view_valid = 0;
644 str_view_valid = 0;
645
646 /* Add a trailing sentinel symbol. */
647 macho_symbols[j].name = "";
648 macho_symbols[j].address = ~(uintptr_t) 0;
649
650 backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),
652
653 sdata->next = NULL;
654 sdata->symbols = macho_symbols;
655 sdata->count = ndefs;
656
657 if (!state->threaded)
658 {
659 struct macho_syminfo_data **pp;
660
661 for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
662 *pp != NULL;
663 pp = &(*pp)->next)
664 ;
665 *pp = sdata;
666 }
667 else
668 {
669 while (1)
670 {
671 struct macho_syminfo_data **pp;
672
673 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
674
675 while (1)
676 {
677 struct macho_syminfo_data *p;
678
680 if (p == NULL)
681 break;
682
683 pp = &p->next;
684 }
685
686 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
687 break;
688 }
689 }
690
691 return 1;
692
693 fail:
694 if (macho_symbols != NULL)
695 backtrace_free (state, macho_symbols, macho_symbol_size,
697 if (sym_view_valid)
699 if (str_view_valid)
701 return 0;
702}
703
704/* Return the symbol name and value for an ADDR. */
705
706static void
707macho_syminfo (struct backtrace_state *state, uintptr_t addr,
710 void *data)
711{
713 struct macho_symbol *sym;
714
715 sym = NULL;
716 if (!state->threaded)
717 {
718 for (sdata = (struct macho_syminfo_data *) state->syminfo_data;
719 sdata != NULL;
720 sdata = sdata->next)
721 {
722 sym = ((struct macho_symbol *)
723 bsearch (&addr, sdata->symbols, sdata->count,
724 sizeof (struct macho_symbol), macho_symbol_search));
725 if (sym != NULL)
726 break;
727 }
728 }
729 else
730 {
731 struct macho_syminfo_data **pp;
732
733 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
734 while (1)
735 {
737 if (sdata == NULL)
738 break;
739
740 sym = ((struct macho_symbol *)
741 bsearch (&addr, sdata->symbols, sdata->count,
742 sizeof (struct macho_symbol), macho_symbol_search));
743 if (sym != NULL)
744 break;
745
746 pp = &sdata->next;
747 }
748 }
749
750 if (sym == NULL)
751 callback (data, addr, NULL, 0, 0);
752 else
753 callback (data, addr, sym->name, sym->address, 0);
754}
755
756/* Look through a fat file to find the relevant executable. Returns 1
757 on success, 0 on failure (in both cases descriptor is closed). */
758
759static int
760macho_add_fat (struct backtrace_state *state, const char *filename,
761 int descriptor, int swapped, off_t offset,
762 const unsigned char *match_uuid,
763 struct libbacktrace_base_address base_address,
764 int skip_symtab, uint32_t nfat_arch, int is_64,
766 fileline *fileline_fn, int *found_sym)
767{
768 int arch_view_valid;
769 unsigned int cputype;
770 size_t arch_size;
771 struct backtrace_view arch_view;
772 unsigned int i;
773
774 arch_view_valid = 0;
775
776#if defined (__x86_64__)
777 cputype = MACH_O_CPU_TYPE_X86_64;
778#elif defined (__i386__)
779 cputype = MACH_O_CPU_TYPE_X86;
780#elif defined (__aarch64__)
781 cputype = MACH_O_CPU_TYPE_ARM64;
782#elif defined (__arm__)
783 cputype = MACH_O_CPU_TYPE_ARM;
784#elif defined (__ppc__)
785 cputype = MACH_O_CPU_TYPE_PPC;
786#elif defined (__ppc64__)
787 cputype = MACH_O_CPU_TYPE_PPC64;
788#else
789 error_callback (data, "unknown Mach-O architecture", 0);
790 goto fail;
791#endif
792
793 if (is_64)
794 arch_size = sizeof (struct macho_fat_arch_64);
795 else
796 arch_size = sizeof (struct macho_fat_arch);
797
798 if (!backtrace_get_view (state, descriptor, offset,
799 nfat_arch * arch_size,
800 error_callback, data, &arch_view))
801 goto fail;
802
803 for (i = 0; i < nfat_arch; ++i)
804 {
805 uint32_t fcputype;
806 uint64_t foffset;
807
808 if (is_64)
809 {
810 struct macho_fat_arch_64 fat_arch_64;
811
812 memcpy (&fat_arch_64,
813 (const char *) arch_view.data + i * arch_size,
814 arch_size);
815 fcputype = fat_arch_64.cputype;
816 foffset = fat_arch_64.offset;
817 if (swapped)
818 {
819 fcputype = __builtin_bswap32 (fcputype);
820 foffset = __builtin_bswap64 (foffset);
821 }
822 }
823 else
824 {
825 struct macho_fat_arch fat_arch_32;
826
827 memcpy (&fat_arch_32,
828 (const char *) arch_view.data + i * arch_size,
829 arch_size);
830 fcputype = fat_arch_32.cputype;
831 foffset = (uint64_t) fat_arch_32.offset;
832 if (swapped)
833 {
834 fcputype = __builtin_bswap32 (fcputype);
835 foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);
836 }
837 }
838
839 if (fcputype == cputype)
840 {
841 /* FIXME: What about cpusubtype? */
843 return macho_add (state, filename, descriptor, foffset, match_uuid,
844 base_address, skip_symtab, error_callback, data,
845 fileline_fn, found_sym);
846 }
847 }
848
849 error_callback (data, "could not find executable in fat file", 0);
850
851 fail:
852 if (arch_view_valid)
854 if (descriptor != -1)
855 backtrace_close (descriptor, error_callback, data);
856 return 0;
857}
858
859/* Look for the dsym file for FILENAME. This is called if FILENAME
860 does not have debug info or a symbol table. Returns 1 on success,
861 0 on failure. */
862
863static int
864macho_add_dsym (struct backtrace_state *state, const char *filename,
865 struct libbacktrace_base_address base_address,
866 const unsigned char *uuid,
868 fileline* fileline_fn)
869{
870 const char *p;
871 const char *dirname;
872 char *diralc;
873 size_t dirnamelen;
874 const char *basename;
875 size_t basenamelen;
876 const char *dsymsuffixdir;
877 size_t dsymsuffixdirlen;
878 size_t dsymlen;
879 char *dsym;
880 char *ps;
881 int d;
882 int does_not_exist;
883 int dummy_found_sym;
884
885 diralc = NULL;
886 dirnamelen = 0;
887 dsym = NULL;
888 dsymlen = 0;
889
890 p = strrchr (filename, '/');
891 if (p == NULL)
892 {
893 dirname = ".";
894 dirnamelen = 1;
895 basename = filename;
896 basenamelen = strlen (basename);
897 diralc = NULL;
898 }
899 else
900 {
901 dirnamelen = p - filename;
902 diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);
903 if (diralc == NULL)
904 goto fail;
905 memcpy (diralc, filename, dirnamelen);
906 diralc[dirnamelen] = '\0';
907 dirname = diralc;
908 basename = p + 1;
909 basenamelen = strlen (basename);
910 }
911
912 dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";
913 dsymsuffixdirlen = strlen (dsymsuffixdir);
914
915 dsymlen = (dirnamelen
916 + 1
917 + basenamelen
918 + dsymsuffixdirlen
919 + basenamelen
920 + 1);
921 dsym = backtrace_alloc (state, dsymlen, error_callback, data);
922 if (dsym == NULL)
923 goto fail;
924
925 ps = dsym;
926 memcpy (ps, dirname, dirnamelen);
927 ps += dirnamelen;
928 *ps++ = '/';
929 memcpy (ps, basename, basenamelen);
930 ps += basenamelen;
931 memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
932 ps += dsymsuffixdirlen;
933 memcpy (ps, basename, basenamelen);
934 ps += basenamelen;
935 *ps = '\0';
936
937 if (diralc != NULL)
938 {
939 backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);
940 diralc = NULL;
941 }
942
943 d = backtrace_open (dsym, error_callback, data, &does_not_exist);
944 if (d < 0)
945 {
946 /* The file does not exist, so we can't read the debug info.
947 Just return success. */
948 backtrace_free (state, dsym, dsymlen, error_callback, data);
949 return 1;
950 }
951
952 if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,
953 error_callback, data, fileline_fn, &dummy_found_sym))
954 goto fail;
955
956 backtrace_free (state, dsym, dsymlen, error_callback, data);
957
958 return 1;
959
960 fail:
961 if (dsym != NULL)
962 backtrace_free (state, dsym, dsymlen, error_callback, data);
963 if (diralc != NULL)
964 backtrace_free (state, diralc, dirnamelen, error_callback, data);
965 return 0;
966}
967
968/* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
969 on failure (in both cases descriptor is closed).
970
971 FILENAME: the name of the executable.
972 DESCRIPTOR: an open descriptor for the executable, closed here.
973 OFFSET: the offset within the file of this executable, for fat files.
974 MATCH_UUID: if not NULL, UUID that must match.
975 BASE_ADDRESS: the load address of the executable.
976 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
977 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
978 FOUND_SYM: set to non-zero if we found the symbol table.
979*/
980
981static int
982macho_add (struct backtrace_state *state, const char *filename, int descriptor,
983 off_t offset, const unsigned char *match_uuid,
984 struct libbacktrace_base_address base_address, int skip_symtab,
986 fileline *fileline_fn, int *found_sym)
987{
988 struct backtrace_view header_view;
989 struct macho_header_32 header;
990 off_t hdroffset;
991 int is_64;
992 struct backtrace_view cmds_view;
993 int cmds_view_valid;
995 int have_dwarf;
996 unsigned char uuid[MACH_O_UUID_LEN];
997 int have_uuid;
998 size_t cmdoffset;
999 unsigned int i;
1000
1001 *found_sym = 0;
1002
1003 cmds_view_valid = 0;
1004
1005 /* The 32-bit and 64-bit file headers start out the same, so we can
1006 just always read the 32-bit version. A fat header is shorter but
1007 it will always be followed by data, so it's OK to read extra. */
1008
1009 if (!backtrace_get_view (state, descriptor, offset,
1010 sizeof (struct macho_header_32),
1011 error_callback, data, &header_view))
1012 goto fail;
1013
1014 memcpy (&header, header_view.data, sizeof header);
1015
1017
1018 switch (header.magic)
1019 {
1020 case MACH_O_MH_MAGIC_32:
1021 is_64 = 0;
1022 hdroffset = offset + sizeof (struct macho_header_32);
1023 break;
1024 case MACH_O_MH_MAGIC_64:
1025 is_64 = 1;
1026 hdroffset = offset + sizeof (struct macho_header_64);
1027 break;
1030 {
1031 struct macho_header_fat fat_header;
1032
1033 hdroffset = offset + sizeof (struct macho_header_fat);
1034 memcpy (&fat_header, &header, sizeof fat_header);
1035 return macho_add_fat (state, filename, descriptor, 0, hdroffset,
1036 match_uuid, base_address, skip_symtab,
1037 fat_header.nfat_arch,
1038 header.magic == MACH_O_MH_MAGIC_FAT_64,
1039 error_callback, data, fileline_fn, found_sym);
1040 }
1043 {
1044 struct macho_header_fat fat_header;
1046
1047 hdroffset = offset + sizeof (struct macho_header_fat);
1048 memcpy (&fat_header, &header, sizeof fat_header);
1049 nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
1050 return macho_add_fat (state, filename, descriptor, 1, hdroffset,
1051 match_uuid, base_address, skip_symtab,
1052 nfat_arch,
1053 header.magic == MACH_O_MH_CIGAM_FAT_64,
1054 error_callback, data, fileline_fn, found_sym);
1055 }
1056 default:
1057 error_callback (data, "executable file is not in Mach-O format", 0);
1058 goto fail;
1059 }
1060
1061 switch (header.filetype)
1062 {
1063 case MACH_O_MH_EXECUTE:
1064 case MACH_O_MH_DYLIB:
1065 case MACH_O_MH_DSYM:
1066 break;
1067 default:
1068 error_callback (data, "executable file is not an executable", 0);
1069 goto fail;
1070 }
1071
1072 if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,
1073 error_callback, data, &cmds_view))
1074 goto fail;
1075 cmds_view_valid = 1;
1076
1077 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1078 have_dwarf = 0;
1079 memset (&uuid, 0, sizeof uuid);
1080 have_uuid = 0;
1081
1082 cmdoffset = 0;
1083 for (i = 0; i < header.ncmds; ++i)
1084 {
1085 const char *pcmd;
1086 struct macho_load_command load_command;
1087
1088 if (cmdoffset + sizeof load_command > header.sizeofcmds)
1089 break;
1090
1091 pcmd = (const char *) cmds_view.data + cmdoffset;
1092 memcpy (&load_command, pcmd, sizeof load_command);
1093
1094 switch (load_command.cmd)
1095 {
1096 case MACH_O_LC_SEGMENT:
1097 {
1098 struct macho_segment_command segcmd;
1099
1100 memcpy (&segcmd, pcmd, sizeof segcmd);
1101 if (memcmp (segcmd.segname,
1102 "__DWARF\0\0\0\0\0\0\0\0\0",
1103 MACH_O_NAMELEN) == 0)
1104 {
1105 if (!macho_add_dwarf_segment (state, descriptor, offset,
1106 load_command.cmd,
1107 pcmd + sizeof segcmd,
1108 (load_command.cmdsize
1109 - sizeof segcmd),
1110 segcmd.nsects, error_callback,
1112 goto fail;
1113 have_dwarf = 1;
1114 }
1115 }
1116 break;
1117
1119 {
1120 struct macho_segment_64_command segcmd;
1121
1122 memcpy (&segcmd, pcmd, sizeof segcmd);
1123 if (memcmp (segcmd.segname,
1124 "__DWARF\0\0\0\0\0\0\0\0\0",
1125 MACH_O_NAMELEN) == 0)
1126 {
1127 if (!macho_add_dwarf_segment (state, descriptor, offset,
1128 load_command.cmd,
1129 pcmd + sizeof segcmd,
1130 (load_command.cmdsize
1131 - sizeof segcmd),
1132 segcmd.nsects, error_callback,
1134 goto fail;
1135 have_dwarf = 1;
1136 }
1137 }
1138 break;
1139
1140 case MACH_O_LC_SYMTAB:
1141 if (!skip_symtab)
1142 {
1143 struct macho_symtab_command symcmd;
1144
1145 memcpy (&symcmd, pcmd, sizeof symcmd);
1146 if (!macho_add_symtab (state, descriptor, base_address, is_64,
1147 offset + symcmd.symoff, symcmd.nsyms,
1148 offset + symcmd.stroff, symcmd.strsize,
1150 goto fail;
1151
1152 *found_sym = 1;
1153 }
1154 break;
1155
1156 case MACH_O_LC_UUID:
1157 {
1158 struct macho_uuid_command uuidcmd;
1159
1160 memcpy (&uuidcmd, pcmd, sizeof uuidcmd);
1161 memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);
1162 have_uuid = 1;
1163 }
1164 break;
1165
1166 default:
1167 break;
1168 }
1169
1170 cmdoffset += load_command.cmdsize;
1171 }
1172
1173 if (!backtrace_close (descriptor, error_callback, data))
1174 goto fail;
1175 descriptor = -1;
1176
1178 cmds_view_valid = 0;
1179
1180 if (match_uuid != NULL)
1181 {
1182 /* If we don't have a UUID, or it doesn't match, just ignore
1183 this file. */
1184 if (!have_uuid
1185 || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)
1186 return 1;
1187 }
1188
1189 if (have_dwarf)
1190 {
1191 int is_big_endian;
1192
1193 is_big_endian = 0;
1194#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1195#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1196 is_big_endian = 1;
1197#endif
1198#endif
1199
1200 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1201 is_big_endian, NULL, error_callback, data,
1202 fileline_fn, NULL))
1203 goto fail;
1204 }
1205
1206 if (!have_dwarf && have_uuid)
1207 {
1208 if (!macho_add_dsym (state, filename, base_address, &uuid[0],
1209 error_callback, data, fileline_fn))
1210 goto fail;
1211 }
1212
1213 return 1;
1214
1215 fail:
1216 if (cmds_view_valid)
1218 if (descriptor != -1)
1219 backtrace_close (descriptor, error_callback, data);
1220 return 0;
1221}
1222
1223#ifdef HAVE_MACH_O_DYLD_H
1224
1225/* Initialize the backtrace data we need from a Mach-O executable
1226 using the dyld support functions. This closes descriptor. */
1227
1228int
1229backtrace_initialize (struct backtrace_state *state, const char *filename,
1231 void *data, fileline *fileline_fn)
1232{
1233 uint32_t c;
1234 uint32_t i;
1235 int closed_descriptor;
1236 int found_sym;
1237 fileline macho_fileline_fn;
1238
1239 closed_descriptor = 0;
1240 found_sym = 0;
1241 macho_fileline_fn = macho_nodebug;
1242
1243 c = _dyld_image_count ();
1244 for (i = 0; i < c; ++i)
1245 {
1246 struct libbacktrace_base_address base_address;
1247 const char *name;
1248 int d;
1249 fileline mff;
1250 int mfs;
1251
1252 name = _dyld_get_image_name (i);
1253 if (name == NULL)
1254 continue;
1255
1256 if (strcmp (name, filename) == 0 && !closed_descriptor)
1257 {
1258 d = descriptor;
1259 closed_descriptor = 1;
1260 }
1261 else
1262 {
1263 int does_not_exist;
1264
1265 d = backtrace_open (name, error_callback, data, &does_not_exist);
1266 if (d < 0)
1267 continue;
1268 }
1269
1270 base_address.m = _dyld_get_image_vmaddr_slide (i);
1271
1272 mff = macho_nodebug;
1273 if (!macho_add (state, name, d, 0, NULL, base_address, 0,
1274 error_callback, data, &mff, &mfs))
1275 continue;
1276
1277 if (mff != macho_nodebug)
1278 macho_fileline_fn = mff;
1279 if (mfs)
1280 found_sym = 1;
1281 }
1282
1283 if (!closed_descriptor)
1284 backtrace_close (descriptor, error_callback, data);
1285
1286 if (!state->threaded)
1287 {
1288 if (found_sym)
1289 state->syminfo_fn = macho_syminfo;
1290 else if (state->syminfo_fn == NULL)
1291 state->syminfo_fn = macho_nosyms;
1292 }
1293 else
1294 {
1295 if (found_sym)
1297 else
1298 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1299 macho_nosyms);
1300 }
1301
1302 if (!state->threaded)
1303 *fileline_fn = state->fileline_fn;
1304 else
1305 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1306
1307 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1308 *fileline_fn = macho_fileline_fn;
1309
1310 return 1;
1311}
1312
1313#else /* !defined (HAVE_MACH_O_DYLD_H) */
1314
1315/* Initialize the backtrace data we need from a Mach-O executable
1316 without using the dyld support functions. This closes
1317 descriptor. */
1318
1319int
1320backtrace_initialize (struct backtrace_state *state, const char *filename,
1322 void *data, fileline *fileline_fn)
1323{
1324 fileline macho_fileline_fn;
1325 struct libbacktrace_base_address zero_base_address;
1326 int found_sym;
1327
1328 macho_fileline_fn = macho_nodebug;
1329 memset (&zero_base_address, 0, sizeof zero_base_address);
1330 if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,
1331 error_callback, data, &macho_fileline_fn, &found_sym))
1332 return 0;
1333
1334 if (!state->threaded)
1335 {
1336 if (found_sym)
1337 state->syminfo_fn = macho_syminfo;
1338 else if (state->syminfo_fn == NULL)
1339 state->syminfo_fn = macho_nosyms;
1340 }
1341 else
1342 {
1343 if (found_sym)
1345 else
1346 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1347 macho_nosyms);
1348 }
1349
1350 if (!state->threaded)
1351 *fileline_fn = state->fileline_fn;
1352 else
1353 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1354
1355 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1356 *fileline_fn = macho_fileline_fn;
1357
1358 return 1;
1359}
1360
1361#endif /* !defined (HAVE_MACH_O_DYLD_H) */
void * backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data)
Definition alloc.c:51
void backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p, size_t size ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
Definition alloc.c:69
void(* backtrace_syminfo_callback)(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
Definition backtrace.h:165
void(* backtrace_error_callback)(void *data, const char *msg, int errnum)
Definition backtrace.h:66
int(* backtrace_full_callback)(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
Definition backtrace.h:100
static void error_callback(void *data, const char *msg, int errnum)
Definition print.c:53
Test enumeration values.
Definition dict_test.h:92
int backtrace_dwarf_add(struct backtrace_state *state, struct libbacktrace_base_address base_address, const struct dwarf_sections *dwarf_sections, int is_bigendian, struct dwarf_data *fileline_altlink, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, struct dwarf_data **fileline_entry)
Definition dwarf.c:4536
#define ATTRIBUTE_UNUSED
Definition filenames.h:42
void backtrace_qsort(void *base, size_t count, size_t size, int(*compar)(const void *, const void *))
Definition sort.c:61
void backtrace_release_view(struct backtrace_state *state, struct backtrace_view *view, backtrace_error_callback error_callback, void *data)
Definition read.c:102
#define backtrace_atomic_load_pointer(p)
Definition internal.h:115
const void * data
Definition internal.h:185
int(* fileline)(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
Definition internal.h:127
#define libbacktrace_add_base(pc, base)
Definition internal.h:361
const unsigned char * data[DEBUG_MAX]
Definition internal.h:323
@ DEBUG_MAX
Definition internal.h:316
int backtrace_close(int descriptor, backtrace_error_callback error_callback, void *data)
Definition posix.c:95
size_t size[DEBUG_MAX]
Definition internal.h:324
#define backtrace_atomic_store_pointer(p, v)
Definition internal.h:117
int backtrace_get_view(struct backtrace_state *state, int descriptor, off_t offset, uint64_t size, backtrace_error_callback error_callback, void *data, struct backtrace_view *view)
Definition read.c:48
int backtrace_open(const char *filename, backtrace_error_callback error_callback, void *data, int *does_not_exist)
Definition posix.c:59
#define __sync_bool_compare_and_swap(A, B, C)
Definition internal.h:77
#define MACH_O_UUID_LEN
Definition macho.c:204
uint32_t magic
Definition macho.c:78
uint64_t size
Definition macho.c:239
uint32_t cmd
Definition macho.c:210
uint64_t offset
Definition macho.c:118
static int macho_add_dwarf_segment(struct backtrace_state *state, int descriptor, off_t offset, unsigned int cmd, const char *psecs, size_t sizesecs, unsigned int nsects, backtrace_error_callback error_callback, void *data, struct dwarf_sections *dwarf_sections)
Definition macho.c:383
#define MACH_O_CPU_TYPE_ARM64
Definition macho.c:134
char sectname[MACH_O_NAMELEN]
Definition macho.c:236
uint32_t offset
Definition macho.c:223
uint32_t magic
Definition macho.c:64
#define MACH_O_N_SECT
Definition macho.c:280
uint8_t n_sect
Definition macho.c:267
#define MACH_O_N_TYPE
Definition macho.c:275
#define MACH_O_N_STAB
Definition macho.c:274
uint32_t ncmds
Definition macho.c:68
uint32_t cputype
Definition macho.c:65
uint32_t addr
Definition macho.c:221
static int macho_symbol_compare(const void *v1, const void *v2)
Definition macho.c:451
#define MACH_O_CPU_TYPE_PPC
Definition macho.c:131
uint32_t initprot
Definition macho.c:168
uint32_t reserved2
Definition macho.c:229
uint32_t cputype
Definition macho.c:52
uint32_t magic
Definition macho.c:51
uint32_t offset
Definition macho.c:240
unsigned char uuid[MACH_O_UUID_LEN]
Definition macho.c:212
#define MACH_O_N_UNDF
Definition macho.c:278
#define MACH_O_MH_MAGIC_FAT_64
Definition macho.c:88
static void macho_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr ATTRIBUTE_UNUSED, backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
Definition macho.c:338
#define MACH_O_MH_DYLIB
Definition macho.c:94
static void macho_syminfo(struct backtrace_state *state, uintptr_t addr, backtrace_syminfo_callback callback, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data)
Definition macho.c:707
uint32_t align
Definition macho.c:120
uint16_t n_desc
Definition macho.c:257
uint32_t nfat_arch
Definition macho.c:79
#define MACH_O_CPU_TYPE_PPC64
Definition macho.c:135
uint32_t offset
Definition macho.c:105
static int macho_add_symtab(struct backtrace_state *state, int descriptor, struct libbacktrace_base_address base_address, int is_64, off_t symoff, unsigned int nsyms, off_t stroff, unsigned int strsize, backtrace_error_callback error_callback, void *data)
Definition macho.c:514
uint32_t ncmds
Definition macho.c:55
uint32_t reloff
Definition macho.c:225
#define MACH_O_CPU_TYPE_ARM
Definition macho.c:130
#define MACH_O_LC_SEGMENT
Definition macho.c:147
uint32_t nreloc
Definition macho.c:243
#define MACH_O_MH_CIGAM_FAT
Definition macho.c:87
uint32_t flags
Definition macho.c:70
#define MACH_O_CPU_TYPE_X86
Definition macho.c:129
uint32_t sizeofcmds
Definition macho.c:69
uint32_t cmdsize
Definition macho.c:195
uint32_t align
Definition macho.c:224
uint32_t symoff
Definition macho.c:196
char sectname[MACH_O_NAMELEN]
Definition macho.c:219
uint32_t n_strx
Definition macho.c:254
#define MACH_O_LC_SEGMENT_64
Definition macho.c:149
uint64_t size
Definition macho.c:119
uint32_t sizeofcmds
Definition macho.c:56
uint32_t cpusubtype
Definition macho.c:66
char segname[MACH_O_NAMELEN]
Definition macho.c:162
uint32_t reserved
Definition macho.c:121
uint32_t size
Definition macho.c:222
const char * name
Definition macho.c:287
uint32_t cmd
Definition macho.c:141
uint32_t reloff
Definition macho.c:242
char segment[MACH_O_NAMELEN]
Definition macho.c:220
static const char *const dwarf_section_names[DEBUG_MAX]
Definition macho.c:302
uint32_t cpusubtype
Definition macho.c:117
uint32_t reserved1
Definition macho.c:228
uint32_t flags
Definition macho.c:227
uint32_t n_value
Definition macho.c:258
uint32_t size
Definition macho.c:106
uint32_t flags
Definition macho.c:57
struct macho_syminfo_data * next
Definition macho.c:295
uint32_t filesize
Definition macho.c:166
uint64_t addr
Definition macho.c:238
uint32_t cmdsize
Definition macho.c:142
struct macho_symbol * symbols
Definition macho.c:296
uint32_t stroff
Definition macho.c:198
uint32_t reserved
Definition macho.c:71
uint32_t filetype
Definition macho.c:54
uint32_t flags
Definition macho.c:244
uint32_t cputype
Definition macho.c:116
uint32_t strsize
Definition macho.c:199
uint32_t reserved1
Definition macho.c:245
static int macho_add_dsym(struct backtrace_state *state, const char *filename, struct libbacktrace_base_address base_address, const unsigned char *uuid, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
Definition macho.c:864
char segment[MACH_O_NAMELEN]
Definition macho.c:237
uint8_t n_type
Definition macho.c:266
uint16_t n_desc
Definition macho.c:268
#define MACH_O_NAMELEN
Definition macho.c:154
uint32_t nreloc
Definition macho.c:226
static int macho_add_fat(struct backtrace_state *state, const char *filename, int descriptor, int swapped, off_t offset, const unsigned char *match_uuid, struct libbacktrace_base_address base_address, int skip_symtab, uint32_t nfat_arch, int is_64, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym)
Definition macho.c:760
uint8_t n_sect
Definition macho.c:256
char segname[MACH_O_NAMELEN]
Definition macho.c:179
#define MACH_O_MH_DSYM
Definition macho.c:95
uint32_t align
Definition macho.c:107
uint32_t cpusubtype
Definition macho.c:104
uint32_t cpusubtype
Definition macho.c:53
uintptr_t address
Definition macho.c:288
uint32_t cputype
Definition macho.c:103
static int macho_add_dwarf_section(struct backtrace_state *state, int descriptor, const char *sectname, uint32_t offset, uint64_t size, backtrace_error_callback error_callback, void *data, struct dwarf_sections *dwarf_sections)
Definition macho.c:350
#define MACH_O_MH_EXECUTE
Definition macho.c:93
uint8_t n_type
Definition macho.c:255
uint32_t filetype
Definition macho.c:67
uint64_t n_value
Definition macho.c:269
uint32_t cmdsize
Definition macho.c:211
#define MACH_O_MH_MAGIC_64
Definition macho.c:85
#define MACH_O_CPU_TYPE_X86_64
Definition macho.c:133
static int macho_nodebug(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED, backtrace_full_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
Definition macho.c:325
uint32_t align
Definition macho.c:241
uint32_t reserved2
Definition macho.c:246
uint32_t reserved3
Definition macho.c:247
uint32_t n_strx
Definition macho.c:265
static int macho_add(struct backtrace_state *, const char *, int, off_t, const unsigned char *, struct libbacktrace_base_address, int, backtrace_error_callback, void *, fileline *, int *)
Definition macho.c:982
#define MACH_O_LC_SYMTAB
Definition macho.c:148
#define MACH_O_LC_UUID
Definition macho.c:150
static int macho_symbol_search(const void *vkey, const void *ventry)
Definition macho.c:469
int backtrace_initialize(struct backtrace_state *state, const char *filename, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
Definition macho.c:1320
#define MACH_O_MH_MAGIC_32
Definition macho.c:84
#define MACH_O_N_ABS
Definition macho.c:279
static int macho_defined_symbol(uint8_t type)
Definition macho.c:494
#define MACH_O_MH_MAGIC_FAT
Definition macho.c:86
#define MACH_O_MH_CIGAM_FAT_64
Definition macho.c:89
unsigned short uint16_t
unsigned int uint32_t
unsigned char uint8_t
long long int off_t
static char const * name
fr_aka_sim_id_type_t type
void * state
Definition testlib.c:46
Functions to help with cleanup.
static fr_slen_t data
Definition value.h:1340