1*f048d548SNamhyung Kim #include <stdio.h> 2*f048d548SNamhyung Kim #include <stdlib.h> 3*f048d548SNamhyung Kim #include <string.h> 4*f048d548SNamhyung Kim 5*f048d548SNamhyung Kim #include <linux/kernel.h> 6*f048d548SNamhyung Kim 7*f048d548SNamhyung Kim #include "util/util.h" 8*f048d548SNamhyung Kim #include "util/debug.h" 9*f048d548SNamhyung Kim 10*f048d548SNamhyung Kim static int addr2line(const char *dso_name, unsigned long addr, 11*f048d548SNamhyung Kim char **file, unsigned int *line_nr) 12*f048d548SNamhyung Kim { 13*f048d548SNamhyung Kim FILE *fp; 14*f048d548SNamhyung Kim char cmd[PATH_MAX]; 15*f048d548SNamhyung Kim char *filename = NULL; 16*f048d548SNamhyung Kim size_t len; 17*f048d548SNamhyung Kim char *sep; 18*f048d548SNamhyung Kim int ret = 0; 19*f048d548SNamhyung Kim 20*f048d548SNamhyung Kim scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, 21*f048d548SNamhyung Kim dso_name, addr); 22*f048d548SNamhyung Kim 23*f048d548SNamhyung Kim fp = popen(cmd, "r"); 24*f048d548SNamhyung Kim if (fp == NULL) { 25*f048d548SNamhyung Kim pr_warning("popen failed for %s\n", dso_name); 26*f048d548SNamhyung Kim return 0; 27*f048d548SNamhyung Kim } 28*f048d548SNamhyung Kim 29*f048d548SNamhyung Kim if (getline(&filename, &len, fp) < 0 || !len) { 30*f048d548SNamhyung Kim pr_warning("addr2line has no output for %s\n", dso_name); 31*f048d548SNamhyung Kim goto out; 32*f048d548SNamhyung Kim } 33*f048d548SNamhyung Kim 34*f048d548SNamhyung Kim sep = strchr(filename, '\n'); 35*f048d548SNamhyung Kim if (sep) 36*f048d548SNamhyung Kim *sep = '\0'; 37*f048d548SNamhyung Kim 38*f048d548SNamhyung Kim if (!strcmp(filename, "??:0")) { 39*f048d548SNamhyung Kim pr_debug("no debugging info in %s\n", dso_name); 40*f048d548SNamhyung Kim free(filename); 41*f048d548SNamhyung Kim goto out; 42*f048d548SNamhyung Kim } 43*f048d548SNamhyung Kim 44*f048d548SNamhyung Kim sep = strchr(filename, ':'); 45*f048d548SNamhyung Kim if (sep) { 46*f048d548SNamhyung Kim *sep++ = '\0'; 47*f048d548SNamhyung Kim *file = filename; 48*f048d548SNamhyung Kim *line_nr = strtoul(sep, NULL, 0); 49*f048d548SNamhyung Kim ret = 1; 50*f048d548SNamhyung Kim } 51*f048d548SNamhyung Kim out: 52*f048d548SNamhyung Kim pclose(fp); 53*f048d548SNamhyung Kim return ret; 54*f048d548SNamhyung Kim } 55*f048d548SNamhyung Kim 56*f048d548SNamhyung Kim char *get_srcline(const char *dso_name, unsigned long addr) 57*f048d548SNamhyung Kim { 58*f048d548SNamhyung Kim char *file; 59*f048d548SNamhyung Kim unsigned line; 60*f048d548SNamhyung Kim char *srcline; 61*f048d548SNamhyung Kim size_t size; 62*f048d548SNamhyung Kim 63*f048d548SNamhyung Kim if (!addr2line(dso_name, addr, &file, &line)) 64*f048d548SNamhyung Kim return SRCLINE_UNKNOWN; 65*f048d548SNamhyung Kim 66*f048d548SNamhyung Kim /* just calculate actual length */ 67*f048d548SNamhyung Kim size = snprintf(NULL, 0, "%s:%u", file, line) + 1; 68*f048d548SNamhyung Kim 69*f048d548SNamhyung Kim srcline = malloc(size); 70*f048d548SNamhyung Kim if (srcline) 71*f048d548SNamhyung Kim snprintf(srcline, size, "%s:%u", file, line); 72*f048d548SNamhyung Kim else 73*f048d548SNamhyung Kim srcline = SRCLINE_UNKNOWN; 74*f048d548SNamhyung Kim 75*f048d548SNamhyung Kim free(file); 76*f048d548SNamhyung Kim return srcline; 77*f048d548SNamhyung Kim } 78*f048d548SNamhyung Kim 79*f048d548SNamhyung Kim void free_srcline(char *srcline) 80*f048d548SNamhyung Kim { 81*f048d548SNamhyung Kim if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) 82*f048d548SNamhyung Kim free(srcline); 83*f048d548SNamhyung Kim } 84