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