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