1f048d548SNamhyung Kim #include <stdio.h> 2f048d548SNamhyung Kim #include <stdlib.h> 3f048d548SNamhyung Kim #include <string.h> 4f048d548SNamhyung Kim 5f048d548SNamhyung Kim #include <linux/kernel.h> 6f048d548SNamhyung Kim 786c98cabSNamhyung Kim #include "util/dso.h" 8f048d548SNamhyung Kim #include "util/util.h" 9f048d548SNamhyung Kim #include "util/debug.h" 10f048d548SNamhyung Kim 11f048d548SNamhyung Kim static int addr2line(const char *dso_name, unsigned long addr, 12f048d548SNamhyung Kim char **file, unsigned int *line_nr) 13f048d548SNamhyung Kim { 14f048d548SNamhyung Kim FILE *fp; 15f048d548SNamhyung Kim char cmd[PATH_MAX]; 16f048d548SNamhyung Kim char *filename = NULL; 17f048d548SNamhyung Kim size_t len; 18f048d548SNamhyung Kim char *sep; 19f048d548SNamhyung Kim int ret = 0; 20f048d548SNamhyung Kim 21f048d548SNamhyung Kim scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, 22f048d548SNamhyung Kim dso_name, addr); 23f048d548SNamhyung Kim 24f048d548SNamhyung Kim fp = popen(cmd, "r"); 25f048d548SNamhyung Kim if (fp == NULL) { 26f048d548SNamhyung Kim pr_warning("popen failed for %s\n", dso_name); 27f048d548SNamhyung Kim return 0; 28f048d548SNamhyung Kim } 29f048d548SNamhyung Kim 30f048d548SNamhyung Kim if (getline(&filename, &len, fp) < 0 || !len) { 31f048d548SNamhyung Kim pr_warning("addr2line has no output for %s\n", dso_name); 32f048d548SNamhyung Kim goto out; 33f048d548SNamhyung Kim } 34f048d548SNamhyung Kim 35f048d548SNamhyung Kim sep = strchr(filename, '\n'); 36f048d548SNamhyung Kim if (sep) 37f048d548SNamhyung Kim *sep = '\0'; 38f048d548SNamhyung Kim 39f048d548SNamhyung Kim if (!strcmp(filename, "??:0")) { 40f048d548SNamhyung Kim pr_debug("no debugging info in %s\n", dso_name); 41f048d548SNamhyung Kim free(filename); 42f048d548SNamhyung Kim goto out; 43f048d548SNamhyung Kim } 44f048d548SNamhyung Kim 45f048d548SNamhyung Kim sep = strchr(filename, ':'); 46f048d548SNamhyung Kim if (sep) { 47f048d548SNamhyung Kim *sep++ = '\0'; 48f048d548SNamhyung Kim *file = filename; 49f048d548SNamhyung Kim *line_nr = strtoul(sep, NULL, 0); 50f048d548SNamhyung Kim ret = 1; 51f048d548SNamhyung Kim } 52f048d548SNamhyung Kim out: 53f048d548SNamhyung Kim pclose(fp); 54f048d548SNamhyung Kim return ret; 55f048d548SNamhyung Kim } 56f048d548SNamhyung Kim 5786c98cabSNamhyung Kim char *get_srcline(struct dso *dso, unsigned long addr) 58f048d548SNamhyung Kim { 59f048d548SNamhyung Kim char *file; 60f048d548SNamhyung Kim unsigned line; 61*2cc9d0efSNamhyung Kim char *srcline; 6286c98cabSNamhyung Kim char *dso_name = dso->long_name; 63f048d548SNamhyung Kim size_t size; 64f048d548SNamhyung Kim 65*2cc9d0efSNamhyung Kim if (!dso->has_srcline) 66*2cc9d0efSNamhyung Kim return SRCLINE_UNKNOWN; 67*2cc9d0efSNamhyung Kim 6858d91a00SNamhyung Kim if (dso_name[0] == '[') 6958d91a00SNamhyung Kim goto out; 7058d91a00SNamhyung Kim 7158d91a00SNamhyung Kim if (!strncmp(dso_name, "/tmp/perf-", 10)) 7258d91a00SNamhyung Kim goto out; 7358d91a00SNamhyung Kim 74f048d548SNamhyung Kim if (!addr2line(dso_name, addr, &file, &line)) 7558d91a00SNamhyung Kim goto out; 76f048d548SNamhyung Kim 77f048d548SNamhyung Kim /* just calculate actual length */ 78f048d548SNamhyung Kim size = snprintf(NULL, 0, "%s:%u", file, line) + 1; 79f048d548SNamhyung Kim 80f048d548SNamhyung Kim srcline = malloc(size); 81f048d548SNamhyung Kim if (srcline) 82f048d548SNamhyung Kim snprintf(srcline, size, "%s:%u", file, line); 83f048d548SNamhyung Kim else 84f048d548SNamhyung Kim srcline = SRCLINE_UNKNOWN; 85f048d548SNamhyung Kim 86f048d548SNamhyung Kim free(file); 87f048d548SNamhyung Kim return srcline; 88*2cc9d0efSNamhyung Kim 89*2cc9d0efSNamhyung Kim out: 90*2cc9d0efSNamhyung Kim dso->has_srcline = 0; 91*2cc9d0efSNamhyung Kim return SRCLINE_UNKNOWN; 92f048d548SNamhyung Kim } 93f048d548SNamhyung Kim 94f048d548SNamhyung Kim void free_srcline(char *srcline) 95f048d548SNamhyung Kim { 96f048d548SNamhyung Kim if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) 97f048d548SNamhyung Kim free(srcline); 98f048d548SNamhyung Kim } 99