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