I've created my DLL using -pg option (compilation and link), and managed to run its code and to call exit at some point.
A file gmon.out is created, so far so good.
But when I do
gprof mydll.dll gmon.out
no useful information is printed.
When I do the same thing with an executable it works properly and I get the timing & count information all right.
Why is this happening on my DLL ?
(This question has been asked several times several years/decades ago but remained unanswered)
Actually, gprof can do that. The issue it's encountering is that addresses in the DLL are different from the ones that are recorded in the
gmon.outfile.On an executable, the (virtual) address is fixed, but on DLLs it is not. Don't ask me if it's because of ASLR or something else, but it complexifies post-mortem debugging a lot.
Plus the fact that the
gmon.outfile format isn't documented, or that there is a documented format but it doesn't match what we were getting.But we kind of figured it out...
There's a header, then a lot of zeroes, then data in the end. I don't know about a lot of data but the knowledge I got is enough to convert the gmon.out file into an useable one.
First, you have to print the address of your DLL entrypoint symbol when starting the program, and compare it to the static value given by
nmLet's say your entrypoint is
_entry. In your program (for example C) just do:Then use
nmon the DLL (which must have symbols) to get the static value. On Windows:Let's say you get
0x1F000000for the static value and0x6F000000for the run-time (printed) value. Then you have a0x50000000offset that you must apply (subtract) to yourgmon.outbinary file.So basically the format is pretty simple:
In the following real-life example I have highlighted the 3 first longwords:
0x10121450)0x1357E590)0x1A2E8C0)Now the start of the data, note that the offset matches (before the data offset there are only zeroes, probably some room for some more data)
Now we have to apply the offset computed/printed when running the code so the addresses from
gmon.outmatch the addresses from the DLLHow to do that? it's pretty easy with some python script. The concept:
The aim is to add the address shift to the header addresses and all the addresses of the chunks, leaving the rest of the data unchanged.
The script, everything is hardcoded but you get the idea
now:
Doing that allows to decode the gmon file against the DLL, since the addresses are now corrected to match the static addresses contained in the DLL.