[2/2] Documentation and testcase

Message ID 87wq283gmx.fsf@redhat.com
State New, archived
Headers

Commit Message

Sergio Durigan Junior March 22, 2015, 8:45 p.m. UTC
  On Friday, March 20 2015, Pedro Alves wrote:

> On 03/20/2015 09:03 PM, Sergio Durigan Junior wrote:
>>> > If not (I assume not), we could test that by loading the core
>>> > into gdb, but _not_ the program, and then disassembling a function's
>>> > address.  It should fail.  Then load the program and disassemble
>>> > again.  It should work now.  Or something along those lines.
>> Hm, OK.  I guess I will try this approach, and if it doesn't happen then
>> I will see about doing a regular file-backed mapping.
>
> Thanks.  If that approach doesn't work (for some odd reason), let's
> try to come up with another approach that still makes sure that the
> program's .text is not dumped, instead of mapping some other file.
> It's important that we don't regress that specifically.

So, here's what I came up with.  I decided to submit it here, and not
create another revision of the patch series.  Hope that's not a
problem.  (I can certainly send a separate series if you want).

I am now creating corefiles that exclude the file-backed bits as well,
and testing according to your instructions.  I tried to make it as clear
as possible in the .exp code.

WDYT?
  

Comments

Pedro Alves March 23, 2015, 8:27 p.m. UTC | #1
On 03/22/2015 08:45 PM, Sergio Durigan Junior wrote:

> +# We do not do file-backed mappings in the test program, but it is
> +# important to test this anyway.  One way of performing the test is to
> +# load GDB with a corefile but without a binary, and then ask for the
> +# disassemble of a function (i.e., the binary's .text section).  GDB
> +# should fail in this case.  However, it must succeed if the binary is
> +# provided along with the corefile.  This is what we test here.

It seems like we now just miss the case of corefilter that _does_ request
that the file backed regions are dumped.  In that case, disassembly
should work without the binary.  Could you add that too, please?  We
can e.g., pass a boolean parameter to test_disasm to specify whether
to expect that disassembly works without a program file.

> +
> +proc test_disasm { core address } {
> +    global testfile
> +
> +    # Restarting GDB without loading the binary
> +    gdb_exit
> +    gdb_start
> +
> +    set core_loaded [gdb_core_cmd "$core" "load core"]
> +    if { $core_loaded == -1 } {
> +	fail "loading $core"
> +	return
> +    }
> +
> +    gdb_test "disassemble $address" "No function contains specified address." \
> +	"disassemble function with corefile and without a binary"
> +
> +    clean_restart $testfile
> +
> +    set core_loaded [gdb_core_cmd "$core" "load core"]
> +    if { $core_loaded == -1 } {
> +	fail "loading $core"
> +	return
> +    }
> +
> +    gdb_test "disassemble $address" "Dump of assembler code for function.*" \
> +	"disassemble function with corefile and with a binary"

Looks like there are duplicate test messages here, in the
cases clean_restart, gdb_core_cmd, etc. fail.  You can fix that
with e.g.:

       with_test_prefix "no binary" {
           # Restart GDB without loading the binary.
           gdb_exit
	   gdb_start

	   set core_loaded [gdb_core_cmd "$core" "load core"]
	   if { $core_loaded == -1 } {
	      fail "load $core"
	      return
	   }

	   gdb_test "disassemble $address" "No function contains specified address." \
		"disassemble function"
       }

       with_test_prefix "with binary" {
	   clean_restart $testfile

	   set core_loaded [gdb_core_cmd "$core" "load core"]
	   if { $core_loaded == -1 } {
	      fail "load $core"
	      return
	   }

	   gdb_test "disassemble $address" "No function contains specified address." \
		"disassemble function"
       }

> +# Getting the inferior's PID

"Get".  Period at end.

> +set infpid ""
> +gdb_test_multiple "info inferiors" "getting inferior pid" {
> +    -re "process \($decimal\).*\r\n$gdb_prompt $" {
> +	set infpid $expect_out(1,string)
> +    }
> +}
> +
> +# Get the main function's address

Period.

(I saw a few other similar gerund uses in the file which
read a bit odd to me, but I didn't point them all out.)

This is OK with the missing test added.

Thanks for the patience and for working on this.

Thanks,
Pedro Alves
  
Sergio Durigan Junior March 23, 2015, 9:08 p.m. UTC | #2
On Monday, March 23 2015, Pedro Alves wrote:

> On 03/22/2015 08:45 PM, Sergio Durigan Junior wrote:
>
>> +# We do not do file-backed mappings in the test program, but it is
>> +# important to test this anyway.  One way of performing the test is to
>> +# load GDB with a corefile but without a binary, and then ask for the
>> +# disassemble of a function (i.e., the binary's .text section).  GDB
>> +# should fail in this case.  However, it must succeed if the binary is
>> +# provided along with the corefile.  This is what we test here.
>
> It seems like we now just miss the case of corefilter that _does_ request
> that the file backed regions are dumped.  In that case, disassembly
> should work without the binary.  Could you add that too, please?  We
> can e.g., pass a boolean parameter to test_disasm to specify whether
> to expect that disassembly works without a program file.

Hm, I'm afraid there's a bit of confusion here, at least from my part.

I am already testing the case when we use a value that requests that
file-backed regions are dumped.  If you take a look at the
"all_anon_corefiles" list, you will see that the each corefile generated
there includes everything *except* for the specific type of mapping we
want to ignore (thus the "non_*" names).  And the result of this test is
that GDB cannot disassemble a function without a binary, even if all the
file-backed pages have been dumped.

Having said that, I made a test with git HEAD without my patch.  I
generated a corefile for the same test program, and then loaded only the
corefile:

  $ ./gdb -q -ex 'core ./core.31118' -ex 'disas 0x4007cb'
  ...
  Program terminated with signal SIGTRAP, Trace/breakpoint trap.
  #0  0x0000000000400905 in ?? ()
  No function contains specified address.
  (gdb) 

Which means that, even without my patch, GDB still cannot disassemble a
function without the binary.

FWIW, I did the same test, but this time using a corefile generated by
the Linux kernel (and with all bits set on coredump_filter), and the
results were the same.

>> +
>> +proc test_disasm { core address } {
>> +    global testfile
>> +
>> +    # Restarting GDB without loading the binary
>> +    gdb_exit
>> +    gdb_start
>> +
>> +    set core_loaded [gdb_core_cmd "$core" "load core"]
>> +    if { $core_loaded == -1 } {
>> +	fail "loading $core"
>> +	return
>> +    }
>> +
>> +    gdb_test "disassemble $address" "No function contains specified address." \
>> +	"disassemble function with corefile and without a binary"
>> +
>> +    clean_restart $testfile
>> +
>> +    set core_loaded [gdb_core_cmd "$core" "load core"]
>> +    if { $core_loaded == -1 } {
>> +	fail "loading $core"
>> +	return
>> +    }
>> +
>> +    gdb_test "disassemble $address" "Dump of assembler code for function.*" \
>> +	"disassemble function with corefile and with a binary"
>
> Looks like there are duplicate test messages here, in the
> cases clean_restart, gdb_core_cmd, etc. fail.  You can fix that
> with e.g.:
>
>        with_test_prefix "no binary" {
>            # Restart GDB without loading the binary.
>            gdb_exit
> 	   gdb_start
>
> 	   set core_loaded [gdb_core_cmd "$core" "load core"]
> 	   if { $core_loaded == -1 } {
> 	      fail "load $core"
> 	      return
> 	   }
>
> 	   gdb_test "disassemble $address" "No function contains specified address." \
> 		"disassemble function"
>        }
>
>        with_test_prefix "with binary" {
> 	   clean_restart $testfile
>
> 	   set core_loaded [gdb_core_cmd "$core" "load core"]
> 	   if { $core_loaded == -1 } {
> 	      fail "load $core"
> 	      return
> 	   }
>
> 	   gdb_test "disassemble $address" "No function contains specified address." \
> 		"disassemble function"
>        }

Thanks, fixed.

>> +# Getting the inferior's PID
>
> "Get".  Period at end.

Fixed.

>> +set infpid ""
>> +gdb_test_multiple "info inferiors" "getting inferior pid" {
>> +    -re "process \($decimal\).*\r\n$gdb_prompt $" {
>> +	set infpid $expect_out(1,string)
>> +    }
>> +}
>> +
>> +# Get the main function's address
>
> Period.

Fixed.

> (I saw a few other similar gerund uses in the file which
> read a bit odd to me, but I didn't point them all out.)

I removed all of them, and also added missing periods all over.  Thanks.

> This is OK with the missing test added.

I'll wait until you clarify that comment above :-).  I won't resubmit
the patch now because it only contains fixes to comments.

> Thanks for the patience and for working on this.

Thank you!
  
Pedro Alves March 23, 2015, 11:06 p.m. UTC | #3
On 03/23/2015 09:08 PM, Sergio Durigan Junior wrote:
> On Monday, March 23 2015, Pedro Alves wrote:
> 
>> On 03/22/2015 08:45 PM, Sergio Durigan Junior wrote:
>>
>>> +# We do not do file-backed mappings in the test program, but it is
>>> +# important to test this anyway.  One way of performing the test is to
>>> +# load GDB with a corefile but without a binary, and then ask for the
>>> +# disassemble of a function (i.e., the binary's .text section).  GDB
>>> +# should fail in this case.  However, it must succeed if the binary is
>>> +# provided along with the corefile.  This is what we test here.
>>
>> It seems like we now just miss the case of corefilter that _does_ request
>> that the file backed regions are dumped.  In that case, disassembly
>> should work without the binary.  Could you add that too, please?  We
>> can e.g., pass a boolean parameter to test_disasm to specify whether
>> to expect that disassembly works without a program file.
> 
> Hm, I'm afraid there's a bit of confusion here, at least from my part.
> 
> I am already testing the case when we use a value that requests that
> file-backed regions are dumped.  If you take a look at the
> "all_anon_corefiles" list, you will see that the each corefile generated
> there includes everything *except* for the specific type of mapping we
> want to ignore (thus the "non_*" names).  
> And the result of this test is
> that GDB cannot disassemble a function without a binary, even if all the
> file-backed pages have been dumped.

Now I'm confused.  If all the file-backed pages have been dumped,
then aren't the .text present in the core dump?  If that doesn't work,
we've just caught a bug somewhere.

> 
> Having said that, I made a test with git HEAD without my patch.  I
> generated a corefile for the same test program, and then loaded only the
> corefile:
> 
>   $ ./gdb -q -ex 'core ./core.31118' -ex 'disas 0x4007cb'
>   ...
>   Program terminated with signal SIGTRAP, Trace/breakpoint trap.
>   #0  0x0000000000400905 in ?? ()
>   No function contains specified address.
>   (gdb) 
> 
> Which means that, even without my patch, GDB still cannot disassemble a
> function without the binary.

Oh, without symbols, you need to tell "disassemble" an address range
to disassemble, not just an address.  Like, "disassemble 0x4007cb, +10".
Otherwise that fails even before a memory read was ever attempted, while
gdb was looking for the function's boundaries.

I tried poking at coredump_filter now and, and I'm actually seeing
the opposite.  I can always disassemble `main'.

$ gdb segv -c core.22587
...
Core was generated by `./segv'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000004004a5 in main () at segv.c:5
5         *(volatile int *)0;
(gdb) x /i $pc
=> 0x4004a5 <main+9>:   mov    (%rax),%eax

$ gdb -c core.22587
...
(gdb) x /i $pc
=> 0x4004a5:    mov    (%rax),%eax


The reason that works is that `main' happens to end up in the
first page of the text segment, and that one ends up always
dumped, as the dynamic loader touches it...

I do see that kernel generated cores do get bigger if I set
file-backed bits in coredump_filter:

$ ls -s --hu  core.*
2.3M core.22528  112K core.22587

Bah, can't immediately think of a portable way to test this now.

> 
> FWIW, I did the same test, but this time using a corefile generated by
> the Linux kernel (and with all bits set on coredump_filter), and the
> results were the same.

Thanks,
Pedro Alves
  
Sergio Durigan Junior March 24, 2015, 6:37 a.m. UTC | #4
On Monday, March 23 2015, Pedro Alves wrote:

> On 03/23/2015 09:08 PM, Sergio Durigan Junior wrote:
>> On Monday, March 23 2015, Pedro Alves wrote:
>> 
>>> On 03/22/2015 08:45 PM, Sergio Durigan Junior wrote:
>>>
>>>> +# We do not do file-backed mappings in the test program, but it is
>>>> +# important to test this anyway.  One way of performing the test is to
>>>> +# load GDB with a corefile but without a binary, and then ask for the
>>>> +# disassemble of a function (i.e., the binary's .text section).  GDB
>>>> +# should fail in this case.  However, it must succeed if the binary is
>>>> +# provided along with the corefile.  This is what we test here.
>>>
>>> It seems like we now just miss the case of corefilter that _does_ request
>>> that the file backed regions are dumped.  In that case, disassembly
>>> should work without the binary.  Could you add that too, please?  We
>>> can e.g., pass a boolean parameter to test_disasm to specify whether
>>> to expect that disassembly works without a program file.
>> 
>> Hm, I'm afraid there's a bit of confusion here, at least from my part.
>> 
>> I am already testing the case when we use a value that requests that
>> file-backed regions are dumped.  If you take a look at the
>> "all_anon_corefiles" list, you will see that the each corefile generated
>> there includes everything *except* for the specific type of mapping we
>> want to ignore (thus the "non_*" names).  
>> And the result of this test is
>> that GDB cannot disassemble a function without a binary, even if all the
>> file-backed pages have been dumped.
>
> Now I'm confused.  If all the file-backed pages have been dumped,
> then aren't the .text present in the core dump?  If that doesn't work,
> we've just caught a bug somewhere.

The bug was my understanding of the disassemble command :-).

>> 
>> Having said that, I made a test with git HEAD without my patch.  I
>> generated a corefile for the same test program, and then loaded only the
>> corefile:
>> 
>>   $ ./gdb -q -ex 'core ./core.31118' -ex 'disas 0x4007cb'
>>   ...
>>   Program terminated with signal SIGTRAP, Trace/breakpoint trap.
>>   #0  0x0000000000400905 in ?? ()
>>   No function contains specified address.
>>   (gdb) 
>> 
>> Which means that, even without my patch, GDB still cannot disassemble a
>> function without the binary.
>
> Oh, without symbols, you need to tell "disassemble" an address range
> to disassemble, not just an address.  Like, "disassemble 0x4007cb, +10".
> Otherwise that fails even before a memory read was ever attempted, while
> gdb was looking for the function's boundaries.

Thanks, this makes sense.  Therefore, my testcase is wrong, because it
is actually testing whether the disassemble command identifies this case
and reacts accordingly, instead of disassembling main...

> I tried poking at coredump_filter now and, and I'm actually seeing
> the opposite.  I can always disassemble `main'.
>
> $ gdb segv -c core.22587
> ...
> Core was generated by `./segv'.
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0  0x00000000004004a5 in main () at segv.c:5
> 5         *(volatile int *)0;
> (gdb) x /i $pc
> => 0x4004a5 <main+9>:   mov    (%rax),%eax
>
> $ gdb -c core.22587
> ...
> (gdb) x /i $pc
> => 0x4004a5:    mov    (%rax),%eax
>
> The reason that works is that `main' happens to end up in the
> first page of the text segment, and that one ends up always
> dumped, as the dynamic loader touches it...

This is strange.  It should not really matter if the dynamic loader
touches it or not, because GDB with my patch (or the Linux kernel,
AFAIK) is actually interested only if the page should be dumped or not
according to coredump_filter.

> I do see that kernel generated cores do get bigger if I set
> file-backed bits in coredump_filter:
>
> $ ls -s --hu  core.*
> 2.3M core.22528  112K core.22587
>
> Bah, can't immediately think of a portable way to test this now.

So, I did more investigation on this.  Here is what I found.

The Linux kernel uses the bit 4 on the coredump_filter file to determine
whether it should dump ELF headers or not.  According to vma_dump_size:

  /*
   * If this looks like the beginning of a DSO or executable mapping,
   * check for an ELF header.  If we find one, dump the first page to
   * aid in determining what was mapped here.
   */
  if (FILTER(ELF_HEADERS) &&
      vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
          u32 __user *header = (u32 __user *) vma->vm_start;
          u32 word;
          mm_segment_t fs = get_fs();
          /*
           * Doing it this way gets the constant folded by GCC.
           */
          union {
                  u32 cmp;
                  char elfmag[SELFMAG];
          } magic;
          BUILD_BUG_ON(SELFMAG != sizeof word);
          magic.elfmag[EI_MAG0] = ELFMAG0;
          magic.elfmag[EI_MAG1] = ELFMAG1;
          magic.elfmag[EI_MAG2] = ELFMAG2;
          magic.elfmag[EI_MAG3] = ELFMAG3;
          /*
           * Switch to the user "segment" for get_user(),
           * then put back what elf_core_dump() had in place.
           */
          set_fs(USER_DS);
          if (unlikely(get_user(word, header)))
                  word = 0;
          set_fs(fs);
          if (word == magic.cmp)
                  return PAGE_SIZE;
  }

So maybe this is what you meant above by "that one ends up always
dumped...", when refering to the first page of the text segment?  Well,
that is partially true: if you unset bit 4, you will see that this page
does not get dumped at all (and therefore we see the "Cannot access
memory..." error; I did some experiments here and confirmed that).

GDB does not honor bit 4, so it will only depend on the file-backed page
to be dumped in order to be able to disassemble things.  And while doing
the tests with my patch, I noticed that it is not always doing the right
thing about anonymous and file-backed mappings (argh).  Sometimes, it is
dumping file-backed private mappings even when I tell it not to do that,
and the reason is this:

  00400000-00401000 r-xp 00000000 fd:03 10914398 /path/to/file
  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
  Anonymous:             4 kB
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  AnonHugePages:         0 kB
  Swap:                  0 kB
  KernelPageSize:        4 kB
  MMUPageSize:           4 kB
  Locked:                0 kB
  VmFlags: rd ex mr mw me dw sd 

This is the .text segment of the test program.  It is a file-backed
private mapping, *but* it also contains anonymous contents.  For this
reason, my patch is considering this mapping as anonymous, because the
Linux kernel kind of does the same thing (again, from vma_dump_size):

  /* Dump segments that have been written to.  */
  if (vma->anon_vma && FILTER(ANON_PRIVATE))
          goto whole;

However, if we look below in the code:

  if (vma->vm_file == NULL)
          return 0;

  if (FILTER(MAPPED_PRIVATE))
          goto whole;

Therefore, if *also* considers tha case when the mapping is file-backed
private (which my patch doesn't do).

All this boils down to: my patch is incorrectly dumping the .text
segment when I ask it not to do that (i.e., when I ask it to ignore
file-backed private mappings and to dump anonymous private mappings),
and it is *not* dumping the .text segment when I ask it to dump it
(i.e., when I ask it to dump file-backed private mappings and to ignore
anonymous private mappings).

So, here's what I propose: I will rework this part of the patch and try
to come up with a better way of identifying these situations (mainly:
when a file-backed mapping has anonymous contents), and I will resubmit
it tomorrow.  Along with that, I should be able to extend the testcase
to cover the disassemble case (and it should start to work fine once I
make those adjustments).

Phew!  What a confusion...  :-/.  I hope things are clearer with this
e-mail.

WDYT?
  
Pedro Alves March 24, 2015, 10:12 a.m. UTC | #5
On 03/24/2015 06:37 AM, Sergio Durigan Junior wrote:
> 
> The Linux kernel uses the bit 4 on the coredump_filter file to determine
> whether it should dump ELF headers or not.  According to vma_dump_size:

...

> So maybe this is what you meant above by "that one ends up always
> dumped...", when refering to the first page of the text segment?  Well,
> that is partially true: if you unset bit 4, you will see that this page
> does not get dumped at all (and therefore we see the "Cannot access
> memory..." error; I did some experiments here and confirmed that).

Ah, indeed I probably had bit 4 set.

> Therefore, if *also* considers tha case when the mapping is file-backed
> private (which my patch doesn't do).
> 
> All this boils down to: my patch is incorrectly dumping the .text
> segment when I ask it not to do that (i.e., when I ask it to ignore
> file-backed private mappings and to dump anonymous private mappings),
> and it is *not* dumping the .text segment when I ask it to dump it
> (i.e., when I ask it to dump file-backed private mappings and to ignore
> anonymous private mappings).
> 
> So, here's what I propose: I will rework this part of the patch and try
> to come up with a better way of identifying these situations (mainly:
> when a file-backed mapping has anonymous contents), and I will resubmit
> it tomorrow.  Along with that, I should be able to extend the testcase
> to cover the disassemble case (and it should start to work fine once I
> make those adjustments).

Sounds good.

> 
> Phew!  What a confusion...  :-/.  I hope things are clearer with this
> e-mail.

Thanks,
Pedro Alves
  
Sergio Durigan Junior March 24, 2015, 11:15 p.m. UTC | #6
On Tuesday, March 24 2015, Pedro Alves wrote:

>> Therefore, if *also* considers tha case when the mapping is file-backed
>> private (which my patch doesn't do).
>> 
>> All this boils down to: my patch is incorrectly dumping the .text
>> segment when I ask it not to do that (i.e., when I ask it to ignore
>> file-backed private mappings and to dump anonymous private mappings),
>> and it is *not* dumping the .text segment when I ask it to dump it
>> (i.e., when I ask it to dump file-backed private mappings and to ignore
>> anonymous private mappings).
>> 
>> So, here's what I propose: I will rework this part of the patch and try
>> to come up with a better way of identifying these situations (mainly:
>> when a file-backed mapping has anonymous contents), and I will resubmit
>> it tomorrow.  Along with that, I should be able to extend the testcase
>> to cover the disassemble case (and it should start to work fine once I
>> make those adjustments).
>
> Sounds good.

And I am back, with new investigations and results.  This whole thing is
starting to driving me crazy.

What I found is interesting.  When a memory mapping is file-backed, but
contains Anonymous: pages, the Linux kernel dumps this region when:

  - The user asks for anonymous pages, *OR*

  - The user asks for file-backed pages

Yes, it dumps the mapping in *both* scenarios.  It is like a
"file-backed anonymous" mapping...

I adjusted my patch to mimic this behavior.  However, there is one more
thing...

For some reason, when I run the binary inside GDB, the .text segment
*contains* Anonymous: pages.  However, when I run the binary outside
GDB, the Anonymous: counter is always zero.  This means that, inside
GDB, when we ask for a corefile that excludes file-backed private
mappings (i.e., the .text segment), according to the Linux kernel's
rules, the .text segment *still* should be dumped because it contains
Anonymous: pages.

Unfortunately, I was not able to generate a binary whose .text segment
contained Anonymous: pages outside GDB.  However, I made a binary
that has Anonymous: pages on a file-backed mapping, and I made the Linux
kernel generate a corefile for it while asking it to exclude file-backed
mappings, and I could confirm that the Linux kernel indeed includes this
mapping in the corefile.

My final proposal, which will be reflected in a patch that will be
submitted soon, is to relax the test of the the disassembly of main.
This way, we can still mimic what the Linux kernel does and make GDB
compatible with it.

Thanks,
  
Pedro Alves March 24, 2015, 11:48 p.m. UTC | #7
On 03/24/2015 11:15 PM, Sergio Durigan Junior wrote:

> And I am back, with new investigations and results.  This whole thing is
> starting to driving me crazy.
> 
> What I found is interesting.  When a memory mapping is file-backed, but
> contains Anonymous: pages, the Linux kernel dumps this region when:
> 
>   - The user asks for anonymous pages, *OR*
> 
>   - The user asks for file-backed pages
> 
> Yes, it dumps the mapping in *both* scenarios.  It is like a
> "file-backed anonymous" mapping...

It makes sense to me.

> 
> I adjusted my patch to mimic this behavior.  However, there is one more
> thing...
> 
> For some reason, when I run the binary inside GDB, the .text segment
> *contains* Anonymous: pages.  However, when I run the binary outside
> GDB, the Anonymous: counter is always zero.  This means that, inside
> GDB, when we ask for a corefile that excludes file-backed private
> mappings (i.e., the .text segment), according to the Linux kernel's
> rules, the .text segment *still* should be dumped because it contains
> Anonymous: pages.

I'd guess those were pages gdb poked/wrote to?  Breakpoints, most
likely.  That should trigger a COW of the poked page.

> Unfortunately, I was not able to generate a binary whose .text segment
> contained Anonymous: pages outside GDB.  However, I made a binary
> that has Anonymous: pages on a file-backed mapping, and I made the Linux
> kernel generate a corefile for it while asking it to exclude file-backed
> mappings, and I could confirm that the Linux kernel indeed includes this
> mapping in the corefile.
> 
> My final proposal, which will be reflected in a patch that will be
> submitted soon, is to relax the test of the the disassembly of main.
> This way, we can still mimic what the Linux kernel does and make GDB
> compatible with it.

Not sure what relax means, but I'll just wait for the patch.  :-)

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 552da31..bbbc5d4 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -10952,6 +10952,39 @@  specified, the file name defaults to @file{core.@var{pid}}, where
 
 Note that this command is implemented only for some systems (as of
 this writing, @sc{gnu}/Linux, FreeBSD, Solaris, and S390).
+
+On @sc{gnu}/Linux, this command can take into account the value of the
+file @file{/proc/@var{pid}/coredump_filter} when generating the core
+dump (@pxref{set use-coredump-filter}).
+
+@kindex set use-coredump-filter
+@anchor{set use-coredump-filter}
+@item set use-coredump-filter on
+@itemx set use-coredump-filter off
+Enable or disable the use of the file
+@file{/proc/@var{pid}/coredump_filter} when generating core dump
+files.  This file is used by the Linux kernel to decide what types of
+memory mappings will be dumped or ignored when generating a core dump
+file.  @var{pid} is the process ID of a currently running process.
+
+To make use of this feature, you have to write in the
+@file{/proc/@var{pid}/coredump_filter} file a value, in hexadecimal,
+which is a bit mask representing the memory mapping types.  If a bit
+is set in the bit mask, then the memory mappings of the corresponding
+types will be dumped; otherwise, they will be ignored.  This
+configuration is inherited by child processes.  For more information
+about the bits that can be set in the
+@file{/proc/@var{pid}/coredump_filter} file, please refer to the
+manpage of @code{core(5)}.
+
+By default, this option is @code{on}.  If this option is turned
+@code{off}, @value{GDBN} does not read the @file{coredump_filter} file
+and instead uses the same default value as the Linux kernel in order
+to decide which pages will be dumped in the core dump file.  This
+value is currently @code{0x33}, which means that bits @code{0}
+(anonymous private mappings), @code{1} (anonymous shared mappings),
+@code{4} (ELF headers) and @code{5} (private huge pages) are active.
+This will cause these memory mappings to be dumped automatically.
 @end table
 
 @node Character Sets
diff --git a/gdb/testsuite/gdb.base/coredump-filter.c b/gdb/testsuite/gdb.base/coredump-filter.c
new file mode 100644
index 0000000..192c469
--- /dev/null
+++ b/gdb/testsuite/gdb.base/coredump-filter.c
@@ -0,0 +1,61 @@ 
+/* Copyright 2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+static void *
+do_mmap (void *addr, size_t size, int prot, int flags, int fd, off_t offset)
+{
+  void *ret = mmap (addr, size, prot, flags, fd, offset);
+
+  assert (ret != NULL);
+  return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+  const size_t size = 10;
+  const int default_prot = PROT_READ | PROT_WRITE;
+  char *private_anon, *shared_anon;
+  char *dont_dump;
+  int i;
+
+  private_anon = do_mmap (NULL, size, default_prot,
+			  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  memset (private_anon, 0x11, size);
+
+  shared_anon = do_mmap (NULL, size, default_prot,
+			 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  memset (shared_anon, 0x22, size);
+
+  dont_dump = do_mmap (NULL, size, default_prot,
+		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  memset (dont_dump, 0x55, size);
+  i = madvise (dont_dump, size, MADV_DONTDUMP);
+  assert_perror (errno);
+  assert (i == 0);
+
+  return 0; /* break-here */
+}
diff --git a/gdb/testsuite/gdb.base/coredump-filter.exp b/gdb/testsuite/gdb.base/coredump-filter.exp
new file mode 100644
index 0000000..2512761
--- /dev/null
+++ b/gdb/testsuite/gdb.base/coredump-filter.exp
@@ -0,0 +1,210 @@ 
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } {
+    untested "could not compile test program"
+    return -1
+}
+
+if { ![runto_main] } {
+    untested "could not run to main"
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+proc do_save_core { filter_flag core ipid } {
+    verbose -log "writing $filter_flag to /proc/$ipid/coredump_filter"
+
+    remote_exec target "sh -c \"echo $filter_flag > /proc/$ipid/coredump_filter\""
+
+    # Generate a corefile
+    gdb_gcore_cmd "$core" "save corefile"
+}
+
+proc do_load_and_test_core { core var working_var working_value } {
+    global hex decimal addr
+
+    set core_loaded [gdb_core_cmd "$core" "load core"]
+    if { $core_loaded == -1 } {
+	fail "loading $core"
+	return
+    }
+
+    # Accessing the memory the addresses point to.
+    gdb_test "print/x *(char *) $addr($var)" "\(\\\$$decimal = <error: \)?Cannot access memory at address $hex\(>\)?" \
+	"printing $var when core is loaded (should not work)"
+    gdb_test "print/x *(char *) $addr($working_var)" " = $working_value.*" \
+	"print/x *$working_var ( = $working_value)"
+}
+
+# We do not do file-backed mappings in the test program, but it is
+# important to test this anyway.  One way of performing the test is to
+# load GDB with a corefile but without a binary, and then ask for the
+# disassemble of a function (i.e., the binary's .text section).  GDB
+# should fail in this case.  However, it must succeed if the binary is
+# provided along with the corefile.  This is what we test here.
+
+proc test_disasm { core address } {
+    global testfile
+
+    # Restarting GDB without loading the binary
+    gdb_exit
+    gdb_start
+
+    set core_loaded [gdb_core_cmd "$core" "load core"]
+    if { $core_loaded == -1 } {
+	fail "loading $core"
+	return
+    }
+
+    gdb_test "disassemble $address" "No function contains specified address." \
+	"disassemble function with corefile and without a binary"
+
+    clean_restart $testfile
+
+    set core_loaded [gdb_core_cmd "$core" "load core"]
+    if { $core_loaded == -1 } {
+	fail "loading $core"
+	return
+    }
+
+    gdb_test "disassemble $address" "Dump of assembler code for function.*" \
+	"disassemble function with corefile and with a binary"
+}
+
+set non_private_anon_core [standard_output_file non-private-anon.gcore]
+set non_shared_anon_core [standard_output_file non-shared-anon.gcore]
+set non_private_file_core [standard_output_file non-private-file.gcore]
+set non_shared_file_core [standard_output_file non-shared-file.gcore]
+set dont_dump_core [standard_output_file dont-dump.gcore]
+
+# We will generate a few corefiles.
+#
+# This list is composed by sub-lists, and their elements are (in
+# order):
+#
+# - name of the test
+# - hexadecimal value to be put in the /proc/PID/coredump_filter file
+# - name of the variable that contains the name of the corefile to be
+#   generated (including the initial $).
+# - name of the variable in the C source code that points to the
+#   memory mapping that will NOT be present in the corefile.
+# - name of a variable in the C source code that points to a memory
+#   mapping that WILL be present in the corefile
+# - corresponding value expected for the above variable
+#
+# This list refers to the corefiles generated by MAP_ANONYMOUS in the
+# test program.
+
+set all_anon_corefiles { { "non-Private-Anonymous" "0x7e" \
+			       $non_private_anon_core \
+			       "private_anon" \
+			       "shared_anon" "0x22" }
+    { "non-Shared-Anonymous" "0x7d" \
+	  $non_shared_anon_core "shared_anon" \
+	  "private_anon" "0x11" }
+    { "DoNotDump" "0x33" \
+	  $dont_dump_core "dont_dump" \
+	  "shared_anon" "0x22" } }
+
+# We do not do file-backed mappings in the test program, but we still
+# generate coredumps to test it.  See the procedure 'test_disasm'
+# above for details.
+#
+# This list is composed by:
+#
+# - name of the test
+# - hexadecimal value to be put in the /proc/PID/coredump_filter file
+# - name of the variable that contains the name of the corefile to be
+#   generated (including the initial $).
+
+set all_file_corefiles { { "non-Private-File-Backed" "0x7b" \
+			       $non_private_file_core }
+    { "non-Shared-File-Backed" "0x77" \
+	  $non_shared_file_core } }
+
+# If corefile loading is not supported, we do not even try to run the
+# tests.
+set core_supported [gdb_gcore_cmd "$non_private_anon_core" "save a corefile"]
+if { !$core_supported } {
+    untested "corefile generation is not supported"
+    return -1
+}
+
+# Getting the inferior's PID
+set infpid ""
+gdb_test_multiple "info inferiors" "getting inferior pid" {
+    -re "process \($decimal\).*\r\n$gdb_prompt $" {
+	set infpid $expect_out(1,string)
+    }
+}
+
+# Get the main function's address
+set main_addr ""
+gdb_test_multiple "print/x &main" "getting main's address" {
+    -re "$decimal = \($hex\)\r\n$gdb_prompt $" {
+	set main_addr $expect_out(1,string)
+    }
+}
+
+# Obtaining the address of each variable that will be checked on each
+# case.
+foreach item $all_anon_corefiles {
+    foreach name [list [lindex $item 3] [lindex $item 4]] {
+	set test "print/x $name"
+	gdb_test_multiple $test $test {
+	    -re " = \($hex\)\r\n$gdb_prompt $" {
+		set addr($name) $expect_out(1,string)
+	    }
+	}
+    }
+}
+
+# Generate corefiles for the "anon" case.
+foreach item $all_anon_corefiles {
+    with_test_prefix "saving corefile for [lindex $item 0]" {
+	do_save_core [lindex $item 1] [subst [lindex $item 2]] $infpid
+    }
+}
+
+# Generate corefiles for the "file" case.
+foreach item $all_file_corefiles {
+    with_test_prefix "saving corefile for [lindex $item 0]" {
+	do_save_core [lindex $item 1] [subst [lindex $item 2]] $infpid
+    }
+}
+
+clean_restart $testfile
+
+foreach item $all_anon_corefiles {
+    with_test_prefix "loading and testing corefile for [lindex $item 0]" {
+	do_load_and_test_core [subst [lindex $item 2]] [lindex $item 3] \
+	    [lindex $item 4] [lindex $item 5]
+    }
+
+    with_test_prefix "disassembling function main for [lindex $item 0]" {
+	test_disasm [subst [lindex $item 2]] $main_addr
+    }
+}
+
+foreach item $all_file_corefiles {
+    with_test_prefix "disassembling function main for [lindex $item 0]" {
+	test_disasm [subst [lindex $item 2]] $main_addr
+    }
+}