]>
git.saurik.com Git - apple/libc.git/blob - gen/backtrace.c
c075de253b56d4c822b76c3a8781fcb33df9bd55
2 * Copyright (c) 2007, 2008 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>
33 #include "stack_logging.h"
36 int backtrace(void** buffer
, int size
) {
37 extern void _thread_stack_pcs(vm_address_t
*buffer
, unsigned max
, unsigned *nb
, unsigned skip
);
38 unsigned int num_frames
;
39 _thread_stack_pcs((vm_address_t
*)buffer
, size
, &num_frames
, 1);
40 while (num_frames
>= 1 && buffer
[num_frames
-1] == NULL
) num_frames
-= 1;
45 #define _BACKTRACE_FORMAT "%-4d%-35s 0x%016lx %s + %lu"
46 #define _BACKTRACE_FORMAT_SIZE 83 /* %lu can take up to 20, does not include %s, includes NUL */
47 #define _BACKTRACE_ADDRESS_LEN 18 /* 0x + 16 (no NUL) */
49 #define _BACKTRACE_FORMAT "%-4d%-35s 0x%08lx %s + %lu"
50 #define _BACKTRACE_FORMAT_SIZE 65 /* %lu can take up to 10, does not include %s, includes NUL */
51 #define _BACKTRACE_ADDRESS_LEN 10 /* 0x + 8 (no NUL) */
54 static int _backtrace_snprintf(char* buf
, size_t size
, int frame
, const void* addr
, const Dl_info
* info
) {
55 char symbuf
[_BACKTRACE_ADDRESS_LEN
+ 1];
56 const char* image
= "???";
57 const char* symbol
= "0x0";
58 uintptr_t symbol_offset
= 0;
60 if (info
->dli_fname
) {
61 const char *tmp
= strrchr(info
->dli_fname
, '/');
63 image
= info
->dli_fname
;
68 if (info
->dli_sname
) {
69 symbol
= info
->dli_sname
;
70 symbol_offset
= (uintptr_t)addr
- (uintptr_t)info
->dli_saddr
;
71 } else if(info
->dli_fname
) {
73 symbol_offset
= (uintptr_t)addr
- (uintptr_t)info
->dli_fbase
;
74 } else if(0 < snprintf(symbuf
, sizeof(symbuf
), "0x%lx", (uintptr_t)info
->dli_saddr
)) {
76 symbol_offset
= (uintptr_t)addr
- (uintptr_t)info
->dli_saddr
;
78 symbol_offset
= (uintptr_t)addr
;
81 return snprintf(buf
, size
,
90 char** backtrace_symbols(void* const* buffer
, int size
) {
96 Dl_info
* info
= calloc(size
, sizeof (Dl_info
));
98 if (info
== NULL
) return NULL
;
100 // Compute the total size for the block that is returned.
101 // The block will contain size number of pointers to the
102 // symbol descriptions.
104 total_bytes
= sizeof(char*) * size
;
106 // Plus each symbol description
107 for (i
= 0 ; i
< size
; ++i
) {
108 dladdr(buffer
[i
], &info
[i
]);
109 total_bytes
+= _BACKTRACE_FORMAT_SIZE
;
110 if (info
[i
].dli_sname
) {
111 total_bytes
+= strlen(info
[i
].dli_sname
);
112 } else if(info
[i
].dli_fname
) {
113 const char *tmp
= strrchr(info
->dli_fname
, '/');
115 total_bytes
+= strlen(info
->dli_fname
);
117 total_bytes
+= strlen(tmp
+ 1);
119 total_bytes
+= _BACKTRACE_ADDRESS_LEN
;
123 result
= (char**)malloc(total_bytes
);
124 if (result
== NULL
) {
128 end
= (intptr_t)result
+ total_bytes
;
130 // Fill in the array of pointers and append the strings for
131 // each symbol description.
134 strs
= ((intptr_t)result
) + sizeof(char*) * size
;
136 for (i
= 0; i
< size
; ++i
) {
137 int chk
= _backtrace_snprintf((char*)strs
, end
- (intptr_t)strs
, i
, buffer
[i
], &info
[i
]);
144 ptrs
[i
] = (char*)strs
;
153 void backtrace_symbols_fd(void* const* buffer
, int size
, int fd
) {
159 iov
[0].iov_base
= buf
;
161 iov
[1].iov_base
= "\n";
164 for (i
= 0; i
< size
; ++i
) {
165 memset(&info
, 0, sizeof(info
));
166 dladdr(buffer
[i
], &info
);
168 iov
[0].iov_len
= _backtrace_snprintf(buf
, sizeof(buf
), i
, buffer
[i
], &info
);