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