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 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <stdio.h> 32 #include <memory.h> 33 #include <debug.h> 34 #include "msg.h" 35 #include "_libld.h" 36 37 38 /* 39 * The loader uses a `segment descriptor' list to describe the output 40 * segments it can potentially create. Additional segments may be added 41 * using a map file. 42 */ 43 #if defined(_ELF64) 44 /* Phdr packing changes under Elf64 */ 45 static Sg_desc sg_desc[LD_NUM] = { 46 {{PT_PHDR, PF_R + PF_X, 0, 0, 0, 0, 0, 0}, 47 MSG_ORIG(MSG_ENT_PHDR), 0, 0, NULL, NULL, 48 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 49 {{PT_INTERP, PF_R, 0, 0, 0, 0, 0, 0}, 50 MSG_ORIG(MSG_ENT_INTERP), 0, 0, NULL, NULL, 51 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 52 {{PT_SUNWCAP, PF_R, 0, 0, 0, 0, 0, 0}, 53 MSG_ORIG(MSG_ENT_SUNWCAP), 0, 0, NULL, NULL, 54 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 55 {{PT_LOAD, PF_R + PF_X, 0, 0, 0, 0, 0, 0}, 56 MSG_ORIG(MSG_ENT_TEXT), 0, 0, NULL, NULL, 57 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 58 {{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0}, 59 MSG_ORIG(MSG_ENT_DATA), 0, 0, NULL, NULL, 60 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 61 {{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0}, 62 MSG_ORIG(MSG_ENT_BSS), 0, 0, NULL, NULL, 63 (FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED), NULL, 0, 0}, 64 #if defined(__x86) && defined(_ELF64) 65 {{PT_LOAD, PF_R, 0, 0, 0, 0, 0, 0}, 66 MSG_ORIG(MSG_ENT_LRODATA), 0, 0, NULL, NULL, 67 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 68 {{PT_LOAD, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0}, 69 MSG_ORIG(MSG_ENT_LDATA), 0, 0, NULL, NULL, 70 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 71 #endif 72 {{PT_DYNAMIC, M_DATASEG_PERM, 0, 0, 0, 0, 0, 0}, 73 MSG_ORIG(MSG_ENT_DYNAMIC), 0, 0, NULL, NULL, 74 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 75 {{PT_SUNWDTRACE, M_DATASEG_PERM | PF_X, 0, 0, 0, 0, 0, 0}, 76 MSG_ORIG(MSG_ENT_DTRACE), 0, 0, NULL, NULL, 77 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 78 {{PT_NOTE, 0, 0, 0, 0, 0, 0, 0}, 79 MSG_ORIG(MSG_ENT_NOTE), 0, 0, NULL, NULL, 80 FLG_SG_TYPE, NULL, 0, 0}, 81 {{PT_SUNWBSS, 0, 0, 0, 0, 0, 0, 0}, 82 MSG_ORIG(MSG_ENT_SUNWBSS), 0, 0, NULL, NULL, 83 FLG_SG_TYPE, NULL, 0, 0}, 84 {{PT_TLS, PF_R, 0, 0, 0, 0, 0, 0}, 85 MSG_ORIG(MSG_ENT_TLS), 0, 0, NULL, NULL, 86 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 87 #if defined(__x86) 88 {{PT_SUNW_UNWIND, PF_R, 0, 0, 0, 0, 0, 0}, 89 MSG_ORIG(MSG_ENT_UNWIND), 0, 0, NULL, NULL, 90 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 91 #endif 92 {{PT_NULL, 0, 0, 0, 0, 0, 0, 0}, 93 MSG_ORIG(MSG_STR_EMPTY), 0, 0, NULL, NULL, 94 FLG_SG_TYPE, NULL, 0, 0} 95 }; 96 #else /* Elf32 */ 97 static Sg_desc sg_desc[LD_NUM] = { 98 {{PT_PHDR, 0, 0, 0, 0, 0, PF_R + PF_X, 0}, 99 MSG_ORIG(MSG_ENT_PHDR), 0, 0, NULL, NULL, 100 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 101 {{PT_INTERP, 0, 0, 0, 0, 0, PF_R, 0}, 102 MSG_ORIG(MSG_ENT_INTERP), 0, 0, NULL, NULL, 103 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 104 {{PT_SUNWCAP, 0, 0, 0, 0, 0, PF_R, 0}, 105 MSG_ORIG(MSG_ENT_SUNWCAP), 0, 0, NULL, NULL, 106 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 107 {{PT_LOAD, 0, 0, 0, 0, 0, PF_R + PF_X, 0}, 108 MSG_ORIG(MSG_ENT_TEXT), 0, 0, NULL, NULL, 109 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 110 {{PT_LOAD, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0}, 111 MSG_ORIG(MSG_ENT_DATA), 0, 0, NULL, NULL, 112 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 113 {{PT_LOAD, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0}, 114 MSG_ORIG(MSG_ENT_BSS), 0, 0, NULL, NULL, 115 (FLG_SG_TYPE | FLG_SG_FLAGS | FLG_SG_DISABLED), NULL, 0, 0}, 116 {{PT_DYNAMIC, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0}, 117 MSG_ORIG(MSG_ENT_DYNAMIC), 0, 0, NULL, NULL, 118 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 119 {{PT_SUNWDTRACE, 0, 0, 0, 0, 0, M_DATASEG_PERM, 0}, 120 MSG_ORIG(MSG_ENT_DTRACE), 0, 0, NULL, NULL, 121 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 122 {{PT_NOTE, 0, 0, 0, 0, 0, 0, 0}, 123 MSG_ORIG(MSG_ENT_NOTE), 0, 0, NULL, NULL, 124 FLG_SG_TYPE, NULL, 0, 0}, 125 {{PT_SUNWBSS, 0, 0, 0, 0, 0, 0, 0}, 126 MSG_ORIG(MSG_ENT_SUNWBSS), 0, 0, NULL, NULL, 127 FLG_SG_TYPE, NULL, 0, 0}, 128 {{PT_TLS, PF_R, 0, 0, 0, 0, 0, 0}, 129 MSG_ORIG(MSG_ENT_TLS), 0, 0, NULL, NULL, 130 (FLG_SG_TYPE | FLG_SG_FLAGS), NULL, 0, 0}, 131 {{PT_NULL, 0, 0, 0, 0, 0, 0, 0}, 132 MSG_ORIG(MSG_STR_EMPTY), 0, 0, NULL, NULL, 133 FLG_SG_TYPE, NULL, 0, 0} 134 }; 135 #endif /* Elfxx */ 136 137 138 /* 139 * The input processing of the loader involves matching the sections of its 140 * input files to an `entrance descriptor definition'. The entrance criteria 141 * is different for either a static or dynamic linkage, and may even be 142 * modified further using a map file. Each entrance criteria is associated 143 * with a segment descriptor, thus a mapping of input sections to output 144 * segments is maintained. 145 */ 146 static const Ent_desc ent_desc[] = { 147 {{NULL, NULL}, MSG_ORIG(MSG_SCN_SUNWBSS), NULL, 148 SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, 149 (Sg_desc *)LD_SUNWBSS, 0, FALSE}, 150 {{NULL, NULL}, NULL, SHT_NOTE, 0, 0, 151 (Sg_desc *)LD_NOTE, 0, FALSE}, 152 #if defined(__x86) && defined(_ELF64) 153 {{NULL, NULL}, MSG_ORIG(MSG_SCN_LRODATA), NULL, 154 SHF_ALLOC + SHF_AMD64_LARGE, SHF_ALLOC + SHF_AMD64_LARGE, 155 (Sg_desc *)LD_LRODATA, 0, FALSE}, 156 #endif 157 {{NULL, NULL}, NULL, NULL, 158 SHF_ALLOC + SHF_WRITE, SHF_ALLOC, 159 (Sg_desc *)LD_TEXT, 0, FALSE}, 160 {{NULL, NULL}, NULL, SHT_NOBITS, 161 SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, 162 (Sg_desc *)LD_BSS, 0, FALSE}, 163 #if defined(__x86) && defined(_ELF64) 164 {{NULL, NULL}, NULL, SHT_NOBITS, 165 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 166 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 167 (Sg_desc *)LD_DATA, 0, FALSE}, 168 {{NULL, NULL}, NULL, NULL, 169 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 170 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 171 (Sg_desc *)LD_LDATA, 0, FALSE}, 172 #endif 173 {{NULL, NULL}, NULL, NULL, 174 SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, 175 (Sg_desc *)LD_DATA, 0, FALSE}, 176 {{NULL, NULL}, NULL, 0, 0, 0, 177 (Sg_desc *)LD_EXTRA, 0, FALSE} 178 }; 179 180 /* 181 * Initialize new entrance and segment descriptors and add them as lists to 182 * the output file descriptor. 183 */ 184 uintptr_t 185 ld_ent_setup(Ofl_desc *ofl, Xword segalign) 186 { 187 Ent_desc *enp; 188 Sg_desc *sgp; 189 size_t size; 190 191 /* 192 * Initialize the elf library. 193 */ 194 if (elf_version(EV_CURRENT) == EV_NONE) { 195 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ELF_LIBELF), 196 EV_CURRENT); 197 return (S_ERROR); 198 } 199 200 /* 201 * Initialize internal Global Symbol Table AVL tree 202 */ 203 avl_create(&ofl->ofl_symavl, &ld_sym_avl_comp, sizeof (Sym_avlnode), 204 SGSOFFSETOF(Sym_avlnode, sav_node)); 205 206 /* 207 * The data segment permissions can differ depending on whether 208 * this object is built statically or dynamically. 209 */ 210 if (ofl->ofl_flags & FLG_OF_DYNAMIC) { 211 sg_desc[LD_DATA].sg_phdr.p_flags = M_DATASEG_PERM; 212 sg_desc[LD_SUNWBSS].sg_phdr.p_flags = M_DATASEG_PERM; 213 } else { 214 sg_desc[LD_DATA].sg_phdr.p_flags = M_DATASEG_PERM | PF_X; 215 } 216 217 /* 218 * Allocate and initialize writable copies of both the entrance and 219 * segment descriptors. 220 */ 221 if ((sgp = libld_malloc(sizeof (sg_desc))) == 0) 222 return (S_ERROR); 223 (void) memcpy(sgp, sg_desc, sizeof (sg_desc)); 224 if ((enp = libld_malloc(sizeof (ent_desc))) == 0) 225 return (S_ERROR); 226 (void) memcpy(enp, ent_desc, sizeof (ent_desc)); 227 228 /* 229 * Traverse the new entrance descriptor list converting the segment 230 * pointer entries to the absolute address within the new segment 231 * descriptor list. Add each entrance descriptor to the output file 232 * list. 233 */ 234 for (size = 0; size < sizeof (ent_desc); size += sizeof (Ent_desc)) { 235 enp->ec_segment = &sgp[(long)enp->ec_segment]; 236 if ((list_appendc(&ofl->ofl_ents, enp)) == 0) 237 return (S_ERROR); 238 enp++; 239 } 240 241 /* 242 * Traverse the new segment descriptor list adding each entry to the 243 * segment descriptor list. For each loadable segment initialize 244 * a default alignment (ld(1) and ld.so.1 initialize this differently). 245 */ 246 for (size = 0; size < sizeof (sg_desc); size += sizeof (Sg_desc)) { 247 Phdr *phdr = &(sgp->sg_phdr); 248 249 if ((list_appendc(&ofl->ofl_segs, sgp)) == 0) 250 return (S_ERROR); 251 if (phdr->p_type == PT_LOAD) 252 phdr->p_align = segalign; 253 254 sgp++; 255 } 256 return (1); 257 } 258