linux/tools/perf/arch/common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stdio.h>
   3#include <stdlib.h>
   4#include "common.h"
   5#include "../util/env.h"
   6#include "../util/debug.h"
   7#include <linux/zalloc.h>
   8
   9const char *const arc_triplets[] = {
  10        "arc-linux-",
  11        "arc-snps-linux-uclibc-",
  12        "arc-snps-linux-gnu-",
  13        NULL
  14};
  15
  16const char *const arm_triplets[] = {
  17        "arm-eabi-",
  18        "arm-linux-androideabi-",
  19        "arm-unknown-linux-",
  20        "arm-unknown-linux-gnu-",
  21        "arm-unknown-linux-gnueabi-",
  22        "arm-linux-gnu-",
  23        "arm-linux-gnueabihf-",
  24        "arm-none-eabi-",
  25        NULL
  26};
  27
  28const char *const arm64_triplets[] = {
  29        "aarch64-linux-android-",
  30        "aarch64-linux-gnu-",
  31        NULL
  32};
  33
  34const char *const powerpc_triplets[] = {
  35        "powerpc-unknown-linux-gnu-",
  36        "powerpc-linux-gnu-",
  37        "powerpc64-unknown-linux-gnu-",
  38        "powerpc64-linux-gnu-",
  39        "powerpc64le-linux-gnu-",
  40        NULL
  41};
  42
  43const char *const s390_triplets[] = {
  44        "s390-ibm-linux-",
  45        "s390x-linux-gnu-",
  46        NULL
  47};
  48
  49const char *const sh_triplets[] = {
  50        "sh-unknown-linux-gnu-",
  51        "sh64-unknown-linux-gnu-",
  52        "sh-linux-gnu-",
  53        "sh64-linux-gnu-",
  54        NULL
  55};
  56
  57const char *const sparc_triplets[] = {
  58        "sparc-unknown-linux-gnu-",
  59        "sparc64-unknown-linux-gnu-",
  60        "sparc64-linux-gnu-",
  61        NULL
  62};
  63
  64const char *const x86_triplets[] = {
  65        "x86_64-pc-linux-gnu-",
  66        "x86_64-unknown-linux-gnu-",
  67        "i686-pc-linux-gnu-",
  68        "i586-pc-linux-gnu-",
  69        "i486-pc-linux-gnu-",
  70        "i386-pc-linux-gnu-",
  71        "i686-linux-android-",
  72        "i686-android-linux-",
  73        "x86_64-linux-gnu-",
  74        "i586-linux-gnu-",
  75        NULL
  76};
  77
  78const char *const mips_triplets[] = {
  79        "mips-unknown-linux-gnu-",
  80        "mipsel-linux-android-",
  81        "mips-linux-gnu-",
  82        "mips64-linux-gnu-",
  83        "mips64el-linux-gnuabi64-",
  84        "mips64-linux-gnuabi64-",
  85        "mipsel-linux-gnu-",
  86        NULL
  87};
  88
  89static bool lookup_path(char *name)
  90{
  91        bool found = false;
  92        char *path, *tmp = NULL;
  93        char buf[PATH_MAX];
  94        char *env = getenv("PATH");
  95
  96        if (!env)
  97                return false;
  98
  99        env = strdup(env);
 100        if (!env)
 101                return false;
 102
 103        path = strtok_r(env, ":", &tmp);
 104        while (path) {
 105                scnprintf(buf, sizeof(buf), "%s/%s", path, name);
 106                if (access(buf, F_OK) == 0) {
 107                        found = true;
 108                        break;
 109                }
 110                path = strtok_r(NULL, ":", &tmp);
 111        }
 112        free(env);
 113        return found;
 114}
 115
 116static int lookup_triplets(const char *const *triplets, const char *name)
 117{
 118        int i;
 119        char buf[PATH_MAX];
 120
 121        for (i = 0; triplets[i] != NULL; i++) {
 122                scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name);
 123                if (lookup_path(buf))
 124                        return i;
 125        }
 126        return -1;
 127}
 128
 129static int perf_env__lookup_binutils_path(struct perf_env *env,
 130                                          const char *name, const char **path)
 131{
 132        int idx;
 133        const char *arch = perf_env__arch(env), *cross_env;
 134        const char *const *path_list;
 135        char *buf = NULL;
 136
 137        /*
 138         * We don't need to try to find objdump path for native system.
 139         * Just use default binutils path (e.g.: "objdump").
 140         */
 141        if (!strcmp(perf_env__arch(NULL), arch))
 142                goto out;
 143
 144        cross_env = getenv("CROSS_COMPILE");
 145        if (cross_env) {
 146                if (asprintf(&buf, "%s%s", cross_env, name) < 0)
 147                        goto out_error;
 148                if (buf[0] == '/') {
 149                        if (access(buf, F_OK) == 0)
 150                                goto out;
 151                        goto out_error;
 152                }
 153                if (lookup_path(buf))
 154                        goto out;
 155                zfree(&buf);
 156        }
 157
 158        if (!strcmp(arch, "arc"))
 159                path_list = arc_triplets;
 160        else if (!strcmp(arch, "arm"))
 161                path_list = arm_triplets;
 162        else if (!strcmp(arch, "arm64"))
 163                path_list = arm64_triplets;
 164        else if (!strcmp(arch, "powerpc"))
 165                path_list = powerpc_triplets;
 166        else if (!strcmp(arch, "sh"))
 167                path_list = sh_triplets;
 168        else if (!strcmp(arch, "s390"))
 169                path_list = s390_triplets;
 170        else if (!strcmp(arch, "sparc"))
 171                path_list = sparc_triplets;
 172        else if (!strcmp(arch, "x86"))
 173                path_list = x86_triplets;
 174        else if (!strcmp(arch, "mips"))
 175                path_list = mips_triplets;
 176        else {
 177                ui__error("binutils for %s not supported.\n", arch);
 178                goto out_error;
 179        }
 180
 181        idx = lookup_triplets(path_list, name);
 182        if (idx < 0) {
 183                ui__error("Please install %s for %s.\n"
 184                          "You can add it to PATH, set CROSS_COMPILE or "
 185                          "override the default using --%s.\n",
 186                          name, arch, name);
 187                goto out_error;
 188        }
 189
 190        if (asprintf(&buf, "%s%s", path_list[idx], name) < 0)
 191                goto out_error;
 192
 193out:
 194        *path = buf;
 195        return 0;
 196out_error:
 197        free(buf);
 198        *path = NULL;
 199        return -1;
 200}
 201
 202int perf_env__lookup_objdump(struct perf_env *env, const char **path)
 203{
 204        /*
 205         * For live mode, env->arch will be NULL and we can use
 206         * the native objdump tool.
 207         */
 208        if (env->arch == NULL)
 209                return 0;
 210
 211        return perf_env__lookup_binutils_path(env, "objdump", path);
 212}
 213
 214/*
 215 * Some architectures have a single address space for kernel and user addresses,
 216 * which makes it possible to determine if an address is in kernel space or user
 217 * space.
 218 */
 219bool perf_env__single_address_space(struct perf_env *env)
 220{
 221        return strcmp(perf_env__arch(env), "sparc");
 222}
 223