-1

Let's say I have a program (program.c) that uses rand function in standard C library.

1 #include <stdlib.h>
2 int main(){
3     int rand_number = rand();
4 }

I also have a shared library (intercept.c) that I created to change the behaviour of rand function (simply adds +1 to the result) in the standard library.

int rand(void){
    int (*rand_func)();
    rand_func = dlsym(RTLD_NEXT, "rand");
    int result = (*rand_func)();
    return result + 1;
}

And I run the program with

LD_PRELOAD=./intercept.so ./program

Is there any way to get the line number (Line 3) and name of the caller function (main) without modifying the program.c's source code?

M.Soyturk
  • 340
  • 3
  • 14
  • 1
    The C standard does not provide any facility for this. If the program is compiled with debugging information, it may be possible to get this information from it. That is somewhat complicated and is unlikely to be worth the effort required. – Eric Postpischil Feb 21 '21 at 14:41
  • before using `rand()`, use something to seed the random number generator, similar to: `#include ` and `srand( (unsigned)time( NULL) );` – user3629249 Feb 22 '21 at 18:17
  • @user3629249 Fully functioning rand function is not important in this context. I put it just to be an example. – M.Soyturk Feb 23 '21 at 07:34

3 Answers3

3

It is not immediate, but you can use backtrace() in order to obtain each frame in the call stack. Then invoking the external command eu-addr2line -f -C -s --pretty-print -p your_pid the_previous_frames... (with popen() or pipe()/fork()/dup2()/exec()...) and parsing its output will provide the information you need (if compiled with -g).

prog-fh
  • 13,492
  • 1
  • 15
  • 30
  • I don't have any control over the program.c. So, I don't know whether it was compiled with -g or not. – M.Soyturk Feb 23 '21 at 07:35
  • @M.Soyturk And with the binary obtained from `program.c` *as is*, did you try this approach? Of course `backtrace()` must be used in *your* code (`intercept.c`) and maybe `eu-addr2line` will give you something if the debug information are present *by chance* in the original program. By the way, what is the point of obtaining a call-stack and line numbers for a code you have no control over? – prog-fh Feb 23 '21 at 08:09
  • I did but I was not able to get the line number. I am trying to develop a collective communication profiling tool and I thought that showing the line number and stacktrace would be a good addition for productivity. Thanks for the answer. – M.Soyturk Feb 23 '21 at 08:43
0

regarding:

Is there any way to get the line number (Line 3) and name of the caller function (main) without modifying the program.c's source code?

compile the program with the -ggdb3 option, Then set a break point where you want to stop the program. Then use the backtrace command bt. This will show the function names, the line numbers, etc

user3629249
  • 16,402
  • 1
  • 16
  • 17
  • I don't have any control over the program.c. So, I don't know which flags were used while compiling program.c – M.Soyturk Feb 23 '21 at 07:36
0

Another (Linux specific) approach is to compile everything with -g (perhaps also -O) using GCC and to use Ian Taylor's excellent libbacktrace.

That library parses the DWARF debug information and knows line numbers.

You'll need several hours to understand libbacktrace (read carefully the header file). I am using it in RefPerSys

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547