xref: /titanic_52/usr/src/cmd/sgs/libld/common/util.c (revision c5accfb2728453a874214835d99897e09a0cf3f2)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
231007fd6fSAli Bahrami  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257257d1b4Sraf 
267257d1b4Sraf /*
277257d1b4Sraf  *	Copyright (c) 1988 AT&T
287257d1b4Sraf  *	  All Rights Reserved
297257d1b4Sraf  */
307257d1b4Sraf 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Utility functions
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <stdio.h>
365aefb655Srie #include <stdarg.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <fcntl.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <sys/mman.h>
417c478bd9Sstevel@tonic-gate #include <errno.h>
425aefb655Srie #include <sgs.h>
437257d1b4Sraf #include <libintl.h>
447c478bd9Sstevel@tonic-gate #include <debug.h>
457c478bd9Sstevel@tonic-gate #include "msg.h"
467c478bd9Sstevel@tonic-gate #include "_libld.h"
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * libld_malloc() and dz_map() are used for both performance and for ease of
507c478bd9Sstevel@tonic-gate  * programming:
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * Performance:
537c478bd9Sstevel@tonic-gate  *	The link-edit is a short lived process which doesn't really free much
547c478bd9Sstevel@tonic-gate  *	of the dynamic memory that it requests.  Because of this, it is more
557c478bd9Sstevel@tonic-gate  *	important to optimize for quick memory allocations than the
567c478bd9Sstevel@tonic-gate  *	re-usability of the memory.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  *	By also mmaping blocks of pages in from /dev/zero we don't need to
597c478bd9Sstevel@tonic-gate  *	waste the overhead of zeroing out these pages for calloc() requests.
607c478bd9Sstevel@tonic-gate  *
617c478bd9Sstevel@tonic-gate  * Memory Management:
627c478bd9Sstevel@tonic-gate  *	By doing all libld memory management through the ld_malloc routine
637c478bd9Sstevel@tonic-gate  *	it's much easier to free up all memory at the end by simply unmaping
647c478bd9Sstevel@tonic-gate  *	all of the blocks that were mapped in through dz_map().  This is much
657c478bd9Sstevel@tonic-gate  *	simpler then trying to track all of the libld structures that were
667c478bd9Sstevel@tonic-gate  *	dynamically allocate and are actually pointers into the ELF files.
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  *	It's important that we can free up all of our dynamic memory because
697c478bd9Sstevel@tonic-gate  *	libld is used by ld.so.1 when it performs dlopen()'s of relocatable
707c478bd9Sstevel@tonic-gate  *	objects.
717c478bd9Sstevel@tonic-gate  *
727c478bd9Sstevel@tonic-gate  * Format:
737c478bd9Sstevel@tonic-gate  *	The memory blocks for each allocation store the size of the allocation
747c478bd9Sstevel@tonic-gate  *	in the first 8 bytes of the block.  The pointer that is returned by
757c478bd9Sstevel@tonic-gate  *	libld_malloc() is actually the address of (block + 8):
767c478bd9Sstevel@tonic-gate  *
777c478bd9Sstevel@tonic-gate  *		(addr - 8)	block_size
787c478bd9Sstevel@tonic-gate  *		(addr)		<allocated block>
797c478bd9Sstevel@tonic-gate  *
807c478bd9Sstevel@tonic-gate  *	The size is retained in order to implement realloc(), and to perform
817c478bd9Sstevel@tonic-gate  *	the required memcpy().  8 bytes are uses, as the memory area returned
827c478bd9Sstevel@tonic-gate  *	by libld_malloc() must be 8 byte-aligned.  Even in a 32-bit environment,
837c478bd9Sstevel@tonic-gate  *	u_longlog_t pointers are employed.
847c478bd9Sstevel@tonic-gate  *
850e233487SRod Evans  * Map anonymous memory via MAP_ANON (added in Solaris 8).
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate static void *
887c478bd9Sstevel@tonic-gate dz_map(size_t size)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	void	*addr;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC),
930e233487SRod Evans 	    (MAP_PRIVATE | MAP_ANON), -1, 0)) == MAP_FAILED) {
940e233487SRod Evans 		int	err = errno;
951007fd6fSAli Bahrami 		eprintf(NULL, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON),
960e233487SRod Evans 		    strerror(err));
977c478bd9Sstevel@tonic-gate 		return (MAP_FAILED);
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 	return (addr);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate void *
1037c478bd9Sstevel@tonic-gate libld_malloc(size_t size)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	Ld_heap		*chp = ld_heap;
1067c478bd9Sstevel@tonic-gate 	void		*vptr;
1077c478bd9Sstevel@tonic-gate 	size_t		asize = size + HEAPALIGN;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	/*
1107c478bd9Sstevel@tonic-gate 	 * If this is the first allocation, or the allocation request is greater
1117c478bd9Sstevel@tonic-gate 	 * than the current free space available, allocate a new heap.
1127c478bd9Sstevel@tonic-gate 	 */
11357ef7aa9SRod Evans 	if ((chp == NULL) ||
1147c478bd9Sstevel@tonic-gate 	    (((size_t)chp->lh_end - (size_t)chp->lh_free) <= asize)) {
1157c478bd9Sstevel@tonic-gate 		Ld_heap	*nhp;
1167c478bd9Sstevel@tonic-gate 		size_t	hsize = (size_t)S_ROUND(sizeof (Ld_heap), HEAPALIGN);
1177c478bd9Sstevel@tonic-gate 		size_t	tsize = (size_t)S_ROUND((asize + hsize), HEAPALIGN);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 		/*
1207c478bd9Sstevel@tonic-gate 		 * Allocate a block that is at minimum 'HEAPBLOCK' size
1217c478bd9Sstevel@tonic-gate 		 */
1227c478bd9Sstevel@tonic-gate 		if (tsize < HEAPBLOCK)
1237c478bd9Sstevel@tonic-gate 			tsize = HEAPBLOCK;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 		if ((nhp = dz_map(tsize)) == MAP_FAILED)
1260e233487SRod Evans 			return (NULL);
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 		nhp->lh_next = chp;
1297c478bd9Sstevel@tonic-gate 		nhp->lh_free = (void *)((size_t)nhp + hsize);
1307c478bd9Sstevel@tonic-gate 		nhp->lh_end = (void *)((size_t)nhp + tsize);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 		ld_heap = chp = nhp;
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 	vptr = chp->lh_free;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/*
1377c478bd9Sstevel@tonic-gate 	 * Assign size to head of allocated block (used by realloc), and
1387c478bd9Sstevel@tonic-gate 	 * memory arena as then next 8-byte aligned offset.
1397c478bd9Sstevel@tonic-gate 	 */
1407c478bd9Sstevel@tonic-gate 	*((size_t *)vptr) = size;
1417c478bd9Sstevel@tonic-gate 	vptr = (void *)((size_t)vptr + HEAPALIGN);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/*
1447c478bd9Sstevel@tonic-gate 	 * Increment free to point to next available block
1457c478bd9Sstevel@tonic-gate 	 */
1467c478bd9Sstevel@tonic-gate 	chp->lh_free = (void *)S_ROUND((size_t)chp->lh_free + asize,
1477c478bd9Sstevel@tonic-gate 	    HEAPALIGN);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	return (vptr);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate void *
1537c478bd9Sstevel@tonic-gate libld_realloc(void *ptr, size_t size)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	size_t	psize;
1567c478bd9Sstevel@tonic-gate 	void	*vptr;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
1597c478bd9Sstevel@tonic-gate 		return (libld_malloc(size));
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/*
1627c478bd9Sstevel@tonic-gate 	 * Size of the allocated blocks is stored *just* before the blocks
1637c478bd9Sstevel@tonic-gate 	 * address.
1647c478bd9Sstevel@tonic-gate 	 */
1657c478bd9Sstevel@tonic-gate 	psize = *((size_t *)((size_t)ptr - HEAPALIGN));
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	/*
1687c478bd9Sstevel@tonic-gate 	 * If the block actually fits then just return.
1697c478bd9Sstevel@tonic-gate 	 */
1707c478bd9Sstevel@tonic-gate 	if (size <= psize)
1717c478bd9Sstevel@tonic-gate 		return (ptr);
1727c478bd9Sstevel@tonic-gate 
17357ef7aa9SRod Evans 	if ((vptr = libld_malloc(size)) != NULL)
1747c478bd9Sstevel@tonic-gate 		(void) memcpy(vptr, ptr, psize);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	return (vptr);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate void
1807c478bd9Sstevel@tonic-gate /* ARGSUSED 0 */
1817c478bd9Sstevel@tonic-gate libld_free(void *ptr)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * Determine if a shared object definition structure already exists and if
1877c478bd9Sstevel@tonic-gate  * not create one.  These definitions provide for recording information
1887c478bd9Sstevel@tonic-gate  * regarding shared objects that are still to be processed.  Once processed
1897c478bd9Sstevel@tonic-gate  * shared objects are maintained on the ofl_sos list.  The information
1907c478bd9Sstevel@tonic-gate  * recorded in this structure includes:
1917c478bd9Sstevel@tonic-gate  *
1927c478bd9Sstevel@tonic-gate  *  o	DT_USED requirements.  In these cases definitions are added during
1937c478bd9Sstevel@tonic-gate  *	mapfile processing of `-' entries (see map_dash()).
1947c478bd9Sstevel@tonic-gate  *
1957c478bd9Sstevel@tonic-gate  *  o	implicit NEEDED entries.  As shared objects are processed from the
1967c478bd9Sstevel@tonic-gate  *	command line so any of their dependencies are recorded in these
1977c478bd9Sstevel@tonic-gate  *	structures for later processing (see process_dynamic()).
1987c478bd9Sstevel@tonic-gate  *
1997c478bd9Sstevel@tonic-gate  *  o	version requirements.  Any explicit shared objects that have version
2007c478bd9Sstevel@tonic-gate  *	dependencies on other objects have their version requirements recorded.
2017c478bd9Sstevel@tonic-gate  *	In these cases definitions are added during mapfile processing of `-'
2027c478bd9Sstevel@tonic-gate  *	entries (see map_dash()).  Also, shared objects may have versioning
2037c478bd9Sstevel@tonic-gate  *	requirements on their NEEDED entries.  These cases are added during
2047c478bd9Sstevel@tonic-gate  *	their version processing (see vers_need_process()).
2057c478bd9Sstevel@tonic-gate  *
2067c478bd9Sstevel@tonic-gate  *	Note: Both process_dynamic() and vers_need_process() may generate the
2077c478bd9Sstevel@tonic-gate  *	initial version definition structure because you can't rely on what
2087c478bd9Sstevel@tonic-gate  *	section (.dynamic or .SUNW_version) may be processed first from	any
2097c478bd9Sstevel@tonic-gate  *	input file.
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate Sdf_desc *
21257ef7aa9SRod Evans sdf_find(const char *name, APlist *alp)
2137c478bd9Sstevel@tonic-gate {
21457ef7aa9SRod Evans 	Aliste		idx;
2157c478bd9Sstevel@tonic-gate 	Sdf_desc	*sdf;
2167c478bd9Sstevel@tonic-gate 
21757ef7aa9SRod Evans 	for (APLIST_TRAVERSE(alp, idx, sdf))
2187c478bd9Sstevel@tonic-gate 		if (strcmp(name, sdf->sdf_name) == 0)
2197c478bd9Sstevel@tonic-gate 			return (sdf);
2207c478bd9Sstevel@tonic-gate 
2210e233487SRod Evans 	return (NULL);
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate Sdf_desc *
22557ef7aa9SRod Evans sdf_add(const char *name, APlist **alpp)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate 	Sdf_desc	*sdf;
2287c478bd9Sstevel@tonic-gate 
22957ef7aa9SRod Evans 	if ((sdf = libld_calloc(sizeof (Sdf_desc), 1)) == NULL)
2307c478bd9Sstevel@tonic-gate 		return ((Sdf_desc *)S_ERROR);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	sdf->sdf_name = name;
2337c478bd9Sstevel@tonic-gate 
23457ef7aa9SRod Evans 	if (aplist_append(alpp, sdf, AL_CNT_OFL_LIBS) == NULL)
2357c478bd9Sstevel@tonic-gate 		return ((Sdf_desc *)S_ERROR);
23657ef7aa9SRod Evans 
2377c478bd9Sstevel@tonic-gate 	return (sdf);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate /*
2417c478bd9Sstevel@tonic-gate  * Add a string, separated by a colon, to an existing string.  Typically used
2427c478bd9Sstevel@tonic-gate  * to maintain filter, rpath and audit names, of which there is normally only
2437c478bd9Sstevel@tonic-gate  * one string supplied anyway.
2447c478bd9Sstevel@tonic-gate  */
2457c478bd9Sstevel@tonic-gate char *
2467c478bd9Sstevel@tonic-gate add_string(char *old, char *str)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	char	*new;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	if (old) {
2517c478bd9Sstevel@tonic-gate 		char	*_str;
2527c478bd9Sstevel@tonic-gate 		size_t	len;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 		/*
2557c478bd9Sstevel@tonic-gate 		 * If an original string exists, make sure this new string
2567c478bd9Sstevel@tonic-gate 		 * doesn't get duplicated.
2577c478bd9Sstevel@tonic-gate 		 */
2587c478bd9Sstevel@tonic-gate 		if ((_str = strstr(old, str)) != NULL) {
2597c478bd9Sstevel@tonic-gate 			if (((_str == old) ||
2607c478bd9Sstevel@tonic-gate 			    (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) &&
2617c478bd9Sstevel@tonic-gate 			    (_str += strlen(str)) &&
2627c478bd9Sstevel@tonic-gate 			    ((*_str == '\0') ||
2637c478bd9Sstevel@tonic-gate 			    (*_str == *(MSG_ORIG(MSG_STR_COLON)))))
2647c478bd9Sstevel@tonic-gate 				return (old);
2657c478bd9Sstevel@tonic-gate 		}
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		len = strlen(old) + strlen(str) + 2;
2680e233487SRod Evans 		if ((new = libld_calloc(1, len)) == NULL)
2697c478bd9Sstevel@tonic-gate 			return ((char *)S_ERROR);
2707c478bd9Sstevel@tonic-gate 		(void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str);
2717c478bd9Sstevel@tonic-gate 	} else {
2720e233487SRod Evans 		if ((new = libld_malloc(strlen(str) + 1)) == NULL)
2737c478bd9Sstevel@tonic-gate 			return ((char *)S_ERROR);
2747c478bd9Sstevel@tonic-gate 		(void) strcpy(new, str);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	return (new);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate /*
281cdcc71c0SAli Bahrami  * The GNU ld '-wrap=XXX' and '--wrap=XXX' options correspond to our
282cdcc71c0SAli Bahrami  * '-z wrap=XXX'. When str2chr() does this conversion, we end up with
283cdcc71c0SAli Bahrami  * the return character set to 'z' and optarg set to 'XXX'. This callback
284cdcc71c0SAli Bahrami  * changes optarg to include the missing wrap= prefix.
285cdcc71c0SAli Bahrami  *
286cdcc71c0SAli Bahrami  * exit:
287cdcc71c0SAli Bahrami  *	Returns c on success, or '?' on error.
288cdcc71c0SAli Bahrami  */
289cdcc71c0SAli Bahrami static int
290cdcc71c0SAli Bahrami str2chr_wrap_cb(int c)
291cdcc71c0SAli Bahrami {
292cdcc71c0SAli Bahrami 	char    *str;
293cdcc71c0SAli Bahrami 	size_t  len = MSG_ARG_WRAP_SIZE + strlen(optarg) + 1;
294cdcc71c0SAli Bahrami 
295cdcc71c0SAli Bahrami 	if ((str = libld_malloc(len)) == NULL)
296cdcc71c0SAli Bahrami 		return ('?');
297cdcc71c0SAli Bahrami 	(void) snprintf(str, len, MSG_ORIG(MSG_FMT_STRCAT),
298cdcc71c0SAli Bahrami 	    MSG_ORIG(MSG_ARG_WRAP), optarg);
299cdcc71c0SAli Bahrami 	optarg = str;
300cdcc71c0SAli Bahrami 	return (c);
301cdcc71c0SAli Bahrami }
302cdcc71c0SAli Bahrami 
303cdcc71c0SAli Bahrami /*
304*c5accfb2SRichard Lowe  * Determine whether this string, possibly with an associated option, should
305*c5accfb2SRichard Lowe  * be translated to an option character.  If so, update the optind and optarg
306*c5accfb2SRichard Lowe  * and optopt as described for short options in getopt(3c).
307cdcc71c0SAli Bahrami  *
308cdcc71c0SAli Bahrami  * entry:
309cdcc71c0SAli Bahrami  *	lml - Link map list for debug messages
310cdcc71c0SAli Bahrami  *	ndx - Starting optind for current item
311cdcc71c0SAli Bahrami  *	argc, argv - Command line arguments
312cdcc71c0SAli Bahrami  *	arg - Option to be examined
313cdcc71c0SAli Bahrami  *	c, opt - Option character (c) and corresponding long name (opt)
314cdcc71c0SAli Bahrami  *	optsz - 0 if option does not accept a value. If option does
315cdcc71c0SAli Bahrami  *		accept a value, strlen(opt), giving the offset to the
316cdcc71c0SAli Bahrami  *		value if the option and value are combined in one string.
317cdcc71c0SAli Bahrami  *	cbfunc - NULL, or pointer to function to call if a translation is
318cdcc71c0SAli Bahrami  *		successful.
31992a02081SRod Evans  */
32092a02081SRod Evans static int
32192a02081SRod Evans str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c,
322cdcc71c0SAli Bahrami     const char *opt, size_t optsz, int cbfunc(int))
32392a02081SRod Evans {
32492a02081SRod Evans 	if (optsz == 0) {
32592a02081SRod Evans 		/*
32692a02081SRod Evans 		 * Compare a single option (ie. there's no associated option
32792a02081SRod Evans 		 * argument).
32892a02081SRod Evans 		 */
32992a02081SRod Evans 		if (strcmp(arg, opt) == 0) {
33092a02081SRod Evans 			DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
33192a02081SRod Evans 			optind += 1;
332*c5accfb2SRichard Lowe 			optopt = c;
33392a02081SRod Evans 			return (c);
33492a02081SRod Evans 		}
33544a646f1SRichard Lowe 	} else if ((strcmp(arg, opt) == 0) ||
33644a646f1SRichard Lowe 	    ((arg[optsz] == '=') && strncmp(arg, opt, optsz) == 0)) {
33792a02081SRod Evans 		/*
33892a02081SRod Evans 		 * Otherwise, compare the option name, which may be
33992a02081SRod Evans 		 * concatenated with the option argument.
34092a02081SRod Evans 		 */
34192a02081SRod Evans 		DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
34292a02081SRod Evans 
34392a02081SRod Evans 		if (arg[optsz] == '\0') {
34492a02081SRod Evans 			/*
34592a02081SRod Evans 			 * Optarg is the next argument (white space separated).
34692a02081SRod Evans 			 * Make sure an optarg is available, and if not return
34792a02081SRod Evans 			 * a failure to prevent any fall-through to the generic
34892a02081SRod Evans 			 * getopt() processing.
349*c5accfb2SRichard Lowe 			 *
350*c5accfb2SRichard Lowe 			 * Since we'll be completely failing this option we
351*c5accfb2SRichard Lowe 			 * don't want to update optopt with the translation,
352*c5accfb2SRichard Lowe 			 * but also need to set it to _something_.  Setting it
353*c5accfb2SRichard Lowe 			 * to the '-' of the argument causes us to behave
354*c5accfb2SRichard Lowe 			 * correctly.
35592a02081SRod Evans 			 */
35692a02081SRod Evans 			if ((++optind + 1) > argc) {
357*c5accfb2SRichard Lowe 				optopt = arg[0];
35892a02081SRod Evans 				return ('?');
35992a02081SRod Evans 			}
36092a02081SRod Evans 			optarg = argv[optind];
36192a02081SRod Evans 			optind++;
36292a02081SRod Evans 		} else {
36392a02081SRod Evans 			/*
36492a02081SRod Evans 			 * GNU option/option argument pairs can be represented
36592a02081SRod Evans 			 * with a "=" separator.  If this is the case, remove
36692a02081SRod Evans 			 * the separator.
36792a02081SRod Evans 			 */
36892a02081SRod Evans 			optarg = &arg[optsz];
36992a02081SRod Evans 			optind++;
37092a02081SRod Evans 			if (*optarg == '=') {
371*c5accfb2SRichard Lowe 				if (*(++optarg) == '\0') {
372*c5accfb2SRichard Lowe 					optopt = arg[0];
37392a02081SRod Evans 					return ('?');
37492a02081SRod Evans 				}
37592a02081SRod Evans 			}
376*c5accfb2SRichard Lowe 		}
377cdcc71c0SAli Bahrami 
378cdcc71c0SAli Bahrami 		if (cbfunc != NULL)
379cdcc71c0SAli Bahrami 			c = (*cbfunc)(c);
380*c5accfb2SRichard Lowe 		optopt = c;
38192a02081SRod Evans 		return (c);
38292a02081SRod Evans 	}
38392a02081SRod Evans 	return (0);
38492a02081SRod Evans }
38592a02081SRod Evans 
38692a02081SRod Evans /*
38792a02081SRod Evans  * Parse an individual option.  The intent of this function is to determine if
38892a02081SRod Evans  * any known, non-Solaris options have been passed to ld(1).  This condition
38992a02081SRod Evans  * can occur as a result of build configuration tools, because of users
39092a02081SRod Evans  * familiarity with other systems, or simply the users preferences.  If a known
39192a02081SRod Evans  * non-Solaris option can be determined, translate that option into the Solaris
39292a02081SRod Evans  * counterpart.
39392a02081SRod Evans  *
39492a02081SRod Evans  * This function will probably never be a complete solution, as new, non-Solaris
39592a02081SRod Evans  * options are discovered, their translation will have to be added.  Other
39692a02081SRod Evans  * non-Solaris options are incompatible with the Solaris link-editor, and will
39792a02081SRod Evans  * never be recognized.  We support what we can.
39892a02081SRod Evans  */
39992a02081SRod Evans int
40092a02081SRod Evans ld_getopt(Lm_list *lml, int ndx, int argc, char **argv)
40192a02081SRod Evans {
40292a02081SRod Evans 	int	c;
40392a02081SRod Evans 
40492a02081SRod Evans 	if ((optind < argc) && argv[optind] && (argv[optind][0] == '-')) {
40592a02081SRod Evans 		char	*arg = &argv[optind][1];
40692a02081SRod Evans 
40792a02081SRod Evans 		switch (*arg) {
40892a02081SRod Evans 		case 'r':
40992a02081SRod Evans 			/* Translate -rpath <optarg> to -R <optarg> */
41092a02081SRod Evans 			if ((c = str2chr(lml, ndx, argc, argv, arg, 'R',
41192a02081SRod Evans 			    MSG_ORIG(MSG_ARG_T_RPATH),
412cdcc71c0SAli Bahrami 			    MSG_ARG_T_RPATH_SIZE, NULL)) != 0) {
41392a02081SRod Evans 				return (c);
41492a02081SRod Evans 			}
41592a02081SRod Evans 			break;
41692a02081SRod Evans 		case 's':
41792a02081SRod Evans 			/* Translate -shared to -G */
41892a02081SRod Evans 			if ((c = str2chr(lml, ndx, argc, argv, arg, 'G',
419cdcc71c0SAli Bahrami 			    MSG_ORIG(MSG_ARG_T_SHARED), 0, NULL)) != 0) {
42092a02081SRod Evans 				return (c);
42192a02081SRod Evans 
42292a02081SRod Evans 			/* Translate -soname <optarg> to -h <optarg> */
42392a02081SRod Evans 			} else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h',
42492a02081SRod Evans 			    MSG_ORIG(MSG_ARG_T_SONAME),
425cdcc71c0SAli Bahrami 			    MSG_ARG_T_SONAME_SIZE, NULL)) != 0) {
426cdcc71c0SAli Bahrami 				return (c);
427cdcc71c0SAli Bahrami 			}
428cdcc71c0SAli Bahrami 			break;
429cdcc71c0SAli Bahrami 		case 'w':
430cdcc71c0SAli Bahrami 			/* Translate -wrap to -z wrap= */
431cdcc71c0SAli Bahrami 			if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
432cdcc71c0SAli Bahrami 			    MSG_ORIG(MSG_ARG_T_WRAP) + 1,
433cdcc71c0SAli Bahrami 			    MSG_ARG_T_WRAP_SIZE - 1, str2chr_wrap_cb)) != 0) {
43492a02081SRod Evans 				return (c);
43592a02081SRod Evans 			}
43692a02081SRod Evans 			break;
437551cffe3SAli Bahrami 		case '(':
438551cffe3SAli Bahrami 			/*
439551cffe3SAli Bahrami 			 * Translate -( to -z rescan-start
440551cffe3SAli Bahrami 			 */
441551cffe3SAli Bahrami 			if ((c = str2chr(lml, ndx, argc, argv,
442cdcc71c0SAli Bahrami 			    arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0, NULL)) !=
443cdcc71c0SAli Bahrami 			    0) {
444551cffe3SAli Bahrami 				optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START);
445551cffe3SAli Bahrami 				return (c);
446551cffe3SAli Bahrami 			}
447551cffe3SAli Bahrami 			break;
448551cffe3SAli Bahrami 		case ')':
449551cffe3SAli Bahrami 			/*
450551cffe3SAli Bahrami 			 * Translate -) to -z rescan-end
451551cffe3SAli Bahrami 			 */
452551cffe3SAli Bahrami 			if ((c = str2chr(lml, ndx, argc, argv,
453cdcc71c0SAli Bahrami 			    arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0, NULL)) !=
454cdcc71c0SAli Bahrami 			    0) {
455551cffe3SAli Bahrami 				optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END);
456551cffe3SAli Bahrami 				return (c);
457551cffe3SAli Bahrami 			}
458551cffe3SAli Bahrami 			break;
45992a02081SRod Evans 		case '-':
46092a02081SRod Evans 			switch (*(arg + 1)) {
46192a02081SRod Evans 			case 'a':
46292a02081SRod Evans 				/*
46392a02081SRod Evans 				 * Translate --allow-multiple-definition to
46492a02081SRod Evans 				 * -zmuldefs
46592a02081SRod Evans 				 */
46692a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
467cdcc71c0SAli Bahrami 				    MSG_ORIG(MSG_ARG_T_MULDEFS), 0, NULL)) !=
468cdcc71c0SAli Bahrami 				    0) {
46992a02081SRod Evans 					optarg =
47092a02081SRod Evans 					    (char *)MSG_ORIG(MSG_ARG_MULDEFS);
47192a02081SRod Evans 					return (c);
47292a02081SRod Evans 
47392a02081SRod Evans 				/*
47492a02081SRod Evans 				 * Translate --auxiliary <optarg> to
47592a02081SRod Evans 				 * -f <optarg>
47692a02081SRod Evans 				 */
47792a02081SRod Evans 				} else if ((c = str2chr(lml, argc, ndx, argv,
47892a02081SRod Evans 				    arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR),
479cdcc71c0SAli Bahrami 				    MSG_ARG_T_AUXFLTR_SIZE, NULL)) != 0) {
48092a02081SRod Evans 					return (c);
48192a02081SRod Evans 				}
48292a02081SRod Evans 				break;
48392a02081SRod Evans 			case 'd':
48492a02081SRod Evans 				/*
48592a02081SRod Evans 				 * Translate --dynamic-linker <optarg> to
48692a02081SRod Evans 				 * -I <optarg>
48792a02081SRod Evans 				 */
48892a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'I',
48992a02081SRod Evans 				    MSG_ORIG(MSG_ARG_T_INTERP),
490cdcc71c0SAli Bahrami 				    MSG_ARG_T_INTERP_SIZE, NULL)) != 0) {
49192a02081SRod Evans 					return (c);
49292a02081SRod Evans 				}
49392a02081SRod Evans 				break;
49492a02081SRod Evans 			case 'e':
49592a02081SRod Evans 				/* Translate --entry <optarg> to -e <optarg> */
49692a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'e',
49792a02081SRod Evans 				    MSG_ORIG(MSG_ARG_T_ENTRY),
498cdcc71c0SAli Bahrami 				    MSG_ARG_T_ENTRY_SIZE, NULL)) != 0) {
49992a02081SRod Evans 					return (c);
50092a02081SRod Evans 				}
501551cffe3SAli Bahrami 				/*
502551cffe3SAli Bahrami 				 * Translate --end-group to -z rescan-end
503551cffe3SAli Bahrami 				 */
504551cffe3SAli Bahrami 				if ((c = str2chr(lml, ndx, argc, argv,
505cdcc71c0SAli Bahrami 				    arg, 'z', MSG_ORIG(MSG_ARG_T_ENDGROUP),
506cdcc71c0SAli Bahrami 				    0, NULL)) != 0) {
507551cffe3SAli Bahrami 					optarg = (char *)
508551cffe3SAli Bahrami 					    MSG_ORIG(MSG_ARG_RESCAN_END);
509551cffe3SAli Bahrami 					return (c);
510551cffe3SAli Bahrami 				}
51192a02081SRod Evans 				break;
51292a02081SRod Evans 			case 'f':
5131007fd6fSAli Bahrami 				/*
5141007fd6fSAli Bahrami 				 * Translate --fatal-warnings to
5151007fd6fSAli Bahrami 				 * -z fatal-warnings.
5161007fd6fSAli Bahrami 				 */
5171007fd6fSAli Bahrami 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
5181007fd6fSAli Bahrami 				    MSG_ORIG(MSG_ARG_T_FATWARN),
5191007fd6fSAli Bahrami 				    0, NULL)) != 0) {
5201007fd6fSAli Bahrami 					optarg = (char *)
5211007fd6fSAli Bahrami 					    MSG_ORIG(MSG_ARG_FATWARN);
5221007fd6fSAli Bahrami 					return (c);
5231007fd6fSAli Bahrami 				}
52492a02081SRod Evans 				/* Translate --filter <optarg> to -F <optarg> */
52592a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'F',
52692a02081SRod Evans 				    MSG_ORIG(MSG_ARG_T_STDFLTR),
527cdcc71c0SAli Bahrami 				    MSG_ARG_T_STDFLTR_SIZE, NULL)) != 0) {
52892a02081SRod Evans 					return (c);
52992a02081SRod Evans 				}
53092a02081SRod Evans 				break;
53192a02081SRod Evans 			case 'h':
53292a02081SRod Evans 				/* Translate --help to -zhelp */
53392a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
534cdcc71c0SAli Bahrami 				    MSG_ORIG(MSG_ARG_T_HELP), 0, NULL)) !=
535cdcc71c0SAli Bahrami 				    0) {
53692a02081SRod Evans 					optarg = (char *)MSG_ORIG(MSG_ARG_HELP);
53792a02081SRod Evans 					return (c);
53892a02081SRod Evans 				}
53992a02081SRod Evans 				break;
54092a02081SRod Evans 			case 'l':
54192a02081SRod Evans 				/*
54292a02081SRod Evans 				 * Translate --library <optarg> to -l <optarg>
54392a02081SRod Evans 				 */
54492a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'l',
54592a02081SRod Evans 				    MSG_ORIG(MSG_ARG_T_LIBRARY),
546cdcc71c0SAli Bahrami 				    MSG_ARG_T_LIBRARY_SIZE, NULL)) != 0) {
54792a02081SRod Evans 					return (c);
54892a02081SRod Evans 
54992a02081SRod Evans 				/*
55092a02081SRod Evans 				 * Translate --library-path <optarg> to
55192a02081SRod Evans 				 * -L <optarg>
55292a02081SRod Evans 				 */
55392a02081SRod Evans 				} else if ((c = str2chr(lml, ndx, argc, argv,
55492a02081SRod Evans 				    arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH),
555cdcc71c0SAli Bahrami 				    MSG_ARG_T_LIBPATH_SIZE, NULL)) != 0) {
55692a02081SRod Evans 					return (c);
55792a02081SRod Evans 				}
55892a02081SRod Evans 				break;
55992a02081SRod Evans 			case 'n':
5601007fd6fSAli Bahrami 				/*
5611007fd6fSAli Bahrami 				 * Translate --no-fatal-warnings to
5621007fd6fSAli Bahrami 				 * -z nofatal-warnings.
5631007fd6fSAli Bahrami 				 */
5641007fd6fSAli Bahrami 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
5651007fd6fSAli Bahrami 				    MSG_ORIG(MSG_ARG_T_NOFATWARN),
5661007fd6fSAli Bahrami 				    0, NULL)) != 0) {
5671007fd6fSAli Bahrami 					optarg = (char *)
5681007fd6fSAli Bahrami 					    MSG_ORIG(MSG_ARG_NOFATWARN);
5691007fd6fSAli Bahrami 					return (c);
5701007fd6fSAli Bahrami 				}
5711007fd6fSAli Bahrami 
57292a02081SRod Evans 				/* Translate --no-undefined to -zdefs */
57392a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
574cdcc71c0SAli Bahrami 				    MSG_ORIG(MSG_ARG_T_NOUNDEF), 0, NULL)) !=
575cdcc71c0SAli Bahrami 				    0) {
57692a02081SRod Evans 					optarg = (char *)MSG_ORIG(MSG_ARG_DEFS);
57792a02081SRod Evans 					return (c);
57892a02081SRod Evans 
57992a02081SRod Evans 				/*
58092a02081SRod Evans 				 * Translate --no-whole-archive to
58192a02081SRod Evans 				 * -z defaultextract
58292a02081SRod Evans 				 */
58392a02081SRod Evans 				} else if ((c = str2chr(lml, ndx, argc, argv,
584cdcc71c0SAli Bahrami 				    arg, 'z', MSG_ORIG(MSG_ARG_T_NOWHOLEARC),
585cdcc71c0SAli Bahrami 				    0, NULL)) != 0) {
58692a02081SRod Evans 					optarg =
58792a02081SRod Evans 					    (char *)MSG_ORIG(MSG_ARG_DFLEXTRT);
58892a02081SRod Evans 					return (c);
58992a02081SRod Evans 				}
59092a02081SRod Evans 				break;
59192a02081SRod Evans 			case 'o':
59292a02081SRod Evans 				/* Translate --output <optarg> to -o <optarg> */
59392a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'o',
59492a02081SRod Evans 				    MSG_ORIG(MSG_ARG_T_OUTPUT),
595cdcc71c0SAli Bahrami 				    MSG_ARG_T_OUTPUT_SIZE, NULL)) != 0) {
59692a02081SRod Evans 					return (c);
59792a02081SRod Evans 				}
59892a02081SRod Evans 				break;
59992a02081SRod Evans 			case 'r':
60092a02081SRod Evans 				/* Translate --relocatable to -r */
60192a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'r',
602cdcc71c0SAli Bahrami 				    MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0,
603cdcc71c0SAli Bahrami 				    NULL)) != 0) {
60492a02081SRod Evans 					return (c);
60592a02081SRod Evans 				}
60692a02081SRod Evans 				break;
60792a02081SRod Evans 			case 's':
60892a02081SRod Evans 				/* Translate --strip-all to -s */
60992a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 's',
610cdcc71c0SAli Bahrami 				    MSG_ORIG(MSG_ARG_T_STRIP), 0, NULL)) !=
611cdcc71c0SAli Bahrami 				    0) {
61292a02081SRod Evans 					return (c);
61392a02081SRod Evans 				}
614551cffe3SAli Bahrami 				/*
615551cffe3SAli Bahrami 				 * Translate --start-group to -z rescan-start
616551cffe3SAli Bahrami 				 */
617551cffe3SAli Bahrami 				if ((c = str2chr(lml, ndx, argc, argv,
618cdcc71c0SAli Bahrami 				    arg, 'z', MSG_ORIG(MSG_ARG_T_STARTGROUP),
619cdcc71c0SAli Bahrami 				    0, NULL)) != 0) {
620551cffe3SAli Bahrami 					optarg = (char *)
621551cffe3SAli Bahrami 					    MSG_ORIG(MSG_ARG_RESCAN_START);
622551cffe3SAli Bahrami 					return (c);
623551cffe3SAli Bahrami 				}
62492a02081SRod Evans 				break;
62592a02081SRod Evans 			case 'u':
62692a02081SRod Evans 				/*
62792a02081SRod Evans 				 * Translate --undefined <optarg> to
62892a02081SRod Evans 				 * -u <optarg>
62992a02081SRod Evans 				 */
63092a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'u',
63192a02081SRod Evans 				    MSG_ORIG(MSG_ARG_T_UNDEF),
632cdcc71c0SAli Bahrami 				    MSG_ARG_T_UNDEF_SIZE, NULL)) != 0) {
63392a02081SRod Evans 					return (c);
63492a02081SRod Evans 				}
63592a02081SRod Evans 				break;
63692a02081SRod Evans 			case 'v':
63792a02081SRod Evans 				/* Translate --version to -V */
63892a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'V',
639cdcc71c0SAli Bahrami 				    MSG_ORIG(MSG_ARG_T_VERSION), 0, NULL)) !=
640cdcc71c0SAli Bahrami 				    0) {
64192a02081SRod Evans 					return (c);
64292a02081SRod Evans 				}
64392a02081SRod Evans 				break;
64492a02081SRod Evans 			case 'w':
64592a02081SRod Evans 				/*
64692a02081SRod Evans 				 * Translate --whole-archive to -z alltextract
64792a02081SRod Evans 				 */
64892a02081SRod Evans 				if ((c = str2chr(lml, ndx, argc, argv,
649cdcc71c0SAli Bahrami 				    arg, 'z', MSG_ORIG(MSG_ARG_T_WHOLEARC),
650cdcc71c0SAli Bahrami 				    0, NULL)) != 0) {
65192a02081SRod Evans 					optarg =
65292a02081SRod Evans 					    (char *)MSG_ORIG(MSG_ARG_ALLEXTRT);
65392a02081SRod Evans 					return (c);
65492a02081SRod Evans 				}
655cdcc71c0SAli Bahrami 				/*
656cdcc71c0SAli Bahrami 				 * Translate --wrap to -z wrap=
657cdcc71c0SAli Bahrami 				 */
658cdcc71c0SAli Bahrami 				if ((c = str2chr(lml, ndx, argc, argv,
659cdcc71c0SAli Bahrami 				    arg, 'z', MSG_ORIG(MSG_ARG_T_WRAP),
660cdcc71c0SAli Bahrami 				    MSG_ARG_T_WRAP_SIZE, str2chr_wrap_cb)) !=
661cdcc71c0SAli Bahrami 				    0) {
662cdcc71c0SAli Bahrami 					return (c);
663cdcc71c0SAli Bahrami 				}
66492a02081SRod Evans 				break;
66592a02081SRod Evans 			}
66692a02081SRod Evans 			break;
66792a02081SRod Evans 		}
66892a02081SRod Evans 	}
669cdcc71c0SAli Bahrami 
67092a02081SRod Evans 	if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
67192a02081SRod Evans 		/*
67292a02081SRod Evans 		 * It is possible that a "-Wl," argument has been used to
67392a02081SRod Evans 		 * specify an option.  This isn't advertized ld(1) syntax, but
67492a02081SRod Evans 		 * compiler drivers and configuration tools, have been known to
67592a02081SRod Evans 		 * pass this compiler option to ld(1).  Strip off the "-Wl,"
67692a02081SRod Evans 		 * prefix and pass the option through.
67792a02081SRod Evans 		 */
67892a02081SRod Evans 		if ((c == 'W') && (strncmp(optarg,
67992a02081SRod Evans 		    MSG_ORIG(MSG_ARG_T_WL), MSG_ARG_T_WL_SIZE) == 0)) {
68092a02081SRod Evans 			DBG_CALL(Dbg_args_Wldel(lml, ndx, optarg));
68192a02081SRod Evans 			c = optarg[MSG_ARG_T_WL_SIZE];
68292a02081SRod Evans 			optarg += MSG_ARG_T_WL_SIZE + 1;
68392a02081SRod Evans 		}
68492a02081SRod Evans 	}
68592a02081SRod Evans 
68692a02081SRod Evans 	return (c);
68792a02081SRod Evans }
68892a02081SRod Evans 
68992a02081SRod Evans /*
690e64d0ff9SAli Bahrami  * A compare routine for Isd_node AVL trees.
6916b3ba5bdSAli Bahrami  */
6926b3ba5bdSAli Bahrami int
6936b3ba5bdSAli Bahrami isdavl_compare(const void *n1, const void *n2)
6946b3ba5bdSAli Bahrami {
6956b3ba5bdSAli Bahrami 	uint_t		hash1, hash2;
6966b3ba5bdSAli Bahrami 	const char	*st1, *st2;
6976b3ba5bdSAli Bahrami 	int		rc;
6986b3ba5bdSAli Bahrami 
6996b3ba5bdSAli Bahrami 	hash1 = ((Isd_node *)n1)->isd_hash;
7006b3ba5bdSAli Bahrami 	hash2 = ((Isd_node *)n2)->isd_hash;
7016b3ba5bdSAli Bahrami 
7026b3ba5bdSAli Bahrami 	if (hash1 > hash2)
7036b3ba5bdSAli Bahrami 		return (1);
7046b3ba5bdSAli Bahrami 	if (hash1 < hash2)
7056b3ba5bdSAli Bahrami 		return (-1);
7066b3ba5bdSAli Bahrami 
707e64d0ff9SAli Bahrami 	st1 = ((Isd_node *)n1)->isd_name;
708e64d0ff9SAli Bahrami 	st2 = ((Isd_node *)n2)->isd_name;
7096b3ba5bdSAli Bahrami 
7106b3ba5bdSAli Bahrami 	rc = strcmp(st1, st2);
7116b3ba5bdSAli Bahrami 	if (rc > 0)
7126b3ba5bdSAli Bahrami 		return (1);
7136b3ba5bdSAli Bahrami 	if (rc < 0)
7146b3ba5bdSAli Bahrami 		return (-1);
7156b3ba5bdSAli Bahrami 	return (0);
7166b3ba5bdSAli Bahrami }
7176b3ba5bdSAli Bahrami 
7186b3ba5bdSAli Bahrami /*
7197257d1b4Sraf  * Messaging support - funnel everything through dgettext().
7207c478bd9Sstevel@tonic-gate  */
7217c478bd9Sstevel@tonic-gate const char *
7227c478bd9Sstevel@tonic-gate _libld_msg(Msg mid)
7237c478bd9Sstevel@tonic-gate {
7247257d1b4Sraf 	return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate /*
7287c478bd9Sstevel@tonic-gate  * Determine whether a symbol name should be demangled.
7297c478bd9Sstevel@tonic-gate  */
7307c478bd9Sstevel@tonic-gate const char *
7317c478bd9Sstevel@tonic-gate demangle(const char *name)
7327c478bd9Sstevel@tonic-gate {
7335aefb655Srie 	if (demangle_flag)
7345aefb655Srie 		return (Elf_demangle_name(name));
7357c478bd9Sstevel@tonic-gate 	else
7367c478bd9Sstevel@tonic-gate 		return (name);
7377c478bd9Sstevel@tonic-gate }
73808278a5eSRod Evans 
73908278a5eSRod Evans /*
74008278a5eSRod Evans  * Compare a series of platform or machine hardware names.
74108278a5eSRod Evans  */
74208278a5eSRod Evans int
74308278a5eSRod Evans cap_names_match(Alist *alp1, Alist *alp2)
74408278a5eSRod Evans {
74508278a5eSRod Evans 	Capstr		*capstr1;
74608278a5eSRod Evans 	Aliste		idx1;
74708278a5eSRod Evans 	int		match = 0;
74808278a5eSRod Evans 	Word		nitems;
74908278a5eSRod Evans 
75008278a5eSRod Evans 	if ((nitems = alist_nitems(alp1)) != alist_nitems(alp2))
75108278a5eSRod Evans 		return (1);
75208278a5eSRod Evans 
75308278a5eSRod Evans 	for (ALIST_TRAVERSE(alp1, idx1, capstr1)) {
75408278a5eSRod Evans 		Capstr		*capstr2;
75508278a5eSRod Evans 		Aliste 		idx2;
75608278a5eSRod Evans 
75708278a5eSRod Evans 		for (ALIST_TRAVERSE(alp2, idx2, capstr2)) {
75808278a5eSRod Evans 			if (strcmp(capstr1->cs_str, capstr2->cs_str))
75908278a5eSRod Evans 				continue;
76008278a5eSRod Evans 
76108278a5eSRod Evans 			match++;
76208278a5eSRod Evans 			break;
76308278a5eSRod Evans 		}
76408278a5eSRod Evans 	}
76508278a5eSRod Evans 
76608278a5eSRod Evans 	if (nitems == match)
76708278a5eSRod Evans 		return (0);
76808278a5eSRod Evans 
76908278a5eSRod Evans 	return (1);
77008278a5eSRod Evans }
771