xref: /onnv-gate/usr/src/cmd/sgs/libelf/common/getarsym.c (revision 6812:febeba71273d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*6812Sraf  * Common Development and Distribution License (the "License").
6*6812Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*6812Sraf 
22*6812Sraf /*
23*6812Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6812Sraf  * Use is subject to license terms.
25*6812Sraf  */
26*6812Sraf 
270Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
30*6812Sraf #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <libelf.h>
350Sstevel@tonic-gate #include "decl.h"
360Sstevel@tonic-gate #include "msg.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate  * Convert archive symbol table to memory format
410Sstevel@tonic-gate  *	This takes a pointer to file's archive symbol table,
420Sstevel@tonic-gate  *	alignment unconstrained.  Returns null terminated
430Sstevel@tonic-gate  *	vector of Elf_Arsym structures.
440Sstevel@tonic-gate  *
450Sstevel@tonic-gate  *	Symbol table is the following:
460Sstevel@tonic-gate  *		# offsets	4-byte word
470Sstevel@tonic-gate  *		offset[0...]	4-byte word each
480Sstevel@tonic-gate  *		strings		null-terminated, for offset[x]
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate 
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #define	get4(p)	((((((p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3])
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 
550Sstevel@tonic-gate static Elf_Void	*arsym	_((Byte *, size_t, size_t *));
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 
580Sstevel@tonic-gate Elf_Void *
59*6812Sraf arsym(Byte *off, size_t sz, size_t *e)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	char		*endstr = (char *)off + sz;
620Sstevel@tonic-gate 	register char	*str;
630Sstevel@tonic-gate 	Byte		*endoff;
640Sstevel@tonic-gate 	Elf_Void	*oas;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	{
670Sstevel@tonic-gate 		register size_t	n;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 		if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) {
700Sstevel@tonic-gate 			_elf_seterr(EFMT_ARSYMSZ, 0);
710Sstevel@tonic-gate 			return (0);
720Sstevel@tonic-gate 		}
730Sstevel@tonic-gate 		off += 4;
740Sstevel@tonic-gate 		endoff = off + n * 4;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 		/*
770Sstevel@tonic-gate 		 * string table must be present, null terminated
780Sstevel@tonic-gate 		 */
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 		if (((str = (char *)endoff) >= endstr) ||
810Sstevel@tonic-gate 		    (*(endstr - 1) != '\0')) {
820Sstevel@tonic-gate 			_elf_seterr(EFMT_ARSYM, 0);
830Sstevel@tonic-gate 			return (0);
840Sstevel@tonic-gate 		}
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 		/*
870Sstevel@tonic-gate 		 * overflow can occur here, but not likely
880Sstevel@tonic-gate 		 */
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 		*e = n + 1;
910Sstevel@tonic-gate 		n = sizeof (Elf_Arsym) * (n + 1);
920Sstevel@tonic-gate 		if ((oas = malloc(n)) == 0) {
930Sstevel@tonic-gate 			_elf_seterr(EMEM_ARSYM, errno);
940Sstevel@tonic-gate 			return (0);
950Sstevel@tonic-gate 		}
960Sstevel@tonic-gate 	}
970Sstevel@tonic-gate 	{
980Sstevel@tonic-gate 		register Elf_Arsym	*as = (Elf_Arsym *)oas;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 		while (off < endoff) {
1010Sstevel@tonic-gate 			if (str >= endstr) {
1020Sstevel@tonic-gate 				_elf_seterr(EFMT_ARSYMSTR, 0);
1030Sstevel@tonic-gate 				free(oas);
1040Sstevel@tonic-gate 				return (0);
1050Sstevel@tonic-gate 			}
1060Sstevel@tonic-gate 			as->as_off = get4(off);
1070Sstevel@tonic-gate 			as->as_name = str;
1080Sstevel@tonic-gate 			as->as_hash = elf_hash(str);
1090Sstevel@tonic-gate 			++as;
1100Sstevel@tonic-gate 			off += 4;
1110Sstevel@tonic-gate 			while (*str++ != '\0')
1120Sstevel@tonic-gate 				/* LINTED */
1130Sstevel@tonic-gate 				;
1140Sstevel@tonic-gate 		}
1150Sstevel@tonic-gate 		as->as_name = 0;
1160Sstevel@tonic-gate 		as->as_off = 0;
1170Sstevel@tonic-gate 		as->as_hash = ~(unsigned long)0L;
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 	return (oas);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate Elf_Arsym *
124*6812Sraf elf_getarsym(Elf *elf, size_t *ptr)
1250Sstevel@tonic-gate {
126*6812Sraf 	Byte		*as;
1270Sstevel@tonic-gate 	size_t		sz;
128*6812Sraf 	Elf_Arsym	*rc;
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if (ptr != 0)
1310Sstevel@tonic-gate 		*ptr = 0;
1320Sstevel@tonic-gate 	if (elf == 0)
1330Sstevel@tonic-gate 		return (0);
1340Sstevel@tonic-gate 	ELFRLOCK(elf);
1350Sstevel@tonic-gate 	if (elf->ed_kind != ELF_K_AR) {
1360Sstevel@tonic-gate 		ELFUNLOCK(elf);
1370Sstevel@tonic-gate 		_elf_seterr(EREQ_AR, 0);
1380Sstevel@tonic-gate 		return (0);
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 	if ((as = (Byte *)elf->ed_arsym) == 0) {
1410Sstevel@tonic-gate 		ELFUNLOCK(elf);
1420Sstevel@tonic-gate 		return (0);
1430Sstevel@tonic-gate 	}
1440Sstevel@tonic-gate 	if (elf->ed_myflags & EDF_ASALLOC) {
1450Sstevel@tonic-gate 		if (ptr != 0)
1460Sstevel@tonic-gate 			*ptr = elf->ed_arsymsz;
1470Sstevel@tonic-gate 		ELFUNLOCK(elf);
1480Sstevel@tonic-gate 		/* LINTED */
1490Sstevel@tonic-gate 		return ((Elf_Arsym *)as);
1500Sstevel@tonic-gate 	}
1510Sstevel@tonic-gate 	/*
1520Sstevel@tonic-gate 	 * We're gonna need a write lock.
1530Sstevel@tonic-gate 	 */
1540Sstevel@tonic-gate 	ELFUNLOCK(elf)
1550Sstevel@tonic-gate 	ELFWLOCK(elf)
1560Sstevel@tonic-gate 	sz = elf->ed_arsymsz;
1570Sstevel@tonic-gate 	if (_elf_vm(elf, (size_t)(as - (Byte *)elf->ed_ident), sz) !=
1580Sstevel@tonic-gate 	    OK_YES) {
1590Sstevel@tonic-gate 		ELFUNLOCK(elf);
1600Sstevel@tonic-gate 		return (0);
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate 	if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz)) == 0) {
1630Sstevel@tonic-gate 		ELFUNLOCK(elf);
1640Sstevel@tonic-gate 		return (0);
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 	elf->ed_myflags |= EDF_ASALLOC;
1670Sstevel@tonic-gate 	if (ptr != 0)
1680Sstevel@tonic-gate 		*ptr = elf->ed_arsymsz;
1690Sstevel@tonic-gate 	rc = (Elf_Arsym *)elf->ed_arsym;
1700Sstevel@tonic-gate 	ELFUNLOCK(elf);
1710Sstevel@tonic-gate 	return (rc);
1720Sstevel@tonic-gate }
173