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