char *replace_line(char *line, char *elem, char *new_elem, int n) { char *new_line; char *beg; int i; i = n - 1; if ((new_line = calloc(sizeof(char) * (my_strlen(line) + my_strlen(new_elem)) , (my_strlen(line) + my_strlen(new_elem)))) == NULL) return (NULL); while (line[++i]) if (!(strncmp(&line[i], elem, my_strlen(elem)))) { if (line[i + my_strlen(elem)] == '\0') return (new_line = short_line(new_line, line, new_elem, i)); else { if ((beg = begin_of_line(line, i)) == NULL) return (NULL); sprintf(new_line, "%s%s%s", beg, new_elem, &line[my_strlen(beg) + my_strlen(elem)]); free_bl(line, beg); return (new_line); } } free(new_line); return (NULL); }
void output_line(struct process *proc, const char *fmt, ...) { if (options.summary) return; if (current_proc != NULL) { if (current_proc->callstack[current_depth].return_addr) fprintf(options.output, " <unfinished ...>\n"); else fprintf(options.output, " <no return ...>\n"); } current_proc = NULL; if (fmt == NULL) return; begin_of_line(proc, 0, 0); va_list args; va_start(args, fmt); vfprintf(options.output, fmt, args); fprintf(options.output, "\n"); va_end(args); current_column = 0; }
char *short_line(char *new_line, char *line, char *new_elem, int i) { char *beg; beg = begin_of_line(line, i); sprintf(new_line, "%s%s", beg, new_elem); free(beg); free(line); return (new_line); }
void output_right(enum tof type, struct process *proc, struct library_symbol *libsym, struct timedelta *spent) { assert(! options.summary); struct prototype *func = lookup_symbol_prototype(proc, libsym); if (func == NULL) return; if (current_proc != NULL && (current_proc != proc || current_depth != proc->callstack_depth)) { fprintf(options.output, " <unfinished ...>\n"); current_proc = NULL; } if (current_proc != proc) { begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1); #ifdef USE_DEMANGLE current_column += fprintf(options.output, "<... %s resumed> ", options.demangle ? my_demangle(libsym->name) : libsym->name); #else current_column += fprintf(options.output, "<... %s resumed> ", libsym->name); #endif } struct callstack_element *stel = &proc->callstack[proc->callstack_depth - 1]; struct fetch_context *context = stel->fetch_context; /* Fetch & enter into dictionary the retval first, so that * other values can use it in expressions. */ struct value retval; bool own_retval = false; if (context != NULL) { value_init(&retval, proc, NULL, func->return_info, 0); own_retval = true; if (fetch_retval(context, type, proc, func->return_info, &retval) < 0) value_set_type(&retval, NULL, 0); else if (stel->arguments != NULL && val_dict_push_named(stel->arguments, &retval, "retval", 0) == 0) own_retval = false; } if (stel->arguments != NULL) output_params(stel->arguments, stel->out.params_left, val_dict_count(stel->arguments), &stel->out.need_delim); current_column += fprintf(options.output, ") "); tabto(options.align - 1); fprintf(options.output, "= "); if (context != NULL && retval.type != NULL) { struct format_argument_data data = { &retval, stel->arguments }; format_argument_cb(options.output, &data); } if (own_retval) value_destroy(&retval); if (opt_T) { assert(spent != NULL); fprintf(options.output, " <%lu.%06d>", (unsigned long) spent->tm.tv_sec, (int) spent->tm.tv_usec); } fprintf(options.output, "\n"); #if defined(HAVE_LIBUNWIND) if (options.bt_depth > 0 && proc->unwind_priv != NULL && proc->unwind_as != NULL) { unw_cursor_t cursor; arch_addr_t ip, function_offset; struct library *lib = NULL; int unwind_depth = options.bt_depth; char fn_name[100]; const char *lib_name; size_t distance; /* Verify that we can safely cast arch_addr_t* to * unw_word_t*. */ (void)sizeof(char[1 - 2*(sizeof(unw_word_t) != sizeof(arch_addr_t))]); unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv); while (unwind_depth) { int rc = unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip); if (rc < 0) { fprintf(options.output, " > Error: %s\n", unw_strerror(rc)); goto cont; } /* We are looking for the library with the base address * closest to the current ip. */ lib_name = "unmapped_area"; distance = (size_t) -1; lib = proc->libraries; while (lib != NULL) { /* N.B.: Assumes sizeof(size_t) == * sizeof(arch_addr_t). * Keyword: double cast. */ if ((ip >= lib->base) && ((size_t)(ip - lib->base) < distance)) { distance = ip - lib->base; lib_name = lib->pathname; } lib = lib->next; } rc = unw_get_proc_name(&cursor, fn_name, sizeof(fn_name), (unw_word_t *) &function_offset); if (rc == 0 || rc == -UNW_ENOMEM) fprintf(options.output, " > %s(%s+%p) [%p]\n", lib_name, fn_name, function_offset, ip); else fprintf(options.output, " > %s(??\?) [%p]\n", lib_name, ip); cont: if (unw_step(&cursor) <= 0) break; unwind_depth--; } fprintf(options.output, "\n"); } #endif /* defined(HAVE_LIBUNWIND) */ #if defined(HAVE_LIBDW) if (options.bt_depth > 0 && proc->leader->dwfl != NULL) { int frames = options.bt_depth; if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid, frame_callback, &frames) < 0) { // Only print an error if we couldn't show anything. // Otherwise just show there might be more... if (frames == options.bt_depth) fprintf(stderr, "dwfl_getthread_frames tid %d: %s\n", proc->pid, dwfl_errmsg(-1)); else fprintf(options.output, " > [...]\n"); } fprintf(options.output, "\n"); } #endif /* defined(HAVE_LIBDW) */ current_proc = NULL; current_column = 0; }
void output_left(enum tof type, struct process *proc, struct library_symbol *libsym) { assert(! options.summary); if (current_proc) { fprintf(options.output, " <unfinished ...>\n"); current_column = 0; } current_proc = proc; current_depth = proc->callstack_depth; begin_of_line(proc, type == LT_TOF_FUNCTION, 1); if (!options.hide_caller && libsym->lib != NULL && libsym->plt_type != LS_TOPLT_NONE) /* We don't terribly mind failing this. */ account_output(¤t_column, fprintf(options.output, "%s->", libsym->lib->soname)); const char *name = libsym->name; #ifdef USE_DEMANGLE if (options.demangle) name = my_demangle(libsym->name); #endif if (account_output(¤t_column, fprintf(options.output, "%s", name)) < 0) return; if (libsym->lib != NULL && libsym->lib->type != LT_LIBTYPE_MAIN && libsym->plt_type == LS_TOPLT_NONE && account_output(¤t_column, fprintf(options.output, "@%s", libsym->lib->soname)) < 0) /* We do mind failing this though. */ return; account_output(¤t_column, fprintf(options.output, "(")); struct prototype *func = lookup_symbol_prototype(proc, libsym); if (func == NULL) { fail: account_output(¤t_column, fprintf(options.output, "???")); return; } struct fetch_context *context = fetch_arg_init(type, proc, func->return_info); if (context == NULL) goto fail; struct value_dict *arguments = malloc(sizeof(*arguments)); if (arguments == NULL) { fetch_arg_done(context); goto fail; } val_dict_init(arguments); ssize_t params_left = -1; int need_delim = 0; if (fetch_params(type, proc, context, arguments, func, ¶ms_left) < 0 || output_params(arguments, 0, params_left, &need_delim) < 0) { val_dict_destroy(arguments); fetch_arg_done(context); arguments = NULL; context = NULL; } struct callstack_element *stel = &proc->callstack[proc->callstack_depth - 1]; stel->fetch_context = context; stel->arguments = arguments; stel->out.params_left = params_left; stel->out.need_delim = need_delim; }