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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * This stuff used to live in cook.c, but was moved out to 32 * facilitate dual (Elf32 and Elf64) compilation. See block 33 * comment in cook.c for more info. 34 */ 35 36 #include <string.h> 37 #include <ar.h> 38 #include <stdlib.h> 39 #include <errno.h> 40 #include <sys/sysmacros.h> 41 #include "decl.h" 42 #include "member.h" 43 #include "msg.h" 44 45 /* 46 * This module is compiled twice, the second time having 47 * -D_ELF64 defined. The following set of macros, along 48 * with machelf.h, represent the differences between the 49 * two compilations. Be careful *not* to add any class- 50 * dependent code (anything that has elf32 or elf64 in the 51 * name) to this code without hiding it behind a switch- 52 * able macro like these. 53 */ 54 #if defined(_ELF64) 55 #define Snode Snode64 56 #define ELFCLASS ELFCLASS64 57 #define ElfField Elf64 58 #define _elf_snode_init _elf64_snode_init 59 #define _elf_prepscan _elf64_prepscan 60 #define _elf_cookscn _elf64_cookscn 61 #define _elf_mtype _elf64_mtype 62 #define _elf_msize _elf64_msize 63 #define elf_fsize elf64_fsize 64 #define _elf_snode _elf64_snode 65 #define _elf_ehdr _elf64_ehdr 66 #define elf_xlatetom elf64_xlatetom 67 #define _elf_phdr _elf64_phdr 68 #define _elf_shdr _elf64_shdr 69 #define _elf_prepscn _elf64_prepscn 70 71 #else /* Elf32 */ 72 #define Snode Snode32 73 #define ELFCLASS ELFCLASS32 74 #define ElfField Elf32 75 #define _elf_snode_init _elf32_snode_init 76 #define _elf_prepscan _elf32_prepscan 77 #define _elf_cookscn _elf32_cookscn 78 #define _elf_mtype _elf32_mtype 79 #define _elf_msize _elf32_msize 80 #define elf_fsize elf32_fsize 81 #define _elf_snode _elf32_snode 82 #define _elf_ehdr _elf32_ehdr 83 #define elf_xlatetom elf32_xlatetom 84 #define _elf_phdr _elf32_phdr 85 #define _elf_shdr _elf32_shdr 86 #define _elf_prepscn _elf32_prepscn 87 88 #endif /* _ELF64 */ 89 90 91 static Okay 92 _elf_prepscn(Elf *elf, size_t cnt) 93 { 94 NOTE(ASSUMING_PROTECTED(*elf)) 95 Elf_Scn * s; 96 Elf_Scn * end; 97 98 if (cnt == 0) 99 return (OK_YES); 100 101 if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) { 102 _elf_seterr(EMEM_SCN, errno); 103 return (OK_NO); 104 } 105 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s)) 106 elf->ed_scntabsz = cnt; 107 end = s + cnt; 108 elf->ed_hdscn = s; 109 do { 110 *s = _elf_snode_init.sb_scn; 111 s->s_elf = elf; 112 s->s_next = s + 1; 113 s->s_index = s - elf->ed_hdscn; 114 s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index; 115 ELFMUTEXINIT(&s->s_mutex); 116 117 /* 118 * Section has not yet been cooked! 119 * 120 * We don't cook a section until it's data is actually 121 * referenced. 122 */ 123 s->s_myflags = 0; 124 } while (++s < end); 125 126 elf->ed_tlscn = --s; 127 s->s_next = 0; 128 129 /* 130 * Section index SHN_UNDEF (0) does not and cannot 131 * have a data buffer. Fix it here. Also mark the 132 * initial section as being allocated for the block 133 */ 134 135 s = elf->ed_hdscn; 136 s->s_myflags = SF_ALLOC; 137 s->s_hdnode = 0; 138 s->s_tlnode = 0; 139 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s)) 140 return (OK_YES); 141 } 142 143 144 Okay 145 _elf_cookscn(Elf_Scn * s) 146 { 147 NOTE(ASSUMING_PROTECTED(*s, *(s->s_elf))) 148 Elf * elf; 149 Shdr * sh; 150 register Dnode * d = &s->s_dnode; 151 size_t fsz, msz; 152 unsigned work; 153 154 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d)) 155 s->s_hdnode = s->s_tlnode = d; 156 s->s_err = 0; 157 s->s_shflags = 0; 158 s->s_uflags = 0; 159 160 161 /* 162 * Prepare d_data for inspection, but don't actually 163 * translate data until needed. Leave the READY 164 * flag off. NOBITS sections see zero size. 165 */ 166 elf = s->s_elf; 167 sh = s->s_shdr; 168 169 d->db_scn = s; 170 d->db_off = sh->sh_offset; 171 d->db_data.d_align = sh->sh_addralign; 172 d->db_data.d_version = elf->ed_version; 173 ELFACCESSDATA(work, _elf_work) 174 d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work); 175 d->db_data.d_buf = 0; 176 d->db_data.d_off = 0; 177 fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version); 178 msz = _elf_msize(d->db_data.d_type, elf->ed_version); 179 d->db_data.d_size = MAX(sh->sh_size, (sh->sh_size / fsz) * msz); 180 d->db_shsz = sh->sh_size; 181 d->db_raw = 0; 182 d->db_buf = 0; 183 d->db_uflags = 0; 184 d->db_myflags = 0; 185 d->db_next = 0; 186 187 if (sh->sh_type != SHT_NOBITS) 188 d->db_fsz = sh->sh_size; 189 else 190 d->db_fsz = 0; 191 192 s->s_myflags |= SF_READY; 193 194 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d)) 195 return (OK_YES); 196 } 197 198 199 200 Snode * 201 _elf_snode() 202 { 203 register Snode *s; 204 205 if ((s = malloc(sizeof (Snode))) == 0) { 206 _elf_seterr(EMEM_SNODE, errno); 207 return (0); 208 } 209 *s = _elf_snode_init; 210 ELFMUTEXINIT(&s->sb_scn.s_mutex); 211 s->sb_scn.s_myflags = SF_ALLOC | SF_READY; 212 s->sb_scn.s_shdr = &s->sb_shdr; 213 return (s); 214 } 215 216 217 218 int 219 _elf_ehdr(Elf * elf, int inplace) 220 { 221 NOTE(ASSUMING_PROTECTED(*elf)) 222 register size_t fsz; /* field size */ 223 Elf_Data dst, src; 224 225 fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version); 226 if (fsz > elf->ed_fsz) { 227 _elf_seterr(EFMT_EHDRSZ, 0); 228 return (-1); 229 } 230 if (inplace && (fsz >= sizeof (Ehdr))) { 231 /* 232 * The translated Ehdr will fit over the original Ehdr. 233 */ 234 /* LINTED */ 235 elf->ed_ehdr = (Ehdr *)elf->ed_ident; 236 elf->ed_status = ES_COOKED; 237 } else { 238 elf->ed_ehdr = malloc(sizeof (Ehdr)); 239 if (elf->ed_ehdr == 0) { 240 _elf_seterr(EMEM_EHDR, errno); 241 return (-1); 242 } 243 elf->ed_myflags |= EDF_EHALLOC; 244 } 245 246 /* 247 * Memory size >= fsz, because otherwise the memory version 248 * loses information and cannot accurately implement the 249 * file. 250 */ 251 252 src.d_buf = (Elf_Void *)elf->ed_ident; 253 src.d_type = ELF_T_EHDR; 254 src.d_size = fsz; 255 src.d_version = elf->ed_version; 256 dst.d_buf = (Elf_Void *)elf->ed_ehdr; 257 dst.d_size = sizeof (Ehdr); 258 dst.d_version = EV_CURRENT; 259 260 if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) || 261 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 262 if (elf->ed_myflags & EDF_EHALLOC) { 263 elf->ed_myflags &= ~EDF_EHALLOC; 264 free(elf->ed_ehdr); 265 } 266 elf->ed_ehdr = 0; 267 return (-1); 268 } 269 270 if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) { 271 _elf_seterr(EREQ_CLASS, 0); 272 if (elf->ed_myflags & EDF_EHALLOC) { 273 elf->ed_myflags &= ~EDF_EHALLOC; 274 free(elf->ed_ehdr); 275 } 276 elf->ed_ehdr = 0; 277 return (-1); 278 } 279 280 if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) { 281 _elf_seterr(EFMT_VER2, 0); 282 if (elf->ed_myflags & EDF_EHALLOC) { 283 elf->ed_myflags &= ~EDF_EHALLOC; 284 free(elf->ed_ehdr); 285 } 286 elf->ed_ehdr = 0; 287 return (-1); 288 } 289 290 return (0); 291 } 292 293 294 295 int 296 _elf_phdr(Elf * elf, int inplace) 297 { 298 NOTE(ASSUMING_PROTECTED(*elf)) 299 register size_t fsz, msz; 300 Elf_Data dst, src; 301 Ehdr * eh = elf->ed_ehdr; /* must be present */ 302 unsigned work; 303 304 if (eh->e_phnum == 0) 305 return (0); 306 307 fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version); 308 if (eh->e_phentsize != fsz) { 309 _elf_seterr(EFMT_PHDRSZ, 0); 310 return (-1); 311 } 312 313 fsz *= eh->e_phnum; 314 ELFACCESSDATA(work, _elf_work) 315 msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum; 316 if ((eh->e_phoff == 0) || 317 (elf->ed_fsz <= eh->e_phoff) || 318 (elf->ed_fsz - eh->e_phoff < fsz)) { 319 _elf_seterr(EFMT_PHTAB, 0); 320 return (-1); 321 } 322 323 if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) { 324 elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff); 325 elf->ed_status = ES_COOKED; 326 } else { 327 if ((elf->ed_phdr = malloc(msz)) == 0) { 328 _elf_seterr(EMEM_PHDR, errno); 329 return (-1); 330 } 331 elf->ed_myflags |= EDF_PHALLOC; 332 } 333 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff); 334 src.d_type = ELF_T_PHDR; 335 src.d_size = fsz; 336 src.d_version = elf->ed_version; 337 dst.d_buf = elf->ed_phdr; 338 dst.d_size = msz; 339 dst.d_version = work; 340 if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) || 341 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 342 if (elf->ed_myflags & EDF_PHALLOC) { 343 elf->ed_myflags &= ~EDF_PHALLOC; 344 free(elf->ed_phdr); 345 } 346 elf->ed_phdr = 0; 347 return (-1); 348 } 349 elf->ed_phdrsz = msz; 350 return (0); 351 } 352 353 354 355 int 356 _elf_shdr(Elf * elf, int inplace) 357 { 358 NOTE(ASSUMING_PROTECTED(*elf)) 359 register size_t fsz, msz; 360 size_t scncnt; 361 Elf_Data dst, src; 362 register Ehdr *eh = elf->ed_ehdr; /* must be present */ 363 364 if ((eh->e_shnum == 0) && (eh->e_shoff == 0)) 365 return (0); 366 367 fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version); 368 if (eh->e_shentsize != fsz) { 369 _elf_seterr(EFMT_SHDRSZ, 0); 370 return (-1); 371 } 372 /* 373 * If we are dealing with a file with 'extended section 374 * indexes' - then we need to load the first section 375 * header. The actual section count is stored in 376 * Shdr[0].sh_size. 377 */ 378 if ((scncnt = eh->e_shnum) == 0) { 379 Shdr sh; 380 if ((eh->e_shoff == 0) || 381 (elf->ed_fsz <= eh->e_shoff) || 382 (elf->ed_fsz - eh->e_shoff < fsz)) { 383 _elf_seterr(EFMT_SHTAB, 0); 384 return (-1); 385 } 386 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff); 387 src.d_type = ELF_T_SHDR; 388 src.d_size = fsz; 389 src.d_version = elf->ed_version; 390 dst.d_buf = (Elf_Void *)&sh; 391 dst.d_size = sizeof (Shdr); 392 dst.d_version = EV_CURRENT; 393 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) || 394 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 395 return (-1); 396 } 397 scncnt = sh.sh_size; 398 } 399 400 fsz *= scncnt; 401 msz = scncnt * sizeof (Shdr); 402 if ((eh->e_shoff == 0) || 403 (elf->ed_fsz <= eh->e_shoff) || 404 (elf->ed_fsz - eh->e_shoff < fsz)) { 405 _elf_seterr(EFMT_SHTAB, 0); 406 return (-1); 407 } 408 409 if (inplace && (fsz >= msz) && 410 ((eh->e_shoff % sizeof (ElfField)) == 0)) { 411 /* LINTED */ 412 elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff); 413 elf->ed_status = ES_COOKED; 414 } else { 415 if ((elf->ed_shdr = malloc(msz)) == 0) { 416 _elf_seterr(EMEM_SHDR, errno); 417 return (-1); 418 } 419 elf->ed_myflags |= EDF_SHALLOC; 420 } 421 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff); 422 src.d_type = ELF_T_SHDR; 423 src.d_size = fsz; 424 src.d_version = elf->ed_version; 425 dst.d_buf = (Elf_Void *)elf->ed_shdr; 426 dst.d_size = msz; 427 dst.d_version = EV_CURRENT; 428 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) || 429 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) || 430 (_elf_prepscn(elf, scncnt) != OK_YES)) { 431 if (elf->ed_myflags & EDF_SHALLOC) { 432 elf->ed_myflags &= ~EDF_SHALLOC; 433 free(elf->ed_shdr); 434 } 435 elf->ed_shdr = 0; 436 return (-1); 437 } 438 return (0); 439 } 440