linux/kernel/gcov/clang.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2019 Google, Inc.
   4 * modified from kernel/gcov/gcc_4_7.c
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 *
  16 * LLVM uses profiling data that's deliberately similar to GCC, but has a
  17 * very different way of exporting that data.  LLVM calls llvm_gcov_init() once
  18 * per module, and provides a couple of callbacks that we can use to ask for
  19 * more data.
  20 *
  21 * We care about the "writeout" callback, which in turn calls back into
  22 * compiler-rt/this module to dump all the gathered coverage data to disk:
  23 *
  24 *    llvm_gcda_start_file()
  25 *      llvm_gcda_emit_function()
  26 *      llvm_gcda_emit_arcs()
  27 *      llvm_gcda_emit_function()
  28 *      llvm_gcda_emit_arcs()
  29 *      [... repeats for each function ...]
  30 *    llvm_gcda_summary_info()
  31 *    llvm_gcda_end_file()
  32 *
  33 * This design is much more stateless and unstructured than gcc's, and is
  34 * intended to run at process exit.  This forces us to keep some local state
  35 * about which module we're dealing with at the moment.  On the other hand, it
  36 * also means we don't depend as much on how LLVM represents profiling data
  37 * internally.
  38 *
  39 * See LLVM's lib/Transforms/Instrumentation/GCOVProfiling.cpp for more
  40 * details on how this works, particularly GCOVProfiler::emitProfileArcs(),
  41 * GCOVProfiler::insertCounterWriteout(), and
  42 * GCOVProfiler::insertFlush().
  43 */
  44
  45#define pr_fmt(fmt)     "gcov: " fmt
  46
  47#include <linux/kernel.h>
  48#include <linux/list.h>
  49#include <linux/printk.h>
  50#include <linux/ratelimit.h>
  51#include <linux/seq_file.h>
  52#include <linux/slab.h>
  53#include <linux/vmalloc.h>
  54#include "gcov.h"
  55
  56typedef void (*llvm_gcov_callback)(void);
  57
  58struct gcov_info {
  59        struct list_head head;
  60
  61        const char *filename;
  62        unsigned int version;
  63        u32 checksum;
  64
  65        struct list_head functions;
  66};
  67
  68struct gcov_fn_info {
  69        struct list_head head;
  70
  71        u32 ident;
  72        u32 checksum;
  73        u8 use_extra_checksum;
  74        u32 cfg_checksum;
  75
  76        u32 num_counters;
  77        u64 *counters;
  78        const char *function_name;
  79};
  80
  81static struct gcov_info *current_info;
  82
  83static LIST_HEAD(clang_gcov_list);
  84
  85void llvm_gcov_init(llvm_gcov_callback writeout, llvm_gcov_callback flush)
  86{
  87        struct gcov_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
  88
  89        if (!info)
  90                return;
  91
  92        INIT_LIST_HEAD(&info->head);
  93        INIT_LIST_HEAD(&info->functions);
  94
  95        mutex_lock(&gcov_lock);
  96
  97        list_add_tail(&info->head, &clang_gcov_list);
  98        current_info = info;
  99        writeout();
 100        current_info = NULL;
 101        if (gcov_events_enabled)
 102                gcov_event(GCOV_ADD, info);
 103
 104        mutex_unlock(&gcov_lock);
 105}
 106EXPORT_SYMBOL(llvm_gcov_init);
 107
 108void llvm_gcda_start_file(const char *orig_filename, const char version[4],
 109                u32 checksum)
 110{
 111        current_info->filename = orig_filename;
 112        memcpy(&current_info->version, version, sizeof(current_info->version));
 113        current_info->checksum = checksum;
 114}
 115EXPORT_SYMBOL(llvm_gcda_start_file);
 116
 117void llvm_gcda_emit_function(u32 ident, const char *function_name,
 118                u32 func_checksum, u8 use_extra_checksum, u32 cfg_checksum)
 119{
 120        struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
 121
 122        if (!info)
 123                return;
 124
 125        INIT_LIST_HEAD(&info->head);
 126        info->ident = ident;
 127        info->checksum = func_checksum;
 128        info->use_extra_checksum = use_extra_checksum;
 129        info->cfg_checksum = cfg_checksum;
 130        if (function_name)
 131                info->function_name = kstrdup(function_name, GFP_KERNEL);
 132
 133        list_add_tail(&info->head, &current_info->functions);
 134}
 135EXPORT_SYMBOL(llvm_gcda_emit_function);
 136
 137void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters)
 138{
 139        struct gcov_fn_info *info = list_last_entry(&current_info->functions,
 140                        struct gcov_fn_info, head);
 141
 142        info->num_counters = num_counters;
 143        info->counters = counters;
 144}
 145EXPORT_SYMBOL(llvm_gcda_emit_arcs);
 146
 147void llvm_gcda_summary_info(void)
 148{
 149}
 150EXPORT_SYMBOL(llvm_gcda_summary_info);
 151
 152void llvm_gcda_end_file(void)
 153{
 154}
 155EXPORT_SYMBOL(llvm_gcda_end_file);
 156
 157/**
 158 * gcov_info_filename - return info filename
 159 * @info: profiling data set
 160 */
 161const char *gcov_info_filename(struct gcov_info *info)
 162{
 163        return info->filename;
 164}
 165
 166/**
 167 * gcov_info_version - return info version
 168 * @info: profiling data set
 169 */
 170unsigned int gcov_info_version(struct gcov_info *info)
 171{
 172        return info->version;
 173}
 174
 175/**
 176 * gcov_info_next - return next profiling data set
 177 * @info: profiling data set
 178 *
 179 * Returns next gcov_info following @info or first gcov_info in the chain if
 180 * @info is %NULL.
 181 */
 182struct gcov_info *gcov_info_next(struct gcov_info *info)
 183{
 184        if (!info)
 185                return list_first_entry_or_null(&clang_gcov_list,
 186                                struct gcov_info, head);
 187        if (list_is_last(&info->head, &clang_gcov_list))
 188                return NULL;
 189        return list_next_entry(info, head);
 190}
 191
 192/**
 193 * gcov_info_link - link/add profiling data set to the list
 194 * @info: profiling data set
 195 */
 196void gcov_info_link(struct gcov_info *info)
 197{
 198        list_add_tail(&info->head, &clang_gcov_list);
 199}
 200
 201/**
 202 * gcov_info_unlink - unlink/remove profiling data set from the list
 203 * @prev: previous profiling data set
 204 * @info: profiling data set
 205 */
 206void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
 207{
 208        /* Generic code unlinks while iterating. */
 209        __list_del_entry(&info->head);
 210}
 211
 212/**
 213 * gcov_info_within_module - check if a profiling data set belongs to a module
 214 * @info: profiling data set
 215 * @mod: module
 216 *
 217 * Returns true if profiling data belongs module, false otherwise.
 218 */
 219bool gcov_info_within_module(struct gcov_info *info, struct module *mod)
 220{
 221        return within_module((unsigned long)info->filename, mod);
 222}
 223
 224/* Symbolic links to be created for each profiling data file. */
 225const struct gcov_link gcov_link[] = {
 226        { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
 227        { 0, NULL},
 228};
 229
 230/**
 231 * gcov_info_reset - reset profiling data to zero
 232 * @info: profiling data set
 233 */
 234void gcov_info_reset(struct gcov_info *info)
 235{
 236        struct gcov_fn_info *fn;
 237
 238        list_for_each_entry(fn, &info->functions, head)
 239                memset(fn->counters, 0,
 240                                sizeof(fn->counters[0]) * fn->num_counters);
 241}
 242
 243/**
 244 * gcov_info_is_compatible - check if profiling data can be added
 245 * @info1: first profiling data set
 246 * @info2: second profiling data set
 247 *
 248 * Returns non-zero if profiling data can be added, zero otherwise.
 249 */
 250int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
 251{
 252        struct gcov_fn_info *fn_ptr1 = list_first_entry_or_null(
 253                        &info1->functions, struct gcov_fn_info, head);
 254        struct gcov_fn_info *fn_ptr2 = list_first_entry_or_null(
 255                        &info2->functions, struct gcov_fn_info, head);
 256
 257        if (info1->checksum != info2->checksum)
 258                return false;
 259        if (!fn_ptr1)
 260                return fn_ptr1 == fn_ptr2;
 261        while (!list_is_last(&fn_ptr1->head, &info1->functions) &&
 262                !list_is_last(&fn_ptr2->head, &info2->functions)) {
 263                if (fn_ptr1->checksum != fn_ptr2->checksum)
 264                        return false;
 265                if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum)
 266                        return false;
 267                if (fn_ptr1->use_extra_checksum &&
 268                        fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)
 269                        return false;
 270                fn_ptr1 = list_next_entry(fn_ptr1, head);
 271                fn_ptr2 = list_next_entry(fn_ptr2, head);
 272        }
 273        return list_is_last(&fn_ptr1->head, &info1->functions) &&
 274                list_is_last(&fn_ptr2->head, &info2->functions);
 275}
 276
 277/**
 278 * gcov_info_add - add up profiling data
 279 * @dest: profiling data set to which data is added
 280 * @source: profiling data set which is added
 281 *
 282 * Adds profiling counts of @source to @dest.
 283 */
 284void gcov_info_add(struct gcov_info *dst, struct gcov_info *src)
 285{
 286        struct gcov_fn_info *dfn_ptr;
 287        struct gcov_fn_info *sfn_ptr = list_first_entry_or_null(&src->functions,
 288                        struct gcov_fn_info, head);
 289
 290        list_for_each_entry(dfn_ptr, &dst->functions, head) {
 291                u32 i;
 292
 293                for (i = 0; i < sfn_ptr->num_counters; i++)
 294                        dfn_ptr->counters[i] += sfn_ptr->counters[i];
 295        }
 296}
 297
 298static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn)
 299{
 300        size_t cv_size; /* counter values size */
 301        struct gcov_fn_info *fn_dup = kmemdup(fn, sizeof(*fn),
 302                        GFP_KERNEL);
 303        if (!fn_dup)
 304                return NULL;
 305        INIT_LIST_HEAD(&fn_dup->head);
 306
 307        fn_dup->function_name = kstrdup(fn->function_name, GFP_KERNEL);
 308        if (!fn_dup->function_name)
 309                goto err_name;
 310
 311        cv_size = fn->num_counters * sizeof(fn->counters[0]);
 312        fn_dup->counters = vmalloc(cv_size);
 313        if (!fn_dup->counters)
 314                goto err_counters;
 315        memcpy(fn_dup->counters, fn->counters, cv_size);
 316
 317        return fn_dup;
 318
 319err_counters:
 320        kfree(fn_dup->function_name);
 321err_name:
 322        kfree(fn_dup);
 323        return NULL;
 324}
 325
 326/**
 327 * gcov_info_dup - duplicate profiling data set
 328 * @info: profiling data set to duplicate
 329 *
 330 * Return newly allocated duplicate on success, %NULL on error.
 331 */
 332struct gcov_info *gcov_info_dup(struct gcov_info *info)
 333{
 334        struct gcov_info *dup;
 335        struct gcov_fn_info *fn;
 336
 337        dup = kmemdup(info, sizeof(*dup), GFP_KERNEL);
 338        if (!dup)
 339                return NULL;
 340        INIT_LIST_HEAD(&dup->head);
 341        INIT_LIST_HEAD(&dup->functions);
 342        dup->filename = kstrdup(info->filename, GFP_KERNEL);
 343        if (!dup->filename)
 344                goto err;
 345
 346        list_for_each_entry(fn, &info->functions, head) {
 347                struct gcov_fn_info *fn_dup = gcov_fn_info_dup(fn);
 348
 349                if (!fn_dup)
 350                        goto err;
 351                list_add_tail(&fn_dup->head, &dup->functions);
 352        }
 353
 354        return dup;
 355
 356err:
 357        gcov_info_free(dup);
 358        return NULL;
 359}
 360
 361/**
 362 * gcov_info_free - release memory for profiling data set duplicate
 363 * @info: profiling data set duplicate to free
 364 */
 365void gcov_info_free(struct gcov_info *info)
 366{
 367        struct gcov_fn_info *fn, *tmp;
 368
 369        list_for_each_entry_safe(fn, tmp, &info->functions, head) {
 370                kfree(fn->function_name);
 371                vfree(fn->counters);
 372                list_del(&fn->head);
 373                kfree(fn);
 374        }
 375        kfree(info->filename);
 376        kfree(info);
 377}
 378
 379#define ITER_STRIDE     PAGE_SIZE
 380
 381/**
 382 * struct gcov_iterator - specifies current file position in logical records
 383 * @info: associated profiling data
 384 * @buffer: buffer containing file data
 385 * @size: size of buffer
 386 * @pos: current position in file
 387 */
 388struct gcov_iterator {
 389        struct gcov_info *info;
 390        void *buffer;
 391        size_t size;
 392        loff_t pos;
 393};
 394
 395/**
 396 * store_gcov_u32 - store 32 bit number in gcov format to buffer
 397 * @buffer: target buffer or NULL
 398 * @off: offset into the buffer
 399 * @v: value to be stored
 400 *
 401 * Number format defined by gcc: numbers are recorded in the 32 bit
 402 * unsigned binary form of the endianness of the machine generating the
 403 * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
 404 * store anything.
 405 */
 406static size_t store_gcov_u32(void *buffer, size_t off, u32 v)
 407{
 408        u32 *data;
 409
 410        if (buffer) {
 411                data = buffer + off;
 412                *data = v;
 413        }
 414
 415        return sizeof(*data);
 416}
 417
 418/**
 419 * store_gcov_u64 - store 64 bit number in gcov format to buffer
 420 * @buffer: target buffer or NULL
 421 * @off: offset into the buffer
 422 * @v: value to be stored
 423 *
 424 * Number format defined by gcc: numbers are recorded in the 32 bit
 425 * unsigned binary form of the endianness of the machine generating the
 426 * file. 64 bit numbers are stored as two 32 bit numbers, the low part
 427 * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
 428 * anything.
 429 */
 430static size_t store_gcov_u64(void *buffer, size_t off, u64 v)
 431{
 432        u32 *data;
 433
 434        if (buffer) {
 435                data = buffer + off;
 436
 437                data[0] = (v & 0xffffffffUL);
 438                data[1] = (v >> 32);
 439        }
 440
 441        return sizeof(*data) * 2;
 442}
 443
 444/**
 445 * convert_to_gcda - convert profiling data set to gcda file format
 446 * @buffer: the buffer to store file data or %NULL if no data should be stored
 447 * @info: profiling data set to be converted
 448 *
 449 * Returns the number of bytes that were/would have been stored into the buffer.
 450 */
 451static size_t convert_to_gcda(char *buffer, struct gcov_info *info)
 452{
 453        struct gcov_fn_info *fi_ptr;
 454        size_t pos = 0;
 455
 456        /* File header. */
 457        pos += store_gcov_u32(buffer, pos, GCOV_DATA_MAGIC);
 458        pos += store_gcov_u32(buffer, pos, info->version);
 459        pos += store_gcov_u32(buffer, pos, info->checksum);
 460
 461        list_for_each_entry(fi_ptr, &info->functions, head) {
 462                u32 i;
 463                u32 len = 2;
 464
 465                if (fi_ptr->use_extra_checksum)
 466                        len++;
 467
 468                pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);
 469                pos += store_gcov_u32(buffer, pos, len);
 470                pos += store_gcov_u32(buffer, pos, fi_ptr->ident);
 471                pos += store_gcov_u32(buffer, pos, fi_ptr->checksum);
 472                if (fi_ptr->use_extra_checksum)
 473                        pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
 474
 475                pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE);
 476                pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2);
 477                for (i = 0; i < fi_ptr->num_counters; i++)
 478                        pos += store_gcov_u64(buffer, pos, fi_ptr->counters[i]);
 479        }
 480
 481        return pos;
 482}
 483
 484/**
 485 * gcov_iter_new - allocate and initialize profiling data iterator
 486 * @info: profiling data set to be iterated
 487 *
 488 * Return file iterator on success, %NULL otherwise.
 489 */
 490struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
 491{
 492        struct gcov_iterator *iter;
 493
 494        iter = kzalloc(sizeof(struct gcov_iterator), GFP_KERNEL);
 495        if (!iter)
 496                goto err_free;
 497
 498        iter->info = info;
 499        /* Dry-run to get the actual buffer size. */
 500        iter->size = convert_to_gcda(NULL, info);
 501        iter->buffer = vmalloc(iter->size);
 502        if (!iter->buffer)
 503                goto err_free;
 504
 505        convert_to_gcda(iter->buffer, info);
 506
 507        return iter;
 508
 509err_free:
 510        kfree(iter);
 511        return NULL;
 512}
 513
 514
 515/**
 516 * gcov_iter_get_info - return profiling data set for given file iterator
 517 * @iter: file iterator
 518 */
 519void gcov_iter_free(struct gcov_iterator *iter)
 520{
 521        vfree(iter->buffer);
 522        kfree(iter);
 523}
 524
 525/**
 526 * gcov_iter_get_info - return profiling data set for given file iterator
 527 * @iter: file iterator
 528 */
 529struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
 530{
 531        return iter->info;
 532}
 533
 534/**
 535 * gcov_iter_start - reset file iterator to starting position
 536 * @iter: file iterator
 537 */
 538void gcov_iter_start(struct gcov_iterator *iter)
 539{
 540        iter->pos = 0;
 541}
 542
 543/**
 544 * gcov_iter_next - advance file iterator to next logical record
 545 * @iter: file iterator
 546 *
 547 * Return zero if new position is valid, non-zero if iterator has reached end.
 548 */
 549int gcov_iter_next(struct gcov_iterator *iter)
 550{
 551        if (iter->pos < iter->size)
 552                iter->pos += ITER_STRIDE;
 553
 554        if (iter->pos >= iter->size)
 555                return -EINVAL;
 556
 557        return 0;
 558}
 559
 560/**
 561 * gcov_iter_write - write data for current pos to seq_file
 562 * @iter: file iterator
 563 * @seq: seq_file handle
 564 *
 565 * Return zero on success, non-zero otherwise.
 566 */
 567int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
 568{
 569        size_t len;
 570
 571        if (iter->pos >= iter->size)
 572                return -EINVAL;
 573
 574        len = ITER_STRIDE;
 575        if (iter->pos + len > iter->size)
 576                len = iter->size - iter->pos;
 577
 578        seq_write(seq, iter->buffer + iter->pos, len);
 579
 580        return 0;
 581}
 582