1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <linux/kernel.h>
- #include "util/util.h"
- #include "util/debug.h"
- static int addr2line(const char *dso_name, unsigned long addr,
- char **file, unsigned int *line_nr)
- {
- FILE *fp;
- char cmd[PATH_MAX];
- char *filename = NULL;
- size_t len;
- char *sep;
- int ret = 0;
- scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
- dso_name, addr);
- fp = popen(cmd, "r");
- if (fp == NULL) {
- pr_warning("popen failed for %s\n", dso_name);
- return 0;
- }
- if (getline(&filename, &len, fp) < 0 || !len) {
- pr_warning("addr2line has no output for %s\n", dso_name);
- goto out;
- }
- sep = strchr(filename, '\n');
- if (sep)
- *sep = '\0';
- if (!strcmp(filename, "??:0")) {
- pr_debug("no debugging info in %s\n", dso_name);
- free(filename);
- goto out;
- }
- sep = strchr(filename, ':');
- if (sep) {
- *sep++ = '\0';
- *file = filename;
- *line_nr = strtoul(sep, NULL, 0);
- ret = 1;
- }
- out:
- pclose(fp);
- return ret;
- }
- char *get_srcline(const char *dso_name, unsigned long addr)
- {
- char *file;
- unsigned line;
- char *srcline;
- size_t size;
- if (!addr2line(dso_name, addr, &file, &line))
- return SRCLINE_UNKNOWN;
- /* just calculate actual length */
- size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
- srcline = malloc(size);
- if (srcline)
- snprintf(srcline, size, "%s:%u", file, line);
- else
- srcline = SRCLINE_UNKNOWN;
- free(file);
- return srcline;
- }
- void free_srcline(char *srcline)
- {
- if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
- free(srcline);
- }
|