int gen()

in cli/bpfcov.c [1187:1306]


int gen(struct root_args *args)
{
    log_info(args, "generating '%s' for program '%s'\n", args->output, args->program[0]);

    /* Get maps info */
    struct bpf_map_info profc_info = {};
    if (get_map_info(bpf_obj_get(args->pin[0]), &profc_info))
    {
        log_fata(args, "could not get info about pinned map '%s'\n", args->pin[0]);
    }
    struct bpf_map_info profd_info = {};
    if (get_map_info(bpf_obj_get(args->pin[1]), &profd_info))
    {
        log_fata(args, "could not get info about pinned map '%s'\n", args->pin[1]);
    }
    struct bpf_map_info profn_info = {};
    if (get_map_info(bpf_obj_get(args->pin[2]), &profn_info))
    {
        log_fata(args, "could not get info about pinned map '%s'\n", args->pin[2]);
    }
    struct bpf_map_info covmap_info = {};
    if (get_map_info(bpf_obj_get(args->pin[3]), &covmap_info))
    {
        log_fata(args, "could not get info about pinned map '%s'\n", args->pin[3]);
    }

    /* Time to write binary data to the output file */
    FILE *outfp = fopen(args->output, "wb");
    if (!outfp)
    {
        log_fata(args, "could not open the output file '%s'\n", args->output);
    }

    /* Write the header */
    log_info(args, "%s\n", "about to write the profraw header...");
    // Magic number
    char magic[8] = {0x81, 0x72, 0x66, 0x6F, 0x72, 0x70, 0x6C, 0xFF};
    fwrite(magic, 1, sizeof(magic), outfp);
    // Version
    void *covmap_data = malloc(covmap_info.value_size);
    if (get_global_data(bpf_obj_get(args->pin[3]), &covmap_info, covmap_data))
    {
        fclose(outfp);
        log_fata(args, "could not get global data from map '%s'\n", args->pin[3]);
    }
    long long int version = 0;
    memcpy(&version, &((char *)covmap_data)[12], 4); // Version is the 3rd int in the coverage mapping header
    version += 1;                                    // Version is 0 indexed
    fwrite(&version, 1, sizeof(version), outfp);
    free(covmap_data);
    // Data size
    long long int func_num = profd_info.value_size / 48; // 5 x i64 + 2 x i32 for each function
    fwrite(&func_num, 1, sizeof(func_num), outfp);
    // Padding before counters
    long long int pad_bef = 0;
    fwrite(&pad_bef, 1, sizeof(pad_bef), outfp);
    // Counters size
    long long int counters_num = profc_info.value_size / 8; // 1 x i64 for each counter element
    fwrite(&counters_num, 1, sizeof(counters_num), outfp);
    // Padding after counters
    long long int pad_aft = 0;
    fwrite(&pad_aft, 1, sizeof(pad_aft), outfp);
    // Names size
    long long int names_sz = profn_info.value_size;
    fwrite(&names_sz, 1, sizeof(names_sz), outfp);
    // Counters delta (nulled)
    long long int counters_delta = 0;
    fwrite(&counters_delta, 1, sizeof(counters_delta), outfp);
    // Names delta (nulled)
    long long int names_delta = 0;
    fwrite(&names_delta, 1, sizeof(names_delta), outfp);
    // IPVK last
    long long int ipvk_last = 1;
    fwrite(&ipvk_last, 1, sizeof(ipvk_last), outfp);

    /* Write the data part */
    log_info(args, "%s\n", "about to write the data in the profraw...");
    void *profd_data = malloc(profd_info.value_size);
    if (get_global_data(bpf_obj_get(args->pin[1]), &profd_info, profd_data))
    {
        fclose(outfp);
        log_fata(args, "could not get global data from map '%s'\n", args->pin[1]);
    }
    fwrite(profd_data, profd_info.value_size, 1, outfp);

    /* Write the counters part */
    log_info(args, "%s\n", "about to write the counters in the profraw..");
    void *profc_data = malloc(profc_info.value_size);
    if (get_global_data(bpf_obj_get(args->pin[0]), &profc_info, profc_data))
    {
        fclose(outfp);
        log_fata(args, "could not get global data from map '%s'\n", args->pin[0]);
    }
    fwrite(profc_data, profc_info.value_size, 1, outfp);

    /* Write the names part */
    log_info(args, "%s\n", "about to write the names in the profraw...");
    void *profn_data = malloc(profn_info.value_size);
    if (get_global_data(bpf_obj_get(args->pin[2]), &profn_info, profn_data))
    {
        fclose(outfp);
        log_fata(args, "could not get global data from map '%s'\n", args->pin[2]);
    }
    fwrite(profn_data, profn_info.value_size, 1, outfp);

    /* Align to 8 bytes */
    unsigned int b = 0;
    for (unsigned int p = b; p < (7 & (16 - profn_info.value_size % 16)); p++)
    {
        fwrite(&b, 1, 1, outfp);
    }

    /* Close */
    fclose(outfp);

    /* Unpin the maps */
    handle_map_pins(args, NULL, args->unpin);

    return 0;
}