Commit | Line | Data |
---|---|---|
68e94f4e IT |
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 | const char *const powerpc_triplets[] = { | |
16 | "powerpc-unknown-linux-gnu-", | |
17 | "powerpc64-unknown-linux-gnu-", | |
18 | NULL | |
19 | }; | |
20 | ||
21 | const char *const s390_triplets[] = { | |
22 | "s390-ibm-linux-", | |
23 | NULL | |
24 | }; | |
25 | ||
26 | const char *const sh_triplets[] = { | |
27 | "sh-unknown-linux-gnu-", | |
28 | "sh64-unknown-linux-gnu-", | |
29 | NULL | |
30 | }; | |
31 | ||
32 | const char *const sparc_triplets[] = { | |
33 | "sparc-unknown-linux-gnu-", | |
34 | "sparc64-unknown-linux-gnu-", | |
35 | NULL | |
36 | }; | |
37 | ||
38 | const char *const x86_triplets[] = { | |
39 | "x86_64-pc-linux-gnu-", | |
40 | "x86_64-unknown-linux-gnu-", | |
41 | "i686-pc-linux-gnu-", | |
42 | "i586-pc-linux-gnu-", | |
43 | "i486-pc-linux-gnu-", | |
44 | "i386-pc-linux-gnu-", | |
45 | "i686-linux-android-", | |
46 | "i686-android-linux-", | |
47 | NULL | |
48 | }; | |
49 | ||
50 | const char *const mips_triplets[] = { | |
51 | "mips-unknown-linux-gnu-", | |
52 | "mipsel-linux-android-", | |
53 | NULL | |
54 | }; | |
55 | ||
56 | static bool lookup_path(char *name) | |
57 | { | |
58 | bool found = false; | |
59 | char *path, *tmp; | |
60 | char buf[PATH_MAX]; | |
61 | char *env = getenv("PATH"); | |
62 | ||
63 | if (!env) | |
64 | return false; | |
65 | ||
66 | env = strdup(env); | |
67 | if (!env) | |
68 | return false; | |
69 | ||
70 | path = strtok_r(env, ":", &tmp); | |
71 | while (path) { | |
72 | scnprintf(buf, sizeof(buf), "%s/%s", path, name); | |
73 | if (access(buf, F_OK) == 0) { | |
74 | found = true; | |
75 | break; | |
76 | } | |
77 | path = strtok_r(NULL, ":", &tmp); | |
78 | } | |
79 | free(env); | |
80 | return found; | |
81 | } | |
82 | ||
83 | static int lookup_triplets(const char *const *triplets, const char *name) | |
84 | { | |
85 | int i; | |
86 | char buf[PATH_MAX]; | |
87 | ||
88 | for (i = 0; triplets[i] != NULL; i++) { | |
89 | scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name); | |
90 | if (lookup_path(buf)) | |
91 | return i; | |
92 | } | |
93 | return -1; | |
94 | } | |
95 | ||
96 | static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, | |
97 | const char *name, | |
98 | const char **path) | |
99 | { | |
100 | int idx; | |
101 | char *arch, *cross_env; | |
102 | struct utsname uts; | |
103 | const char *const *path_list; | |
104 | char *buf = NULL; | |
105 | ||
106 | if (uname(&uts) < 0) | |
107 | goto out; | |
108 | ||
109 | /* | |
110 | * We don't need to try to find objdump path for native system. | |
111 | * Just use default binutils path (e.g.: "objdump"). | |
112 | */ | |
113 | if (!strcmp(uts.machine, env->arch)) | |
114 | goto out; | |
115 | ||
116 | cross_env = getenv("CROSS_COMPILE"); | |
117 | if (cross_env) { | |
118 | if (asprintf(&buf, "%s%s", cross_env, name) < 0) | |
119 | goto out_error; | |
120 | if (buf[0] == '/') { | |
121 | if (access(buf, F_OK) == 0) | |
122 | goto out; | |
123 | goto out_error; | |
124 | } | |
125 | if (lookup_path(buf)) | |
126 | goto out; | |
127 | free(buf); | |
128 | } | |
129 | ||
130 | arch = env->arch; | |
131 | ||
132 | if (!strcmp(arch, "arm")) | |
133 | path_list = arm_triplets; | |
134 | else if (!strcmp(arch, "powerpc")) | |
135 | path_list = powerpc_triplets; | |
136 | else if (!strcmp(arch, "sh")) | |
137 | path_list = sh_triplets; | |
138 | else if (!strcmp(arch, "s390")) | |
139 | path_list = s390_triplets; | |
140 | else if (!strcmp(arch, "sparc")) | |
141 | path_list = sparc_triplets; | |
142 | else if (!strcmp(arch, "x86") || !strcmp(arch, "i386") || | |
143 | !strcmp(arch, "i486") || !strcmp(arch, "i586") || | |
144 | !strcmp(arch, "i686")) | |
145 | path_list = x86_triplets; | |
146 | else if (!strcmp(arch, "mips")) | |
147 | path_list = mips_triplets; | |
148 | else { | |
149 | ui__error("binutils for %s not supported.\n", arch); | |
150 | goto out_error; | |
151 | } | |
152 | ||
153 | idx = lookup_triplets(path_list, name); | |
154 | if (idx < 0) { | |
155 | ui__error("Please install %s for %s.\n" | |
156 | "You can add it to PATH, set CROSS_COMPILE or " | |
157 | "override the default using --%s.\n", | |
158 | name, arch, name); | |
159 | goto out_error; | |
160 | } | |
161 | ||
162 | if (asprintf(&buf, "%s%s", path_list[idx], name) < 0) | |
163 | goto out_error; | |
164 | ||
165 | out: | |
166 | *path = buf; | |
167 | return 0; | |
168 | out_error: | |
169 | free(buf); | |
170 | *path = NULL; | |
171 | return -1; | |
172 | } | |
173 | ||
174 | int perf_session_env__lookup_objdump(struct perf_session_env *env) | |
175 | { | |
176 | return perf_session_env__lookup_binutils_path(env, "objdump", | |
177 | &objdump_path); | |
178 | } |