blob: 4a773a7971129779f76b7ddafdbe7619f44ff945 [file] [log] [blame]
Juan Cespedesac3db291998-04-25 14:31:58 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes3268a161997-08-25 16:45:22 +02005#include <stdio.h>
Juan Cespedes5e4455b1997-08-24 01:48:26 +02006#include <stdarg.h>
Juan Cespedes1cd999a2001-07-03 00:46:04 +02007#include <string.h>
Juan Cespedes5e0acdb1998-04-04 08:34:07 +02008#include <time.h>
9#include <sys/time.h>
10#include <unistd.h>
Juan Cespedes5e4455b1997-08-24 01:48:26 +020011
12#include "ltrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010013#include "options.h"
14#include "output.h"
Juan Cespedes5e4455b1997-08-24 01:48:26 +020015
Juan Cespedesac3db291998-04-25 14:31:58 +020016#if HAVE_LIBIBERTY
17#include "demangle.h"
18#endif
19
Juan Cespedes5e01f651998-03-08 22:31:44 +010020static pid_t current_pid = 0;
Juan Cespedes5916fda2002-02-25 00:19:21 +010021static int current_depth = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +010022static int current_column = 0;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020023
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010024static void
25output_indent(struct process * proc) {
Juan Cespedes3f0b62e2001-07-09 01:02:52 +020026 current_column += fprintf(output, "%*s", opt_n * proc->callstack_depth, "");
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020027}
Juan Cespedes5e4455b1997-08-24 01:48:26 +020028
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010029static void
30begin_of_line(enum tof type, struct process * proc) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010031 current_column = 0;
32 if (!proc) {
33 return;
Juan Cespedes5e4455b1997-08-24 01:48:26 +020034 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010035 if ((output!=stderr) && (opt_p || opt_f)) {
36 current_column += fprintf(output, "%u ", proc->pid);
37 } else if (list_of_processes->next) {
38 current_column += fprintf(output, "[pid %u] ", proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010039 }
Juan Cespedesf666d191998-09-20 23:04:34 +020040 if (opt_r) {
41 struct timeval tv;
42 struct timezone tz;
43 static struct timeval old_tv={0,0};
44 struct timeval diff;
45
46 gettimeofday(&tv, &tz);
47
48 if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
49 old_tv.tv_sec=tv.tv_sec;
50 old_tv.tv_usec=tv.tv_usec;
51 }
52 diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
53 if (tv.tv_usec >= old_tv.tv_usec) {
54 diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
55 } else {
56 diff.tv_sec++;
57 diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
58 }
59 old_tv.tv_sec = tv.tv_sec;
60 old_tv.tv_usec = tv.tv_usec;
61 current_column += fprintf(output, "%3lu.%06d ",
62 diff.tv_sec, (int)diff.tv_usec);
63 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020064 if (opt_t) {
65 struct timeval tv;
66 struct timezone tz;
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020067
68 gettimeofday(&tv, &tz);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020069 if (opt_t>2) {
70 current_column += fprintf(output, "%lu.%06d ",
71 tv.tv_sec, (int)tv.tv_usec);
72 } else if (opt_t>1) {
Juan Cespedesf666d191998-09-20 23:04:34 +020073 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020074 current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
75 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
76 } else {
Juan Cespedesf666d191998-09-20 23:04:34 +020077 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020078 current_column += fprintf(output, "%02d:%02d:%02d ",
79 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
80 }
81 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010082 if (opt_i) {
83 if (type==LT_TOF_FUNCTION) {
84 current_column += fprintf(output, "[%08x] ",
85 (unsigned)proc->return_addr);
86 } else {
87 current_column += fprintf(output, "[%08x] ",
88 (unsigned)proc->instruction_pointer);
89 }
90 }
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010091 if (opt_n > 0 && type!=LT_TOF_NONE) {
Juan Cespedes3f0b62e2001-07-09 01:02:52 +020092 output_indent(proc);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020093 }
Juan Cespedes5e4455b1997-08-24 01:48:26 +020094}
95
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010096static struct function *
97name2func(char * name) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010098 struct function * tmp;
Juan Cespedes1b9cfd61999-08-30 19:34:50 +020099 const char * str1, * str2;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100100
101 tmp = list_of_functions;
102 while(tmp) {
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200103#if HAVE_LIBIBERTY
104 str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
105 str2 = opt_C ? my_demangle(name) : name;
106#else
107 str1 = tmp->name;
108 str2 = name;
109#endif
110 if (!strcmp(str1, str2)) {
111
Juan Cespedes5e01f651998-03-08 22:31:44 +0100112 return tmp;
113 }
114 tmp = tmp->next;
115 }
116 return NULL;
117}
118
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100119void
120output_line(struct process * proc, char *fmt, ...) {
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200121 va_list args;
122
Juan Cespedes5e01f651998-03-08 22:31:44 +0100123 if (current_pid) {
124 fprintf(output, " <unfinished ...>\n");
125 }
Juan Cespedes28f60191998-04-12 00:04:39 +0200126 current_pid=0;
127 if (!fmt) {
128 return;
129 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100130 begin_of_line(LT_TOF_NONE, proc);
131
Juan Cespedes21c63a12001-07-07 20:56:56 +0200132 va_start(args, fmt);
133 vfprintf(output, fmt, args);
134 fprintf(output, "\n");
135 va_end(args);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100136 current_column=0;
137}
138
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100139static void
140tabto(int col) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100141 if (current_column < col) {
142 fprintf(output, "%*s", col-current_column, "");
143 }
144}
145
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100146void
147output_left(enum tof type, struct process * proc, char * function_name) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100148 struct function * func;
149
150 if (current_pid) {
Juan Cespedes21c63a12001-07-07 20:56:56 +0200151 fprintf(output, " <unfinished ...>\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100152 current_pid=0;
153 current_column=0;
154 }
Juan Cespedes5916fda2002-02-25 00:19:21 +0100155 current_pid = proc->pid;
156 current_depth = proc->callstack_depth;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100157 proc->type_being_displayed = type;
158 begin_of_line(type, proc);
Juan Cespedesac3db291998-04-25 14:31:58 +0200159#if HAVE_LIBIBERTY
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200160 current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200161#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100162 current_column += fprintf(output, "%s(", function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200163#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100164
165 func = name2func(function_name);
166 if (!func) {
167 int i;
168 for(i=0; i<4; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200169 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100170 current_column += fprintf(output, ", ");
171 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200172 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100173 return;
174 } else {
175 int i;
176 for(i=0; i< func->num_params - func->params_right - 1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200177 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100178 current_column += fprintf(output, ", ");
179 }
180 if (func->num_params>func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200181 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100182 if (func->params_right) {
183 current_column += fprintf(output, ", ");
184 }
185 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100186 }
187}
188
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100189void
190output_right(enum tof type, struct process * proc, char * function_name) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100191 struct function * func = name2func(function_name);
192
Juan Cespedes6ff816f2002-03-01 21:05:39 +0100193 if (current_pid && (current_pid!=proc->pid ||
194 current_depth != proc->callstack_depth)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100195 fprintf(output, " <unfinished ...>\n");
Juan Cespedes5916fda2002-02-25 00:19:21 +0100196 current_pid = 0;
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200197 }
198 if (current_pid != proc->pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100199 begin_of_line(type, proc);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200200#if HAVE_LIBIBERTY
201 current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
202#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100203 current_column += fprintf(output, "<... %s resumed> ", function_name);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200204#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100205 }
206
207 if (!func) {
208 current_column += fprintf(output, ") ");
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100209 tabto(opt_a-1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100210 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200211 display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
Juan Cespedes3268a161997-08-25 16:45:22 +0200212 fprintf(output, "\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100213 } else {
214 int i;
215 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200216 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100217 current_column += fprintf(output, ", ");
218 }
219 if (func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200220 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100221 }
222 current_column += fprintf(output, ") ");
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100223 tabto(opt_a-1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100224 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200225 if (func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100226 fprintf(output, "<void>");
227 } else {
228 display_arg(type, proc, -1, func->return_type);
229 }
230 fprintf(output, "\n");
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200231 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100232 current_pid=0;
233 current_column=0;
Juan Cespedesc40e64a1997-10-26 20:34:00 +0100234}