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