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.