in profiler/stack_printer.cpp [196:397]
void print_stack_trace(struct ksyms *ksyms, struct syms_cache *syms_cache,
struct profile_bpf *obj)
{
const struct ksym *ksym;
const struct syms *syms = NULL;
const struct sym *sym;
int cfd, sfd;
lua_stack_backtrace lua_bt = {};
__u32 nr_count;
struct stack_key *k;
__u64 v;
unsigned long *kip;
unsigned long *uip;
bool has_collision = false;
unsigned int missing_stacks = 0;
struct key_ext_t counts[MAX_ENTRIES];
unsigned int nr_kip;
unsigned int nr_uip;
int idx = 0;
/* add 1 for kernel_ip */
kip = (unsigned long *)calloc(env.perf_max_stack_depth + 1, sizeof(*kip));
if (!kip)
{
fprintf(stderr, "failed to alloc kernel ip\n");
return;
}
uip = (unsigned long *)calloc(env.perf_max_stack_depth, sizeof(*uip));
if (!uip)
{
fprintf(stderr, "failed to alloc user ip\n");
return;
}
cfd = bpf_map__fd(obj->maps.counts);
sfd = bpf_map__fd(obj->maps.stackmap);
nr_count = MAX_ENTRIES;
if (!read_counts_map(cfd, counts, &nr_count))
{
goto cleanup;
}
qsort(counts, nr_count, sizeof(counts[0]), cmp_counts);
for (std::size_t i = 0; i < nr_count; i++)
{
k = &counts[i].k;
v = counts[i].v;
nr_uip = 0;
nr_kip = 0;
idx = 0;
if (!env.user_stacks_only && stack_id_err(k->kern_stack_id))
{
missing_stacks += 1;
has_collision |= (k->kern_stack_id == -EEXIST);
}
if (!env.kernel_stacks_only && stack_id_err(k->user_stack_id))
{
missing_stacks += 1;
has_collision |= (k->user_stack_id == -EEXIST);
}
if (!env.kernel_stacks_only && k->user_stack_id >= 0)
{
if (bpf_map_lookup_elem(sfd, &k->user_stack_id, uip) == 0)
{
/* count the number of ips */
while (nr_uip < env.perf_max_stack_depth && uip[nr_uip])
nr_uip++;
syms = syms_cache__get_syms(syms_cache, k->pid);
}
int stack_level = lua_bt_map.get_lua_stack_backtrace(k->user_stack_id, &lua_bt);
if (env.lua_user_stacks_only && env.folded)
{
if (stack_level <= 0)
{
// if show lua user stack only, then we do not count the stack if it is not lua stack
continue;
}
}
}
if (!env.user_stacks_only && k->kern_stack_id >= 0)
{
if (k->kernel_ip)
kip[nr_kip++] = k->kernel_ip;
if (bpf_map_lookup_elem(sfd, &k->kern_stack_id, kip + nr_kip) == 0)
{
/* count the number of ips */
while (nr_kip < env.perf_max_stack_depth && kip[nr_kip])
nr_kip++;
}
}
if (env.folded)
{
// print folded stack output
printf("%s", k->name);
if (!env.kernel_stacks_only)
{
if (stack_id_err(k->user_stack_id))
printf(";[Missed User Stack]");
if (syms)
{
if (!env.disable_lua_user_trace)
{
print_fold_user_stack_with_lua(&lua_bt, syms, uip, nr_uip);
}
else
{
const struct sym *sym = NULL;
for (int j = nr_uip - 1; j >= 0; j--)
{
sym = syms__map_addr(syms, uip[j]);
printf(";%s", sym ? sym->name : "[unknown]");
}
}
}
}
if (!env.user_stacks_only)
{
if (env.delimiter && k->user_stack_id >= 0 &&
k->kern_stack_id >= 0)
printf(";-");
if (stack_id_err(k->kern_stack_id))
printf(";[Missed Kernel Stack]");
for (std::size_t j = nr_kip - 1; j >= 0; j--)
{
ksym = ksyms__map_addr(ksyms, kip[j]);
printf(";%s", ksym ? ksym->name : "[unknown]");
}
}
printf(" %lld\n", v);
}
else
{
// print default multi-line stack output
if (!env.user_stacks_only)
{
if (stack_id_err(k->kern_stack_id))
printf(" [Missed Kernel Stack]\n");
for (std::size_t j = 0; j < nr_kip; j++)
{
ksym = ksyms__map_addr(ksyms, kip[j]);
if (ksym)
printf(" #%-2d 0x%lx %s+0x%lx\n", idx++, kip[j], ksym->name, kip[j] - ksym->addr);
else
printf(" #%-2d 0x%lx [unknown]\n", idx++, kip[j]);
}
}
if (!env.kernel_stacks_only)
{
if (env.delimiter && k->kern_stack_id >= 0 &&
k->user_stack_id >= 0)
printf(" --\n");
if (stack_id_err(k->user_stack_id))
printf(" [Missed User Stack]\n");
if (!syms)
{
for (std::size_t j = 0; j < nr_uip; j++)
printf(" #%-2d 0x%016lx [unknown]\n", idx++, uip[j]);
}
else
{
for (std::size_t j = 0; j < nr_uip; j++)
{
char *dso_name;
uint64_t dso_offset;
sym = syms__map_addr_dso(syms, uip[j], &dso_name, &dso_offset);
printf(" #%-2d 0x%016lx", idx++, uip[j]);
if (sym)
printf(" %s+0x%lx", sym->name, sym->offset);
if (dso_name)
printf(" (%s+0x%lx)", dso_name, dso_offset);
printf("\n");
}
}
}
printf(" %-16s %s (%d)\n", "-", k->name, k->pid);
printf(" %lld\n\n", v);
}
}
if (missing_stacks > 0)
{
fprintf(stderr, "WARNING: %d stack traces could not be displayed.%s\n",
missing_stacks, has_collision ? " Consider increasing --stack-storage-size." : "");
}
cleanup:
free(kip);
free(uip);
}