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