1/**************************************************************************** 2 * * 3 * GNAT COMPILER COMPONENTS * 4 * * 5 * S I G T R A M P * 6 * * 7 * Asm Implementation File * 8 * * 9 * Copyright (C) 2011-2014, Free Software Foundation, Inc. * 10 * * 11 * GNAT is free software; you can redistribute it and/or modify it under * 12 * terms of the GNU General Public License as published by the Free Soft- * 13 * ware Foundation; either version 3, or (at your option) any later ver- * 14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- * 15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * 16 * or FITNESS FOR A PARTICULAR PURPOSE. * 17 * * 18 * As a special exception under Section 7 of GPL version 3, you are granted * 19 * additional permissions described in the GCC Runtime Library Exception, * 20 * version 3.1, as published by the Free Software Foundation. * 21 * * 22 * In particular, you can freely distribute your programs built with the * 23 * GNAT Pro compiler, including any required library run-time units, using * 24 * any licensing terms of your choosing. See the AdaCore Software License * 25 * for full details. * 26 * * 27 * GNAT was originally developed by the GNAT team at New York University. * 28 * Extensive contributions were provided by Ada Core Technologies Inc. * 29 * * 30 ****************************************************************************/ 31 32/************************************************** 33 * VxWorks version of the __gnat_sigtramp service * 34 **************************************************/ 35 36#include "sigtramp.h" 37/* See sigtramp.h for a general explanation of functionality. */ 38 39#include <vxWorks.h> 40#include <arch/../regs.h> 41#ifndef __RTP__ 42#include <sigLib.h> 43#else 44#include <signal.h> 45#include <regs.h> 46 47typedef struct mcontext 48 { 49 REG_SET regs; 50 } mcontext_t; 51 52typedef struct ucontext 53 { 54 mcontext_t uc_mcontext; /* register set */ 55 struct ucontext * uc_link; /* not used */ 56 sigset_t uc_sigmask; /* set of signals blocked */ 57 stack_t uc_stack; /* stack of context signaled */ 58 } ucontext_t; 59#endif 60 61/* ---------------------- 62 -- General comments -- 63 ---------------------- 64 65 Stubs are generated from toplevel asms and .cfi directives, much simpler 66 to use and check for correctness than manual encodings of CFI byte 67 sequences. The general idea is to establish CFA as sigcontext->sc_pregs 68 (for DKM) and mcontext (for RTP) and state where to find the registers as 69 offsets from there. 70 71 As of today, we support a stub providing CFI info for common 72 registers (GPRs, LR, ...). We might need variants with support for floating 73 point or altivec registers as well at some point. 74 75 Checking which variant should apply and getting at sc_pregs / mcontext 76 is simpler to express in C (we can't use offsetof in toplevel asms and 77 hardcoding constants is not workable with the flurry of VxWorks variants), 78 so this is the choice for our toplevel interface. 79 80 Note that the registers we "restore" here are those to which we have 81 direct access through the system sigcontext structure, which includes 82 only a partial set of the non-volatiles ABI-wise. */ 83 84/* ------------------------------------------- 85 -- Prototypes for our internal asm stubs -- 86 ------------------------------------------- 87 88 Eventhough our symbols will remain local, the prototype claims "extern" 89 and not "static" to prevent compiler complaints about a symbol used but 90 never defined. */ 91 92/* sigtramp stub providing CFI info for common registers. */ 93 94extern void __gnat_sigtramp_common 95(int signo, void *siginfo, void *sigcontext, 96 __sigtramphandler_t * handler, void * sc_pregs); 97 98 99/* ------------------------------------- 100 -- Common interface implementation -- 101 ------------------------------------- 102 103 We enforce optimization to minimize the overhead of the extra layer. */ 104 105void __gnat_sigtramp (int signo, void *si, void *sc, 106 __sigtramphandler_t * handler) 107 __attribute__((optimize(2))); 108 109void __gnat_sigtramp (int signo, void *si, void *sc, 110 __sigtramphandler_t * handler) 111{ 112#ifdef __RTP__ 113 mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext; 114 115 /* Pass MCONTEXT in the fifth position so that the assembly code can find 116 it at the same stack location or in the same register as SC_PREGS. */ 117 __gnat_sigtramp_common (signo, si, mcontext, handler, mcontext); 118#else 119 struct sigcontext * sctx = (struct sigcontext *) sc; 120 121 __gnat_sigtramp_common (signo, si, sctx, handler, sctx->sc_pregs); 122#endif 123} 124 125 126/* --------------------------- 127 -- And now the asm stubs -- 128 --------------------------- 129 130 They all have a common structure with blocks of asm sequences queued one 131 after the others. Typically: 132 133 SYMBOL_START 134 135 CFI_DIRECTIVES 136 CFI_DEF_CFA, 137 CFI_COMMON_REGISTERS, 138 ... 139 140 STUB_BODY 141 asm code to establish frame, setup the cfa reg value, 142 call the real signal handler, ... 143 144 SYMBOL_END 145*/ 146 147/*-------------------------------- 148 -- Misc constants and helpers -- 149 -------------------------------- */ 150 151/* asm string construction helpers. */ 152 153#define STR(TEXT) #TEXT 154/* stringify expanded TEXT, surrounding it with double quotes. */ 155 156#define S(E) STR(E) 157/* stringify E, which will resolve as text but may contain macros 158 still to be expanded. */ 159 160/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of 161 multine contents: */ 162#define TAB(S) "\t" S 163#define CR(S) S "\n" 164 165#undef TCR 166#define TCR(S) TAB(CR(S)) 167 168/* REGNO constants, dwarf column numbers for registers of interest. */ 169 170#if defined (__PPC__) 171 172#define REGNO_LR 65 173#define REGNO_CTR 66 174#define REGNO_CR 70 175#define REGNO_XER 76 176#define REGNO_GR(N) (N) 177 178#define REGNO_PC 67 /* ARG_POINTER_REGNUM */ 179 180#define FUNCTION "@function" 181 182#elif defined (__ARMEL__) 183 184#define REGNO_G_REG_OFFSET(N) (N) 185 186#define REGNO_PC_OFFSET 15 /* PC_REGNUM */ 187 188#define FUNCTION "%function" 189 190#else 191Not_implemented; 192#endif /* REGNO constants */ 193 194 195/*------------------------------ 196 -- Stub construction blocks -- 197 ------------------------------ */ 198 199/* CFA setup block 200 --------------- 201 Only non-volatile registers are suitable for a CFA base. These are the 202 only ones we can expect to be able retrieve from the unwinding context 203 while walking up the chain, saved by at least the bottom-most exception 204 propagation services. We set a non-volatile register to the value we 205 need in the stub body that follows. */ 206 207#if defined (__PPC__) 208 209/* Use r15 for PPC. Note that r14 is inappropriate here, even though it 210 is non-volatile according to the ABI, because GCC uses it as an extra 211 SCRATCH on SPE targets. */ 212 213#define CFA_REG 15 214 215#elif defined (__ARMEL__) 216 217/* Use r8 for ARM. Any of r4-r8 should work. */ 218 219#define CFA_REG 8 220 221#else 222Not_implemented; 223#endif /* CFA setup block */ 224 225#define CFI_DEF_CFA \ 226CR(".cfi_def_cfa " S(CFA_REG) ", 0") 227 228/* Register location blocks 229 ------------------------ 230 Rules to find registers of interest from the CFA. This should comprise 231 all the non-volatile registers relevant to the interrupted context. 232 233 Note that we include r1 in this set, unlike the libgcc unwinding 234 fallbacks. This is useful for fallbacks to allow the use of r1 in CFI 235 expressions and the absence of rule for r1 gets compensated by using the 236 target CFA instead. We don't need the expression facility here and 237 setup a fake CFA to allow very simple offset expressions, so having a 238 rule for r1 is the proper thing to do. We for sure have observed 239 crashes in some cases without it. */ 240 241#define COMMON_CFI(REG) \ 242 ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) 243 244#if defined (__PPC__) 245 246#define CFI_COMMON_REGS \ 247CR("# CFI for common registers\n") \ 248TCR(COMMON_CFI(GR(0))) \ 249TCR(COMMON_CFI(GR(1))) \ 250TCR(COMMON_CFI(GR(2))) \ 251TCR(COMMON_CFI(GR(3))) \ 252TCR(COMMON_CFI(GR(4))) \ 253TCR(COMMON_CFI(GR(5))) \ 254TCR(COMMON_CFI(GR(6))) \ 255TCR(COMMON_CFI(GR(7))) \ 256TCR(COMMON_CFI(GR(8))) \ 257TCR(COMMON_CFI(GR(9))) \ 258TCR(COMMON_CFI(GR(10))) \ 259TCR(COMMON_CFI(GR(11))) \ 260TCR(COMMON_CFI(GR(12))) \ 261TCR(COMMON_CFI(GR(13))) \ 262TCR(COMMON_CFI(GR(14))) \ 263TCR(COMMON_CFI(GR(15))) \ 264TCR(COMMON_CFI(GR(16))) \ 265TCR(COMMON_CFI(GR(17))) \ 266TCR(COMMON_CFI(GR(18))) \ 267TCR(COMMON_CFI(GR(19))) \ 268TCR(COMMON_CFI(GR(20))) \ 269TCR(COMMON_CFI(GR(21))) \ 270TCR(COMMON_CFI(GR(22))) \ 271TCR(COMMON_CFI(GR(23))) \ 272TCR(COMMON_CFI(GR(24))) \ 273TCR(COMMON_CFI(GR(25))) \ 274TCR(COMMON_CFI(GR(26))) \ 275TCR(COMMON_CFI(GR(27))) \ 276TCR(COMMON_CFI(GR(28))) \ 277TCR(COMMON_CFI(GR(29))) \ 278TCR(COMMON_CFI(GR(30))) \ 279TCR(COMMON_CFI(GR(31))) \ 280TCR(COMMON_CFI(LR)) \ 281TCR(COMMON_CFI(CR)) \ 282TCR(COMMON_CFI(CTR)) \ 283TCR(COMMON_CFI(XER)) \ 284TCR(COMMON_CFI(PC)) \ 285TCR(".cfi_return_column " S(REGNO_PC)) 286 287/* Trampoline body block 288 --------------------- */ 289 290#define SIGTRAMP_BODY \ 291CR("") \ 292TCR("# Allocate frame and save the non-volatile") \ 293TCR("# registers we're going to modify") \ 294TCR("stwu %r1,-16(%r1)") \ 295TCR("mflr %r0") \ 296TCR("stw %r0,20(%r1)") \ 297TCR("stw %r" S(CFA_REG) ",8(%r1)") \ 298TCR("") \ 299TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ 300TCR("mr %r" S(CFA_REG) ", %r7") \ 301TCR("") \ 302TCR("# Call the real handler. The signo, siginfo and sigcontext") \ 303TCR("# arguments are the same as those we received in r3, r4 and r5") \ 304TCR("mtctr %r6") \ 305TCR("bctrl") \ 306TCR("") \ 307TCR("# Restore our callee-saved items, release our frame and return") \ 308TCR("lwz %r" S(CFA_REG) ",8(%r1)") \ 309TCR("lwz %r0,20(%r1)") \ 310TCR("mtlr %r0") \ 311TCR("") \ 312TCR("addi %r1,%r1,16") \ 313TCR("blr") 314 315#elif defined (__ARMEL__) 316 317#define CFI_COMMON_REGS \ 318CR("# CFI for common registers\n") \ 319TCR(COMMON_CFI(G_REG_OFFSET(0))) \ 320TCR(COMMON_CFI(G_REG_OFFSET(1))) \ 321TCR(COMMON_CFI(G_REG_OFFSET(2))) \ 322TCR(COMMON_CFI(G_REG_OFFSET(3))) \ 323TCR(COMMON_CFI(G_REG_OFFSET(4))) \ 324TCR(COMMON_CFI(G_REG_OFFSET(5))) \ 325TCR(COMMON_CFI(G_REG_OFFSET(6))) \ 326TCR(COMMON_CFI(G_REG_OFFSET(7))) \ 327TCR(COMMON_CFI(G_REG_OFFSET(8))) \ 328TCR(COMMON_CFI(G_REG_OFFSET(9))) \ 329TCR(COMMON_CFI(G_REG_OFFSET(10))) \ 330TCR(COMMON_CFI(G_REG_OFFSET(11))) \ 331TCR(COMMON_CFI(G_REG_OFFSET(12))) \ 332TCR(COMMON_CFI(G_REG_OFFSET(13))) \ 333TCR(COMMON_CFI(G_REG_OFFSET(14))) \ 334TCR(COMMON_CFI(PC_OFFSET)) \ 335TCR(".cfi_return_column " S(REGNO_PC_OFFSET)) 336 337/* Trampoline body block 338 --------------------- */ 339 340#define SIGTRAMP_BODY \ 341CR("") \ 342TCR("# Allocate frame and save the non-volatile") \ 343TCR("# registers we're going to modify") \ 344TCR("mov ip, sp") \ 345TCR("stmfd sp!, {r"S(CFA_REG)", fp, ip, lr, pc}") \ 346TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \ 347TCR("ldr r"S(CFA_REG)", [ip]") \ 348TCR("") \ 349TCR("# Call the real handler. The signo, siginfo and sigcontext") \ 350TCR("# arguments are the same as those we received in r0, r1 and r2") \ 351TCR("sub fp, ip, #4") \ 352TCR("blx r3") \ 353TCR("# Restore our callee-saved items, release our frame and return") \ 354TCR("ldmfd sp, {r"S(CFA_REG)", fp, sp, pc}") 355 356#else 357Not_implemented; 358#endif /* CFI_COMMON_REGS and SIGTRAMP_BODY */ 359 360/* Symbol definition block 361 ----------------------- */ 362 363#define SIGTRAMP_START(SYM) \ 364CR("# " S(SYM) " cfi trampoline") \ 365TCR(".type " S(SYM) ", "FUNCTION) \ 366CR("") \ 367CR(S(SYM) ":") \ 368TCR(".cfi_startproc") \ 369TCR(".cfi_signal_frame") 370 371/* Symbol termination block 372 ------------------------ */ 373 374#define SIGTRAMP_END(SYM) \ 375CR(".cfi_endproc") \ 376TCR(".size " S(SYM) ", .-" S(SYM)) 377 378/*---------------------------- 379 -- And now, the real code -- 380 ---------------------------- */ 381 382/* Text section start. The compiler isn't aware of that switch. */ 383 384asm (".text\n" 385 TCR(".align 2")); 386 387/* sigtramp stub for common registers. */ 388 389#define TRAMP_COMMON __gnat_sigtramp_common 390 391asm (SIGTRAMP_START(TRAMP_COMMON)); 392asm (CFI_DEF_CFA); 393asm (CFI_COMMON_REGS); 394asm (SIGTRAMP_BODY); 395asm (SIGTRAMP_END(TRAMP_COMMON)); 396 397 398