output.c revision e3eb9aa37086f16c0c8c2778dcd8020a39a92564
1#if HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include <stdio.h> 6#include <stdarg.h> 7#include <time.h> 8#include <sys/time.h> 9#include <unistd.h> 10 11#include "ltrace.h" 12#include "options.h" 13#include "output.h" 14 15#if HAVE_LIBIBERTY 16#include "demangle.h" 17#endif 18 19static pid_t current_pid = 0; 20static int current_column = 0; 21 22static void begin_of_line(enum tof type, struct process * proc) 23{ 24 current_column = 0; 25 if (!proc) { 26 return; 27 } 28 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); 32 } 33 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 } 57 if (opt_t) { 58 struct timeval tv; 59 struct timezone tz; 60 61 gettimeofday(&tv, &tz); 62 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) { 66 struct tm * tmp = localtime(&tv.tv_sec); 67 current_column += fprintf(output, "%02d:%02d:%02d.%06d ", 68 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (int)tv.tv_usec); 69 } else { 70 struct tm * tmp = localtime(&tv.tv_sec); 71 current_column += fprintf(output, "%02d:%02d:%02d ", 72 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 73 } 74 } 75 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 } 84} 85 86static 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, ...) 101{ 102 va_list args; 103 104 if (current_pid) { 105 fprintf(output, " <unfinished ...>\n"); 106 } 107 current_pid=0; 108 if (!fmt) { 109 return; 110 } 111 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); 117 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) { 132#if 0 /* FIXME: should I do this? */ 133 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); 147#if HAVE_LIBIBERTY 148 current_column += fprintf(output, "%s(", my_demangle(function_name)); 149#else 150 current_column += fprintf(output, "%s(", function_name); 151#endif 152 153 func = name2func(function_name); 154 if (!func) { 155 int i; 156 for(i=0; i<4; i++) { 157 current_column += display_arg(type, proc, i, ARGTYPE_UNKNOWN); 158 current_column += fprintf(output, ", "); 159 } 160 current_column += display_arg(type, proc, 4, ARGTYPE_UNKNOWN); 161 return; 162 } else { 163 int i; 164 for(i=0; i< func->num_params - func->params_right - 1; i++) { 165 current_column += display_arg(type, proc, i, func->arg_types[i]); 166 current_column += fprintf(output, ", "); 167 } 168 if (func->num_params>func->params_right) { 169 current_column += display_arg(type, proc, i, func->arg_types[i]); 170 if (func->params_right) { 171 current_column += fprintf(output, ", "); 172 } 173 } 174 if (!func->params_right && func->return_type == ARGTYPE_VOID) { 175 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 188 if (func && func->params_right==0 && func->return_type == ARGTYPE_VOID) { 189 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, "= "); 205 display_arg(type, proc, -1, ARGTYPE_UNKNOWN); 206 fprintf(output, "\n"); 207 } else { 208 int i; 209 for(i=func->num_params-func->params_right; i<func->num_params-1; i++) { 210 current_column += display_arg(type, proc, i, func->arg_types[i]); 211 current_column += fprintf(output, ", "); 212 } 213 if (func->params_right) { 214 current_column += display_arg(type, proc, i, func->arg_types[i]); 215 } 216 current_column += fprintf(output, ") "); 217 tabto(opt_a); 218 fprintf(output, "= "); 219 if (func->return_type == ARGTYPE_VOID) { 220 fprintf(output, "<void>"); 221 } else { 222 display_arg(type, proc, -1, func->return_type); 223 } 224 fprintf(output, "\n"); 225 } 226 current_pid=0; 227 current_column=0; 228} 229