1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright (c) 1988 AT&T
28 * All Rights Reserved
29 */
30
31 /*
32 * Copyright (c) 2018, Joyent, Inc.
33 */
34
35 /*
36 * Utility functions
37 */
38 #include <unistd.h>
39 #include <stdio.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <sys/types.h>
44 #include <sys/mman.h>
45 #include <errno.h>
46 #include <sgs.h>
47 #include <libintl.h>
48 #include <debug.h>
49 #include "msg.h"
50 #include "_libld.h"
51
52 /*
53 * Determine if a shared object definition structure already exists and if
54 * not create one. These definitions provide for recording information
55 * regarding shared objects that are still to be processed. Once processed
56 * shared objects are maintained on the ofl_sos list. The information
57 * recorded in this structure includes:
58 *
59 * o DT_USED requirements. In these cases definitions are added during
60 * mapfile processing of `-' entries (see map_dash()).
61 *
62 * o implicit NEEDED entries. As shared objects are processed from the
63 * command line so any of their dependencies are recorded in these
64 * structures for later processing (see process_dynamic()).
65 *
66 * o version requirements. Any explicit shared objects that have version
67 * dependencies on other objects have their version requirements recorded.
68 * In these cases definitions are added during mapfile processing of `-'
69 * entries (see map_dash()). Also, shared objects may have versioning
70 * requirements on their NEEDED entries. These cases are added during
71 * their version processing (see vers_need_process()).
72 *
73 * Note: Both process_dynamic() and vers_need_process() may generate the
74 * initial version definition structure because you can't rely on what
75 * section (.dynamic or .SUNW_version) may be processed first from any
76 * input file.
77 */
78 Sdf_desc *
sdf_find(const char * name,APlist * alp)79 sdf_find(const char *name, APlist *alp)
80 {
81 Aliste idx;
82 Sdf_desc *sdf;
83
84 for (APLIST_TRAVERSE(alp, idx, sdf))
85 if (strcmp(name, sdf->sdf_name) == 0)
86 return (sdf);
87
88 return (NULL);
89 }
90
91 Sdf_desc *
sdf_add(const char * name,APlist ** alpp)92 sdf_add(const char *name, APlist **alpp)
93 {
94 Sdf_desc *sdf;
95
96 if ((sdf = libld_calloc(1, sizeof (Sdf_desc))) == NULL)
97 return ((Sdf_desc *)S_ERROR);
98
99 sdf->sdf_name = name;
100
101 if (aplist_append(alpp, sdf, AL_CNT_OFL_LIBS) == NULL)
102 return ((Sdf_desc *)S_ERROR);
103
104 return (sdf);
105 }
106
107 /*
108 * Add a string, separated by a colon, to an existing string. Typically used
109 * to maintain filter, rpath and audit names, of which there is normally only
110 * one string supplied anyway.
111 */
112 char *
add_string(char * old,char * str)113 add_string(char *old, char *str)
114 {
115 char *new;
116
117 if (old) {
118 char *_str;
119 size_t len;
120
121 /*
122 * If an original string exists, make sure this new string
123 * doesn't get duplicated.
124 */
125 if ((_str = strstr(old, str)) != NULL) {
126 if (((_str == old) ||
127 (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) &&
128 (_str += strlen(str)) &&
129 ((*_str == '\0') ||
130 (*_str == *(MSG_ORIG(MSG_STR_COLON)))))
131 return (old);
132 }
133
134 len = strlen(old) + strlen(str) + 2;
135 if ((new = libld_calloc(1, len)) == NULL)
136 return ((char *)S_ERROR);
137 (void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str);
138 } else {
139 if ((new = libld_malloc(strlen(str) + 1)) == NULL)
140 return ((char *)S_ERROR);
141 (void) strcpy(new, str);
142 }
143
144 return (new);
145 }
146
147 /*
148 * The GNU ld '-wrap=XXX' and '--wrap=XXX' options correspond to our
149 * '-z wrap=XXX'. When str2chr() does this conversion, we end up with
150 * the return character set to 'z' and optarg set to 'XXX'. This callback
151 * changes optarg to include the missing wrap= prefix.
152 *
153 * exit:
154 * Returns c on success, or '?' on error.
155 */
156 static int
str2chr_wrap_cb(int c)157 str2chr_wrap_cb(int c)
158 {
159 char *str;
160 size_t len = MSG_ARG_WRAP_SIZE + strlen(optarg) + 1;
161
162 if ((str = libld_malloc(len)) == NULL)
163 return ('?');
164 (void) snprintf(str, len, MSG_ORIG(MSG_FMT_STRCAT),
165 MSG_ORIG(MSG_ARG_WRAP), optarg);
166 optarg = str;
167 return (c);
168 }
169
170 /*
171 * Determine whether this string, possibly with an associated option, should
172 * be translated to an option character. If so, update the optind and optarg
173 * and optopt as described for short options in getopt(3c).
174 *
175 * entry:
176 * lml - Link map list for debug messages
177 * ndx - Starting optind for current item
178 * argc, argv - Command line arguments
179 * arg - Option to be examined
180 * c, opt - Option character (c) and corresponding long name (opt)
181 * optsz - 0 if option does not accept a value. If option does
182 * accept a value, strlen(opt), giving the offset to the
183 * value if the option and value are combined in one string.
184 * cbfunc - NULL, or pointer to function to call if a translation is
185 * successful.
186 */
187 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))188 str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c,
189 const char *opt, size_t optsz, int (*cbfunc)(int))
190 {
191 if (optsz == 0) {
192 /*
193 * Compare a single option (ie. there's no associated option
194 * argument).
195 */
196 if (strcmp(arg, opt) == 0) {
197 DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
198 optind += 1;
199 optopt = c;
200 return (c);
201 }
202 } else if ((strcmp(arg, opt) == 0) ||
203 ((arg[optsz] == '=') && strncmp(arg, opt, optsz) == 0)) {
204 /*
205 * Otherwise, compare the option name, which may be
206 * concatenated with the option argument.
207 */
208 DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c));
209
210 if (arg[optsz] == '\0') {
211 /*
212 * Optarg is the next argument (white space separated).
213 * Make sure an optarg is available, and if not return
214 * a failure to prevent any fall-through to the generic
215 * getopt() processing.
216 *
217 * Since we'll be completely failing this option we
218 * don't want to update optopt with the translation,
219 * but also need to set it to _something_. Setting it
220 * to the '-' of the argument causes us to behave
221 * correctly.
222 */
223 if ((++optind + 1) > argc) {
224 optopt = arg[0];
225 return ('?');
226 }
227 optarg = argv[optind];
228 optind++;
229 } else {
230 /*
231 * GNU option/option argument pairs can be represented
232 * with a "=" separator. If this is the case, remove
233 * the separator.
234 */
235 optarg = &arg[optsz];
236 optind++;
237 if (*optarg == '=') {
238 if (*(++optarg) == '\0') {
239 optopt = arg[0];
240 return ('?');
241 }
242 }
243 }
244
245 if (cbfunc != NULL)
246 c = (*cbfunc)(c);
247 optopt = c;
248 return (c);
249 }
250 return (0);
251 }
252
253 /*
254 * Parse an individual option. The intent of this function is to determine if
255 * any known, non-Solaris options have been passed to ld(1). This condition
256 * can occur as a result of build configuration tools, because of users
257 * familiarity with other systems, or simply the users preferences. If a known
258 * non-Solaris option can be determined, translate that option into the Solaris
259 * counterpart.
260 *
261 * This function will probably never be a complete solution, as new, non-Solaris
262 * options are discovered, their translation will have to be added. Other
263 * non-Solaris options are incompatible with the Solaris link-editor, and will
264 * never be recognized. We support what we can.
265 */
266 int
ld_getopt(Lm_list * lml,int ndx,int argc,char ** argv)267 ld_getopt(Lm_list *lml, int ndx, int argc, char **argv)
268 {
269 int c;
270
271 if ((optind < argc) && argv[optind] && (argv[optind][0] == '-')) {
272 char *arg = &argv[optind][1];
273
274 switch (*arg) {
275 case 'r':
276 /* Translate -rpath <optarg> to -R <optarg> */
277 if ((c = str2chr(lml, ndx, argc, argv, arg, 'R',
278 MSG_ORIG(MSG_ARG_T_RPATH),
279 MSG_ARG_T_RPATH_SIZE, NULL)) != 0) {
280 return (c);
281 }
282 break;
283 case 's':
284 /* Translate -shared to -G */
285 if ((c = str2chr(lml, ndx, argc, argv, arg, 'G',
286 MSG_ORIG(MSG_ARG_T_SHARED), 0, NULL)) != 0) {
287 return (c);
288
289 /* Translate -soname <optarg> to -h <optarg> */
290 } else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h',
291 MSG_ORIG(MSG_ARG_T_SONAME),
292 MSG_ARG_T_SONAME_SIZE, NULL)) != 0) {
293 return (c);
294 }
295 break;
296 case 'w':
297 /* Translate -wrap to -z wrap= */
298 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
299 MSG_ORIG(MSG_ARG_T_WRAP) + 1,
300 MSG_ARG_T_WRAP_SIZE - 1, str2chr_wrap_cb)) != 0) {
301 return (c);
302 }
303 break;
304 case '(':
305 /*
306 * Translate -( to -z rescan-start
307 */
308 if ((c = str2chr(lml, ndx, argc, argv,
309 arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0, NULL)) !=
310 0) {
311 optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START);
312 return (c);
313 }
314 break;
315 case ')':
316 /*
317 * Translate -) to -z rescan-end
318 */
319 if ((c = str2chr(lml, ndx, argc, argv,
320 arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0, NULL)) !=
321 0) {
322 optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END);
323 return (c);
324 }
325 break;
326 case '-':
327 switch (*(arg + 1)) {
328 case 'a':
329 /*
330 * Translate --allow-multiple-definition to
331 * -zmuldefs
332 */
333 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
334 MSG_ORIG(MSG_ARG_T_MULDEFS), 0, NULL)) !=
335 0) {
336 optarg =
337 (char *)MSG_ORIG(MSG_ARG_MULDEFS);
338 return (c);
339
340 /*
341 * Translate --auxiliary <optarg> to
342 * -f <optarg>
343 */
344 } else if ((c = str2chr(lml, argc, ndx, argv,
345 arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR),
346 MSG_ARG_T_AUXFLTR_SIZE, NULL)) != 0) {
347 return (c);
348 }
349 break;
350 case 'd':
351 /*
352 * Translate --dynamic-linker <optarg> to
353 * -I <optarg>
354 */
355 if ((c = str2chr(lml, ndx, argc, argv, arg, 'I',
356 MSG_ORIG(MSG_ARG_T_INTERP),
357 MSG_ARG_T_INTERP_SIZE, NULL)) != 0) {
358 return (c);
359 }
360 break;
361 case 'e':
362 /* Translate --entry <optarg> to -e <optarg> */
363 if ((c = str2chr(lml, ndx, argc, argv, arg, 'e',
364 MSG_ORIG(MSG_ARG_T_ENTRY),
365 MSG_ARG_T_ENTRY_SIZE, NULL)) != 0) {
366 return (c);
367 }
368 /*
369 * Translate --end-group to -z rescan-end
370 */
371 if ((c = str2chr(lml, ndx, argc, argv,
372 arg, 'z', MSG_ORIG(MSG_ARG_T_ENDGROUP),
373 0, NULL)) != 0) {
374 optarg = (char *)
375 MSG_ORIG(MSG_ARG_RESCAN_END);
376 return (c);
377 }
378 break;
379 case 'f':
380 /*
381 * Translate --fatal-warnings to
382 * -z fatal-warnings.
383 */
384 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
385 MSG_ORIG(MSG_ARG_T_FATWARN),
386 0, NULL)) != 0) {
387 optarg = (char *)
388 MSG_ORIG(MSG_ARG_FATWARN);
389 return (c);
390 }
391 /* Translate --filter <optarg> to -F <optarg> */
392 if ((c = str2chr(lml, ndx, argc, argv, arg, 'F',
393 MSG_ORIG(MSG_ARG_T_STDFLTR),
394 MSG_ARG_T_STDFLTR_SIZE, NULL)) != 0) {
395 return (c);
396 }
397 break;
398 case 'h':
399 /* Translate --help to -zhelp */
400 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
401 MSG_ORIG(MSG_ARG_T_HELP), 0, NULL)) !=
402 0) {
403 optarg = (char *)MSG_ORIG(MSG_ARG_HELP);
404 return (c);
405 }
406 break;
407 case 'l':
408 /*
409 * Translate --library <optarg> to -l <optarg>
410 */
411 if ((c = str2chr(lml, ndx, argc, argv, arg, 'l',
412 MSG_ORIG(MSG_ARG_T_LIBRARY),
413 MSG_ARG_T_LIBRARY_SIZE, NULL)) != 0) {
414 return (c);
415
416 /*
417 * Translate --library-path <optarg> to
418 * -L <optarg>
419 */
420 } else if ((c = str2chr(lml, ndx, argc, argv,
421 arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH),
422 MSG_ARG_T_LIBPATH_SIZE, NULL)) != 0) {
423 return (c);
424 }
425 break;
426 case 'n':
427 /*
428 * Translate --no-fatal-warnings to
429 * -z nofatal-warnings.
430 */
431 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
432 MSG_ORIG(MSG_ARG_T_NOFATWARN),
433 0, NULL)) != 0) {
434 optarg = (char *)
435 MSG_ORIG(MSG_ARG_NOFATWARN);
436 return (c);
437 }
438
439 /* Translate --no-undefined to -zdefs */
440 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
441 MSG_ORIG(MSG_ARG_T_NOUNDEF), 0, NULL)) !=
442 0) {
443 optarg = (char *)MSG_ORIG(MSG_ARG_DEFS);
444 return (c);
445
446 /*
447 * Translate --no-whole-archive to
448 * -z defaultextract
449 */
450 } else if ((c = str2chr(lml, ndx, argc, argv,
451 arg, 'z', MSG_ORIG(MSG_ARG_T_NOWHOLEARC),
452 0, NULL)) != 0) {
453 optarg =
454 (char *)MSG_ORIG(MSG_ARG_DFLEXTRT);
455 return (c);
456 }
457 break;
458 case 'o':
459 /* Translate --output <optarg> to -o <optarg> */
460 if ((c = str2chr(lml, ndx, argc, argv, arg, 'o',
461 MSG_ORIG(MSG_ARG_T_OUTPUT),
462 MSG_ARG_T_OUTPUT_SIZE, NULL)) != 0) {
463 return (c);
464 }
465 break;
466 case 'r':
467 /* Translate --relocatable to -r */
468 if ((c = str2chr(lml, ndx, argc, argv, arg, 'r',
469 MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0,
470 NULL)) != 0) {
471 return (c);
472 }
473 break;
474 case 's':
475 /* Translate --strip-all to -s */
476 if ((c = str2chr(lml, ndx, argc, argv, arg, 's',
477 MSG_ORIG(MSG_ARG_T_STRIP), 0, NULL)) !=
478 0) {
479 return (c);
480 }
481 /*
482 * Translate --start-group to -z rescan-start
483 */
484 if ((c = str2chr(lml, ndx, argc, argv,
485 arg, 'z', MSG_ORIG(MSG_ARG_T_STARTGROUP),
486 0, NULL)) != 0) {
487 optarg = (char *)
488 MSG_ORIG(MSG_ARG_RESCAN_START);
489 return (c);
490 }
491 break;
492 case 'u':
493 /*
494 * Translate --undefined <optarg> to
495 * -u <optarg>
496 */
497 if ((c = str2chr(lml, ndx, argc, argv, arg, 'u',
498 MSG_ORIG(MSG_ARG_T_UNDEF),
499 MSG_ARG_T_UNDEF_SIZE, NULL)) != 0) {
500 return (c);
501 }
502 break;
503 case 'v':
504 /* Translate --version to -V */
505 if ((c = str2chr(lml, ndx, argc, argv, arg, 'V',
506 MSG_ORIG(MSG_ARG_T_VERSION), 0, NULL)) !=
507 0) {
508 return (c);
509 }
510 break;
511 case 'w':
512 /*
513 * Translate --whole-archive to -z alltextract
514 */
515 if ((c = str2chr(lml, ndx, argc, argv,
516 arg, 'z', MSG_ORIG(MSG_ARG_T_WHOLEARC),
517 0, NULL)) != 0) {
518 optarg =
519 (char *)MSG_ORIG(MSG_ARG_ALLEXTRT);
520 return (c);
521 }
522 /*
523 * Translate --wrap to -z wrap=
524 */
525 if ((c = str2chr(lml, ndx, argc, argv,
526 arg, 'z', MSG_ORIG(MSG_ARG_T_WRAP),
527 MSG_ARG_T_WRAP_SIZE, str2chr_wrap_cb)) !=
528 0) {
529 return (c);
530 }
531 break;
532 }
533 break;
534 }
535 }
536
537 if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
538 /*
539 * It is possible that a "-Wl," argument has been used to
540 * specify an option. This isn't advertized ld(1) syntax, but
541 * compiler drivers and configuration tools, have been known to
542 * pass this compiler option to ld(1). Strip off the "-Wl,"
543 * prefix and pass the option through.
544 */
545 if ((c == 'W') && (strncmp(optarg,
546 MSG_ORIG(MSG_ARG_T_WL), MSG_ARG_T_WL_SIZE) == 0)) {
547 DBG_CALL(Dbg_args_Wldel(lml, ndx, optarg));
548 c = optarg[MSG_ARG_T_WL_SIZE];
549 optarg += MSG_ARG_T_WL_SIZE + 1;
550 }
551 }
552
553 return (c);
554 }
555
556 /*
557 * A compare routine for Isd_node AVL trees.
558 */
559 int
isdavl_compare(const void * n1,const void * n2)560 isdavl_compare(const void *n1, const void *n2)
561 {
562 uint_t hash1, hash2;
563 const char *st1, *st2;
564 int rc;
565
566 hash1 = ((Isd_node *)n1)->isd_hash;
567 hash2 = ((Isd_node *)n2)->isd_hash;
568
569 if (hash1 > hash2)
570 return (1);
571 if (hash1 < hash2)
572 return (-1);
573
574 st1 = ((Isd_node *)n1)->isd_name;
575 st2 = ((Isd_node *)n2)->isd_name;
576
577 rc = strcmp(st1, st2);
578 if (rc > 0)
579 return (1);
580 if (rc < 0)
581 return (-1);
582 return (0);
583 }
584
585 /*
586 * Messaging support - funnel everything through dgettext().
587 */
588 const char *
_libld_msg(Msg mid)589 _libld_msg(Msg mid)
590 {
591 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
592 }
593
594 /*
595 * Determine whether a symbol name should be demangled.
596 */
597 const char *
demangle(const char * name)598 demangle(const char *name)
599 {
600 if (demangle_flag)
601 return (Elf_demangle_name(name));
602 else
603 return (name);
604 }
605
606 /*
607 * Compare a series of platform or machine hardware names.
608 */
609 int
cap_names_match(Alist * alp1,Alist * alp2)610 cap_names_match(Alist *alp1, Alist *alp2)
611 {
612 Capstr *capstr1;
613 Aliste idx1;
614 int match = 0;
615 Word nitems;
616
617 if ((nitems = alist_nitems(alp1)) != alist_nitems(alp2))
618 return (1);
619
620 for (ALIST_TRAVERSE(alp1, idx1, capstr1)) {
621 Capstr *capstr2;
622 Aliste idx2;
623
624 for (ALIST_TRAVERSE(alp2, idx2, capstr2)) {
625 if (strcmp(capstr1->cs_str, capstr2->cs_str))
626 continue;
627
628 match++;
629 break;
630 }
631 }
632
633 if (nitems == match)
634 return (0);
635
636 return (1);
637 }
638