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