annotate libbacktrace/macho.c @ 158:494b0b89df80 default tip

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