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 #include <stdlib.h> 33 #include <errno.h> 34 #include <libelf.h> 35 #include "decl.h" 36 #include "msg.h" 37 38 39 /* 40 * Convert archive symbol table to memory format 41 * This takes a pointer to file's archive symbol table, 42 * alignment unconstrained. Returns null terminated 43 * vector of Elf_Arsym structures. 44 * 45 * Symbol table is the following: 46 * # offsets 4-byte word 47 * offset[0...] 4-byte word each 48 * strings null-terminated, for offset[x] 49 */ 50 51 52 #define get4(p) ((((((p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3]) 53 54 55 static Elf_Void *arsym _((Byte *, size_t, size_t *)); 56 57 58 Elf_Void * 59 arsym(Byte *off, size_t sz, size_t *e) 60 { 61 char *endstr = (char *)off + sz; 62 register char *str; 63 Byte *endoff; 64 Elf_Void *oas; 65 66 { 67 register size_t n; 68 69 if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) { 70 _elf_seterr(EFMT_ARSYMSZ, 0); 71 return (0); 72 } 73 off += 4; 74 endoff = off + n * 4; 75 76 /* 77 * string table must be present, null terminated 78 */ 79 80 if (((str = (char *)endoff) >= endstr) || 81 (*(endstr - 1) != '\0')) { 82 _elf_seterr(EFMT_ARSYM, 0); 83 return (0); 84 } 85 86 /* 87 * overflow can occur here, but not likely 88 */ 89 90 *e = n + 1; 91 n = sizeof (Elf_Arsym) * (n + 1); 92 if ((oas = malloc(n)) == 0) { 93 _elf_seterr(EMEM_ARSYM, errno); 94 return (0); 95 } 96 } 97 { 98 register Elf_Arsym *as = (Elf_Arsym *)oas; 99 100 while (off < endoff) { 101 if (str >= endstr) { 102 _elf_seterr(EFMT_ARSYMSTR, 0); 103 free(oas); 104 return (0); 105 } 106 as->as_off = get4(off); 107 as->as_name = str; 108 as->as_hash = elf_hash(str); 109 ++as; 110 off += 4; 111 while (*str++ != '\0') 112 /* LINTED */ 113 ; 114 } 115 as->as_name = 0; 116 as->as_off = 0; 117 as->as_hash = ~(unsigned long)0L; 118 } 119 return (oas); 120 } 121 122 123 Elf_Arsym * 124 elf_getarsym(Elf *elf, size_t *ptr) 125 { 126 Byte *as; 127 size_t sz; 128 Elf_Arsym *rc; 129 130 if (ptr != 0) 131 *ptr = 0; 132 if (elf == 0) 133 return (0); 134 ELFRLOCK(elf); 135 if (elf->ed_kind != ELF_K_AR) { 136 ELFUNLOCK(elf); 137 _elf_seterr(EREQ_AR, 0); 138 return (0); 139 } 140 if ((as = (Byte *)elf->ed_arsym) == 0) { 141 ELFUNLOCK(elf); 142 return (0); 143 } 144 if (elf->ed_myflags & EDF_ASALLOC) { 145 if (ptr != 0) 146 *ptr = elf->ed_arsymsz; 147 ELFUNLOCK(elf); 148 /* LINTED */ 149 return ((Elf_Arsym *)as); 150 } 151 /* 152 * We're gonna need a write lock. 153 */ 154 ELFUNLOCK(elf) 155 ELFWLOCK(elf) 156 sz = elf->ed_arsymsz; 157 if (_elf_vm(elf, (size_t)(as - (Byte *)elf->ed_ident), sz) != 158 OK_YES) { 159 ELFUNLOCK(elf); 160 return (0); 161 } 162 if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz)) == 0) { 163 ELFUNLOCK(elf); 164 return (0); 165 } 166 elf->ed_myflags |= EDF_ASALLOC; 167 if (ptr != 0) 168 *ptr = elf->ed_arsymsz; 169 rc = (Elf_Arsym *)elf->ed_arsym; 170 ELFUNLOCK(elf); 171 return (rc); 172 } 173