提交 eab8bcb6 编写于 作者: L Linus Torvalds

Merge branch 'perf-tools-for-linus' of git://github.com/acmel/linux

* 'perf-tools-for-linus' of git://github.com/acmel/linux:
  perf tools: Add support for disabling -Werror via WERROR=0
  perf top: Fix userspace sample addr map offset
  perf symbols: Fix issue with binaries using 16-bytes buildids (v2)
  perf tool: Fix endianness handling of u32 data in samples
  perf sort: Fix symbol sort output by separating unresolved samples by type
  perf symbols: Synthesize anonymous mmap events
  perf record: Create events initially disabled and enable after init
  perf symbols: Add some heuristics for choosing the best duplicate symbol
  perf symbols: Preserve symbol scope when parsing /proc/kallsyms
  perf symbols: /proc/kallsyms does not sort module symbols
  perf symbols: Fix ppc64 SEGV in dso__load_sym with debuginfo files
  perf probe: Fix regression of variable finder
...@@ -30,6 +30,8 @@ endif ...@@ -30,6 +30,8 @@ endif
# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
# #
# Define NO_DWARF if you do not want debug-info analysis feature at all. # Define NO_DWARF if you do not want debug-info analysis feature at all.
#
# Define WERROR=0 to disable treating any warnings as errors.
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
...@@ -63,6 +65,11 @@ ifeq ($(ARCH),x86_64) ...@@ -63,6 +65,11 @@ ifeq ($(ARCH),x86_64)
endif endif
endif endif
# Treat warnings as errors unless directed not to
ifneq ($(WERROR),0)
CFLAGS_WERROR := -Werror
endif
# #
# Include saner warnings here, which can catch bugs: # Include saner warnings here, which can catch bugs:
# #
...@@ -95,7 +102,7 @@ ifndef PERF_DEBUG ...@@ -95,7 +102,7 @@ ifndef PERF_DEBUG
CFLAGS_OPTIMIZE = -O6 CFLAGS_OPTIMIZE = -O6
endif endif
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm EXTLIBS = -lpthread -lrt -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
ALL_LDFLAGS = $(LDFLAGS) ALL_LDFLAGS = $(LDFLAGS)
......
...@@ -161,6 +161,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) ...@@ -161,6 +161,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
struct perf_event_attr *attr = &evsel->attr; struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */ int track = !evsel->idx; /* only the first counter needs these */
attr->disabled = 1;
attr->inherit = !no_inherit; attr->inherit = !no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_TOTAL_TIME_RUNNING |
...@@ -671,6 +672,8 @@ static int __cmd_record(int argc, const char **argv) ...@@ -671,6 +672,8 @@ static int __cmd_record(int argc, const char **argv)
} }
} }
perf_evlist__enable(evsel_list);
/* /*
* Let the child rip * Let the child rip
*/ */
......
...@@ -561,7 +561,7 @@ static int test__basic_mmap(void) ...@@ -561,7 +561,7 @@ static int test__basic_mmap(void)
} }
err = perf_event__parse_sample(event, attr.sample_type, sample_size, err = perf_event__parse_sample(event, attr.sample_type, sample_size,
false, &sample); false, &sample, false);
if (err) { if (err) {
pr_err("Can't parse sample, err = %d\n", err); pr_err("Can't parse sample, err = %d\n", err);
goto out_munmap; goto out_munmap;
......
...@@ -191,7 +191,8 @@ static void __zero_source_counters(struct sym_entry *syme) ...@@ -191,7 +191,8 @@ static void __zero_source_counters(struct sym_entry *syme)
symbol__annotate_zero_histograms(sym); symbol__annotate_zero_histograms(sym);
} }
static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) static void record_precise_ip(struct sym_entry *syme, struct map *map,
int counter, u64 ip)
{ {
struct annotation *notes; struct annotation *notes;
struct symbol *sym; struct symbol *sym;
...@@ -205,8 +206,8 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) ...@@ -205,8 +206,8 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
if (pthread_mutex_trylock(&notes->lock)) if (pthread_mutex_trylock(&notes->lock))
return; return;
ip = syme->map->map_ip(syme->map, ip); ip = map->map_ip(map, ip);
symbol__inc_addr_samples(sym, syme->map, counter, ip); symbol__inc_addr_samples(sym, map, counter, ip);
pthread_mutex_unlock(&notes->lock); pthread_mutex_unlock(&notes->lock);
} }
...@@ -810,7 +811,7 @@ static void perf_event__process_sample(const union perf_event *event, ...@@ -810,7 +811,7 @@ static void perf_event__process_sample(const union perf_event *event,
evsel = perf_evlist__id2evsel(top.evlist, sample->id); evsel = perf_evlist__id2evsel(top.evlist, sample->id);
assert(evsel != NULL); assert(evsel != NULL);
syme->count[evsel->idx]++; syme->count[evsel->idx]++;
record_precise_ip(syme, evsel->idx, ip); record_precise_ip(syme, al.map, evsel->idx, ip);
pthread_mutex_lock(&top.active_symbols_lock); pthread_mutex_lock(&top.active_symbols_lock);
if (list_empty(&syme->node) || !syme->node.next) { if (list_empty(&syme->node) || !syme->node.next) {
static bool first = true; static bool first = true;
......
...@@ -169,12 +169,17 @@ static int perf_event__synthesize_mmap_events(union perf_event *event, ...@@ -169,12 +169,17 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
continue; continue;
pbf += n + 3; pbf += n + 3;
if (*pbf == 'x') { /* vm_exec */ if (*pbf == 'x') { /* vm_exec */
char anonstr[] = "//anon\n";
char *execname = strchr(bf, '/'); char *execname = strchr(bf, '/');
/* Catch VDSO */ /* Catch VDSO */
if (execname == NULL) if (execname == NULL)
execname = strstr(bf, "[vdso]"); execname = strstr(bf, "[vdso]");
/* Catch anonymous mmaps */
if ((execname == NULL) && !strstr(bf, "["))
execname = anonstr;
if (execname == NULL) if (execname == NULL)
continue; continue;
......
...@@ -186,6 +186,6 @@ const char *perf_event__name(unsigned int id); ...@@ -186,6 +186,6 @@ const char *perf_event__name(unsigned int id);
int perf_event__parse_sample(const union perf_event *event, u64 type, int perf_event__parse_sample(const union perf_event *event, u64 type,
int sample_size, bool sample_id_all, int sample_size, bool sample_id_all,
struct perf_sample *sample); struct perf_sample *sample, bool swapped);
#endif /* __PERF_RECORD_H */ #endif /* __PERF_RECORD_H */
...@@ -113,6 +113,19 @@ void perf_evlist__disable(struct perf_evlist *evlist) ...@@ -113,6 +113,19 @@ void perf_evlist__disable(struct perf_evlist *evlist)
} }
} }
void perf_evlist__enable(struct perf_evlist *evlist)
{
int cpu, thread;
struct perf_evsel *pos;
for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE);
}
}
}
int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
{ {
int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
......
...@@ -54,6 +54,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); ...@@ -54,6 +54,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
void perf_evlist__munmap(struct perf_evlist *evlist); void perf_evlist__munmap(struct perf_evlist *evlist);
void perf_evlist__disable(struct perf_evlist *evlist); void perf_evlist__disable(struct perf_evlist *evlist);
void perf_evlist__enable(struct perf_evlist *evlist);
static inline void perf_evlist__set_maps(struct perf_evlist *evlist, static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
struct cpu_map *cpus, struct cpu_map *cpus,
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* Released under the GPL v2. (and only v2, not any later version) * Released under the GPL v2. (and only v2, not any later version)
*/ */
#include <byteswap.h>
#include "asm/bug.h"
#include "evsel.h" #include "evsel.h"
#include "evlist.h" #include "evlist.h"
#include "util.h" #include "util.h"
...@@ -342,10 +344,20 @@ static bool sample_overlap(const union perf_event *event, ...@@ -342,10 +344,20 @@ static bool sample_overlap(const union perf_event *event,
int perf_event__parse_sample(const union perf_event *event, u64 type, int perf_event__parse_sample(const union perf_event *event, u64 type,
int sample_size, bool sample_id_all, int sample_size, bool sample_id_all,
struct perf_sample *data) struct perf_sample *data, bool swapped)
{ {
const u64 *array; const u64 *array;
/*
* used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed.
*/
union {
u64 val64;
u32 val32[2];
} u;
data->cpu = data->pid = data->tid = -1; data->cpu = data->pid = data->tid = -1;
data->stream_id = data->id = data->time = -1ULL; data->stream_id = data->id = data->time = -1ULL;
...@@ -366,9 +378,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, ...@@ -366,9 +378,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
} }
if (type & PERF_SAMPLE_TID) { if (type & PERF_SAMPLE_TID) {
u32 *p = (u32 *)array; u.val64 = *array;
data->pid = p[0]; if (swapped) {
data->tid = p[1]; /* undo swap of u64, then swap on individual u32s */
u.val64 = bswap_64(u.val64);
u.val32[0] = bswap_32(u.val32[0]);
u.val32[1] = bswap_32(u.val32[1]);
}
data->pid = u.val32[0];
data->tid = u.val32[1];
array++; array++;
} }
...@@ -395,8 +414,15 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, ...@@ -395,8 +414,15 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
} }
if (type & PERF_SAMPLE_CPU) { if (type & PERF_SAMPLE_CPU) {
u32 *p = (u32 *)array;
data->cpu = *p; u.val64 = *array;
if (swapped) {
/* undo swap of u64, then swap on individual u32s */
u.val64 = bswap_64(u.val64);
u.val32[0] = bswap_32(u.val32[0]);
}
data->cpu = u.val32[0];
array++; array++;
} }
...@@ -423,18 +449,24 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, ...@@ -423,18 +449,24 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
} }
if (type & PERF_SAMPLE_RAW) { if (type & PERF_SAMPLE_RAW) {
u32 *p = (u32 *)array; u.val64 = *array;
if (WARN_ONCE(swapped,
"Endianness of raw data not corrected!\n")) {
/* undo swap of u64, then swap on individual u32s */
u.val64 = bswap_64(u.val64);
u.val32[0] = bswap_32(u.val32[0]);
u.val32[1] = bswap_32(u.val32[1]);
}
if (sample_overlap(event, array, sizeof(u32))) if (sample_overlap(event, array, sizeof(u32)))
return -EFAULT; return -EFAULT;
data->raw_size = *p; data->raw_size = u.val32[0];
p++;
if (sample_overlap(event, p, data->raw_size)) if (sample_overlap(event, &u.val32[1], data->raw_size))
return -EFAULT; return -EFAULT;
data->raw_data = p; data->raw_data = &u.val32[1];
} }
return 0; return 0;
......
...@@ -659,7 +659,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -659,7 +659,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die)) if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
ret = -ENOENT; ret = -ENOENT;
} }
if (ret == 0) if (ret >= 0)
ret = convert_variable(&vr_die, pf); ret = convert_variable(&vr_die, pf);
if (ret < 0) if (ret < 0)
......
...@@ -162,7 +162,8 @@ static inline int perf_session__parse_sample(struct perf_session *session, ...@@ -162,7 +162,8 @@ static inline int perf_session__parse_sample(struct perf_session *session,
{ {
return perf_event__parse_sample(event, session->sample_type, return perf_event__parse_sample(event, session->sample_type,
session->sample_size, session->sample_size,
session->sample_id_all, sample); session->sample_id_all, sample,
session->header.needs_swap);
} }
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
......
...@@ -151,11 +151,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) ...@@ -151,11 +151,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{ {
u64 ip_l, ip_r; u64 ip_l, ip_r;
if (!left->ms.sym && !right->ms.sym)
return right->level - left->level;
if (!left->ms.sym || !right->ms.sym)
return cmp_null(left->ms.sym, right->ms.sym);
if (left->ms.sym == right->ms.sym) if (left->ms.sym == right->ms.sym)
return 0; return 0;
ip_l = left->ms.sym ? left->ms.sym->start : left->ip; ip_l = left->ms.sym->start;
ip_r = right->ms.sym ? right->ms.sym->start : right->ip; ip_r = right->ms.sym->start;
return (int64_t)(ip_r - ip_l); return (int64_t)(ip_r - ip_l);
} }
......
...@@ -74,16 +74,104 @@ static void dso__set_sorted_by_name(struct dso *dso, enum map_type type) ...@@ -74,16 +74,104 @@ static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
bool symbol_type__is_a(char symbol_type, enum map_type map_type) bool symbol_type__is_a(char symbol_type, enum map_type map_type)
{ {
symbol_type = toupper(symbol_type);
switch (map_type) { switch (map_type) {
case MAP__FUNCTION: case MAP__FUNCTION:
return symbol_type == 'T' || symbol_type == 'W'; return symbol_type == 'T' || symbol_type == 'W';
case MAP__VARIABLE: case MAP__VARIABLE:
return symbol_type == 'D' || symbol_type == 'd'; return symbol_type == 'D';
default: default:
return false; return false;
} }
} }
static int prefix_underscores_count(const char *str)
{
const char *tail = str;
while (*tail == '_')
tail++;
return tail - str;
}
#define SYMBOL_A 0
#define SYMBOL_B 1
static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
{
s64 a;
s64 b;
/* Prefer a symbol with non zero length */
a = syma->end - syma->start;
b = symb->end - symb->start;
if ((b == 0) && (a > 0))
return SYMBOL_A;
else if ((a == 0) && (b > 0))
return SYMBOL_B;
/* Prefer a non weak symbol over a weak one */
a = syma->binding == STB_WEAK;
b = symb->binding == STB_WEAK;
if (b && !a)
return SYMBOL_A;
if (a && !b)
return SYMBOL_B;
/* Prefer a global symbol over a non global one */
a = syma->binding == STB_GLOBAL;
b = symb->binding == STB_GLOBAL;
if (a && !b)
return SYMBOL_A;
if (b && !a)
return SYMBOL_B;
/* Prefer a symbol with less underscores */
a = prefix_underscores_count(syma->name);
b = prefix_underscores_count(symb->name);
if (b > a)
return SYMBOL_A;
else if (a > b)
return SYMBOL_B;
/* If all else fails, choose the symbol with the longest name */
if (strlen(syma->name) >= strlen(symb->name))
return SYMBOL_A;
else
return SYMBOL_B;
}
static void symbols__fixup_duplicate(struct rb_root *symbols)
{
struct rb_node *nd;
struct symbol *curr, *next;
nd = rb_first(symbols);
while (nd) {
curr = rb_entry(nd, struct symbol, rb_node);
again:
nd = rb_next(&curr->rb_node);
next = rb_entry(nd, struct symbol, rb_node);
if (!nd)
break;
if (curr->start != next->start)
continue;
if (choose_best_symbol(curr, next) == SYMBOL_A) {
rb_erase(&next->rb_node, symbols);
goto again;
} else {
nd = rb_next(&curr->rb_node);
rb_erase(&curr->rb_node, symbols);
}
}
}
static void symbols__fixup_end(struct rb_root *symbols) static void symbols__fixup_end(struct rb_root *symbols)
{ {
struct rb_node *nd, *prevnd = rb_first(symbols); struct rb_node *nd, *prevnd = rb_first(symbols);
...@@ -438,18 +526,11 @@ int kallsyms__parse(const char *filename, void *arg, ...@@ -438,18 +526,11 @@ int kallsyms__parse(const char *filename, void *arg,
char *line = NULL; char *line = NULL;
size_t n; size_t n;
int err = -1; int err = -1;
u64 prev_start = 0;
char prev_symbol_type = 0;
char *prev_symbol_name;
FILE *file = fopen(filename, "r"); FILE *file = fopen(filename, "r");
if (file == NULL) if (file == NULL)
goto out_failure; goto out_failure;
prev_symbol_name = malloc(KSYM_NAME_LEN);
if (prev_symbol_name == NULL)
goto out_close;
err = 0; err = 0;
while (!feof(file)) { while (!feof(file)) {
...@@ -470,7 +551,7 @@ int kallsyms__parse(const char *filename, void *arg, ...@@ -470,7 +551,7 @@ int kallsyms__parse(const char *filename, void *arg,
if (len + 2 >= line_len) if (len + 2 >= line_len)
continue; continue;
symbol_type = toupper(line[len]); symbol_type = line[len];
len += 2; len += 2;
symbol_name = line + len; symbol_name = line + len;
len = line_len - len; len = line_len - len;
...@@ -480,24 +561,18 @@ int kallsyms__parse(const char *filename, void *arg, ...@@ -480,24 +561,18 @@ int kallsyms__parse(const char *filename, void *arg,
break; break;
} }
if (prev_symbol_type) { /*
u64 end = start; * module symbols are not sorted so we add all
if (end != prev_start) * symbols with zero length and rely on
--end; * symbols__fixup_end() to fix it up.
err = process_symbol(arg, prev_symbol_name, */
prev_symbol_type, prev_start, end); err = process_symbol(arg, symbol_name,
if (err) symbol_type, start, start);
break; if (err)
} break;
memcpy(prev_symbol_name, symbol_name, len + 1);
prev_symbol_type = symbol_type;
prev_start = start;
} }
free(prev_symbol_name);
free(line); free(line);
out_close:
fclose(file); fclose(file);
return err; return err;
...@@ -703,6 +778,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, ...@@ -703,6 +778,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
if (dso__load_all_kallsyms(dso, filename, map) < 0) if (dso__load_all_kallsyms(dso, filename, map) < 0)
return -1; return -1;
symbols__fixup_duplicate(&dso->symbols[map->type]);
symbols__fixup_end(&dso->symbols[map->type]);
if (dso->kernel == DSO_TYPE_GUEST_KERNEL) if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
dso->symtab_type = SYMTAB__GUEST_KALLSYMS; dso->symtab_type = SYMTAB__GUEST_KALLSYMS;
else else
...@@ -1092,8 +1170,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, ...@@ -1092,8 +1170,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
if (dso->has_build_id) { if (dso->has_build_id) {
u8 build_id[BUILD_ID_SIZE]; u8 build_id[BUILD_ID_SIZE];
if (elf_read_build_id(elf, build_id, if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
BUILD_ID_SIZE) != BUILD_ID_SIZE)
goto out_elf_end; goto out_elf_end;
if (!dso__build_id_equal(dso, build_id)) if (!dso__build_id_equal(dso, build_id))
...@@ -1111,6 +1188,8 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, ...@@ -1111,6 +1188,8 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
} }
opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx); opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
if (opdshdr.sh_type != SHT_PROGBITS)
opdsec = NULL;
if (opdsec) if (opdsec)
opddata = elf_rawdata(opdsec, NULL); opddata = elf_rawdata(opdsec, NULL);
...@@ -1276,6 +1355,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, ...@@ -1276,6 +1355,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
* For misannotated, zeroed, ASM function sizes. * For misannotated, zeroed, ASM function sizes.
*/ */
if (nr > 0) { if (nr > 0) {
symbols__fixup_duplicate(&dso->symbols[map->type]);
symbols__fixup_end(&dso->symbols[map->type]); symbols__fixup_end(&dso->symbols[map->type]);
if (kmap) { if (kmap) {
/* /*
...@@ -1362,8 +1442,8 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size) ...@@ -1362,8 +1442,8 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
ptr = data->d_buf; ptr = data->d_buf;
while (ptr < (data->d_buf + data->d_size)) { while (ptr < (data->d_buf + data->d_size)) {
GElf_Nhdr *nhdr = ptr; GElf_Nhdr *nhdr = ptr;
int namesz = NOTE_ALIGN(nhdr->n_namesz), size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
descsz = NOTE_ALIGN(nhdr->n_descsz); descsz = NOTE_ALIGN(nhdr->n_descsz);
const char *name; const char *name;
ptr += sizeof(*nhdr); ptr += sizeof(*nhdr);
...@@ -1372,8 +1452,10 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size) ...@@ -1372,8 +1452,10 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
if (nhdr->n_type == NT_GNU_BUILD_ID && if (nhdr->n_type == NT_GNU_BUILD_ID &&
nhdr->n_namesz == sizeof("GNU")) { nhdr->n_namesz == sizeof("GNU")) {
if (memcmp(name, "GNU", sizeof("GNU")) == 0) { if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
memcpy(bf, ptr, BUILD_ID_SIZE); size_t sz = min(size, descsz);
err = BUILD_ID_SIZE; memcpy(bf, ptr, sz);
memset(bf + sz, 0, size - sz);
err = descsz;
break; break;
} }
} }
...@@ -1425,7 +1507,7 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size) ...@@ -1425,7 +1507,7 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
while (1) { while (1) {
char bf[BUFSIZ]; char bf[BUFSIZ];
GElf_Nhdr nhdr; GElf_Nhdr nhdr;
int namesz, descsz; size_t namesz, descsz;
if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
break; break;
...@@ -1434,15 +1516,16 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size) ...@@ -1434,15 +1516,16 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
descsz = NOTE_ALIGN(nhdr.n_descsz); descsz = NOTE_ALIGN(nhdr.n_descsz);
if (nhdr.n_type == NT_GNU_BUILD_ID && if (nhdr.n_type == NT_GNU_BUILD_ID &&
nhdr.n_namesz == sizeof("GNU")) { nhdr.n_namesz == sizeof("GNU")) {
if (read(fd, bf, namesz) != namesz) if (read(fd, bf, namesz) != (ssize_t)namesz)
break; break;
if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
if (read(fd, build_id, size_t sz = min(descsz, size);
BUILD_ID_SIZE) == BUILD_ID_SIZE) { if (read(fd, build_id, sz) == (ssize_t)sz) {
memset(build_id + sz, 0, size - sz);
err = 0; err = 0;
break; break;
} }
} else if (read(fd, bf, descsz) != descsz) } else if (read(fd, bf, descsz) != (ssize_t)descsz)
break; break;
} else { } else {
int n = namesz + descsz; int n = namesz + descsz;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册