void print_stack_trace()

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);
}