Bug 21189

Summary: gprof doesn't work with code built with PIE
Product: binutils Reporter: Matthias Klose <doko>
Component: gprofAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: hjl.tools, leo, nickc
Priority: P2    
Version: 2.28   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Matthias Klose 2017-02-21 10:14:21 UTC
[forwarded from https://bugs.debian.org/854704]

"""
Since --enabled-default-pie was enabled in Debian for GCC 6, gprof no longer
works. I run a simple program compiled with default flags and gprof's output is
empty.

$ cat infloop.c
int main() {
    for(long i = 0; i < 1000000000; i ++) {}
    return 0;
}
$ gcc infloop.c -o infloop -pg
$ time ./infloop

real    0m2.067s
user    0m2.064s
sys     0m0.004s
$ gprof ./infloop | grep main
$

However, when I compile the same program with any earlier version of gcc, such
as gcc 5.4.1, or with the option -no-pie to disable PIE, it works.

$ gcc-5 infloop.c -o infloop -pg
$ rm gmon.out
$ time ./infloop

real    0m2.041s
user    0m2.036s
sys     0m0.000s
$ gprof ./infloop | grep main
101.41      2.06     2.06                             main
$ gcc -no-pie infloop.c -o infloop -pg
$ rm gmon.out
$ time ./infloop

real    0m2.019s
user    0m2.016s
sys     0m0.000s
$ gprof ./infloop | grep main
101.41      2.03     2.03                             main
$

This is the case for more complex programs too: gprof simply outputs nothing
other than the help-text. It looks like gcc is correctly generating the
gmon.out file, since it gets quite large and contains non-zero values.

Since GCC 6 moved to --enable-default-pie, all executables are of type DYN (not
EXEC), like shared libraries, and may be loaded at any base address. I suspect
this is breaking gprof's symbol lookup functionality. For instance, 0 is now a
valid address within the DYN ELF file. A good workaround for now is -no-pie,
but it would be great to get this fixed since Debian GCC now defaults to PIE.
"""
Comment 1 Nick Clifton 2017-02-22 11:29:03 UTC
Hi Matthias,

> Since --enabled-default-pie was enabled in Debian for GCC 6, gprof no longer
> works.

I think that this might be a glibc bug.  Specifically in their implementation of mcount() for PIE environments.

Running "gprof -d infloop | grep main" shows that main starts at address 0x860:

  [get_src_info] 0x860 -> infloop.c:1 (main)
  [core_create_function_syms] 15 main 0x860

And that it covers 0x2f bytes:

  [symtab_finalize] 0x860-0x88f	main

But, the data in the gmon.out file us using much higher addresses:

  [hist_read_rec] n_lowpc 0x4004e0 n_highpc 0x400718 ncnt 144

  [assign_samples] bin_low_pc=0x40063a, bin_high_pc=0x40063e, bin_count=18
  [assign_samples] bin_low_pc=0x40063e, bin_high_pc=0x400642, bin_count=38
  [assign_samples] bin_low_pc=0x400646, bin_high_pc=0x40064a, bin_count=82
  [assign_samples] total_time 138.000000

Of course I may be wrong - I am not an expert on gprof - but it does look to me like the contents of the gmon.out file are wrong.

Alternatively maybe gprof needs a way compute a starting address bias for PIE executables.

Cheers
  Nick
Comment 2 H.J. Lu 2017-02-22 16:48:52 UTC
The load address of PIE is determined at run-time and changes for
each run.  But the format of gmon.out doesn't support the changing load
address.
Comment 3 Nick Clifton 2017-02-22 17:34:13 UTC
(In reply to H.J. Lu from comment #2)
> The load address of PIE is determined at run-time and changes for
> each run.  But the format of gmon.out doesn't support the changing load
> address.

All the more reason then for mcount() to adjust its output in order to allow
for the run-time address bias.
Comment 4 account disabled by myself since useless 2022-07-29 00:20:47 UTC
I was affected by this problem. So (maybe) I'll figure something out.
Please kick me if you have any new information.

Rgs.
Comment 5 account disabled by myself since useless 2022-08-02 19:01:09 UTC
(In reply to Leo Yuriev from comment #4)
> I was affected by this problem. So (maybe) I'll figure something out.
> Please kick me if you have any new information.
> 
> Rgs.


Looking into the source code, I found that this problem has been fixed for a long time ;)


Please close this bug as dublicate of Bug 22284.
Comment 6 H.J. Lu 2022-08-02 19:23:50 UTC
This has been fixed in glibc.

*** This bug has been marked as a duplicate of bug 22284 ***