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