Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <stdio.h>
  3#include <stdlib.h>
  4#include <string.h>
  5#include <assert.h>
  6#include <errno.h>
  7#include <fcntl.h>
  8#include <poll.h>
  9#include <unistd.h>
 10#include <linux/perf_event.h>
 11#include <sys/mman.h>
 12#include "trace_helpers.h"
 13
 14#define DEBUGFS "/sys/kernel/debug/tracing/"
 15
 16#define MAX_SYMS 300000
 17static struct ksym syms[MAX_SYMS];
 18static int sym_cnt;
 19
 20static int ksym_cmp(const void *p1, const void *p2)
 21{
 22	return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr;
 23}
 24
 25int load_kallsyms(void)
 26{
 27	FILE *f = fopen("/proc/kallsyms", "r");
 28	char func[256], buf[256];
 29	char symbol;
 30	void *addr;
 31	int i = 0;
 32
 33	if (!f)
 34		return -ENOENT;
 35
 36	while (fgets(buf, sizeof(buf), f)) {
 37		if (sscanf(buf, "%p %c %s", &addr, &symbol, func) != 3)
 38			break;
 39		if (!addr)
 40			continue;
 41		syms[i].addr = (long) addr;
 42		syms[i].name = strdup(func);
 43		i++;
 44	}
 45	fclose(f);
 46	sym_cnt = i;
 47	qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp);
 48	return 0;
 49}
 50
 51struct ksym *ksym_search(long key)
 52{
 53	int start = 0, end = sym_cnt;
 54	int result;
 55
 56	/* kallsyms not loaded. return NULL */
 57	if (sym_cnt <= 0)
 58		return NULL;
 59
 60	while (start < end) {
 61		size_t mid = start + (end - start) / 2;
 62
 63		result = key - syms[mid].addr;
 64		if (result < 0)
 65			end = mid;
 66		else if (result > 0)
 67			start = mid + 1;
 68		else
 69			return &syms[mid];
 70	}
 71
 72	if (start >= 1 && syms[start - 1].addr < key &&
 73	    key < syms[start].addr)
 74		/* valid ksym */
 75		return &syms[start - 1];
 76
 77	/* out of range. return _stext */
 78	return &syms[0];
 79}
 80
 81long ksym_get_addr(const char *name)
 82{
 83	int i;
 84
 85	for (i = 0; i < sym_cnt; i++) {
 86		if (strcmp(syms[i].name, name) == 0)
 87			return syms[i].addr;
 88	}
 89
 90	return 0;
 91}
 92
 93/* open kallsyms and read symbol addresses on the fly. Without caching all symbols,
 94 * this is faster than load + find.
 95 */
 96int kallsyms_find(const char *sym, unsigned long long *addr)
 97{
 98	char type, name[500];
 99	unsigned long long value;
100	int err = 0;
101	FILE *f;
102
103	f = fopen("/proc/kallsyms", "r");
104	if (!f)
105		return -EINVAL;
106
107	while (fscanf(f, "%llx %c %499s%*[^\n]\n", &value, &type, name) > 0) {
108		if (strcmp(name, sym) == 0) {
109			*addr = value;
110			goto out;
111		}
112	}
113	err = -ENOENT;
114
115out:
116	fclose(f);
117	return err;
118}
119
120void read_trace_pipe(void)
121{
122	int trace_fd;
123
124	trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0);
125	if (trace_fd < 0)
126		return;
127
128	while (1) {
129		static char buf[4096];
130		ssize_t sz;
131
132		sz = read(trace_fd, buf, sizeof(buf) - 1);
133		if (sz > 0) {
134			buf[sz] = 0;
135			puts(buf);
136		}
137	}
138}