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