output.c revision 8cc1b9d456c8f41e3a8cc0d3ec0d77eb779cb7bb
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdio.h>
6#include <stdarg.h>
7#include <string.h>
8#include <time.h>
9#include <sys/time.h>
10#include <unistd.h>
11
12#include "ltrace.h"
13#include "options.h"
14#include "output.h"
15
16#if HAVE_LIBIBERTY
17#include "demangle.h"
18#endif
19
20static pid_t current_pid = 0;
21static int current_depth = 0;
22static int current_column = 0;
23
24static void
25output_indent(struct process * proc) {
26	current_column += fprintf(output, "%*s", opt_n * proc->callstack_depth, "");
27}
28
29static void
30begin_of_line(enum tof type, struct process * proc) {
31	current_column = 0;
32	if (!proc) {
33		return;
34	}
35	if ((output!=stderr) && (opt_p || opt_f)) {
36		current_column += fprintf(output, "%u ", proc->pid);
37	} else if (list_of_processes->next) {
38		current_column += fprintf(output, "[pid %u] ", proc->pid);
39	}
40	if (opt_r) {
41		struct timeval tv;
42		struct timezone tz;
43		static struct timeval old_tv={0,0};
44		struct timeval diff;
45
46		gettimeofday(&tv, &tz);
47
48		if (old_tv.tv_sec==0 && old_tv.tv_usec==0) {
49			old_tv.tv_sec=tv.tv_sec;
50			old_tv.tv_usec=tv.tv_usec;
51		}
52		diff.tv_sec = tv.tv_sec - old_tv.tv_sec;
53		if (tv.tv_usec >= old_tv.tv_usec) {
54			diff.tv_usec = tv.tv_usec - old_tv.tv_usec;
55		} else {
56			diff.tv_sec++;
57			diff.tv_usec = 1000000 + tv.tv_usec - old_tv.tv_usec;
58		}
59		old_tv.tv_sec = tv.tv_sec;
60		old_tv.tv_usec = tv.tv_usec;
61		current_column += fprintf(output, "%3lu.%06d ",
62			diff.tv_sec, (int)diff.tv_usec);
63	}
64	if (opt_t) {
65		struct timeval tv;
66		struct timezone tz;
67
68		gettimeofday(&tv, &tz);
69		if (opt_t>2) {
70			current_column += fprintf(output, "%lu.%06d ",
71				tv.tv_sec, (int)tv.tv_usec);
72		} else if (opt_t>1) {
73			struct tm * tmp = localtime(&tv.tv_sec);
74			current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
75				tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
76		} else {
77			struct tm * tmp = localtime(&tv.tv_sec);
78			current_column += fprintf(output, "%02d:%02d:%02d ",
79				tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
80		}
81	}
82	if (opt_i) {
83		if (type==LT_TOF_FUNCTION) {
84			current_column += fprintf(output, "[%08x] ",
85				(unsigned)proc->return_addr);
86		} else {
87			current_column += fprintf(output, "[%08x] ",
88				(unsigned)proc->instruction_pointer);
89		}
90	}
91	if (opt_n > 0 && type!=LT_TOF_NONE) {
92		output_indent(proc);
93	}
94}
95
96static struct function *
97name2func(char * name) {
98	struct function * tmp;
99	const char * str1, * str2;
100
101	tmp = list_of_functions;
102	while(tmp) {
103#if HAVE_LIBIBERTY
104		str1 = opt_C ? my_demangle(tmp->name) : tmp->name;
105		str2 = opt_C ? my_demangle(name) : name;
106#else
107		str1 = tmp->name;
108		str2 = name;
109#endif
110		if (!strcmp(str1, str2)) {
111
112			return tmp;
113		}
114		tmp = tmp->next;
115	}
116	return NULL;
117}
118
119void
120output_line(struct process * proc, char *fmt, ...) {
121	va_list args;
122
123	if (current_pid) {
124		fprintf(output, " <unfinished ...>\n");
125	}
126	current_pid=0;
127	if (!fmt) {
128		return;
129	}
130	begin_of_line(LT_TOF_NONE, proc);
131
132	va_start(args, fmt);
133	vfprintf(output, fmt, args);
134	fprintf(output, "\n");
135	va_end(args);
136	current_column=0;
137}
138
139static void
140tabto(int col) {
141	if (current_column < col) {
142		fprintf(output, "%*s", col-current_column, "");
143	}
144}
145
146void
147output_left(enum tof type, struct process * proc, char * function_name) {
148	struct function * func;
149
150	if (current_pid) {
151		fprintf(output, " <unfinished ...>\n");
152		current_pid=0;
153		current_column=0;
154	}
155	current_pid = proc->pid;
156	current_depth = proc->callstack_depth;
157	proc->type_being_displayed = type;
158	begin_of_line(type, proc);
159#if HAVE_LIBIBERTY
160	current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
161#else
162	current_column += fprintf(output, "%s(", function_name);
163#endif
164
165	func = name2func(function_name);
166	if (!func) {
167		int i;
168		for(i=0; i<4; i++) {
169			current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
170			current_column += fprintf(output, ", ");
171		}
172		current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
173		return;
174	} else {
175		int i;
176		for(i=0; i< func->num_params - func->params_right - 1; i++) {
177			current_column += display_arg(type, proc, i, func->arg_types[i]);
178			current_column += fprintf(output, ", ");
179		}
180		if (func->num_params>func->params_right) {
181			current_column += display_arg(type, proc, i, func->arg_types[i]);
182			if (func->params_right) {
183				current_column += fprintf(output, ", ");
184			}
185		}
186	}
187}
188
189void
190output_right(enum tof type, struct process * proc, char * function_name) {
191	struct function * func = name2func(function_name);
192
193	if ((current_pid && current_pid!=proc->pid) ||
194			current_depth != proc->callstack_depth) {
195		fprintf(output, " <unfinished ...>\n");
196		current_pid = 0;
197	}
198	if (current_pid != proc->pid) {
199		begin_of_line(type, proc);
200#if HAVE_LIBIBERTY
201		current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
202#else
203		current_column += fprintf(output, "<... %s resumed> ", function_name);
204#endif
205	}
206
207	if (!func) {
208		current_column += fprintf(output, ") ");
209		tabto(opt_a);
210		fprintf(output, "= ");
211		display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
212		fprintf(output, "\n");
213	} else {
214		int i;
215		for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
216			current_column += display_arg(type, proc, i, func->arg_types[i]);
217			current_column += fprintf(output, ", ");
218		}
219		if (func->params_right) {
220			current_column += display_arg(type, proc, i, func->arg_types[i]);
221		}
222		current_column += fprintf(output, ") ");
223			tabto(opt_a);
224			fprintf(output, "= ");
225		if (func->return_type == ARGTYPE_VOID) {
226			fprintf(output, "<void>");
227		} else {
228			display_arg(type, proc, -1, func->return_type);
229		}
230		fprintf(output, "\n");
231	}
232	current_pid=0;
233	current_column=0;
234}
235