14 #include "hook-arch-c.h"
20 static sigaction_t sigaction_orig;
21 /* == sigaction_orig_libc + trampoline_size */
22 INTERNAL sigaction_t sigaction_orig_libc_cont;
27 typedef void (*sa_sigaction_t) (int, siginfo_t *, void *);
29 static const sa_sigaction_t *const_sigaction_pointer_get (const struct sigaction *act)
31 if (act->sa_flags & SA_SIGINFO)
32 return (sa_sigaction_t *) &act->sa_sigaction;
34 return (sa_sigaction_t *) &act->sa_handler;
37 static sa_sigaction_t *sigaction_pointer_get (struct sigaction *act)
39 return (sa_sigaction_t *) const_sigaction_pointer_get
40 ((const struct sigaction *) act);
43 /* `SA_RESETHAND' will reset `*sigaction_pointer_get ()' to `SIG_DFL'
44 even for `sigaction' parameter `oldact'.
45 `SA_RESETHAND' will stay set there. */
47 static struct sigaction act_app[NSIG];
49 static void handler (int signum, siginfo_t *siginfo, void *ucontext_t_pointer)
51 struct sigaction *act = &act_app[signum];
52 sa_sigaction_t *act_sigaction_pointer;
54 act_sigaction_pointer = sigaction_pointer_get (act);
55 if (*act_sigaction_pointer != (sa_sigaction_t) SIG_DFL)
56 (*act_sigaction_pointer) (signum, siginfo, ucontext_t_pointer);
59 struct sigaction sig_dfl;
61 /* Reset the handler first to get caught SEGV in core_dump(). */
62 sig_dfl.sa_handler = SIG_DFL;
63 sigemptyset (&sig_dfl.sa_mask);
65 (*sigaction_orig) (signum, act, NULL);
69 if (act->sa_flags & SA_RESETHAND)
70 *act_sigaction_pointer = (sa_sigaction_t) SIG_DFL;
73 static int sigaction_subst (int signum, const struct sigaction *act,
74 struct sigaction *oldact)
76 struct sigaction act_new, act_app_saved;
81 /* Core dumping signals: */
82 #define SIGNAL_CORE(name) case name:
83 #include "signal-core.h"
88 return (*sigaction_orig) (signum, act, oldact);
91 act_app_saved = act_app[signum];
94 const sa_sigaction_t *const_act_sigaction_pointer;
96 const_act_sigaction_pointer = const_sigaction_pointer_get (act);
97 if (*const_act_sigaction_pointer == (sa_sigaction_t) SIG_DFL
98 || act->sa_flags & SA_RESETHAND)
100 sa_sigaction_t *act_sigaction_pointer;
102 act_app[signum] = *act;
105 act_sigaction_pointer = sigaction_pointer_get (&act_new);
106 *act_sigaction_pointer = handler;
107 act_new.sa_flags &= ~SA_RESETHAND;
110 retval = (*sigaction_orig) (signum, act, oldact);
113 sa_sigaction_t *oldact_sigaction_pointer;
115 assert (memcmp (&act_app_saved.sa_mask, &oldact->sa_mask,
116 sizeof (&act_app_saved.sa_mask)) == 0);
117 assert ((act_app_saved.sa_flags & ~SA_RESETHAND)
118 == (oldact->sa_flags & ~SA_RESETHAND));
119 oldact_sigaction_pointer = sigaction_pointer_get (oldact);
120 if (*oldact_sigaction_pointer == handler)
121 *oldact_sigaction_pointer = *(sigaction_pointer_get (&act_app[signum]));
122 oldact->sa_flags = act_app_saved.sa_flags;
127 static void sigaction_orig_patch (void)
129 unsigned long page_start, page_end;
130 sigaction_t sigaction_orig_libc;
132 sigaction_orig_libc = sigaction_orig;
134 page_start = (unsigned long) sigaction_orig_libc & PAGE_MASK;
135 page_end = ((unsigned long) sigaction_orig_libc + trampoline_size
136 + PAGE_SIZE - 1) & PAGE_MASK;
138 if (maps_verify ((void *) page_start, (void *) page_end))
140 fprintf (stderr, "libobjid: Invalid \"%s\" (0x%lx, %u)\n",
141 MAPS_FILENAME, page_start, (unsigned) (page_end - page_start));
144 maps_static_setup ((void *) page_start, (void *) page_end);
145 if (mprotect ((void *) page_start, page_end - page_start,
146 PROT_READ | PROT_WRITE | PROT_EXEC))
148 fprintf (stderr, "libobjid: mprotect (0x%lx, %u): %m\n", page_start,
149 (unsigned) (page_end - page_start));
152 if (memcmp (sigaction_orig_libc, sigaction_trampoline, trampoline_size) != 0)
154 fprintf (stderr, "libobjid: libc prologue (%p) is not matching\n",
155 sigaction_orig_libc);
158 /* Target jump from our trampoline. */
159 sigaction_orig_libc_cont = (sigaction_t) ((char *) sigaction_orig_libc
161 /* Jump instruction to our `sigaction_subst'. */
162 memcpy (sigaction_orig_libc, sigaction_trampoline_jmpdir,
164 /* Long direct jump operand is relative on i386 but absolute on x86_64. */
165 #define REBASE(ptr) ((char *) (ptr) - (char *) sigaction_trampoline_jmpdir \
166 + (char *) sigaction_orig_libc)
167 *(void **) REBASE (sigaction_trampoline_jmpdir_vec) = (void *)
168 ((char *) sigaction_subst - ((void *) sigaction_trampoline_jmpdir_base
169 == (void *) sigaction_trampoline ? NULL
170 : REBASE (sigaction_trampoline_jmpdir_base)));
173 /* Returning through our trampoline code back to the original function. */
174 sigaction_orig = sigaction_trampoline;
177 static void signal_init (int signum)
179 sighandler_t handler_orig;
181 handler_orig = signal (signum, SIG_DFL);
182 if (handler_orig != SIG_DFL)
183 fprintf (stderr, "libobjid: signal_init: %d: %p\n", signum, handler_orig);
186 static void *libc_handle;
188 static void libobjid_init (void) __attribute__((__constructor__));
189 static void libobjid_init (void)
193 debug_str = getenv ("LIBOBJID");
194 if (debug_str != NULL)
195 debug = atoi (debug_str);
197 if (libc_handle == NULL)
199 libc_handle = dlopen (NULL, RTLD_LAZY); /* RTLD_LAZY is mandatory */
200 if (libc_handle == NULL)
201 fprintf (stderr, "libobjid: dlopen (NULL): %s\n", dlerror ());
203 if (libc_handle == NULL)
206 #define SIGACTION_NAME "sigaction"
207 sigaction_orig = (sigaction_t) dlsym (libc_handle, SIGACTION_NAME);
208 if (sigaction_orig == NULL)
209 fprintf (stderr, "libobjid: dlsym (\"%s\"): %s\n", SIGACTION_NAME,
211 #undef SIGACTION_NAME
212 if (sigaction_orig == NULL)
215 sigaction_orig_patch ();
217 #define SIGNAL_CORE(name) signal_init (name);
218 #include "signal-core.h"
222 static void libobjid_fini (void) __attribute__((__constructor__));
223 static void libobjid_fini (void)
225 if (libc_handle != NULL && dlclose (libc_handle))
226 fprintf (stderr, "libobjid: dlclose (): %s\n", dlerror ());