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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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, ¶ms_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