Comment # 7 on bug 1133245 from
I've got it.

So for the following conftest:

     1    /* confdefs.h */
     2    #define PACKAGE_NAME ""
     3    #define PACKAGE_TARNAME ""
     4    #define PACKAGE_VERSION ""
     5    #define PACKAGE_STRING ""
     6    #define PACKAGE_BUGREPORT ""
     7    #define PACKAGE_URL ""
     8    #define PACKAGE "libsigsegv"
     9    #define VERSION "2.12"
    10    #define STDC_HEADERS 1
    11    #define HAVE_SYS_TYPES_H 1
    12    #define HAVE_SYS_STAT_H 1
    13    #define HAVE_STDLIB_H 1
    14    #define HAVE_STRING_H 1
    15    #define HAVE_MEMORY_H 1
    16    #define HAVE_STRINGS_H 1
    17    #define HAVE_INTTYPES_H 1
    18    #define HAVE_STDINT_H 1
    19    #define HAVE_UNISTD_H 1
    20    #define HAVE_DLFCN_H 1
    21    #define LT_OBJDIR ".libs/"
    22    #define HAVE_SYS_SIGNAL_H 1
    23    #define CFG_SIGNALS "signals.h"
    24    #define HAVE_UNISTD_H 1
    25    #define HAVE_GETPAGESIZE 1
    26    #define HAVE_SYSCONF_PAGESIZE 1
    27    #define HAVE_MMAP_ANON 1
    28    #define HAVE_MMAP_ANONYMOUS 1
    29    #define HAVE_MMAP_DEVZERO 1
    30    /* end confdefs.h.  */
    31    
    32    
    33    #include <stdlib.h>
    34    #include <signal.h>
    35    #if HAVE_SYS_SIGNAL_H
    36    # include <sys/signal.h>
    37    #endif
    38    
    39    #include <sys/types.h>
    40    #include <sys/mman.h>
    41    #if HAVE_MMAP_DEVZERO
    42    # include <fcntl.h>
    43    # ifndef MAP_FILE
    44    #  define MAP_FILE 0
    45    # endif
    46    #endif
    47    #ifndef PROT_NONE
    48    # define PROT_NONE 0
    49    #endif
    50    #if HAVE_MMAP_ANON
    51    # define zero_fd -1
    52    # define map_flags MAP_ANON | MAP_PRIVATE
    53    #elif HAVE_MMAP_ANONYMOUS
    54    # define zero_fd -1
    55    # define map_flags MAP_ANONYMOUS | MAP_PRIVATE
    56    #elif HAVE_MMAP_DEVZERO
    57    static int zero_fd;
    58    # define map_flags MAP_FILE | MAP_PRIVATE
    59    #endif
    60    #if defined __NetBSD__ && (defined __sparc__ || defined __sparc64__)
    61      /* getpagesize () is 0x1000 or 0x2000, depending on hardware.  */
    62    # include <unistd.h>
    63    # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (getpagesize () - 1)
    64    #elif defined __linux__ && (defined __s390__ || defined __s390x__)
    65    # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (0x1000UL - 1)
    66    #else
    67    # define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS 0UL
    68    #endif
    69    unsigned long page;
    70    int handler_called = 0;
    71    void sigsegv_handler (int sig, siginfo_t *sip, void *ucp)
    72    {
    73      void *fault_address = (void *) (sip->si_addr);
    74      handler_called++;
    75      if (handler_called == 10)
    76        exit (4);
    77      if (fault_address
    78          != (void*)((page + 0x678) &
~SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS))
    79        exit (3);
    80      if (mprotect ((void *) page, 0x10000, PROT_READ | PROT_WRITE) < 0)
    81        exit (2);
    82    }
    83    void crasher (unsigned long p)
    84    {
    85      *(int *) (p + 0x678) = 42;
    86    }
    87    int main ()
    88    {
    89      void *p;
    90      struct sigaction action;
    91      /* Preparations.  */
    92    #if !HAVE_MMAP_ANON && !HAVE_MMAP_ANONYMOUS && HAVE_MMAP_DEVZERO
    93      zero_fd = open ("/dev/zero", O_RDONLY, 0644);
    94    #endif
    95      /* Setup some mmaped memory.  */
    96    #ifdef __hpux
    97      /* HP-UX 10 mmap() often fails when given a hint.  So give the OS
complete
    98         freedom about the address range.  */
    99      p = mmap ((void *) 0,          0x10000, PROT_READ | PROT_WRITE,
map_flags, zero_fd, 0);
   100    #else
   101      p = mmap ((void *) 0x12340000, 0x10000, PROT_READ | PROT_WRITE,
map_flags, zero_fd, 0);
   102    #endif
   103      if (p == (void *)(-1))
   104        exit (2);
   105      page = (unsigned long) p;
   106      /* Make it read-only.  */
   107    #if defined __linux__ && defined __sparc__
   108      /* On Linux 2.6.26/SPARC64, PROT_READ has the same effect as
   109         PROT_READ | PROT_WRITE.  */
   110      if (mprotect ((void *) page, 0x10000, PROT_NONE) < 0)
   111    #else
   112      if (mprotect ((void *) page, 0x10000, PROT_READ) < 0)
   113    #endif
   114        exit (2);
   115      /* Install the SIGSEGV handler.  */
   116      sigemptyset(&action.sa_mask);
   117    action.sa_sigaction = &sigsegv_handler;
   118       action.sa_flags = SA_SIGINFO;
   119      sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
   120      sigaction (SIGBUS, &action, (struct sigaction *) NULL);
   121      /* The first write access should invoke the handler and then
complete.  */
   122      crasher (page);
   123      /* The second write access should not invoke the handler.  */
   124      crasher (page);
   125      /* Check that the handler was called only once.  */
   126      if (handler_called != 1)
   127        exit (1);
   128      /* Test passed!  */
   129      return 0;
   130    }


In normal mode the segfault happens here:

   ���0x401102 <main+130>     callq  0x401030 <sigaction@plt>
   ���0x401107 <main+135>     mov    0x2f4a(%rip),%rax        # 0x404058 <page>
  >���0x40110e <main+142>     movl   $0x2a,0x678(%rax)
   ���0x401118 <main+152>     cmpl   $0x1,0x2f35(%rip)
   ���0x40111f <main+159>     jne    0x401135 <main+181>

So the handler is called before the cmpl instruction.
While with LTO we end up with:

   ���0x40110b <main+139>     cmpl   $0x1,0x2f46(%rip)        # 0x404058
<handler_called>
  >���0x401112 <main+146>     movl   $0x2a,0x678(%rbx)
   ���0x40111c <main+156>     jne    0x401133 <main+179>
   ���0x40111e <main+158>     add    $0xa0,%rsp

So comparison of (handler_called != 1) happens before the store that triggers
the handler.
It's correct in my opinion to do such transformation.


You are receiving this mail because: