Spec-Zone.ru › GCC 12

10.2 Вызов gcov

gcov [options] files

gcov принимает следующие параметры:

-a
--all-blocks

Записывает индивидуальные счётчики выполнения для каждого базового блока. Обычно gcov выводит счётчики выполнения только для основных блоков строки. С этим параметром можно определить, не выполняются ли блоки внутри одной строки.

-b
--branch-probabilities

Записывает частоты ветвлений в выходной файл и информацию о сводном анализе ветвлений в стандартный вывод. Этот параметр позволяет увидеть, насколько часто каждая ветвь в вашей программе проходила. Неусловные ветви не будут показаны, если не задан параметр -u.

-c
--branch-counts

Записывает частоты ветвлений в виде количества пройденных ветвей, а не в процентах.

-d
--display-progress

Отображает ход выполнения в стандартном выводе.

-f
--function-summaries

Выводит сводные таблицы для каждой функции в дополнение к сводной таблице для всего файла.

-h
--help

Отображает справку по использованию gcov (в стандартном выводе) и завершает работу без дальнейшей обработки.

-j
--json-format

Выводит файл gcov в удобном для парсинга промежуточном формате JSON, который не требует исходного кода для генерации. JSON-файл сжат алгоритмом gzip, и файлы имеют расширение .gcov.json.gz.

Структура JSON имеет следующий вид:

{
  "current_working_directory": "foo/bar",
  "data_file": "a.out",
  "format_version": "1",
  "gcc_version": "11.1.1 20210510"
  "files": ["$file"]
}

Поля корневого элемента имеют следующее значение:

  • current_working_directory: рабочая директория, в которой был скомпилирован модуль
  • data_file: имя файла данных (GCDA)
  • format_version: семантическая версия формата
  • gcc_version: версия компилятора GCC

Каждый элемент file имеет следующий вид:

{
  "file": "a.c",
  "functions": ["$function"],
  "lines": ["$line"]
}

Поля элемента file имеют следующее значение:

  • file_name: имя исходного файла

Каждый элемент function имеет следующий вид:

{
  "blocks": 2,
  "blocks_executed": 2,
  "demangled_name": "foo",
  "end_column": 1,
  "end_line": 4,
  "execution_count": 1,
  "name": "foo",
  "start_column": 5,
  "start_line": 1
}

Поля элемента function имеют следующее значение:

  • blocks: количество блоков в функции
  • blocks_executed: количество выполненных блоков функции
  • demangled_name: раскомпонованное имя функции
  • end_column: столбец в исходном файле, где заканчивается функция
  • end_line: строка в исходном файле, где заканчивается функция
  • execution_count: количество выполнений функции
  • name: имя функции
  • start_column: столбец в исходном файле, где начинается функция
  • start_line: строка в исходном файле, где начинается функция

Обратите внимание, что номера строк и столбцов начинаются с 1. В текущей реализации start_line и start_column не включают шаблонные параметры и возвращаемый тип, но, вероятно, это будет исправлено в будущем.

Каждый элемент line имеет следующий вид:

{
  "branches": ["$branch"],
  "count": 2,
  "line_number": 15,
  "unexecuted_block": false,
  "function_name": "foo",
}

Ветви присутствуют только с параметром -b. Поля элемента line имеют следующее значение:

  • count: количество выполнений строки
  • line_number: номер строки
  • unexecuted_block: флаг, указывающий, содержит ли строка невыполненный блок (не все операторы в строке были выполнены)
  • function_name: имя функции, к которой принадлежит эта строка (для строки с вложенными операторами может не быть задано)

Каждый элемент branch имеет следующий вид:

{
  "count": 11,
  "fallthrough": true,
  "throw": false
}

Поля элемента branch имеют следующее значение:

  • count: количество выполнений ветви
  • fallthrough: true, если ветвь является проходящей ветвью
  • throw: true, если ветвь является исключительной ветвью
-H
--human-readable

Записывает счётчики в удобочитаемом формате (например, 24,6k).

-k
--use-colors

Использует цвета для строк кода с нулевой покрываемостью. Мы используем красный цвет для обычных строк и голубой для исключительных. Те же цвета используются для базовых блоков с параметром -a.

-l
--long-file-names

Создаёт длинные имена файлов для включённых исходных файлов. Например, если файл заголовков x.h содержит код и был включён в файл a.c, то запуск gcov для файла a.c создаст выходной файл a.c##x.h.gcov вместо x.h.gcov. Это может быть полезно, если x.h включён в несколько исходных файлов, и вы хотите видеть отдельные вклады. Если вы используете параметр «-p», имена включающего и включаемого файлов будут полными путями.

-m
--demangled-names

Отображает раскомпонованные имена функций в выводе. По умолчанию отображаются составные имена функций.

-n
--no-output

Не создавать выходной файл gcov.

-o directory|file
--object-directory directory
--object-file file

Укажите либо директорию, содержащую файлы данных gcov, либо имя объекта. Файлы данных .gcno и .gcda ищутся с помощью этого параметра. Если указана директория, файлы данных находятся в этой директории и называются так же, как имя входного файла, без расширения. Если указан файл, файлы данных называются так же, как и этот файл, без расширения.

-p
--preserve-paths

Сохранить полную информацию о пути в именах созданных файлов .gcov. Без этого параметра используется только имя файла. С этим параметром используются все каталоги, при этом символы «/» заменяются символами «#», компоненты директории . удаляются, а компоненты .. переименовываются в «^». Это полезно, если исходные файлы находятся в нескольких разных директориях.

-q
--use-hotness-colors

Выводить цветной вывод, похожий на perf, для горячих строк. Легенда шкалы цветов печатается в самом начале выходного файла.

-r
--relative-only

Выводить только информацию об исходных файлах с относительным именем пути (после удаления префикса исходника). Абсолютные пути обычно относятся к системным заголовочным файлам, и покрытие любых встраиваемых функций в них, как правило, не представляет интереса.

-s directory
--source-prefix directory

Префикс для имён исходных файлов, подлежащих удалению при создании файлов выходного покрытия. Этот параметр полезен при построении в отдельной директории, когда путь к исходной директории не требуется при определении имён выходных файлов. Обратите внимание, что этот префикс проверяется до определения, является ли исходный файл абсолютным.

-t
--stdout

Выводить в стандартный вывод вместо выходных файлов.

-u
--unconditional-branches

При наличии вероятностей ветвления включать вероятности неусловных ветвлений. Неусловные ветви обычно не представляют интереса.

-v
--version

Отобразить номер версии gcov (в стандартном выводе) и завершить работу без дальнейшей обработки.

-w
--verbose

Печать подробных сообщений, связанных с базовыми блоками и дугами.

-x
--hash-filenames

При использовании –preserve-paths, gcov использует полный путь к исходным файлам для создания имени выходного файла. Это может привести к длинным именам файлов, которые могут превысить лимиты файловой системы. Этот параметр создаёт имена вида source-file##md5.gcov, где компонент source-file — конечная часть имени файла, а компонент md5 вычисляется из полного составного имени, которое в противном случае было бы использовано. Этот параметр является альтернативой –preserve-paths на системах с ограничением файловой системы.

gcov следует запускать с текущей директорией, совпадающей с той, в которой был вызван компилятор. В противном случае он не сможет найти исходные файлы. gcov создаёт файлы, называемые mangledname.gcov в текущей директории. Они содержат информацию о покрытии исходного файла, которому соответствуют. Один файл .gcov создаётся для каждого исходного (или заголовочного) файла, содержащего код, который был скомпилирован для создания файлов данных. Часть имени выходного файла mangledname обычно просто имя исходного файла, но может быть более сложной, если заданы параметры «-l» или «-p». Обратитесь к этим параметрам для получения подробностей.

Если вы вызываете gcov с несколькими входными файлами, вклады каждого входного файла суммируются. Обычно вы вызываете его со списком файлов, как окончательный этап компоновки вашего исполняемого файла.

Файлы .gcov содержат разделенные символом ‘:’ поля наряду с исходным кодом программы. Формат:

execution_count:line_number:source line text

Дополнительная информация о блоках может следовать за каждой строкой при запросе параметром командной строки. execution_count имеет значение ‘-’ для строк, не содержащих кода. Невыполненные строки помечаются «#####» или «=====», в зависимости от того, доступны ли они по обычным путям или только по исключительным путям, таким как обработчики исключений C++, соответственно. При использовании параметра «-a», невыполненные блоки помечаются «$$$$$» или «%%%%%», в зависимости от того, доступен ли базовый блок по обычным или исключительным путям. Выполненные базовые блоки, имеющие оператор с нулевым execution_count, оканчиваются символом ‘*’ и окрашиваются пурпурным цветом с параметром -k. Эта функция не поддерживается в Ada.

Обратите внимание, что GCC может полностью удалить тела функций, которые не нужны — например, если они везде инлайнены. Такие функции помечаются ‘-’, что может быть запутанно. Используйте параметры -fkeep-inline-functions и -fkeep-static-functions, чтобы сохранить эти функции и позволить gcov правильно отобразить их execution_count.

Некоторые строки информации в начале имеют номер_строки ноль. Эти строки преамбулы имеют вид

-:0:tag:value

Порядок и количество этих строк преамбулы будут увеличены по мере развития gcov — не полагайтесь на их неизменность. Используйте тег для поиска конкретной строки преамбулы.

Дополнительная информация блока имеет вид

tag information

Информация information предназначена для чтения человеком, но разработана достаточно просто для машинного анализа.

При печати процентов, 0% и 100% печатаются только тогда, когда значения точно равны 0% и 100% соответственно. Другие значения, которые обычно округляются до 0% или 100%, вместо этого печатаются как ближайшее неграничное значение.

При использовании gcov, необходимо предварительно скомпилировать программу с особым параметром GCC ‘--coverage’. Это сообщает компилятору сгенерировать дополнительную информацию, необходимую gcov (по существу, граф потоков программы), а также включает дополнительный код в объектные файлы для генерации дополнительной информации о профилировании, необходимой gcov. Эти дополнительные файлы размещаются в каталоге, где расположен объектный файл.

Запуск программы приведет к генерации выходных данных профиля. Для каждого исходного файла, скомпилированного с -fprofile-arcs, соответствующий файл .gcda будет помещен в каталог объектного файла.

Запуск gcov с именами исходных файлов вашей программы в качестве аргументов теперь создаст список кода вместе с частотой выполнения каждой строки. Например, если ваша программа называется tmp.cpp, вот что вы видите при использовании базовой gcov функции:

$ g++ --coverage tmp.cpp -c
$ g++ --coverage tmp.o
$ a.out
$ gcov tmp.cpp -m
File 'tmp.cpp'
Lines executed:92.86% of 14
Creating 'tmp.cpp.gcov'

Файл tmp.cpp.gcov содержит выходные данные gcov. Вот пример:

-:    0:Source:tmp.cpp
        -:    0:Working directory:/home/gcc/testcase
        -:    0:Graph:tmp.gcno
        -:    0:Data:tmp.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};
        -:   13:
        -:   14:template class Foo<int>;
        -:   15:template class Foo<char>;
        -:   16:
        -:   17:int
        1:   18:main (void)
        -:   19:{
        -:   20:  int i, total;
        1:   21:  Foo<int> counter;
        -:   22:
        1:   23:  counter.inc();
        1:   24:  counter.inc();
        1:   25:  total = 0;
        -:   26:
       11:   27:  for (i = 0; i < 10; i++)
       10:   28:    total += i;
        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
        -:   31:
        1:   32:  if (total != 45)
    #####:   33:    printf ("Failure\n");
        -:   34:  else
        1:   35:    printf ("Success\n");
        1:   36:  return 0;
        -:   37:}

Обратите внимание, что строка 7 показана в отчете несколько раз. Первое появление представляет общее количество выполнений строки, а следующие два относятся к случаям конструкторов класса Foo. Как вы также можете видеть, строка 30 содержит некоторые невыполненные базовые блоки, и поэтому количество выполнений имеет символ звездочки.

При использовании параметра -a, вы получите индивидуальные подсчёты блоков, и вывод будет выглядеть так:

-:    0:Source:tmp.cpp
        -:    0:Working directory:/home/gcc/testcase
        -:    0:Graph:tmp.gcno
        -:    0:Data:tmp.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};
        -:   13:
        -:   14:template class Foo<int>;
        -:   15:template class Foo<char>;
        -:   16:
        -:   17:int
        1:   18:main (void)
        -:   19:{
        -:   20:  int i, total;
        1:   21:  Foo<int> counter;
        1:   21-block  0
        -:   22:
        1:   23:  counter.inc();
        1:   23-block  0
        1:   24:  counter.inc();
        1:   24-block  0
        1:   25:  total = 0;
        -:   26:
       11:   27:  for (i = 0; i < 10; i++)
        1:   27-block  0
       11:   27-block  1
       10:   28:    total += i;
       10:   28-block  0
        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
        1:   30-block  0
    %%%%%:   30-block  1
        1:   30-block  2
        -:   31:
        1:   32:  if (total != 45)
        1:   32-block  0
    #####:   33:    printf ("Failure\n");
    %%%%%:   33-block  0
        -:   34:  else
        1:   35:    printf ("Success\n");
        1:   35-block  0
        1:   36:  return 0;
        1:   36-block  0
        -:   37:}

В этом режиме каждый базовый блок показан только в одной строке — последней строке блока. Многострочный блок будет вносить вклад только в счёт выполнения последней строки, и другие строки не будут показаны, как содержащие код, если предыдущие блоки не заканчиваются на этих строках. Общее количество выполнений строки показано, а последующие строки показывают количества выполнений отдельных блоков, которые заканчиваются на этой строке. После каждого блока будут показаны счёт ветвлений и вызовов блока, если задан параметр -b.

Из-за способа, которым GCC обрабатывает вызовы, счёт вызовов может быть показан после строки без отдельных блоков. Как вы можете видеть, строка 33 содержит базовый блок, который не был выполнен.

При использовании параметра -b, ваш вывод будет выглядеть так:

-:    0:Source:tmp.cpp
        -:    0:Working directory:/home/gcc/testcase
        -:    0:Graph:tmp.gcno
        -:    0:Data:tmp.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
function Foo<char>::Foo() called 0 returned 0% blocks executed 0%
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
function Foo<int>::Foo() called 1 returned 100% blocks executed 100%
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
function Foo<char>::inc() called 0 returned 0% blocks executed 0%
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
function Foo<int>::inc() called 2 returned 100% blocks executed 100%
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};
        -:   13:
        -:   14:template class Foo<int>;
        -:   15:template class Foo<char>;
        -:   16:
        -:   17:int
function main called 1 returned 100% blocks executed 81%
        1:   18:main (void)
        -:   19:{
        -:   20:  int i, total;
        1:   21:  Foo<int> counter;
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        -:   22:
        1:   23:  counter.inc();
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        1:   24:  counter.inc();
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        1:   25:  total = 0;
        -:   26:
       11:   27:  for (i = 0; i < 10; i++)
branch  0 taken 91% (fallthrough)
branch  1 taken 9%
       10:   28:    total += i;
        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:   31:
        1:   32:  if (total != 45)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:   33:    printf ("Failure\n");
call    0 never executed
branch  1 never executed
branch  2 never executed
        -:   34:  else
        1:   35:    printf ("Success\n");
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        1:   36:  return 0;
        -:   37:}

Для каждой функции печатается строка, показывающая, сколько раз функция вызывается, сколько раз она возвращается и какой процент блоков функции был выполнен.

Для каждого базового блока после последней строки базового блока печатается строка, описывающая ветвь или вызов, завершающий базовый блок. Для одной строки исходного кода может быть указано несколько ветвей и вызовов, если на этой строке заканчивается несколько базовых блоков. В этом случае ветви и вызовы обозначаются номерами. Нет простого способа сопоставить эти ветви и вызовы с конструкциями исходного кода. Однако, в целом, ветвь или вызов с наименьшим номером будут соответствовать наиболее левому конструкту на строке исходного кода.

Для ветви, если она была выполнена хотя бы один раз, будет напечатан процент, указывающий количество раз, когда ветвь была пройдена, делённое на количество раз, когда ветвь была выполнена. В противном случае печатается сообщение «никогда не выполнена».

Для вызова, если он был выполнен хотя бы один раз, будет напечатан процент, указывающий количество возвращений вызова, делённое на количество вызовов. Обычно это будет 100%, но может быть меньше для функций, которые вызывают exit или longjmp, и таким образом могут не возвращаться каждый раз, когда вызываются.

Счёт выполнения является кумулятивным. Если пример программы будет выполнен снова без удаления файла .gcda, счёт количества раз, когда каждая строка в исходном коде была выполнена, будет добавлен к результатам предыдущего(их) выполнения(й). Это потенциально полезно в нескольких аспектах. Например, это может использоваться для накопления данных в течение нескольких запусков программы в рамках набора тестов на проверку или для предоставления более точной долгосрочной информации в течение большого количества запусков программы.

Данные в файлах .gcda сохраняются непосредственно перед завершением программы. Для каждого исходного файла, скомпилированного с -fprofile-arcs, код профилирования сначала пытается прочитать существующий файл .gcda; если файл не соответствует исполняемому файлу (отличается количеством базовых блоков), он игнорирует содержимое файла. Затем он добавляет новые счётчики выполнения и, наконец, записывает данные в файл.

Далее: Gcov и оптимизация, Предыдущий: Введение в Gcov, Вверх: Gcov [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Invoking-Gcov.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API