18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#ifndef _GNU_SOURCE 38c2ecf20Sopenharmony_ci# define _GNU_SOURCE 48c2ecf20Sopenharmony_ci#endif 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <stdio.h> 78c2ecf20Sopenharmony_ci#include <stdlib.h> 88c2ecf20Sopenharmony_ci#include <string.h> 98c2ecf20Sopenharmony_ci#include <linux/string.h> 108c2ecf20Sopenharmony_ci#include <errno.h> 118c2ecf20Sopenharmony_ci#include <unistd.h> 128c2ecf20Sopenharmony_ci#include "fs.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "tracing_path.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic char tracing_mnt[PATH_MAX] = "/sys/kernel/debug"; 178c2ecf20Sopenharmony_cistatic char tracing_path[PATH_MAX] = "/sys/kernel/debug/tracing"; 188c2ecf20Sopenharmony_cistatic char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events"; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void __tracing_path_set(const char *tracing, const char *mountpoint) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci snprintf(tracing_mnt, sizeof(tracing_mnt), "%s", mountpoint); 238c2ecf20Sopenharmony_ci snprintf(tracing_path, sizeof(tracing_path), "%s/%s", 248c2ecf20Sopenharmony_ci mountpoint, tracing); 258c2ecf20Sopenharmony_ci snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s", 268c2ecf20Sopenharmony_ci mountpoint, tracing, "events"); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic const char *tracing_path_tracefs_mount(void) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci const char *mnt; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci mnt = tracefs__mount(); 348c2ecf20Sopenharmony_ci if (!mnt) 358c2ecf20Sopenharmony_ci return NULL; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci __tracing_path_set("", mnt); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci return tracing_path; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic const char *tracing_path_debugfs_mount(void) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci const char *mnt; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci mnt = debugfs__mount(); 478c2ecf20Sopenharmony_ci if (!mnt) 488c2ecf20Sopenharmony_ci return NULL; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci __tracing_path_set("tracing/", mnt); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return tracing_path; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ciconst char *tracing_path_mount(void) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci const char *mnt; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci mnt = tracing_path_tracefs_mount(); 608c2ecf20Sopenharmony_ci if (mnt) 618c2ecf20Sopenharmony_ci return mnt; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci mnt = tracing_path_debugfs_mount(); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return mnt; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_civoid tracing_path_set(const char *mntpt) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci __tracing_path_set("tracing/", mntpt); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cichar *get_tracing_file(const char *name) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci char *file; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (asprintf(&file, "%s/%s", tracing_path_mount(), name) < 0) 788c2ecf20Sopenharmony_ci return NULL; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return file; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_civoid put_tracing_file(char *file) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci free(file); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cichar *get_events_file(const char *name) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci char *file; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (asprintf(&file, "%s/events/%s", tracing_path_mount(), name) < 0) 938c2ecf20Sopenharmony_ci return NULL; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return file; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_civoid put_events_file(char *file) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci free(file); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciDIR *tracing_events__opendir(void) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci DIR *dir = NULL; 1068c2ecf20Sopenharmony_ci char *path = get_tracing_file("events"); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (path) { 1098c2ecf20Sopenharmony_ci dir = opendir(path); 1108c2ecf20Sopenharmony_ci put_events_file(path); 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci return dir; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciint tracing_path__strerror_open_tp(int err, char *buf, size_t size, 1178c2ecf20Sopenharmony_ci const char *sys, const char *name) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci char sbuf[128]; 1208c2ecf20Sopenharmony_ci char filename[PATH_MAX]; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*"); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci switch (err) { 1258c2ecf20Sopenharmony_ci case ENOENT: 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * We will get here if we can't find the tracepoint, but one of 1288c2ecf20Sopenharmony_ci * debugfs or tracefs is configured, which means you probably 1298c2ecf20Sopenharmony_ci * want some tracepoint which wasn't compiled in your kernel. 1308c2ecf20Sopenharmony_ci * - jirka 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci if (debugfs__configured() || tracefs__configured()) { 1338c2ecf20Sopenharmony_ci /* sdt markers */ 1348c2ecf20Sopenharmony_ci if (!strncmp(filename, "sdt_", 4)) { 1358c2ecf20Sopenharmony_ci snprintf(buf, size, 1368c2ecf20Sopenharmony_ci "Error:\tFile %s/%s not found.\n" 1378c2ecf20Sopenharmony_ci "Hint:\tSDT event cannot be directly recorded on.\n" 1388c2ecf20Sopenharmony_ci "\tPlease first use 'perf probe %s:%s' before recording it.\n", 1398c2ecf20Sopenharmony_ci tracing_events_path, filename, sys, name); 1408c2ecf20Sopenharmony_ci } else { 1418c2ecf20Sopenharmony_ci snprintf(buf, size, 1428c2ecf20Sopenharmony_ci "Error:\tFile %s/%s not found.\n" 1438c2ecf20Sopenharmony_ci "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n", 1448c2ecf20Sopenharmony_ci tracing_events_path, filename); 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci snprintf(buf, size, "%s", 1498c2ecf20Sopenharmony_ci "Error:\tUnable to find debugfs/tracefs\n" 1508c2ecf20Sopenharmony_ci "Hint:\tWas your kernel compiled with debugfs/tracefs support?\n" 1518c2ecf20Sopenharmony_ci "Hint:\tIs the debugfs/tracefs filesystem mounted?\n" 1528c2ecf20Sopenharmony_ci "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); 1538c2ecf20Sopenharmony_ci break; 1548c2ecf20Sopenharmony_ci case EACCES: { 1558c2ecf20Sopenharmony_ci snprintf(buf, size, 1568c2ecf20Sopenharmony_ci "Error:\tNo permissions to read %s/%s\n" 1578c2ecf20Sopenharmony_ci "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n", 1588c2ecf20Sopenharmony_ci tracing_events_path, filename, tracing_path_mount()); 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci break; 1618c2ecf20Sopenharmony_ci default: 1628c2ecf20Sopenharmony_ci snprintf(buf, size, "%s", str_error_r(err, sbuf, sizeof(sbuf))); 1638c2ecf20Sopenharmony_ci break; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci} 168