output.c revision 3f0b62e9df224dbdc20a8fa91afe8a0c81a230e9
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_column = 0;
22
23static void output_indent(struct process * proc)
24{
25	current_column += fprintf(output, "%*s", opt_n * proc->callstack_depth, "");
26}
27
28static void begin_of_line(enum tof type, struct process * proc)
29{
30	current_column = 0;
31	if (!proc) {
32		return;
33	}
34	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);
38	}
39	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	}
63	if (opt_t) {
64		struct timeval tv;
65		struct timezone tz;
66
67		gettimeofday(&tv, &tz);
68		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) {
72			struct tm * tmp = localtime(&tv.tv_sec);
73			current_column += fprintf(output, "%02d:%02d:%02d.%06d ",
74				tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec);
75		} else {
76			struct tm * tmp = localtime(&tv.tv_sec);
77			current_column += fprintf(output, "%02d:%02d:%02d ",
78				tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
79		}
80	}
81	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	}
90	if (opt_n > 0) {
91		output_indent(proc);
92	}
93}
94
95static struct function * name2func(char * name)
96{
97	struct function * tmp;
98	const char * str1, * str2;
99
100	tmp = list_of_functions;
101	while(tmp) {
102#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
111			return tmp;
112		}
113		tmp = tmp->next;
114	}
115	return NULL;
116}
117
118void output_line(struct process * proc, char *fmt, ...)
119{
120	va_list args;
121
122	if (current_pid) {
123		fprintf(output, " <unfinished ...>\n");
124	}
125	current_pid=0;
126	if (!fmt) {
127		return;
128	}
129	begin_of_line(LT_TOF_NONE, proc);
130
131	va_start(args, fmt);
132	vfprintf(output, fmt, args);
133	fprintf(output, "\n");
134	va_end(args);
135	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) {
150		fprintf(output, " <unfinished ...>\n");
151		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);
157#if HAVE_LIBIBERTY
158	current_column += fprintf(output, "%s(", opt_C ? my_demangle(function_name): function_name);
159#else
160	current_column += fprintf(output, "%s(", function_name);
161#endif
162
163	func = name2func(function_name);
164	if (!func) {
165		int i;
166		for(i=0; i<4; i++) {
167			current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN);
168			current_column += fprintf(output, ", ");
169		}
170		current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN);
171		return;
172	} else {
173		int i;
174		for(i=0; i< func->num_params - func->params_right - 1; i++) {
175			current_column += display_arg(type, proc, i, func->arg_types[i]);
176			current_column += fprintf(output, ", ");
177		}
178		if (func->num_params>func->params_right) {
179			current_column += display_arg(type, proc, i, func->arg_types[i]);
180			if (func->params_right) {
181				current_column += fprintf(output, ", ");
182			}
183		}
184	}
185}
186
187void output_right(enum tof type, struct process * proc, char * function_name)
188{
189	struct function * func = name2func(function_name);
190
191	if (current_pid && current_pid!=proc->pid) {
192		fprintf(output, " <unfinished ...>\n");
193	}
194	if (current_pid != proc->pid) {
195		begin_of_line(type, proc);
196#if HAVE_LIBIBERTY
197		current_column += fprintf(output, "<... %s resumed> ", opt_C ? my_demangle(function_name) : function_name);
198#else
199		current_column += fprintf(output, "<... %s resumed> ", function_name);
200#endif
201	}
202
203	if (!func) {
204		current_column += fprintf(output, ") ");
205		tabto(opt_a);
206		fprintf(output, "= ");
207		display_arg(type, proc, -1, ARGTYPE_UNKNOWN);
208		fprintf(output, "\n");
209	} else {
210		int i;
211		for(i=func->num_params-func->params_right; i<func->num_params-1; i++) {
212			current_column += display_arg(type, proc, i, func->arg_types[i]);
213			current_column += fprintf(output, ", ");
214		}
215		if (func->params_right) {
216			current_column += display_arg(type, proc, i, func->arg_types[i]);
217		}
218		current_column += fprintf(output, ") ");
219			tabto(opt_a);
220			fprintf(output, "= ");
221		if (func->return_type == ARGTYPE_VOID) {
222			fprintf(output, "<void>");
223		} else {
224			display_arg(type, proc, -1, func->return_type);
225		}
226		fprintf(output, "\n");
227	}
228	current_pid=0;
229	current_column=0;
230}
231