mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 02:19:51 +00:00
perf tools: Split up build id saving into fetch and write
We are saving the build id once we stop the profiling. And only after doing that we know if we need to set that feature in the header through the feature bitmap. But if we want a proper feature support in the headers, using a rule of offset/size pairs in sections, we need to know in advance how many features we need to set in the headers, so that we can reserve rooms for their section headers. The current state doesn't allow that, as it forces us to first save the build-ids to the file right after the datas instead of planning any structured layout. That's why this splits up the build-ids processing in two parts: one that fetches the build-ids from the Dso objects, and one that saves them into the file. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> LKML-Reference: <1257911467-28276-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
8671dab9d5
commit
57f395a7ea
4 changed files with 57 additions and 22 deletions
|
@ -69,6 +69,13 @@ struct build_id_event {
|
||||||
char filename[];
|
char filename[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct build_id_list {
|
||||||
|
struct build_id_event event;
|
||||||
|
struct list_head list;
|
||||||
|
const char *dso_name;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
typedef union event_union {
|
typedef union event_union {
|
||||||
struct perf_event_header header;
|
struct perf_event_header header;
|
||||||
struct ip_event ip;
|
struct ip_event ip;
|
||||||
|
|
|
@ -174,29 +174,18 @@ static void do_write(int fd, void *buf, size_t size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool write_buildid_table(int fd)
|
static void write_buildid_table(int fd, struct list_head *id_head)
|
||||||
{
|
{
|
||||||
struct dso *pos;
|
struct build_id_list *iter, *next;
|
||||||
bool have_buildid = false;
|
|
||||||
|
|
||||||
list_for_each_entry(pos, &dsos, node) {
|
list_for_each_entry_safe(iter, next, id_head, list) {
|
||||||
struct build_id_event b;
|
struct build_id_event *b = &iter->event;
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (filename__read_build_id(pos->long_name,
|
do_write(fd, b, sizeof(*b));
|
||||||
&b.build_id,
|
do_write(fd, (void *)iter->dso_name, iter->len);
|
||||||
sizeof(b.build_id)) < 0)
|
list_del(&iter->list);
|
||||||
continue;
|
free(iter);
|
||||||
have_buildid = true;
|
|
||||||
memset(&b.header, 0, sizeof(b.header));
|
|
||||||
len = strlen(pos->long_name) + 1;
|
|
||||||
len = ALIGN(len, 64);
|
|
||||||
b.header.size = sizeof(b) + len;
|
|
||||||
do_write(fd, &b, sizeof(b));
|
|
||||||
do_write(fd, pos->long_name, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return have_buildid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -226,10 +215,14 @@ perf_header__adds_write(struct perf_header *self, int fd, bool at_exit)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (at_exit) {
|
if (at_exit) {
|
||||||
lseek(fd, self->data_offset + self->data_size, SEEK_SET);
|
LIST_HEAD(id_list);
|
||||||
if (write_buildid_table(fd))
|
|
||||||
|
if (fetch_build_id_table(&id_list)) {
|
||||||
|
lseek(fd, self->data_offset + self->data_size, SEEK_SET);
|
||||||
perf_header__set_feat(self, HEADER_BUILD_ID);
|
perf_header__set_feat(self, HEADER_BUILD_ID);
|
||||||
lseek(fd, cur_offset, SEEK_SET);
|
write_buildid_table(fd, &id_list);
|
||||||
|
lseek(fd, cur_offset, SEEK_SET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -851,6 +851,40 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fetch_build_id_table(struct list_head *head)
|
||||||
|
{
|
||||||
|
bool have_buildid = false;
|
||||||
|
struct dso *pos;
|
||||||
|
|
||||||
|
list_for_each_entry(pos, &dsos, node) {
|
||||||
|
struct build_id_list *new;
|
||||||
|
struct build_id_event b;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (filename__read_build_id(pos->long_name,
|
||||||
|
&b.build_id,
|
||||||
|
sizeof(b.build_id)) < 0)
|
||||||
|
continue;
|
||||||
|
have_buildid = true;
|
||||||
|
memset(&b.header, 0, sizeof(b.header));
|
||||||
|
len = strlen(pos->long_name) + 1;
|
||||||
|
len = ALIGN(len, 64);
|
||||||
|
b.header.size = sizeof(b) + len;
|
||||||
|
|
||||||
|
new = malloc(sizeof(*new));
|
||||||
|
if (!new)
|
||||||
|
die("No memory\n");
|
||||||
|
|
||||||
|
memcpy(&new->event, &b, sizeof(b));
|
||||||
|
new->dso_name = pos->long_name;
|
||||||
|
new->len = len;
|
||||||
|
|
||||||
|
list_add_tail(&new->list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
return have_buildid;
|
||||||
|
}
|
||||||
|
|
||||||
int filename__read_build_id(const char *filename, void *bf, size_t size)
|
int filename__read_build_id(const char *filename, void *bf, size_t size)
|
||||||
{
|
{
|
||||||
int fd, err = -1;
|
int fd, err = -1;
|
||||||
|
|
|
@ -86,6 +86,7 @@ char dso__symtab_origin(const struct dso *self);
|
||||||
void dso__set_build_id(struct dso *self, void *build_id);
|
void dso__set_build_id(struct dso *self, void *build_id);
|
||||||
|
|
||||||
int filename__read_build_id(const char *filename, void *bf, size_t size);
|
int filename__read_build_id(const char *filename, void *bf, size_t size);
|
||||||
|
bool fetch_build_id_table(struct list_head *head);
|
||||||
int build_id__sprintf(u8 *self, int len, char *bf);
|
int build_id__sprintf(u8 *self, int len, char *bf);
|
||||||
|
|
||||||
int load_kernel(symbol_filter_t filter);
|
int load_kernel(symbol_filter_t filter);
|
||||||
|
|
Loading…
Reference in a new issue