linux/tools/perf/builtin-buildid-cache.c
<<
>>
Prefs
   1/*
   2 * builtin-buildid-cache.c
   3 *
   4 * Builtin buildid-cache command: Manages build-id cache
   5 *
   6 * Copyright (C) 2010, Red Hat Inc.
   7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
   8 */
   9#include "builtin.h"
  10#include "perf.h"
  11#include "util/cache.h"
  12#include "util/debug.h"
  13#include "util/header.h"
  14#include "util/parse-options.h"
  15#include "util/strlist.h"
  16#include "util/build-id.h"
  17#include "util/session.h"
  18#include "util/symbol.h"
  19
  20static int build_id_cache__add_file(const char *filename, const char *debugdir)
  21{
  22        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
  23        u8 build_id[BUILD_ID_SIZE];
  24        int err;
  25
  26        if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
  27                pr_debug("Couldn't read a build-id in %s\n", filename);
  28                return -1;
  29        }
  30
  31        build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
  32        err = build_id_cache__add_s(sbuild_id, debugdir, filename,
  33                                    false, false);
  34        if (verbose)
  35                pr_info("Adding %s %s: %s\n", sbuild_id, filename,
  36                        err ? "FAIL" : "Ok");
  37        return err;
  38}
  39
  40static int build_id_cache__remove_file(const char *filename,
  41                                       const char *debugdir)
  42{
  43        u8 build_id[BUILD_ID_SIZE];
  44        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
  45
  46        int err;
  47
  48        if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
  49                pr_debug("Couldn't read a build-id in %s\n", filename);
  50                return -1;
  51        }
  52
  53        build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
  54        err = build_id_cache__remove_s(sbuild_id, debugdir);
  55        if (verbose)
  56                pr_info("Removing %s %s: %s\n", sbuild_id, filename,
  57                        err ? "FAIL" : "Ok");
  58
  59        return err;
  60}
  61
  62static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
  63{
  64        char filename[PATH_MAX];
  65        u8 build_id[BUILD_ID_SIZE];
  66
  67        if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
  68            filename__read_build_id(filename, build_id,
  69                                    sizeof(build_id)) != sizeof(build_id)) {
  70                if (errno == ENOENT)
  71                        return false;
  72
  73                pr_warning("Problems with %s file, consider removing it from the cache\n", 
  74                           filename);
  75        } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
  76                pr_warning("Problems with %s file, consider removing it from the cache\n", 
  77                           filename);
  78        }
  79
  80        return true;
  81}
  82
  83static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
  84{
  85        struct perf_session *session = perf_session__new(filename, O_RDONLY,
  86                                                         force, false, NULL);
  87        if (session == NULL)
  88                return -1;
  89
  90        perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
  91        perf_session__delete(session);
  92
  93        return 0;
  94}
  95
  96static int build_id_cache__update_file(const char *filename,
  97                                       const char *debugdir)
  98{
  99        u8 build_id[BUILD_ID_SIZE];
 100        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 101
 102        int err;
 103
 104        if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
 105                pr_debug("Couldn't read a build-id in %s\n", filename);
 106                return -1;
 107        }
 108
 109        build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
 110        err = build_id_cache__remove_s(sbuild_id, debugdir);
 111        if (!err) {
 112                err = build_id_cache__add_s(sbuild_id, debugdir, filename,
 113                                            false, false);
 114        }
 115        if (verbose)
 116                pr_info("Updating %s %s: %s\n", sbuild_id, filename,
 117                        err ? "FAIL" : "Ok");
 118
 119        return err;
 120}
 121
 122int cmd_buildid_cache(int argc, const char **argv,
 123                      const char *prefix __maybe_unused)
 124{
 125        struct strlist *list;
 126        struct str_node *pos;
 127        int ret = 0;
 128        bool force = false;
 129        char debugdir[PATH_MAX];
 130        char const *add_name_list_str = NULL,
 131                   *remove_name_list_str = NULL,
 132                   *missing_filename = NULL,
 133                   *update_name_list_str = NULL;
 134
 135        const struct option buildid_cache_options[] = {
 136        OPT_STRING('a', "add", &add_name_list_str,
 137                   "file list", "file(s) to add"),
 138        OPT_STRING('r', "remove", &remove_name_list_str, "file list",
 139                    "file(s) to remove"),
 140        OPT_STRING('M', "missing", &missing_filename, "file",
 141                   "to find missing build ids in the cache"),
 142        OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
 143        OPT_STRING('u', "update", &update_name_list_str, "file list",
 144                    "file(s) to update"),
 145        OPT_INCR('v', "verbose", &verbose, "be more verbose"),
 146        OPT_END()
 147        };
 148        const char * const buildid_cache_usage[] = {
 149                "perf buildid-cache [<options>]",
 150                NULL
 151        };
 152
 153        argc = parse_options(argc, argv, buildid_cache_options,
 154                             buildid_cache_usage, 0);
 155
 156        if (symbol__init() < 0)
 157                return -1;
 158
 159        setup_pager();
 160
 161        snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
 162
 163        if (add_name_list_str) {
 164                list = strlist__new(true, add_name_list_str);
 165                if (list) {
 166                        strlist__for_each(pos, list)
 167                                if (build_id_cache__add_file(pos->s, debugdir)) {
 168                                        if (errno == EEXIST) {
 169                                                pr_debug("%s already in the cache\n",
 170                                                         pos->s);
 171                                                continue;
 172                                        }
 173                                        pr_warning("Couldn't add %s: %s\n",
 174                                                   pos->s, strerror(errno));
 175                                }
 176
 177                        strlist__delete(list);
 178                }
 179        }
 180
 181        if (remove_name_list_str) {
 182                list = strlist__new(true, remove_name_list_str);
 183                if (list) {
 184                        strlist__for_each(pos, list)
 185                                if (build_id_cache__remove_file(pos->s, debugdir)) {
 186                                        if (errno == ENOENT) {
 187                                                pr_debug("%s wasn't in the cache\n",
 188                                                         pos->s);
 189                                                continue;
 190                                        }
 191                                        pr_warning("Couldn't remove %s: %s\n",
 192                                                   pos->s, strerror(errno));
 193                                }
 194
 195                        strlist__delete(list);
 196                }
 197        }
 198
 199        if (missing_filename)
 200                ret = build_id_cache__fprintf_missing(missing_filename, force, stdout);
 201
 202        if (update_name_list_str) {
 203                list = strlist__new(true, update_name_list_str);
 204                if (list) {
 205                        strlist__for_each(pos, list)
 206                                if (build_id_cache__update_file(pos->s, debugdir)) {
 207                                        if (errno == ENOENT) {
 208                                                pr_debug("%s wasn't in the cache\n",
 209                                                         pos->s);
 210                                                continue;
 211                                        }
 212                                        pr_warning("Couldn't update %s: %s\n",
 213                                                   pos->s, strerror(errno));
 214                                }
 215
 216                        strlist__delete(list);
 217                }
 218        }
 219
 220        return ret;
 221}
 222
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.