📄 readme
字号:
etrace: A run-time tracing tool-------------------------------These source files comprise a simple but efficient utility that allows thedisplay of a function call tree in a C program at run-time. It is alsopossible to dump the results of a program execution to an ASCII file forlater examination.* ptrace.c compiles your code to enable this run-time tracing* etrace is a Python script that will perform the run-time tracing bydisplaying the function names as they are called* etrace.pl is a Perl script that will perform the run-time tracing bydisplaying the function names as they are called. Moreover, etrace.plcan be used to trace dynamic libraries.License-------This is free software placed in the public domain. Enjoy!Pre-requisites--------------- gcc version 2.95 or later.- The presence of the 'nm' utility on your machine, with a compatible BSD output.- Python 1.5 or later (for etrace) or Perl (for etrace.pl).Portability-----------This code is known to run under Linux, FreeBSD, Solaris, and HPUX.Example using etrace--------------------There is an example in the example/ sub-dir. To compile it, do: % cd example % makeYou should now have an executable called "crumble". Running it should giveyou a recipe for an apple crumble, with 1-second pauses between sentencesto demonstrate the run-time ability. Now let's get to this function calltree:To get the tree at run-time, open two terminals.In the first terminal: % cd etrace/example % ../src/etrace crumbleIn the second terminal: % cd etrace/example % crumbleBoth terminals need to be in the same directory. Data are exchanged betweenthe running process you are trying to monitor and the 'etrace' scriptthrough a named pipe in this directory.You should see this: main | Crumble_make_apple_crumble | | Crumble_buy_stuff | | | Crumble_buy | | | Crumble_buy (total: 5 times) | | Crumble_prepare_apples | | | Crumble_skin_and_dice | | Crumble_mix | | Crumble_finalize | | | Crumble_put | | | Crumble_put (total: 2 times) | | Crumble_cook | | | Crumble_put | | | Crumble_bakeTo get the tree into a file for later use, do the following: % cd etrace/example % touch TRACE % crumble % ../src/etrace crumble > logThe trace has been saved to a file called 'log' in the current directory.Example using etrace.pl-----------------------There is an example in the example/ sub-dir. To compile it, do: % cd example % makeYou should now have an executable called "crumble". Running it should giveyou a recipe for an apple crumble, with 1-second pauses between sentencesto demonstrate the run-time ability. Now let's get to this function calltree:To get the tree at run-time, open two terminals.In the first terminal: % cd etrace/example % ../src/etrace.pl crumbleIn the second terminal: % cd etrace/example % crumbleBoth terminals need to be in the same directory. Data are exchanged betweenthe running process you are trying to monitor and the 'etrace' scriptthrough a named pipe in this directory.You should see this:\-- main| \-- Crumble_make_apple_crumble| | \-- Crumble_buy_stuff| | | \-- Crumble_buy| | | \-- Crumble_buy| | | \-- Crumble_buy| | | \-- Crumble_buy| | | \-- Crumble_buy| | \-- Crumble_prepare_apples| | | \-- Crumble_skin_and_dice| | \-- Crumble_mix| | \-- Crumble_finalize| | | \-- Crumble_put| | | \-- Crumble_put| | \-- Crumble_cook| | | \-- Crumble_put| | | \-- Crumble_bakeTo get the tree into a file for later use, you can do the following: % cd etrace/example % touch TRACE % crumble % ../src/etrace.pl crumble > logor % cd etrace/example % touch TRACE % crumble % ../src/etrace.pl crumble TRACE > logEither way, the trace has been saved to a file called 'log' in thecurrent directory.To see how to modify ptrace.c to work with a dynamic library, look atthe example2 directory. The sources there also create a stand-aloneexecutable, but the PTRACE_REFERENCE_FUNCTION macro is defined just asit would be for a dynamic library.How does it work?-----------------gcc 2.95 has a nifty feature called "instrument-functions", that adds acouple of function calls to all functions in your code. Every time afunction starts, a function called __cyg_profile_func_enter() is called,and every time a function exits, a function called__cyg_profile_func_exit() is called.The code in ptrace.c simply redirects the information gathered at each callto a text file.Now, if you examine closely what you get from this output, you will seethat only the binary addresses of functions are printed out. To make thelink to true function names, you need to interpret the binary and make thelist of associations. There are many ways of doing this, and to be trulyplatform-independent you should have a look at the BFD library from the GNUproject.etrace implements a much simpler (but of course much less portable)solution by using the 'nm' utility to dump a list of all defined symbolsand associated addresses. The link between them and the pretty printing asa function call tree is all done in the 'etrace' script.etrace.pl works in a manner similarly to etrace. Up to outputpretty-printing, it works the same as etrace on stand-aloneprograms. If the first line of the TRACE file is marked "REFERENCE",however, it uses the values provided to calculate where the referencefunction actually resides in memory, and compares the differencebetween that address and the address in the symbol table; this offsetis then applied to all the function addresses in the trace. Thisfeature is enabled by defining the PTRACE_REFERENCE_FUNCTION inptrace.c and is essential to correctly map the function names whentracing a dynamic library (this feature is optional for stand-aloneprograms).ptrace/etrace usage-------------------The ptrace.c module will look for a file called "TRACE" in the currentdirectory. If no such file can be found, nothing will be logged. You stillget the penalty associated to the two function calls but nothing elsechanges.If a TRACE file can be found, log data will be appended to it.The idea is to make the TRACE file a fifo so that another process can readfrom it and display the informations at run-time. This is exactly what the'etrace' script does. You do not have to create the fifo yourself, one willbe created upon startup of 'etrace', and will be deleted afterwards.'etrace' needs to know the name of the executable you are trying to trace,to retrieve the symbols (with 'nm'). This is the only argument to thescript.'etrace.pl' takes two arguments. The first argument, which ismandatory, is either the name of the executable you want to trace, orthe name of the symbol file (produced by nm) of the executable youwant to trace. The second argument, which is optional, is either thename of the trace file produced by ptrace (if you want to see thefunction calls after the program has finished running) or the name touse for the FIFO (in which case you will need to make sure ptrace.cwrites to a file with that same name).How to use it in your code--------------------------To trace a stand-alone program, there is no need to #include anyadditional file. Just link your code against ptrace.c and use the-finstrument-functions option as a compile option for gcc. This shoulddo it.Now when you want to trace at run-time (handy to see where the code breaksin case of segfault), open two terminals. Launch first 'etrace myprogram'in one terminal, and 'myprogram' in the other. Remember both need to be inthe same directory for the magic to work.If you want to log the trace to a file, create an empty file called TRACEin the current directory, launch your program, and examine the resultsusing 'etrace myprogram'.If you want to trace a library, you need to provide ptrace.c with thename of a reference function. The name and address of this function,once loaded, will be the first line output to the trace file, and willbe used by etrace.pl to correctly map the function pointers to thesymbol names. To provide ptrace.c with the reference function, simplyset the macro PTRACE_REFERENCE_FUNCTION to the name of a function inyour library. You may #include any header files needed to make thisfunction visible in the "User Macros" section of ptrace.c.How to modify it----------------If you do not like the name of the trace file (TRACE) you can actuallyrename that both in ptrace.c and etrace. You could also use a dynamic filename but you need then a way of exchanging the file name between bothprocesses.If you prefer, you could have ptrace.c redirect its output to a socket andetrace retrieve it as a client. This would substantially increase theamount of code but could be interesting for remotely debugging anapplication.The output of your 'nm' command might slightly change from the BSD standard(identical to Linux, Solaris, and to some extent to the HPUX output). Youwill need to modify the simplistic parser implemented in 'etrace' to handlethese changes.You could also use the tracing feature to have 'ptrace.c' send many moreinformations through the line, like memory allocations, file operations,etc. This might make the output somewhat harder to read and is mostprobably better handled by a debugger.Well anyway, this is just one possible use of the function instrumentationfeature of gcc 2.95. Thanks to the gcc team for this VERY useful tool!Feedback--------Feedback is always welcome.However, this code is not supported. This is only 80 lines of Python and100 lines of C, so if you need additional features I'd say you are betteroff on your own. :-)N. DevillardWed May 9 15:29:04 CEST 2001V. ChudnovskyMon Mar 8 2004
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -