| /* Copyright 1992-2021 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/>. */ |
| |
| /* This test has two large memory areas buf_rw and buf_ro. |
| |
| buf_rw is written to by the program while buf_ro is initialized at |
| compile / load time. Thus, when a core file is created, buf_rw's |
| memory should reside in the core file, but buf_ro probably won't be. |
| Instead, the contents of buf_ro are available from the executable. |
| |
| Now, for the wrinkle: We create a one page read-only mapping over |
| both of these areas. This will create a one page "hole" of all |
| zeros in each area. |
| |
| Will GDB be able to correctly read memory from each of the four |
| (or six, if you count the regions on the other side of each hole) |
| memory regions? */ |
| |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <fcntl.h> |
| #include <sys/mman.h> |
| #include <signal.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <inttypes.h> |
| |
| /* These are globals so that we can find them easily when debugging |
| the core file. */ |
| long pagesize; |
| uintptr_t addr; |
| char *mbuf_ro; |
| char *mbuf_rw; |
| |
| /* 256 KiB buffer. */ |
| char buf_rw[256 * 1024]; |
| |
| #define C5_16 \ |
| 0xc5, 0xc5, 0xc5, 0xc5, \ |
| 0xc5, 0xc5, 0xc5, 0xc5, \ |
| 0xc5, 0xc5, 0xc5, 0xc5, \ |
| 0xc5, 0xc5, 0xc5, 0xc5 |
| |
| #define C5_256 \ |
| C5_16, C5_16, C5_16, C5_16, \ |
| C5_16, C5_16, C5_16, C5_16, \ |
| C5_16, C5_16, C5_16, C5_16, \ |
| C5_16, C5_16, C5_16, C5_16 |
| |
| #define C5_1k \ |
| C5_256, C5_256, C5_256, C5_256 |
| |
| #define C5_8k \ |
| C5_1k, C5_1k, C5_1k, C5_1k, \ |
| C5_1k, C5_1k, C5_1k, C5_1k |
| |
| #define C5_64k \ |
| C5_8k, C5_8k, C5_8k, C5_8k, \ |
| C5_8k, C5_8k, C5_8k, C5_8k |
| |
| #define C5_256k \ |
| C5_64k, C5_64k, C5_64k, C5_64k |
| |
| /* 256 KiB worth of data. For this test case, we can't allocate a |
| buffer and then fill it; we want GDB to have to read this data |
| from the executable; it should NOT find it in the core file. */ |
| |
| const char buf_ro[] = { C5_256k }; |
| |
| int |
| main (int argc, char **argv) |
| { |
| int i, bitcount; |
| |
| #ifdef _SC_PAGESIZE |
| pagesize = sysconf (_SC_PAGESIZE); |
| #else |
| pagesize = 8192; |
| #endif |
| |
| /* Verify that pagesize is a power of 2. */ |
| bitcount = 0; |
| for (i = 0; i < 4 * sizeof (pagesize); i++) |
| if (pagesize & (1 << i)) |
| bitcount++; |
| |
| if (bitcount != 1) |
| { |
| fprintf (stderr, "pagesize is not a power of 2.\n"); |
| exit (1); |
| } |
| |
| /* Compute an address that should be within buf_ro. Complain if not. */ |
| addr = ((uintptr_t) buf_ro + pagesize) & ~(pagesize - 1); |
| |
| if (addr <= (uintptr_t) buf_ro |
| || addr >= (uintptr_t) buf_ro + sizeof (buf_ro)) |
| { |
| fprintf (stderr, "Unable to compute a suitable address within buf_ro.\n"); |
| exit (1); |
| } |
| |
| mbuf_ro = mmap ((void *) addr, pagesize, PROT_READ, |
| MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); |
| |
| if (mbuf_ro == MAP_FAILED) |
| { |
| fprintf (stderr, "mmap #1 failed: %s.\n", strerror (errno)); |
| exit (1); |
| } |
| |
| /* Write (and fill) the R/W region. */ |
| for (i = 0; i < sizeof (buf_rw); i++) |
| buf_rw[i] = 0x6b; |
| |
| /* Compute an mmap address within buf_rw. Complain if it's somewhere |
| else. */ |
| addr = ((uintptr_t) buf_rw + pagesize) & ~(pagesize - 1); |
| |
| if (addr <= (uintptr_t) buf_rw |
| || addr >= (uintptr_t) buf_rw + sizeof (buf_rw)) |
| { |
| fprintf (stderr, "Unable to compute a suitable address within buf_rw.\n"); |
| exit (1); |
| } |
| |
| mbuf_rw = mmap ((void *) addr, pagesize, PROT_READ, |
| MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); |
| |
| if (mbuf_rw == MAP_FAILED) |
| { |
| fprintf (stderr, "mmap #2 failed: %s.\n", strerror (errno)); |
| exit (1); |
| } |
| |
| /* With correct ulimit, etc. this should cause a core dump. */ |
| abort (); |
| } |