Bug 11804 - Fix -Wl,-z,relro gcore writer (+maybe reader)
Summary: Fix -Wl,-z,relro gcore writer (+maybe reader)
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: corefiles (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Jan Kratochvil
URL:
Keywords:
: 9904 (view as bug list)
Depends on:
Blocks: 16981
  Show dependency treegraph
 
Reported: 2010-07-10 21:14 UTC by Jan Kratochvil
Modified: 2014-05-25 09:24 UTC (History)
4 users (show)

See Also:
Host:
Target: x86_64-unknown-linux-gnu
Build:
Last reconfirmed:


Attachments
gcore reader fix; maybe not needed. (496 bytes, patch)
2010-07-10 21:15 UTC, Jan Kratochvil
Details | Diff
Preliminary fix (merged two parts). (4.87 KB, patch)
2010-08-16 17:22 UTC, Jan Kratochvil
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Kratochvil 2010-07-10 21:14:33 UTC
Core files for -Wl,-z,relro generated by:
kernel-2.6.33.5-124.fc13.x86_64
kernel-xen-2.6.18-194.8.1.el5.x86_64
works correctly because:
Roland McGrath:
------------------------------------------------------------------------------
The kernel's default rules dump any MAP_PRIVATE file mapping that has
actually been modified (i.e. COW performed), so you should always have
.dynamic and all other parts of any data sgements that were written to,
regardless of their page protections at the time of the dump.
------------------------------------------------------------------------------

Core files generated by GDB gcore do not contain page containing DYNAMIC
containing DT_DEBUG pointing at _r_debug, therefore GDB cannot later find out
the shared library list.

(a) Fix gcore:
Roland McGrath:
------------------------------------------------------------------------------
gdb/gcore could do something similar from userland if it looks at
/proc/pid/smaps.  I think you can say that any non-shared mapping listed
with either Private_Dirty or Swap nonzero is one's that's been written to.
But we should probably double-check with the kernel VM people.
------------------------------------------------------------------------------

(b) We can possibly make GDB compatible even with current broken gcore by
    a hack depending on unique `_r_debug' symbol.  [patch attached]
Comment 1 Jan Kratochvil 2010-07-10 21:15:16 UTC
Created attachment 4878 [details]
gcore reader fix; maybe not needed.
Comment 2 Jan Kratochvil 2010-08-16 17:20:29 UTC
Comment on attachment 4878 [details]
gcore reader fix; maybe not needed.

The patch cannot work.
Comment 3 Jan Kratochvil 2010-08-16 17:22:55 UTC
Created attachment 4934 [details]
Preliminary fix (merged two parts).
Comment 4 Jan Kratochvil 2010-08-30 09:16:10 UTC
Post:
[patch] Code cleanup: Make function typedef for find memory region
http://sourceware.org/ml/gdb-patches/2010-08/msg00498.html
[patch] Fix gcore writer for -Wl,-z,relro (PR corefiles/11804)
http://sourceware.org/ml/gdb-patches/2010-08/msg00499.html
Comment 5 Richard Biener 2010-08-31 11:26:54 UTC
Hm, it doesn't seem to work reliably for me (it works for dumping core of
/bin/sleep).  If I dump core of a running /usr/lib/postfix/qmgr on load
I get

# gdb /usr/lib/postfix/qmgr
Reading symbols from /usr/lib/postfix/qmgr...Missing separate debuginfo for
/usr/lib/postfix/qmgr
Try: zypper install -C
"debuginfo(build-id)=a67933b04330530f5e80941c968ba3623b1fd5ac"
(no debugging symbols found)...done.
(gdb) set debug solib
(gdb) set verbose
(gdb) core core.4529
svr4_current_sos: exec_bfd /usr/lib/postfix/qmgr
elf_locate_base: found program entry address 0x7fac68ab63a0 for
/usr/lib/postfix/qmgr
elf_locate_base: expected relocation offset 0x7fac68ab2000 for /usr/lib/postfix/qmgr
elf_locate_base: .dynamic section found in /usr/lib/postfix/qmgr
elf_locate_base: .dynamic addr 0x20fbc0
elf_locate_base: read in .dynamic section
elf_locate_base: tag at offset 0x0 is not readable, dropping relocation offset
0x7fac68ab2000
elf_locate_base: found program entry address 0x7fac68ab63a0 for
/usr/lib/postfix/qmgr
elf_locate_base: expected relocation offset 0x7fac68ab2000 for /usr/lib/postfix/qmgr
elf_locate_base: .dynamic section found in /usr/lib/postfix/qmgr
elf_locate_base: .dynamic addr 0x20fbc0
elf_locate_base: read in .dynamic section
elf_locate_base: tag at offset 0x0 is not readable, dropping relocation offset
0x7fac68ab2000
elf_locate_base: unrelocated ptr addr 0x20fd18
elf_locate_base: relocated ptr addr 0x20fd18 (relocation offset 0x0) for
/usr/lib/postfix/qmgr
elf_locate_base: Tag entry has value 0x0 -- return now
svr4_current_sos: no DT_DEBUG found in /usr/lib/postfix/qmgr -- return now

the program address looks good, the .dynamic section in the running process
is mapped like

7fac68cc1000-7fac68cc2000 r--p 0000f000 08:06 360346                     /usr/li
b/postfix/qmgr
Size:                  4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         4 kB
Private_Dirty:         0 kB
Referenced:            4 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
7fac68cc2000-7fac68cc3000 rw-p 00010000 08:06 360346                     /usr/li
b/postfix/qmgr
Size:                  4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
7fac68cc3000-7fac68cfe000 rw-p 00000000 00:00 0                          [heap]

thus the relocated address should be not in the core file but taken from
/usr/lib/postfix/qmgr - but that fails.  Is this not available at this point
or where do I need to dig?  I'm not too familiar with the gdb codebase...
Comment 6 Richard Biener 2010-08-31 11:45:13 UTC
Hm, it _is_ in the core-file:

Save segment, 4096 bytes at 0x7fac68cc1000 (r  ) for                     
/usr/lib/postfix/qmgr
Save segment, 4096 bytes at 0x7fac68cc1000
Comment 7 Richard Biener 2010-08-31 11:52:46 UTC
And in the core file:

  [67] load              NOBITS           00007fac68cc1000  000ed558
       0000000000001000  0000000000000000   A       0     0     1
Comment 8 Richard Biener 2010-08-31 12:07:59 UTC
The executable is built with -fPIE, but there seem to be relocations in the
respective page:

Relocation section '.rela.dyn' at offset 0x25d0 contains 133 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000020f740  000000000008 R_X86_64_RELATIVE                    000000000000d96e
00000020f760  000000000008 R_X86_64_RELATIVE                    000000000000bf88
...
00000020fb10  008e00000001 R_X86_64_64       00000000002103e0 var_dest_rate_dela
y + 0
00000020fb50  008a00000001 R_X86_64_64       0000000000210400 var_defer_xports +
 0
00000020fb70  008000000001 R_X86_64_64       0000000000210438 var_conc_pos_feedb
ack + 0
00000020fb90  00ac00000001 R_X86_64_64       00000000002103f8 var_conc_neg_feedb
ack + 0
00000020fe38  000b00000006 R_X86_64_GLOB_DAT 0000000000000000 var_daemon_timeout
 + 0
Comment 9 Richard Biener 2010-08-31 12:52:03 UTC
In my gdb copy (7.0 based), the following looks suspicious:

    if (dyn_tag == dyntag)
      {
        /* If requested, try to read the runtime value of this .dynamic
           entry.  */
        if (ptr)
          {
            gdb_byte ptr_buf[8];
            CORE_ADDR ptr_addr;
            int got;

            ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;

                                                  ^^^^^^^^^^^^^^^^^

            if (ptr != NULL)
              {
                if (debug_solib)
                  fprintf_unfiltered (gdb_stdlog,
                                      "elf_locate_base: unrelocated ptr addr %s\n",
                                      paddress (target_gdbarch, ptr_addr));


I can see the dynamic section contents just fine at dyn_addr + (buf - bufstart).
OTOH a recent 7.1 tree looks much different (but has the same logic and
also doesn't work for me - but it lost the nice debugging stuff).
Comment 10 Richard Biener 2010-08-31 13:31:02 UTC
Hm.  The .dynamic section in memory is different from that in the file-backing
(at least DT_DEBUG has been filled in by the dynamic loader).  But still the
page is marked clean in /proc/smaps.
Comment 11 Jan Kratochvil 2010-08-31 14:06:27 UTC
(In reply to comment #7)
> And in the core file:
>   [67] load              NOBITS           00007fac68cc1000  000ed558
>        0000000000001000  0000000000000000   A       0     0     1

Not sure what you have meant but there is NOBITS, therefore it is _not_ present
in the core file.

(In reply to comment #9)
> OTOH a recent 7.1 tree looks much different (but has the same logic and
> also doesn't work for me - but it lost the nice debugging stuff).

Sorry but I am not going to support the former Jeff Johnston's PIE patch magic.
Also there were some post-7.1 PIE fixes, suggesting just to use FSF GDB HEAD as
there will be even still one PIE bug in FSF GDB 7.2.
http://sourceware.org/ml/gdb-patches/2010-07/msg00237.html


(In reply to comment #10)
> Hm.  The .dynamic section in memory is different from that in the file-backing
> (at least DT_DEBUG has been filled in by the dynamic loader).  But still the
> page is marked clean in /proc/smaps.

I have tested this on Fedora14snapshot + kernel-2.6.33.6-147.fc13.x86_64
and it works for me.

./gdb -nx /usr/libexec/postfix/qmgr
GNU gdb (GDB) 7.2.50.20100831-cvs
[...]
This GDB was configured as "x86_64-unknown-linux-gnu".
[...]
Reading symbols from /usr/libexec/postfix/qmgr...(no debugging symbols
found)...done.
(gdb) start
Temporary breakpoint 1 at 0x8ae0
Starting program: /usr/libexec/postfix/qmgr
[Thread debugging using libthread_db enabled]
Temporary breakpoint 1, 0x00007ffff7fbdae0 in main ()
(gdb) info files
        `/usr/libexec/postfix/qmgr', file type elf64-x86-64.
[...]
        0x00007ffff81ff940 - 0x00007ffff81ffba0 is .dynamic

7ffff81fe000-7ffff8200000 r--p 00049000 fd:01 6523997                   
/usr/libexec/postfix/qmgr
Size:                  8 kB
Rss:                   8 kB
Pss:                   8 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         8 kB
Referenced:            8 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB

unpatched:
  [92] load              NOBITS          00007ffff81fe000 115dec 002000 00   A 
0   0  1

patched:
  [92] load              PROGBITS        00007ffff81fe000 002000 00   A  0   0  1

Thanks for the testing, though.

From your dumps I believe your .dynamic was at 0x7fac68cc1bc0 and its DT_DEBUG
was at 0x7fac68cc1d18 which would suggest there is some problem in Linux
kernel's content of /proc/PID/smaps.
Comment 12 Richard Biener 2010-08-31 14:10:25 UTC
> (In reply to comment #10)
> > Hm.  The .dynamic section in memory is different from that in the file-backing
> > (at least DT_DEBUG has been filled in by the dynamic loader).  But still the
> > page is marked clean in /proc/smaps.
> 
> I have tested this on Fedora14snapshot + kernel-2.6.33.6-147.fc13.x86_64
> and it works for me.
> 
> ./gdb -nx /usr/libexec/postfix/qmgr
> GNU gdb (GDB) 7.2.50.20100831-cvs
> [...]
> This GDB was configured as "x86_64-unknown-linux-gnu".
> [...]
> Reading symbols from /usr/libexec/postfix/qmgr...(no debugging symbols
> found)...done.
> (gdb) start
> Temporary breakpoint 1 at 0x8ae0
> Starting program: /usr/libexec/postfix/qmgr
> [Thread debugging using libthread_db enabled]
> Temporary breakpoint 1, 0x00007ffff7fbdae0 in main ()
> (gdb) info files
>         `/usr/libexec/postfix/qmgr', file type elf64-x86-64.
> [...]
>         0x00007ffff81ff940 - 0x00007ffff81ffba0 is .dynamic
> 
> 7ffff81fe000-7ffff8200000 r--p 00049000 fd:01 6523997                   
> /usr/libexec/postfix/qmgr
> Size:                  8 kB
> Rss:                   8 kB
> Pss:                   8 kB
> Shared_Clean:          0 kB
> Shared_Dirty:          0 kB
> Private_Clean:         0 kB
> Private_Dirty:         8 kB
> Referenced:            8 kB
> Swap:                  0 kB
> KernelPageSize:        4 kB
> MMUPageSize:           4 kB
> 
> unpatched:
>   [92] load              NOBITS          00007ffff81fe000 115dec 002000 00   A 
> 0   0  1
> 
> patched:
>   [92] load              PROGBITS        00007ffff81fe000 002000 00   A  0   0  1
> 
> Thanks for the testing, though.
> 
> From your dumps I believe your .dynamic was at 0x7fac68cc1bc0 and its DT_DEBUG
> was at 0x7fac68cc1d18 which would suggest there is some problem in Linux
> kernel's content of /proc/PID/smaps.

Yeah - I've bounced it to our kernel folks.  New started processes work fine,
but a lot of old processes on my system have lost the dirty bits in
/proc/smaps ... let's see what their response will be.
Comment 13 Jan Kratochvil 2010-09-09 21:40:32 UTC
(In reply to comment #12)
> Yeah - I've bounced it to our kernel folks.

Any follow-up would be great, before pinging it for FSF GDB, thanks.
Comment 14 Jan Kratochvil 2012-07-28 06:19:18 UTC
*** Bug 9904 has been marked as a duplicate of this bug. ***
Comment 15 Jan Kratochvil 2012-07-28 07:06:53 UTC
[PATCH] refreshed patch for PR 11804 and PR 9904
http://sourceware.org/ml/gdb-patches/2012-07/msg00249.html
From: Jean-Marc Saffroy <saffroy at gmail dot com>
Comment 16 Sourceware Commits 2012-08-07 13:26:39 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	jkratoch@sourceware.org	2012-08-07 13:26:33

Modified files:
	gdb            : ChangeLog defs.h fbsd-nat.c gcore.c gnu-nat.c 
	                 linux-tdep.c procfs.c 
	gdb/testsuite  : ChangeLog 
Added files:
	gdb/testsuite/gdb.base: gcore-relro-lib.c gcore-relro-main.c 
	                        gcore-relro.exp 

Log message:
	gdb/
	PR 11804
	* defs.h (find_memory_region_ftype): New comment.  New arg modified.
	* fbsd-nat.c (fbsd_find_memory_regions): Add the passed modified value.
	* gcore.c (gcore_create_callback): New function comment.  Add modified
	parameter.  Only write modified regions.  Set SEC_READONLY exactly
	according to MODIFIED.
	(objfile_find_memory_regions): Ignore separate debug info files.  Ass
	the passed modified value to FUNC.
	* gnu-nat.c (gnu_find_memory_regions): Add the passed modified value.
	* linux-tdep.c (linux_find_memory_regions): Try to reads smaps file
	first.  New variables modified and has_anonymous.  Parse the lines of
	smaps file.  Add the passed MODIFIED value to FUNC.
	* procfs.c (find_memory_regions_callback): Add the passed modified
	value.
	
	gdb/testsuite/
	PR 11804
	* gdb.base/gcore-relro.exp: New file.
	* gdb.base/gcore-relro-main.c: New file.
	* gdb.base/gcore-relro-lib.c: New file.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.14563&r2=1.14564
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/defs.h.diff?cvsroot=src&r1=1.320&r2=1.321
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/fbsd-nat.c.diff?cvsroot=src&r1=1.26&r2=1.27
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/gcore.c.diff?cvsroot=src&r1=1.52&r2=1.53
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/gnu-nat.c.diff?cvsroot=src&r1=1.79&r2=1.80
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/linux-tdep.c.diff?cvsroot=src&r1=1.21&r2=1.22
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/procfs.c.diff?cvsroot=src&r1=1.159&r2=1.160
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&r1=1.3328&r2=1.3329
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/gcore-relro-lib.c.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/gcore-relro-main.c.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/gcore-relro.exp.diff?cvsroot=src&r1=NONE&r2=1.1
Comment 17 Jan Kratochvil 2012-08-07 13:27:59 UTC
Checked in.