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