mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	 24a6034acc
			
		
	
	
		24a6034acc
		
	
	
	
	
		
			
			To reduce the reliance of trace samples (trace*_user) on bpf_load, move read_trace_pipe to trace_helpers. By moving this bpf_loader helper elsewhere, trace functions can be easily migrated to libbbpf. Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/20200321100424.1593964-2-danieltimlee@gmail.com
		
			
				
	
	
		
			112 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <assert.h>
 | |
| #include <errno.h>
 | |
| #include <fcntl.h>
 | |
| #include <poll.h>
 | |
| #include <unistd.h>
 | |
| #include <linux/perf_event.h>
 | |
| #include <sys/mman.h>
 | |
| #include "trace_helpers.h"
 | |
| 
 | |
| #define DEBUGFS "/sys/kernel/debug/tracing/"
 | |
| 
 | |
| #define MAX_SYMS 300000
 | |
| static struct ksym syms[MAX_SYMS];
 | |
| static int sym_cnt;
 | |
| 
 | |
| static int ksym_cmp(const void *p1, const void *p2)
 | |
| {
 | |
| 	return ((struct ksym *)p1)->addr - ((struct ksym *)p2)->addr;
 | |
| }
 | |
| 
 | |
| int load_kallsyms(void)
 | |
| {
 | |
| 	FILE *f = fopen("/proc/kallsyms", "r");
 | |
| 	char func[256], buf[256];
 | |
| 	char symbol;
 | |
| 	void *addr;
 | |
| 	int i = 0;
 | |
| 
 | |
| 	if (!f)
 | |
| 		return -ENOENT;
 | |
| 
 | |
| 	while (fgets(buf, sizeof(buf), f)) {
 | |
| 		if (sscanf(buf, "%p %c %s", &addr, &symbol, func) != 3)
 | |
| 			break;
 | |
| 		if (!addr)
 | |
| 			continue;
 | |
| 		syms[i].addr = (long) addr;
 | |
| 		syms[i].name = strdup(func);
 | |
| 		i++;
 | |
| 	}
 | |
| 	fclose(f);
 | |
| 	sym_cnt = i;
 | |
| 	qsort(syms, sym_cnt, sizeof(struct ksym), ksym_cmp);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| struct ksym *ksym_search(long key)
 | |
| {
 | |
| 	int start = 0, end = sym_cnt;
 | |
| 	int result;
 | |
| 
 | |
| 	/* kallsyms not loaded. return NULL */
 | |
| 	if (sym_cnt <= 0)
 | |
| 		return NULL;
 | |
| 
 | |
| 	while (start < end) {
 | |
| 		size_t mid = start + (end - start) / 2;
 | |
| 
 | |
| 		result = key - syms[mid].addr;
 | |
| 		if (result < 0)
 | |
| 			end = mid;
 | |
| 		else if (result > 0)
 | |
| 			start = mid + 1;
 | |
| 		else
 | |
| 			return &syms[mid];
 | |
| 	}
 | |
| 
 | |
| 	if (start >= 1 && syms[start - 1].addr < key &&
 | |
| 	    key < syms[start].addr)
 | |
| 		/* valid ksym */
 | |
| 		return &syms[start - 1];
 | |
| 
 | |
| 	/* out of range. return _stext */
 | |
| 	return &syms[0];
 | |
| }
 | |
| 
 | |
| long ksym_get_addr(const char *name)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < sym_cnt; i++) {
 | |
| 		if (strcmp(syms[i].name, name) == 0)
 | |
| 			return syms[i].addr;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void read_trace_pipe(void)
 | |
| {
 | |
| 	int trace_fd;
 | |
| 
 | |
| 	trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0);
 | |
| 	if (trace_fd < 0)
 | |
| 		return;
 | |
| 
 | |
| 	while (1) {
 | |
| 		static char buf[4096];
 | |
| 		ssize_t sz;
 | |
| 
 | |
| 		sz = read(trace_fd, buf, sizeof(buf) - 1);
 | |
| 		if (sz > 0) {
 | |
| 			buf[sz] = 0;
 | |
| 			puts(buf);
 | |
| 		}
 | |
| 	}
 | |
| }
 |