v / thirdparty / libbacktrace / darwin.c
1697 lines · 1422 sloc · 42.54 KB · e78481994a892734d00a24a16951a2df75f76631
Raw
1// macho.c:
2#include <sys/types.h>
3#include <dirent.h>
4#include <stdlib.h>
5#include <string.h>
6
7#ifdef HAVE_MACH_O_DYLD_H
8#include <mach-o/dyld.h>
9#endif
10
11
12/* Mach-O file header for a 32-bit executable. */
13
14struct macho_header_32
15{
16 uint32_t magic; /* Magic number (MACH_O_MAGIC_32) */
17 uint32_t cputype; /* CPU type */
18 uint32_t cpusubtype; /* CPU subtype */
19 uint32_t filetype; /* Type of file (object, executable) */
20 uint32_t ncmds; /* Number of load commands */
21 uint32_t sizeofcmds; /* Total size of load commands */
22 uint32_t flags; /* Flags for special features */
23};
24
25/* Mach-O file header for a 64-bit executable. */
26
27struct macho_header_64
28{
29 uint32_t magic; /* Magic number (MACH_O_MAGIC_64) */
30 uint32_t cputype; /* CPU type */
31 uint32_t cpusubtype; /* CPU subtype */
32 uint32_t filetype; /* Type of file (object, executable) */
33 uint32_t ncmds; /* Number of load commands */
34 uint32_t sizeofcmds; /* Total size of load commands */
35 uint32_t flags; /* Flags for special features */
36 uint32_t reserved; /* Reserved */
37};
38
39/* Mach-O file header for a fat executable. */
40
41struct macho_header_fat
42{
43 uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */
44 uint32_t nfat_arch; /* Number of components */
45};
46
47/* Values for the header magic field. */
48
49#define MACH_O_MH_MAGIC_32 0xfeedface
50#define MACH_O_MH_MAGIC_64 0xfeedfacf
51#define MACH_O_MH_MAGIC_FAT 0xcafebabe
52#define MACH_O_MH_CIGAM_FAT 0xbebafeca
53#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf
54#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca
55
56/* Value for the header filetype field. */
57
58#define MACH_O_MH_EXECUTE 0x02
59#define MACH_O_MH_DYLIB 0x06
60#define MACH_O_MH_DSYM 0x0a
61
62/* A component of a fat file. A fat file starts with a
63 macho_header_fat followed by nfat_arch instances of this
64 struct. */
65
66struct macho_fat_arch
67{
68 uint32_t cputype; /* CPU type */
69 uint32_t cpusubtype; /* CPU subtype */
70 uint32_t offset; /* File offset of this entry */
71 uint32_t size; /* Size of this entry */
72 uint32_t align; /* Alignment of this entry */
73};
74
75/* A component of a 64-bit fat file. This is used if the magic field
76 is MAGIC_FAT_64. This is only used when some file size or file
77 offset is too large to represent in the 32-bit format. */
78
79struct macho_fat_arch_64
80{
81 uint32_t cputype; /* CPU type */
82 uint32_t cpusubtype; /* CPU subtype */
83 uint64_t offset; /* File offset of this entry */
84 uint64_t size; /* Size of this entry */
85 uint32_t align; /* Alignment of this entry */
86 uint32_t reserved; /* Reserved */
87};
88
89/* Values for the fat_arch cputype field (and the header cputype
90 field). */
91
92#define MACH_O_CPU_ARCH_ABI64 0x01000000
93
94#define MACH_O_CPU_TYPE_X86 7
95#define MACH_O_CPU_TYPE_ARM 12
96#define MACH_O_CPU_TYPE_PPC 18
97
98#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)
99#define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)
100#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)
101
102/* The header of a load command. */
103
104struct macho_load_command
105{
106 uint32_t cmd; /* The type of load command */
107 uint32_t cmdsize; /* Size in bytes of the entire command */
108};
109
110/* Values for the load_command cmd field. */
111
112#define MACH_O_LC_SEGMENT 0x01
113#define MACH_O_LC_SYMTAB 0x02
114#define MACH_O_LC_SEGMENT_64 0x19
115#define MACH_O_LC_UUID 0x1b
116
117/* The length of a section of segment name. */
118
119#define MACH_O_NAMELEN (16)
120
121/* LC_SEGMENT load command. */
122
123struct macho_segment_command
124{
125 uint32_t cmd; /* The type of load command (LC_SEGMENT) */
126 uint32_t cmdsize; /* Size in bytes of the entire command */
127 char segname[MACH_O_NAMELEN]; /* Segment name */
128 uint32_t vmaddr; /* Virtual memory address */
129 uint32_t vmsize; /* Virtual memory size */
130 uint32_t fileoff; /* Offset of data to be mapped */
131 uint32_t filesize; /* Size of data in file */
132 uint32_t maxprot; /* Maximum permitted virtual protection */
133 uint32_t initprot; /* Initial virtual memory protection */
134 uint32_t nsects; /* Number of sections in this segment */
135 uint32_t flags; /* Flags */
136};
137
138/* LC_SEGMENT_64 load command. */
139
140struct macho_segment_64_command
141{
142 uint32_t cmd; /* The type of load command (LC_SEGMENT) */
143 uint32_t cmdsize; /* Size in bytes of the entire command */
144 char segname[MACH_O_NAMELEN]; /* Segment name */
145 uint64_t vmaddr; /* Virtual memory address */
146 uint64_t vmsize; /* Virtual memory size */
147 uint64_t fileoff; /* Offset of data to be mapped */
148 uint64_t filesize; /* Size of data in file */
149 uint32_t maxprot; /* Maximum permitted virtual protection */
150 uint32_t initprot; /* Initial virtual memory protection */
151 uint32_t nsects; /* Number of sections in this segment */
152 uint32_t flags; /* Flags */
153};
154
155/* LC_SYMTAB load command. */
156
157struct macho_symtab_command
158{
159 uint32_t cmd; /* The type of load command (LC_SEGMENT) */
160 uint32_t cmdsize; /* Size in bytes of the entire command */
161 uint32_t symoff; /* File offset of symbol table */
162 uint32_t nsyms; /* Number of symbols */
163 uint32_t stroff; /* File offset of string table */
164 uint32_t strsize; /* String table size */
165};
166
167/* The length of a Mach-O uuid. */
168
169#define MACH_O_UUID_LEN (16)
170
171/* LC_UUID load command. */
172
173struct macho_uuid_command
174{
175 uint32_t cmd; /* Type of load command (LC_UUID) */
176 uint32_t cmdsize; /* Size in bytes of command */
177 unsigned char uuid[MACH_O_UUID_LEN]; /* UUID */
178};
179
180/* 32-bit section header within a LC_SEGMENT segment. */
181
182struct macho_section
183{
184 char sectname[MACH_O_NAMELEN]; /* Section name */
185 char segment[MACH_O_NAMELEN]; /* Segment of this section */
186 uint32_t addr; /* Address in memory */
187 uint32_t size; /* Section size */
188 uint32_t offset; /* File offset */
189 uint32_t align; /* Log2 of section alignment */
190 uint32_t reloff; /* File offset of relocations */
191 uint32_t nreloc; /* Number of relocs for this section */
192 uint32_t flags; /* Flags */
193 uint32_t reserved1;
194 uint32_t reserved2;
195};
196
197/* 64-bit section header within a LC_SEGMENT_64 segment. */
198
199struct macho_section_64
200{
201 char sectname[MACH_O_NAMELEN]; /* Section name */
202 char segment[MACH_O_NAMELEN]; /* Segment of this section */
203 uint64_t addr; /* Address in memory */
204 uint64_t size; /* Section size */
205 uint32_t offset; /* File offset */
206 uint32_t align; /* Log2 of section alignment */
207 uint32_t reloff; /* File offset of section relocations */
208 uint32_t nreloc; /* Number of relocs for this section */
209 uint32_t flags; /* Flags */
210 uint32_t reserved1;
211 uint32_t reserved2;
212 uint32_t reserved3;
213};
214
215/* 32-bit symbol data. */
216
217struct macho_nlist
218{
219 uint32_t n_strx; /* Index of name in string table */
220 uint8_t n_type; /* Type flag */
221 uint8_t n_sect; /* Section number */
222 uint16_t n_desc; /* Stabs description field */
223 uint32_t n_value; /* Value */
224};
225
226/* 64-bit symbol data. */
227
228struct macho_nlist_64
229{
230 uint32_t n_strx; /* Index of name in string table */
231 uint8_t n_type; /* Type flag */
232 uint8_t n_sect; /* Section number */
233 uint16_t n_desc; /* Stabs description field */
234 uint64_t n_value; /* Value */
235};
236
237/* Value found in nlist n_type field. */
238
239#define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
240#define MACH_O_N_TYPE 0x0e /* Mask for type bits */
241
242/* Values found after masking with MACH_O_N_TYPE. */
243#define MACH_O_N_UNDF 0x00 /* Undefined symbol */
244#define MACH_O_N_ABS 0x02 /* Absolute symbol */
245#define MACH_O_N_SECT 0x0e /* Defined in section from n_sect field */
246
247
248/* Information we keep for a Mach-O symbol. */
249
250struct macho_symbol
251{
252 const char *name; /* Symbol name */
253 uintptr_t address; /* Symbol address */
254};
255
256/* Information to pass to macho_syminfo. */
257
258struct macho_syminfo_data
259{
260 struct macho_syminfo_data *next; /* Next module */
261 struct macho_symbol *symbols; /* Symbols sorted by address */
262 size_t count; /* Number of symbols */
263};
264
265/* Names of sections, indexed by enum dwarf_section in internal.h. */
266
267static const char * const dwarf_section_names[DEBUG_MAX] =
268{
269 "__debug_info",
270 "__debug_line",
271 "__debug_abbrev",
272 "__debug_ranges",
273 "__debug_str",
274 "__debug_addr",
275 "__debug_str_offs",
276 "__debug_line_str",
277 "__debug_rnglists"
278};
279
280/* Forward declaration. */
281
282static int macho_add (struct backtrace_state *, const char *, int, off_t,
283 const unsigned char *, struct libbacktrace_base_address,
284 int, backtrace_error_callback, void *, fileline *,
285 int *);
286
287/* A dummy callback function used when we can't find any debug info. */
288
289static int
290macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
291 uintptr_t pc ATTRIBUTE_UNUSED,
292 backtrace_full_callback callback ATTRIBUTE_UNUSED,
293 backtrace_error_callback error_callback, void *data)
294{
295 error_callback (data, "no debug info in Mach-O executable (make sure to compile with -g; may need to run dsymutil)", -1);
296 return 0;
297}
298
299/* A dummy callback function used when we can't find a symbol
300 table. */
301
302static void
303macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
304 uintptr_t addr ATTRIBUTE_UNUSED,
305 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
306 backtrace_error_callback error_callback, void *data)
307{
308 error_callback (data, "no symbol table in Mach-O executable", -1);
309}
310
311/* Add a single DWARF section to DWARF_SECTIONS, if we need the
312 section. Returns 1 on success, 0 on failure. */
313
314static int
315macho_add_dwarf_section (struct backtrace_state *state, int descriptor,
316 const char *sectname, uint32_t offset, uint64_t size,
317 backtrace_error_callback error_callback, void *data,
318 struct dwarf_sections *dwarf_sections)
319{
320 int i;
321
322 for (i = 0; i < (int) DEBUG_MAX; ++i)
323 {
324 if (dwarf_section_names[i][0] != '\0'
325 && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)
326 {
327 struct backtrace_view section_view;
328
329 /* FIXME: Perhaps it would be better to try to use a single
330 view to read all the DWARF data, as we try to do for
331 ELF. */
332
333 if (!backtrace_get_view (state, descriptor, offset, size,
334 error_callback, data, §ion_view))
335 return 0;
336 dwarf_sections->data[i] = (const unsigned char *) section_view.data;
337 dwarf_sections->size[i] = size;
338 break;
339 }
340 }
341 return 1;
342}
343
344/* Collect DWARF sections from a DWARF segment. Returns 1 on success,
345 0 on failure. */
346
347static int
348macho_add_dwarf_segment (struct backtrace_state *state, int descriptor,
349 off_t offset, unsigned int cmd, const char *psecs,
350 size_t sizesecs, unsigned int nsects,
351 backtrace_error_callback error_callback, void *data,
352 struct dwarf_sections *dwarf_sections)
353{
354 size_t sec_header_size;
355 size_t secoffset;
356 unsigned int i;
357
358 switch (cmd)
359 {
360 case MACH_O_LC_SEGMENT:
361 sec_header_size = sizeof (struct macho_section);
362 break;
363 case MACH_O_LC_SEGMENT_64:
364 sec_header_size = sizeof (struct macho_section_64);
365 break;
366 default:
367 abort ();
368 }
369
370 secoffset = 0;
371 for (i = 0; i < nsects; ++i)
372 {
373 if (secoffset + sec_header_size > sizesecs)
374 {
375 error_callback (data, "section overflow withing segment", 0);
376 return 0;
377 }
378
379 switch (cmd)
380 {
381 case MACH_O_LC_SEGMENT:
382 {
383 struct macho_section section;
384
385 memcpy (§ion, psecs + secoffset, sizeof section);
386 macho_add_dwarf_section (state, descriptor, section.sectname,
387 offset + section.offset, section.size,
388 error_callback, data, dwarf_sections);
389 }
390 break;
391
392 case MACH_O_LC_SEGMENT_64:
393 {
394 struct macho_section_64 section;
395
396 memcpy (§ion, psecs + secoffset, sizeof section);
397 macho_add_dwarf_section (state, descriptor, section.sectname,
398 offset + section.offset, section.size,
399 error_callback, data, dwarf_sections);
400 }
401 break;
402
403 default:
404 abort ();
405 }
406
407 secoffset += sec_header_size;
408 }
409
410 return 1;
411}
412
413/* Compare struct macho_symbol for qsort. */
414
415static int
416macho_symbol_compare (const void *v1, const void *v2)
417{
418 const struct macho_symbol *m1 = (const struct macho_symbol *) v1;
419 const struct macho_symbol *m2 = (const struct macho_symbol *) v2;
420
421 if (m1->address < m2->address)
422 return -1;
423 else if (m1->address > m2->address)
424 return 1;
425 else
426 return 0;
427}
428
429/* Compare an address against a macho_symbol for bsearch. We allocate
430 one extra entry in the array so that this can safely look at the
431 next entry. */
432
433static int
434macho_symbol_search (const void *vkey, const void *ventry)
435{
436 const uintptr_t *key = (const uintptr_t *) vkey;
437 const struct macho_symbol *entry = (const struct macho_symbol *) ventry;
438 uintptr_t addr;
439
440 addr = *key;
441 if (addr < entry->address)
442 return -1;
443 else if (entry->name[0] == '\0'
444 && entry->address == ~(uintptr_t) 0)
445 return -1;
446 else if ((entry + 1)->name[0] == '\0'
447 && (entry + 1)->address == ~(uintptr_t) 0)
448 return -1;
449 else if (addr >= (entry + 1)->address)
450 return 1;
451 else
452 return 0;
453}
454
455/* Return whether the symbol type field indicates a symbol table entry
456 that we care about: a function or data symbol. */
457
458static int
459macho_defined_symbol (uint8_t type)
460{
461 if ((type & MACH_O_N_STAB) != 0)
462 return 0;
463 switch (type & MACH_O_N_TYPE)
464 {
465 case MACH_O_N_UNDF:
466 return 0;
467 case MACH_O_N_ABS:
468 return 1;
469 case MACH_O_N_SECT:
470 return 1;
471 default:
472 return 0;
473 }
474}
475
476/* Add symbol table information for a Mach-O file. */
477
478static int
479macho_add_symtab (struct backtrace_state *state, int descriptor,
480 struct libbacktrace_base_address base_address, int is_64,
481 off_t symoff, unsigned int nsyms, off_t stroff,
482 unsigned int strsize,
483 backtrace_error_callback error_callback, void *data)
484{
485 size_t symsize;
486 struct backtrace_view sym_view;
487 int sym_view_valid;
488 struct backtrace_view str_view;
489 int str_view_valid;
490 size_t ndefs;
491 size_t symtaboff;
492 unsigned int i;
493 size_t macho_symbol_size;
494 struct macho_symbol *macho_symbols;
495 unsigned int j;
496 struct macho_syminfo_data *sdata;
497
498 sym_view_valid = 0;
499 str_view_valid = 0;
500 macho_symbol_size = 0;
501 macho_symbols = NULL;
502
503 if (is_64)
504 symsize = sizeof (struct macho_nlist_64);
505 else
506 symsize = sizeof (struct macho_nlist);
507
508 if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,
509 error_callback, data, &sym_view))
510 goto fail;
511 sym_view_valid = 1;
512
513 if (!backtrace_get_view (state, descriptor, stroff, strsize,
514 error_callback, data, &str_view))
515 return 0;
516 str_view_valid = 1;
517
518 ndefs = 0;
519 symtaboff = 0;
520 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
521 {
522 if (is_64)
523 {
524 struct macho_nlist_64 nlist;
525
526 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
527 sizeof nlist);
528 if (macho_defined_symbol (nlist.n_type))
529 ++ndefs;
530 }
531 else
532 {
533 struct macho_nlist nlist;
534
535 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
536 sizeof nlist);
537 if (macho_defined_symbol (nlist.n_type))
538 ++ndefs;
539 }
540 }
541
542 /* Add 1 to ndefs to make room for a sentinel. */
543 macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);
544 macho_symbols = ((struct macho_symbol *)
545 backtrace_alloc (state, macho_symbol_size, error_callback,
546 data));
547 if (macho_symbols == NULL)
548 goto fail;
549
550 j = 0;
551 symtaboff = 0;
552 for (i = 0; i < nsyms; ++i, symtaboff += symsize)
553 {
554 uint32_t strx;
555 uint64_t value;
556 const char *name;
557
558 strx = 0;
559 value = 0;
560 if (is_64)
561 {
562 struct macho_nlist_64 nlist;
563
564 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
565 sizeof nlist);
566 if (!macho_defined_symbol (nlist.n_type))
567 continue;
568
569 strx = nlist.n_strx;
570 value = nlist.n_value;
571 }
572 else
573 {
574 struct macho_nlist nlist;
575
576 memcpy (&nlist, (const char *) sym_view.data + symtaboff,
577 sizeof nlist);
578 if (!macho_defined_symbol (nlist.n_type))
579 continue;
580
581 strx = nlist.n_strx;
582 value = nlist.n_value;
583 }
584
585 if (strx >= strsize)
586 {
587 error_callback (data, "symbol string index out of range", 0);
588 goto fail;
589 }
590
591 name = (const char *) str_view.data + strx;
592 if (name[0] == '_')
593 ++name;
594 macho_symbols[j].name = name;
595 macho_symbols[j].address = libbacktrace_add_base (value, base_address);
596 ++j;
597 }
598
599 sdata = ((struct macho_syminfo_data *)
600 backtrace_alloc (state, sizeof *sdata, error_callback, data));
601 if (sdata == NULL)
602 goto fail;
603
604 /* We need to keep the string table since it holds the names, but we
605 can release the symbol table. */
606
607 backtrace_release_view (state, &sym_view, error_callback, data);
608 sym_view_valid = 0;
609 str_view_valid = 0;
610
611 /* Add a trailing sentinel symbol. */
612 macho_symbols[j].name = "";
613 macho_symbols[j].address = ~(uintptr_t) 0;
614
615 backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),
616 macho_symbol_compare);
617
618 sdata->next = NULL;
619 sdata->symbols = macho_symbols;
620 sdata->count = ndefs;
621
622 if (!state->threaded)
623 {
624 struct macho_syminfo_data **pp;
625
626 for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
627 *pp != NULL;
628 pp = &(*pp)->next)
629 ;
630 *pp = sdata;
631 }
632 else
633 {
634 while (1)
635 {
636 struct macho_syminfo_data **pp;
637
638 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
639
640 while (1)
641 {
642 struct macho_syminfo_data *p;
643
644 p = backtrace_atomic_load_pointer (pp);
645 if (p == NULL)
646 break;
647
648 pp = &p->next;
649 }
650
651 if (__sync_bool_compare_and_swap (pp, NULL, sdata))
652 break;
653 }
654 }
655
656 return 1;
657
658 fail:
659 if (macho_symbols != NULL)
660 backtrace_free (state, macho_symbols, macho_symbol_size,
661 error_callback, data);
662 if (sym_view_valid)
663 backtrace_release_view (state, &sym_view, error_callback, data);
664 if (str_view_valid)
665 backtrace_release_view (state, &str_view, error_callback, data);
666 return 0;
667}
668
669/* Return the symbol name and value for an ADDR. */
670
671static void
672macho_syminfo (struct backtrace_state *state, uintptr_t addr,
673 backtrace_syminfo_callback callback,
674 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
675 void *data)
676{
677 struct macho_syminfo_data *sdata;
678 struct macho_symbol *sym;
679
680 sym = NULL;
681 if (!state->threaded)
682 {
683 for (sdata = (struct macho_syminfo_data *) state->syminfo_data;
684 sdata != NULL;
685 sdata = sdata->next)
686 {
687 sym = ((struct macho_symbol *)
688 bsearch (&addr, sdata->symbols, sdata->count,
689 sizeof (struct macho_symbol), macho_symbol_search));
690 if (sym != NULL)
691 break;
692 }
693 }
694 else
695 {
696 struct macho_syminfo_data **pp;
697
698 pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;
699 while (1)
700 {
701 sdata = backtrace_atomic_load_pointer (pp);
702 if (sdata == NULL)
703 break;
704
705 sym = ((struct macho_symbol *)
706 bsearch (&addr, sdata->symbols, sdata->count,
707 sizeof (struct macho_symbol), macho_symbol_search));
708 if (sym != NULL)
709 break;
710
711 pp = &sdata->next;
712 }
713 }
714
715 if (sym == NULL)
716 callback (data, addr, NULL, 0, 0);
717 else
718 callback (data, addr, sym->name, sym->address, 0);
719}
720
721/* Look through a fat file to find the relevant executable. Returns 1
722 on success, 0 on failure (in both cases descriptor is closed). */
723
724static int
725macho_add_fat (struct backtrace_state *state, const char *filename,
726 int descriptor, int swapped, off_t offset,
727 const unsigned char *match_uuid,
728 struct libbacktrace_base_address base_address,
729 int skip_symtab, uint32_t nfat_arch, int is_64,
730 backtrace_error_callback error_callback, void *data,
731 fileline *fileline_fn, int *found_sym)
732{
733 int arch_view_valid;
734 unsigned int cputype;
735 size_t arch_size;
736 struct backtrace_view arch_view;
737 unsigned int i;
738
739 arch_view_valid = 0;
740
741#if defined (__x86_64__)
742 cputype = MACH_O_CPU_TYPE_X86_64;
743#elif defined (__i386__)
744 cputype = MACH_O_CPU_TYPE_X86;
745#elif defined (__aarch64__)
746 cputype = MACH_O_CPU_TYPE_ARM64;
747#elif defined (__arm__)
748 cputype = MACH_O_CPU_TYPE_ARM;
749#elif defined (__ppc__)
750 cputype = MACH_O_CPU_TYPE_PPC;
751#elif defined (__ppc64__)
752 cputype = MACH_O_CPU_TYPE_PPC64;
753#else
754 error_callback (data, "unknown Mach-O architecture", 0);
755 goto fail;
756#endif
757
758 if (is_64)
759 arch_size = sizeof (struct macho_fat_arch_64);
760 else
761 arch_size = sizeof (struct macho_fat_arch);
762
763 if (!backtrace_get_view (state, descriptor, offset,
764 nfat_arch * arch_size,
765 error_callback, data, &arch_view))
766 goto fail;
767
768 for (i = 0; i < nfat_arch; ++i)
769 {
770 uint32_t fcputype;
771 uint64_t foffset;
772
773 if (is_64)
774 {
775 struct macho_fat_arch_64 fat_arch_64;
776
777 memcpy (&fat_arch_64,
778 (const char *) arch_view.data + i * arch_size,
779 arch_size);
780 fcputype = fat_arch_64.cputype;
781 foffset = fat_arch_64.offset;
782 if (swapped)
783 {
784 fcputype = __builtin_bswap32 (fcputype);
785 foffset = __builtin_bswap64 (foffset);
786 }
787 }
788 else
789 {
790 struct macho_fat_arch fat_arch_32;
791
792 memcpy (&fat_arch_32,
793 (const char *) arch_view.data + i * arch_size,
794 arch_size);
795 fcputype = fat_arch_32.cputype;
796 foffset = (uint64_t) fat_arch_32.offset;
797 if (swapped)
798 {
799 fcputype = __builtin_bswap32 (fcputype);
800 foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);
801 }
802 }
803
804 if (fcputype == cputype)
805 {
806 /* FIXME: What about cpusubtype? */
807 backtrace_release_view (state, &arch_view, error_callback, data);
808 return macho_add (state, filename, descriptor, foffset, match_uuid,
809 base_address, skip_symtab, error_callback, data,
810 fileline_fn, found_sym);
811 }
812 }
813
814 error_callback (data, "could not find executable in fat file", 0);
815
816 fail:
817 if (arch_view_valid)
818 backtrace_release_view (state, &arch_view, error_callback, data);
819 if (descriptor != -1)
820 backtrace_close (descriptor, error_callback, data);
821 return 0;
822}
823
824/* Look for the dsym file for FILENAME. This is called if FILENAME
825 does not have debug info or a symbol table. Returns 1 on success,
826 0 on failure. */
827
828static int
829macho_add_dsym (struct backtrace_state *state, const char *filename,
830 struct libbacktrace_base_address base_address,
831 const unsigned char *uuid,
832 backtrace_error_callback error_callback, void *data,
833 fileline* fileline_fn)
834{
835 const char *p;
836 const char *dirname;
837 char *diralc;
838 size_t dirnamelen;
839 const char *basename;
840 size_t basenamelen;
841 const char *dsymsuffixdir;
842 size_t dsymsuffixdirlen;
843 size_t dsymlen;
844 char *dsym;
845 char *ps;
846 int d;
847 int does_not_exist;
848 int dummy_found_sym;
849
850 diralc = NULL;
851 dirnamelen = 0;
852 dsym = NULL;
853 dsymlen = 0;
854
855 p = strrchr (filename, '/');
856 if (p == NULL)
857 {
858 dirname = ".";
859 dirnamelen = 1;
860 basename = filename;
861 basenamelen = strlen (basename);
862 diralc = NULL;
863 }
864 else
865 {
866 dirnamelen = p - filename;
867 diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);
868 if (diralc == NULL)
869 goto fail;
870 memcpy (diralc, filename, dirnamelen);
871 diralc[dirnamelen] = '\0';
872 dirname = diralc;
873 basename = p + 1;
874 basenamelen = strlen (basename);
875 }
876
877 dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";
878 dsymsuffixdirlen = strlen (dsymsuffixdir);
879
880 dsymlen = (dirnamelen
881 + 1
882 + basenamelen
883 + dsymsuffixdirlen
884 + basenamelen
885 + 1);
886 dsym = backtrace_alloc (state, dsymlen, error_callback, data);
887 if (dsym == NULL)
888 goto fail;
889
890 ps = dsym;
891 memcpy (ps, dirname, dirnamelen);
892 ps += dirnamelen;
893 *ps++ = '/';
894 memcpy (ps, basename, basenamelen);
895 ps += basenamelen;
896 memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);
897 ps += dsymsuffixdirlen;
898 memcpy (ps, basename, basenamelen);
899 ps += basenamelen;
900 *ps = '\0';
901
902 if (diralc != NULL)
903 {
904 backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);
905 diralc = NULL;
906 }
907
908 d = backtrace_open (dsym, error_callback, data, &does_not_exist);
909 if (d < 0)
910 {
911 /* The file does not exist, so we can't read the debug info.
912 Just return success. */
913 backtrace_free (state, dsym, dsymlen, error_callback, data);
914 return 1;
915 }
916
917 if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,
918 error_callback, data, fileline_fn, &dummy_found_sym))
919 goto fail;
920
921 backtrace_free (state, dsym, dsymlen, error_callback, data);
922
923 return 1;
924
925 fail:
926 if (dsym != NULL)
927 backtrace_free (state, dsym, dsymlen, error_callback, data);
928 if (diralc != NULL)
929 backtrace_free (state, diralc, dirnamelen, error_callback, data);
930 return 0;
931}
932
933/* Add the backtrace data for a Macho-O file. Returns 1 on success, 0
934 on failure (in both cases descriptor is closed).
935
936 FILENAME: the name of the executable.
937 DESCRIPTOR: an open descriptor for the executable, closed here.
938 OFFSET: the offset within the file of this executable, for fat files.
939 MATCH_UUID: if not NULL, UUID that must match.
940 BASE_ADDRESS: the load address of the executable.
941 SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.
942 FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.
943 FOUND_SYM: set to non-zero if we found the symbol table.
944*/
945
946static int
947macho_add (struct backtrace_state *state, const char *filename, int descriptor,
948 off_t offset, const unsigned char *match_uuid,
949 struct libbacktrace_base_address base_address, int skip_symtab,
950 backtrace_error_callback error_callback, void *data,
951 fileline *fileline_fn, int *found_sym)
952{
953 struct backtrace_view header_view;
954 struct macho_header_32 header;
955 off_t hdroffset;
956 int is_64;
957 struct backtrace_view cmds_view;
958 int cmds_view_valid;
959 struct dwarf_sections dwarf_sections;
960 int have_dwarf;
961 unsigned char uuid[MACH_O_UUID_LEN];
962 int have_uuid;
963 size_t cmdoffset;
964 unsigned int i;
965
966 *found_sym = 0;
967
968 cmds_view_valid = 0;
969
970 /* The 32-bit and 64-bit file headers start out the same, so we can
971 just always read the 32-bit version. A fat header is shorter but
972 it will always be followed by data, so it's OK to read extra. */
973
974 if (!backtrace_get_view (state, descriptor, offset,
975 sizeof (struct macho_header_32),
976 error_callback, data, &header_view))
977 goto fail;
978
979 memcpy (&header, header_view.data, sizeof header);
980
981 backtrace_release_view (state, &header_view, error_callback, data);
982
983 switch (header.magic)
984 {
985 case MACH_O_MH_MAGIC_32:
986 is_64 = 0;
987 hdroffset = offset + sizeof (struct macho_header_32);
988 break;
989 case MACH_O_MH_MAGIC_64:
990 is_64 = 1;
991 hdroffset = offset + sizeof (struct macho_header_64);
992 break;
993 case MACH_O_MH_MAGIC_FAT:
994 case MACH_O_MH_MAGIC_FAT_64:
995 {
996 struct macho_header_fat fat_header;
997
998 hdroffset = offset + sizeof (struct macho_header_fat);
999 memcpy (&fat_header, &header, sizeof fat_header);
1000 return macho_add_fat (state, filename, descriptor, 0, hdroffset,
1001 match_uuid, base_address, skip_symtab,
1002 fat_header.nfat_arch,
1003 header.magic == MACH_O_MH_MAGIC_FAT_64,
1004 error_callback, data, fileline_fn, found_sym);
1005 }
1006 case MACH_O_MH_CIGAM_FAT:
1007 case MACH_O_MH_CIGAM_FAT_64:
1008 {
1009 struct macho_header_fat fat_header;
1010 uint32_t nfat_arch;
1011
1012 hdroffset = offset + sizeof (struct macho_header_fat);
1013 memcpy (&fat_header, &header, sizeof fat_header);
1014 nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
1015 return macho_add_fat (state, filename, descriptor, 1, hdroffset,
1016 match_uuid, base_address, skip_symtab,
1017 nfat_arch,
1018 header.magic == MACH_O_MH_CIGAM_FAT_64,
1019 error_callback, data, fileline_fn, found_sym);
1020 }
1021 default:
1022 error_callback (data, "executable file is not in Mach-O format", 0);
1023 goto fail;
1024 }
1025
1026 switch (header.filetype)
1027 {
1028 case MACH_O_MH_EXECUTE:
1029 case MACH_O_MH_DYLIB:
1030 case MACH_O_MH_DSYM:
1031 break;
1032 default:
1033 error_callback (data, "executable file is not an executable", 0);
1034 goto fail;
1035 }
1036
1037 if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,
1038 error_callback, data, &cmds_view))
1039 goto fail;
1040 cmds_view_valid = 1;
1041
1042 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1043 have_dwarf = 0;
1044 memset (&uuid, 0, sizeof uuid);
1045 have_uuid = 0;
1046
1047 cmdoffset = 0;
1048 for (i = 0; i < header.ncmds; ++i)
1049 {
1050 const char *pcmd;
1051 struct macho_load_command load_command;
1052
1053 if (cmdoffset + sizeof load_command > header.sizeofcmds)
1054 break;
1055
1056 pcmd = (const char *) cmds_view.data + cmdoffset;
1057 memcpy (&load_command, pcmd, sizeof load_command);
1058
1059 switch (load_command.cmd)
1060 {
1061 case MACH_O_LC_SEGMENT:
1062 {
1063 struct macho_segment_command segcmd;
1064
1065 memcpy (&segcmd, pcmd, sizeof segcmd);
1066 if (memcmp (segcmd.segname,
1067 "__DWARF\0\0\0\0\0\0\0\0\0",
1068 MACH_O_NAMELEN) == 0)
1069 {
1070 if (!macho_add_dwarf_segment (state, descriptor, offset,
1071 load_command.cmd,
1072 pcmd + sizeof segcmd,
1073 (load_command.cmdsize
1074 - sizeof segcmd),
1075 segcmd.nsects, error_callback,
1076 data, &dwarf_sections))
1077 goto fail;
1078 have_dwarf = 1;
1079 }
1080 }
1081 break;
1082
1083 case MACH_O_LC_SEGMENT_64:
1084 {
1085 struct macho_segment_64_command segcmd;
1086
1087 memcpy (&segcmd, pcmd, sizeof segcmd);
1088 if (memcmp (segcmd.segname,
1089 "__DWARF\0\0\0\0\0\0\0\0\0",
1090 MACH_O_NAMELEN) == 0)
1091 {
1092 if (!macho_add_dwarf_segment (state, descriptor, offset,
1093 load_command.cmd,
1094 pcmd + sizeof segcmd,
1095 (load_command.cmdsize
1096 - sizeof segcmd),
1097 segcmd.nsects, error_callback,
1098 data, &dwarf_sections))
1099 goto fail;
1100 have_dwarf = 1;
1101 }
1102 }
1103 break;
1104
1105 case MACH_O_LC_SYMTAB:
1106 if (!skip_symtab)
1107 {
1108 struct macho_symtab_command symcmd;
1109
1110 memcpy (&symcmd, pcmd, sizeof symcmd);
1111 if (!macho_add_symtab (state, descriptor, base_address, is_64,
1112 offset + symcmd.symoff, symcmd.nsyms,
1113 offset + symcmd.stroff, symcmd.strsize,
1114 error_callback, data))
1115 goto fail;
1116
1117 *found_sym = 1;
1118 }
1119 break;
1120
1121 case MACH_O_LC_UUID:
1122 {
1123 struct macho_uuid_command uuidcmd;
1124
1125 memcpy (&uuidcmd, pcmd, sizeof uuidcmd);
1126 memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);
1127 have_uuid = 1;
1128 }
1129 break;
1130
1131 default:
1132 break;
1133 }
1134
1135 cmdoffset += load_command.cmdsize;
1136 }
1137
1138 if (!backtrace_close (descriptor, error_callback, data))
1139 goto fail;
1140 descriptor = -1;
1141
1142 backtrace_release_view (state, &cmds_view, error_callback, data);
1143 cmds_view_valid = 0;
1144
1145 if (match_uuid != NULL)
1146 {
1147 /* If we don't have a UUID, or it doesn't match, just ignore
1148 this file. */
1149 if (!have_uuid
1150 || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)
1151 return 1;
1152 }
1153
1154 if (have_dwarf)
1155 {
1156 int is_big_endian;
1157
1158 is_big_endian = 0;
1159#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
1160#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1161 is_big_endian = 1;
1162#endif
1163#endif
1164
1165 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1166 is_big_endian, NULL, error_callback, data,
1167 fileline_fn, NULL))
1168 goto fail;
1169 }
1170
1171 if (!have_dwarf && have_uuid)
1172 {
1173 if (!macho_add_dsym (state, filename, base_address, &uuid[0],
1174 error_callback, data, fileline_fn))
1175 goto fail;
1176 }
1177
1178 return 1;
1179
1180 fail:
1181 if (cmds_view_valid)
1182 backtrace_release_view (state, &cmds_view, error_callback, data);
1183 if (descriptor != -1)
1184 backtrace_close (descriptor, error_callback, data);
1185 return 0;
1186}
1187
1188#ifdef HAVE_MACH_O_DYLD_H
1189
1190/* Initialize the backtrace data we need from a Mach-O executable
1191 using the dyld support functions. This closes descriptor. */
1192
1193int
1194backtrace_initialize (struct backtrace_state *state, const char *filename,
1195 int descriptor, backtrace_error_callback error_callback,
1196 void *data, fileline *fileline_fn)
1197{
1198 uint32_t c;
1199 uint32_t i;
1200 int closed_descriptor;
1201 int found_sym;
1202 fileline macho_fileline_fn;
1203
1204 closed_descriptor = 0;
1205 found_sym = 0;
1206 macho_fileline_fn = macho_nodebug;
1207
1208 c = _dyld_image_count ();
1209 for (i = 0; i < c; ++i)
1210 {
1211 struct libbacktrace_base_address base_address;
1212 const char *name;
1213 int d;
1214 fileline mff;
1215 int mfs;
1216
1217 name = _dyld_get_image_name (i);
1218 if (name == NULL)
1219 continue;
1220
1221 if (strcmp (name, filename) == 0 && !closed_descriptor)
1222 {
1223 d = descriptor;
1224 closed_descriptor = 1;
1225 }
1226 else
1227 {
1228 int does_not_exist;
1229
1230 d = backtrace_open (name, error_callback, data, &does_not_exist);
1231 if (d < 0)
1232 continue;
1233 }
1234
1235 base_address.m = _dyld_get_image_vmaddr_slide (i);
1236
1237 mff = macho_nodebug;
1238 if (!macho_add (state, name, d, 0, NULL, base_address, 0,
1239 error_callback, data, &mff, &mfs))
1240 continue;
1241
1242 if (mff != macho_nodebug)
1243 macho_fileline_fn = mff;
1244 if (mfs)
1245 found_sym = 1;
1246 }
1247
1248 if (!closed_descriptor)
1249 backtrace_close (descriptor, error_callback, data);
1250
1251 if (!state->threaded)
1252 {
1253 if (found_sym)
1254 state->syminfo_fn = macho_syminfo;
1255 else if (state->syminfo_fn == NULL)
1256 state->syminfo_fn = macho_nosyms;
1257 }
1258 else
1259 {
1260 if (found_sym)
1261 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1262 else
1263 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1264 macho_nosyms);
1265 }
1266
1267 if (!state->threaded)
1268 *fileline_fn = state->fileline_fn;
1269 else
1270 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1271
1272 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1273 *fileline_fn = macho_fileline_fn;
1274
1275 return 1;
1276}
1277
1278#else /* !defined (HAVE_MACH_O_DYLD_H) */
1279
1280/* Initialize the backtrace data we need from a Mach-O executable
1281 without using the dyld support functions. This closes
1282 descriptor. */
1283
1284int
1285backtrace_initialize (struct backtrace_state *state, const char *filename,
1286 int descriptor, backtrace_error_callback error_callback,
1287 void *data, fileline *fileline_fn)
1288{
1289 fileline macho_fileline_fn;
1290 struct libbacktrace_base_address zero_base_address;
1291 int found_sym;
1292
1293 macho_fileline_fn = macho_nodebug;
1294 memset (&zero_base_address, 0, sizeof zero_base_address);
1295 if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,
1296 error_callback, data, &macho_fileline_fn, &found_sym))
1297 return 0;
1298
1299 if (!state->threaded)
1300 {
1301 if (found_sym)
1302 state->syminfo_fn = macho_syminfo;
1303 else if (state->syminfo_fn == NULL)
1304 state->syminfo_fn = macho_nosyms;
1305 }
1306 else
1307 {
1308 if (found_sym)
1309 backtrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);
1310 else
1311 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1312 macho_nosyms);
1313 }
1314
1315 if (!state->threaded)
1316 *fileline_fn = state->fileline_fn;
1317 else
1318 *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1319
1320 if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)
1321 *fileline_fn = macho_fileline_fn;
1322
1323 return 1;
1324}
1325
1326#endif /* !defined (HAVE_MACH_O_DYLD_H) */
1327// mmapio.c:
1328#include <errno.h>
1329#include <sys/types.h>
1330#include <sys/mman.h>
1331#include <unistd.h>
1332
1333
1334#ifndef HAVE_DECL_GETPAGESIZE
1335extern int getpagesize (void);
1336#endif
1337
1338#ifndef MAP_FAILED
1339#define MAP_FAILED ((void *)-1)
1340#endif
1341
1342/* This file implements file views and memory allocation when mmap is
1343 available. */
1344
1345/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */
1346
1347int
1348backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
1349 int descriptor, off_t offset, uint64_t size,
1350 backtrace_error_callback error_callback,
1351 void *data, struct backtrace_view *view)
1352{
1353 size_t pagesize;
1354 unsigned int inpage;
1355 off_t pageoff;
1356 void *map;
1357
1358 if ((uint64_t) (size_t) size != size)
1359 {
1360 error_callback (data, "file size too large", 0);
1361 return 0;
1362 }
1363
1364 pagesize = getpagesize ();
1365 inpage = offset % pagesize;
1366 pageoff = offset - inpage;
1367
1368 size += inpage;
1369 size = (size + (pagesize - 1)) & ~ (pagesize - 1);
1370
1371 map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
1372 if (map == MAP_FAILED)
1373 {
1374 error_callback (data, "mmap", errno);
1375 return 0;
1376 }
1377
1378 view->data = (char *) map + inpage;
1379 view->base = map;
1380 view->len = size;
1381
1382 return 1;
1383}
1384
1385/* Release a view read by backtrace_get_view. */
1386
1387void
1388backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
1389 struct backtrace_view *view,
1390 backtrace_error_callback error_callback,
1391 void *data)
1392{
1393 union {
1394 const void *cv;
1395 void *v;
1396 } const_cast;
1397
1398 const_cast.cv = view->base;
1399 if (munmap (const_cast.v, view->len) < 0)
1400 error_callback (data, "munmap", errno);
1401}
1402// mmap.c:
1403#include <errno.h>
1404#include <string.h>
1405#include <stdlib.h>
1406#include <unistd.h>
1407#include <sys/types.h>
1408#include <sys/mman.h>
1409
1410
1411#ifndef HAVE_DECL_GETPAGESIZE
1412extern int getpagesize (void);
1413#endif
1414
1415/* Memory allocation on systems that provide anonymous mmap. This
1416 permits the backtrace functions to be invoked from a signal
1417 handler, assuming that mmap is async-signal safe. */
1418
1419#ifndef MAP_ANONYMOUS
1420#define MAP_ANONYMOUS MAP_ANON
1421#endif
1422
1423#ifndef MAP_FAILED
1424#define MAP_FAILED ((void *)-1)
1425#endif
1426
1427/* A list of free memory blocks. */
1428
1429struct backtrace_freelist_struct
1430{
1431 /* Next on list. */
1432 struct backtrace_freelist_struct *next;
1433 /* Size of this block, including this structure. */
1434 size_t size;
1435};
1436
1437/* Free memory allocated by backtrace_alloc. */
1438
1439static void
1440backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size)
1441{
1442 /* Just leak small blocks. We don't have to be perfect. Don't put
1443 more than 16 entries on the free list, to avoid wasting time
1444 searching when allocating a block. If we have more than 16
1445 entries, leak the smallest entry. */
1446
1447 if (size >= sizeof (struct backtrace_freelist_struct))
1448 {
1449 size_t c;
1450 struct backtrace_freelist_struct **ppsmall;
1451 struct backtrace_freelist_struct **pp;
1452 struct backtrace_freelist_struct *p;
1453
1454 c = 0;
1455 ppsmall = NULL;
1456 for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)
1457 {
1458 if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size)
1459 ppsmall = pp;
1460 ++c;
1461 }
1462 if (c >= 16)
1463 {
1464 if (size <= (*ppsmall)->size)
1465 return;
1466 *ppsmall = (*ppsmall)->next;
1467 }
1468
1469 p = (struct backtrace_freelist_struct *) addr;
1470 p->next = state->freelist;
1471 p->size = size;
1472 state->freelist = p;
1473 }
1474}
1475
1476/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
1477 report an error. */
1478
1479void *
1480backtrace_alloc (struct backtrace_state *state,
1481 size_t size, backtrace_error_callback error_callback,
1482 void *data)
1483{
1484 void *ret;
1485 int locked;
1486 struct backtrace_freelist_struct **pp;
1487 size_t pagesize;
1488 size_t asksize;
1489 void *page;
1490
1491 ret = NULL;
1492
1493 /* If we can acquire the lock, then see if there is space on the
1494 free list. If we can't acquire the lock, drop straight into
1495 using mmap. __sync_lock_test_and_set returns the old state of
1496 the lock, so we have acquired it if it returns 0. */
1497
1498 if (!state->threaded)
1499 locked = 1;
1500 else
1501 locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
1502
1503 if (locked)
1504 {
1505 for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)
1506 {
1507 if ((*pp)->size >= size)
1508 {
1509 struct backtrace_freelist_struct *p;
1510
1511 p = *pp;
1512 *pp = p->next;
1513
1514 /* Round for alignment; we assume that no type we care about
1515 is more than 8 bytes. */
1516 size = (size + 7) & ~ (size_t) 7;
1517 if (size < p->size)
1518 backtrace_free_locked (state, (char *) p + size,
1519 p->size - size);
1520
1521 ret = (void *) p;
1522
1523 break;
1524 }
1525 }
1526
1527 if (state->threaded)
1528 __sync_lock_release (&state->lock_alloc);
1529 }
1530
1531 if (ret == NULL)
1532 {
1533 /* Allocate a new page. */
1534
1535 pagesize = getpagesize ();
1536 asksize = (size + pagesize - 1) & ~ (pagesize - 1);
1537 page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,
1538 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1539 if (page == MAP_FAILED)
1540 {
1541 if (error_callback)
1542 error_callback (data, "mmap", errno);
1543 }
1544 else
1545 {
1546 size = (size + 7) & ~ (size_t) 7;
1547 if (size < asksize)
1548 backtrace_free (state, (char *) page + size, asksize - size,
1549 error_callback, data);
1550
1551 ret = page;
1552 }
1553 }
1554
1555 return ret;
1556}
1557
1558/* Free memory allocated by backtrace_alloc. */
1559
1560void
1561backtrace_free (struct backtrace_state *state, void *addr, size_t size,
1562 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
1563 void *data ATTRIBUTE_UNUSED)
1564{
1565 int locked;
1566
1567 /* If we are freeing a large aligned block, just release it back to
1568 the system. This case arises when growing a vector for a large
1569 binary with lots of debug info. Calling munmap here may cause us
1570 to call mmap again if there is also a large shared library; we
1571 just live with that. */
1572 if (size >= 16 * 4096)
1573 {
1574 size_t pagesize;
1575
1576 pagesize = getpagesize ();
1577 if (((uintptr_t) addr & (pagesize - 1)) == 0
1578 && (size & (pagesize - 1)) == 0)
1579 {
1580 /* If munmap fails for some reason, just add the block to
1581 the freelist. */
1582 if (munmap (addr, size) == 0)
1583 return;
1584 }
1585 }
1586
1587 /* If we can acquire the lock, add the new space to the free list.
1588 If we can't acquire the lock, just leak the memory.
1589 __sync_lock_test_and_set returns the old state of the lock, so we
1590 have acquired it if it returns 0. */
1591
1592 if (!state->threaded)
1593 locked = 1;
1594 else
1595 locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
1596
1597 if (locked)
1598 {
1599 backtrace_free_locked (state, addr, size);
1600
1601 if (state->threaded)
1602 __sync_lock_release (&state->lock_alloc);
1603 }
1604}
1605
1606/* Grow VEC by SIZE bytes. */
1607
1608void *
1609backtrace_vector_grow (struct backtrace_state *state,size_t size,
1610 backtrace_error_callback error_callback,
1611 void *data, struct backtrace_vector *vec)
1612{
1613 void *ret;
1614
1615 if (size > vec->alc)
1616 {
1617 size_t pagesize;
1618 size_t alc;
1619 void *base;
1620
1621 pagesize = getpagesize ();
1622 alc = vec->size + size;
1623 if (vec->size == 0)
1624 alc = 16 * size;
1625 else if (alc < pagesize)
1626 {
1627 alc *= 2;
1628 if (alc > pagesize)
1629 alc = pagesize;
1630 }
1631 else
1632 {
1633 alc *= 2;
1634 alc = (alc + pagesize - 1) & ~ (pagesize - 1);
1635 }
1636 base = backtrace_alloc (state, alc, error_callback, data);
1637 if (base == NULL)
1638 return NULL;
1639 if (vec->base != NULL)
1640 {
1641 memcpy (base, vec->base, vec->size);
1642 backtrace_free (state, vec->base, vec->size + vec->alc,
1643 error_callback, data);
1644 }
1645 vec->base = base;
1646 vec->alc = alc - vec->size;
1647 }
1648
1649 ret = (char *) vec->base + vec->size;
1650 vec->size += size;
1651 vec->alc -= size;
1652 return ret;
1653}
1654
1655/* Finish the current allocation on VEC. */
1656
1657void *
1658backtrace_vector_finish (
1659 struct backtrace_state *state ATTRIBUTE_UNUSED,
1660 struct backtrace_vector *vec,
1661 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
1662 void *data ATTRIBUTE_UNUSED)
1663{
1664 void *ret;
1665
1666 ret = vec->base;
1667 vec->base = (char *) vec->base + vec->size;
1668 vec->size = 0;
1669 return ret;
1670}
1671
1672/* Release any extra space allocated for VEC. */
1673
1674int
1675backtrace_vector_release (struct backtrace_state *state,
1676 struct backtrace_vector *vec,
1677 backtrace_error_callback error_callback,
1678 void *data)
1679{
1680 size_t size;
1681 size_t alc;
1682 size_t aligned;
1683
1684 /* Make sure that the block that we free is aligned on an 8-byte
1685 boundary. */
1686 size = vec->size;
1687 alc = vec->alc;
1688 aligned = (size + 7) & ~ (size_t) 7;
1689 alc -= aligned - size;
1690
1691 backtrace_free (state, (char *) vec->base + aligned, alc,
1692 error_callback, data);
1693 vec->alc = 0;
1694 if (vec->size == 0)
1695 vec->base = NULL;
1696 return 1;
1697}
1698