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