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