18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * builtin-buildid-cache.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Builtin buildid-cache command: Manages build-id cache 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2010, Red Hat Inc. 88c2ecf20Sopenharmony_ci * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <sys/types.h> 118c2ecf20Sopenharmony_ci#include <sys/time.h> 128c2ecf20Sopenharmony_ci#include <time.h> 138c2ecf20Sopenharmony_ci#include <dirent.h> 148c2ecf20Sopenharmony_ci#include <errno.h> 158c2ecf20Sopenharmony_ci#include <unistd.h> 168c2ecf20Sopenharmony_ci#include "builtin.h" 178c2ecf20Sopenharmony_ci#include "namespaces.h" 188c2ecf20Sopenharmony_ci#include "util/debug.h" 198c2ecf20Sopenharmony_ci#include "util/header.h" 208c2ecf20Sopenharmony_ci#include <subcmd/pager.h> 218c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h> 228c2ecf20Sopenharmony_ci#include "util/strlist.h" 238c2ecf20Sopenharmony_ci#include "util/build-id.h" 248c2ecf20Sopenharmony_ci#include "util/session.h" 258c2ecf20Sopenharmony_ci#include "util/dso.h" 268c2ecf20Sopenharmony_ci#include "util/symbol.h" 278c2ecf20Sopenharmony_ci#include "util/time-utils.h" 288c2ecf20Sopenharmony_ci#include "util/util.h" 298c2ecf20Sopenharmony_ci#include "util/probe-file.h" 308c2ecf20Sopenharmony_ci#include <linux/string.h> 318c2ecf20Sopenharmony_ci#include <linux/err.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci char root_dir[PATH_MAX]; 368c2ecf20Sopenharmony_ci char *p; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci strlcpy(root_dir, proc_dir, sizeof(root_dir)); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci p = strrchr(root_dir, '/'); 418c2ecf20Sopenharmony_ci if (!p) 428c2ecf20Sopenharmony_ci return -1; 438c2ecf20Sopenharmony_ci *p = '\0'; 448c2ecf20Sopenharmony_ci return sysfs__sprintf_build_id(root_dir, sbuildid); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic int build_id_cache__kcore_dir(char *dir, size_t sz) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci return fetch_current_timestamp(dir, sz); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic bool same_kallsyms_reloc(const char *from_dir, char *to_dir) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci char from[PATH_MAX]; 558c2ecf20Sopenharmony_ci char to[PATH_MAX]; 568c2ecf20Sopenharmony_ci const char *name; 578c2ecf20Sopenharmony_ci u64 addr1 = 0, addr2 = 0; 588c2ecf20Sopenharmony_ci int i, err = -1; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci scnprintf(from, sizeof(from), "%s/kallsyms", from_dir); 618c2ecf20Sopenharmony_ci scnprintf(to, sizeof(to), "%s/kallsyms", to_dir); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { 648c2ecf20Sopenharmony_ci err = kallsyms__get_function_start(from, name, &addr1); 658c2ecf20Sopenharmony_ci if (!err) 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (err) 708c2ecf20Sopenharmony_ci return false; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (kallsyms__get_function_start(to, name, &addr2)) 738c2ecf20Sopenharmony_ci return false; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci return addr1 == addr2; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int build_id_cache__kcore_existing(const char *from_dir, char *to_dir, 798c2ecf20Sopenharmony_ci size_t to_dir_sz) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci char from[PATH_MAX]; 828c2ecf20Sopenharmony_ci char to[PATH_MAX]; 838c2ecf20Sopenharmony_ci char to_subdir[PATH_MAX]; 848c2ecf20Sopenharmony_ci struct dirent *dent; 858c2ecf20Sopenharmony_ci int ret = -1; 868c2ecf20Sopenharmony_ci DIR *d; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci d = opendir(to_dir); 898c2ecf20Sopenharmony_ci if (!d) 908c2ecf20Sopenharmony_ci return -1; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci scnprintf(from, sizeof(from), "%s/modules", from_dir); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci while (1) { 958c2ecf20Sopenharmony_ci dent = readdir(d); 968c2ecf20Sopenharmony_ci if (!dent) 978c2ecf20Sopenharmony_ci break; 988c2ecf20Sopenharmony_ci if (dent->d_type != DT_DIR) 998c2ecf20Sopenharmony_ci continue; 1008c2ecf20Sopenharmony_ci scnprintf(to, sizeof(to), "%s/%s/modules", to_dir, 1018c2ecf20Sopenharmony_ci dent->d_name); 1028c2ecf20Sopenharmony_ci scnprintf(to_subdir, sizeof(to_subdir), "%s/%s", 1038c2ecf20Sopenharmony_ci to_dir, dent->d_name); 1048c2ecf20Sopenharmony_ci if (!compare_proc_modules(from, to) && 1058c2ecf20Sopenharmony_ci same_kallsyms_reloc(from_dir, to_subdir)) { 1068c2ecf20Sopenharmony_ci strlcpy(to_dir, to_subdir, to_dir_sz); 1078c2ecf20Sopenharmony_ci ret = 0; 1088c2ecf20Sopenharmony_ci break; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci closedir(d); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return ret; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic int build_id_cache__add_kcore(const char *filename, bool force) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci char dir[32], sbuildid[SBUILD_ID_SIZE]; 1208c2ecf20Sopenharmony_ci char from_dir[PATH_MAX], to_dir[PATH_MAX]; 1218c2ecf20Sopenharmony_ci char *p; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci strlcpy(from_dir, filename, sizeof(from_dir)); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci p = strrchr(from_dir, '/'); 1268c2ecf20Sopenharmony_ci if (!p || strcmp(p + 1, "kcore")) 1278c2ecf20Sopenharmony_ci return -1; 1288c2ecf20Sopenharmony_ci *p = '\0'; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0) 1318c2ecf20Sopenharmony_ci return -1; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s", 1348c2ecf20Sopenharmony_ci buildid_dir, DSO__NAME_KCORE, sbuildid); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (!force && 1378c2ecf20Sopenharmony_ci !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 1388c2ecf20Sopenharmony_ci pr_debug("same kcore found in %s\n", to_dir); 1398c2ecf20Sopenharmony_ci return 0; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (build_id_cache__kcore_dir(dir, sizeof(dir))) 1438c2ecf20Sopenharmony_ci return -1; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s/%s", 1468c2ecf20Sopenharmony_ci buildid_dir, DSO__NAME_KCORE, sbuildid, dir); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (mkdir_p(to_dir, 0755)) 1498c2ecf20Sopenharmony_ci return -1; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (kcore_copy(from_dir, to_dir)) { 1528c2ecf20Sopenharmony_ci /* Remove YYYYmmddHHMMSShh directory */ 1538c2ecf20Sopenharmony_ci if (!rmdir(to_dir)) { 1548c2ecf20Sopenharmony_ci p = strrchr(to_dir, '/'); 1558c2ecf20Sopenharmony_ci if (p) 1568c2ecf20Sopenharmony_ci *p = '\0'; 1578c2ecf20Sopenharmony_ci /* Try to remove buildid directory */ 1588c2ecf20Sopenharmony_ci if (!rmdir(to_dir)) { 1598c2ecf20Sopenharmony_ci p = strrchr(to_dir, '/'); 1608c2ecf20Sopenharmony_ci if (p) 1618c2ecf20Sopenharmony_ci *p = '\0'; 1628c2ecf20Sopenharmony_ci /* Try to remove [kernel.kcore] directory */ 1638c2ecf20Sopenharmony_ci rmdir(to_dir); 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci return -1; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci pr_debug("kcore added to build-id cache directory %s\n", to_dir); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int build_id_cache__add_file(const char *filename, struct nsinfo *nsi) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci char sbuild_id[SBUILD_ID_SIZE]; 1778c2ecf20Sopenharmony_ci struct build_id bid; 1788c2ecf20Sopenharmony_ci int err; 1798c2ecf20Sopenharmony_ci struct nscookie nsc; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci nsinfo__mountns_enter(nsi, &nsc); 1828c2ecf20Sopenharmony_ci err = filename__read_build_id(filename, &bid); 1838c2ecf20Sopenharmony_ci nsinfo__mountns_exit(&nsc); 1848c2ecf20Sopenharmony_ci if (err < 0) { 1858c2ecf20Sopenharmony_ci pr_debug("Couldn't read a build-id in %s\n", filename); 1868c2ecf20Sopenharmony_ci return -1; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci build_id__sprintf(&bid, sbuild_id); 1908c2ecf20Sopenharmony_ci err = build_id_cache__add_s(sbuild_id, filename, nsi, 1918c2ecf20Sopenharmony_ci false, false); 1928c2ecf20Sopenharmony_ci pr_debug("Adding %s %s: %s\n", sbuild_id, filename, 1938c2ecf20Sopenharmony_ci err ? "FAIL" : "Ok"); 1948c2ecf20Sopenharmony_ci return err; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci char sbuild_id[SBUILD_ID_SIZE]; 2008c2ecf20Sopenharmony_ci struct build_id bid; 2018c2ecf20Sopenharmony_ci struct nscookie nsc; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci int err; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci nsinfo__mountns_enter(nsi, &nsc); 2068c2ecf20Sopenharmony_ci err = filename__read_build_id(filename, &bid); 2078c2ecf20Sopenharmony_ci nsinfo__mountns_exit(&nsc); 2088c2ecf20Sopenharmony_ci if (err < 0) { 2098c2ecf20Sopenharmony_ci pr_debug("Couldn't read a build-id in %s\n", filename); 2108c2ecf20Sopenharmony_ci return -1; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci build_id__sprintf(&bid, sbuild_id); 2148c2ecf20Sopenharmony_ci err = build_id_cache__remove_s(sbuild_id); 2158c2ecf20Sopenharmony_ci pr_debug("Removing %s %s: %s\n", sbuild_id, filename, 2168c2ecf20Sopenharmony_ci err ? "FAIL" : "Ok"); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return err; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci struct strlist *list; 2248c2ecf20Sopenharmony_ci struct str_node *pos; 2258c2ecf20Sopenharmony_ci int err; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci err = build_id_cache__list_build_ids(pathname, nsi, &list); 2288c2ecf20Sopenharmony_ci if (err) 2298c2ecf20Sopenharmony_ci goto out; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, list) { 2328c2ecf20Sopenharmony_ci err = build_id_cache__remove_s(pos->s); 2338c2ecf20Sopenharmony_ci pr_debug("Removing %s %s: %s\n", pos->s, pathname, 2348c2ecf20Sopenharmony_ci err ? "FAIL" : "Ok"); 2358c2ecf20Sopenharmony_ci if (err) 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci strlist__delete(list); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciout: 2418c2ecf20Sopenharmony_ci pr_debug("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok"); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return err; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic int build_id_cache__purge_all(void) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci struct strlist *list; 2498c2ecf20Sopenharmony_ci struct str_node *pos; 2508c2ecf20Sopenharmony_ci int err = 0; 2518c2ecf20Sopenharmony_ci char *buf; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci list = build_id_cache__list_all(false); 2548c2ecf20Sopenharmony_ci if (!list) { 2558c2ecf20Sopenharmony_ci pr_debug("Failed to get buildids: -%d\n", errno); 2568c2ecf20Sopenharmony_ci return -EINVAL; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, list) { 2608c2ecf20Sopenharmony_ci buf = build_id_cache__origname(pos->s); 2618c2ecf20Sopenharmony_ci err = build_id_cache__remove_s(pos->s); 2628c2ecf20Sopenharmony_ci pr_debug("Removing %s (%s): %s\n", buf, pos->s, 2638c2ecf20Sopenharmony_ci err ? "FAIL" : "Ok"); 2648c2ecf20Sopenharmony_ci free(buf); 2658c2ecf20Sopenharmony_ci if (err) 2668c2ecf20Sopenharmony_ci break; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci strlist__delete(list); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci pr_debug("Purged all: %s\n", err ? "FAIL" : "Ok"); 2718c2ecf20Sopenharmony_ci return err; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci char filename[PATH_MAX]; 2778c2ecf20Sopenharmony_ci struct build_id bid; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (dso__build_id_filename(dso, filename, sizeof(filename), false) && 2808c2ecf20Sopenharmony_ci filename__read_build_id(filename, &bid) == -1) { 2818c2ecf20Sopenharmony_ci if (errno == ENOENT) 2828c2ecf20Sopenharmony_ci return false; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci pr_warning("Problems with %s file, consider removing it from the cache\n", 2858c2ecf20Sopenharmony_ci filename); 2868c2ecf20Sopenharmony_ci } else if (memcmp(dso->bid.data, bid.data, bid.size)) { 2878c2ecf20Sopenharmony_ci pr_warning("Problems with %s file, consider removing it from the cache\n", 2888c2ecf20Sopenharmony_ci filename); 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return true; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic int build_id_cache__fprintf_missing(struct perf_session *session, FILE *fp) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic int build_id_cache__update_file(const char *filename, struct nsinfo *nsi) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci char sbuild_id[SBUILD_ID_SIZE]; 3038c2ecf20Sopenharmony_ci struct build_id bid; 3048c2ecf20Sopenharmony_ci struct nscookie nsc; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci int err; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci nsinfo__mountns_enter(nsi, &nsc); 3098c2ecf20Sopenharmony_ci err = filename__read_build_id(filename, &bid); 3108c2ecf20Sopenharmony_ci nsinfo__mountns_exit(&nsc); 3118c2ecf20Sopenharmony_ci if (err < 0) { 3128c2ecf20Sopenharmony_ci pr_debug("Couldn't read a build-id in %s\n", filename); 3138c2ecf20Sopenharmony_ci return -1; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci err = 0; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci build_id__sprintf(&bid, sbuild_id); 3188c2ecf20Sopenharmony_ci if (build_id_cache__cached(sbuild_id)) 3198c2ecf20Sopenharmony_ci err = build_id_cache__remove_s(sbuild_id); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (!err) 3228c2ecf20Sopenharmony_ci err = build_id_cache__add_s(sbuild_id, filename, nsi, false, 3238c2ecf20Sopenharmony_ci false); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci pr_debug("Updating %s %s: %s\n", sbuild_id, filename, 3268c2ecf20Sopenharmony_ci err ? "FAIL" : "Ok"); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return err; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic int build_id_cache__show_all(void) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci struct strlist *bidlist; 3348c2ecf20Sopenharmony_ci struct str_node *nd; 3358c2ecf20Sopenharmony_ci char *buf; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci bidlist = build_id_cache__list_all(true); 3388c2ecf20Sopenharmony_ci if (!bidlist) { 3398c2ecf20Sopenharmony_ci pr_debug("Failed to get buildids: -%d\n", errno); 3408c2ecf20Sopenharmony_ci return -1; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci strlist__for_each_entry(nd, bidlist) { 3438c2ecf20Sopenharmony_ci buf = build_id_cache__origname(nd->s); 3448c2ecf20Sopenharmony_ci fprintf(stdout, "%s %s\n", nd->s, buf); 3458c2ecf20Sopenharmony_ci free(buf); 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci strlist__delete(bidlist); 3488c2ecf20Sopenharmony_ci return 0; 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ciint cmd_buildid_cache(int argc, const char **argv) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci struct strlist *list; 3548c2ecf20Sopenharmony_ci struct str_node *pos; 3558c2ecf20Sopenharmony_ci int ret = 0; 3568c2ecf20Sopenharmony_ci int ns_id = -1; 3578c2ecf20Sopenharmony_ci bool force = false; 3588c2ecf20Sopenharmony_ci bool list_files = false; 3598c2ecf20Sopenharmony_ci bool opts_flag = false; 3608c2ecf20Sopenharmony_ci bool purge_all = false; 3618c2ecf20Sopenharmony_ci char const *add_name_list_str = NULL, 3628c2ecf20Sopenharmony_ci *remove_name_list_str = NULL, 3638c2ecf20Sopenharmony_ci *purge_name_list_str = NULL, 3648c2ecf20Sopenharmony_ci *missing_filename = NULL, 3658c2ecf20Sopenharmony_ci *update_name_list_str = NULL, 3668c2ecf20Sopenharmony_ci *kcore_filename = NULL; 3678c2ecf20Sopenharmony_ci char sbuf[STRERR_BUFSIZE]; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci struct perf_data data = { 3708c2ecf20Sopenharmony_ci .mode = PERF_DATA_MODE_READ, 3718c2ecf20Sopenharmony_ci }; 3728c2ecf20Sopenharmony_ci struct perf_session *session = NULL; 3738c2ecf20Sopenharmony_ci struct nsinfo *nsi = NULL; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci const struct option buildid_cache_options[] = { 3768c2ecf20Sopenharmony_ci OPT_STRING('a', "add", &add_name_list_str, 3778c2ecf20Sopenharmony_ci "file list", "file(s) to add"), 3788c2ecf20Sopenharmony_ci OPT_STRING('k', "kcore", &kcore_filename, 3798c2ecf20Sopenharmony_ci "file", "kcore file to add"), 3808c2ecf20Sopenharmony_ci OPT_STRING('r', "remove", &remove_name_list_str, "file list", 3818c2ecf20Sopenharmony_ci "file(s) to remove"), 3828c2ecf20Sopenharmony_ci OPT_STRING('p', "purge", &purge_name_list_str, "file list", 3838c2ecf20Sopenharmony_ci "file(s) to remove (remove old caches too)"), 3848c2ecf20Sopenharmony_ci OPT_BOOLEAN('P', "purge-all", &purge_all, "purge all cached files"), 3858c2ecf20Sopenharmony_ci OPT_BOOLEAN('l', "list", &list_files, "list all cached files"), 3868c2ecf20Sopenharmony_ci OPT_STRING('M', "missing", &missing_filename, "file", 3878c2ecf20Sopenharmony_ci "to find missing build ids in the cache"), 3888c2ecf20Sopenharmony_ci OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 3898c2ecf20Sopenharmony_ci OPT_STRING('u', "update", &update_name_list_str, "file list", 3908c2ecf20Sopenharmony_ci "file(s) to update"), 3918c2ecf20Sopenharmony_ci OPT_INCR('v', "verbose", &verbose, "be more verbose"), 3928c2ecf20Sopenharmony_ci OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"), 3938c2ecf20Sopenharmony_ci OPT_END() 3948c2ecf20Sopenharmony_ci }; 3958c2ecf20Sopenharmony_ci const char * const buildid_cache_usage[] = { 3968c2ecf20Sopenharmony_ci "perf buildid-cache [<options>]", 3978c2ecf20Sopenharmony_ci NULL 3988c2ecf20Sopenharmony_ci }; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci argc = parse_options(argc, argv, buildid_cache_options, 4018c2ecf20Sopenharmony_ci buildid_cache_usage, 0); 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci opts_flag = add_name_list_str || kcore_filename || 4048c2ecf20Sopenharmony_ci remove_name_list_str || purge_name_list_str || 4058c2ecf20Sopenharmony_ci missing_filename || update_name_list_str || 4068c2ecf20Sopenharmony_ci purge_all; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (argc || !(list_files || opts_flag)) 4098c2ecf20Sopenharmony_ci usage_with_options(buildid_cache_usage, buildid_cache_options); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* -l is exclusive. It can not be used with other options. */ 4128c2ecf20Sopenharmony_ci if (list_files && opts_flag) { 4138c2ecf20Sopenharmony_ci usage_with_options_msg(buildid_cache_usage, 4148c2ecf20Sopenharmony_ci buildid_cache_options, "-l is exclusive.\n"); 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (ns_id > 0) 4188c2ecf20Sopenharmony_ci nsi = nsinfo__new(ns_id); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci if (missing_filename) { 4218c2ecf20Sopenharmony_ci data.path = missing_filename; 4228c2ecf20Sopenharmony_ci data.force = force; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci session = perf_session__new(&data, false, NULL); 4258c2ecf20Sopenharmony_ci if (IS_ERR(session)) 4268c2ecf20Sopenharmony_ci return PTR_ERR(session); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (symbol__init(session ? &session->header.env : NULL) < 0) 4308c2ecf20Sopenharmony_ci goto out; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci setup_pager(); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (list_files) { 4358c2ecf20Sopenharmony_ci ret = build_id_cache__show_all(); 4368c2ecf20Sopenharmony_ci goto out; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (add_name_list_str) { 4408c2ecf20Sopenharmony_ci list = strlist__new(add_name_list_str, NULL); 4418c2ecf20Sopenharmony_ci if (list) { 4428c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, list) 4438c2ecf20Sopenharmony_ci if (build_id_cache__add_file(pos->s, nsi)) { 4448c2ecf20Sopenharmony_ci if (errno == EEXIST) { 4458c2ecf20Sopenharmony_ci pr_debug("%s already in the cache\n", 4468c2ecf20Sopenharmony_ci pos->s); 4478c2ecf20Sopenharmony_ci continue; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci pr_warning("Couldn't add %s: %s\n", 4508c2ecf20Sopenharmony_ci pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci strlist__delete(list); 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci if (remove_name_list_str) { 4588c2ecf20Sopenharmony_ci list = strlist__new(remove_name_list_str, NULL); 4598c2ecf20Sopenharmony_ci if (list) { 4608c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, list) 4618c2ecf20Sopenharmony_ci if (build_id_cache__remove_file(pos->s, nsi)) { 4628c2ecf20Sopenharmony_ci if (errno == ENOENT) { 4638c2ecf20Sopenharmony_ci pr_debug("%s wasn't in the cache\n", 4648c2ecf20Sopenharmony_ci pos->s); 4658c2ecf20Sopenharmony_ci continue; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci pr_warning("Couldn't remove %s: %s\n", 4688c2ecf20Sopenharmony_ci pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci strlist__delete(list); 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (purge_name_list_str) { 4768c2ecf20Sopenharmony_ci list = strlist__new(purge_name_list_str, NULL); 4778c2ecf20Sopenharmony_ci if (list) { 4788c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, list) 4798c2ecf20Sopenharmony_ci if (build_id_cache__purge_path(pos->s, nsi)) { 4808c2ecf20Sopenharmony_ci if (errno == ENOENT) { 4818c2ecf20Sopenharmony_ci pr_debug("%s wasn't in the cache\n", 4828c2ecf20Sopenharmony_ci pos->s); 4838c2ecf20Sopenharmony_ci continue; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci pr_warning("Couldn't remove %s: %s\n", 4868c2ecf20Sopenharmony_ci pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci strlist__delete(list); 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci if (purge_all) { 4948c2ecf20Sopenharmony_ci if (build_id_cache__purge_all()) { 4958c2ecf20Sopenharmony_ci pr_warning("Couldn't remove some caches. Error: %s.\n", 4968c2ecf20Sopenharmony_ci str_error_r(errno, sbuf, sizeof(sbuf))); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (missing_filename) 5018c2ecf20Sopenharmony_ci ret = build_id_cache__fprintf_missing(session, stdout); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (update_name_list_str) { 5048c2ecf20Sopenharmony_ci list = strlist__new(update_name_list_str, NULL); 5058c2ecf20Sopenharmony_ci if (list) { 5068c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, list) 5078c2ecf20Sopenharmony_ci if (build_id_cache__update_file(pos->s, nsi)) { 5088c2ecf20Sopenharmony_ci if (errno == ENOENT) { 5098c2ecf20Sopenharmony_ci pr_debug("%s wasn't in the cache\n", 5108c2ecf20Sopenharmony_ci pos->s); 5118c2ecf20Sopenharmony_ci continue; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci pr_warning("Couldn't update %s: %s\n", 5148c2ecf20Sopenharmony_ci pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci strlist__delete(list); 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci if (kcore_filename && build_id_cache__add_kcore(kcore_filename, force)) 5228c2ecf20Sopenharmony_ci pr_warning("Couldn't add %s\n", kcore_filename); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ciout: 5258c2ecf20Sopenharmony_ci perf_session__delete(session); 5268c2ecf20Sopenharmony_ci nsinfo__zput(nsi); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci return ret; 5298c2ecf20Sopenharmony_ci} 530