Последовательность вызовов функций в C - PullRequest
0 голосов
/ 17 марта 2012

Я хочу увидеть поток кода базовой программы, такой как ниже.

#include<stdio.h>
int main ()
{
    FILE *fptr = fopen("/mnt/myfilesystem/test.txt", "r");
    if(fptr) {
        printf("open successful\n");
        fclose(fptr);
    }
    else
        printf("open failed\n");

    return 0;
}

Я хочу увидеть полную последовательность вызовов функций, выполняемых при запуске этой программы. Я пытался использовать strace и ptrace, но они перечисляют только системные вызовы :( Любые предложения о том, как это можно сделать?

Заранее спасибо !!

Ответы [ 6 ]

5 голосов
/ 17 марта 2012

Вы можете использовать gnu profiler gprof .

Скомпилируйте его (main.cc) с -pg флажками:

gcc -pg main.cc -o main

Затем выполните его (./main). Ваш двоичный файл создаст файл (gmon.out). Затем вы можете получить трассировку, используя gprof:

gprof main gmon.out

с вашим примером я получаю:

index % time    self  children    called     name
                0.00    0.00       1/1           __do_global_ctors_aux [9]
[7]      0.0    0.00    0.00       1         global constructors keyed to main [7]
                0.00    0.00       1/1           __static_initialization_and_destruction_0(int, int) [8]
-----------------------------------------------
                0.00    0.00       1/1           global constructors keyed to main [7]
[8]      0.0    0.00    0.00       1         __static_initialization_and_destruction_0(int, int) [8]

это не так много информации, потому что ваше приложение не сложное.

Если вы хотите отслеживать системные вызовы, попробуйте strace ./main. Вывод длинный, вы увидите все системные вызовы:

execve("", [""], [/* 26 vars */]) = 0
brk(0)                                  = 0x877f000
access("", F_OK)      = -1 ENOENT
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7748000
access("", R_OK)      = -1 ENOENT
open("", O_RDONLY) = -1 ENOENT
open("", O_RDONLY) = -1 ENOENT
stat64("", 0xbfdc4a18) = -1 ENOENT
open("", O_RDONLY) = -1 ENOENT
stat64("", {st_mode=S_IFDIR|0755, st_size=6104, ...}) = 0
open("", O_RDONLY) = -1 ENOENT
open("", O_RDONLY)      = 3
....
3 голосов
/ 17 марта 2012

Звучит так, как вы хотите ltrace .

2 голосов
/ 17 марта 2012

Речь идет не о трассировке вызова, на которую уже дан ответ, но я думаю, что в коде есть ошибка, возможно, поэтому вы и спрашиваете.

close должно быть fclose, чтобы соответствовать fopen

close для файловых дескрипторов, а не FILE*, который возвращается fopen

0 голосов
/ 18 марта 2012

Когда вы компилируете для профилирования, используя -pg, компилятор автоматически вставляет вызов функции с именем mcount.Эта функция предоставляется специальной библиотекой и создает базу данных всех вызовов (с адресом from-to-address и счетчиком).

Однако, если вы предоставляете свою собственную функцию mcount (будьте осторожны не для компиляции с включенным профилированием!) Он может делать все что угодно.

Я не проверял это, и я не знаю, каковы параметры mcount (хотя я 'Я уверен, что это не так уж сложно выяснить), но пример реализации может выглядеть следующим образом:

void mcount (void *to)
{
  void *from = __builtin_return_address ();
  printf ("call from %p to %p\n", from, to);
}

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

Однако есть проблема: он считает только те функции, которые были скомпилированы с включенным профилированием, и этот , вероятно, не включает функции библиотеки C, такие как printf.

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

0 голосов
/ 17 марта 2012

статически компилировать и дизассемблировать.

0 голосов
/ 17 марта 2012

У вас есть доступ к компьютеру Mac, Solaris или FreeBSD?

Все они имеют DTrace, и с помощью соответствующего поставщика вы можете отслеживать практически все, что захотите.Если у вас есть доступ к машине с одной из этих ОС, взгляните на руководство пользователя dtrace (желательно найти загружаемый файл в формате pdf)

Это может дать вам скрипт, который дает трассировку программы:http://www.dtracebook.com/index.php/Applicationsили http://www.brendangregg.com/dtrace.html

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