162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <limits.h> 362306a36Sopenharmony_ci#include <stdio.h> 462306a36Sopenharmony_ci#include <stdlib.h> 562306a36Sopenharmony_ci#include <string.h> 662306a36Sopenharmony_ci#include <unistd.h> 762306a36Sopenharmony_ci#include "common.h" 862306a36Sopenharmony_ci#include "../util/env.h" 962306a36Sopenharmony_ci#include "../util/debug.h" 1062306a36Sopenharmony_ci#include <linux/zalloc.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciconst char *const arc_triplets[] = { 1362306a36Sopenharmony_ci "arc-linux-", 1462306a36Sopenharmony_ci "arc-snps-linux-uclibc-", 1562306a36Sopenharmony_ci "arc-snps-linux-gnu-", 1662306a36Sopenharmony_ci NULL 1762306a36Sopenharmony_ci}; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciconst char *const arm_triplets[] = { 2062306a36Sopenharmony_ci "arm-eabi-", 2162306a36Sopenharmony_ci "arm-linux-androideabi-", 2262306a36Sopenharmony_ci "arm-unknown-linux-", 2362306a36Sopenharmony_ci "arm-unknown-linux-gnu-", 2462306a36Sopenharmony_ci "arm-unknown-linux-gnueabi-", 2562306a36Sopenharmony_ci "arm-linux-gnu-", 2662306a36Sopenharmony_ci "arm-linux-gnueabihf-", 2762306a36Sopenharmony_ci "arm-none-eabi-", 2862306a36Sopenharmony_ci NULL 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciconst char *const arm64_triplets[] = { 3262306a36Sopenharmony_ci "aarch64-linux-android-", 3362306a36Sopenharmony_ci "aarch64-linux-gnu-", 3462306a36Sopenharmony_ci NULL 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciconst char *const powerpc_triplets[] = { 3862306a36Sopenharmony_ci "powerpc-unknown-linux-gnu-", 3962306a36Sopenharmony_ci "powerpc-linux-gnu-", 4062306a36Sopenharmony_ci "powerpc64-unknown-linux-gnu-", 4162306a36Sopenharmony_ci "powerpc64-linux-gnu-", 4262306a36Sopenharmony_ci "powerpc64le-linux-gnu-", 4362306a36Sopenharmony_ci NULL 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciconst char *const riscv32_triplets[] = { 4762306a36Sopenharmony_ci "riscv32-unknown-linux-gnu-", 4862306a36Sopenharmony_ci "riscv32-linux-android-", 4962306a36Sopenharmony_ci "riscv32-linux-gnu-", 5062306a36Sopenharmony_ci NULL 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciconst char *const riscv64_triplets[] = { 5462306a36Sopenharmony_ci "riscv64-unknown-linux-gnu-", 5562306a36Sopenharmony_ci "riscv64-linux-android-", 5662306a36Sopenharmony_ci "riscv64-linux-gnu-", 5762306a36Sopenharmony_ci NULL 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciconst char *const s390_triplets[] = { 6162306a36Sopenharmony_ci "s390-ibm-linux-", 6262306a36Sopenharmony_ci "s390x-linux-gnu-", 6362306a36Sopenharmony_ci NULL 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciconst char *const sh_triplets[] = { 6762306a36Sopenharmony_ci "sh-unknown-linux-gnu-", 6862306a36Sopenharmony_ci "sh-linux-gnu-", 6962306a36Sopenharmony_ci NULL 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ciconst char *const sparc_triplets[] = { 7362306a36Sopenharmony_ci "sparc-unknown-linux-gnu-", 7462306a36Sopenharmony_ci "sparc64-unknown-linux-gnu-", 7562306a36Sopenharmony_ci "sparc64-linux-gnu-", 7662306a36Sopenharmony_ci NULL 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciconst char *const x86_triplets[] = { 8062306a36Sopenharmony_ci "x86_64-pc-linux-gnu-", 8162306a36Sopenharmony_ci "x86_64-unknown-linux-gnu-", 8262306a36Sopenharmony_ci "i686-pc-linux-gnu-", 8362306a36Sopenharmony_ci "i586-pc-linux-gnu-", 8462306a36Sopenharmony_ci "i486-pc-linux-gnu-", 8562306a36Sopenharmony_ci "i386-pc-linux-gnu-", 8662306a36Sopenharmony_ci "i686-linux-android-", 8762306a36Sopenharmony_ci "i686-android-linux-", 8862306a36Sopenharmony_ci "x86_64-linux-gnu-", 8962306a36Sopenharmony_ci "i586-linux-gnu-", 9062306a36Sopenharmony_ci NULL 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciconst char *const mips_triplets[] = { 9462306a36Sopenharmony_ci "mips-unknown-linux-gnu-", 9562306a36Sopenharmony_ci "mipsel-linux-android-", 9662306a36Sopenharmony_ci "mips-linux-gnu-", 9762306a36Sopenharmony_ci "mips64-linux-gnu-", 9862306a36Sopenharmony_ci "mips64el-linux-gnuabi64-", 9962306a36Sopenharmony_ci "mips64-linux-gnuabi64-", 10062306a36Sopenharmony_ci "mipsel-linux-gnu-", 10162306a36Sopenharmony_ci NULL 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic bool lookup_path(char *name) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci bool found = false; 10762306a36Sopenharmony_ci char *path, *tmp = NULL; 10862306a36Sopenharmony_ci char buf[PATH_MAX]; 10962306a36Sopenharmony_ci char *env = getenv("PATH"); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (!env) 11262306a36Sopenharmony_ci return false; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci env = strdup(env); 11562306a36Sopenharmony_ci if (!env) 11662306a36Sopenharmony_ci return false; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci path = strtok_r(env, ":", &tmp); 11962306a36Sopenharmony_ci while (path) { 12062306a36Sopenharmony_ci scnprintf(buf, sizeof(buf), "%s/%s", path, name); 12162306a36Sopenharmony_ci if (access(buf, F_OK) == 0) { 12262306a36Sopenharmony_ci found = true; 12362306a36Sopenharmony_ci break; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci path = strtok_r(NULL, ":", &tmp); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci free(env); 12862306a36Sopenharmony_ci return found; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic int lookup_triplets(const char *const *triplets, const char *name) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci int i; 13462306a36Sopenharmony_ci char buf[PATH_MAX]; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci for (i = 0; triplets[i] != NULL; i++) { 13762306a36Sopenharmony_ci scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name); 13862306a36Sopenharmony_ci if (lookup_path(buf)) 13962306a36Sopenharmony_ci return i; 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci return -1; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic int perf_env__lookup_binutils_path(struct perf_env *env, 14562306a36Sopenharmony_ci const char *name, char **path) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci int idx; 14862306a36Sopenharmony_ci const char *arch = perf_env__arch(env), *cross_env; 14962306a36Sopenharmony_ci const char *const *path_list; 15062306a36Sopenharmony_ci char *buf = NULL; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci /* 15362306a36Sopenharmony_ci * We don't need to try to find objdump path for native system. 15462306a36Sopenharmony_ci * Just use default binutils path (e.g.: "objdump"). 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci if (!strcmp(perf_env__arch(NULL), arch)) 15762306a36Sopenharmony_ci goto out; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci cross_env = getenv("CROSS_COMPILE"); 16062306a36Sopenharmony_ci if (cross_env) { 16162306a36Sopenharmony_ci if (asprintf(&buf, "%s%s", cross_env, name) < 0) 16262306a36Sopenharmony_ci goto out_error; 16362306a36Sopenharmony_ci if (buf[0] == '/') { 16462306a36Sopenharmony_ci if (access(buf, F_OK) == 0) 16562306a36Sopenharmony_ci goto out; 16662306a36Sopenharmony_ci goto out_error; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci if (lookup_path(buf)) 16962306a36Sopenharmony_ci goto out; 17062306a36Sopenharmony_ci zfree(&buf); 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (!strcmp(arch, "arc")) 17462306a36Sopenharmony_ci path_list = arc_triplets; 17562306a36Sopenharmony_ci else if (!strcmp(arch, "arm")) 17662306a36Sopenharmony_ci path_list = arm_triplets; 17762306a36Sopenharmony_ci else if (!strcmp(arch, "arm64")) 17862306a36Sopenharmony_ci path_list = arm64_triplets; 17962306a36Sopenharmony_ci else if (!strcmp(arch, "powerpc")) 18062306a36Sopenharmony_ci path_list = powerpc_triplets; 18162306a36Sopenharmony_ci else if (!strcmp(arch, "riscv32")) 18262306a36Sopenharmony_ci path_list = riscv32_triplets; 18362306a36Sopenharmony_ci else if (!strcmp(arch, "riscv64")) 18462306a36Sopenharmony_ci path_list = riscv64_triplets; 18562306a36Sopenharmony_ci else if (!strcmp(arch, "sh")) 18662306a36Sopenharmony_ci path_list = sh_triplets; 18762306a36Sopenharmony_ci else if (!strcmp(arch, "s390")) 18862306a36Sopenharmony_ci path_list = s390_triplets; 18962306a36Sopenharmony_ci else if (!strcmp(arch, "sparc")) 19062306a36Sopenharmony_ci path_list = sparc_triplets; 19162306a36Sopenharmony_ci else if (!strcmp(arch, "x86")) 19262306a36Sopenharmony_ci path_list = x86_triplets; 19362306a36Sopenharmony_ci else if (!strcmp(arch, "mips")) 19462306a36Sopenharmony_ci path_list = mips_triplets; 19562306a36Sopenharmony_ci else { 19662306a36Sopenharmony_ci ui__error("binutils for %s not supported.\n", arch); 19762306a36Sopenharmony_ci goto out_error; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci idx = lookup_triplets(path_list, name); 20162306a36Sopenharmony_ci if (idx < 0) { 20262306a36Sopenharmony_ci ui__error("Please install %s for %s.\n" 20362306a36Sopenharmony_ci "You can add it to PATH, set CROSS_COMPILE or " 20462306a36Sopenharmony_ci "override the default using --%s.\n", 20562306a36Sopenharmony_ci name, arch, name); 20662306a36Sopenharmony_ci goto out_error; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (asprintf(&buf, "%s%s", path_list[idx], name) < 0) 21062306a36Sopenharmony_ci goto out_error; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ciout: 21362306a36Sopenharmony_ci *path = buf; 21462306a36Sopenharmony_ci return 0; 21562306a36Sopenharmony_ciout_error: 21662306a36Sopenharmony_ci free(buf); 21762306a36Sopenharmony_ci *path = NULL; 21862306a36Sopenharmony_ci return -1; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciint perf_env__lookup_objdump(struct perf_env *env, char **path) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci /* 22462306a36Sopenharmony_ci * For live mode, env->arch will be NULL and we can use 22562306a36Sopenharmony_ci * the native objdump tool. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci if (env->arch == NULL) 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci return perf_env__lookup_binutils_path(env, "objdump", path); 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* 23462306a36Sopenharmony_ci * Some architectures have a single address space for kernel and user addresses, 23562306a36Sopenharmony_ci * which makes it possible to determine if an address is in kernel space or user 23662306a36Sopenharmony_ci * space. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_cibool perf_env__single_address_space(struct perf_env *env) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci return strcmp(perf_env__arch(env), "sparc"); 24162306a36Sopenharmony_ci} 242