Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/perf/arch/common.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <limits.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <unistd.h>
7
#include "common.h"
8
#include "../util/env.h"
9
#include "../util/debug.h"
10
#include <linux/zalloc.h>
11
12
const char *const arc_triplets[] = {
13
"arc-linux-",
14
"arc-snps-linux-uclibc-",
15
"arc-snps-linux-gnu-",
16
NULL
17
};
18
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-",
25
"arm-linux-gnu-",
26
"arm-linux-gnueabihf-",
27
"arm-none-eabi-",
28
NULL
29
};
30
31
const char *const arm64_triplets[] = {
32
"aarch64-linux-android-",
33
"aarch64-linux-gnu-",
34
NULL
35
};
36
37
const char *const powerpc_triplets[] = {
38
"powerpc-unknown-linux-gnu-",
39
"powerpc-linux-gnu-",
40
"powerpc64-unknown-linux-gnu-",
41
"powerpc64-linux-gnu-",
42
"powerpc64le-linux-gnu-",
43
NULL
44
};
45
46
const char *const riscv32_triplets[] = {
47
"riscv32-unknown-linux-gnu-",
48
"riscv32-linux-android-",
49
"riscv32-linux-gnu-",
50
NULL
51
};
52
53
const char *const riscv64_triplets[] = {
54
"riscv64-unknown-linux-gnu-",
55
"riscv64-linux-android-",
56
"riscv64-linux-gnu-",
57
NULL
58
};
59
60
const char *const s390_triplets[] = {
61
"s390-ibm-linux-",
62
"s390x-linux-gnu-",
63
NULL
64
};
65
66
const char *const sh_triplets[] = {
67
"sh-unknown-linux-gnu-",
68
"sh-linux-gnu-",
69
NULL
70
};
71
72
const char *const sparc_triplets[] = {
73
"sparc-unknown-linux-gnu-",
74
"sparc64-unknown-linux-gnu-",
75
"sparc64-linux-gnu-",
76
NULL
77
};
78
79
const char *const x86_triplets[] = {
80
"x86_64-pc-linux-gnu-",
81
"x86_64-unknown-linux-gnu-",
82
"i686-pc-linux-gnu-",
83
"i586-pc-linux-gnu-",
84
"i486-pc-linux-gnu-",
85
"i386-pc-linux-gnu-",
86
"i686-linux-android-",
87
"i686-android-linux-",
88
"x86_64-linux-gnu-",
89
"i586-linux-gnu-",
90
NULL
91
};
92
93
const char *const mips_triplets[] = {
94
"mips-unknown-linux-gnu-",
95
"mipsel-linux-android-",
96
"mips-linux-gnu-",
97
"mips64-linux-gnu-",
98
"mips64el-linux-gnuabi64-",
99
"mips64-linux-gnuabi64-",
100
"mipsel-linux-gnu-",
101
NULL
102
};
103
104
static bool lookup_path(char *name)
105
{
106
bool found = false;
107
char *path, *tmp = NULL;
108
char buf[PATH_MAX];
109
char *env = getenv("PATH");
110
111
if (!env)
112
return false;
113
114
env = strdup(env);
115
if (!env)
116
return false;
117
118
path = strtok_r(env, ":", &tmp);
119
while (path) {
120
scnprintf(buf, sizeof(buf), "%s/%s", path, name);
121
if (access(buf, F_OK) == 0) {
122
found = true;
123
break;
124
}
125
path = strtok_r(NULL, ":", &tmp);
126
}
127
free(env);
128
return found;
129
}
130
131
static int lookup_triplets(const char *const *triplets, const char *name)
132
{
133
int i;
134
char buf[PATH_MAX];
135
136
for (i = 0; triplets[i] != NULL; i++) {
137
scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name);
138
if (lookup_path(buf))
139
return i;
140
}
141
return -1;
142
}
143
144
static int perf_env__lookup_binutils_path(struct perf_env *env,
145
const char *name, char **path)
146
{
147
int idx;
148
const char *arch = perf_env__arch(env), *cross_env;
149
const char *const *path_list;
150
char *buf = NULL;
151
152
/*
153
* We don't need to try to find objdump path for native system.
154
* Just use default binutils path (e.g.: "objdump").
155
*/
156
if (!strcmp(perf_env__arch(NULL), arch))
157
goto out;
158
159
cross_env = getenv("CROSS_COMPILE");
160
if (cross_env) {
161
if (asprintf(&buf, "%s%s", cross_env, name) < 0)
162
goto out_error;
163
if (buf[0] == '/') {
164
if (access(buf, F_OK) == 0)
165
goto out;
166
goto out_error;
167
}
168
if (lookup_path(buf))
169
goto out;
170
zfree(&buf);
171
}
172
173
if (!strcmp(arch, "arc"))
174
path_list = arc_triplets;
175
else if (!strcmp(arch, "arm"))
176
path_list = arm_triplets;
177
else if (!strcmp(arch, "arm64"))
178
path_list = arm64_triplets;
179
else if (!strcmp(arch, "powerpc"))
180
path_list = powerpc_triplets;
181
else if (!strcmp(arch, "riscv32"))
182
path_list = riscv32_triplets;
183
else if (!strcmp(arch, "riscv64"))
184
path_list = riscv64_triplets;
185
else if (!strcmp(arch, "sh"))
186
path_list = sh_triplets;
187
else if (!strcmp(arch, "s390"))
188
path_list = s390_triplets;
189
else if (!strcmp(arch, "sparc"))
190
path_list = sparc_triplets;
191
else if (!strcmp(arch, "x86"))
192
path_list = x86_triplets;
193
else if (!strcmp(arch, "mips"))
194
path_list = mips_triplets;
195
else {
196
ui__error("binutils for %s not supported.\n", arch);
197
goto out_error;
198
}
199
200
idx = lookup_triplets(path_list, name);
201
if (idx < 0) {
202
ui__error("Please install %s for %s.\n"
203
"You can add it to PATH, set CROSS_COMPILE or "
204
"override the default using --%s.\n",
205
name, arch, name);
206
goto out_error;
207
}
208
209
if (asprintf(&buf, "%s%s", path_list[idx], name) < 0)
210
goto out_error;
211
212
out:
213
*path = buf;
214
return 0;
215
out_error:
216
free(buf);
217
*path = NULL;
218
return -1;
219
}
220
221
int perf_env__lookup_objdump(struct perf_env *env, char **path)
222
{
223
/*
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
*/
238
bool perf_env__single_address_space(struct perf_env *env)
239
{
240
return strcmp(perf_env__arch(env), "sparc");
241
}
242
243