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 /* 23 * Copyright (c) 1988 AT&T 24 * 25 * All Rights Reserved 26 * 27 */ 28 29 /* 30 * Copyright (c) 1999 by Sun Microsystems, Inc. 31 * All rights reserved. 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ 35 36 #include "syn.h" 37 #include <ar.h> 38 #include <stdlib.h> 39 #include <memory.h> 40 #include <errno.h> 41 #include <libelf.h> 42 #include "decl.h" 43 #include "msg.h" 44 #include "member.h" 45 46 #define MANGLE '\177' 47 48 49 /* 50 * Archive processing 51 * When processing an archive member, two things can happen 52 * that are a little tricky. 53 * 54 * Sliding 55 * Sliding support is left in for backward compatibility and for 56 * support of Archives produced on other systems. The bundled 57 * ar(1) produces archives with all members on a 4 byte boundry, 58 * so current archives should need no sliding. 59 * 60 * Archive members that are only 2-byte aligned within the file will 61 * be slid. To reuse the file's memory image, the library slides an 62 * archive member into its header to align the bytes. This means 63 * the header must be disposable. 64 * 65 * Header reuse 66 * Because the library can trample the header, it must be preserved to 67 * avoid restrictions on archive member reuse. That is, if the member 68 * header changes, the library may see garbage the next time it looks 69 * at the header. After extracting the original header, the library 70 * appends it to the parents `ed_memlist' list, thus future lookups first 71 * check this list to determine if a member has previously been processed 72 * and whether sliding occured. 73 */ 74 75 76 /* 77 * Size check 78 * If the header is too small, the following generates a negative 79 * subscript for x.x and fails to compile. 80 * 81 * The check is based on sizeof (Elf64) because that's always going 82 * to be at least as big as Elf32. 83 */ 84 85 struct x 86 { 87 char x[sizeof (struct ar_hdr) - 3 * sizeof (Elf64) - 1]; 88 }; 89 90 91 92 static const char fmag[] = ARFMAG; 93 94 95 /* 96 * Convert a string starting at 'p' and ending at 'end' into 97 * an integer. Base is the base of the number being converted 98 * (either 8 or 10). 99 * 100 * Returns the converted integer of the string being scaned. 101 */ 102 unsigned long 103 _elf_number(char * p, char * end, int base) 104 { 105 register unsigned c; 106 register unsigned long n = 0; 107 108 while (p < end) { 109 if ((c = *p - '0') >= base) { 110 while (*p++ == ' ') 111 if (p >= end) 112 return (n); 113 return (0); 114 } 115 n *= base; 116 n += c; 117 ++p; 118 } 119 return (n); 120 } 121 122 123 /* 124 * Convert ar_hdr to Member 125 * Converts ascii file representation to the binary memory values. 126 */ 127 Member * 128 _elf_armem(Elf * elf, char * file, size_t fsz) 129 { 130 register struct ar_hdr *f = (struct ar_hdr *)file; 131 register Member *m; 132 register Memlist *l, * ol; 133 register Memident *i; 134 135 if (fsz < sizeof (struct ar_hdr)) { 136 _elf_seterr(EFMT_ARHDRSZ, 0); 137 return (0); 138 } 139 140 /* 141 * Determine in this member has already been processed 142 */ 143 for (l = elf->ed_memlist, ol = l; l; ol = l, l = l->m_next) 144 for (i = (Memident *)(l + 1); i < l->m_free; i++) 145 if (i->m_offset == file) 146 return (i->m_member); 147 148 if (f->ar_fmag[0] != fmag[0] || f->ar_fmag[1] != fmag[1]) { 149 _elf_seterr(EFMT_ARFMAG, 0); 150 return (0); 151 } 152 153 /* 154 * Allocate a new member structure and assign it to the next free 155 * free memlist ident. 156 */ 157 if ((m = (Member *)malloc(sizeof (Member))) == 0) { 158 _elf_seterr(EMEM_ARMEM, errno); 159 return (0); 160 } 161 if ((elf->ed_memlist == 0) || (ol->m_free == ol->m_end)) { 162 if ((l = (Memlist *)malloc(sizeof (Memlist) + 163 (sizeof (Memident) * MEMIDENTNO))) == 0) { 164 _elf_seterr(EMEM_ARMEM, errno); 165 return (0); 166 } 167 l->m_next = 0; 168 l->m_free = (Memident *)(l + 1); 169 l->m_end = (Memident *)((uintptr_t)l->m_free + 170 (sizeof (Memident) * MEMIDENTNO)); 171 172 if (elf->ed_memlist == 0) 173 elf->ed_memlist = l; 174 else 175 ol->m_next = l; 176 ol = l; 177 } 178 ol->m_free->m_offset = file; 179 ol->m_free->m_member = m; 180 ol->m_free++; 181 182 m->m_err = 0; 183 (void) memcpy(m->m_name, f->ar_name, ARSZ(ar_name)); 184 m->m_name[ARSZ(ar_name)] = '\0'; 185 m->m_hdr.ar_name = m->m_name; 186 (void) memcpy(m->m_raw, f->ar_name, ARSZ(ar_name)); 187 m->m_raw[ARSZ(ar_name)] = '\0'; 188 m->m_hdr.ar_rawname = m->m_raw; 189 m->m_slide = 0; 190 191 /* 192 * Classify file name. 193 * If a name error occurs, delay until getarhdr(). 194 */ 195 196 if (f->ar_name[0] != '/') { /* regular name */ 197 register char *p; 198 199 p = &m->m_name[sizeof (m->m_name)]; 200 while (*--p != '/') 201 if (p <= m->m_name) 202 break; 203 *p = '\0'; 204 } else if (f->ar_name[1] >= '0' && f->ar_name[1] <= '9') { /* strtab */ 205 register unsigned long j; 206 207 j = _elf_number(&f->ar_name[1], 208 &f->ar_name[ARSZ(ar_name)], 10); 209 if (j < elf->ed_arstrsz) 210 m->m_hdr.ar_name = elf->ed_arstr + j; 211 else { 212 m->m_hdr.ar_name = 0; 213 /*LINTED*/ /* MSG_INTL(EFMT_ARSTRNM) */ 214 m->m_err = (int)EFMT_ARSTRNM; 215 } 216 } else if (f->ar_name[1] == ' ') /* "/" */ 217 m->m_name[1] = '\0'; 218 else if (f->ar_name[1] == '/' && f->ar_name[2] == ' ') /* "//" */ 219 m->m_name[2] = '\0'; 220 else { /* "/?" */ 221 m->m_hdr.ar_name = 0; 222 /*LINTED*/ /* MSG_INTL(EFMT_ARUNKNM) */ 223 m->m_err = (int)EFMT_ARUNKNM; 224 } 225 226 m->m_hdr.ar_date = (time_t)_elf_number(f->ar_date, 227 &f->ar_date[ARSZ(ar_date)], 10); 228 /* LINTED */ 229 m->m_hdr.ar_uid = (uid_t)_elf_number(f->ar_uid, 230 &f->ar_uid[ARSZ(ar_uid)], 10); 231 /* LINTED */ 232 m->m_hdr.ar_gid = (gid_t)_elf_number(f->ar_gid, 233 &f->ar_gid[ARSZ(ar_gid)], 10); 234 /* LINTED */ 235 m->m_hdr.ar_mode = (mode_t)_elf_number(f->ar_mode, 236 &f->ar_mode[ARSZ(ar_mode)], 8); 237 m->m_hdr.ar_size = (off_t)_elf_number(f->ar_size, 238 &f->ar_size[ARSZ(ar_size)], 10); 239 240 return (m); 241 } 242 243 244 /* 245 * Initial archive processing 246 * An archive may have two special members. 247 * A symbol table, named /, must be first if it is present. 248 * A string table, named //, must precede all "normal" members. 249 * 250 * This code "peeks" at headers but doesn't change them. 251 * Later processing wants original headers. 252 * 253 * String table is converted, changing '/' name terminators 254 * to nulls. The last byte in the string table, which should 255 * be '\n', is set to nil, guaranteeing null termination. That 256 * byte should be '\n', but this code doesn't check. 257 * 258 * The symbol table conversion is delayed until needed. 259 */ 260 void 261 _elf_arinit(Elf * elf) 262 { 263 char * base = elf->ed_ident; 264 register char * end = base + elf->ed_fsz; 265 register struct ar_hdr * a; 266 register char * hdr = base + SARMAG; 267 register char * mem; 268 int j; 269 size_t sz = SARMAG; 270 271 elf->ed_status = ES_COOKED; 272 elf->ed_nextoff = SARMAG; 273 for (j = 0; j < 2; ++j) { /* 2 special members */ 274 unsigned long n; 275 276 if (((end - hdr) < sizeof (struct ar_hdr)) || 277 (_elf_vm(elf, (size_t)(SARMAG), 278 sizeof (struct ar_hdr)) != OK_YES)) 279 return; 280 281 a = (struct ar_hdr *)hdr; 282 mem = (char *)a + sizeof (struct ar_hdr); 283 n = _elf_number(a->ar_size, &a->ar_size[ARSZ(ar_size)], 10); 284 if ((end - mem < n) || (a->ar_name[0] != '/') || 285 ((sz = n) != n)) { 286 return; 287 } 288 289 hdr = mem + sz; 290 if (a->ar_name[1] == ' ') { 291 elf->ed_arsym = mem; 292 elf->ed_arsymsz = sz; 293 elf->ed_arsymoff = (char *)a - base; 294 } else if (a->ar_name[1] == '/' && a->ar_name[2] == ' ') { 295 int k; 296 297 if (_elf_vm(elf, (size_t)(mem - elf->ed_ident), 298 sz) != OK_YES) 299 return; 300 if (elf->ed_vm == 0) { 301 char * nmem; 302 if ((nmem = malloc(sz)) == 0) { 303 _elf_seterr(EMEM_ARSTR, errno); 304 return; 305 } 306 (void) memcpy(nmem, mem, sz); 307 elf->ed_myflags |= EDF_ASTRALLOC; 308 mem = nmem; 309 } 310 311 elf->ed_arstr = mem; 312 elf->ed_arstrsz = sz; 313 elf->ed_arstroff = (char *)a - base; 314 for (k = 0; k < sz; k++) { 315 if (*mem == '/') 316 *mem = '\0'; 317 ++mem; 318 } 319 *(mem - 1) = '\0'; 320 } else { 321 return; 322 } 323 hdr += sz & 1; 324 } 325 } 326