1327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi/* 2327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * Copyright (c) 2013 Luca Clementi <luca.clementi@gmail.com> 3327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 4327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * Redistribution and use in source and binary forms, with or without 5327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * modification, are permitted provided that the following conditions 6327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * are met: 7327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 1. Redistributions of source code must retain the above copyright 8327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * notice, this list of conditions and the following disclaimer. 9327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 2. Redistributions in binary form must reproduce the above copyright 10327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * notice, this list of conditions and the following disclaimer in the 11327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * documentation and/or other materials provided with the distribution. 12327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 3. The name of the author may not be used to endorse or promote products 13327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * derived from this software without specific prior written permission. 14327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 15327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi */ 26327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 27327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi#include "defs.h" 28327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi#include <limits.h> 29327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi#include <libunwind-ptrace.h> 30327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 31c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin#ifdef _LARGEFILE64_SOURCE 32c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin# ifdef HAVE_FOPEN64 33c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin# define fopen_for_input fopen64 34c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin# else 35c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin# define fopen_for_input fopen 36c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin# endif 37c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin#else 38c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin# define fopen_for_input fopen 39c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin#endif 40c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin 414e121e5bb45f79ec61dc2c01c7625ccf215d8457Masatake YAMATO#define DPRINTF(F, A, ...) if (debug_flag) fprintf(stderr, " [unwind(" A ")] " F "\n", __VA_ARGS__) 424e121e5bb45f79ec61dc2c01c7625ccf215d8457Masatake YAMATO 43327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi/* 44327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * Кeep a sorted array of cache entries, 45327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * so that we can binary search through it. 46327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi */ 47327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementistruct mmap_cache_t { 48327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi /** 49327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * example entry: 509a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin * 7fabbb09b000-7fabbb09f000 r-xp 00179000 fc:00 1180246 /lib/libc-2.11.1.so 51327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 52327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * start_addr is 0x7fabbb09b000 53327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * end_addr is 0x7fabbb09f000 54327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * mmap_offset is 0x179000 55327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * binary_filename is "/lib/libc-2.11.1.so" 56327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi */ 57327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi unsigned long start_addr; 58327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi unsigned long end_addr; 59327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi unsigned long mmap_offset; 60806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin char *binary_filename; 61327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi}; 62327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 632d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO/* 642d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * Type used in stacktrace walker 652d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO */ 662d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOtypedef void (*call_action_fn)(void *data, 67806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *binary_filename, 68806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *symbol_name, 696555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin unw_word_t function_offset, 702d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO unsigned long true_offset); 712d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOtypedef void (*error_action_fn)(void *data, 722d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO const char *error, 732d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO unsigned long true_offset); 742d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 75f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO/* 76f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO * Type used in stacktrace capturing 77f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO */ 78f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstruct call_t { 79f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO struct call_t* next; 80f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO char *output_line; 81f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO}; 82f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 83f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstruct queue_t { 84f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO struct call_t *tail; 85f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO struct call_t *head; 86f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO}; 879bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 88f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstatic void queue_print(struct queue_t *queue); 899bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOstatic void delete_mmap_cache(struct tcb *tcp, const char *caller); 902d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 91327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementistatic unw_addr_space_t libunwind_as; 929bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOstatic unsigned int mmap_cache_generation; 93327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 94327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementivoid 956141392856a170c9297783e6bfbd9fd970f76fdfMasatake YAMATOunwind_init(void) 96327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi{ 97327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi libunwind_as = unw_create_addr_space(&_UPT_accessors, 0); 98327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!libunwind_as) 99327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi error_msg_and_die("failed to create address space for stack tracing"); 100a0b4ee7b38e600f28e547585e754b7737b388d90Masatake YAMATO unw_set_caching_policy(libunwind_as, UNW_CACHE_GLOBAL); 101327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi} 102327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 103327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementivoid 1046141392856a170c9297783e6bfbd9fd970f76fdfMasatake YAMATOunwind_tcb_init(struct tcb *tcp) 105327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi{ 106327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi tcp->libunwind_ui = _UPT_create(tcp->pid); 107327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!tcp->libunwind_ui) 108327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi die_out_of_memory(); 109f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 110f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tcp->queue = malloc(sizeof(*tcp->queue)); 111f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (!tcp->queue) 112f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO die_out_of_memory(); 113f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tcp->queue->head = NULL; 114f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tcp->queue->tail = NULL; 115327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi} 116327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 117327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementivoid 1186141392856a170c9297783e6bfbd9fd970f76fdfMasatake YAMATOunwind_tcb_fin(struct tcb *tcp) 119327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi{ 120f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue_print(tcp->queue); 121f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO free(tcp->queue); 122f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tcp->queue = NULL; 123f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 1249bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO delete_mmap_cache(tcp, __FUNCTION__); 125f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 126327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi _UPT_destroy(tcp->libunwind_ui); 127327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi tcp->libunwind_ui = NULL; 128327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi} 129327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 130327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi/* 131327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * caching of /proc/ID/maps for each process to speed up stack tracing 132327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * 1339a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin * The cache must be refreshed after syscalls that affect memory mappings, 1349a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin * e.g. mmap, mprotect, munmap, execve. 135327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi */ 136b65042fbdb576d13e9bb57c21a890539cab25c43Masatake YAMATOstatic void 1379bc6561588093a788c29f07579f9e4103864a752Masatake YAMATObuild_mmap_cache(struct tcb* tcp) 138327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi{ 1399a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin FILE *fp; 1409a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin struct mmap_cache_t *cache_head; 141327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi /* start with a small dynamically-allocated array and then expand it */ 142327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi size_t cur_array_size = 10; 1439a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin char filename[sizeof("/proc/4294967296/maps")]; 1449a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin char buffer[PATH_MAX + 80]; 145327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 1469a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin unw_flush_cache(libunwind_as, 0, 0); 147a0b4ee7b38e600f28e547585e754b7737b388d90Masatake YAMATO 1489a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin sprintf(filename, "/proc/%u/maps", tcp->pid); 149c903c822ee94478bff1732eb80744e201c074d26Dmitry V. Levin fp = fopen_for_input(filename, "r"); 150327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!fp) { 151327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi perror_msg("fopen: %s", filename); 152327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi return; 153327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi } 154327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 155327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi cache_head = calloc(cur_array_size, sizeof(*cache_head)); 156327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!cache_head) 157327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi die_out_of_memory(); 158327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 159327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi while (fgets(buffer, sizeof(buffer), fp) != NULL) { 1609a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin struct mmap_cache_t *entry; 1619a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin unsigned long start_addr, end_addr, mmap_offset; 16273741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin char exec_bit; 1639a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin char binary_path[PATH_MAX]; 164327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 1659a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin if (sscanf(buffer, "%lx-%lx %*c%*c%c%*c %lx %*x:%*x %*d %[^\n]", 16673741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin &start_addr, &end_addr, &exec_bit, 16773741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin &mmap_offset, binary_path) != 5) 16873741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin continue; 16973741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin 17073741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin /* ignore mappings that have no PROT_EXEC bit set */ 17173741d2e2ee0f9d446b0dc2fbc70be3f5b10521bDmitry V. Levin if (exec_bit != 'x') 172327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi continue; 173327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 1749a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin if (end_addr < start_addr) { 1759a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin error_msg("%s: unrecognized file format", filename); 1769a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin break; 177327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi } 178327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 179327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi /* 180327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * sanity check to make sure that we're storing 181327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi * non-overlapping regions in ascending order 182327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi */ 183327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (tcp->mmap_cache_size > 0) { 1849a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry = &cache_head[tcp->mmap_cache_size - 1]; 1859a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin if (entry->start_addr == start_addr && 1869a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry->end_addr == end_addr) { 1879a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin /* duplicate entry, e.g. [vsyscall] */ 1889a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin continue; 1899a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin } 1909a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin if (start_addr <= entry->start_addr || 1919a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin start_addr < entry->end_addr) { 1929a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin error_msg("%s: overlapping memory region", 1939a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin filename); 1949a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin continue; 1959a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin } 196327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi } 197327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 198327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (tcp->mmap_cache_size >= cur_array_size) { 199327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi cur_array_size *= 2; 2009a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin cache_head = realloc(cache_head, 2019a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin cur_array_size * sizeof(*cache_head)); 202327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!cache_head) 203327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi die_out_of_memory(); 204327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi } 2059a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin 2069a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry = &cache_head[tcp->mmap_cache_size]; 2079a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry->start_addr = start_addr; 2089a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry->end_addr = end_addr; 2099a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry->mmap_offset = mmap_offset; 2109a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin entry->binary_filename = strdup(binary_path); 2119a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin if (!entry->binary_filename) 2129a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin die_out_of_memory(); 2139a349c7779c1c0da89b4eb2821c3b5e6de84adcfDmitry V. Levin tcp->mmap_cache_size++; 214327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi } 215327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi fclose(fp); 216327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi tcp->mmap_cache = cache_head; 2179bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp->mmap_cache_generation = mmap_cache_generation; 2189bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 2199bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO DPRINTF("tgen=%u, ggen=%u, tcp=%p, cache=%p", 2209bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO "cache-build", 2219bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp->mmap_cache_generation, 2229bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO mmap_cache_generation, 2239bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp, tcp->mmap_cache); 224327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi} 225327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 226327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi/* deleting the cache */ 2279bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOstatic void 2289bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOdelete_mmap_cache(struct tcb *tcp, const char *caller) 229327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi{ 230327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi unsigned int i; 2319bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 2329bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO DPRINTF("tgen=%u, ggen=%u, tcp=%p, cache=%p, caller=%s", 2339bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO "cache-delete", 2349bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp->mmap_cache_generation, 2359bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO mmap_cache_generation, 2369bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp, tcp->mmap_cache, caller); 2379bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 238327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi for (i = 0; i < tcp->mmap_cache_size; i++) { 239327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi free(tcp->mmap_cache[i].binary_filename); 240327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi tcp->mmap_cache[i].binary_filename = NULL; 241327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi } 242327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi free(tcp->mmap_cache); 243327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi tcp->mmap_cache = NULL; 244327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi tcp->mmap_cache_size = 0; 245327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi} 246327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 2479bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOstatic bool 2489bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOrebuild_cache_if_invalid(struct tcb *tcp, const char *caller) 2499bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO{ 2509bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO if ((tcp->mmap_cache_generation != mmap_cache_generation) 2519bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO && tcp->mmap_cache) 2529bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO delete_mmap_cache(tcp, caller); 2539bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 2549bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO if (!tcp->mmap_cache) 2559bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO build_mmap_cache(tcp); 2569bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 2579bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO if (!tcp->mmap_cache || !tcp->mmap_cache_size) 2589bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO return false; 2599bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO else 2609bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO return true; 2619bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO} 2629bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 2639bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOvoid 2649bc6561588093a788c29f07579f9e4103864a752Masatake YAMATOunwind_cache_invalidate(struct tcb* tcp) 2659bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO{ 266f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi#if SUPPORTED_PERSONALITIES > 1 267f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi if (tcp->currpers != DEFAULT_PERSONALITY) { 268f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi /* disable strack trace */ 269f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi return; 270f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi } 271f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi#endif 2729bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO mmap_cache_generation++; 2739bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO DPRINTF("tgen=%u, ggen=%u, tcp=%p, cache=%p", "increment", 2749bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp->mmap_cache_generation, 2759bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO mmap_cache_generation, 2769bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp, 2779bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp->mmap_cache); 2789bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO} 2799bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO 28052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levinstatic void 28152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levinget_symbol_name(unw_cursor_t *cursor, char **name, 28252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin size_t *size, unw_word_t *offset) 28352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin{ 28452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin for (;;) { 28552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin int rc = unw_get_proc_name(cursor, *name, *size, offset); 28652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (rc == 0) 28752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin break; 28852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (rc != -UNW_ENOMEM) { 28952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin **name = '\0'; 29052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin *offset = 0; 29152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin break; 29252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin } 29352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin *size *= 2; 29452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin *name = realloc(*name, *size); 29552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (!*name) 29652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin die_out_of_memory(); 29752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin } 29852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin} 29952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 30052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levinstatic int 30152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levinprint_stack_frame(struct tcb *tcp, 30252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin call_action_fn call_action, 30352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin error_action_fn error_action, 30452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin void *data, 30552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin unw_cursor_t *cursor, 30652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin char **symbol_name, 30752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin size_t *symbol_name_size) 30852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin{ 30952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin unw_word_t ip; 31052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin int lower = 0; 31152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin int upper = (int) tcp->mmap_cache_size - 1; 31252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 31352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (unw_get_reg(cursor, UNW_REG_IP, &ip) < 0) { 31452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin perror_msg("Can't walk the stack of process %d", tcp->pid); 31552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin return -1; 31652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin } 31752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 31852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin while (lower <= upper) { 31952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin struct mmap_cache_t *cur_mmap_cache; 32052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin int mid = (upper + lower) / 2; 32152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 32252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin cur_mmap_cache = &tcp->mmap_cache[mid]; 32352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 32452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (ip >= cur_mmap_cache->start_addr && 32552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin ip < cur_mmap_cache->end_addr) { 32652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin unsigned long true_offset; 32752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin unw_word_t function_offset; 32852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 32952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin get_symbol_name(cursor, symbol_name, symbol_name_size, 33052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin &function_offset); 33152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin true_offset = ip - cur_mmap_cache->start_addr + 33252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin cur_mmap_cache->mmap_offset; 33352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin call_action(data, 33452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin cur_mmap_cache->binary_filename, 33552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin *symbol_name, 33652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin function_offset, 33752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin true_offset); 33852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin return 0; 33952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin } 34052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin else if (ip < cur_mmap_cache->start_addr) 34152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin upper = mid - 1; 34252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin else 34352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin lower = mid + 1; 34452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin } 34552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 34652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin /* 34752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin * there is a bug in libunwind >= 1.0 34852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin * after a set_tid_address syscall 34952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin * unw_get_reg returns IP == 0 35052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin */ 35152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if(ip) 35252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin error_action(data, "unexpected_backtracing_error", ip); 35352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin return -1; 35452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin} 35552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 3562d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO/* 3572d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * walking the stack 3582d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO */ 3592d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOstatic void 3602d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOstacktrace_walk(struct tcb *tcp, 3612d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO call_action_fn call_action, 3622d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO error_action_fn error_action, 3632d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO void *data) 364327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi{ 36552840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin char *symbol_name; 366327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi size_t symbol_name_size = 40; 36752840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin unw_cursor_t cursor; 36852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin int stack_depth; 369327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 370327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!tcp->mmap_cache) 3719bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO error_msg_and_die("bug: mmap_cache is NULL"); 3729bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO if (tcp->mmap_cache_size == 0) 3739bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO error_msg_and_die("bug: mmap_cache is empty"); 374327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 375327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi symbol_name = malloc(symbol_name_size); 376327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (!symbol_name) 377327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi die_out_of_memory(); 378327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 379327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi if (unw_init_remote(&cursor, libunwind_as, tcp->libunwind_ui) < 0) 380327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi perror_msg_and_die("Can't initiate libunwind"); 381327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi 38252840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin for (stack_depth = 0; stack_depth < 256; ++stack_depth) { 38352840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (print_stack_frame(tcp, call_action, error_action, data, 38452840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin &cursor, &symbol_name, &symbol_name_size) < 0) 385327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi break; 38652840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (unw_step(&cursor) <= 0) 387327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi break; 38852840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin } 38952840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin if (stack_depth >= 256) 39052840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin error_action(data, "too many stack frames", 0); 39152840ede0c72d90b9dad3dc829ef4b4909d51ab6Dmitry V. Levin 392327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi free(symbol_name); 393327064b63722a4400058e0e7e9b39d9e34b14b57Luca Clementi} 3942d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 3952d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO/* 396f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO * printing an entry in stack to stream or buffer 3972d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO */ 3982d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO/* 3992d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * we want to keep the format used by backtrace_symbols from the glibc 4002d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * 4012d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * ./a.out() [0x40063d] 4022d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * ./a.out() [0x4006bb] 4032d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * ./a.out() [0x4006c6] 4042d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * /lib64/libc.so.6(__libc_start_main+0xed) [0x7fa2f8a5976d] 4052d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * ./a.out() [0x400569] 4062d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO */ 4072d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO#define STACK_ENTRY_SYMBOL_FMT \ 4082d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO " > %s(%s+0x%lx) [0x%lx]\n", \ 4092d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO binary_filename, \ 4102d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO symbol_name, \ 4116555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin (unsigned long) function_offset, \ 4122d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO true_offset 4132d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO#define STACK_ENTRY_NOSYMBOL_FMT \ 4142d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO " > %s() [0x%lx]\n", \ 4152d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO binary_filename, true_offset 4162d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO#define STACK_ENTRY_BUG_FMT \ 4172d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO " > BUG IN %s\n" 4182d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO#define STACK_ENTRY_ERROR_WITH_OFFSET_FMT \ 4192d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO " > %s [0x%lx]\n", error, true_offset 4202d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO#define STACK_ENTRY_ERROR_FMT \ 4212d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO " > %s\n", error 4222d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 4232d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOstatic void 4242d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOprint_call_cb(void *dummy, 425806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *binary_filename, 426806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *symbol_name, 4276555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin unw_word_t function_offset, 4282d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO unsigned long true_offset) 4292d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO{ 4302d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO if (symbol_name) 4312d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO tprintf(STACK_ENTRY_SYMBOL_FMT); 4322d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO else if (binary_filename) 4332d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO tprintf(STACK_ENTRY_NOSYMBOL_FMT); 4342d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO else 4352d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO tprintf(STACK_ENTRY_BUG_FMT, __FUNCTION__); 4362d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 4372d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO line_ended(); 4382d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO} 4392d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 4402d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOstatic void 4412d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOprint_error_cb(void *dummy, 4422d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO const char *error, 4432d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO unsigned long true_offset) 4442d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO{ 4452d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO if (true_offset) 4462d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO tprintf(STACK_ENTRY_ERROR_WITH_OFFSET_FMT); 4472d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO else 4482d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO tprintf(STACK_ENTRY_ERROR_FMT); 4492d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 4502d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO line_ended(); 4512d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO} 4522d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO 453f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstatic char * 454806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levinsprint_call_or_error(const char *binary_filename, 455806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *symbol_name, 4566555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin unw_word_t function_offset, 457f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO unsigned long true_offset, 458f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO const char *error) 459f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO{ 460f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO char *output_line = NULL; 461f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO int n; 462f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 463f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (symbol_name) 464f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO n = asprintf(&output_line, STACK_ENTRY_SYMBOL_FMT); 465f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO else if (binary_filename) 466f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO n = asprintf(&output_line, STACK_ENTRY_NOSYMBOL_FMT); 467f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO else if (error) 468f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO n = true_offset 469f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO ? asprintf(&output_line, STACK_ENTRY_ERROR_WITH_OFFSET_FMT) 470f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO : asprintf(&output_line, STACK_ENTRY_ERROR_FMT); 471f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO else 472f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO n = asprintf(&output_line, STACK_ENTRY_BUG_FMT, __FUNCTION__); 473f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 474f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (n < 0) 475f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO error_msg_and_die("error in asprintf"); 476f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 477f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO return output_line; 478f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO} 479f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 480f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO/* 481f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO * queue manipulators 482f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO */ 483f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstatic void 484f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOqueue_put(struct queue_t *queue, 485806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *binary_filename, 486806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *symbol_name, 4876555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin unw_word_t function_offset, 488f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO unsigned long true_offset, 489f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO const char *error) 490f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO{ 491f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO struct call_t *call; 492f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 493f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO call = malloc(sizeof(*call)); 494f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (!call) 495f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO die_out_of_memory(); 496f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 497f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO call->output_line = sprint_call_or_error(binary_filename, 498f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO symbol_name, 4996555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin function_offset, 500f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO true_offset, 501f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO error); 502f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO call->next = NULL; 503f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 504f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (!queue->head) { 505f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue->head = call; 506f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue->tail = call; 507f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO } else { 508f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue->tail->next = call; 509f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue->tail = call; 510f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO } 511f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO} 512f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 513f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstatic void 514f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOqueue_put_call(void *queue, 515806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *binary_filename, 516806539c55c8697f7f0a4bfd95345f216797fe7e0Dmitry V. Levin const char *symbol_name, 5176555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin unw_word_t function_offset, 518f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO unsigned long true_offset) 519f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO{ 520f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue_put(queue, 521f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO binary_filename, 522f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO symbol_name, 5236555711a6ee9b63a5a9c5e3e530d066306c0760cDmitry V. Levin function_offset, 524f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO true_offset, 525f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO NULL); 526f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO} 527f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 528f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstatic void 529f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOqueue_put_error(void *queue, 530f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO const char *error, 531e4113974893293c82f177fe4195cac0a5b70465aDmitry V. Levin unsigned long ip) 532f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO{ 533f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue_put(queue, NULL, NULL, 0, ip, error); 534f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO} 535f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 536f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOstatic void 537f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOqueue_print(struct queue_t *queue) 538f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO{ 539f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO struct call_t *call, *tmp; 540f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 541f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue->tail = NULL; 542f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO call = queue->head; 543f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue->head = NULL; 544f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO while (call) { 545f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tmp = call; 546f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO call = call->next; 547f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 548f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tprints(tmp->output_line); 549f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO line_ended(); 550f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 551f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO free(tmp->output_line); 552f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tmp->output_line = NULL; 553f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO tmp->next = NULL; 554f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO free(tmp); 555f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO } 556f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO} 557f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 5582d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO/* 5592d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO * printing stack 5602d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO */ 5612d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOvoid 5622d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATOunwind_print_stacktrace(struct tcb* tcp) 5632d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO{ 564f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi#if SUPPORTED_PERSONALITIES > 1 565f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi if (tcp->currpers != DEFAULT_PERSONALITY) { 566f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi /* disable strack trace */ 567f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi return; 568f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi } 569f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi#endif 570f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (tcp->queue->head) { 571f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO DPRINTF("tcp=%p, queue=%p", "queueprint", tcp, tcp->queue->head); 572f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO queue_print(tcp->queue); 573f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO } 5749bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO else if (rebuild_cache_if_invalid(tcp, __FUNCTION__)) { 575f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO DPRINTF("tcp=%p, queue=%p", "stackprint", tcp, tcp->queue->head); 576f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO stacktrace_walk(tcp, print_call_cb, print_error_cb, NULL); 577f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO } 578f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO} 579f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 580f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO/* 581f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO * capturing stack 582f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO */ 583f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOvoid 584f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATOunwind_capture_stacktrace(struct tcb *tcp) 585f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO{ 586f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi#if SUPPORTED_PERSONALITIES > 1 587f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi if (tcp->currpers != DEFAULT_PERSONALITY) { 588f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi /* disable strack trace */ 589f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi return; 590f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi } 591f1d73110a00122879a0fdb63bbeffc0bd161e857Luca Clementi#endif 592f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO if (tcp->queue->head) 593f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO error_msg_and_die("bug: unprinted entries in queue"); 594f8e39d7b7a9d581e634be59af73cf82cb566abf9Masatake YAMATO 5959bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO if (rebuild_cache_if_invalid(tcp, __FUNCTION__)) { 5969bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO stacktrace_walk(tcp, queue_put_call, queue_put_error, 5979bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO tcp->queue); 5989bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO DPRINTF("tcp=%p, queue=%p", "captured", tcp, tcp->queue->head); 5999bc6561588093a788c29f07579f9e4103864a752Masatake YAMATO } 6002d534daaa66ddc6a0558717160f0e1b337f7b7c5Masatake YAMATO} 601