blob: ed9743a6a13901eac6f8c09f173c16a906758ff0 [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;
21static int current_column = 0;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020022static int indent_count = 0;
23
Juan Cespedes21c63a12001-07-07 20:56:56 +020024static void output_increase_indent(void)
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020025{
26 indent_count++;
27}
28
Juan Cespedes21c63a12001-07-07 20:56:56 +020029static void output_decrease_indent(void)
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020030{
31 indent_count--;
32}
33
34static void output_indent(void)
35{
36 int i, j;
Juan Cespedes21c63a12001-07-07 20:56:56 +020037 for (i = 0; i < indent_count; i++) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020038 for (j = 0; j < opt_n; j++) fprintf(output, " ");
39 current_column += opt_n;
40 }
41}
Juan Cespedes5e4455b1997-08-24 01:48:26 +020042
Juan Cespedes5e01f651998-03-08 22:31:44 +010043static void begin_of_line(enum tof type, struct process * proc)
Juan Cespedes5e4455b1997-08-24 01:48:26 +020044{
Juan Cespedes5e01f651998-03-08 22:31:44 +010045 current_column = 0;
46 if (!proc) {
47 return;
Juan Cespedes5e4455b1997-08-24 01:48:26 +020048 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010049 if ((output!=stderr) && (opt_p || opt_f)) {
50 current_column += fprintf(output, "%u ", proc->pid);
51 } else if (list_of_processes->next) {
52 current_column += fprintf(output, "[pid %u] ", proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010053 }
Juan Cespedesf666d191998-09-20 23:04:34 +020054 if (opt_r) {
55 struct timeval tv;
56 struct timezone tz;
57 static struct timeval old_tv={0,0};
58 struct timeval diff;
59
60 gettimeofday(&tv, &tz);
61
62 if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
63 old_tv.tv_sec=tv.tv_sec;
64 old_tv.tv_usec=tv.tv_usec;
65 }
66 diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
67 if (tv.tv_usec >= old_tv.tv_usec) {
68 diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
69 } else {
70 diff.tv_sec++;
71 diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
72 }
73 old_tv.tv_sec = tv.tv_sec;
74 old_tv.tv_usec = tv.tv_usec;
75 current_column += fprintf(output, "%3lu.%06d ",
76 diff.tv_sec, (int)diff.tv_usec);
77 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020078 if (opt_t) {
79 struct timeval tv;
80 struct timezone tz;
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020081
82 gettimeofday(&tv, &tz);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020083 if (opt_t>2) {
84 current_column += fprintf(output, "%lu.%06d ",
85 tv.tv_sec, (int)tv.tv_usec);
86 } else if (opt_t>1) {
Juan Cespedesf666d191998-09-20 23:04:34 +020087 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020088 current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
89 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
90 } else {
Juan Cespedesf666d191998-09-20 23:04:34 +020091 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020092 current_column += fprintf(output, "%02d:%02d:%02d ",
93 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
94 }
95 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010096 if (opt_i) {
97 if (type==LT_TOF_FUNCTION) {
98 current_column += fprintf(output, "[%08x] ",
99 (unsigned)proc->return_addr);
100 } else {
101 current_column += fprintf(output, "[%08x] ",
102 (unsigned)proc->instruction_pointer);
103 }
104 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200105 if (opt_n > 0) {
106 output_indent();
107 }
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200108}
109
Juan Cespedes5e01f651998-03-08 22:31:44 +0100110static struct function * name2func(char * name)
111{
112 struct function * tmp;
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200113 const char * str1, * str2;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100114
115 tmp = list_of_functions;
116 while(tmp) {
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200117#if HAVE_LIBIBERTY
118 str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
119 str2 = opt_C ? my_demangle(name) : name;
120#else
121 str1 = tmp->name;
122 str2 = name;
123#endif
124 if (!strcmp(str1, str2)) {
125
Juan Cespedes5e01f651998-03-08 22:31:44 +0100126 return tmp;
127 }
128 tmp = tmp->next;
129 }
130 return NULL;
131}
132
133void output_line(struct process * proc, char *fmt, ...)
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200134{
135 va_list args;
136
Juan Cespedes5e01f651998-03-08 22:31:44 +0100137 if (current_pid) {
138 fprintf(output, " <unfinished ...>\n");
139 }
Juan Cespedes28f60191998-04-12 00:04:39 +0200140 current_pid=0;
141 if (!fmt) {
142 return;
143 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100144 begin_of_line(LT_TOF_NONE, proc);
145
Juan Cespedes21c63a12001-07-07 20:56:56 +0200146 va_start(args, fmt);
147 vfprintf(output, fmt, args);
148 fprintf(output, "\n");
149 va_end(args);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100150 current_column=0;
151}
152
153static void tabto(int col)
154{
155 if (current_column < col) {
156 fprintf(output, "%*s", col-current_column, "");
157 }
158}
159
160void output_left(enum tof type, struct process * proc, char * function_name)
161{
162 struct function * func;
163
164 if (current_pid) {
Juan Cespedes21c63a12001-07-07 20:56:56 +0200165 fprintf(output, " <unfinished ...>\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100166 current_pid=0;
167 current_column=0;
168 }
169 current_pid=proc->pid;
170 proc->type_being_displayed = type;
171 begin_of_line(type, proc);
Juan Cespedes21c63a12001-07-07 20:56:56 +0200172 output_increase_indent();
Juan Cespedesac3db291998-04-25 14:31:58 +0200173#if HAVE_LIBIBERTY
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200174 current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200175#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100176 current_column += fprintf(output, "%s(", function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200177#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100178
179 func = name2func(function_name);
180 if (!func) {
181 int i;
182 for(i=0; i<4; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200183 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100184 current_column += fprintf(output, ", ");
185 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200186 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100187 return;
188 } else {
189 int i;
190 for(i=0; i< func->num_params - func->params_right - 1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200191 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100192 current_column += fprintf(output, ", ");
193 }
194 if (func->num_params>func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200195 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100196 if (func->params_right) {
197 current_column += fprintf(output, ", ");
198 }
199 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100200 }
201}
202
203void output_right(enum tof type, struct process * proc, char * function_name)
204{
205 struct function * func = name2func(function_name);
206
Juan Cespedes21c63a12001-07-07 20:56:56 +0200207 output_decrease_indent();
208
Juan Cespedes5e01f651998-03-08 22:31:44 +0100209 if (current_pid && current_pid!=proc->pid) {
210 fprintf(output, " <unfinished ...>\n");
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200211 }
212 if (current_pid != proc->pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100213 begin_of_line(type, proc);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200214#if HAVE_LIBIBERTY
215 current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
216#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100217 current_column += fprintf(output, "<... %s resumed> ", function_name);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200218#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100219 }
220
221 if (!func) {
222 current_column += fprintf(output, ") ");
223 tabto(opt_a);
224 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200225 display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
Juan Cespedes3268a161997-08-25 16:45:22 +0200226 fprintf(output, "\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100227 } else {
228 int i;
229 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200230 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100231 current_column += fprintf(output, ", ");
232 }
233 if (func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200234 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100235 }
236 current_column += fprintf(output, ") ");
237 tabto(opt_a);
238 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200239 if (func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100240 fprintf(output, "<void>");
241 } else {
242 display_arg(type, proc, -1, func->return_type);
243 }
244 fprintf(output, "\n");
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200245 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100246 current_pid=0;
247 current_column=0;
Juan Cespedesc40e64a1997-10-26 20:34:00 +0100248}