| /* 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/>. */ |
| |
| /* Simple little program that just generates a core dump from inside some |
| nested function calls. */ |
| |
| #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> |
| |
| #ifndef __STDC__ |
| #define const /**/ |
| #endif |
| |
| #define MAPSIZE (8 * 1024) |
| |
| /* Don't make these automatic vars or we will have to walk back up the |
| stack to access them. */ |
| |
| char *buf1; |
| char *buf2; |
| char *buf2ro; |
| char *buf3; |
| |
| int coremaker_data = 1; /* In Data section */ |
| int coremaker_bss; /* In BSS section */ |
| |
| /* Place a chunk of memory before coremaker_ro to improve the chances |
| that coremaker_ro will end up on it's own page. See: |
| |
| https://sourceware.org/pipermail/gdb-patches/2020-May/168168.html |
| https://sourceware.org/pipermail/gdb-patches/2020-May/168170.html */ |
| const unsigned char filler_ro[MAPSIZE] = {1, 2, 3, 4, 5, 6, 7, 8}; |
| const int coremaker_ro = 201; /* In Read-Only Data section */ |
| |
| /* Note that if the mapping fails for any reason, we set buf2 |
| to -1 and the testsuite notices this and reports it as |
| a failure due to a mapping error. This way we don't have |
| to test for specific errors when running the core maker. */ |
| |
| void |
| mmapdata () |
| { |
| int j, fd; |
| |
| /* Allocate and initialize a buffer that will be used to write |
| the file that is later mapped in. */ |
| |
| buf1 = (char *) malloc (MAPSIZE); |
| for (j = 0; j < MAPSIZE; ++j) |
| { |
| buf1[j] = j; |
| } |
| |
| /* Write the file to map in */ |
| |
| fd = open ("coremmap.data", O_CREAT | O_RDWR, 0666); |
| if (fd == -1) |
| { |
| perror ("coremmap.data open failed"); |
| buf2 = (char *) -1; |
| return; |
| } |
| write (fd, buf1, MAPSIZE); |
| |
| /* Now map the file into our address space as buf2 */ |
| |
| buf2 = (char *) mmap (0, MAPSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); |
| if (buf2 == (char *) MAP_FAILED) |
| { |
| perror ("mmap failed"); |
| return; |
| } |
| |
| /* Map in another copy, read-only. We won't write to this copy so it |
| will likely not end up in the core file. */ |
| buf2ro = (char *) mmap (0, MAPSIZE, PROT_READ, MAP_PRIVATE, fd, 0); |
| if (buf2ro == (char *) -1) |
| { |
| perror ("mmap failed"); |
| return; |
| } |
| |
| /* Verify that the original data and the mapped data are identical. |
| If not, we'd rather fail now than when trying to access the mapped |
| data from the core file. */ |
| |
| for (j = 0; j < MAPSIZE; ++j) |
| { |
| if (buf1[j] != buf2[j] || buf1[j] != buf2ro[j]) |
| { |
| fprintf (stderr, "mapped data is incorrect"); |
| buf2 = buf2ro = (char *) -1; |
| return; |
| } |
| } |
| /* Touch buf2 so kernel writes it out into 'core'. */ |
| buf2[0] = buf1[0]; |
| |
| /* Create yet another region which is allocated, but not written to. */ |
| buf3 = mmap (NULL, MAPSIZE, PROT_READ | PROT_WRITE, |
| MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
| if (buf3 == (char *) -1) |
| { |
| perror ("mmap failed"); |
| return; |
| } |
| } |
| |
| void |
| func2 () |
| { |
| int coremaker_local[5]; |
| int i; |
| |
| #ifdef SA_FULLDUMP |
| /* Force a corefile that includes the data section for AIX. */ |
| { |
| struct sigaction sa; |
| |
| sigaction (SIGABRT, (struct sigaction *)0, &sa); |
| sa.sa_flags |= SA_FULLDUMP; |
| sigaction (SIGABRT, &sa, (struct sigaction *)0); |
| } |
| #endif |
| |
| /* Make sure that coremaker_local doesn't get optimized away. */ |
| for (i = 0; i < 5; i++) |
| coremaker_local[i] = i; |
| coremaker_bss = 0; |
| for (i = 0; i < 5; i++) |
| coremaker_bss += coremaker_local[i]; |
| coremaker_data = coremaker_ro + 1; |
| abort (); |
| } |
| |
| void |
| func1 () |
| { |
| func2 (); |
| } |
| |
| int |
| main (int argc, char **argv) |
| { |
| if (argc == 2 && strcmp (argv[1], "sleep") == 0) |
| { |
| sleep (60); |
| return 0; |
| } |
| mmapdata (); |
| func1 (); |
| return 0; |
| } |