blob: d5b66e2871e3c250c874414095b72418b7794d90 [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 Cespedes5e0acdb1998-04-04 08:34:07 +02007#include <time.h>
8#include <sys/time.h>
9#include <unistd.h>
Juan Cespedes5e4455b1997-08-24 01:48:26 +020010
11#include "ltrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010012#include "options.h"
13#include "output.h"
Juan Cespedes5e4455b1997-08-24 01:48:26 +020014
Juan Cespedesac3db291998-04-25 14:31:58 +020015#if HAVE_LIBIBERTY
16#include "demangle.h"
17#endif
18
Juan Cespedes5e01f651998-03-08 22:31:44 +010019static pid_t current_pid = 0;
20static int current_column = 0;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020021static int indent_count = 0;
22
23void output_increase_indent(void)
24{
25 indent_count++;
26}
27
28void output_decrease_indent(void)
29{
30 indent_count--;
31}
32
33static void output_indent(void)
34{
35 int i, j;
36 for (i = 1; i < indent_count; i++) {
37 for (j = 0; j < opt_n; j++) fprintf(output, " ");
38 current_column += opt_n;
39 }
40}
Juan Cespedes5e4455b1997-08-24 01:48:26 +020041
Juan Cespedes5e01f651998-03-08 22:31:44 +010042static void begin_of_line(enum tof type, struct process * proc)
Juan Cespedes5e4455b1997-08-24 01:48:26 +020043{
Juan Cespedes5e01f651998-03-08 22:31:44 +010044 current_column = 0;
45 if (!proc) {
46 return;
Juan Cespedes5e4455b1997-08-24 01:48:26 +020047 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010048 if ((output!=stderr) && (opt_p || opt_f)) {
49 current_column += fprintf(output, "%u ", proc->pid);
50 } else if (list_of_processes->next) {
51 current_column += fprintf(output, "[pid %u] ", proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010052 }
Juan Cespedesf666d191998-09-20 23:04:34 +020053 if (opt_r) {
54 struct timeval tv;
55 struct timezone tz;
56 static struct timeval old_tv={0,0};
57 struct timeval diff;
58
59 gettimeofday(&tv, &tz);
60
61 if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
62 old_tv.tv_sec=tv.tv_sec;
63 old_tv.tv_usec=tv.tv_usec;
64 }
65 diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
66 if (tv.tv_usec >= old_tv.tv_usec) {
67 diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
68 } else {
69 diff.tv_sec++;
70 diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
71 }
72 old_tv.tv_sec = tv.tv_sec;
73 old_tv.tv_usec = tv.tv_usec;
74 current_column += fprintf(output, "%3lu.%06d ",
75 diff.tv_sec, (int)diff.tv_usec);
76 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020077 if (opt_t) {
78 struct timeval tv;
79 struct timezone tz;
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020080
81 gettimeofday(&tv, &tz);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020082 if (opt_t>2) {
83 current_column += fprintf(output, "%lu.%06d ",
84 tv.tv_sec, (int)tv.tv_usec);
85 } else if (opt_t>1) {
Juan Cespedesf666d191998-09-20 23:04:34 +020086 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020087 current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
88 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
89 } else {
Juan Cespedesf666d191998-09-20 23:04:34 +020090 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020091 current_column += fprintf(output, "%02d:%02d:%02d ",
92 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
93 }
94 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010095 if (opt_i) {
96 if (type==LT_TOF_FUNCTION) {
97 current_column += fprintf(output, "[%08x] ",
98 (unsigned)proc->return_addr);
99 } else {
100 current_column += fprintf(output, "[%08x] ",
101 (unsigned)proc->instruction_pointer);
102 }
103 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200104 if (opt_n > 0) {
105 output_indent();
106 }
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200107}
108
Juan Cespedes5e01f651998-03-08 22:31:44 +0100109static struct function * name2func(char * name)
110{
111 struct function * tmp;
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200112 const char * str1, * str2;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100113
114 tmp = list_of_functions;
115 while(tmp) {
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200116#if HAVE_LIBIBERTY
117 str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
118 str2 = opt_C ? my_demangle(name) : name;
119#else
120 str1 = tmp->name;
121 str2 = name;
122#endif
123 if (!strcmp(str1, str2)) {
124
Juan Cespedes5e01f651998-03-08 22:31:44 +0100125 return tmp;
126 }
127 tmp = tmp->next;
128 }
129 return NULL;
130}
131
132void output_line(struct process * proc, char *fmt, ...)
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200133{
134 va_list args;
135
Juan Cespedes5e01f651998-03-08 22:31:44 +0100136 if (current_pid) {
137 fprintf(output, " <unfinished ...>\n");
138 }
Juan Cespedes28f60191998-04-12 00:04:39 +0200139 current_pid=0;
140 if (!fmt) {
141 return;
142 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100143 begin_of_line(LT_TOF_NONE, proc);
144
145 va_start(args, fmt);
146 vfprintf(output, fmt, args);
147 fprintf(output, "\n");
148 va_end(args);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100149 current_column=0;
150}
151
152static void tabto(int col)
153{
154 if (current_column < col) {
155 fprintf(output, "%*s", col-current_column, "");
156 }
157}
158
159void output_left(enum tof type, struct process * proc, char * function_name)
160{
161 struct function * func;
162
163 if (current_pid) {
Juan Cespedes81690ef1998-03-13 19:31:29 +0100164#if 0 /* FIXME: should I do this? */
Juan Cespedes5e01f651998-03-08 22:31:44 +0100165 if (current_pid == proc->pid
166 && proc->type_being_displayed == LT_TOF_FUNCTION
167 && proc->type_being_displayed == type) {
168 tabto(opt_a);
169 fprintf(output, "= ???\n");
170 } else
171#endif
172 fprintf(output, " <unfinished ...>\n");
173 current_pid=0;
174 current_column=0;
175 }
176 current_pid=proc->pid;
177 proc->type_being_displayed = type;
178 begin_of_line(type, proc);
Juan Cespedesac3db291998-04-25 14:31:58 +0200179#if HAVE_LIBIBERTY
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200180 current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200181#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100182 current_column += fprintf(output, "%s(", function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200183#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100184
185 func = name2func(function_name);
186 if (!func) {
187 int i;
188 for(i=0; i<4; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200189 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100190 current_column += fprintf(output, ", ");
191 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200192 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100193 return;
194 } else {
195 int i;
196 for(i=0; i< func->num_params - func->params_right - 1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200197 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100198 current_column += fprintf(output, ", ");
199 }
200 if (func->num_params>func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200201 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100202 if (func->params_right) {
203 current_column += fprintf(output, ", ");
204 }
205 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100206 }
207}
208
209void output_right(enum tof type, struct process * proc, char * function_name)
210{
211 struct function * func = name2func(function_name);
212
Juan Cespedes5e01f651998-03-08 22:31:44 +0100213 if (current_pid && current_pid!=proc->pid) {
214 fprintf(output, " <unfinished ...>\n");
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200215 }
216 if (current_pid != proc->pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100217 begin_of_line(type, proc);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200218#if HAVE_LIBIBERTY
219 current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
220#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100221 current_column += fprintf(output, "<... %s resumed> ", function_name);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200222#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100223 }
224
225 if (!func) {
226 current_column += fprintf(output, ") ");
227 tabto(opt_a);
228 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200229 display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
Juan Cespedes3268a161997-08-25 16:45:22 +0200230 fprintf(output, "\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100231 } else {
232 int i;
233 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
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 current_column += fprintf(output, ", ");
236 }
237 if (func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200238 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100239 }
240 current_column += fprintf(output, ") ");
241 tabto(opt_a);
242 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200243 if (func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100244 fprintf(output, "<void>");
245 } else {
246 display_arg(type, proc, -1, func->return_type);
247 }
248 fprintf(output, "\n");
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200249 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100250 current_pid=0;
251 current_column=0;
Juan Cespedesc40e64a1997-10-26 20:34:00 +0100252}