output.c 22.7 KB
Newer Older
1 2
/*
 * This file is part of ltrace.
Petr Machata's avatar
Nits  
Petr Machata committed
3
 * Copyright (C) 2011,2012,2013,2014 Petr Machata, Red Hat Inc.
4 5
 * Copyright (C) 2010 Joe Damato
 * Copyright (C) 1997,1998,1999,2001,2002,2003,2004,2007,2008,2009 Juan Cespedes
6
 * Copyright (C) 2006 Paul Gilliam, IBM Corporation
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Copyright (C) 2006 Ian Wienand
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

Juan Cespedes's avatar
Juan Cespedes committed
25 26
#include "config.h"

Juan Céspedes's avatar
Juan Céspedes committed
27
#include <stdio.h>
Juan Cespedes's avatar
Juan Cespedes committed
28
#include <stdlib.h>
Juan Céspedes's avatar
Juan Céspedes committed
29
#include <stdarg.h>
Juan Cespedes's avatar
Juan Cespedes committed
30
#include <string.h>
Juan Cespedes's avatar
Juan Cespedes committed
31 32 33
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
34
#include <errno.h>
Petr Machata's avatar
Petr Machata committed
35
#include <assert.h>
36
#include <inttypes.h>
Juan Céspedes's avatar
Juan Céspedes committed
37

38
#include "output.h"
39
#include "demangle.h"
Petr Machata's avatar
Petr Machata committed
40 41
#include "fetch.h"
#include "lens_default.h"
42
#include "library.h"
Petr Machata's avatar
Petr Machata committed
43
#include "memstream.h"
44
#include "options.h"
Petr Machata's avatar
Petr Machata committed
45 46
#include "param.h"
#include "proc.h"
47
#include "prototype.h"
48
#include "summary.h"
49
#include "type.h"
50 51
#include "value.h"
#include "value_dict.h"
52
#include "filter.h"
53
#include "debug.h"
54 55 56 57

#if defined(HAVE_LIBDW)
#include "dwarf_prototypes.h"
#endif
Juan Cespedes's avatar
Juan Cespedes committed
58

59
static struct process *current_proc = NULL;
Petr Machata's avatar
Petr Machata committed
60
static size_t current_depth = 0;
Juan Cespedes's avatar
Juan Cespedes committed
61
static int current_column = 0;
Juan Cespedes's avatar
Juan Cespedes committed
62

63
static void
64
output_indent(struct process *proc)
Petr Machata's avatar
Petr Machata committed
65 66 67
{
	int d = options.indent * (proc->callstack_depth - 1);
	current_column += fprintf(options.output, "%*s", d, "");
Juan Cespedes's avatar
Juan Cespedes committed
68
}
Juan Céspedes's avatar
Juan Céspedes committed
69

70
static void
71
begin_of_line(struct process *proc, int is_func, int indent)
72
{
Juan Cespedes's avatar
Juan Cespedes committed
73 74 75 76
	current_column = 0;
	if (!proc) {
		return;
	}
77 78
	if ((options.output != stderr) && (opt_p || options.follow)) {
		current_column += fprintf(options.output, "%u ", proc->pid);
79
	} else if (options.follow) {
80
		current_column += fprintf(options.output, "[pid %u] ", proc->pid);
Juan Cespedes's avatar
Juan Cespedes committed
81
	}
Juan Cespedes's avatar
Juan Cespedes committed
82 83
	if (opt_r) {
		struct timeval tv;
84
		static struct timeval old_tv = { 0, 0 };
Juan Cespedes's avatar
Juan Cespedes committed
85 86
		struct timeval diff;

87
		gettimeofday(&tv, NULL);
Juan Cespedes's avatar
Juan Cespedes committed
88

89 90 91
		if (old_tv.tv_sec == 0 && old_tv.tv_usec == 0) {
			old_tv.tv_sec = tv.tv_sec;
			old_tv.tv_usec = tv.tv_usec;
Juan Cespedes's avatar
Juan Cespedes committed
92 93 94 95 96
		}
		diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
		if (tv.tv_usec >= old_tv.tv_usec) {
			diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
		} else {
Juan Cespedes's avatar
Juan Cespedes committed
97
			diff.tv_sec--;
Juan Cespedes's avatar
Juan Cespedes committed
98 99 100 101
			diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
		}
		old_tv.tv_sec = tv.tv_sec;
		old_tv.tv_usec = tv.tv_usec;
102
		current_column += fprintf(options.output, "%3lu.%06d ",
103 104
					  (unsigned long)diff.tv_sec,
					  (int)diff.tv_usec);
Juan Cespedes's avatar
Juan Cespedes committed
105
	}
Juan Cespedes's avatar
Juan Cespedes committed
106 107
	if (opt_t) {
		struct timeval tv;
108
		gettimeofday(&tv, NULL);
109
		if (opt_t > 2) {
110
			current_column += fprintf(options.output, "%lu.%06d ",
111 112
						  (unsigned long)tv.tv_sec,
						  (int)tv.tv_usec);
113 114 115
		} else if (opt_t > 1) {
			struct tm *tmp = localtime(&tv.tv_sec);
			current_column +=
116
			    fprintf(options.output, "%02d:%02d:%02d.%06d ",
117 118
				    tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
				    (int)tv.tv_usec);
Juan Cespedes's avatar
Juan Cespedes committed
119
		} else {
120
			struct tm *tmp = localtime(&tv.tv_sec);
121
			current_column += fprintf(options.output, "%02d:%02d:%02d ",
122 123
						  tmp->tm_hour, tmp->tm_min,
						  tmp->tm_sec);
Juan Cespedes's avatar
Juan Cespedes committed
124 125
		}
	}
Juan Céspedes's avatar
Juan Céspedes committed
126
	if (opt_i) {
127 128 129
		if (is_func) {
			struct callstack_element *stel
				= &proc->callstack[proc->callstack_depth - 1];
130
			current_column += fprintf(options.output, "[%p] ",
131 132
						  stel->return_addr);
		} else {
133
			current_column += fprintf(options.output, "[%p] ",
134
						  proc->instruction_pointer);
135
		}
Juan Céspedes's avatar
Juan Céspedes committed
136
	}
137
	if (options.indent > 0 && indent) {
Juan Cespedes's avatar
Juan Cespedes committed
138
		output_indent(proc);
Juan Cespedes's avatar
Juan Cespedes committed
139
	}
Juan Céspedes's avatar
Juan Céspedes committed
140 141
}

142 143 144
static struct arg_type_info *
get_unknown_type(void)
{
Petr Machata's avatar
Petr Machata committed
145 146 147 148 149 150 151 152 153
	static struct arg_type_info *ret = NULL;
	if (ret != NULL)
		return ret;

	static struct arg_type_info info;
	info = *type_get_simple(ARGTYPE_LONG);
	info.lens = &guess_lens;
	ret = &info;
	return ret;
154 155
}

156
/* The default prototype is: long X(long, long, long, long).  */
157
static struct prototype *
158 159
build_default_prototype(void)
{
160 161 162
	static struct prototype *ret = NULL;
	if (ret != NULL)
		return ret;
163

164 165
	static struct prototype proto;
	prototype_init(&proto);
166

167 168 169 170
	struct arg_type_info *unknown_type = get_unknown_type();
	assert(unknown_type != NULL);
	proto.return_info = unknown_type;
	proto.own_return_info = 0;
171

172 173
	struct param unknown_param;
	param_init_type(&unknown_param, unknown_type, 0);
Petr Machata's avatar
Petr Machata committed
174

175 176 177 178 179 180 181 182
	size_t i;
	for (i = 0; i < 4; ++i)
		if (prototype_push_param(&proto, &unknown_param) < 0) {
			report_global_error("build_default_prototype: %s",
					    strerror(errno));
			prototype_destroy(&proto);
			return NULL;
		}
183

184
	ret = &proto;
185 186 187
	return ret;
}

188 189 190 191 192 193 194 195 196 197 198 199
static bool
snip_period(char *buf)
{
	char *period = strrchr(buf, '.');
	if (period != NULL && strcmp(period, ".so") != 0) {
		*period = 0;
		return true;
	} else {
		return false;
	}
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
struct lookup_prototype_alias_context
{
	struct library *lib;
	struct prototype *result; // output
};
static enum callback_status
lookup_prototype_alias_cb(const char *name, void *data)
{
	struct lookup_prototype_alias_context *context =
		(struct lookup_prototype_alias_context*)data;

	struct library *lib = context->lib;

	context->result =
		protolib_lookup_prototype(lib->protolib, name,
					  lib->type != LT_LIBTYPE_SYSCALL);
	if (context->result != NULL)
		return CBS_STOP;

	return CBS_CONT;
}

222
static struct prototype *
223 224
library_get_prototype(struct library *lib, const char *name)
{
225 226 227
	if (lib->protolib == NULL) {
		size_t sz = strlen(lib->soname);
		char buf[sz + 1];
228
		memcpy(buf, lib->soname, sz + 1);
229 230 231 232 233 234 235 236 237

		do {
			if (protolib_cache_maybe_load(&g_protocache, buf, 0,
						      true, &lib->protolib) < 0)
				return NULL;
		} while (lib->protolib == NULL
			 && lib->type == LT_LIBTYPE_DSO
			 && snip_period(buf));

238
#if defined(HAVE_LIBDW)
Dima Kogan's avatar
Dima Kogan committed
239 240
		// DWARF data fills in the gaps in the .conf files, so I don't
		// check for lib->protolib==NULL here
241
		if (lib->dwfl_module != NULL &&
Dima Kogan's avatar
Dima Kogan committed
242 243 244
		    (filter_matches_library(options.plt_filter,    lib ) ||
		     filter_matches_library(options.static_filter, lib ) ||
		     filter_matches_library(options.export_filter, lib )))
245
			import_DWARF_prototypes(lib);
246
		else
Dima Kogan's avatar
Dima Kogan committed
247 248 249 250
			debug(DEBUG_FUNCTION,
			      "Filter didn't match prototype '%s' in lib '%s'. "
			      "Not importing",
			      name, lib->soname);
251 252
#endif

253 254 255 256
		if (lib->protolib == NULL)
			lib->protolib = protolib_cache_default(&g_protocache,
							       buf, 0);
	}
257 258 259
	if (lib->protolib == NULL)
		return NULL;

260 261 262 263 264 265 266 267 268 269
	struct prototype *result =
		protolib_lookup_prototype(lib->protolib, name,
					  lib->type != LT_LIBTYPE_SYSCALL);
	if (result != NULL)
		return result;

	// prototype not found. Is it aliased?
	struct lookup_prototype_alias_context context = {.lib = lib,
							 .result = NULL};
	library_exported_names_each_alias(&lib->exported_names, name,
270
					  NULL, lookup_prototype_alias_cb,
271 272 273 274
					  &context);

	// if found, the prototype is stored here, otherwise it's NULL
	return context.result;
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
}

struct find_proto_data {
	const char *name;
	struct prototype *ret;
};

static enum callback_status
find_proto_cb(struct process *proc, struct library *lib, void *d)
{
	struct find_proto_data *data = d;
	data->ret = library_get_prototype(lib, data->name);
	return CBS_STOP_IF(data->ret != NULL);
}

static struct prototype *
lookup_symbol_prototype(struct process *proc, struct library_symbol *libsym)
292
{
293 294 295
	if (libsym->proto != NULL)
		return libsym->proto;

296 297
	struct library *lib = libsym->lib;
	if (lib != NULL) {
298 299 300 301 302 303 304
		struct find_proto_data data = { libsym->name };
		data.ret = library_get_prototype(lib, libsym->name);
		if (data.ret == NULL
		    && libsym->plt_type == LS_TOPLT_EXEC)
			proc_each_library(proc, NULL, find_proto_cb, &data);
		if (data.ret != NULL)
			return data.ret;
305 306
	}

307
	return build_default_prototype();
Juan Céspedes's avatar
Juan Céspedes committed
308 309
}

310
void
311
output_line(struct process *proc, const char *fmt, ...)
312 313
{
	if (options.summary)
Juan Cespedes's avatar
Juan Cespedes committed
314
		return;
315 316 317

	if (current_proc != NULL) {
		if (current_proc->callstack[current_depth].return_addr)
318
			fprintf(options.output, " <unfinished ...>\n");
319
		else
320
			fprintf(options.output, " <no return ...>\n");
Juan Cespedes's avatar
Juan Cespedes committed
321
	}
322 323
	current_proc = NULL;
	if (fmt == NULL)
Juan Cespedes's avatar
Juan Cespedes committed
324
		return;
325

326
	begin_of_line(proc, 0, 0);
Juan Cespedes's avatar
Juan Cespedes committed
327

328
	va_list args;
Juan Cespedes's avatar
Juan Cespedes committed
329
	va_start(args, fmt);
330 331
	vfprintf(options.output, fmt, args);
	fprintf(options.output, "\n");
Juan Cespedes's avatar
Juan Cespedes committed
332
	va_end(args);
333

334
	current_column = 0;
Juan Cespedes's avatar
Juan Cespedes committed
335 336
}

337 338
static void
tabto(int col) {
Juan Cespedes's avatar
Juan Cespedes committed
339
	if (current_column < col) {
340
		fprintf(options.output, "%*s", col - current_column, "");
Juan Céspedes's avatar
Juan Céspedes committed
341 342
	}
}
Juan Cespedes's avatar
Juan Cespedes committed
343

344
static int
345
output_error(FILE *stream)
346
{
347
	return fprintf(stream, "?");
348 349 350
}

static int
351 352
fetch_simple_param(enum tof type, struct process *proc,
		   struct fetch_context *context,
353 354
		   struct value_dict *arguments,
		   struct arg_type_info *info, int own,
355 356 357 358 359 360 361 362
		   struct value *valuep)
{
	/* Arrays decay into pointers per C standard.  We check for
	 * this here, because here we also capture arrays that come
	 * from parameter packs.  */
	if (info->type == ARGTYPE_ARRAY) {
		struct arg_type_info *tmp = malloc(sizeof(*tmp));
		if (tmp != NULL) {
363
			type_init_pointer(tmp, info, own);
364
			tmp->lens = info->lens;
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
			info = tmp;
			own = 1;
		}
	}

	struct value value;
	value_init(&value, proc, NULL, info, own);
	if (fetch_arg_next(context, type, proc, info, &value) < 0)
		return -1;

	if (val_dict_push_next(arguments, &value) < 0) {
		value_destroy(&value);
		return -1;
	}

	if (valuep != NULL)
		*valuep = value;

	return 0;
}

static void
fetch_param_stop(struct value_dict *arguments, ssize_t *params_leftp)
{
	if (*params_leftp == -1)
		*params_leftp = val_dict_count(arguments);
}

Petr Machata's avatar
Petr Machata committed
393
static int
394 395
fetch_param_pack(enum tof type, struct process *proc,
		 struct fetch_context *context,
Petr Machata's avatar
Petr Machata committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
		 struct value_dict *arguments, struct param *param,
		 ssize_t *params_leftp)
{
	struct param_enum *e = param_pack_init(param, arguments);
	if (e == NULL)
		return -1;

	int ret = 0;
	while (1) {
		int insert_stop = 0;
		struct arg_type_info *info = malloc(sizeof(*info));
		if (info == NULL
		    || param_pack_next(param, e, info, &insert_stop) < 0) {
		fail:
			free(info);
			ret = -1;
			break;
		}

		if (insert_stop)
			fetch_param_stop(arguments, params_leftp);

418 419 420
		if (info->type == ARGTYPE_VOID) {
			type_destroy(info);
			free(info);
Petr Machata's avatar
Petr Machata committed
421
			break;
422
		}
Petr Machata's avatar
Petr Machata committed
423 424 425

		struct value val;
		if (fetch_simple_param(type, proc, context, arguments,
426
				       info, 1, &val) < 0)
Petr Machata's avatar
Petr Machata committed
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
			goto fail;

		int stop = 0;
		switch (param_pack_stop(param, e, &val)) {
		case PPCB_ERR:
			goto fail;
		case PPCB_STOP:
			stop = 1;
		case PPCB_CONT:
			break;
		}

		if (stop)
			break;
	}

	param_pack_done(param, e);
	return ret;
}

447
static int
448 449
fetch_one_param(enum tof type, struct process *proc,
		struct fetch_context *context,
Petr Machata's avatar
Petr Machata committed
450
		struct value_dict *arguments, struct param *param,
451 452
		ssize_t *params_leftp)
{
Petr Machata's avatar
Petr Machata committed
453
	switch (param->flavor) {
454
		int rc;
Petr Machata's avatar
Petr Machata committed
455 456
	case PARAM_FLAVOR_TYPE:
		return fetch_simple_param(type, proc, context, arguments,
457
					  param->u.type.type, 0, NULL);
Petr Machata's avatar
Petr Machata committed
458 459

	case PARAM_FLAVOR_PACK:
460 461 462 463 464 465 466
		if (fetch_param_pack_start(context,
					   param->u.pack.ppflavor) < 0)
			return -1;
	        rc = fetch_param_pack(type, proc, context, arguments,
				      param, params_leftp);
		fetch_param_pack_end(context);
		return rc;
Petr Machata's avatar
Petr Machata committed
467 468 469 470 471 472 473 474

	case PARAM_FLAVOR_STOP:
		fetch_param_stop(arguments, params_leftp);
		return 0;
	}

	assert(!"Invalid param flavor!");
	abort();
475 476
}

477 478 479 480 481 482 483 484 485 486 487 488 489
struct fetch_one_param_data
{
	struct process *proc;
	struct fetch_context *context;
	struct value_dict *arguments;
	ssize_t *params_leftp;
	enum tof tof;
};

static enum callback_status
fetch_one_param_cb(struct prototype *proto, struct param *param, void *data)
{
	struct fetch_one_param_data *cb_data = data;
490 491 492 493
	return CBS_STOP_IF(fetch_one_param(cb_data->tof, cb_data->proc,
					   cb_data->context,
					   cb_data->arguments, param,
					   cb_data->params_leftp) < 0);
494 495
}

496
static int
497 498
fetch_params(enum tof type, struct process *proc,
	     struct fetch_context *context,
499 500
	     struct value_dict *arguments, struct prototype *func,
	     ssize_t *params_leftp)
501
{
502 503 504 505 506
	struct fetch_one_param_data cb_data
		= { proc, context, arguments, params_leftp, type };
	if (prototype_each_param(func, NULL,
				 &fetch_one_param_cb, &cb_data) != NULL)
		return -1;
507 508 509

	/* Implicit stop at the end of parameter list.  */
	fetch_param_stop(arguments, params_leftp);
Petr Machata's avatar
Petr Machata committed
510

511 512 513
	return 0;
}

514 515 516 517 518 519
struct format_argument_data
{
	struct value *value;
	struct value_dict *arguments;
};

520
static int
521
format_argument_cb(FILE *stream, void *ptr)
522
{
523 524 525 526
	struct format_argument_data *data = ptr;
	int o = format_argument(stream, data->value, data->arguments);
	if (o < 0)
		o = output_error(stream);
527 528 529 530 531 532 533 534 535 536 537 538
	return o;
}

static int
output_params(struct value_dict *arguments, size_t start, size_t end,
	      int *need_delimp)
{
	size_t i;
	for (i = start; i < end; ++i) {
		struct value *value = val_dict_get_num(arguments, i);
		if (value == NULL)
			return -1;
539 540 541 542 543

		struct format_argument_data data = { value, arguments };
		int o = delim_output(options.output, need_delimp,
				     format_argument_cb, &data);
		if (o < 0)
544
			return -1;
545
		current_column += o;
546 547 548 549
	}
	return 0;
}

550
void
551
output_left(enum tof type, struct process *proc,
552 553
	    struct library_symbol *libsym)
{
554 555
	assert(! options.summary);

556
	if (current_proc) {
557
		fprintf(options.output, " <unfinished ...>\n");
558
		current_column = 0;
Juan Cespedes's avatar
Juan Cespedes committed
559
	}
560
	current_proc = proc;
Juan Cespedes's avatar
Juan Cespedes committed
561
	current_depth = proc->callstack_depth;
562
	begin_of_line(proc, type == LT_TOF_FUNCTION, 1);
563 564
	if (!options.hide_caller && libsym->lib != NULL
	    && libsym->plt_type != LS_TOPLT_NONE)
565 566 567 568
		/* We don't terribly mind failing this.  */
		account_output(&current_column,
			       fprintf(options.output, "%s->",
				       libsym->lib->soname));
569

570
	const char *name = libsym->name;
Juan Cespedes's avatar
Juan Cespedes committed
571
#ifdef USE_DEMANGLE
572
	if (options.demangle)
573
		name = my_demangle(libsym->name);
Juan Cespedes's avatar
Juan Cespedes committed
574
#endif
575
	if (account_output(&current_column,
576
			   fprintf(options.output, "%s", name)) < 0)
577
		return;
Juan Cespedes's avatar
Juan Cespedes committed
578

579 580 581 582 583 584 585 586 587 588 589
	if (libsym->lib != NULL
	    && libsym->lib->type != LT_LIBTYPE_MAIN
	    && libsym->plt_type == LS_TOPLT_NONE
	    && account_output(&current_column,
			      fprintf(options.output, "@%s",
				      libsym->lib->soname)) < 0)
		/* We do mind failing this though.  */
		return;

	account_output(&current_column, fprintf(options.output, "("));

590
	struct prototype *func = lookup_symbol_prototype(proc->leader, libsym);
591
	if (func == NULL) {
592
	fail:
593
		account_output(&current_column, fprintf(options.output, "???"));
594
		return;
595
	}
596

597 598
	struct fetch_context *context = fetch_arg_init(type, proc,
						       func->return_info);
599 600 601
	if (context == NULL)
		goto fail;

602
	struct value_dict *arguments = malloc(sizeof(*arguments));
603 604 605 606
	if (arguments == NULL) {
		fetch_arg_done(context);
		goto fail;
	}
607 608
	val_dict_init(arguments);

609 610 611 612 613 614
	ssize_t params_left = -1;
	int need_delim = 0;
	if (fetch_params(type, proc, context, arguments, func, &params_left) < 0
	    || output_params(arguments, 0, params_left, &need_delim) < 0) {
		val_dict_destroy(arguments);
		fetch_arg_done(context);
Petr Machata's avatar
Petr Machata committed
615 616
		arguments = NULL;
		context = NULL;
Juan Cespedes's avatar
Juan Cespedes committed
617
	}
618 619 620

	struct callstack_element *stel
		= &proc->callstack[proc->callstack_depth - 1];
621
	stel->fetch_context = context;
622
	stel->arguments = arguments;
623 624
	stel->out.params_left = params_left;
	stel->out.need_delim = need_delim;
Juan Cespedes's avatar
Juan Cespedes committed
625 626
}

627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
#if defined(HAVE_LIBDW)
/* Prints information about one frame of a thread.  Called by
   dwfl_getthread_frames in output_right.  Returns 1 when done (max
   number of frames reached).  Returns -1 on error.  Returns 0 on
   success (if there are more frames in the thread, call us again).  */
static int
frame_callback (Dwfl_Frame *state, void *arg)
{
	Dwarf_Addr pc;
	bool isactivation;

	int *frames = (int *) arg;

	if (!dwfl_frame_pc(state, &pc, &isactivation))
		return -1;

	if (!isactivation)
		pc--;

	Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(state));
	Dwfl_Module *mod = dwfl_addrmodule(dwfl, pc);
	const char *modname = NULL;
	const char *symname = NULL;
	GElf_Off off = 0;
	if (mod != NULL) {
		GElf_Sym sym;
		modname = dwfl_module_info(mod, NULL, NULL, NULL, NULL,
					   NULL, NULL, NULL);
		symname = dwfl_module_addrinfo(mod, pc, &off, &sym,
					       NULL, NULL, NULL);
	}

	/* This mimics the output produced by libunwind below.  */
	fprintf(options.output, " > %s(%s+0x%" PRIx64 ") [%" PRIx64 "]\n",
		modname, symname, off, pc);

	/* See if we can extract the source line too and print it on
	   the next line if we can find it.  */
	if (mod != NULL) {
		Dwfl_Line *l = dwfl_module_getsrc(mod, pc);
		if (l != NULL) {
			int line, col;
			line = col = -1;
			const char *src = dwfl_lineinfo(l, NULL, &line, &col,
							NULL, NULL);
			if (src != NULL) {
				fprintf(options.output, "\t%s", src);
				if (line > 0) {
					fprintf(options.output, ":%d", line);
					if (col > 0)
			                        fprintf(options.output,
							":%d", col);
				}
				fprintf(options.output, "\n");
			}

		}
	}

	/* Max number of frames to print reached? */
	if ((*frames)-- == 0)
		return 1;

	return 0;
}
#endif /* defined(HAVE_LIBDW) */

694
void
695 696
output_right(enum tof type, struct process *proc, struct library_symbol *libsym,
	     struct timedelta *spent)
Petr Machata's avatar
Petr Machata committed
697
{
698 699
	assert(! options.summary);

700
	struct prototype *func = lookup_symbol_prototype(proc, libsym);
701 702
	if (func == NULL)
		return;
Juan Cespedes's avatar
Juan Cespedes committed
703

704 705 706
	if (current_proc != NULL
		    && (current_proc != proc
			|| current_depth != proc->callstack_depth)) {
707
		fprintf(options.output, " <unfinished ...>\n");
708
		current_proc = NULL;
Juan Cespedes's avatar
Juan Cespedes committed
709
	}
710
	if (current_proc != proc) {
711
		begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1);
Juan Cespedes's avatar
Juan Cespedes committed
712
#ifdef USE_DEMANGLE
713
		current_column +=
714
		    fprintf(options.output, "<... %s resumed> ",
715 716
			    options.demangle ? my_demangle(libsym->name)
			    : libsym->name);
Juan Cespedes's avatar
Juan Cespedes committed
717
#else
718
		current_column +=
719
		    fprintf(options.output, "<... %s resumed> ", libsym->name);
Juan Cespedes's avatar
Juan Cespedes committed
720
#endif
Juan Cespedes's avatar
Juan Cespedes committed
721 722
	}

723 724 725
	struct callstack_element *stel
		= &proc->callstack[proc->callstack_depth - 1];

726 727 728 729
	struct fetch_context *context = stel->fetch_context;

	/* Fetch & enter into dictionary the retval first, so that
	 * other values can use it in expressions.  */
730
	struct value retval;
Petr Machata's avatar
Nits  
Petr Machata committed
731
	bool own_retval = false;
732 733
	if (context != NULL) {
		value_init(&retval, proc, NULL, func->return_info, 0);
Petr Machata's avatar
Nits  
Petr Machata committed
734
		own_retval = true;
735
		if (fetch_retval(context, type, proc, func->return_info,
736 737 738
				 &retval) < 0)
			value_set_type(&retval, NULL, 0);
		else if (stel->arguments != NULL
Petr Machata's avatar
Nits  
Petr Machata committed
739 740 741
			 && val_dict_push_named(stel->arguments, &retval,
						"retval", 0) == 0)
			own_retval = false;
Juan Cespedes's avatar
Juan Cespedes committed
742
	}
743

744 745 746 747 748 749 750 751 752
	if (stel->arguments != NULL)
		output_params(stel->arguments, stel->out.params_left,
			      val_dict_count(stel->arguments),
			      &stel->out.need_delim);

	current_column += fprintf(options.output, ") ");
	tabto(options.align - 1);
	fprintf(options.output, "= ");

753 754 755 756
	if (context != NULL && retval.type != NULL) {
		struct format_argument_data data = { &retval, stel->arguments };
		format_argument_cb(options.output, &data);
	}
757 758 759 760

	if (own_retval)
		value_destroy(&retval);

Juan Cespedes's avatar
Juan Cespedes committed
761
	if (opt_T) {
762
		assert(spent != NULL);
763
		fprintf(options.output, " <%lu.%06d>",
764 765
			(unsigned long) spent->tm.tv_sec,
			(int) spent->tm.tv_usec);
Juan Cespedes's avatar
Juan Cespedes committed
766
	}
767

768
	fprintf(options.output, "\n");
769 770

#if defined(HAVE_LIBUNWIND)
771 772 773
	if (options.bt_depth > 0
	    && proc->unwind_priv != NULL
	    && proc->unwind_as != NULL) {
774
		unw_cursor_t cursor;
775 776
		arch_addr_t ip, function_offset;
		struct library *lib = NULL;
777 778
		int unwind_depth = options.bt_depth;
		char fn_name[100];
779 780
		const char *lib_name;
		size_t distance;
781

782 783 784 785
		/* Verify that we can safely cast arch_addr_t* to
		 * unw_word_t*.  */
		(void)sizeof(char[1 - 2*(sizeof(unw_word_t)
					!= sizeof(arch_addr_t))]);
786 787
		unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv);
		while (unwind_depth) {
788

Petr Machata's avatar
Nits  
Petr Machata committed
789 790 791
			int rc = unw_get_reg(&cursor, UNW_REG_IP,
					     (unw_word_t *) &ip);
			if (rc < 0) {
792
				fprintf(options.output, " > Error: %s\n",
Petr Machata's avatar
Nits  
Petr Machata committed
793
					unw_strerror(rc));
794
				goto cont;
795
			}
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814

			/* We are looking for the library with the base address
			 * closest to the current ip.  */
			lib_name = "unmapped_area";
			distance = (size_t) -1;
			lib = proc->libraries;
			while (lib != NULL) {
				/* N.B.: Assumes sizeof(size_t) ==
				 * sizeof(arch_addr_t).
				 * Keyword: double cast.  */
				if ((ip >= lib->base) &&
					    ((size_t)(ip - lib->base)
					    < distance)) {
					distance = ip - lib->base;
					lib_name = lib->pathname;
				}
				lib = lib->next;
			}

Petr Machata's avatar
Nits  
Petr Machata committed
815 816 817 818
			rc = unw_get_proc_name(&cursor, fn_name,
					       sizeof(fn_name),
					       (unw_word_t *) &function_offset);
			if (rc == 0 || rc == -UNW_ENOMEM)
819
				fprintf(options.output, " > %s(%s+%p) [%p]\n",
820
					lib_name, fn_name, function_offset, ip);
821 822 823
			else
				fprintf(options.output, " > %s(??\?) [%p]\n",
					lib_name, ip);
824

825
		cont:
826 827 828 829 830 831 832 833
			if (unw_step(&cursor) <= 0)
				break;
			unwind_depth--;
		}
		fprintf(options.output, "\n");
	}
#endif /* defined(HAVE_LIBUNWIND) */

834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
#if defined(HAVE_LIBDW)
	if (options.bt_depth > 0 && proc->leader->dwfl != NULL) {
		int frames = options.bt_depth;
		if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid,
					  frame_callback, &frames) < 0) {
			// Only print an error if we couldn't show anything.
			// Otherwise just show there might be more...
			if (frames == options.bt_depth)
				fprintf(stderr,
					"dwfl_getthread_frames tid %d: %s\n",
					proc->pid, dwfl_errmsg(-1));
			else
				fprintf(options.output, " > [...]\n");
		}
		fprintf(options.output, "\n");
	  }
#endif /* defined(HAVE_LIBDW) */

852
	current_proc = NULL;
853
	current_column = 0;
Juan Cespedes's avatar
Juan Cespedes committed
854
}
855

Petr Machata's avatar
Petr Machata committed
856 857 858 859 860 861 862 863 864 865 866 867 868 869
int
delim_output(FILE *stream, int *need_delimp,
	     int (*writer)(FILE *stream, void *data),
	     void *data)
{
	int o;

	/* If we don't need a delimiter, then we don't need to go
	 * through a temporary stream.  It's all the same whether
	 * WRITER emits anything or not.  */
	if (!*need_delimp) {
		o = writer(stream, data);

	} else {
870 871 872 873 874 875
		struct memstream ms;
		if (memstream_init(&ms) < 0)
			return -1;
		o = writer(ms.stream, data);
		if (memstream_close(&ms) < 0)
			o = -1;
Petr Machata's avatar
Petr Machata committed
876 877
		if (o > 0 && ((*need_delimp
			       && account_output(&o, fprintf(stream, ", ")) < 0)
878
			      || fwrite(ms.buf, 1, ms.size, stream) != ms.size))
Petr Machata's avatar
Petr Machata committed
879 880
			o = -1;

881
		memstream_destroy(&ms);
Petr Machata's avatar
Petr Machata committed
882 883 884 885 886 887 888 889 890
	}

	if (o < 0)
		return -1;

	*need_delimp = *need_delimp || o > 0;
	return o;
}

891 892 893 894 895 896 897 898
int
account_output(int *countp, int c)
{
	if (c > 0)
		*countp += c;
	return c;
}

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
static void
do_report(const char *filename, unsigned line_no, const char *severity,
	  const char *fmt, va_list args)
{
	char buf[128];
	vsnprintf(buf, sizeof(buf), fmt, args);
	buf[sizeof(buf) - 1] = 0;
	if (filename != NULL)
		output_line(0, "%s:%d: %s: %s",
			    filename, line_no, severity, buf);
	else
		output_line(0, "%s: %s", severity, buf);
}

void
914
report_error(const char *filename, unsigned line_no, const char *fmt, ...)
915 916 917 918 919 920 921 922
{
	va_list args;
	va_start(args, fmt);
	do_report(filename, line_no, "error", fmt, args);
	va_end(args);
}

void
923
report_warning(const char *filename, unsigned line_no, const char *fmt, ...)
924 925 926 927 928 929 930 931
{
	va_list args;
	va_start(args, fmt);
	do_report(filename, line_no, "warning", fmt, args);
	va_end(args);
}

void
932
report_global_error(const char *fmt, ...)
933 934 935 936 937 938
{
	va_list args;
	va_start(args, fmt);
	do_report(NULL, 0, "error", fmt, args);
	va_end(args);
}