]>
git.saurik.com Git - apple/libc.git/blob - gen/backtrace.c
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <mach/vm_types.h>
32 #include "stack_logging.h"
35 int backtrace(void** buffer
, int size
) {
36 extern void _thread_stack_pcs(vm_address_t
*buffer
, unsigned max
, unsigned *nb
, unsigned skip
);
37 unsigned int num_frames
;
38 _thread_stack_pcs((vm_address_t
*)buffer
, size
, &num_frames
, 1);
39 while (num_frames
>= 1 && buffer
[num_frames
-1] == NULL
) num_frames
-= 1;
44 #define _BACKTRACE_FORMAT "%-4d%-35s 0x%016x %s + %u"
45 #define _BACKTRACE_FORMAT_SIZE 82
47 #define _BACKTRACE_FORMAT "%-4d%-35s 0x%08x %s + %u"
48 #define _BACKTRACE_FORMAT_SIZE 65
52 static int _backtrace_snprintf(char* buf
, size_t size
, int frame
, const void* addr
, const Dl_info
* info
) {
54 const char* image
= "???";
55 const char* symbol
= symbuf
;
57 if (info
->dli_fname
) {
58 image
= strrchr(info
->dli_fname
, '/') + 1;
59 if (image
== NULL
) image
= info
->dli_fname
;
62 if (info
->dli_sname
) {
63 symbol
= info
->dli_sname
;
65 snprintf(symbuf
, sizeof(symbuf
), "0x%x", info
->dli_saddr
);
68 return snprintf(buf
, size
,
74 addr
- info
->dli_saddr
) + 1;
77 char** backtrace_symbols(void* const* buffer
, int size
) {
83 Dl_info
* info
= calloc(size
, sizeof (Dl_info
));
85 if (info
== NULL
) return NULL
;
87 // Compute the total size for the block that is returned.
88 // The block will contain size number of pointers to the
89 // symbol descriptions.
91 total_bytes
= sizeof(char*) * size
;
93 // Plus each symbol description
94 for (i
= 0 ; i
< size
; ++i
) {
95 dladdr(buffer
[i
], &info
[i
]);
96 total_bytes
+= _BACKTRACE_FORMAT_SIZE
+ 1;
97 if (info
[i
].dli_sname
) total_bytes
+= strlen(info
[i
].dli_sname
);
100 result
= (char**)malloc(total_bytes
);
101 if (result
== NULL
) {
106 // Fill in the array of pointers and append the strings for
107 // each symbol description.
110 strs
= ((intptr_t)result
) + sizeof(char*) * size
;
112 for (i
= 0; i
< size
; ++i
) {
113 ptrs
[i
] = (char*)strs
;
114 strs
+= _backtrace_snprintf((char*)strs
, total_bytes
, i
, buffer
[i
], &info
[i
]);
122 void backtrace_symbols_fd(void* const* buffer
, int size
, int fd
) {
128 iov
[0].iov_base
= buf
;
130 iov
[1].iov_base
= "\n";
133 for (i
= 0; i
< size
; ++i
) {
134 memset(&info
, 0, sizeof(info
));
135 dladdr(buffer
[i
], &info
);
137 iov
[0].iov_len
= _backtrace_snprintf(buf
, sizeof(buf
), i
, buffer
[i
], &info
);