194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata/*
294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * This file is part of ltrace.
30f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata * Copyright (C) 2011,2012,2013,2014 Petr Machata, Red Hat Inc.
494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Copyright (C) 2010 Joe Damato
594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Copyright (C) 1997,1998,1999,2001,2002,2003,2004,2007,2008,2009 Juan Cespedes
6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2006 Paul Gilliam, IBM Corporation
794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Copyright (C) 2006 Ian Wienand
894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * This program is free software; you can redistribute it and/or
1094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * modify it under the terms of the GNU General Public License as
1194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * published by the Free Software Foundation; either version 2 of the
1294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * License, or (at your option) any later version.
1394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
1494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * This program is distributed in the hope that it will be useful, but
1594078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
1694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * General Public License for more details.
1894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata *
1994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * You should have received a copy of the GNU General Public License
2094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * along with this program; if not, write to the Free Software
2194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
2294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata * 02110-1301 USA
2394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata */
2494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
25ac3db297f7c6f08b02a7edfb32e441875fd7c1d7Juan Cespedes#include "config.h"
26ac3db297f7c6f08b02a7edfb32e441875fd7c1d7Juan Cespedes
273268a165cbb4d5b63d2cd7d9e63ccffc40d969e1Juan Cespedes#include <stdio.h>
28d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes#include <stdlib.h>
295e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes#include <stdarg.h>
301cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes#include <string.h>
315e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes#include <time.h>
325e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes#include <sys/time.h>
335e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes#include <unistd.h>
34f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata#include <errno.h>
35865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include <assert.h>
36dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard#include <inttypes.h>
375e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes
38ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include "output.h"
393ac8db64ad80c4afacf06a97d0163c9f3f2c9e17Petr Machata#include "demangle.h"
409bc290b692c0b5075c6ea8e93f67a179572375f0Petr Machata#include "fetch.h"
419bc290b692c0b5075c6ea8e93f67a179572375f0Petr Machata#include "lens_default.h"
4229add4fdf852b10ddd22cac0d1390f6d01577bc2Petr Machata#include "library.h"
439bc290b692c0b5075c6ea8e93f67a179572375f0Petr Machata#include "memstream.h"
448bf82d0625c5704d31961db7e0458b247300275cPetr Machata#include "options.h"
459bc290b692c0b5075c6ea8e93f67a179572375f0Petr Machata#include "param.h"
469bc290b692c0b5075c6ea8e93f67a179572375f0Petr Machata#include "proc.h"
47ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include "prototype.h"
488a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include "summary.h"
49000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include "type.h"
5094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include "value.h"
5194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include "value_dict.h"
52ac3db297f7c6f08b02a7edfb32e441875fd7c1d7Juan Cespedes
538a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatastatic struct process *current_proc = NULL;
54ba1664b062414481d0f37d06bb01a19874c8d481Petr Machatastatic size_t current_depth = 0;
555e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedesstatic int current_column = 0;
565b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
57f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
58929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataoutput_indent(struct process *proc)
5954004758185489b6bf74aa94e7ccd83b23840362Petr Machata{
6054004758185489b6bf74aa94e7ccd83b23840362Petr Machata	int d = options.indent * (proc->callstack_depth - 1);
6154004758185489b6bf74aa94e7ccd83b23840362Petr Machata	current_column += fprintf(options.output, "%*s", d, "");
625b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
635e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes
64f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
65929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabegin_of_line(struct process *proc, int is_func, int indent)
6637b73c0ab8cbcab4729df6d12f2dc846d4652310Petr Machata{
675e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	current_column = 0;
685e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	if (!proc) {
695e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes		return;
705e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
71c693f02a01835a6fc603212d323a364a22a4fa26Juan Cespedes	if ((options.output != stderr) && (opt_p || options.follow)) {
72c693f02a01835a6fc603212d323a364a22a4fa26Juan Cespedes		current_column += fprintf(options.output, "%u ", proc->pid);
73e12df4c65dfbd6d0e4a95ff90261b3b7c07298a2Juan Cespedes	} else if (options.follow) {
74b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		current_column += fprintf(options.output, "[pid %u] ", proc->pid);
755e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
76f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes	if (opt_r) {
77f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		struct timeval tv;
782d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		static struct timeval old_tv = { 0, 0 };
79f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		struct timeval diff;
80f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes
81756422773afa17f39d3296669eb66708557f7d3cPetr Machata		gettimeofday(&tv, NULL);
82f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes
832d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		if (old_tv.tv_sec == 0 && old_tv.tv_usec == 0) {
842d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			old_tv.tv_sec = tv.tv_sec;
852d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			old_tv.tv_usec = tv.tv_usec;
86f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		}
87f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
88f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		if (tv.tv_usec >= old_tv.tv_usec) {
89f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes			diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
90f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		} else {
915c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes			diff.tv_sec--;
92f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes			diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
93f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		}
94f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		old_tv.tv_sec = tv.tv_sec;
95f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes		old_tv.tv_usec = tv.tv_usec;
96b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		current_column += fprintf(options.output, "%3lu.%06d ",
976bb420106f77ef8f134a1d4c001668e832f96cc9Andrey Zonov					  (unsigned long)diff.tv_sec,
986bb420106f77ef8f134a1d4c001668e832f96cc9Andrey Zonov					  (int)diff.tv_usec);
99f666d191986d3b342cfa8b2e96ed90a49edf4303Juan Cespedes	}
1005e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes	if (opt_t) {
1015e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes		struct timeval tv;
102756422773afa17f39d3296669eb66708557f7d3cPetr Machata		gettimeofday(&tv, NULL);
1032d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		if (opt_t > 2) {
104b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			current_column += fprintf(options.output, "%lu.%06d ",
1056bb420106f77ef8f134a1d4c001668e832f96cc9Andrey Zonov						  (unsigned long)tv.tv_sec,
1066bb420106f77ef8f134a1d4c001668e832f96cc9Andrey Zonov						  (int)tv.tv_usec);
1072d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (opt_t > 1) {
1082d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			struct tm *tmp = localtime(&tv.tv_sec);
1092d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			current_column +=
110b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			    fprintf(options.output, "%02d:%02d:%02d.%06d ",
1112d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				    tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
1122d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				    (int)tv.tv_usec);
1135e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes		} else {
1142d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			struct tm *tmp = localtime(&tv.tv_sec);
115b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			current_column += fprintf(options.output, "%02d:%02d:%02d ",
1162d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand						  tmp->tm_hour, tmp->tm_min,
1172d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand						  tmp->tm_sec);
1185e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes		}
1195e0acdb26c98f0d95a5266e579669b5c19eb02ceJuan Cespedes	}
1205e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes	if (opt_i) {
1214dcc3893d488d19c7606acfa80752babbbe04645Petr Machata		if (is_func) {
1224dcc3893d488d19c7606acfa80752babbbe04645Petr Machata			struct callstack_element *stel
1234dcc3893d488d19c7606acfa80752babbbe04645Petr Machata				= &proc->callstack[proc->callstack_depth - 1];
124b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			current_column += fprintf(options.output, "[%p] ",
1254dcc3893d488d19c7606acfa80752babbbe04645Petr Machata						  stel->return_addr);
1264dcc3893d488d19c7606acfa80752babbbe04645Petr Machata		} else {
127b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			current_column += fprintf(options.output, "[%p] ",
1282d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand						  proc->instruction_pointer);
1294dcc3893d488d19c7606acfa80752babbbe04645Petr Machata		}
1305e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes	}
13137b73c0ab8cbcab4729df6d12f2dc846d4652310Petr Machata	if (options.indent > 0 && indent) {
1323f0b62e9df224dbdc20a8fa91afe8a0c81a230e9Juan Cespedes		output_indent(proc);
1335b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	}
1345e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes}
1355e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes
136b781916d24d6ee96842c818b5e18af31808d427dPetr Machatastatic struct arg_type_info *
137b781916d24d6ee96842c818b5e18af31808d427dPetr Machataget_unknown_type(void)
138b781916d24d6ee96842c818b5e18af31808d427dPetr Machata{
139f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	static struct arg_type_info *ret = NULL;
140f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	if (ret != NULL)
141f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata		return ret;
142f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata
143f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	static struct arg_type_info info;
144f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	info = *type_get_simple(ARGTYPE_LONG);
145f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	info.lens = &guess_lens;
146f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	ret = &info;
147f1bd48b7aaa1a2155180052cb2bf73985b4b0b2dPetr Machata	return ret;
148b781916d24d6ee96842c818b5e18af31808d427dPetr Machata}
149b781916d24d6ee96842c818b5e18af31808d427dPetr Machata
150f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata/* The default prototype is: long X(long, long, long, long).  */
1513d083b6326ab15015979c97c884a6104c1fa65f5Petr Machatastatic struct prototype *
152f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatabuild_default_prototype(void)
153f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
154ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	static struct prototype *ret = NULL;
155ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	if (ret != NULL)
156ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return ret;
157f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
158ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	static struct prototype proto;
159ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	prototype_init(&proto);
160f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
161ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct arg_type_info *unknown_type = get_unknown_type();
162ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	assert(unknown_type != NULL);
163ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	proto.return_info = unknown_type;
164ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	proto.own_return_info = 0;
165f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
166ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct param unknown_param;
167ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	param_init_type(&unknown_param, unknown_type, 0);
168865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
169ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	size_t i;
170ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	for (i = 0; i < 4; ++i)
171ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		if (prototype_push_param(&proto, &unknown_param) < 0) {
172ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata			report_global_error("build_default_prototype: %s",
173ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata					    strerror(errno));
174ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata			prototype_destroy(&proto);
175ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata			return NULL;
176ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		}
177f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
178ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	ret = &proto;
179f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	return ret;
180f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
181f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
18298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machatastatic bool
18398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machatasnip_period(char *buf)
18498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata{
18598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	char *period = strrchr(buf, '.');
18698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (period != NULL && strcmp(period, ".so") != 0) {
18798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		*period = 0;
18898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return true;
18998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	} else {
19098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return false;
19198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	}
19298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata}
19398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
1943d083b6326ab15015979c97c884a6104c1fa65f5Petr Machatastatic struct prototype *
195a94d9dfc864c261717de8859aa49bb758eccac90Petr Machatalibrary_get_prototype(struct library *lib, const char *name)
196a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata{
19798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (lib->protolib == NULL) {
19898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		size_t sz = strlen(lib->soname);
19998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		char buf[sz + 1];
200ac52f2660ec717b6b25c313f20e47a622d3357d8Petr Machata		memcpy(buf, lib->soname, sz + 1);
20198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
20298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		do {
20398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			if (protolib_cache_maybe_load(&g_protocache, buf, 0,
20498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata						      true, &lib->protolib) < 0)
20598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata				return NULL;
20698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		} while (lib->protolib == NULL
20798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			 && lib->type == LT_LIBTYPE_DSO
20898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			 && snip_period(buf));
20998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
21098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		if (lib->protolib == NULL)
21198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			lib->protolib = protolib_cache_default(&g_protocache,
21298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata							       buf, 0);
21398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	}
214a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	if (lib->protolib == NULL)
215a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata		return NULL;
216a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata
21782f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	return protolib_lookup_prototype(lib->protolib, name,
21882f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata					 lib->type != LT_LIBTYPE_SYSCALL);
219a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata}
220a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata
221a94d9dfc864c261717de8859aa49bb758eccac90Petr Machatastruct find_proto_data {
222a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	const char *name;
223a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	struct prototype *ret;
224a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata};
225a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata
226a94d9dfc864c261717de8859aa49bb758eccac90Petr Machatastatic enum callback_status
227a94d9dfc864c261717de8859aa49bb758eccac90Petr Machatafind_proto_cb(struct process *proc, struct library *lib, void *d)
228a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata{
229a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	struct find_proto_data *data = d;
230a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	data->ret = library_get_prototype(lib, data->name);
231a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	return CBS_STOP_IF(data->ret != NULL);
232a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata}
233a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata
234a94d9dfc864c261717de8859aa49bb758eccac90Petr Machatastatic struct prototype *
235a94d9dfc864c261717de8859aa49bb758eccac90Petr Machatalookup_symbol_prototype(struct process *proc, struct library_symbol *libsym)
2363d083b6326ab15015979c97c884a6104c1fa65f5Petr Machata{
237b8f0d8b5859a7d69f6aed4904a87ac6a423285f6Petr Machata	if (libsym->proto != NULL)
238b8f0d8b5859a7d69f6aed4904a87ac6a423285f6Petr Machata		return libsym->proto;
239b8f0d8b5859a7d69f6aed4904a87ac6a423285f6Petr Machata
24008cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	struct library *lib = libsym->lib;
24108cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	if (lib != NULL) {
242a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata		struct find_proto_data data = { libsym->name };
243a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata		data.ret = library_get_prototype(lib, libsym->name);
244a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata		if (data.ret == NULL
245a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata		    && libsym->plt_type == LS_TOPLT_EXEC)
246a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata			proc_each_library(proc, NULL, find_proto_cb, &data);
247a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata		if (data.ret != NULL)
248a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata			return data.ret;
24908cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	}
25008cdf328add7b723b94b151866e5d0173662f6c6Petr Machata
251ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return build_default_prototype();
2525e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes}
2535e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes
254f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
255929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataoutput_line(struct process *proc, const char *fmt, ...)
256efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata{
257efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata	if (options.summary)
258d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes		return;
259efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata
260efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata	if (current_proc != NULL) {
261efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata		if (current_proc->callstack[current_depth].return_addr)
262b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			fprintf(options.output, " <unfinished ...>\n");
263efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata		else
264b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes			fprintf(options.output, " <no return ...>\n");
2655e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
266efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata	current_proc = NULL;
267efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata	if (fmt == NULL)
26828f60197b93b45422a73e5d1a6aa581584d6c4a5Juan Cespedes		return;
269efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata
27037b73c0ab8cbcab4729df6d12f2dc846d4652310Petr Machata	begin_of_line(proc, 0, 0);
2715e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
272efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata	va_list args;
27321c63a1469bc049d93444b8a15afd685ee251392Juan Cespedes	va_start(args, fmt);
274b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes	vfprintf(options.output, fmt, args);
275b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes	fprintf(options.output, "\n");
27621c63a1469bc049d93444b8a15afd685ee251392Juan Cespedes	va_end(args);
277efc9436b1ac30e73347696cf3fcfc9ad3f60772fPetr Machata
2782d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	current_column = 0;
2795e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
2805e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
281f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
282f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedestabto(int col) {
2835e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	if (current_column < col) {
284b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		fprintf(options.output, "%*s", col - current_column, "");
2855e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes	}
2865e4455bffd7cd5c4a948ce7f7f4be9da55c67fb4Juan Cespedes}
287c40e64afa6a897bb7eb6fd4dc21f622632ae215aJuan Cespedes
288f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic int
289f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machataoutput_error(FILE *stream)
290f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
291f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	return fprintf(stream, "?");
292f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
293f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
294f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic int
295929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_simple_param(enum tof type, struct process *proc,
296929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		   struct fetch_context *context,
297bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata		   struct value_dict *arguments,
298bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata		   struct arg_type_info *info, int own,
299f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		   struct value *valuep)
300f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
301f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	/* Arrays decay into pointers per C standard.  We check for
302f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	 * this here, because here we also capture arrays that come
303f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	 * from parameter packs.  */
304f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (info->type == ARGTYPE_ARRAY) {
305f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		struct arg_type_info *tmp = malloc(sizeof(*tmp));
306f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		if (tmp != NULL) {
307bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata			type_init_pointer(tmp, info, own);
308b781916d24d6ee96842c818b5e18af31808d427dPetr Machata			tmp->lens = info->lens;
309f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata			info = tmp;
310f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata			own = 1;
311f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		}
312f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	}
313f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
314f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	struct value value;
315f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	value_init(&value, proc, NULL, info, own);
316f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (fetch_arg_next(context, type, proc, info, &value) < 0)
317f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		return -1;
318f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
319f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (val_dict_push_next(arguments, &value) < 0) {
320f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		value_destroy(&value);
321f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		return -1;
322f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	}
323f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
324f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (valuep != NULL)
325f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		*valuep = value;
326f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
327f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	return 0;
328f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
329f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
330f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic void
331f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatafetch_param_stop(struct value_dict *arguments, ssize_t *params_leftp)
332f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
333f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (*params_leftp == -1)
334f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		*params_leftp = val_dict_count(arguments);
335f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
336f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
337f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic int
338929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_param_pack(enum tof type, struct process *proc,
339929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		 struct fetch_context *context,
340865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		 struct value_dict *arguments, struct param *param,
341865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		 ssize_t *params_leftp)
342865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
343865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	struct param_enum *e = param_pack_init(param, arguments);
344865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	if (e == NULL)
345865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		return -1;
346865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
347865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	int ret = 0;
348865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	while (1) {
349865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		int insert_stop = 0;
350865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct arg_type_info *info = malloc(sizeof(*info));
351865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (info == NULL
352865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		    || param_pack_next(param, e, info, &insert_stop) < 0) {
353865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		fail:
354865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			free(info);
355865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			ret = -1;
356865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			break;
357865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		}
358865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
359865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (insert_stop)
360865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			fetch_param_stop(arguments, params_leftp);
361865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
362bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata		if (info->type == ARGTYPE_VOID) {
363bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata			type_destroy(info);
364bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata			free(info);
365865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			break;
366bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata		}
367865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
368865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct value val;
369865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (fetch_simple_param(type, proc, context, arguments,
370bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata				       info, 1, &val) < 0)
371865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			goto fail;
372865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
373865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		int stop = 0;
374865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		switch (param_pack_stop(param, e, &val)) {
375865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		case PPCB_ERR:
376865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			goto fail;
377865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		case PPCB_STOP:
378865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			stop = 1;
379865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		case PPCB_CONT:
380865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			break;
381865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		}
382865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
383865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (stop)
384865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			break;
385865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	}
386865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
387865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param_pack_done(param, e);
388865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	return ret;
389865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
390865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
391865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatastatic int
392929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_one_param(enum tof type, struct process *proc,
393929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		struct fetch_context *context,
394865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct value_dict *arguments, struct param *param,
395f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		ssize_t *params_leftp)
396f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
397865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	switch (param->flavor) {
398e36298a706b96bfdf9335fbe8288827761d77957Petr Machata		int rc;
399865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	case PARAM_FLAVOR_TYPE:
400865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		return fetch_simple_param(type, proc, context, arguments,
401bc58f2a1b2b516b2176a4a32117065dde4813734Petr Machata					  param->u.type.type, 0, NULL);
402865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
403865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	case PARAM_FLAVOR_PACK:
404e36298a706b96bfdf9335fbe8288827761d77957Petr Machata		if (fetch_param_pack_start(context,
405e36298a706b96bfdf9335fbe8288827761d77957Petr Machata					   param->u.pack.ppflavor) < 0)
406e36298a706b96bfdf9335fbe8288827761d77957Petr Machata			return -1;
407e36298a706b96bfdf9335fbe8288827761d77957Petr Machata	        rc = fetch_param_pack(type, proc, context, arguments,
408e36298a706b96bfdf9335fbe8288827761d77957Petr Machata				      param, params_leftp);
409e36298a706b96bfdf9335fbe8288827761d77957Petr Machata		fetch_param_pack_end(context);
410e36298a706b96bfdf9335fbe8288827761d77957Petr Machata		return rc;
411865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
412865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	case PARAM_FLAVOR_STOP:
413865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		fetch_param_stop(arguments, params_leftp);
414865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		return 0;
415865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	}
416865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
417865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	assert(!"Invalid param flavor!");
418865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	abort();
419f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
420f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
421ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastruct fetch_one_param_data
422ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
423ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct process *proc;
424ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct fetch_context *context;
425ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct value_dict *arguments;
426ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	ssize_t *params_leftp;
427ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	enum tof tof;
428ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata};
429ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
430ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic enum callback_status
431ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatafetch_one_param_cb(struct prototype *proto, struct param *param, void *data)
432ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
433ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct fetch_one_param_data *cb_data = data;
434a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	return CBS_STOP_IF(fetch_one_param(cb_data->tof, cb_data->proc,
435a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata					   cb_data->context,
436a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata					   cb_data->arguments, param,
437a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata					   cb_data->params_leftp) < 0);
438ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
439ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
440f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic int
441929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_params(enum tof type, struct process *proc,
442929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata	     struct fetch_context *context,
4433d083b6326ab15015979c97c884a6104c1fa65f5Petr Machata	     struct value_dict *arguments, struct prototype *func,
4443d083b6326ab15015979c97c884a6104c1fa65f5Petr Machata	     ssize_t *params_leftp)
445f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
446ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct fetch_one_param_data cb_data
447ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		= { proc, context, arguments, params_leftp, type };
448ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	if (prototype_each_param(func, NULL,
449ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata				 &fetch_one_param_cb, &cb_data) != NULL)
450ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return -1;
451f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
452f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	/* Implicit stop at the end of parameter list.  */
453f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	fetch_param_stop(arguments, params_leftp);
454865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
455f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	return 0;
456f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
457f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
458f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machatastruct format_argument_data
459f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata{
460f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	struct value *value;
461f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	struct value_dict *arguments;
462f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata};
463f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
464f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic int
465f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machataformat_argument_cb(FILE *stream, void *ptr)
466f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
467f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	struct format_argument_data *data = ptr;
468f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	int o = format_argument(stream, data->value, data->arguments);
469f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	if (o < 0)
470f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		o = output_error(stream);
471f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	return o;
472f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
473f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
474f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machatastatic int
475f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machataoutput_params(struct value_dict *arguments, size_t start, size_t end,
476f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	      int *need_delimp)
477f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata{
478f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	size_t i;
479f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	for (i = start; i < end; ++i) {
480f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		struct value *value = val_dict_get_num(arguments, i);
481f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		if (value == NULL)
482f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata			return -1;
483f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata
484f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		struct format_argument_data data = { value, arguments };
485f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		int o = delim_output(options.output, need_delimp,
486f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata				     format_argument_cb, &data);
487f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		if (o < 0)
488f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata			return -1;
489f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		current_column += o;
490f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	}
491f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	return 0;
492f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata}
493f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
494f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
495929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataoutput_left(enum tof type, struct process *proc,
49629add4fdf852b10ddd22cac0d1390f6d01577bc2Petr Machata	    struct library_symbol *libsym)
49729add4fdf852b10ddd22cac0d1390f6d01577bc2Petr Machata{
4988a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata	assert(! options.summary);
4998a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata
50076c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam	if (current_proc) {
501b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		fprintf(options.output, " <unfinished ...>\n");
5022d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		current_column = 0;
5035e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
50476c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam	current_proc = proc;
5055916fda0d07da90cac8a78cbfa73374d81b150beJuan Cespedes	current_depth = proc->callstack_depth;
506f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	begin_of_line(proc, type == LT_TOF_FUNCTION, 1);
50753bc49ba54e39fe306f8009e18c9797cc0aa46f2Petr Machata	if (!options.hide_caller && libsym->lib != NULL
50853bc49ba54e39fe306f8009e18c9797cc0aa46f2Petr Machata	    && libsym->plt_type != LS_TOPLT_NONE)
5090965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata		/* We don't terribly mind failing this.  */
5100965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata		account_output(&current_column,
5110965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata			       fprintf(options.output, "%s->",
5120965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata				       libsym->lib->soname));
513f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
51408cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	const char *name = libsym->name;
515d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef USE_DEMANGLE
516f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (options.demangle)
51708cdf328add7b723b94b151866e5d0173662f6c6Petr Machata		name = my_demangle(libsym->name);
518ac3db297f7c6f08b02a7edfb32e441875fd7c1d7Juan Cespedes#endif
519adec201a52c240cf4b533c05106aedddc911ca76Petr Machata	if (account_output(&current_column,
5200965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata			   fprintf(options.output, "%s", name)) < 0)
521f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		return;
5225e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
5230965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	if (libsym->lib != NULL
5240965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	    && libsym->lib->type != LT_LIBTYPE_MAIN
5250965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	    && libsym->plt_type == LS_TOPLT_NONE
5260965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	    && account_output(&current_column,
5270965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata			      fprintf(options.output, "@%s",
5280965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata				      libsym->lib->soname)) < 0)
5290965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata		/* We do mind failing this though.  */
5300965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata		return;
5310965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata
5320965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	account_output(&current_column, fprintf(options.output, "("));
5330965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata
534a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	struct prototype *func = lookup_symbol_prototype(proc, libsym);
5350965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	if (func == NULL) {
5361b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata	fail:
5370965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata		account_output(&current_column, fprintf(options.output, "???"));
538f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		return;
5390965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata	}
54094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
541f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	struct fetch_context *context = fetch_arg_init(type, proc,
542f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata						       func->return_info);
5431b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata	if (context == NULL)
5441b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata		goto fail;
5451b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata
54694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	struct value_dict *arguments = malloc(sizeof(*arguments));
5471b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata	if (arguments == NULL) {
5481b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata		fetch_arg_done(context);
5491b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata		goto fail;
5501b02c7398257f4b62cde3907c8f2d3b8348c2f74Petr Machata	}
55194078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	val_dict_init(arguments);
55294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
553f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	ssize_t params_left = -1;
554f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	int need_delim = 0;
555f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (fetch_params(type, proc, context, arguments, func, &params_left) < 0
556f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	    || output_params(arguments, 0, params_left, &need_delim) < 0) {
557f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		val_dict_destroy(arguments);
558f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		fetch_arg_done(context);
559865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		arguments = NULL;
560865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		context = NULL;
5615e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
56294078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
56394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	struct callstack_element *stel
56494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		= &proc->callstack[proc->callstack_depth - 1];
565f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	stel->fetch_context = context;
56694078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	stel->arguments = arguments;
567f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	stel->out.params_left = params_left;
568f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	stel->out.need_delim = need_delim;
569c40e64afa6a897bb7eb6fd4dc21f622632ae215aJuan Cespedes}
570c40e64afa6a897bb7eb6fd4dc21f622632ae215aJuan Cespedes
571dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard#if defined(HAVE_LIBDW)
572dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard/* Prints information about one frame of a thread.  Called by
573dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard   dwfl_getthread_frames in output_right.  Returns 1 when done (max
574dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard   number of frames reached).  Returns -1 on error.  Returns 0 on
575dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard   success (if there are more frames in the thread, call us again).  */
576dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaardstatic int
577dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaardframe_callback (Dwfl_Frame *state, void *arg)
578dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard{
579dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	Dwarf_Addr pc;
580dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	bool isactivation;
581dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
582dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	int *frames = (int *) arg;
583dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
584dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	if (!dwfl_frame_pc(state, &pc, &isactivation))
585dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		return -1;
586dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
587dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	if (!isactivation)
588dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		pc--;
589dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
590dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(state));
591dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	Dwfl_Module *mod = dwfl_addrmodule(dwfl, pc);
592dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	const char *modname = NULL;
593dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	const char *symname = NULL;
594dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	GElf_Off off = 0;
595dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	if (mod != NULL) {
596dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		GElf_Sym sym;
597dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		modname = dwfl_module_info(mod, NULL, NULL, NULL, NULL,
598dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					   NULL, NULL, NULL);
599dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		symname = dwfl_module_addrinfo(mod, pc, &off, &sym,
600dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					       NULL, NULL, NULL);
601dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	}
602dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
603dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	/* This mimics the output produced by libunwind below.  */
604dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	fprintf(options.output, " > %s(%s+0x%" PRIx64 ") [%" PRIx64 "]\n",
605dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		modname, symname, off, pc);
606dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
607dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	/* See if we can extract the source line too and print it on
608dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	   the next line if we can find it.  */
609dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	if (mod != NULL) {
610dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		Dwfl_Line *l = dwfl_module_getsrc(mod, pc);
611dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		if (l != NULL) {
612dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			int line, col;
613dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			line = col = -1;
614dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			const char *src = dwfl_lineinfo(l, NULL, &line, &col,
615dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard							NULL, NULL);
616dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			if (src != NULL) {
617dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard				fprintf(options.output, "\t%s", src);
618dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard				if (line > 0) {
619dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					fprintf(options.output, ":%d", line);
620dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					if (col > 0)
621dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			                        fprintf(options.output,
622dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard							":%d", col);
623dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard				}
624dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard				fprintf(options.output, "\n");
625dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			}
626dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
627dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		}
628dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	}
629dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
630dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	/* Max number of frames to print reached? */
631dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	if ((*frames)-- == 0)
632dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		return 1;
633dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
634dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	return 0;
635dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard}
636dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard#endif /* defined(HAVE_LIBDW) */
637dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
638f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
6398a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machataoutput_right(enum tof type, struct process *proc, struct library_symbol *libsym,
6408a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata	     struct timedelta *spent)
64114184b3a0c938c196f77d2d3bfc7e82fa10d661bPetr Machata{
6428a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata	assert(! options.summary);
6438a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata
644a94d9dfc864c261717de8859aa49bb758eccac90Petr Machata	struct prototype *func = lookup_symbol_prototype(proc, libsym);
645f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (func == NULL)
646f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		return;
6475e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
6488a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata	if (current_proc != NULL
6498a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata		    && (current_proc != proc
6508a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata			|| current_depth != proc->callstack_depth)) {
651b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		fprintf(options.output, " <unfinished ...>\n");
6528a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata		current_proc = NULL;
6531b9cfd6ad305ad909e8ff17139111a7c78f01464Juan Cespedes	}
65476c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam	if (current_proc != proc) {
65537b73c0ab8cbcab4729df6d12f2dc846d4652310Petr Machata		begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1);
656d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef USE_DEMANGLE
6572d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		current_column +=
658b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		    fprintf(options.output, "<... %s resumed> ",
65908cdf328add7b723b94b151866e5d0173662f6c6Petr Machata			    options.demangle ? my_demangle(libsym->name)
66008cdf328add7b723b94b151866e5d0173662f6c6Petr Machata			    : libsym->name);
6611b9cfd6ad305ad909e8ff17139111a7c78f01464Juan Cespedes#else
6622d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		current_column +=
66308cdf328add7b723b94b151866e5d0173662f6c6Petr Machata		    fprintf(options.output, "<... %s resumed> ", libsym->name);
6641b9cfd6ad305ad909e8ff17139111a7c78f01464Juan Cespedes#endif
6655e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
6665e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
66794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	struct callstack_element *stel
66894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		= &proc->callstack[proc->callstack_depth - 1];
66994078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
670f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	struct fetch_context *context = stel->fetch_context;
671f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
672f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	/* Fetch & enter into dictionary the retval first, so that
673f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	 * other values can use it in expressions.  */
67494078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	struct value retval;
6750f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata	bool own_retval = false;
676f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (context != NULL) {
677f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		value_init(&retval, proc, NULL, func->return_info, 0);
6780f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata		own_retval = true;
679f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		if (fetch_retval(context, type, proc, func->return_info,
680a6fb1f5c52bb6c5f460bfb1631162ecf31c96621Petr Machata				 &retval) < 0)
681a6fb1f5c52bb6c5f460bfb1631162ecf31c96621Petr Machata			value_set_type(&retval, NULL, 0);
682a6fb1f5c52bb6c5f460bfb1631162ecf31c96621Petr Machata		else if (stel->arguments != NULL
6830f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata			 && val_dict_push_named(stel->arguments, &retval,
6840f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata						"retval", 0) == 0)
6850f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata			own_retval = false;
6865e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
68794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
688f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (stel->arguments != NULL)
689f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		output_params(stel->arguments, stel->out.params_left,
690f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata			      val_dict_count(stel->arguments),
691f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata			      &stel->out.need_delim);
692f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
693f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	current_column += fprintf(options.output, ") ");
694f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	tabto(options.align - 1);
695f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	fprintf(options.output, "= ");
696f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
697f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	if (context != NULL && retval.type != NULL) {
698f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		struct format_argument_data data = { &retval, stel->arguments };
699f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata		format_argument_cb(options.output, &data);
700f7c46bba61bb830e5a283ef8b0174f33c3989821Petr Machata	}
701f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
702f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata	if (own_retval)
703f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata		value_destroy(&retval);
704f6ec08afb96292fd3c802c1f633d8de249664c72Petr Machata
705d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes	if (opt_T) {
7068a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata		assert(spent != NULL);
707b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes		fprintf(options.output, " <%lu.%06d>",
7088a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata			(unsigned long) spent->tm.tv_sec,
7098a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata			(int) spent->tm.tv_usec);
710d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes	}
7118a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata
712b65bdc581f1ff747a53a1e2494d1cebb56453cb2Juan Cespedes	fprintf(options.output, "\n");
713ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato
714ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato#if defined(HAVE_LIBUNWIND)
715af1e603fa8afd1ed0f1819a984c57311efbc7f1fPetr Machata	if (options.bt_depth > 0
716af1e603fa8afd1ed0f1819a984c57311efbc7f1fPetr Machata	    && proc->unwind_priv != NULL
717af1e603fa8afd1ed0f1819a984c57311efbc7f1fPetr Machata	    && proc->unwind_as != NULL) {
718ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		unw_cursor_t cursor;
7192927648b952d197b6f3693651694097c38e99f95Luca Clementi		arch_addr_t ip, function_offset;
7202927648b952d197b6f3693651694097c38e99f95Luca Clementi		struct library *lib = NULL;
721ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		int unwind_depth = options.bt_depth;
722ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		char fn_name[100];
7232927648b952d197b6f3693651694097c38e99f95Luca Clementi		const char *lib_name;
7242927648b952d197b6f3693651694097c38e99f95Luca Clementi		size_t distance;
725ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato
7262927648b952d197b6f3693651694097c38e99f95Luca Clementi		/* Verify that we can safely cast arch_addr_t* to
7272927648b952d197b6f3693651694097c38e99f95Luca Clementi		 * unw_word_t*.  */
72855720814c8712f699f88ea483aa538db2fba9e79Mohamad Ayyash		(void)sizeof(char[1 - 2*(sizeof(unw_word_t)
7292927648b952d197b6f3693651694097c38e99f95Luca Clementi					!= sizeof(arch_addr_t))]);
730ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv);
731ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		while (unwind_depth) {
732af452c67bceba1326bb629d7c1a8241d54c09038Luca Clementi
7330f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata			int rc = unw_get_reg(&cursor, UNW_REG_IP,
7340f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata					     (unw_word_t *) &ip);
7350f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata			if (rc < 0) {
7365d3be3319b6997961283e5da61318bf46ac650a3Luca Clementi				fprintf(options.output, " > Error: %s\n",
7370f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata					unw_strerror(rc));
7385d3be3319b6997961283e5da61318bf46ac650a3Luca Clementi				goto cont;
739af452c67bceba1326bb629d7c1a8241d54c09038Luca Clementi			}
7402927648b952d197b6f3693651694097c38e99f95Luca Clementi
7412927648b952d197b6f3693651694097c38e99f95Luca Clementi			/* We are looking for the library with the base address
7422927648b952d197b6f3693651694097c38e99f95Luca Clementi			 * closest to the current ip.  */
7432927648b952d197b6f3693651694097c38e99f95Luca Clementi			lib_name = "unmapped_area";
7442927648b952d197b6f3693651694097c38e99f95Luca Clementi			distance = (size_t) -1;
7452927648b952d197b6f3693651694097c38e99f95Luca Clementi			lib = proc->libraries;
7462927648b952d197b6f3693651694097c38e99f95Luca Clementi			while (lib != NULL) {
7472927648b952d197b6f3693651694097c38e99f95Luca Clementi				/* N.B.: Assumes sizeof(size_t) ==
7482927648b952d197b6f3693651694097c38e99f95Luca Clementi				 * sizeof(arch_addr_t).
7492927648b952d197b6f3693651694097c38e99f95Luca Clementi				 * Keyword: double cast.  */
7502927648b952d197b6f3693651694097c38e99f95Luca Clementi				if ((ip >= lib->base) &&
7512927648b952d197b6f3693651694097c38e99f95Luca Clementi					    ((size_t)(ip - lib->base)
7522927648b952d197b6f3693651694097c38e99f95Luca Clementi					    < distance)) {
7532927648b952d197b6f3693651694097c38e99f95Luca Clementi					distance = ip - lib->base;
7542927648b952d197b6f3693651694097c38e99f95Luca Clementi					lib_name = lib->pathname;
7552927648b952d197b6f3693651694097c38e99f95Luca Clementi				}
7562927648b952d197b6f3693651694097c38e99f95Luca Clementi				lib = lib->next;
7572927648b952d197b6f3693651694097c38e99f95Luca Clementi			}
7582927648b952d197b6f3693651694097c38e99f95Luca Clementi
7590f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata			rc = unw_get_proc_name(&cursor, fn_name,
7600f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata					       sizeof(fn_name),
7610f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata					       (unw_word_t *) &function_offset);
7620f6f30c4d0fbedda3aa4bc707a75085bcc2c8f7fPetr Machata			if (rc == 0 || rc == -UNW_ENOMEM)
763af452c67bceba1326bb629d7c1a8241d54c09038Luca Clementi				fprintf(options.output, " > %s(%s+%p) [%p]\n",
7642927648b952d197b6f3693651694097c38e99f95Luca Clementi					lib_name, fn_name, function_offset, ip);
765af452c67bceba1326bb629d7c1a8241d54c09038Luca Clementi			else
766af452c67bceba1326bb629d7c1a8241d54c09038Luca Clementi				fprintf(options.output, " > %s(??\?) [%p]\n",
767af452c67bceba1326bb629d7c1a8241d54c09038Luca Clementi					lib_name, ip);
7682927648b952d197b6f3693651694097c38e99f95Luca Clementi
7695d3be3319b6997961283e5da61318bf46ac650a3Luca Clementi		cont:
770ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato			if (unw_step(&cursor) <= 0)
771ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato				break;
772ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato			unwind_depth--;
773ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		}
774ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato		fprintf(options.output, "\n");
775ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato	}
776ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato#endif /* defined(HAVE_LIBUNWIND) */
777ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9Joe Damato
778dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard#if defined(HAVE_LIBDW)
779dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	if (options.bt_depth > 0 && proc->leader->dwfl != NULL) {
780dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		int frames = options.bt_depth;
781dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid,
782dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					  frame_callback, &frames) < 0) {
783dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			// Only print an error if we couldn't show anything.
784dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			// Otherwise just show there might be more...
785dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			if (frames == options.bt_depth)
786dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard				fprintf(stderr,
787dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					"dwfl_getthread_frames tid %d: %s\n",
788dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard					proc->pid, dwfl_errmsg(-1));
789dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard			else
790dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard				fprintf(options.output, " > [...]\n");
791dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		}
792dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard		fprintf(options.output, "\n");
793dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard	  }
794dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard#endif /* defined(HAVE_LIBDW) */
795dfefa9f057857735a073ea655f5cb34351032c8eMark Wielaard
7968a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata	current_proc = NULL;
7972d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	current_column = 0;
798c40e64afa6a897bb7eb6fd4dc21f622632ae215aJuan Cespedes}
799d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata
800adec201a52c240cf4b533c05106aedddc911ca76Petr Machataint
8019c400988106520325615ad46a075b562649bbb38Petr Machatadelim_output(FILE *stream, int *need_delimp,
8029c400988106520325615ad46a075b562649bbb38Petr Machata	     int (*writer)(FILE *stream, void *data),
8039c400988106520325615ad46a075b562649bbb38Petr Machata	     void *data)
8049c400988106520325615ad46a075b562649bbb38Petr Machata{
8059c400988106520325615ad46a075b562649bbb38Petr Machata	int o;
8069c400988106520325615ad46a075b562649bbb38Petr Machata
8079c400988106520325615ad46a075b562649bbb38Petr Machata	/* If we don't need a delimiter, then we don't need to go
8089c400988106520325615ad46a075b562649bbb38Petr Machata	 * through a temporary stream.  It's all the same whether
8099c400988106520325615ad46a075b562649bbb38Petr Machata	 * WRITER emits anything or not.  */
8109c400988106520325615ad46a075b562649bbb38Petr Machata	if (!*need_delimp) {
8119c400988106520325615ad46a075b562649bbb38Petr Machata		o = writer(stream, data);
8129c400988106520325615ad46a075b562649bbb38Petr Machata
8139c400988106520325615ad46a075b562649bbb38Petr Machata	} else {
8142ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata		struct memstream ms;
8152ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata		if (memstream_init(&ms) < 0)
8162ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata			return -1;
8172ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata		o = writer(ms.stream, data);
8182ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata		if (memstream_close(&ms) < 0)
8192ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata			o = -1;
8209c400988106520325615ad46a075b562649bbb38Petr Machata		if (o > 0 && ((*need_delimp
8219c400988106520325615ad46a075b562649bbb38Petr Machata			       && account_output(&o, fprintf(stream, ", ")) < 0)
8222ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata			      || fwrite(ms.buf, 1, ms.size, stream) != ms.size))
8239c400988106520325615ad46a075b562649bbb38Petr Machata			o = -1;
8249c400988106520325615ad46a075b562649bbb38Petr Machata
8252ae374a196ca76406cd14503622060c2c5dc4cefPetr Machata		memstream_destroy(&ms);
8269c400988106520325615ad46a075b562649bbb38Petr Machata	}
8279c400988106520325615ad46a075b562649bbb38Petr Machata
8289c400988106520325615ad46a075b562649bbb38Petr Machata	if (o < 0)
8299c400988106520325615ad46a075b562649bbb38Petr Machata		return -1;
8309c400988106520325615ad46a075b562649bbb38Petr Machata
8319c400988106520325615ad46a075b562649bbb38Petr Machata	*need_delimp = *need_delimp || o > 0;
8329c400988106520325615ad46a075b562649bbb38Petr Machata	return o;
8339c400988106520325615ad46a075b562649bbb38Petr Machata}
8349c400988106520325615ad46a075b562649bbb38Petr Machata
8359c400988106520325615ad46a075b562649bbb38Petr Machataint
836adec201a52c240cf4b533c05106aedddc911ca76Petr Machataaccount_output(int *countp, int c)
837adec201a52c240cf4b533c05106aedddc911ca76Petr Machata{
838adec201a52c240cf4b533c05106aedddc911ca76Petr Machata	if (c > 0)
839adec201a52c240cf4b533c05106aedddc911ca76Petr Machata		*countp += c;
840adec201a52c240cf4b533c05106aedddc911ca76Petr Machata	return c;
841adec201a52c240cf4b533c05106aedddc911ca76Petr Machata}
842adec201a52c240cf4b533c05106aedddc911ca76Petr Machata
843d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machatastatic void
844d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machatado_report(const char *filename, unsigned line_no, const char *severity,
845d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	  const char *fmt, va_list args)
846d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata{
847d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	char buf[128];
848d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	vsnprintf(buf, sizeof(buf), fmt, args);
849d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	buf[sizeof(buf) - 1] = 0;
850d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	if (filename != NULL)
851d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata		output_line(0, "%s:%d: %s: %s",
852d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata			    filename, line_no, severity, buf);
853d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	else
854d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata		output_line(0, "%s: %s", severity, buf);
855d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata}
856d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata
857d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machatavoid
85889c5ca29993660f2edb2d875bd26748e09400f4dPetr Machatareport_error(const char *filename, unsigned line_no, const char *fmt, ...)
859d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata{
860d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_list args;
861d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_start(args, fmt);
862d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	do_report(filename, line_no, "error", fmt, args);
863d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_end(args);
864d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata}
865d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata
866d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machatavoid
86789c5ca29993660f2edb2d875bd26748e09400f4dPetr Machatareport_warning(const char *filename, unsigned line_no, const char *fmt, ...)
868d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata{
869d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_list args;
870d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_start(args, fmt);
871d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	do_report(filename, line_no, "warning", fmt, args);
872d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_end(args);
873d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata}
874d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata
875d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machatavoid
87689c5ca29993660f2edb2d875bd26748e09400f4dPetr Machatareport_global_error(const char *fmt, ...)
877d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata{
878d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_list args;
879d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_start(args, fmt);
880d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	do_report(NULL, 0, "error", fmt, args);
881d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata	va_end(args);
882d71cf2d1b61338c9e77acd5479b017dbc0d2dffdPetr Machata}
883