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 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * This stuff used to live in cook.c, but was moved out to 34 * facilitate dual (Elf32 and Elf64) compilation. See block 35 * comment in cook.c for more info. 36 */ 37 38 #include <string.h> 39 #include <ar.h> 40 #include <stdlib.h> 41 #include <errno.h> 42 #include "decl.h" 43 #include "member.h" 44 #include "msg.h" 45 46 /* 47 * This module is compiled twice, the second time having 48 * -D_ELF64 defined. The following set of macros, along 49 * with machelf.h, represent the differences between the 50 * two compilations. Be careful *not* to add any class- 51 * dependent code (anything that has elf32 or elf64 in the 52 * name) to this code without hiding it behind a switch- 53 * able macro like these. 54 */ 55 #if defined(_ELF64) 56 #define Snode Snode64 57 #define ELFCLASS ELFCLASS64 58 #define ElfField Elf64 59 #define _elf_snode_init _elf64_snode_init 60 #define _elf_prepscan _elf64_prepscan 61 #define _elf_cookscn _elf64_cookscn 62 #define _elf_mtype _elf64_mtype 63 #define _elf_msize _elf64_msize 64 #define elf_fsize elf64_fsize 65 #define _elf_snode _elf64_snode 66 #define _elf_ehdr _elf64_ehdr 67 #define elf_xlatetom elf64_xlatetom 68 #define _elf_phdr _elf64_phdr 69 #define _elf_shdr _elf64_shdr 70 #define _elf_prepscn _elf64_prepscn 71 72 #else /* Elf32 */ 73 #define Snode Snode32 74 #define ELFCLASS ELFCLASS32 75 #define ElfField Elf32 76 #define _elf_snode_init _elf32_snode_init 77 #define _elf_prepscan _elf32_prepscan 78 #define _elf_cookscn _elf32_cookscn 79 #define _elf_mtype _elf32_mtype 80 #define _elf_msize _elf32_msize 81 #define elf_fsize elf32_fsize 82 #define _elf_snode _elf32_snode 83 #define _elf_ehdr _elf32_ehdr 84 #define elf_xlatetom elf32_xlatetom 85 #define _elf_phdr _elf32_phdr 86 #define _elf_shdr _elf32_shdr 87 #define _elf_prepscn _elf32_prepscn 88 89 #endif /* _ELF64 */ 90 91 92 static Okay 93 _elf_prepscn(Elf *elf, size_t cnt) 94 { 95 NOTE(ASSUMING_PROTECTED(*elf)) 96 Elf_Scn * s; 97 Elf_Scn * end; 98 99 if (cnt == 0) 100 return (OK_YES); 101 102 if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) { 103 _elf_seterr(EMEM_SCN, errno); 104 return (OK_NO); 105 } 106 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s)) 107 elf->ed_scntabsz = cnt; 108 end = s + cnt; 109 elf->ed_hdscn = s; 110 do { 111 *s = _elf_snode_init.sb_scn; 112 s->s_elf = elf; 113 s->s_next = s + 1; 114 s->s_index = s - elf->ed_hdscn; 115 s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index; 116 ELFMUTEXINIT(&s->s_mutex); 117 118 /* 119 * Section has not yet been cooked! 120 * 121 * We don't cook a section until it's data is actually 122 * referenced. 123 */ 124 s->s_myflags = 0; 125 } while (++s < end); 126 127 elf->ed_tlscn = --s; 128 s->s_next = 0; 129 130 /* 131 * Section index SHN_UNDEF (0) does not and cannot 132 * have a data buffer. Fix it here. Also mark the 133 * initial section as being allocated for the block 134 */ 135 136 s = elf->ed_hdscn; 137 s->s_myflags = SF_ALLOC; 138 s->s_hdnode = 0; 139 s->s_tlnode = 0; 140 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s)) 141 return (OK_YES); 142 } 143 144 145 Okay 146 _elf_cookscn(Elf_Scn * s) 147 { 148 NOTE(ASSUMING_PROTECTED(*s, *(s->s_elf))) 149 Elf * elf; 150 Shdr * sh; 151 register Dnode * d = &s->s_dnode; 152 size_t fsz, msz; 153 unsigned work; 154 155 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d)) 156 s->s_hdnode = s->s_tlnode = d; 157 s->s_err = 0; 158 s->s_shflags = 0; 159 s->s_uflags = 0; 160 161 162 /* 163 * Prepare d_data for inspection, but don't actually 164 * translate data until needed. Leave the READY 165 * flag off. NOBITS sections see zero size. 166 */ 167 elf = s->s_elf; 168 sh = s->s_shdr; 169 170 d->db_scn = s; 171 d->db_off = sh->sh_offset; 172 d->db_data.d_align = sh->sh_addralign; 173 d->db_data.d_version = elf->ed_version; 174 ELFACCESSDATA(work, _elf_work) 175 d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work); 176 d->db_data.d_buf = 0; 177 d->db_data.d_off = 0; 178 fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version); 179 msz = _elf_msize(d->db_data.d_type, elf->ed_version); 180 d->db_data.d_size = (sh->sh_size / fsz) * msz; 181 d->db_shsz = sh->sh_size; 182 d->db_raw = 0; 183 d->db_buf = 0; 184 d->db_uflags = 0; 185 d->db_myflags = 0; 186 d->db_next = 0; 187 188 if (sh->sh_type != SHT_NOBITS) 189 d->db_fsz = sh->sh_size; 190 else 191 d->db_fsz = 0; 192 193 s->s_myflags |= SF_READY; 194 195 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d)) 196 return (OK_YES); 197 } 198 199 200 201 Snode * 202 _elf_snode() 203 { 204 register Snode *s; 205 206 if ((s = malloc(sizeof (Snode))) == 0) { 207 _elf_seterr(EMEM_SNODE, errno); 208 return (0); 209 } 210 *s = _elf_snode_init; 211 ELFMUTEXINIT(&s->sb_scn.s_mutex); 212 s->sb_scn.s_myflags = SF_ALLOC | SF_READY; 213 s->sb_scn.s_shdr = &s->sb_shdr; 214 return (s); 215 } 216 217 218 219 int 220 _elf_ehdr(Elf * elf, int inplace) 221 { 222 NOTE(ASSUMING_PROTECTED(*elf)) 223 register size_t fsz; /* field size */ 224 Elf_Data dst, src; 225 226 fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version); 227 if (fsz > elf->ed_fsz) { 228 _elf_seterr(EFMT_EHDRSZ, 0); 229 return (-1); 230 } 231 if (inplace && (fsz >= sizeof (Ehdr))) { 232 /* 233 * The translated Ehdr will fit over the original Ehdr. 234 */ 235 /* LINTED */ 236 elf->ed_ehdr = (Ehdr *)elf->ed_ident; 237 elf->ed_status = ES_COOKED; 238 } else { 239 elf->ed_ehdr = malloc(sizeof (Ehdr)); 240 if (elf->ed_ehdr == 0) { 241 _elf_seterr(EMEM_EHDR, errno); 242 return (-1); 243 } 244 elf->ed_myflags |= EDF_EHALLOC; 245 } 246 247 /* 248 * Memory size >= fsz, because otherwise the memory version 249 * loses information and cannot accurately implement the 250 * file. 251 */ 252 253 src.d_buf = (Elf_Void *)elf->ed_ident; 254 src.d_type = ELF_T_EHDR; 255 src.d_size = fsz; 256 src.d_version = elf->ed_version; 257 dst.d_buf = (Elf_Void *)elf->ed_ehdr; 258 dst.d_size = sizeof (Ehdr); 259 dst.d_version = EV_CURRENT; 260 261 if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) || 262 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 263 if (elf->ed_myflags & EDF_EHALLOC) { 264 elf->ed_myflags &= ~EDF_EHALLOC; 265 free(elf->ed_ehdr); 266 } 267 elf->ed_ehdr = 0; 268 return (-1); 269 } 270 271 if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) { 272 _elf_seterr(EREQ_CLASS, 0); 273 if (elf->ed_myflags & EDF_EHALLOC) { 274 elf->ed_myflags &= ~EDF_EHALLOC; 275 free(elf->ed_ehdr); 276 } 277 elf->ed_ehdr = 0; 278 return (-1); 279 } 280 281 if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) { 282 _elf_seterr(EFMT_VER2, 0); 283 if (elf->ed_myflags & EDF_EHALLOC) { 284 elf->ed_myflags &= ~EDF_EHALLOC; 285 free(elf->ed_ehdr); 286 } 287 elf->ed_ehdr = 0; 288 return (-1); 289 } 290 291 return (0); 292 } 293 294 295 296 int 297 _elf_phdr(Elf * elf, int inplace) 298 { 299 NOTE(ASSUMING_PROTECTED(*elf)) 300 register size_t fsz, msz; 301 Elf_Data dst, src; 302 Ehdr * eh = elf->ed_ehdr; /* must be present */ 303 unsigned work; 304 305 if (eh->e_phnum == 0) 306 return (0); 307 308 fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version); 309 if (eh->e_phentsize != fsz) { 310 _elf_seterr(EFMT_PHDRSZ, 0); 311 return (-1); 312 } 313 314 fsz *= eh->e_phnum; 315 ELFACCESSDATA(work, _elf_work) 316 msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum; 317 if ((eh->e_phoff == 0) || 318 ((fsz + eh->e_phoff) > elf->ed_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