1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdbool.h>
6 #include <sys/vfs.h>
7 #include <sys/mount.h>
8 #include <linux/kernel.h>
9 
10 #include "debugfs.h"
11 
12 char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
13 
14 static const char * const debugfs_known_mountpoints[] = {
15 	"/sys/kernel/debug/",
16 	"/debug/",
17 	0,
18 };
19 
20 static bool debugfs_found;
21 
22 /* find the path to the mounted debugfs */
debugfs_find_mountpoint(void)23 const char *debugfs_find_mountpoint(void)
24 {
25 	const char * const *ptr;
26 	char type[100];
27 	FILE *fp;
28 
29 	if (debugfs_found)
30 		return (const char *)debugfs_mountpoint;
31 
32 	ptr = debugfs_known_mountpoints;
33 	while (*ptr) {
34 		if (debugfs_valid_mountpoint(*ptr) == 0) {
35 			debugfs_found = true;
36 			strcpy(debugfs_mountpoint, *ptr);
37 			return debugfs_mountpoint;
38 		}
39 		ptr++;
40 	}
41 
42 	/* give up and parse /proc/mounts */
43 	fp = fopen("/proc/mounts", "r");
44 	if (fp == NULL)
45 		return NULL;
46 
47 	while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
48 		      debugfs_mountpoint, type) == 2) {
49 		if (strcmp(type, "debugfs") == 0)
50 			break;
51 	}
52 	fclose(fp);
53 
54 	if (strcmp(type, "debugfs") != 0)
55 		return NULL;
56 
57 	debugfs_found = true;
58 
59 	return debugfs_mountpoint;
60 }
61 
62 /* verify that a mountpoint is actually a debugfs instance */
63 
debugfs_valid_mountpoint(const char * debugfs)64 int debugfs_valid_mountpoint(const char *debugfs)
65 {
66 	struct statfs st_fs;
67 
68 	if (statfs(debugfs, &st_fs) < 0)
69 		return -ENOENT;
70 	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
71 		return -ENOENT;
72 
73 	return 0;
74 }
75 
76 /* mount the debugfs somewhere if it's not mounted */
debugfs_mount(const char * mountpoint)77 char *debugfs_mount(const char *mountpoint)
78 {
79 #ifdef __APPLE__
80 	goto out;
81 #else
82 	/* see if it's already mounted */
83 	if (debugfs_find_mountpoint())
84 		goto out;
85 
86 	/* if not mounted and no argument */
87 	if (mountpoint == NULL) {
88 		/* see if environment variable set */
89 		mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
90 		/* if no environment variable, use default */
91 		if (mountpoint == NULL)
92 			mountpoint = "/sys/kernel/debug";
93 	}
94 
95 	if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
96 		return NULL;
97 
98 	/* save the mountpoint */
99 	debugfs_found = true;
100 	strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
101 #endif
102 out:
103 	return debugfs_mountpoint;
104 }
105