1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* 31 * Utility functions 32 */ 33 #include <unistd.h> 34 #include <signal.h> 35 #include <locale.h> 36 #include <string.h> 37 #include "msg.h" 38 #include "_libld.h" 39 40 /* 41 * Exit after cleaning up. 42 */ 43 int 44 ld_exit(Ofl_desc *ofl) 45 { 46 /* 47 * If we have created an output file remove it. 48 */ 49 if ((ofl->ofl_fd > 0) && ((ofl->ofl_flags1 & FLG_OF1_NONREG) == 0)) 50 (void) unlink(ofl->ofl_name); 51 52 /* 53 * Inform any support library that the link-edit has failed. 54 */ 55 ld_sup_atexit(ofl, 1); 56 57 /* 58 * Wrap up debug output file if one is open 59 */ 60 dbg_cleanup(); 61 62 return (1); 63 } 64 65 /* 66 * Establish the signals we're interested in, and the handlers that need to be 67 * reinstalled should any of these signals occur. 68 */ 69 typedef struct { 70 int signo; 71 void (* defhdl)(); 72 } Signals; 73 74 static Signals signals[] = { 75 { SIGHUP, SIG_DFL }, 76 { SIGINT, SIG_IGN }, 77 { SIGQUIT, SIG_DFL }, 78 { SIGBUS, SIG_DFL }, 79 { SIGTERM, SIG_IGN }, 80 { 0, 0 } }; 81 82 static Ofl_desc *Ofl = 0; 83 84 /* 85 * Define our signal handler. 86 */ 87 static void 88 /* ARGSUSED2 */ 89 handler(int sig, siginfo_t *sip, void *utp) 90 { 91 struct sigaction nact; 92 Signals * sigs; 93 94 /* 95 * Reset all ignore handlers regardless of how we got here. 96 */ 97 nact.sa_handler = SIG_IGN; 98 nact.sa_flags = 0; 99 (void) sigemptyset(&nact.sa_mask); 100 101 for (sigs = signals; sigs->signo; sigs++) { 102 if (sigs->defhdl == SIG_IGN) 103 (void) sigaction(sigs->signo, &nact, NULL); 104 } 105 106 /* 107 * The model for creating an output file is to ftruncate() it to the 108 * required size and mmap() a mapping into which the new contents are 109 * written. Neither of these operations guarantee that the required 110 * disk blocks exist, and should we run out of disk space a bus error 111 * is generated. 112 * Other situations have been reported to result in ld catching a bus 113 * error (one instance was a stale NFS handle from an unstable server). 114 * Thus we catch all bus errors and hope we can decode a better error. 115 */ 116 if ((sig == SIGBUS) && sip && Ofl->ofl_name) { 117 eprintf(Ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INTERRUPT), 118 Ofl->ofl_name, strerror(sip->si_errno)); 119 } 120 /* 121 * This assert(0) causes DEBUG enabled linkers to produce a core file. 122 */ 123 if ((sig != SIGHUP) && (sig != SIGINT)) 124 assert(0); 125 126 exit(ld_exit(Ofl)); 127 } 128 129 /* 130 * Establish a signal handler for all signals we're interested in. 131 */ 132 void 133 ld_init_sighandler(Ofl_desc *ofl) 134 { 135 struct sigaction nact, oact; 136 Signals * sigs; 137 138 Ofl = ofl; 139 140 /* 141 * Our heavy use of mmap() means that we are susceptible to 142 * receiving a SIGBUS in low diskspace situations. The main 143 * purpose of the signal handler is to handle that situation 144 * gracefully, so that out of disk errors don't drop a core file. 145 * 146 * In rare cases, this will prevent us from getting a core from a 147 * SIGBUS triggered by an internal alignment error in libld. 148 * If -znosighandler is set, return without registering the 149 * handler. This is primarily of use for debugging problems in 150 * the field, and is not of general interest. 151 */ 152 if (ofl->ofl_flags1 & FLG_OF1_NOSGHND) 153 return; 154 155 /* 156 * For each signal we're interested in set up a signal handler that 157 * insures we clean up any output file we're in the middle of creating. 158 */ 159 nact.sa_sigaction = handler; 160 (void) sigemptyset(&nact.sa_mask); 161 162 for (sigs = signals; sigs->signo; sigs++) { 163 if ((sigaction(sigs->signo, NULL, &oact) == 0) && 164 (oact.sa_handler != SIG_IGN)) { 165 nact.sa_flags = SA_SIGINFO; 166 if (sigs->defhdl == SIG_DFL) 167 nact.sa_flags |= (SA_RESETHAND | SA_NODEFER); 168 (void) sigaction(sigs->signo, &nact, NULL); 169 } 170 } 171 } 172