blob: 577983a1f058bc57e54c2928cd21bbe82ae6f51f [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;
89
90 tmp = list_of_functions;
91 while(tmp) {
92 if (!strcmp(tmp->name, name)) {
93 return tmp;
94 }
95 tmp = tmp->next;
96 }
97 return NULL;
98}
99
100void output_line(struct process * proc, char *fmt, ...)
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200101{
102 va_list args;
103
Juan Cespedes5e01f651998-03-08 22:31:44 +0100104 if (current_pid) {
105 fprintf(output, " <unfinished ...>\n");
106 }
Juan Cespedes28f60191998-04-12 00:04:39 +0200107 current_pid=0;
108 if (!fmt) {
109 return;
110 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 begin_of_line(LT_TOF_NONE, proc);
112
113 va_start(args, fmt);
114 vfprintf(output, fmt, args);
115 fprintf(output, "\n");
116 va_end(args);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100117 current_column=0;
118}
119
120static void tabto(int col)
121{
122 if (current_column < col) {
123 fprintf(output, "%*s", col-current_column, "");
124 }
125}
126
127void output_left(enum tof type, struct process * proc, char * function_name)
128{
129 struct function * func;
130
131 if (current_pid) {
Juan Cespedes81690ef1998-03-13 19:31:29 +0100132#if 0 /* FIXME: should I do this? */
Juan Cespedes5e01f651998-03-08 22:31:44 +0100133 if (current_pid == proc->pid
134 && proc->type_being_displayed == LT_TOF_FUNCTION
135 && proc->type_being_displayed == type) {
136 tabto(opt_a);
137 fprintf(output, "= ???\n");
138 } else
139#endif
140 fprintf(output, " <unfinished ...>\n");
141 current_pid=0;
142 current_column=0;
143 }
144 current_pid=proc->pid;
145 proc->type_being_displayed = type;
146 begin_of_line(type, proc);
Juan Cespedesac3db291998-04-25 14:31:58 +0200147#if HAVE_LIBIBERTY
148 current_column += fprintf(output, "%s(", my_demangle(function_name));
149#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100150 current_column += fprintf(output, "%s(", function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200151#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100152
153 func = name2func(function_name);
154 if (!func) {
155 int i;
156 for(i=0; i<4; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200157 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100158 current_column += fprintf(output, ", ");
159 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200160 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100161 return;
162 } else {
163 int i;
164 for(i=0; i< func->num_params - func->params_right - 1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200165 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100166 current_column += fprintf(output, ", ");
167 }
168 if (func->num_params>func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200169 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100170 if (func->params_right) {
171 current_column += fprintf(output, ", ");
172 }
173 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200174 if (!func->params_right && func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100175 current_column += fprintf(output, ") ");
176 tabto(opt_a);
177 fprintf(output, "= <void>\n");
178 current_pid = 0;
179 current_column = 0;
180 }
181 }
182}
183
184void output_right(enum tof type, struct process * proc, char * function_name)
185{
186 struct function * func = name2func(function_name);
187
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200188 if (func && func->params_right==0 && func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100189 return;
190 }
191
192 if (current_pid && current_pid!=proc->pid) {
193 fprintf(output, " <unfinished ...>\n");
194 begin_of_line(type, proc);
195 current_column += fprintf(output, "<... %s resumed> ", function_name);
196 } else if (!current_pid) {
197 begin_of_line(type, proc);
198 current_column += fprintf(output, "<... %s resumed> ", function_name);
199 }
200
201 if (!func) {
202 current_column += fprintf(output, ") ");
203 tabto(opt_a);
204 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200205 display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
Juan Cespedes3268a161997-08-25 16:45:22 +0200206 fprintf(output, "\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100207 } else {
208 int i;
209 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200210 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100211 current_column += fprintf(output, ", ");
212 }
213 if (func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200214 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100215 }
216 current_column += fprintf(output, ") ");
217 tabto(opt_a);
218 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200219 if (func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100220 fprintf(output, "<void>");
221 } else {
222 display_arg(type, proc, -1, func->return_type);
223 }
224 fprintf(output, "\n");
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200225 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100226 current_pid=0;
227 current_column=0;
Juan Cespedesc40e64a1997-10-26 20:34:00 +0100228}