Merge commit 'v3.1-rc9' into perf/core
Merge reason: pick up latest fixes. Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@ -76,16 +76,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)
|
||||
{
|
||||
symbol_type = toupper(symbol_type);
|
||||
|
||||
switch (map_type) {
|
||||
case MAP__FUNCTION:
|
||||
return symbol_type == 'T' || symbol_type == 'W';
|
||||
case MAP__VARIABLE:
|
||||
return symbol_type == 'D' || symbol_type == 'd';
|
||||
return symbol_type == 'D';
|
||||
default:
|
||||
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)
|
||||
{
|
||||
struct rb_node *nd, *prevnd = rb_first(symbols);
|
||||
@ -440,18 +528,11 @@ int kallsyms__parse(const char *filename, void *arg,
|
||||
char *line = NULL;
|
||||
size_t n;
|
||||
int err = -1;
|
||||
u64 prev_start = 0;
|
||||
char prev_symbol_type = 0;
|
||||
char *prev_symbol_name;
|
||||
FILE *file = fopen(filename, "r");
|
||||
|
||||
if (file == NULL)
|
||||
goto out_failure;
|
||||
|
||||
prev_symbol_name = malloc(KSYM_NAME_LEN);
|
||||
if (prev_symbol_name == NULL)
|
||||
goto out_close;
|
||||
|
||||
err = 0;
|
||||
|
||||
while (!feof(file)) {
|
||||
@ -472,7 +553,7 @@ int kallsyms__parse(const char *filename, void *arg,
|
||||
if (len + 2 >= line_len)
|
||||
continue;
|
||||
|
||||
symbol_type = toupper(line[len]);
|
||||
symbol_type = line[len];
|
||||
len += 2;
|
||||
symbol_name = line + len;
|
||||
len = line_len - len;
|
||||
@ -482,24 +563,18 @@ int kallsyms__parse(const char *filename, void *arg,
|
||||
break;
|
||||
}
|
||||
|
||||
if (prev_symbol_type) {
|
||||
u64 end = start;
|
||||
if (end != prev_start)
|
||||
--end;
|
||||
err = process_symbol(arg, prev_symbol_name,
|
||||
prev_symbol_type, prev_start, end);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(prev_symbol_name, symbol_name, len + 1);
|
||||
prev_symbol_type = symbol_type;
|
||||
prev_start = start;
|
||||
/*
|
||||
* module symbols are not sorted so we add all
|
||||
* symbols with zero length and rely on
|
||||
* symbols__fixup_end() to fix it up.
|
||||
*/
|
||||
err = process_symbol(arg, symbol_name,
|
||||
symbol_type, start, start);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
free(prev_symbol_name);
|
||||
free(line);
|
||||
out_close:
|
||||
fclose(file);
|
||||
return err;
|
||||
|
||||
@ -705,6 +780,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
|
||||
if (dso__load_all_kallsyms(dso, filename, map) < 0)
|
||||
return -1;
|
||||
|
||||
symbols__fixup_duplicate(&dso->symbols[map->type]);
|
||||
symbols__fixup_end(&dso->symbols[map->type]);
|
||||
|
||||
if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
|
||||
dso->symtab_type = SYMTAB__GUEST_KALLSYMS;
|
||||
else
|
||||
@ -1094,8 +1172,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
|
||||
if (dso->has_build_id) {
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
|
||||
if (elf_read_build_id(elf, build_id,
|
||||
BUILD_ID_SIZE) != BUILD_ID_SIZE)
|
||||
if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
|
||||
goto out_elf_end;
|
||||
|
||||
if (!dso__build_id_equal(dso, build_id))
|
||||
@ -1113,6 +1190,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);
|
||||
if (opdshdr.sh_type != SHT_PROGBITS)
|
||||
opdsec = NULL;
|
||||
if (opdsec)
|
||||
opddata = elf_rawdata(opdsec, NULL);
|
||||
|
||||
@ -1278,6 +1357,7 @@ new_symbol:
|
||||
* For misannotated, zeroed, ASM function sizes.
|
||||
*/
|
||||
if (nr > 0) {
|
||||
symbols__fixup_duplicate(&dso->symbols[map->type]);
|
||||
symbols__fixup_end(&dso->symbols[map->type]);
|
||||
if (kmap) {
|
||||
/*
|
||||
@ -1364,8 +1444,8 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
|
||||
ptr = data->d_buf;
|
||||
while (ptr < (data->d_buf + data->d_size)) {
|
||||
GElf_Nhdr *nhdr = ptr;
|
||||
int namesz = NOTE_ALIGN(nhdr->n_namesz),
|
||||
descsz = NOTE_ALIGN(nhdr->n_descsz);
|
||||
size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
|
||||
descsz = NOTE_ALIGN(nhdr->n_descsz);
|
||||
const char *name;
|
||||
|
||||
ptr += sizeof(*nhdr);
|
||||
@ -1374,8 +1454,10 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
|
||||
if (nhdr->n_type == NT_GNU_BUILD_ID &&
|
||||
nhdr->n_namesz == sizeof("GNU")) {
|
||||
if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
|
||||
memcpy(bf, ptr, BUILD_ID_SIZE);
|
||||
err = BUILD_ID_SIZE;
|
||||
size_t sz = min(size, descsz);
|
||||
memcpy(bf, ptr, sz);
|
||||
memset(bf + sz, 0, size - sz);
|
||||
err = descsz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1427,7 +1509,7 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
|
||||
while (1) {
|
||||
char bf[BUFSIZ];
|
||||
GElf_Nhdr nhdr;
|
||||
int namesz, descsz;
|
||||
size_t namesz, descsz;
|
||||
|
||||
if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
|
||||
break;
|
||||
@ -1436,15 +1518,16 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
|
||||
descsz = NOTE_ALIGN(nhdr.n_descsz);
|
||||
if (nhdr.n_type == NT_GNU_BUILD_ID &&
|
||||
nhdr.n_namesz == sizeof("GNU")) {
|
||||
if (read(fd, bf, namesz) != namesz)
|
||||
if (read(fd, bf, namesz) != (ssize_t)namesz)
|
||||
break;
|
||||
if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
|
||||
if (read(fd, build_id,
|
||||
BUILD_ID_SIZE) == BUILD_ID_SIZE) {
|
||||
size_t sz = min(descsz, size);
|
||||
if (read(fd, build_id, sz) == (ssize_t)sz) {
|
||||
memset(build_id + sz, 0, size - sz);
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
} else if (read(fd, bf, descsz) != descsz)
|
||||
} else if (read(fd, bf, descsz) != (ssize_t)descsz)
|
||||
break;
|
||||
} else {
|
||||
int n = namesz + descsz;
|
||||
|
Reference in New Issue
Block a user