1 /* 2 * Copyright (c) 2013 Luca Clementi <luca.clementi (at) gmail.com> 3 * Copyright (c) 2013-2018 The strace developers. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "defs.h" 29 #include <limits.h> 30 #include <libunwind-ptrace.h> 31 32 #ifdef USE_DEMANGLE 33 # if defined HAVE_DEMANGLE_H 34 # include <demangle.h> 35 # elif defined HAVE_LIBIBERTY_DEMANGLE_H 36 # include <libiberty/demangle.h> 37 # endif 38 #endif 39 40 #include "xstring.h" 41 42 #ifdef _LARGEFILE64_SOURCE 43 # ifdef HAVE_FOPEN64 44 # define fopen_for_input fopen64 45 # else 46 # define fopen_for_input fopen 47 # endif 48 #else 49 # define fopen_for_input fopen 50 #endif 51 52 /* 53 * Keep a sorted array of cache entries, 54 * so that we can binary search through it. 55 */ 56 struct mmap_cache_t { 57 /** 58 * example entry: 59 * 7fabbb09b000-7fabbb09f000 r-xp 00179000 fc:00 1180246 /lib/libc-2.11.1.so 60 * 61 * start_addr is 0x7fabbb09b000 62 * end_addr is 0x7fabbb09f000 63 * mmap_offset is 0x179000 64 * binary_filename is "/lib/libc-2.11.1.so" 65 */ 66 unsigned long start_addr; 67 unsigned long end_addr; 68 unsigned long mmap_offset; 69 char *binary_filename; 70 }; 71 72 /* 73 * Type used in stacktrace walker 74 */ 75 typedef void (*call_action_fn)(void *data, 76 const char *binary_filename, 77 const char *symbol_name, 78 unw_word_t function_offset, 79 unsigned long true_offset); 80 typedef void (*error_action_fn)(void *data, 81 const char *error, 82 unsigned long true_offset); 83 84 /* 85 * Type used in stacktrace capturing 86 */ 87 struct call_t { 88 struct call_t *next; 89 char *output_line; 90 }; 91 92 struct queue_t { 93 struct call_t *tail; 94 struct call_t *head; 95 }; 96 97 static void queue_print(struct queue_t *queue); 98 static void delete_mmap_cache(struct tcb *tcp, const char *caller); 99 100 static unw_addr_space_t libunwind_as; 101 static unsigned int mmap_cache_generation; 102 103 static const char asprintf_error_str[] = "???"; 104 105 void 106 unwind_init(void) 107 { 108 libunwind_as = unw_create_addr_space(&_UPT_accessors, 0); 109 if (!libunwind_as) 110 error_msg_and_die("failed to create address space for stack tracing"); 111 unw_set_caching_policy(libunwind_as, UNW_CACHE_GLOBAL); 112 } 113 114 void 115 unwind_tcb_init(struct tcb *tcp) 116 { 117 if (tcp->libunwind_ui) 118 return; 119 120 tcp->libunwind_ui = _UPT_create(tcp->pid); 121 if (!tcp->libunwind_ui) 122 perror_msg_and_die("_UPT_create"); 123 124 tcp->queue = xmalloc(sizeof(*tcp->queue)); 125 tcp->queue->head = NULL; 126 tcp->queue->tail = NULL; 127 } 128 129 void 130 unwind_tcb_fin(struct tcb *tcp) 131 { 132 queue_print(tcp->queue); 133 free(tcp->queue); 134 tcp->queue = NULL; 135 136 delete_mmap_cache(tcp, __func__); 137 138 _UPT_destroy(tcp->libunwind_ui); 139 tcp->libunwind_ui = NULL; 140 } 141 142 /* 143 * caching of /proc/ID/maps for each process to speed up stack tracing 144 * 145 * The cache must be refreshed after syscalls that affect memory mappings, 146 * e.g. mmap, mprotect, munmap, execve. 147 */ 148 static void 149 build_mmap_cache(struct tcb *tcp) 150 { 151 FILE *fp; 152 struct mmap_cache_t *cache_head = NULL; 153 size_t cur_array_size = 0; 154 char filename[sizeof("/proc/4294967296/maps")]; 155 char buffer[PATH_MAX + 80]; 156 157 unw_flush_cache(libunwind_as, 0, 0); 158 159 xsprintf(filename, "/proc/%u/maps", tcp->pid); 160 fp = fopen_for_input(filename, "r"); 161 if (!fp) { 162 perror_msg("fopen: %s", filename); 163 return; 164 } 165 166 while (fgets(buffer, sizeof(buffer), fp) != NULL) { 167 struct mmap_cache_t *entry; 168 unsigned long start_addr, end_addr, mmap_offset; 169 char exec_bit; 170 char binary_path[sizeof(buffer)]; 171 172 if (sscanf(buffer, "%lx-%lx %*c%*c%c%*c %lx %*x:%*x %*d %[^\n]", 173 &start_addr, &end_addr, &exec_bit, 174 &mmap_offset, binary_path) != 5) 175 continue; 176 177 /* ignore mappings that have no PROT_EXEC bit set */ 178 if (exec_bit != 'x') 179 continue; 180 181 if (end_addr < start_addr) { 182 error_msg("%s: unrecognized file format", filename); 183 break; 184 } 185 186 /* 187 * sanity check to make sure that we're storing 188 * non-overlapping regions in ascending order 189 */ 190 if (tcp->mmap_cache_size > 0) { 191 entry = &cache_head[tcp->mmap_cache_size - 1]; 192 if (entry->start_addr == start_addr && 193 entry->end_addr == end_addr) { 194 /* duplicate entry, e.g. [vsyscall] */ 195 continue; 196 } 197 if (start_addr <= entry->start_addr || 198 start_addr < entry->end_addr) { 199 debug_msg("%s: overlapping memory region: " 200 "\"%s\" [%08lx-%08lx] overlaps with " 201 "\"%s\" [%08lx-%08lx]", 202 filename, binary_path, start_addr, 203 end_addr, entry->binary_filename, 204 entry->start_addr, entry->end_addr); 205 continue; 206 } 207 } 208 209 if (tcp->mmap_cache_size >= cur_array_size) 210 cache_head = xgrowarray(cache_head, &cur_array_size, 211 sizeof(*cache_head)); 212 213 entry = &cache_head[tcp->mmap_cache_size]; 214 entry->start_addr = start_addr; 215 entry->end_addr = end_addr; 216 entry->mmap_offset = mmap_offset; 217 entry->binary_filename = xstrdup(binary_path); 218 tcp->mmap_cache_size++; 219 } 220 fclose(fp); 221 tcp->mmap_cache = cache_head; 222 tcp->mmap_cache_generation = mmap_cache_generation; 223 224 debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p", 225 tcp->mmap_cache_generation, 226 mmap_cache_generation, 227 tcp, tcp->mmap_cache); 228 } 229 230 /* deleting the cache */ 231 static void 232 delete_mmap_cache(struct tcb *tcp, const char *caller) 233 { 234 unsigned int i; 235 236 debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p, caller=%s", 237 tcp->mmap_cache_generation, 238 mmap_cache_generation, 239 tcp, tcp->mmap_cache, caller); 240 241 for (i = 0; i < tcp->mmap_cache_size; i++) { 242 free(tcp->mmap_cache[i].binary_filename); 243 tcp->mmap_cache[i].binary_filename = NULL; 244 } 245 free(tcp->mmap_cache); 246 tcp->mmap_cache = NULL; 247 tcp->mmap_cache_size = 0; 248 } 249 250 static bool 251 rebuild_cache_if_invalid(struct tcb *tcp, const char *caller) 252 { 253 if ((tcp->mmap_cache_generation != mmap_cache_generation) 254 && tcp->mmap_cache) 255 delete_mmap_cache(tcp, caller); 256 257 if (!tcp->mmap_cache) 258 build_mmap_cache(tcp); 259 260 return tcp->mmap_cache && tcp->mmap_cache_size; 261 } 262 263 void 264 unwind_cache_invalidate(struct tcb *tcp) 265 { 266 #if SUPPORTED_PERSONALITIES > 1 267 if (tcp->currpers != DEFAULT_PERSONALITY) { 268 /* disable stack trace */ 269 return; 270 } 271 #endif 272 mmap_cache_generation++; 273 debug_func_msg("tgen=%u, ggen=%u, tcp=%p, cache=%p", 274 tcp->mmap_cache_generation, 275 mmap_cache_generation, 276 tcp, tcp->mmap_cache); 277 } 278 279 static void 280 get_symbol_name(unw_cursor_t *cursor, char **name, 281 size_t *size, unw_word_t *offset) 282 { 283 for (;;) { 284 int rc = unw_get_proc_name(cursor, *name, *size, offset); 285 if (rc == 0) 286 break; 287 if (rc != -UNW_ENOMEM) { 288 **name = '\0'; 289 *offset = 0; 290 break; 291 } 292 *name = xgrowarray(*name, size, 1); 293 } 294 } 295 296 static int 297 print_stack_frame(struct tcb *tcp, 298 call_action_fn call_action, 299 error_action_fn error_action, 300 void *data, 301 unw_cursor_t *cursor, 302 char **symbol_name, 303 size_t *symbol_name_size) 304 { 305 unw_word_t ip; 306 int lower = 0; 307 int upper = (int) tcp->mmap_cache_size - 1; 308 309 if (unw_get_reg(cursor, UNW_REG_IP, &ip) < 0) { 310 perror_msg("Can't walk the stack of process %d", tcp->pid); 311 return -1; 312 } 313 314 while (lower <= upper) { 315 struct mmap_cache_t *cur_mmap_cache; 316 int mid = (upper + lower) / 2; 317 318 cur_mmap_cache = &tcp->mmap_cache[mid]; 319 320 if (ip >= cur_mmap_cache->start_addr && 321 ip < cur_mmap_cache->end_addr) { 322 unsigned long true_offset; 323 unw_word_t function_offset; 324 325 get_symbol_name(cursor, symbol_name, symbol_name_size, 326 &function_offset); 327 true_offset = ip - cur_mmap_cache->start_addr + 328 cur_mmap_cache->mmap_offset; 329 330 #ifdef USE_DEMANGLE 331 char *demangled_name = 332 cplus_demangle(*symbol_name, 333 DMGL_AUTO | DMGL_PARAMS); 334 #endif 335 336 call_action(data, 337 cur_mmap_cache->binary_filename, 338 #ifdef USE_DEMANGLE 339 demangled_name ? demangled_name : 340 #endif 341 *symbol_name, 342 function_offset, 343 true_offset); 344 #ifdef USE_DEMANGLE 345 free(demangled_name); 346 #endif 347 348 return 0; 349 } else if (ip < cur_mmap_cache->start_addr) 350 upper = mid - 1; 351 else 352 lower = mid + 1; 353 } 354 355 /* 356 * there is a bug in libunwind >= 1.0 357 * after a set_tid_address syscall 358 * unw_get_reg returns IP == 0 359 */ 360 if (ip) 361 error_action(data, "unexpected_backtracing_error", ip); 362 return -1; 363 } 364 365 /* 366 * walking the stack 367 */ 368 static void 369 stacktrace_walk(struct tcb *tcp, 370 call_action_fn call_action, 371 error_action_fn error_action, 372 void *data) 373 { 374 char *symbol_name; 375 size_t symbol_name_size = 40; 376 unw_cursor_t cursor; 377 int stack_depth; 378 379 if (!tcp->mmap_cache) 380 error_msg_and_die("bug: mmap_cache is NULL"); 381 if (tcp->mmap_cache_size == 0) 382 error_msg_and_die("bug: mmap_cache is empty"); 383 384 symbol_name = xmalloc(symbol_name_size); 385 386 if (unw_init_remote(&cursor, libunwind_as, tcp->libunwind_ui) < 0) 387 perror_msg_and_die("Can't initiate libunwind"); 388 389 for (stack_depth = 0; stack_depth < 256; ++stack_depth) { 390 if (print_stack_frame(tcp, call_action, error_action, data, 391 &cursor, &symbol_name, &symbol_name_size) < 0) 392 break; 393 if (unw_step(&cursor) <= 0) 394 break; 395 } 396 if (stack_depth >= 256) 397 error_action(data, "too many stack frames", 0); 398 399 free(symbol_name); 400 } 401 402 /* 403 * printing an entry in stack to stream or buffer 404 */ 405 /* 406 * we want to keep the format used by backtrace_symbols from the glibc 407 * 408 * ./a.out() [0x40063d] 409 * ./a.out() [0x4006bb] 410 * ./a.out() [0x4006c6] 411 * /lib64/libc.so.6(__libc_start_main+0xed) [0x7fa2f8a5976d] 412 * ./a.out() [0x400569] 413 */ 414 #define STACK_ENTRY_SYMBOL_FMT \ 415 " > %s(%s+0x%lx) [0x%lx]\n", \ 416 binary_filename, \ 417 symbol_name, \ 418 (unsigned long) function_offset, \ 419 true_offset 420 #define STACK_ENTRY_NOSYMBOL_FMT \ 421 " > %s() [0x%lx]\n", \ 422 binary_filename, true_offset 423 #define STACK_ENTRY_BUG_FMT \ 424 " > BUG IN %s\n" 425 #define STACK_ENTRY_ERROR_WITH_OFFSET_FMT \ 426 " > %s [0x%lx]\n", error, true_offset 427 #define STACK_ENTRY_ERROR_FMT \ 428 " > %s\n", error 429 430 static void 431 print_call_cb(void *dummy, 432 const char *binary_filename, 433 const char *symbol_name, 434 unw_word_t function_offset, 435 unsigned long true_offset) 436 { 437 if (symbol_name && (symbol_name[0] != '\0')) 438 tprintf(STACK_ENTRY_SYMBOL_FMT); 439 else if (binary_filename) 440 tprintf(STACK_ENTRY_NOSYMBOL_FMT); 441 else 442 tprintf(STACK_ENTRY_BUG_FMT, __func__); 443 444 line_ended(); 445 } 446 447 static void 448 print_error_cb(void *dummy, 449 const char *error, 450 unsigned long true_offset) 451 { 452 if (true_offset) 453 tprintf(STACK_ENTRY_ERROR_WITH_OFFSET_FMT); 454 else 455 tprintf(STACK_ENTRY_ERROR_FMT); 456 457 line_ended(); 458 } 459 460 static char * 461 sprint_call_or_error(const char *binary_filename, 462 const char *symbol_name, 463 unw_word_t function_offset, 464 unsigned long true_offset, 465 const char *error) 466 { 467 char *output_line = NULL; 468 int n; 469 470 if (symbol_name) 471 n = asprintf(&output_line, STACK_ENTRY_SYMBOL_FMT); 472 else if (binary_filename) 473 n = asprintf(&output_line, STACK_ENTRY_NOSYMBOL_FMT); 474 else if (error) 475 n = true_offset 476 ? asprintf(&output_line, STACK_ENTRY_ERROR_WITH_OFFSET_FMT) 477 : asprintf(&output_line, STACK_ENTRY_ERROR_FMT); 478 else 479 n = asprintf(&output_line, STACK_ENTRY_BUG_FMT, __func__); 480 481 if (n < 0) { 482 perror_func_msg("asprintf"); 483 output_line = (char *) asprintf_error_str; 484 } 485 486 return output_line; 487 } 488 489 /* 490 * queue manipulators 491 */ 492 static void 493 queue_put(struct queue_t *queue, 494 const char *binary_filename, 495 const char *symbol_name, 496 unw_word_t function_offset, 497 unsigned long true_offset, 498 const char *error) 499 { 500 struct call_t *call; 501 502 call = xmalloc(sizeof(*call)); 503 call->output_line = sprint_call_or_error(binary_filename, 504 symbol_name, 505 function_offset, 506 true_offset, 507 error); 508 call->next = NULL; 509 510 if (!queue->head) { 511 queue->head = call; 512 queue->tail = call; 513 } else { 514 queue->tail->next = call; 515 queue->tail = call; 516 } 517 } 518 519 static void 520 queue_put_call(void *queue, 521 const char *binary_filename, 522 const char *symbol_name, 523 unw_word_t function_offset, 524 unsigned long true_offset) 525 { 526 queue_put(queue, 527 binary_filename, 528 symbol_name, 529 function_offset, 530 true_offset, 531 NULL); 532 } 533 534 static void 535 queue_put_error(void *queue, 536 const char *error, 537 unsigned long ip) 538 { 539 queue_put(queue, NULL, NULL, 0, ip, error); 540 } 541 542 static void 543 queue_print(struct queue_t *queue) 544 { 545 struct call_t *call, *tmp; 546 547 queue->tail = NULL; 548 call = queue->head; 549 queue->head = NULL; 550 while (call) { 551 tmp = call; 552 call = call->next; 553 554 tprints(tmp->output_line); 555 line_ended(); 556 557 if (tmp->output_line != asprintf_error_str) 558 free(tmp->output_line); 559 560 tmp->output_line = NULL; 561 tmp->next = NULL; 562 free(tmp); 563 } 564 } 565 566 /* 567 * printing stack 568 */ 569 void 570 unwind_print_stacktrace(struct tcb *tcp) 571 { 572 #if SUPPORTED_PERSONALITIES > 1 573 if (tcp->currpers != DEFAULT_PERSONALITY) { 574 /* disable stack trace */ 575 return; 576 } 577 #endif 578 if (tcp->queue->head) { 579 debug_func_msg("head: tcp=%p, queue=%p", tcp, tcp->queue->head); 580 queue_print(tcp->queue); 581 } else if (rebuild_cache_if_invalid(tcp, __func__)) { 582 debug_func_msg("walk: tcp=%p, queue=%p", tcp, tcp->queue->head); 583 stacktrace_walk(tcp, print_call_cb, print_error_cb, NULL); 584 } 585 } 586 587 /* 588 * capturing stack 589 */ 590 void 591 unwind_capture_stacktrace(struct tcb *tcp) 592 { 593 #if SUPPORTED_PERSONALITIES > 1 594 if (tcp->currpers != DEFAULT_PERSONALITY) { 595 /* disable stack trace */ 596 return; 597 } 598 #endif 599 if (tcp->queue->head) 600 error_msg_and_die("bug: unprinted entries in queue"); 601 602 if (rebuild_cache_if_invalid(tcp, __func__)) { 603 stacktrace_walk(tcp, queue_put_call, queue_put_error, 604 tcp->queue); 605 debug_func_msg("tcp=%p, queue=%p", tcp, tcp->queue->head); 606 } 607 } 608