blob: da67298f39d6be0a8091d16f7d1361c42193b3b7 [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 +020022
Juan Cespedes3f0b62e2001-07-09 01:02:52 +020023static void output_indent(struct process * proc)
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020024{
Juan Cespedes3f0b62e2001-07-09 01:02:52 +020025 current_column += fprintf(output, "%*s", opt_n * proc->callstack_depth, "");
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020026}
Juan Cespedes5e4455b1997-08-24 01:48:26 +020027
Juan Cespedes5e01f651998-03-08 22:31:44 +010028static void begin_of_line(enum tof type, struct process * proc)
Juan Cespedes5e4455b1997-08-24 01:48:26 +020029{
Juan Cespedes5e01f651998-03-08 22:31:44 +010030 current_column = 0;
31 if (!proc) {
32 return;
Juan Cespedes5e4455b1997-08-24 01:48:26 +020033 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010034 if ((output!=stderr) && (opt_p || opt_f)) {
35 current_column += fprintf(output, "%u ", proc->pid);
36 } else if (list_of_processes->next) {
37 current_column += fprintf(output, "[pid %u] ", proc->pid);
Juan Cespedes5e01f651998-03-08 22:31:44 +010038 }
Juan Cespedesf666d191998-09-20 23:04:34 +020039 if (opt_r) {
40 struct timeval tv;
41 struct timezone tz;
42 static struct timeval old_tv={0,0};
43 struct timeval diff;
44
45 gettimeofday(&tv, &tz);
46
47 if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
48 old_tv.tv_sec=tv.tv_sec;
49 old_tv.tv_usec=tv.tv_usec;
50 }
51 diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
52 if (tv.tv_usec >= old_tv.tv_usec) {
53 diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
54 } else {
55 diff.tv_sec++;
56 diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
57 }
58 old_tv.tv_sec = tv.tv_sec;
59 old_tv.tv_usec = tv.tv_usec;
60 current_column += fprintf(output, "%3lu.%06d ",
61 diff.tv_sec, (int)diff.tv_usec);
62 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020063 if (opt_t) {
64 struct timeval tv;
65 struct timezone tz;
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020066
67 gettimeofday(&tv, &tz);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020068 if (opt_t>2) {
69 current_column += fprintf(output, "%lu.%06d ",
70 tv.tv_sec, (int)tv.tv_usec);
71 } else if (opt_t>1) {
Juan Cespedesf666d191998-09-20 23:04:34 +020072 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020073 current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
74 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
75 } else {
Juan Cespedesf666d191998-09-20 23:04:34 +020076 struct tm * tmp = localtime(&tv.tv_sec);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020077 current_column += fprintf(output, "%02d:%02d:%02d ",
78 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
79 }
80 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010081 if (opt_i) {
82 if (type==LT_TOF_FUNCTION) {
83 current_column += fprintf(output, "[%08x] ",
84 (unsigned)proc->return_addr);
85 } else {
86 current_column += fprintf(output, "[%08x] ",
87 (unsigned)proc->instruction_pointer);
88 }
89 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020090 if (opt_n > 0) {
Juan Cespedes3f0b62e2001-07-09 01:02:52 +020091 output_indent(proc);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020092 }
Juan Cespedes5e4455b1997-08-24 01:48:26 +020093}
94
Juan Cespedes5e01f651998-03-08 22:31:44 +010095static struct function * name2func(char * name)
96{
97 struct function * tmp;
Juan Cespedes1b9cfd61999-08-30 19:34:50 +020098 const char * str1, * str2;
Juan Cespedes5e01f651998-03-08 22:31:44 +010099
100 tmp = list_of_functions;
101 while(tmp) {
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200102#if HAVE_LIBIBERTY
103 str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
104 str2 = opt_C ? my_demangle(name) : name;
105#else
106 str1 = tmp->name;
107 str2 = name;
108#endif
109 if (!strcmp(str1, str2)) {
110
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 return tmp;
112 }
113 tmp = tmp->next;
114 }
115 return NULL;
116}
117
118void output_line(struct process * proc, char *fmt, ...)
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200119{
120 va_list args;
121
Juan Cespedes5e01f651998-03-08 22:31:44 +0100122 if (current_pid) {
123 fprintf(output, " <unfinished ...>\n");
124 }
Juan Cespedes28f60191998-04-12 00:04:39 +0200125 current_pid=0;
126 if (!fmt) {
127 return;
128 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100129 begin_of_line(LT_TOF_NONE, proc);
130
Juan Cespedes21c63a12001-07-07 20:56:56 +0200131 va_start(args, fmt);
132 vfprintf(output, fmt, args);
133 fprintf(output, "\n");
134 va_end(args);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100135 current_column=0;
136}
137
138static void tabto(int col)
139{
140 if (current_column < col) {
141 fprintf(output, "%*s", col-current_column, "");
142 }
143}
144
145void output_left(enum tof type, struct process * proc, char * function_name)
146{
147 struct function * func;
148
149 if (current_pid) {
Juan Cespedes21c63a12001-07-07 20:56:56 +0200150 fprintf(output, " <unfinished ...>\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100151 current_pid=0;
152 current_column=0;
153 }
154 current_pid=proc->pid;
155 proc->type_being_displayed = type;
156 begin_of_line(type, proc);
Juan Cespedesac3db291998-04-25 14:31:58 +0200157#if HAVE_LIBIBERTY
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200158 current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200159#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100160 current_column += fprintf(output, "%s(", function_name);
Juan Cespedesac3db291998-04-25 14:31:58 +0200161#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100162
163 func = name2func(function_name);
164 if (!func) {
165 int i;
166 for(i=0; i<4; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200167 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100168 current_column += fprintf(output, ", ");
169 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200170 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100171 return;
172 } else {
173 int i;
174 for(i=0; i< func->num_params - func->params_right - 1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200175 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100176 current_column += fprintf(output, ", ");
177 }
178 if (func->num_params>func->params_right) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200179 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100180 if (func->params_right) {
181 current_column += fprintf(output, ", ");
182 }
183 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100184 }
185}
186
187void output_right(enum tof type, struct process * proc, char * function_name)
188{
189 struct function * func = name2func(function_name);
190
Juan Cespedes5e01f651998-03-08 22:31:44 +0100191 if (current_pid && current_pid!=proc->pid) {
192 fprintf(output, " <unfinished ...>\n");
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200193 }
194 if (current_pid != proc->pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100195 begin_of_line(type, proc);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200196#if HAVE_LIBIBERTY
197 current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
198#else
Juan Cespedes5e01f651998-03-08 22:31:44 +0100199 current_column += fprintf(output, "<... %s resumed> ", function_name);
Juan Cespedes1b9cfd61999-08-30 19:34:50 +0200200#endif
Juan Cespedes5e01f651998-03-08 22:31:44 +0100201 }
202
203 if (!func) {
204 current_column += fprintf(output, ") ");
205 tabto(opt_a);
206 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200207 display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
Juan Cespedes3268a161997-08-25 16:45:22 +0200208 fprintf(output, "\n");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100209 } else {
210 int i;
211 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200212 current_column += display_arg(type, proc, i, func->arg_types[i]);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100213 current_column += fprintf(output, ", ");
214 }
215 if (func->params_right) {
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 }
218 current_column += fprintf(output, ") ");
219 tabto(opt_a);
220 fprintf(output, "= ");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +0200221 if (func->return_type == ARGTYPE_VOID) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100222 fprintf(output, "<void>");
223 } else {
224 display_arg(type, proc, -1, func->return_type);
225 }
226 fprintf(output, "\n");
Juan Cespedes5e4455b1997-08-24 01:48:26 +0200227 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100228 current_pid=0;
229 current_column=0;
Juan Cespedesc40e64a1997-10-26 20:34:00 +0100230}