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 /* Copyright (c) 1988 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.16 */ 32 33 34 #pragma weak elf_getdata = _elf_getdata 35 36 37 #include "syn.h" 38 #include <stdlib.h> 39 #include <assert.h> 40 #include <errno.h> 41 #include <libelf.h> 42 #include "decl.h" 43 #include "msg.h" 44 45 46 /* 47 * Convert data from file format to memory format. 48 */ 49 50 51 static const size_t align32[ELF_T_NUM] = 52 { 53 1, /* ELF_T_BYTE */ 54 sizeof (Elf32), /* ELF_T_ADDR */ 55 sizeof (Elf32), /* ELF_T_DYN */ 56 sizeof (Elf32), /* ELF_T_EHDR */ 57 sizeof (Elf32_Half), /* ELF_T_HALF */ 58 sizeof (Elf32), /* ELF_T_OFF */ 59 sizeof (Elf32), /* ELF_T_PHDR */ 60 sizeof (Elf32), /* ELF_T_RELA */ 61 sizeof (Elf32), /* ELF_T_REL */ 62 sizeof (Elf32), /* ELF_T_SHDR */ 63 sizeof (Elf32), /* ELF_T_SWORD */ 64 sizeof (Elf32), /* ELF_T_SYM */ 65 sizeof (Elf32), /* ELF_T_WORD */ 66 sizeof (Elf32), /* ELF_T_VERDEF */ 67 sizeof (Elf32), /* ELF_T_VERNEED */ 68 sizeof (Elf64_Sxword), /* ELF_T_SXWORD */ 69 sizeof (Elf64), /* ELF_T_XWORD */ 70 sizeof (Elf32_Half), /* ELF_T_SYMINFO */ 71 sizeof (Elf32), /* ELF_T_NOTE */ 72 sizeof (Elf32_Lword), /* ELF_T_MOVE */ 73 sizeof (Elf32_Lword), /* ELF_T_MOVEP */ 74 sizeof (Elf32_Word) /* ELF_T_CAP */ 75 76 }; 77 78 #define Nalign32 (sizeof (align32)/sizeof (align32[0])) 79 80 static const size_t align64[ELF_T_NUM] = 81 { 82 1, /* ELF_T_BYTE */ 83 sizeof (Elf64), /* ELF_T_ADDR */ 84 sizeof (Elf64), /* ELF_T_DYN */ 85 sizeof (Elf64), /* ELF_T_EHDR */ 86 sizeof (Elf64_Half), /* ELF_T_HALF */ 87 sizeof (Elf64), /* ELF_T_OFF */ 88 sizeof (Elf64), /* ELF_T_PHDR */ 89 sizeof (Elf64), /* ELF_T_RELA */ 90 sizeof (Elf64), /* ELF_T_REL */ 91 sizeof (Elf64), /* ELF_T_SHDR */ 92 sizeof (Elf64_Word), /* ELF_T_SWORD */ 93 sizeof (Elf64), /* ELF_T_SYM */ 94 sizeof (Elf64_Word), /* ELF_T_WORD */ 95 sizeof (Elf64), /* ELF_T_VDEF */ 96 sizeof (Elf64), /* ELF_T_VNEED */ 97 sizeof (Elf64), /* ELF_T_SXWORD */ 98 sizeof (Elf64), /* ELF_T_XWORD */ 99 sizeof (Elf32_Half), /* ELF_T_SYMINFO */ 100 sizeof (Elf32), /* ELF_T_NOTE */ 101 sizeof (Elf64), /* ELF_T_MOVE */ 102 sizeof (Elf64), /* ELF_T_MOVEP */ 103 sizeof (Elf64_Word) /* ELF_T_CAP */ 104 }; 105 106 #define Nalign64 (sizeof (align64)/sizeof (align64[0])) 107 108 109 /* 110 * Could use an array indexed by ELFCLASS*, but I'd rather 111 * avoid .data over something this infrequently used. The 112 * next choice would be to add extra conditionals. 113 */ 114 #define NALIGN(elf) ((elf->ed_class == ELFCLASS32) ? Nalign32 : Nalign64) 115 #define ALIGN(elf) ((elf->ed_class == ELFCLASS32) ? align32 : align64) 116 117 118 Elf_Data * 119 _elf_locked_getdata(Elf_Scn * scn, Elf_Data * data) 120 { 121 Dnode * d = (Dnode *)data; 122 Elf * elf; 123 Elf_Data src; 124 unsigned work; 125 126 assert(!elf_threaded || RW_LOCK_HELD(&(scn->s_elf->ed_rwlock))); 127 assert(!elf_threaded || MUTEX_HELD(&(scn->s_mutex))); 128 elf = scn->s_elf; 129 130 if ((scn->s_myflags & SF_READY) == 0) { 131 UPGRADELOCKS(elf, scn) 132 /* 133 * make sure someone else didn't come along and cook 134 * this stuff. 135 */ 136 if ((scn->s_myflags & SF_READY) == 0) 137 (void) _elf_cookscn(scn); 138 DOWNGRADELOCKS(elf, scn) 139 } 140 141 if (d == 0) 142 d = scn->s_hdnode; 143 else 144 d = d->db_next; 145 146 if (scn->s_err != 0) { 147 /*LINTED*/ 148 _elf_seterr((Msg)scn->s_err, 0); 149 return (0); 150 } 151 152 if (d == 0) { 153 return (0); 154 } 155 156 if (d->db_scn != scn) { 157 _elf_seterr(EREQ_DATA, 0); 158 return (0); 159 } 160 161 if (d->db_myflags & DBF_READY) { 162 return (&d->db_data); 163 } 164 elf = scn->s_elf; 165 166 /* 167 * Prepare return buffer. The data comes from the memory 168 * image of the file. "Empty" regions get an empty buffer. 169 * 170 * Only sections of an ELF_C_READ file can be not READY here. 171 * Furthermore, the input file must have been cooked or 172 * frozen by now. Translate cooked files in place if possible. 173 */ 174 175 ELFACCESSDATA(work, _elf_work) 176 d->db_data.d_version = work; 177 if ((d->db_off == 0) || (d->db_fsz == 0)) { 178 d->db_myflags |= DBF_READY; 179 return (&d->db_data); 180 } 181 182 if (elf->ed_class == ELFCLASS32) { 183 Elf32_Shdr *sh = scn->s_shdr; 184 size_t sz = sh->sh_entsize; 185 Elf_Type t = d->db_data.d_type; 186 187 if ((t != ELF_T_BYTE) && 188 (sz > 1) && (sz != elf32_fsize(t, 1, elf->ed_version))) { 189 _elf_seterr(EFMT_ENTSZ, 0); 190 return (0); 191 } 192 } else if (elf->ed_class == ELFCLASS64) { 193 Elf64_Shdr *sh = scn->s_shdr; 194 Elf64_Xword sz = sh->sh_entsize; 195 Elf_Type t = d->db_data.d_type; 196 197 if (t != ELF_T_BYTE && sz > 1 && 198 sz != elf64_fsize(t, 1, elf->ed_version)) { 199 _elf_seterr(EFMT_ENTSZ, 0); 200 return (0); 201 } 202 } else { 203 _elf_seterr(EREQ_CLASS, 0); 204 return (0); 205 } 206 207 208 /* 209 * validate the region 210 */ 211 212 if ((d->db_off < 0) || (d->db_off >= elf->ed_fsz) || 213 (elf->ed_fsz - d->db_off < d->db_fsz)) { 214 _elf_seterr(EFMT_DATA, 0); 215 return (0); 216 } 217 218 /* 219 * set up translation buffers and validate 220 */ 221 222 src.d_buf = (Elf_Void *)(elf->ed_ident + d->db_off); 223 src.d_size = d->db_fsz; 224 src.d_type = d->db_data.d_type; 225 src.d_version = elf->ed_version; 226 if (elf->ed_vm) { 227 UPGRADELOCKS(elf, scn) 228 if (_elf_vm(elf, (size_t)d->db_off, d->db_fsz) != OK_YES) { 229 DOWNGRADELOCKS(elf, scn) 230 return (0); 231 } 232 DOWNGRADELOCKS(elf, scn) 233 } 234 235 /* 236 * decide where to put destination 237 */ 238 239 switch (elf->ed_status) { 240 case ES_COOKED: 241 if ((size_t)d->db_data.d_type >= NALIGN(elf)) { 242 _elf_seterr(EBUG_COOKTYPE, 0); 243 return (0); 244 } 245 246 /* 247 * If the destination size (memory) is at least as 248 * big as the source size (file), and has the necessary 249 * alignment, reuse the space. 250 * 251 * Note that it is not sufficient to check the alignment 252 * of the offset within the object. Rather, we must check 253 * the alignment of the actual data buffer. The offset is 254 * sufficient if the file is a plain object file, which 255 * will always be mapped on a page boundary. In an archive 256 * however, the only guarantee is that the object will start 257 * on an even boundary within the archive file. The 258 * Solaris ar(1) adds padding in most (but not all cases) 259 * which minimizes this issue, but it is still important 260 * for the remaining cases that do not get padded. It also 261 * matters with archives produced by other versions of 262 * ar(1), such as the GNU version, or one from another 263 * ELF based operating system. 264 */ 265 266 if (d->db_data.d_size <= src.d_size) { 267 d->db_data.d_buf = (Elf_Void *)(elf->ed_ident + 268 d->db_off); 269 if (((uintptr_t)d->db_data.d_buf 270 % ALIGN(elf)[d->db_data.d_type]) == 0) { 271 break; 272 } else { /* Failure: Restore NULL buffer pointer */ 273 d->db_data.d_buf = 0; 274 } 275 } 276 277 /*FALLTHRU*/ 278 case ES_FROZEN: 279 if ((d->db_buf = malloc(d->db_data.d_size)) == 0) { 280 _elf_seterr(EMEM_DATA, errno); 281 return (0); 282 } 283 d->db_data.d_buf = d->db_buf; 284 break; 285 286 default: 287 _elf_seterr(EBUG_COOKSTAT, 0); 288 return (0); 289 } 290 291 if (elf->ed_class == ELFCLASS32) { 292 if (elf32_xlatetom(&d->db_data, &src, elf->ed_encode) == 0) 293 return (0); 294 } else { /* ELFCLASS64 */ 295 if (elf64_xlatetom(&d->db_data, &src, elf->ed_encode) == 0) 296 return (0); 297 } 298 d->db_myflags |= DBF_READY; 299 300 return (&d->db_data); 301 } 302 303 Elf_Data * 304 elf_getdata(Elf_Scn * scn, Elf_Data * data) 305 { 306 Elf_Data * rc; 307 Elf * elf; 308 309 /* 310 * trap null args, end of list, previous buffer. 311 * SHT_NULL sections have no buffer list, so they 312 * fall out here too. 313 */ 314 if (scn == 0) 315 return (0); 316 317 elf = scn->s_elf; 318 READLOCKS(elf, scn); 319 rc = _elf_locked_getdata(scn, data); 320 READUNLOCKS(elf, scn); 321 return (rc); 322 } 323