xref: /openbmc/linux/tools/perf/arch/common.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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