blob: 892713687142d3215d4d1cbb008cd372e6c485ec [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 Cespedes5e4455b1997-08-24 01:48:26 +020021
Juan Cespedes5e01f651998-03-08 22:31:44 +010022static void begin_of_line(enum tof type, struct process * proc)
Juan Cespedes5e4455b1997-08-24 01:48:26 +020023{
Juan Cespedes5e01f651998-03-08 22:31:44 +010024 current_column = 0;
25 if (!proc) {
26 return;
Juan Cespedes5e4455b1997-08-24 01:48:26 +020027 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010028 if ((output!=stderr) && (opt_p || opt_f)) {
29 current_column += fprintf(output, "%u ", proc->pid);
30 } else if (list_of_processes->next) {
31 current_column += fprintf(output, "[pid %u] ", proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010032 }
Juan Cespedesf666d191998-09-20 23:04:34 +020033 if (opt_r) {
34 struct timeval tv;
35 struct timezone tz;
36 static struct timeval old_tv={0,0};
37 struct timeval diff;
38
39 gettimeofday(&tv, &tz);
40
41 if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
42 old_tv.tv_sec=tv.tv_sec;
43 old_tv.tv_usec=tv.tv_usec;
44 }
45 diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
46 if (tv.tv_usec >= old_tv.tv_usec) {
47 diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
48 } else {
49 diff.tv_sec++;
50 diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
51 }
52 old_tv.tv_sec = tv.tv_sec;
53 old_tv.tv_usec = tv.tv_usec;
54 current_column += fprintf(output, "%3lu.%06d ",
55 diff.tv_sec, (int)diff.tv_usec);
56 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020057 if (opt_t) {
58 struct timeval tv;
59 struct timezone tz;
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020060
61 gettimeofday(&tv, &tz);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020062 if (opt_t>2) {
63 current_column += fprintf(output, "%lu.%06d ",
64 tv.tv_sec, (int)tv.tv_usec);
65 } else if (opt_t>1) {
Juan Cespedesf666d191998-09-20 23:04:34 +020066 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020067 current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
68 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
69 } else {
Juan Cespedesf666d191998-09-20 23:04:34 +020070 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020071 current_column += fprintf(output, "%02d:%02d:%02d ",
72 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
73 }
74 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010075 if (opt_i) {
76 if (type==LT_TOF_FUNCTION) {
77 current_column += fprintf(output, "[%08x] ",
78 (unsigned)proc->return_addr);
79 } else {
80 current_column += fprintf(output, "[%08x] ",
81 (unsigned)proc->instruction_pointer);
82 }
83 }
Juan Cespedes5e4455b1997-08-24 01:48:26 +020084}
85
Juan Cespedes5e01f651998-03-08 22:31:44 +010086static struct function * name2func(char * name)
87{
88 struct function * tmp;
Juan Cespedes1b9cfd61999-08-30 19:34:50 +020089 const char * str1, * str2;
Juan Cespedes5e01f651998-03-08 22:31:44 +010090
91 tmp = list_of_functions;
92 while(tmp) {
Juan Cespedes1b9cfd61999-08-30 19:34:50 +020093#if HAVE_LIBIBERTY
94 str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
95 str2 = opt_C ? my_demangle(name) : name;
96#else
97 str1 = tmp->name;
98 str2 = name;
99#endif
100 if (!strcmp(str1, str2)) {
101
Juan Cespedes5e01f651998-03-08 22:31:44 +0100102 return tmp;
103 }
104 tmp = tmp->next;
105 }
106 return NULL;
107}
108
109void output_line(struct process * proc, char *fmt, ...)
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200110{
111 va_list args;
112
Juan Cespedes5e01f651998-03-08 22:31:44 +0100113 if (current_pid) {
114 fprintf(output, " <unfinished ...>\n");
115 }
Juan Cespedes28f60191998-04-12 00:04:39 +0200116 current_pid=0;
117 if (!fmt) {
118 return;
119 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100120 begin_of_line(LT_TOF_NONE, proc);
121
122 va_start(args, fmt);
123 vfprintf(output, fmt, args);
124 fprintf(output, "\n");
125 va_end(args);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100126 current_column=0;
127}
128
129static void tabto(int col)
130{
131 if (current_column < col) {
132 fprintf(output, "%*s", col-current_column, "");
133 }
134}
135
136void output_left(enum tof type, struct process * proc, char * function_name)
137{
138 struct function * func;
139
140 if (current_pid) {
Juan Cespedes81690ef1998-03-13 19:31:29 +0100141#if 0 /* FIXME: should I do this? */
Juan Cespedes5e01f651998-03-08 22:31:44 +0100142 if (current_pid == proc->pid
143 && proc->type_being_displayed == LT_TOF_FUNCTION
144 && proc->type_being_displayed == type) {
145 tabto(opt_a);
146 fprintf(output, "= ???\n");
147 } else
148#endif
149 fprintf(output, " <unfinished ...>\n");
150 current_pid=0;
151 current_column=0;
152 }
153 current_pid=proc->pid;
154 proc->type_being_displayed = type;
155 begin_of_line(type, proc);
Juan Cespedesac3db291998-04-25 14:31:58 +0200156#if HAVE_LIBIBERTY
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200157 current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200158#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100159 current_column += fprintf(output, "%s(", function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200160#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100161
162 func = name2func(function_name);
163 if (!func) {
164 int i;
165 for(i=0; i<4; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200166 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100167 current_column += fprintf(output, ", ");
168 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200169 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100170 return;
171 } else {
172 int i;
173 for(i=0; i< func->num_params - func->params_right - 1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200174 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100175 current_column += fprintf(output, ", ");
176 }
177 if (func->num_params>func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200178 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100179 if (func->params_right) {
180 current_column += fprintf(output, ", ");
181 }
182 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200183 if (!func->params_right && func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100184 current_column += fprintf(output, ") ");
185 tabto(opt_a);
186 fprintf(output, "= <void>\n");
187 current_pid = 0;
188 current_column = 0;
189 }
190 }
191}
192
193void output_right(enum tof type, struct process * proc, char * function_name)
194{
195 struct function * func = name2func(function_name);
196
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200197 if (func && func->params_right==0 && func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100198 return;
199 }
200
201 if (current_pid && current_pid!=proc->pid) {
202 fprintf(output, " <unfinished ...>\n");
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200203 }
204 if (current_pid != proc->pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100205 begin_of_line(type, proc);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200206#if HAVE_LIBIBERTY
207 current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
208#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100209 current_column += fprintf(output, "<... %s resumed> ", function_name);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200210#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100211 }
212
213 if (!func) {
214 current_column += fprintf(output, ") ");
215 tabto(opt_a);
216 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200217 display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
Juan Cespedes3268a161997-08-25 16:45:22 +0200218 fprintf(output, "\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100219 } else {
220 int i;
221 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200222 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100223 current_column += fprintf(output, ", ");
224 }
225 if (func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200226 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100227 }
228 current_column += fprintf(output, ") ");
229 tabto(opt_a);
230 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200231 if (func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100232 fprintf(output, "<void>");
233 } else {
234 display_arg(type, proc, -1, func->return_type);
235 }
236 fprintf(output, "\n");
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200237 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100238 current_pid=0;
239 current_column=0;
Juan Cespedesc40e64a1997-10-26 20:34:00 +0100240}