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