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 *
dz_map(size_t size)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 *
libld_malloc(size_t size)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 *
libld_realloc(void * ptr,size_t size)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 */
libld_free(void * ptr)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 *
sdf_find(const char * name,APlist * alp)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 *
sdf_add(const char * name,APlist ** alpp)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 *
add_string(char * old,char * str)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
str2chr_wrap_cb(int c)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*1ca6c4d7SRichard Lowe * Determine whether this string, possibly with an associated option, should
305*1ca6c4d7SRichard Lowe * be translated to an option character. If so, update the optind and optarg
306*1ca6c4d7SRichard 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
str2chr(Lm_list * lml,int ndx,int argc,char ** argv,char * arg,int c,const char * opt,size_t optsz,int cbfunc (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*1ca6c4d7SRichard Lowe optopt = c;
33392a02081SRod Evans return (c);
33492a02081SRod Evans }
335ecd7f3e3SRichard Lowe } else if ((strcmp(arg, opt) == 0) ||
336ecd7f3e3SRichard 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*1ca6c4d7SRichard Lowe *
350*1ca6c4d7SRichard Lowe * Since we'll be completely failing this option we
351*1ca6c4d7SRichard Lowe * don't want to update optopt with the translation,
352*1ca6c4d7SRichard Lowe * but also need to set it to _something_. Setting it
353*1ca6c4d7SRichard Lowe * to the '-' of the argument causes us to behave
354*1ca6c4d7SRichard Lowe * correctly.
35592a02081SRod Evans */
35692a02081SRod Evans if ((++optind + 1) > argc) {
357*1ca6c4d7SRichard 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*1ca6c4d7SRichard Lowe if (*(++optarg) == '\0') {
372*1ca6c4d7SRichard Lowe optopt = arg[0];
37392a02081SRod Evans return ('?');
37492a02081SRod Evans }
37592a02081SRod Evans }
376*1ca6c4d7SRichard Lowe }
377cdcc71c0SAli Bahrami
378cdcc71c0SAli Bahrami if (cbfunc != NULL)
379cdcc71c0SAli Bahrami c = (*cbfunc)(c);
380*1ca6c4d7SRichard 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
ld_getopt(Lm_list * lml,int ndx,int argc,char ** argv)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
isdavl_compare(const void * n1,const void * n2)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 *
_libld_msg(Msg mid)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 *
demangle(const char * name)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
cap_names_match(Alist * alp1,Alist * alp2)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