Skip to content

Commit 0141226

Browse files
mhiramathitachiacmel
authored andcommitted
perf buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
Use path/to/bin/buildid/elf instead of path/to/bin/buildid to store corresponding elf binary. This also stores vdso in buildid/vdso, kallsyms in buildid/kallsyms. Note that the existing caches are not updated until user adds or updates the cache. Anyway, if there is the old style build-id cache it falls back to use it. (IOW, it is backward compatible) Signed-off-by: Masami Hiramatsu <[email protected]> Signed-off-by: Masami Hiramatsu <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Ananth N Mavinakayanahalli <[email protected]> Cc: Brendan Gregg <[email protected]> Cc: Hemant Kumar <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/r/20160528151537.16098.85815.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 4e4b6c0 commit 0141226

File tree

4 files changed

+96
-31
lines changed

4 files changed

+96
-31
lines changed

tools/perf/util/build-id.c

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,32 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
144144
return ret;
145145
}
146146

147-
static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
147+
char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
148+
size_t size)
149+
{
150+
bool is_alloc = !!bf;
151+
bool retry_old = true;
152+
153+
asnprintf(&bf, size, "%s/%s/%s/kallsyms",
154+
buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
155+
retry:
156+
if (!access(bf, F_OK))
157+
return bf;
158+
if (is_alloc)
159+
free(bf);
160+
if (retry_old) {
161+
/* Try old style kallsyms cache */
162+
asnprintf(&bf, size, "%s/%s/%s",
163+
buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
164+
retry_old = false;
165+
goto retry;
166+
}
167+
168+
return NULL;
169+
}
170+
171+
static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
172+
size_t size)
148173
{
149174
char *tmp = bf;
150175
int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
@@ -154,23 +179,52 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
154179
return bf;
155180
}
156181

182+
static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
183+
{
184+
return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
185+
}
186+
157187
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
158188
{
159-
char build_id_hex[SBUILD_ID_SIZE];
189+
bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
190+
bool is_vdso = dso__is_vdso((struct dso *)dso);
191+
char sbuild_id[SBUILD_ID_SIZE];
192+
char *linkname;
193+
bool alloc = (bf == NULL);
194+
int ret;
160195

161196
if (!dso->has_build_id)
162197
return NULL;
163198

164-
build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
165-
return build_id__filename(build_id_hex, bf, size);
199+
build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
200+
linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
201+
if (!linkname)
202+
return NULL;
203+
204+
/* Check if old style build_id cache */
205+
if (is_regular_file(linkname))
206+
ret = asnprintf(&bf, size, "%s", linkname);
207+
else
208+
ret = asnprintf(&bf, size, "%s/%s", linkname,
209+
build_id_cache__basename(is_kallsyms, is_vdso));
210+
if (ret < 0 || (!alloc && size < (unsigned int)ret))
211+
bf = NULL;
212+
free(linkname);
213+
214+
return bf;
166215
}
167216

168217
bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
169218
{
170-
char *id_name, *ch;
219+
char *id_name = NULL, *ch;
171220
struct stat sb;
221+
char sbuild_id[SBUILD_ID_SIZE];
222+
223+
if (!dso->has_build_id)
224+
goto err;
172225

173-
id_name = dso__build_id_filename(dso, bf, size);
226+
build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
227+
id_name = build_id_cache__linkname(sbuild_id, NULL, 0);
174228
if (!id_name)
175229
goto err;
176230
if (access(id_name, F_OK))
@@ -194,18 +248,14 @@ bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
194248
if (ch - 3 < bf)
195249
goto err;
196250

251+
free(id_name);
197252
return strncmp(".ko", ch - 3, 3) == 0;
198253
err:
199-
/*
200-
* If dso__build_id_filename work, get id_name again,
201-
* because id_name points to bf and is broken.
202-
*/
203-
if (id_name)
204-
id_name = dso__build_id_filename(dso, bf, size);
205254
pr_err("Invalid build id: %s\n", id_name ? :
206255
dso->long_name ? :
207256
dso->short_name ? :
208257
"[unknown]");
258+
free(id_name);
209259
return false;
210260
}
211261

@@ -341,7 +391,8 @@ void disable_buildid_cache(void)
341391
}
342392

343393
static char *build_id_cache__dirname_from_path(const char *name,
344-
bool is_kallsyms, bool is_vdso)
394+
bool is_kallsyms, bool is_vdso,
395+
const char *sbuild_id)
345396
{
346397
char *realname = (char *)name, *filename;
347398
bool slash = is_kallsyms || is_vdso;
@@ -352,8 +403,9 @@ static char *build_id_cache__dirname_from_path(const char *name,
352403
return NULL;
353404
}
354405

355-
if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
356-
is_vdso ? DSO__NAME_VDSO : realname) < 0)
406+
if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "",
407+
is_vdso ? DSO__NAME_VDSO : realname,
408+
sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
357409
filename = NULL;
358410

359411
if (!slash)
@@ -368,7 +420,8 @@ int build_id_cache__list_build_ids(const char *pathname,
368420
char *dir_name;
369421
int ret = 0;
370422

371-
dir_name = build_id_cache__dirname_from_path(pathname, false, false);
423+
dir_name = build_id_cache__dirname_from_path(pathname, false, false,
424+
NULL);
372425
if (!dir_name)
373426
return -ENOMEM;
374427

@@ -385,7 +438,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
385438
{
386439
const size_t size = PATH_MAX;
387440
char *realname = NULL, *filename = NULL, *dir_name = NULL,
388-
*linkname = zalloc(size), *targetname, *tmp;
441+
*linkname = zalloc(size), *tmp;
389442
int err = -1;
390443

391444
if (!is_kallsyms) {
@@ -394,14 +447,22 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
394447
goto out_free;
395448
}
396449

397-
dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
450+
dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
451+
is_vdso, sbuild_id);
398452
if (!dir_name)
399453
goto out_free;
400454

455+
/* Remove old style build-id cache */
456+
if (is_regular_file(dir_name))
457+
if (unlink(dir_name))
458+
goto out_free;
459+
401460
if (mkdir_p(dir_name, 0755))
402461
goto out_free;
403462

404-
if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
463+
/* Save the allocated buildid dirname */
464+
if (asprintf(&filename, "%s/%s", dir_name,
465+
build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
405466
filename = NULL;
406467
goto out_free;
407468
}
@@ -415,7 +476,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
415476
goto out_free;
416477
}
417478

418-
if (!build_id__filename(sbuild_id, linkname, size))
479+
if (!build_id_cache__linkname(sbuild_id, linkname, size))
419480
goto out_free;
420481
tmp = strrchr(linkname, '/');
421482
*tmp = '\0';
@@ -424,10 +485,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
424485
goto out_free;
425486

426487
*tmp = '/';
427-
targetname = filename + strlen(buildid_dir) - 5;
428-
memcpy(targetname, "../..", 5);
488+
tmp = dir_name + strlen(buildid_dir) - 5;
489+
memcpy(tmp, "../..", 5);
429490

430-
if (symlink(targetname, linkname) == 0)
491+
if (symlink(tmp, linkname) == 0)
431492
err = 0;
432493
out_free:
433494
if (!is_kallsyms)
@@ -452,7 +513,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
452513
bool build_id_cache__cached(const char *sbuild_id)
453514
{
454515
bool ret = false;
455-
char *filename = build_id__filename(sbuild_id, NULL, 0);
516+
char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
456517

457518
if (filename && !access(filename, F_OK))
458519
ret = true;
@@ -471,7 +532,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
471532
if (filename == NULL || linkname == NULL)
472533
goto out_free;
473534

474-
if (!build_id__filename(sbuild_id, linkname, size))
535+
if (!build_id_cache__linkname(sbuild_id, linkname, size))
475536
goto out_free;
476537

477538
if (access(linkname, F_OK))
@@ -489,7 +550,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
489550
tmp = strrchr(linkname, '/') + 1;
490551
snprintf(tmp, size - (tmp - linkname), "%s", filename);
491552

492-
if (unlink(linkname))
553+
if (rm_rf(linkname))
493554
goto out_free;
494555

495556
err = 0;
@@ -501,7 +562,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
501562

502563
static int dso__cache_build_id(struct dso *dso, struct machine *machine)
503564
{
504-
bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
565+
bool is_kallsyms = dso__is_kallsyms(dso);
505566
bool is_vdso = dso__is_vdso(dso);
506567
const char *name = dso->long_name;
507568
char nm[PATH_MAX];

tools/perf/util/build-id.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct dso;
1414
int build_id__sprintf(const u8 *build_id, int len, char *bf);
1515
int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
1616
int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
17+
char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
18+
size_t size);
1719

1820
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
1921
bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);

tools/perf/util/dso.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ static inline bool dso__is_kcore(struct dso *dso)
349349
dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
350350
}
351351

352+
static inline bool dso__is_kallsyms(struct dso *dso)
353+
{
354+
return dso->kernel && dso->long_name[0] != '/';
355+
}
356+
352357
void dso__free_a2l(struct dso *dso);
353358

354359
enum dso_type dso__type(struct dso *dso, struct machine *machine);

tools/perf/util/symbol.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,10 +1704,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
17041704
}
17051705

17061706
/* Finally, find a cache of kallsyms */
1707-
scnprintf(path, sizeof(path), "%s/%s/%s",
1708-
buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
1709-
1710-
if (access(path, F_OK)) {
1707+
if (!build_id_cache__kallsyms_path(sbuild_id, path, sizeof(path))) {
17111708
pr_err("No kallsyms or vmlinux with build-id %s was found\n",
17121709
sbuild_id);
17131710
return NULL;

0 commit comments

Comments
 (0)