1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
28520a98dSArnaldo Carvalho de Melo #include <limits.h>
368e94f4eSIrina Tirdea #include <stdio.h>
4215a0d30SArnaldo Carvalho de Melo #include <stdlib.h>
58520a98dSArnaldo Carvalho de Melo #include <string.h>
691854f9aSArnaldo Carvalho de Melo #include <unistd.h>
768e94f4eSIrina Tirdea #include "common.h"
84e8fbc1cSArnaldo Carvalho de Melo #include "../util/env.h"
968e94f4eSIrina Tirdea #include "../util/debug.h"
107f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
1168e94f4eSIrina Tirdea
126d99a79cSEugeniy Paltsev const char *const arc_triplets[] = {
136d99a79cSEugeniy Paltsev "arc-linux-",
146d99a79cSEugeniy Paltsev "arc-snps-linux-uclibc-",
156d99a79cSEugeniy Paltsev "arc-snps-linux-gnu-",
166d99a79cSEugeniy Paltsev NULL
176d99a79cSEugeniy Paltsev };
186d99a79cSEugeniy Paltsev
1968e94f4eSIrina Tirdea const char *const arm_triplets[] = {
2068e94f4eSIrina Tirdea "arm-eabi-",
2168e94f4eSIrina Tirdea "arm-linux-androideabi-",
2268e94f4eSIrina Tirdea "arm-unknown-linux-",
2368e94f4eSIrina Tirdea "arm-unknown-linux-gnu-",
2468e94f4eSIrina Tirdea "arm-unknown-linux-gnueabi-",
2578f69b58SRavi Bangoria "arm-linux-gnu-",
2678f69b58SRavi Bangoria "arm-linux-gnueabihf-",
2778f69b58SRavi Bangoria "arm-none-eabi-",
2868e94f4eSIrina Tirdea NULL
2968e94f4eSIrina Tirdea };
3068e94f4eSIrina Tirdea
31c4d2df49SElliott Hughes const char *const arm64_triplets[] = {
32c4d2df49SElliott Hughes "aarch64-linux-android-",
3378f69b58SRavi Bangoria "aarch64-linux-gnu-",
34c4d2df49SElliott Hughes NULL
35c4d2df49SElliott Hughes };
36c4d2df49SElliott Hughes
3768e94f4eSIrina Tirdea const char *const powerpc_triplets[] = {
3868e94f4eSIrina Tirdea "powerpc-unknown-linux-gnu-",
396db47fdeSKim Phillips "powerpc-linux-gnu-",
4068e94f4eSIrina Tirdea "powerpc64-unknown-linux-gnu-",
4178f69b58SRavi Bangoria "powerpc64-linux-gnu-",
4278f69b58SRavi Bangoria "powerpc64le-linux-gnu-",
4368e94f4eSIrina Tirdea NULL
4468e94f4eSIrina Tirdea };
4568e94f4eSIrina Tirdea
4668e94f4eSIrina Tirdea const char *const riscv32_triplets[] = {
4768e94f4eSIrina Tirdea "riscv32-unknown-linux-gnu-",
4878f69b58SRavi Bangoria "riscv32-linux-android-",
4968e94f4eSIrina Tirdea "riscv32-linux-gnu-",
5068e94f4eSIrina Tirdea NULL
5168e94f4eSIrina Tirdea };
5268e94f4eSIrina Tirdea
5368e94f4eSIrina Tirdea const char *const riscv64_triplets[] = {
5478f69b58SRavi Bangoria "riscv64-unknown-linux-gnu-",
5568e94f4eSIrina Tirdea "riscv64-linux-android-",
5668e94f4eSIrina Tirdea "riscv64-linux-gnu-",
5768e94f4eSIrina Tirdea NULL
5868e94f4eSIrina Tirdea };
5968e94f4eSIrina Tirdea
6068e94f4eSIrina Tirdea const char *const s390_triplets[] = {
6178f69b58SRavi Bangoria "s390-ibm-linux-",
6268e94f4eSIrina Tirdea "s390x-linux-gnu-",
6368e94f4eSIrina Tirdea NULL
6468e94f4eSIrina Tirdea };
6568e94f4eSIrina Tirdea
6668e94f4eSIrina Tirdea const char *const sh_triplets[] = {
6768e94f4eSIrina Tirdea "sh-unknown-linux-gnu-",
6868e94f4eSIrina Tirdea "sh-linux-gnu-",
6968e94f4eSIrina Tirdea NULL
7068e94f4eSIrina Tirdea };
7168e94f4eSIrina Tirdea
7268e94f4eSIrina Tirdea const char *const sparc_triplets[] = {
7368e94f4eSIrina Tirdea "sparc-unknown-linux-gnu-",
7478f69b58SRavi Bangoria "sparc64-unknown-linux-gnu-",
7578f69b58SRavi Bangoria "sparc64-linux-gnu-",
7668e94f4eSIrina Tirdea NULL
7768e94f4eSIrina Tirdea };
7868e94f4eSIrina Tirdea
7968e94f4eSIrina Tirdea const char *const x86_triplets[] = {
8068e94f4eSIrina Tirdea "x86_64-pc-linux-gnu-",
8168e94f4eSIrina Tirdea "x86_64-unknown-linux-gnu-",
8278f69b58SRavi Bangoria "i686-pc-linux-gnu-",
8378f69b58SRavi Bangoria "i586-pc-linux-gnu-",
8478f69b58SRavi Bangoria "i486-pc-linux-gnu-",
8578f69b58SRavi Bangoria "i386-pc-linux-gnu-",
8678f69b58SRavi Bangoria "i686-linux-android-",
8768e94f4eSIrina Tirdea "i686-android-linux-",
8868e94f4eSIrina Tirdea "x86_64-linux-gnu-",
8968e94f4eSIrina Tirdea "i586-linux-gnu-",
9068e94f4eSIrina Tirdea NULL
9168e94f4eSIrina Tirdea };
9268e94f4eSIrina Tirdea
935bcaaca3SMartin Liška const char *const mips_triplets[] = {
9468e94f4eSIrina Tirdea "mips-unknown-linux-gnu-",
9568e94f4eSIrina Tirdea "mipsel-linux-android-",
9668e94f4eSIrina Tirdea "mips-linux-gnu-",
9768e94f4eSIrina Tirdea "mips64-linux-gnu-",
9868e94f4eSIrina Tirdea "mips64el-linux-gnuabi64-",
9968e94f4eSIrina Tirdea "mips64-linux-gnuabi64-",
10068e94f4eSIrina Tirdea "mipsel-linux-gnu-",
10168e94f4eSIrina Tirdea NULL
10268e94f4eSIrina Tirdea };
10368e94f4eSIrina Tirdea
lookup_path(char * name)10468e94f4eSIrina Tirdea static bool lookup_path(char *name)
10568e94f4eSIrina Tirdea {
10668e94f4eSIrina Tirdea bool found = false;
10768e94f4eSIrina Tirdea char *path, *tmp = NULL;
10868e94f4eSIrina Tirdea char buf[PATH_MAX];
10968e94f4eSIrina Tirdea char *env = getenv("PATH");
11068e94f4eSIrina Tirdea
11168e94f4eSIrina Tirdea if (!env)
11268e94f4eSIrina Tirdea return false;
11368e94f4eSIrina Tirdea
11468e94f4eSIrina Tirdea env = strdup(env);
11568e94f4eSIrina Tirdea if (!env)
11668e94f4eSIrina Tirdea return false;
11768e94f4eSIrina Tirdea
11868e94f4eSIrina Tirdea path = strtok_r(env, ":", &tmp);
11968e94f4eSIrina Tirdea while (path) {
12068e94f4eSIrina Tirdea scnprintf(buf, sizeof(buf), "%s/%s", path, name);
12168e94f4eSIrina Tirdea if (access(buf, F_OK) == 0) {
12268e94f4eSIrina Tirdea found = true;
12368e94f4eSIrina Tirdea break;
12468e94f4eSIrina Tirdea }
12568e94f4eSIrina Tirdea path = strtok_r(NULL, ":", &tmp);
12668e94f4eSIrina Tirdea }
12768e94f4eSIrina Tirdea free(env);
12868e94f4eSIrina Tirdea return found;
12968e94f4eSIrina Tirdea }
130eebd0bfcSArnaldo Carvalho de Melo
lookup_triplets(const char * const * triplets,const char * name)131*56d9117cSIan Rogers static int lookup_triplets(const char *const *triplets, const char *name)
13268e94f4eSIrina Tirdea {
13368e94f4eSIrina Tirdea int i;
1344e8fbc1cSArnaldo Carvalho de Melo char buf[PATH_MAX];
13568e94f4eSIrina Tirdea
13668e94f4eSIrina Tirdea for (i = 0; triplets[i] != NULL; i++) {
13768e94f4eSIrina Tirdea scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name);
13868e94f4eSIrina Tirdea if (lookup_path(buf))
13968e94f4eSIrina Tirdea return i;
14068e94f4eSIrina Tirdea }
14168e94f4eSIrina Tirdea return -1;
1424e8fbc1cSArnaldo Carvalho de Melo }
14368e94f4eSIrina Tirdea
perf_env__lookup_binutils_path(struct perf_env * env,const char * name,char ** path)14468e94f4eSIrina Tirdea static int perf_env__lookup_binutils_path(struct perf_env *env,
14568e94f4eSIrina Tirdea const char *name, char **path)
14668e94f4eSIrina Tirdea {
14768e94f4eSIrina Tirdea int idx;
14868e94f4eSIrina Tirdea const char *arch = perf_env__arch(env), *cross_env;
14968e94f4eSIrina Tirdea const char *const *path_list;
15068e94f4eSIrina Tirdea char *buf = NULL;
15168e94f4eSIrina Tirdea
15268e94f4eSIrina Tirdea /*
15368e94f4eSIrina Tirdea * We don't need to try to find objdump path for native system.
15468e94f4eSIrina Tirdea * Just use default binutils path (e.g.: "objdump").
15568e94f4eSIrina Tirdea */
15604662523SArnaldo Carvalho de Melo if (!strcmp(perf_env__arch(NULL), arch))
15768e94f4eSIrina Tirdea goto out;
15868e94f4eSIrina Tirdea
1596d99a79cSEugeniy Paltsev cross_env = getenv("CROSS_COMPILE");
1606d99a79cSEugeniy Paltsev if (cross_env) {
1616d99a79cSEugeniy Paltsev if (asprintf(&buf, "%s%s", cross_env, name) < 0)
16268e94f4eSIrina Tirdea goto out_error;
163c4d2df49SElliott Hughes if (buf[0] == '/') {
164c4d2df49SElliott Hughes if (access(buf, F_OK) == 0)
16568e94f4eSIrina Tirdea goto out;
16668e94f4eSIrina Tirdea goto out_error;
16768e94f4eSIrina Tirdea }
16868e94f4eSIrina Tirdea if (lookup_path(buf))
16968e94f4eSIrina Tirdea goto out;
17068e94f4eSIrina Tirdea zfree(&buf);
17168e94f4eSIrina Tirdea }
17268e94f4eSIrina Tirdea
17348ed0eceSNamhyung Kim if (!strcmp(arch, "arc"))
17468e94f4eSIrina Tirdea path_list = arc_triplets;
17568e94f4eSIrina Tirdea else if (!strcmp(arch, "arm"))
17668e94f4eSIrina Tirdea path_list = arm_triplets;
17768e94f4eSIrina Tirdea else if (!strcmp(arch, "arm64"))
17868e94f4eSIrina Tirdea path_list = arm64_triplets;
17968e94f4eSIrina Tirdea else if (!strcmp(arch, "powerpc"))
18068e94f4eSIrina Tirdea path_list = powerpc_triplets;
18168e94f4eSIrina Tirdea else if (!strcmp(arch, "riscv32"))
18268e94f4eSIrina Tirdea path_list = riscv32_triplets;
18368e94f4eSIrina Tirdea else if (!strcmp(arch, "riscv64"))
18468e94f4eSIrina Tirdea path_list = riscv64_triplets;
18568e94f4eSIrina Tirdea else if (!strcmp(arch, "sh"))
18668e94f4eSIrina Tirdea path_list = sh_triplets;
18768e94f4eSIrina Tirdea else if (!strcmp(arch, "s390"))
18868e94f4eSIrina Tirdea path_list = s390_triplets;
18968e94f4eSIrina Tirdea else if (!strcmp(arch, "sparc"))
19068e94f4eSIrina Tirdea path_list = sparc_triplets;
19168e94f4eSIrina Tirdea else if (!strcmp(arch, "x86"))
19268e94f4eSIrina Tirdea path_list = x86_triplets;
19368e94f4eSIrina Tirdea else if (!strcmp(arch, "mips"))
19468e94f4eSIrina Tirdea path_list = mips_triplets;
19568e94f4eSIrina Tirdea else {
19668e94f4eSIrina Tirdea ui__error("binutils for %s not supported.\n", arch);
19768e94f4eSIrina Tirdea goto out_error;
19868e94f4eSIrina Tirdea }
19968e94f4eSIrina Tirdea
20068e94f4eSIrina Tirdea idx = lookup_triplets(path_list, name);
20168e94f4eSIrina Tirdea if (idx < 0) {
20268e94f4eSIrina Tirdea ui__error("Please install %s for %s.\n"
203*56d9117cSIan Rogers "You can add it to PATH, set CROSS_COMPILE or "
20468e94f4eSIrina Tirdea "override the default using --%s.\n",
205ff6f7778SNamhyung Kim name, arch, name);
206ff6f7778SNamhyung Kim goto out_error;
207ff6f7778SNamhyung Kim }
208ff6f7778SNamhyung Kim
209ff6f7778SNamhyung Kim if (asprintf(&buf, "%s%s", path_list[idx], name) < 0)
210ff6f7778SNamhyung Kim goto out_error;
211ff6f7778SNamhyung Kim
212f178fd2dSArnaldo Carvalho de Melo out:
21368e94f4eSIrina Tirdea *path = buf;
214ec1891afSAdrian Hunter return 0;
215ec1891afSAdrian Hunter out_error:
216ec1891afSAdrian Hunter free(buf);
217ec1891afSAdrian Hunter *path = NULL;
218ec1891afSAdrian Hunter return -1;
219ec1891afSAdrian Hunter }
220ec1891afSAdrian Hunter
perf_env__lookup_objdump(struct perf_env * env,char ** path)221ec1891afSAdrian Hunter int perf_env__lookup_objdump(struct perf_env *env, char **path)
222ec1891afSAdrian Hunter {
223ec1891afSAdrian Hunter /*
224 * For live mode, env->arch will be NULL and we can use
225 * the native objdump tool.
226 */
227 if (env->arch == NULL)
228 return 0;
229
230 return perf_env__lookup_binutils_path(env, "objdump", path);
231 }
232
233 /*
234 * Some architectures have a single address space for kernel and user addresses,
235 * which makes it possible to determine if an address is in kernel space or user
236 * space.
237 */
perf_env__single_address_space(struct perf_env * env)238 bool perf_env__single_address_space(struct perf_env *env)
239 {
240 return strcmp(perf_env__arch(env), "sparc");
241 }
242