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
227257d1b4Sraf /*
231007fd6fSAli Bahrami * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247257d1b4Sraf */
257257d1b4Sraf
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T
287c478bd9Sstevel@tonic-gate * All Rights Reserved
297c478bd9Sstevel@tonic-gate */
307257d1b4Sraf
317d732bb0SJohn Levon /*
327d732bb0SJohn Levon * Copyright (c) 2018, Joyent, Inc.
337d732bb0SJohn Levon */
347d732bb0SJohn Levon
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate * Utility functions
377c478bd9Sstevel@tonic-gate */
387257d1b4Sraf #include <unistd.h>
397257d1b4Sraf #include <stdio.h>
407257d1b4Sraf #include <stdarg.h>
417257d1b4Sraf #include <string.h>
427257d1b4Sraf #include <fcntl.h>
437257d1b4Sraf #include <sys/types.h>
447257d1b4Sraf #include <sys/mman.h>
457257d1b4Sraf #include <errno.h>
467257d1b4Sraf #include <sgs.h>
477257d1b4Sraf #include <libintl.h>
487257d1b4Sraf #include <debug.h>
497257d1b4Sraf #include "msg.h"
507257d1b4Sraf #include "_libld.h"
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * Determine if a shared object definition structure already exists and if
547c478bd9Sstevel@tonic-gate * not create one. These definitions provide for recording information
557c478bd9Sstevel@tonic-gate * regarding shared objects that are still to be processed. Once processed
567c478bd9Sstevel@tonic-gate * shared objects are maintained on the ofl_sos list. The information
577c478bd9Sstevel@tonic-gate * recorded in this structure includes:
587c478bd9Sstevel@tonic-gate *
597c478bd9Sstevel@tonic-gate * o DT_USED requirements. In these cases definitions are added during
607c478bd9Sstevel@tonic-gate * mapfile processing of `-' entries (see map_dash()).
617c478bd9Sstevel@tonic-gate *
627c478bd9Sstevel@tonic-gate * o implicit NEEDED entries. As shared objects are processed from the
637c478bd9Sstevel@tonic-gate * command line so any of their dependencies are recorded in these
647c478bd9Sstevel@tonic-gate * structures for later processing (see process_dynamic()).
657c478bd9Sstevel@tonic-gate *
667c478bd9Sstevel@tonic-gate * o version requirements. Any explicit shared objects that have version
677c478bd9Sstevel@tonic-gate * dependencies on other objects have their version requirements recorded.
687c478bd9Sstevel@tonic-gate * In these cases definitions are added during mapfile processing of `-'
697c478bd9Sstevel@tonic-gate * entries (see map_dash()). Also, shared objects may have versioning
707c478bd9Sstevel@tonic-gate * requirements on their NEEDED entries. These cases are added during
717c478bd9Sstevel@tonic-gate * their version processing (see vers_need_process()).
727c478bd9Sstevel@tonic-gate *
737c478bd9Sstevel@tonic-gate * Note: Both process_dynamic() and vers_need_process() may generate the
747c478bd9Sstevel@tonic-gate * initial version definition structure because you can't rely on what
757c478bd9Sstevel@tonic-gate * section (.dynamic or .SUNW_version) may be processed first from any
767c478bd9Sstevel@tonic-gate * input file.
777c478bd9Sstevel@tonic-gate */
787c478bd9Sstevel@tonic-gate Sdf_desc *
sdf_find(const char * name,APlist * alp)7957ef7aa9SRod Evans sdf_find(const char *name, APlist *alp)
807c478bd9Sstevel@tonic-gate {
8157ef7aa9SRod Evans Aliste idx;
827c478bd9Sstevel@tonic-gate Sdf_desc *sdf;
837c478bd9Sstevel@tonic-gate
8457ef7aa9SRod Evans for (APLIST_TRAVERSE(alp, idx, sdf))
857c478bd9Sstevel@tonic-gate if (strcmp(name, sdf->sdf_name) == 0)
867c478bd9Sstevel@tonic-gate return (sdf);
877c478bd9Sstevel@tonic-gate
880e233487SRod Evans return (NULL);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate Sdf_desc *
sdf_add(const char * name,APlist ** alpp)9257ef7aa9SRod Evans sdf_add(const char *name, APlist **alpp)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate Sdf_desc *sdf;
957c478bd9Sstevel@tonic-gate
96*fb12490aSRichard Lowe if ((sdf = libld_calloc(1, sizeof (Sdf_desc))) == NULL)
977c478bd9Sstevel@tonic-gate return ((Sdf_desc *)S_ERROR);
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate sdf->sdf_name = name;
1007c478bd9Sstevel@tonic-gate
10157ef7aa9SRod Evans if (aplist_append(alpp, sdf, AL_CNT_OFL_LIBS) == NULL)
1027c478bd9Sstevel@tonic-gate return ((Sdf_desc *)S_ERROR);
10357ef7aa9SRod Evans
10457ef7aa9SRod Evans return (sdf);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate * Add a string, separated by a colon, to an existing string. Typically used
1097c478bd9Sstevel@tonic-gate * to maintain filter, rpath and audit names, of which there is normally only
1107c478bd9Sstevel@tonic-gate * one string supplied anyway.
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate char *
add_string(char * old,char * str)1137c478bd9Sstevel@tonic-gate add_string(char *old, char *str)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate char *new;
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate if (old) {
1187c478bd9Sstevel@tonic-gate char *_str;
1197c478bd9Sstevel@tonic-gate size_t len;
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * If an original string exists, make sure this new string
1237c478bd9Sstevel@tonic-gate * doesn't get duplicated.
1247c478bd9Sstevel@tonic-gate */
1257c478bd9Sstevel@tonic-gate if ((_str = strstr(old, str)) != NULL) {
1267c478bd9Sstevel@tonic-gate if (((_str == old) ||
1277c478bd9Sstevel@tonic-gate (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) &&
1287c478bd9Sstevel@tonic-gate (_str += strlen(str)) &&
1297c478bd9Sstevel@tonic-gate ((*_str == '\0') ||
1307c478bd9Sstevel@tonic-gate (*_str == *(MSG_ORIG(MSG_STR_COLON)))))
1317c478bd9Sstevel@tonic-gate return (old);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate len = strlen(old) + strlen(str) + 2;
1350e233487SRod Evans if ((new = libld_calloc(1, len)) == NULL)
1367c478bd9Sstevel@tonic-gate return ((char *)S_ERROR);
1377c478bd9Sstevel@tonic-gate (void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str);
1387c478bd9Sstevel@tonic-gate } else {
1390e233487SRod Evans if ((new = libld_malloc(strlen(str) + 1)) == NULL)
1407c478bd9Sstevel@tonic-gate return ((char *)S_ERROR);
1417c478bd9Sstevel@tonic-gate (void) strcpy(new, str);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate return (new);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
147cdcc71c0SAli Bahrami /*
148cdcc71c0SAli Bahrami * The GNU ld '-wrap=XXX' and '--wrap=XXX' options correspond to our
149cdcc71c0SAli Bahrami * '-z wrap=XXX'. When str2chr() does this conversion, we end up with
150cdcc71c0SAli Bahrami * the return character set to 'z' and optarg set to 'XXX'. This callback
151cdcc71c0SAli Bahrami * changes optarg to include the missing wrap= prefix.
152cdcc71c0SAli Bahrami *
153cdcc71c0SAli Bahrami * exit:
154cdcc71c0SAli Bahrami * Returns c on success, or '?' on error.
155cdcc71c0SAli Bahrami */
156cdcc71c0SAli Bahrami static int
str2chr_wrap_cb(int c)157cdcc71c0SAli Bahrami str2chr_wrap_cb(int c)
158cdcc71c0SAli Bahrami {
159cdcc71c0SAli Bahrami char *str;
160cdcc71c0SAli Bahrami size_t len = MSG_ARG_WRAP_SIZE + strlen(optarg) + 1;
161cdcc71c0SAli Bahrami
162cdcc71c0SAli Bahrami if ((str = libld_malloc(len)) == NULL)
163cdcc71c0SAli Bahrami return ('?');
164cdcc71c0SAli Bahrami (void) snprintf(str, len, MSG_ORIG(MSG_FMT_STRCAT),
165cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_WRAP), optarg);
166cdcc71c0SAli Bahrami optarg = str;
167cdcc71c0SAli Bahrami return (c);
168cdcc71c0SAli Bahrami }
169cdcc71c0SAli Bahrami
17092a02081SRod Evans /*
171c5accfb2SRichard Lowe * Determine whether this string, possibly with an associated option, should
172c5accfb2SRichard Lowe * be translated to an option character. If so, update the optind and optarg
173c5accfb2SRichard Lowe * and optopt as described for short options in getopt(3c).
174cdcc71c0SAli Bahrami *
175cdcc71c0SAli Bahrami * entry:
176cdcc71c0SAli Bahrami * lml - Link map list for debug messages
177cdcc71c0SAli Bahrami * ndx - Starting optind for current item
178cdcc71c0SAli Bahrami * argc, argv - Command line arguments
179cdcc71c0SAli Bahrami * arg - Option to be examined
180cdcc71c0SAli Bahrami * c, opt - Option character (c) and corresponding long name (opt)
181cdcc71c0SAli Bahrami * optsz - 0 if option does not accept a value. If option does
182cdcc71c0SAli Bahrami * accept a value, strlen(opt), giving the offset to the
183cdcc71c0SAli Bahrami * value if the option and value are combined in one string.
184cdcc71c0SAli Bahrami * cbfunc - NULL, or pointer to function to call if a translation is
185cdcc71c0SAli Bahrami * successful.
18692a02081SRod Evans */
18792a02081SRod 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))18892a02081SRod Evans str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c,
1897d732bb0SJohn Levon const char *opt, size_t optsz, int (*cbfunc)(int))
19092a02081SRod Evans {
19192a02081SRod Evans if (optsz == 0) {
19292a02081SRod Evans /*
19392a02081SRod Evans * Compare a single option (ie. there's no associated option
19492a02081SRod Evans * argument).
19592a02081SRod Evans */
19692a02081SRod Evans if (strcmp(arg, opt) == 0) {
19792a02081SRod Evans DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
19892a02081SRod Evans optind += 1;
199c5accfb2SRichard Lowe optopt = c;
20092a02081SRod Evans return (c);
20192a02081SRod Evans }
20244a646f1SRichard Lowe } else if ((strcmp(arg, opt) == 0) ||
20344a646f1SRichard Lowe ((arg[optsz] == '=') && strncmp(arg, opt, optsz) == 0)) {
20492a02081SRod Evans /*
20592a02081SRod Evans * Otherwise, compare the option name, which may be
20692a02081SRod Evans * concatenated with the option argument.
20792a02081SRod Evans */
20892a02081SRod Evans DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
20992a02081SRod Evans
21092a02081SRod Evans if (arg[optsz] == '\0') {
21192a02081SRod Evans /*
21292a02081SRod Evans * Optarg is the next argument (white space separated).
21392a02081SRod Evans * Make sure an optarg is available, and if not return
21492a02081SRod Evans * a failure to prevent any fall-through to the generic
21592a02081SRod Evans * getopt() processing.
216c5accfb2SRichard Lowe *
217c5accfb2SRichard Lowe * Since we'll be completely failing this option we
218c5accfb2SRichard Lowe * don't want to update optopt with the translation,
219c5accfb2SRichard Lowe * but also need to set it to _something_. Setting it
220c5accfb2SRichard Lowe * to the '-' of the argument causes us to behave
221c5accfb2SRichard Lowe * correctly.
22292a02081SRod Evans */
22392a02081SRod Evans if ((++optind + 1) > argc) {
224c5accfb2SRichard Lowe optopt = arg[0];
22592a02081SRod Evans return ('?');
22692a02081SRod Evans }
22792a02081SRod Evans optarg = argv[optind];
22892a02081SRod Evans optind++;
22992a02081SRod Evans } else {
23092a02081SRod Evans /*
23192a02081SRod Evans * GNU option/option argument pairs can be represented
23292a02081SRod Evans * with a "=" separator. If this is the case, remove
23392a02081SRod Evans * the separator.
23492a02081SRod Evans */
23592a02081SRod Evans optarg = &arg[optsz];
23692a02081SRod Evans optind++;
23792a02081SRod Evans if (*optarg == '=') {
238c5accfb2SRichard Lowe if (*(++optarg) == '\0') {
239c5accfb2SRichard Lowe optopt = arg[0];
24092a02081SRod Evans return ('?');
241c5accfb2SRichard Lowe }
24292a02081SRod Evans }
24392a02081SRod Evans }
244cdcc71c0SAli Bahrami
245cdcc71c0SAli Bahrami if (cbfunc != NULL)
246cdcc71c0SAli Bahrami c = (*cbfunc)(c);
247c5accfb2SRichard Lowe optopt = c;
24892a02081SRod Evans return (c);
24992a02081SRod Evans }
25092a02081SRod Evans return (0);
25192a02081SRod Evans }
25292a02081SRod Evans
25392a02081SRod Evans /*
25492a02081SRod Evans * Parse an individual option. The intent of this function is to determine if
25592a02081SRod Evans * any known, non-Solaris options have been passed to ld(1). This condition
25692a02081SRod Evans * can occur as a result of build configuration tools, because of users
25792a02081SRod Evans * familiarity with other systems, or simply the users preferences. If a known
25892a02081SRod Evans * non-Solaris option can be determined, translate that option into the Solaris
25992a02081SRod Evans * counterpart.
26092a02081SRod Evans *
26192a02081SRod Evans * This function will probably never be a complete solution, as new, non-Solaris
26292a02081SRod Evans * options are discovered, their translation will have to be added. Other
26392a02081SRod Evans * non-Solaris options are incompatible with the Solaris link-editor, and will
26492a02081SRod Evans * never be recognized. We support what we can.
26592a02081SRod Evans */
26692a02081SRod Evans int
ld_getopt(Lm_list * lml,int ndx,int argc,char ** argv)26792a02081SRod Evans ld_getopt(Lm_list *lml, int ndx, int argc, char **argv)
26892a02081SRod Evans {
26992a02081SRod Evans int c;
27092a02081SRod Evans
27192a02081SRod Evans if ((optind < argc) && argv[optind] && (argv[optind][0] == '-')) {
27292a02081SRod Evans char *arg = &argv[optind][1];
27392a02081SRod Evans
27492a02081SRod Evans switch (*arg) {
27592a02081SRod Evans case 'r':
27692a02081SRod Evans /* Translate -rpath <optarg> to -R <optarg> */
27792a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'R',
27892a02081SRod Evans MSG_ORIG(MSG_ARG_T_RPATH),
279cdcc71c0SAli Bahrami MSG_ARG_T_RPATH_SIZE, NULL)) != 0) {
28092a02081SRod Evans return (c);
28192a02081SRod Evans }
28292a02081SRod Evans break;
28392a02081SRod Evans case 's':
28492a02081SRod Evans /* Translate -shared to -G */
28592a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'G',
286cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_SHARED), 0, NULL)) != 0) {
28792a02081SRod Evans return (c);
28892a02081SRod Evans
28992a02081SRod Evans /* Translate -soname <optarg> to -h <optarg> */
29092a02081SRod Evans } else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h',
29192a02081SRod Evans MSG_ORIG(MSG_ARG_T_SONAME),
292cdcc71c0SAli Bahrami MSG_ARG_T_SONAME_SIZE, NULL)) != 0) {
293cdcc71c0SAli Bahrami return (c);
294cdcc71c0SAli Bahrami }
295cdcc71c0SAli Bahrami break;
296cdcc71c0SAli Bahrami case 'w':
297cdcc71c0SAli Bahrami /* Translate -wrap to -z wrap= */
298cdcc71c0SAli Bahrami if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
299cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_WRAP) + 1,
300cdcc71c0SAli Bahrami MSG_ARG_T_WRAP_SIZE - 1, str2chr_wrap_cb)) != 0) {
30192a02081SRod Evans return (c);
30292a02081SRod Evans }
30392a02081SRod Evans break;
304551cffe3SAli Bahrami case '(':
305551cffe3SAli Bahrami /*
306551cffe3SAli Bahrami * Translate -( to -z rescan-start
307551cffe3SAli Bahrami */
308551cffe3SAli Bahrami if ((c = str2chr(lml, ndx, argc, argv,
309cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0, NULL)) !=
310cdcc71c0SAli Bahrami 0) {
311551cffe3SAli Bahrami optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START);
312551cffe3SAli Bahrami return (c);
313551cffe3SAli Bahrami }
314551cffe3SAli Bahrami break;
315551cffe3SAli Bahrami case ')':
316551cffe3SAli Bahrami /*
317551cffe3SAli Bahrami * Translate -) to -z rescan-end
318551cffe3SAli Bahrami */
319551cffe3SAli Bahrami if ((c = str2chr(lml, ndx, argc, argv,
320cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0, NULL)) !=
321cdcc71c0SAli Bahrami 0) {
322551cffe3SAli Bahrami optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END);
323551cffe3SAli Bahrami return (c);
324551cffe3SAli Bahrami }
325551cffe3SAli Bahrami break;
32692a02081SRod Evans case '-':
32792a02081SRod Evans switch (*(arg + 1)) {
32892a02081SRod Evans case 'a':
32992a02081SRod Evans /*
33092a02081SRod Evans * Translate --allow-multiple-definition to
33192a02081SRod Evans * -zmuldefs
33292a02081SRod Evans */
33392a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
334cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_MULDEFS), 0, NULL)) !=
335cdcc71c0SAli Bahrami 0) {
33692a02081SRod Evans optarg =
33792a02081SRod Evans (char *)MSG_ORIG(MSG_ARG_MULDEFS);
33892a02081SRod Evans return (c);
33992a02081SRod Evans
34092a02081SRod Evans /*
34192a02081SRod Evans * Translate --auxiliary <optarg> to
34292a02081SRod Evans * -f <optarg>
34392a02081SRod Evans */
34492a02081SRod Evans } else if ((c = str2chr(lml, argc, ndx, argv,
34592a02081SRod Evans arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR),
346cdcc71c0SAli Bahrami MSG_ARG_T_AUXFLTR_SIZE, NULL)) != 0) {
34792a02081SRod Evans return (c);
34892a02081SRod Evans }
34992a02081SRod Evans break;
35092a02081SRod Evans case 'd':
35192a02081SRod Evans /*
35292a02081SRod Evans * Translate --dynamic-linker <optarg> to
35392a02081SRod Evans * -I <optarg>
35492a02081SRod Evans */
35592a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'I',
35692a02081SRod Evans MSG_ORIG(MSG_ARG_T_INTERP),
357cdcc71c0SAli Bahrami MSG_ARG_T_INTERP_SIZE, NULL)) != 0) {
35892a02081SRod Evans return (c);
35992a02081SRod Evans }
36092a02081SRod Evans break;
36192a02081SRod Evans case 'e':
36292a02081SRod Evans /* Translate --entry <optarg> to -e <optarg> */
36392a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'e',
36492a02081SRod Evans MSG_ORIG(MSG_ARG_T_ENTRY),
365cdcc71c0SAli Bahrami MSG_ARG_T_ENTRY_SIZE, NULL)) != 0) {
36692a02081SRod Evans return (c);
36792a02081SRod Evans }
368551cffe3SAli Bahrami /*
369551cffe3SAli Bahrami * Translate --end-group to -z rescan-end
370551cffe3SAli Bahrami */
371551cffe3SAli Bahrami if ((c = str2chr(lml, ndx, argc, argv,
372cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_ENDGROUP),
373cdcc71c0SAli Bahrami 0, NULL)) != 0) {
374551cffe3SAli Bahrami optarg = (char *)
375551cffe3SAli Bahrami MSG_ORIG(MSG_ARG_RESCAN_END);
376551cffe3SAli Bahrami return (c);
377551cffe3SAli Bahrami }
37892a02081SRod Evans break;
37992a02081SRod Evans case 'f':
3801007fd6fSAli Bahrami /*
3811007fd6fSAli Bahrami * Translate --fatal-warnings to
3821007fd6fSAli Bahrami * -z fatal-warnings.
3831007fd6fSAli Bahrami */
3841007fd6fSAli Bahrami if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
3851007fd6fSAli Bahrami MSG_ORIG(MSG_ARG_T_FATWARN),
3861007fd6fSAli Bahrami 0, NULL)) != 0) {
3871007fd6fSAli Bahrami optarg = (char *)
3881007fd6fSAli Bahrami MSG_ORIG(MSG_ARG_FATWARN);
3891007fd6fSAli Bahrami return (c);
3901007fd6fSAli Bahrami }
39192a02081SRod Evans /* Translate --filter <optarg> to -F <optarg> */
39292a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'F',
39392a02081SRod Evans MSG_ORIG(MSG_ARG_T_STDFLTR),
394cdcc71c0SAli Bahrami MSG_ARG_T_STDFLTR_SIZE, NULL)) != 0) {
39592a02081SRod Evans return (c);
39692a02081SRod Evans }
39792a02081SRod Evans break;
39892a02081SRod Evans case 'h':
39992a02081SRod Evans /* Translate --help to -zhelp */
40092a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
401cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_HELP), 0, NULL)) !=
402cdcc71c0SAli Bahrami 0) {
40392a02081SRod Evans optarg = (char *)MSG_ORIG(MSG_ARG_HELP);
40492a02081SRod Evans return (c);
40592a02081SRod Evans }
40692a02081SRod Evans break;
40792a02081SRod Evans case 'l':
40892a02081SRod Evans /*
40992a02081SRod Evans * Translate --library <optarg> to -l <optarg>
41092a02081SRod Evans */
41192a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'l',
41292a02081SRod Evans MSG_ORIG(MSG_ARG_T_LIBRARY),
413cdcc71c0SAli Bahrami MSG_ARG_T_LIBRARY_SIZE, NULL)) != 0) {
41492a02081SRod Evans return (c);
41592a02081SRod Evans
41692a02081SRod Evans /*
41792a02081SRod Evans * Translate --library-path <optarg> to
41892a02081SRod Evans * -L <optarg>
41992a02081SRod Evans */
42092a02081SRod Evans } else if ((c = str2chr(lml, ndx, argc, argv,
42192a02081SRod Evans arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH),
422cdcc71c0SAli Bahrami MSG_ARG_T_LIBPATH_SIZE, NULL)) != 0) {
42392a02081SRod Evans return (c);
42492a02081SRod Evans }
42592a02081SRod Evans break;
42692a02081SRod Evans case 'n':
4271007fd6fSAli Bahrami /*
4281007fd6fSAli Bahrami * Translate --no-fatal-warnings to
4291007fd6fSAli Bahrami * -z nofatal-warnings.
4301007fd6fSAli Bahrami */
4311007fd6fSAli Bahrami if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
4321007fd6fSAli Bahrami MSG_ORIG(MSG_ARG_T_NOFATWARN),
4331007fd6fSAli Bahrami 0, NULL)) != 0) {
4341007fd6fSAli Bahrami optarg = (char *)
4351007fd6fSAli Bahrami MSG_ORIG(MSG_ARG_NOFATWARN);
4361007fd6fSAli Bahrami return (c);
4371007fd6fSAli Bahrami }
4381007fd6fSAli Bahrami
43992a02081SRod Evans /* Translate --no-undefined to -zdefs */
44092a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
441cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_NOUNDEF), 0, NULL)) !=
442cdcc71c0SAli Bahrami 0) {
44392a02081SRod Evans optarg = (char *)MSG_ORIG(MSG_ARG_DEFS);
44492a02081SRod Evans return (c);
44592a02081SRod Evans
44692a02081SRod Evans /*
44792a02081SRod Evans * Translate --no-whole-archive to
44892a02081SRod Evans * -z defaultextract
44992a02081SRod Evans */
45092a02081SRod Evans } else if ((c = str2chr(lml, ndx, argc, argv,
451cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_NOWHOLEARC),
452cdcc71c0SAli Bahrami 0, NULL)) != 0) {
45392a02081SRod Evans optarg =
45492a02081SRod Evans (char *)MSG_ORIG(MSG_ARG_DFLEXTRT);
45592a02081SRod Evans return (c);
45692a02081SRod Evans }
45792a02081SRod Evans break;
45892a02081SRod Evans case 'o':
45992a02081SRod Evans /* Translate --output <optarg> to -o <optarg> */
46092a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'o',
46192a02081SRod Evans MSG_ORIG(MSG_ARG_T_OUTPUT),
462cdcc71c0SAli Bahrami MSG_ARG_T_OUTPUT_SIZE, NULL)) != 0) {
46392a02081SRod Evans return (c);
46492a02081SRod Evans }
46592a02081SRod Evans break;
46692a02081SRod Evans case 'r':
46792a02081SRod Evans /* Translate --relocatable to -r */
46892a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'r',
469cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0,
470cdcc71c0SAli Bahrami NULL)) != 0) {
47192a02081SRod Evans return (c);
47292a02081SRod Evans }
47392a02081SRod Evans break;
47492a02081SRod Evans case 's':
47592a02081SRod Evans /* Translate --strip-all to -s */
47692a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 's',
477cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_STRIP), 0, NULL)) !=
478cdcc71c0SAli Bahrami 0) {
47992a02081SRod Evans return (c);
48092a02081SRod Evans }
481551cffe3SAli Bahrami /*
482551cffe3SAli Bahrami * Translate --start-group to -z rescan-start
483551cffe3SAli Bahrami */
484551cffe3SAli Bahrami if ((c = str2chr(lml, ndx, argc, argv,
485cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_STARTGROUP),
486cdcc71c0SAli Bahrami 0, NULL)) != 0) {
487551cffe3SAli Bahrami optarg = (char *)
488551cffe3SAli Bahrami MSG_ORIG(MSG_ARG_RESCAN_START);
489551cffe3SAli Bahrami return (c);
490551cffe3SAli Bahrami }
49192a02081SRod Evans break;
49292a02081SRod Evans case 'u':
49392a02081SRod Evans /*
49492a02081SRod Evans * Translate --undefined <optarg> to
49592a02081SRod Evans * -u <optarg>
49692a02081SRod Evans */
49792a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'u',
49892a02081SRod Evans MSG_ORIG(MSG_ARG_T_UNDEF),
499cdcc71c0SAli Bahrami MSG_ARG_T_UNDEF_SIZE, NULL)) != 0) {
50092a02081SRod Evans return (c);
50192a02081SRod Evans }
50292a02081SRod Evans break;
50392a02081SRod Evans case 'v':
50492a02081SRod Evans /* Translate --version to -V */
50592a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv, arg, 'V',
506cdcc71c0SAli Bahrami MSG_ORIG(MSG_ARG_T_VERSION), 0, NULL)) !=
507cdcc71c0SAli Bahrami 0) {
50892a02081SRod Evans return (c);
50992a02081SRod Evans }
51092a02081SRod Evans break;
51192a02081SRod Evans case 'w':
51292a02081SRod Evans /*
51392a02081SRod Evans * Translate --whole-archive to -z alltextract
51492a02081SRod Evans */
51592a02081SRod Evans if ((c = str2chr(lml, ndx, argc, argv,
516cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_WHOLEARC),
517cdcc71c0SAli Bahrami 0, NULL)) != 0) {
51892a02081SRod Evans optarg =
51992a02081SRod Evans (char *)MSG_ORIG(MSG_ARG_ALLEXTRT);
52092a02081SRod Evans return (c);
52192a02081SRod Evans }
522cdcc71c0SAli Bahrami /*
523cdcc71c0SAli Bahrami * Translate --wrap to -z wrap=
524cdcc71c0SAli Bahrami */
525cdcc71c0SAli Bahrami if ((c = str2chr(lml, ndx, argc, argv,
526cdcc71c0SAli Bahrami arg, 'z', MSG_ORIG(MSG_ARG_T_WRAP),
527cdcc71c0SAli Bahrami MSG_ARG_T_WRAP_SIZE, str2chr_wrap_cb)) !=
528cdcc71c0SAli Bahrami 0) {
529cdcc71c0SAli Bahrami return (c);
530cdcc71c0SAli Bahrami }
53192a02081SRod Evans break;
53292a02081SRod Evans }
53392a02081SRod Evans break;
53492a02081SRod Evans }
53592a02081SRod Evans }
536cdcc71c0SAli Bahrami
53792a02081SRod Evans if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
53892a02081SRod Evans /*
53992a02081SRod Evans * It is possible that a "-Wl," argument has been used to
54092a02081SRod Evans * specify an option. This isn't advertized ld(1) syntax, but
54192a02081SRod Evans * compiler drivers and configuration tools, have been known to
54292a02081SRod Evans * pass this compiler option to ld(1). Strip off the "-Wl,"
54392a02081SRod Evans * prefix and pass the option through.
54492a02081SRod Evans */
54592a02081SRod Evans if ((c == 'W') && (strncmp(optarg,
54692a02081SRod Evans MSG_ORIG(MSG_ARG_T_WL), MSG_ARG_T_WL_SIZE) == 0)) {
54792a02081SRod Evans DBG_CALL(Dbg_args_Wldel(lml, ndx, optarg));
54892a02081SRod Evans c = optarg[MSG_ARG_T_WL_SIZE];
54992a02081SRod Evans optarg += MSG_ARG_T_WL_SIZE + 1;
55092a02081SRod Evans }
55192a02081SRod Evans }
55292a02081SRod Evans
55392a02081SRod Evans return (c);
55492a02081SRod Evans }
55592a02081SRod Evans
5567c478bd9Sstevel@tonic-gate /*
557e64d0ff9SAli Bahrami * A compare routine for Isd_node AVL trees.
5587c478bd9Sstevel@tonic-gate */
5596b3ba5bdSAli Bahrami int
isdavl_compare(const void * n1,const void * n2)5606b3ba5bdSAli Bahrami isdavl_compare(const void *n1, const void *n2)
5616b3ba5bdSAli Bahrami {
5626b3ba5bdSAli Bahrami uint_t hash1, hash2;
5636b3ba5bdSAli Bahrami const char *st1, *st2;
5646b3ba5bdSAli Bahrami int rc;
5656b3ba5bdSAli Bahrami
5666b3ba5bdSAli Bahrami hash1 = ((Isd_node *)n1)->isd_hash;
5676b3ba5bdSAli Bahrami hash2 = ((Isd_node *)n2)->isd_hash;
5686b3ba5bdSAli Bahrami
5696b3ba5bdSAli Bahrami if (hash1 > hash2)
5706b3ba5bdSAli Bahrami return (1);
5716b3ba5bdSAli Bahrami if (hash1 < hash2)
5726b3ba5bdSAli Bahrami return (-1);
5736b3ba5bdSAli Bahrami
574e64d0ff9SAli Bahrami st1 = ((Isd_node *)n1)->isd_name;
575e64d0ff9SAli Bahrami st2 = ((Isd_node *)n2)->isd_name;
5766b3ba5bdSAli Bahrami
5776b3ba5bdSAli Bahrami rc = strcmp(st1, st2);
5786b3ba5bdSAli Bahrami if (rc > 0)
5796b3ba5bdSAli Bahrami return (1);
5806b3ba5bdSAli Bahrami if (rc < 0)
5816b3ba5bdSAli Bahrami return (-1);
5826b3ba5bdSAli Bahrami return (0);
5836b3ba5bdSAli Bahrami }
5847c478bd9Sstevel@tonic-gate
5856b3ba5bdSAli Bahrami /*
5866b3ba5bdSAli Bahrami * Messaging support - funnel everything through dgettext().
5876b3ba5bdSAli Bahrami */
5887c478bd9Sstevel@tonic-gate const char *
_libld_msg(Msg mid)5897c478bd9Sstevel@tonic-gate _libld_msg(Msg mid)
5907c478bd9Sstevel@tonic-gate {
5917257d1b4Sraf return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate /*
5957c478bd9Sstevel@tonic-gate * Determine whether a symbol name should be demangled.
5967c478bd9Sstevel@tonic-gate */
5977c478bd9Sstevel@tonic-gate const char *
demangle(const char * name)5987c478bd9Sstevel@tonic-gate demangle(const char *name)
5997c478bd9Sstevel@tonic-gate {
6005aefb655Srie if (demangle_flag)
6015aefb655Srie return (Elf_demangle_name(name));
6027c478bd9Sstevel@tonic-gate else
6037c478bd9Sstevel@tonic-gate return (name);
6047c478bd9Sstevel@tonic-gate }
60508278a5eSRod Evans
60608278a5eSRod Evans /*
60708278a5eSRod Evans * Compare a series of platform or machine hardware names.
60808278a5eSRod Evans */
60908278a5eSRod Evans int
cap_names_match(Alist * alp1,Alist * alp2)61008278a5eSRod Evans cap_names_match(Alist *alp1, Alist *alp2)
61108278a5eSRod Evans {
61208278a5eSRod Evans Capstr *capstr1;
61308278a5eSRod Evans Aliste idx1;
61408278a5eSRod Evans int match = 0;
61508278a5eSRod Evans Word nitems;
61608278a5eSRod Evans
61708278a5eSRod Evans if ((nitems = alist_nitems(alp1)) != alist_nitems(alp2))
61808278a5eSRod Evans return (1);
61908278a5eSRod Evans
62008278a5eSRod Evans for (ALIST_TRAVERSE(alp1, idx1, capstr1)) {
62108278a5eSRod Evans Capstr *capstr2;
622*fb12490aSRichard Lowe Aliste idx2;
62308278a5eSRod Evans
62408278a5eSRod Evans for (ALIST_TRAVERSE(alp2, idx2, capstr2)) {
62508278a5eSRod Evans if (strcmp(capstr1->cs_str, capstr2->cs_str))
62608278a5eSRod Evans continue;
62708278a5eSRod Evans
62808278a5eSRod Evans match++;
62908278a5eSRod Evans break;
63008278a5eSRod Evans }
63108278a5eSRod Evans }
63208278a5eSRod Evans
63308278a5eSRod Evans if (nitems == match)
63408278a5eSRod Evans return (0);
63508278a5eSRod Evans
63608278a5eSRod Evans return (1);
63708278a5eSRod Evans }
638