diff options
Diffstat (limited to 'tools/perf/util/build-id.c')
-rw-r--r-- | tools/perf/util/build-id.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 6a7e273a514a..f1479eeef7da 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -166,6 +166,50 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) | |||
166 | return build_id__filename(build_id_hex, bf, size); | 166 | return build_id__filename(build_id_hex, bf, size); |
167 | } | 167 | } |
168 | 168 | ||
169 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) | ||
170 | { | ||
171 | char *id_name, *ch; | ||
172 | struct stat sb; | ||
173 | |||
174 | id_name = dso__build_id_filename(dso, bf, size); | ||
175 | if (!id_name) | ||
176 | goto err; | ||
177 | if (access(id_name, F_OK)) | ||
178 | goto err; | ||
179 | if (lstat(id_name, &sb) == -1) | ||
180 | goto err; | ||
181 | if ((size_t)sb.st_size > size - 1) | ||
182 | goto err; | ||
183 | if (readlink(id_name, bf, size - 1) < 0) | ||
184 | goto err; | ||
185 | |||
186 | bf[sb.st_size] = '\0'; | ||
187 | |||
188 | /* | ||
189 | * link should be: | ||
190 | * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92 | ||
191 | */ | ||
192 | ch = strrchr(bf, '/'); | ||
193 | if (!ch) | ||
194 | goto err; | ||
195 | if (ch - 3 < bf) | ||
196 | goto err; | ||
197 | |||
198 | return strncmp(".ko", ch - 3, 3) == 0; | ||
199 | err: | ||
200 | /* | ||
201 | * If dso__build_id_filename work, get id_name again, | ||
202 | * because id_name points to bf and is broken. | ||
203 | */ | ||
204 | if (id_name) | ||
205 | id_name = dso__build_id_filename(dso, bf, size); | ||
206 | pr_err("Invalid build id: %s\n", id_name ? : | ||
207 | dso->long_name ? : | ||
208 | dso->short_name ? : | ||
209 | "[unknown]"); | ||
210 | return false; | ||
211 | } | ||
212 | |||
169 | #define dsos__for_each_with_build_id(pos, head) \ | 213 | #define dsos__for_each_with_build_id(pos, head) \ |
170 | list_for_each_entry(pos, head, node) \ | 214 | list_for_each_entry(pos, head, node) \ |
171 | if (!pos->has_build_id) \ | 215 | if (!pos->has_build_id) \ |
@@ -211,6 +255,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd) | |||
211 | dsos__for_each_with_build_id(pos, &machine->dsos.head) { | 255 | dsos__for_each_with_build_id(pos, &machine->dsos.head) { |
212 | const char *name; | 256 | const char *name; |
213 | size_t name_len; | 257 | size_t name_len; |
258 | bool in_kernel = false; | ||
214 | 259 | ||
215 | if (!pos->hit) | 260 | if (!pos->hit) |
216 | continue; | 261 | continue; |
@@ -227,8 +272,11 @@ static int machine__write_buildid_table(struct machine *machine, int fd) | |||
227 | name_len = pos->long_name_len + 1; | 272 | name_len = pos->long_name_len + 1; |
228 | } | 273 | } |
229 | 274 | ||
275 | in_kernel = pos->kernel || | ||
276 | is_kernel_module(name, | ||
277 | PERF_RECORD_MISC_CPUMODE_UNKNOWN); | ||
230 | err = write_buildid(name, name_len, pos->build_id, machine->pid, | 278 | err = write_buildid(name, name_len, pos->build_id, machine->pid, |
231 | pos->kernel ? kmisc : umisc, fd); | 279 | in_kernel ? kmisc : umisc, fd); |
232 | if (err) | 280 | if (err) |
233 | break; | 281 | break; |
234 | } | 282 | } |