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