(root)/
strace-6.5/
tests/
pc.c
       1  /*
       2   * Copyright (c) 2015-2020 Dmitry V. Levin <ldv@strace.io>
       3   * Copyright (c) 2015-2021 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: GPL-2.0-or-later
       7   */
       8  
       9  #include "tests.h"
      10  #include "scno.h"
      11  #include <assert.h>
      12  #include <dlfcn.h>
      13  #include <fcntl.h>
      14  #include <unistd.h>
      15  #include <sys/mman.h>
      16  #include <sys/wait.h>
      17  #include <sys/sendfile.h>
      18  #include <sys/prctl.h>
      19  
      20  int main(void)
      21  {
      22  	const unsigned long pagesize = get_page_size();
      23  
      24  #ifdef __s390__
      25  	/*
      26  	 * The si_addr field is unreliable:
      27  	 * https://marc.info/?l=linux-s390&m=142515870124248&w=2
      28  	 */
      29  	error_msg_and_skip("s390: si_addr is unreliable");
      30  #endif
      31  
      32  	/* write instruction pointer length to the log */
      33  	assert(syscall(__NR_write, -1, (void *) 8UL, 2 * sizeof(void *)) < 0);
      34  
      35  	/* just a noticeable line in the log */
      36  	assert(munmap(&main, 0) < 0);
      37  
      38  	int pid = fork();
      39  	if (pid < 0)
      40  		perror_msg_and_fail("fork");
      41  
      42  	if (!pid) {
      43  		const unsigned long mask = ~(pagesize - 1);
      44  		unsigned long addr = (unsigned long) &main & mask;
      45  		unsigned long size = pagesize << 1;
      46  
      47  #ifdef HAVE_DLADDR
      48  		Dl_info info;
      49  		if (dladdr(&main, &info)) {
      50  			const unsigned long base =
      51  				(unsigned long) info.dli_fbase & mask;
      52  			if (base < addr) {
      53  				size += addr - base;
      54  				addr = base;
      55  			}
      56  		} else
      57  #endif
      58  		{
      59  			addr -= size;
      60  			size <<= 1;
      61  		}
      62  
      63  		/* Avoid creating core dumps */
      64  		(void) prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
      65  
      66  		/* SIGSEGV is expected */
      67  		(void) munmap((void *) addr, size);
      68  		(void) munmap((void *) addr, size);
      69  		error_msg_and_skip("SIGSEGV did not happen");
      70  	}
      71  
      72  	int status;
      73  	assert(wait(&status) == pid);
      74  	assert(WIFSIGNALED(status));
      75  	assert(WTERMSIG(status) == SIGSEGV);
      76  
      77  	/* dump process map for debug purposes */
      78  	close(0);
      79  	if (!open("/proc/self/maps", O_RDONLY))
      80  		(void) sendfile(1, 0, NULL, pagesize);
      81  
      82  	return 0;
      83  }