summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/libld/common/_libld.h
blob: 7cbfe05e651b8df51ae0c64114f8c821f1807b88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *	Copyright (c) 1988 AT&T
 *	  All Rights Reserved
 *
 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
 */

/*
 * Local include file for ld library.
 */

#ifndef	_LIBLD_DOT_H
#define	_LIBLD_DOT_H

#include <libld.h>
#include <_libelf.h>
#include <debug.h>
#include <conv.h>
#include <msg.h>
#include <reloc_defs.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * In order to allow for cross linking, we need to be able to build
 * libld with support for multiple targets within a single object.
 * This is done using a global variable (ld_targ) of type Target to
 * access target-specific code for the current target via indirection.
 */

/*
 * Machine information for target
 */
typedef struct {
	Half		m_mach;		/* ELF machine code for target */
	Half		m_machplus;	/* Alt ELF machine code for target */
					/*	Used for EM_SPARC32PLUS */
	Word		m_flagsplus;	/* ELF header flags used to identify */
					/*	a machplus object */
	uchar_t		m_class;	/* Target ELFCLASS */
	uchar_t		m_data;		/* Target byte order */

	Xword		m_segm_align;	/* segment alignment */
	Xword		m_segm_origin;	/* Default 1st segment origin */
	Xword		m_segm_aorigin;	/* Alternative 1st segment origin */
	Word		m_dataseg_perm;	/* data segment permission mask */
	Word		m_stack_perm;	/* ABI default stack permission mask */
	Word		m_word_align;	/* alignment to use for Word sections */
	const char	*m_def_interp;	/* Def. interpreter for dyn objects */

	/* Relocation type codes */
	Word		m_r_arrayaddr;
	Word		m_r_copy;
	Word		m_r_glob_dat;
	Word		m_r_jmp_slot;
	Word		m_r_num;
	Word		m_r_none;
	Word		m_r_relative;
	Word		m_r_register;

	/* Relocation related constants */
	Word		m_rel_dt_count;	/* Either DT_REL or DT_RELA */
	Word		m_rel_dt_ent;	/* Either DT_RELENT or DT_RELAENT */
	Word		m_rel_dt_size;	/* Either DT_RELSZ or DT_RELASZ */
	Word		m_rel_dt_type;	/* Either DT_RELCOUNT or DT_RELACOUNT */
	Word		m_rel_sht_type;	/* Either SHT_REL or SHT_RELA */

	/* GOT related constants */
	Word		m_got_entsize;
	Word		m_got_xnumber;	/* reserved # of got ents */

	/* PLT related constants */
	Word		m_plt_align;
	Word		m_plt_entsize;
	Word		m_plt_reservsz;
	Word		m_plt_shf_flags;

	/* Section type of .eh_frame/.eh_frame_hdr sections */
	Word		m_sht_unwind;

	Word		m_dt_register;
} Target_mach;


/*
 * Section identifiers, used to order sections in output object
 */
typedef struct {
	Word		id_array;
	Word		id_bss;
	Word		id_cap;
	Word		id_capinfo;
	Word		id_capchain;
	Word		id_data;
	Word		id_dynamic;
	Word		id_dynsort;
	Word		id_dynstr;
	Word		id_dynsym;
	Word		id_dynsym_ndx;
	Word		id_got;
	Word		id_gotdata;
	Word		id_hash;
	Word		id_interp;
	Word		id_lbss;
	Word		id_ldynsym;
	Word		id_note;
	Word		id_null;
	Word		id_plt;
	Word		id_rel;
	Word		id_strtab;
	Word		id_syminfo;
	Word		id_symtab;
	Word		id_symtab_ndx;
	Word		id_text;
	Word		id_tls;
	Word		id_tlsbss;
	Word		id_unknown;
	Word		id_unwind;
	Word		id_unwindhdr;
	Word		id_user;
	Word		id_version;
} Target_machid;

/*
 * Target_nullfunc supplies machine code for generating a
 *
 *	void (*)(void)
 *
 * unnamed function. Such a function can be called, and returns
 * immediately without doing any work. This is used to back FUNC
 * symbol definitions added with a mapfile.
 *
 * The machine instructions are specified as an array of bytes rather
 * than a larger integer type in order to avoid byte order issues that
 * can otherwise occur in cross linking.
 */
typedef struct {
	const uchar_t	*nf_template;	/* Array of machine inst. bytes */
	size_t		nf_size;	/* # bytes in nf_template */
} Target_nullfunc;

/*
 * Target_fill supplies machine code for fill bytes in executable output
 * sections. Normally, libelf fills the gaps caused by alignment and size
 * requirements of the constituent input sections with 0. Depending on the
 * target architecture, it may be desirable to instead fill with executable
 * NOP instructions. There are two reasons to do this:
 *
 *  -	So that .init/.fini sections will not contain unexecutable gaps
 *	that cause the executing program to trap and die.
 *
 *  -	To eliminate confusing garbage instructions between sections containing
 *	executable code when viewed with a disassembler.
 *
 * The ff_execfill function is allowed to be NULL if the underlying target
 * does not require a special fill for executable sections.
 */
typedef struct {
	_elf_execfill_func_t	*ff_execfill;
} Target_fillfunc;

/*
 * Target_machrel holds pointers to the reloc_table and machrel functions
 * for a given target machine.
 *
 * The following function pointers are allowed to be NULL, if the
 * underlying target does not require the specified operation. All
 * other functions must be supplied:
 *
 *	mr_assign_got
 *	mr_reloc_register
 *	mr_reloc_GOTOP
 *	mr_allocate_got
 */
typedef struct {
	const Rel_entry	*mr_reloc_table;

	Word		(* mr_init_rel)(Rel_desc *, Word *, void *);
	void		(* mr_mach_eflags)(Ehdr *, Ofl_desc *);
	void		(* mr_mach_make_dynamic)(Ofl_desc *, size_t *);
	void		(* mr_mach_update_odynamic)(Ofl_desc *, Dyn **);
	Xword		(* mr_calc_plt_addr)(Sym_desc *, Ofl_desc *);
	uintptr_t	(* mr_perform_outreloc)(Rel_desc *, Ofl_desc *,
			    Boolean *);
	uintptr_t	(* mr_do_activerelocs)(Ofl_desc *);
	uintptr_t	(* mr_add_outrel)(Word, Rel_desc *, Ofl_desc *);
	uintptr_t	(* mr_reloc_register)(Rel_desc *, Is_desc *,
			    Ofl_desc *);
	uintptr_t	(* mr_reloc_local)(Rel_desc *, Ofl_desc *);
	uintptr_t	(* mr_reloc_GOTOP)(Boolean, Rel_desc *, Ofl_desc *);
	uintptr_t	(* mr_reloc_TLS)(Boolean, Rel_desc *, Ofl_desc *);
	uintptr_t	(* mr_assign_got)(Ofl_desc *, Sym_desc *);

	Gotndx		*(* mr_find_got_ndx)(Alist *, Gotref, Ofl_desc *,
			    Rel_desc *);
	Xword		(* mr_calc_got_offset)(Rel_desc *, Ofl_desc *);
	uintptr_t	(* mr_assign_got_ndx)(Alist **, Gotndx *, Gotref,
			    Ofl_desc *, Rel_desc *, Sym_desc *);
	void		(* mr_assign_plt_ndx)(Sym_desc *, Ofl_desc *);
	uintptr_t	(* mr_allocate_got)(Ofl_desc *);
	uintptr_t	(* mr_fillin_gotplt)(Ofl_desc *);
} Target_machrel;


/*
 * Target_machsym holds pointers to the machsym functions
 * for a given target machine.
 *
 * These fields are allowed to be NULL for targets that do not require
 * special handling of register symbols. Register symbols are used by
 * sparc targets. If any of these fields are non-NULL, all of them are
 * required to be present (use empty stub routines if necessary).
 */
typedef struct {
	int		(* ms_reg_check)(Sym_desc *, Sym *, const char *,
			    Ifl_desc *, Ofl_desc *);
	int		(* ms_mach_sym_typecheck)(Sym_desc *, Sym *,
			    Ifl_desc *, Ofl_desc *);
	const char	*(* ms_is_regsym)(Ofl_desc *, Ifl_desc *, Sym *,
			    const char *, int, Word, const char *, sd_flag_t *);
	Sym_desc	*(* ms_reg_find)(Sym * sym, Ofl_desc * ofl);
	int		(* ms_reg_enter)(Sym_desc *, Ofl_desc *);
} Target_machsym;

typedef struct {
	Target_mach	t_m;
	Target_machid	t_id;
	Target_nullfunc	t_nf;
	Target_fillfunc	t_ff;
	Target_machrel	t_mr;
	Target_machsym	t_ms;
} Target;

/*
 * Structure to manage the update of weak symbols from their associated alias.
 */
typedef	struct wk_desc {
	Sym		*wk_symtab;	/* the .symtab entry */
	Sym		*wk_dynsym;	/* the .dynsym entry */
	Sym_desc	*wk_weak;	/* the original weak symbol */
	Sym_desc	*wk_alias;	/* the real symbol */
} Wk_desc;

/*
 * Structure to manage the support library interfaces.
 */
typedef struct func_list {
	const char	*fl_obj;	/* name of support object */
					/*	function is from */
	void		(*fl_fptr)();	/* function pointer */
	uint_t		fl_version;	/* ld_version() level */
} Func_list;

typedef	struct support_list {
	const char	*sup_name;	/* ld_support function name */
	Alist		*sup_funcs;	/* list of support functions */
} Support_list;

/*
 * Structure to manage a sorted output relocation list.
 *
 *	rl_key1		->	pointer to needed ndx
 *	rl_key2		->	pointer to symbol relocation is against
 *	rl_key3		->	virtual offset of relocation
 */
typedef struct reloc_list {
	Sym_desc	*rl_key2;
	Xword		rl_key3;
	Rel_desc	*rl_rsp;
	Half		rl_key1;
} Reloc_list;


typedef struct sym_s_list {
	Word		sl_hval;
	Sym_desc	*sl_sdp;
} Sym_s_list;

/*
 * Dynamic per-symbol filtee string table descriptor.  This associates filtee
 * strings that will be created in the .dynstr, with .dynamic entries.
 */
typedef struct {
	const char	*dft_str;	/* dynstr string */
	Word		dft_flag;	/* auxiliary/filtee type */
	Half		dft_ndx;	/* eventual ndx into .dynamic */
} Dfltr_desc;

/*
 * Per-symbol filtee descriptor.  This associates symbol definitions with
 * their filtees.
 */
typedef struct {
	Sym_desc	*sft_sdp;	/* symbol descriptor */
	Aliste		sft_idx;	/* index into dtstr descriptor */
} Sfltr_desc;

/*
 * Capabilities descriptor, and capabilities group descriptor, used to track
 * the symbol capabilities of any input files and the output file.
 *
 * A relocatable object input file may contain one or more symbol capabilities
 * groups.  The Cap_desc structures keep track of all unique groups that are
 * collected for the output file.  Relocatable objects that contain an object
 * capabilities group, and the -z symbolcap option is in effect, have their
 * object group translated to a symbol capabilities group.
 *
 * Individual capabilities groups are maintained with the Cap_group descriptor.
 * A group can consist of one or more capabilities definitions.  One or more
 * symbols can be associated with each group.
 *
 * For the output file, capabilities families are used to track the symbols of
 * a given family, each symbol being associated with a different group.  This
 * collection of data is used to create the final Capinfo structure, and for
 * dynamic objects, the Capchain structure.
 *
 * For example, an object may contain two capabilities groups:
 *
 *	CA_SUNW_MACH - sun4u		CA_SUNW_MACH - sun4v
 *
 * Two symbols can be associated with each group:
 *
 *	foo%sun4u			foo%sun4v
 *	bar%sun4u			bar%sun4v
 *
 * Two families are maintained, and include the generic, or lead, instance of
 * the capabilities members:
 *
 *	foo,  foo%sun4u,  foo%sun4v
 *	bar,  bar%sun4u,  bar%sun4v
 */
struct cap_desc {
	APlist		*ca_groups;	/* capabilities groups (Cap_group) */
	APlist		*ca_syms;	/* copies of symbols that are being */
					/*	translated from object to */
};					/*	symbol capabilities */

typedef struct {
	Objcapset	cg_set;		/* unpacked SHT_SUNW_cap elements */
	APlist		*cg_secs;	/* sections, and hence files, that */
					/*	use this descriptor */
	Word		cg_num;		/* number of comparable elements in */
					/*	the group */
	Word		cg_ndx;		/* final capability group index */
} Cap_group;

/*
 * A Capabilities family node, extends a symbol node, and provides for tracking
 * capabilities families.  A family is defined by its lead symbol (for example,
 * a generic, non-capabilities aware foo()), and one or more capabilities
 * members (for example, capabilities instances foo%sun4u(), foo%sun4v(), etc.).
 *
 * Each member associates a symbol with its group using a Cap_sym structure.
 */
typedef struct {
	Sym_avlnode	cn_symavlnode;
	APlist		*cn_members;
	APlist		*cn_aliases;
} Cap_avlnode;

typedef struct {
	Sym_desc	*cs_sdp;	/* capabilities symbol descriptor */
	Cap_group	*cs_group;	/* associated capabilities group */
} Cap_sym;

/*
 * Define Alist initialization sizes.
 */
#define	AL_CNT_IFL_GROUPS	20	/* ifl_groups */
#define	AL_CNT_IFL_RELSECS	6	/* ifl_relsect */

#define	AL_CNT_CAP_DESCS	4	/* symbol capabilities descriptors */
#define	AL_CNT_CAP_SYMS		20	/* capabilities symbols */
#define	AL_CNT_CAP_SECS		10	/* capabilities sections */
#define	AL_CNT_CAP_NAMES	10	/* Objcapset platform and machine */
					/*	names */
#define	AL_CNT_CAP_MEMS		10	/* capability family members */
#define	AL_CNT_CAP_PAIRS	10	/* capability symbol pairs */
#define	AL_CNT_CAP_ALIASES	2	/* capability lead symbol aliases */

#define	AL_CNT_OFL_DTSFLTRS	4	/* ofl_dtsfltrs */
#define	AL_CNT_OFL_SYMFLTRS	20	/* ofl_symfltrs */
#define	AL_CNT_OFL_MAPSECS	10	/* ofl_map{text|data} */
#define	AL_CNT_OFL_OBJS		50	/* ofl_objs */
#define	AL_CNT_OFL_LIBS		10	/* ofl_sos */
#define	AL_CNT_OFL_LIBDIRS	10	/* ofl_[ud]libdirs */
#define	AL_CNT_OFL_MAPFILES	6	/* ofl_maps */
#define	AL_CNT_OFL_ENTRANCE	10	/* ofl_ents */
#define	AL_CNT_OFL_RELS		4	/* ofl_outrels */
#define	AL_CNT_OFL_COPYRELS	10	/* ofl_copyrels */
#define	AL_CNT_OFL_ARRAYS	10	/* ofl_{init|fini|prei}array */
#define	AL_CNT_OFL_OSGROUPS	10	/* ofl_osgroups */
#define	AL_CNT_OFL_OSTLSSEG	4	/* ofl_ostlsseg */
#define	AL_CNT_OFL_ORDERED	4	/* ofl_ordered */
#define	AL_CNT_OFL_SYMINFOSYMS	50	/* ofl_syminfsyms */
#define	AL_CNT_OFL_MOVE		10	/* ofl_ismove */
#define	AL_CNT_OFL_UNWIND	1	/* ofl_unwind */
#define	AL_CNT_OFL_PARSYMS	10	/* ofl_parsyms */

#define	AL_CNT_OS_MSTRISDESCS	10	/* os_mstrisdescs */
#define	AL_CNT_OS_RELISDESCS	100	/* os_relisdescs */
#define	AL_CNT_OS_COMDATS	20	/* os_comdats */
#define	AL_CNT_OS_ISDESCS_BA	4	/* os_isdesc: BEFORE|AFTER */
#define	AL_CNT_OS_ISDESCS	60	/* os_isdesc: ORDERED|DEFAULT */

#define	AL_CNT_SG_IS_ORDER	40	/* sg_is_order */
#define	AL_CNT_SG_OSDESC	40	/* sg_osdescs */
#define	AL_CNT_SG_SECORDER	40	/* sg_secorder */
#define	AL_CNT_SG_SIZESYM	1	/* sg_sizesym */

#define	AL_CNT_SDP_GOT		1	/* sd_GOTndxs */
#define	AL_CNT_SDP_MOVE		1	/* sd_move */
#define	AL_CNT_SDP_DFILES	1	/* sa_dfiles */

#define	AL_CNT_SDF_VERSIONS	2	/* sdf_{vers|verneed} */

#define	AL_CNT_EC_FILES		1	/* ec_files */

#define	AL_CNT_VERDESCS		20	/* version desc */
#define	AL_CNT_WEAK		20	/* weak desc */
#define	AL_CNT_SUPPORT		2	/* support libraries */
#define	AL_CNT_STRMRGREL	500	/* ld_make_strmerge() reloc alist cnt */
#define	AL_CNT_STRMRGSYM	20	/* ld_make_strmerge() sym alist cnt */
#define	AL_CNT_SEGMENTS		20	/* ofl_segs */

#define	AL_CNT_ASSDEFLIB	4	/* ofl_assdeflib exceptions count */
#define	AL_CNT_MAPASSERT	10	/* mapfile assertions */

/*
 * Return codes for {tls|got}_fixups() routines
 */
typedef enum {
	FIX_ERROR,	/* fatal error - time to punt */
	FIX_DONE,	/* relocation done - no further processing required */
	FIX_RELOC	/* do_reloc() relocation processing required */
} Fixupret;

#ifndef	FILENAME_MAX
#define	FILENAME_MAX	BUFSIZ		/* maximum length of a path name */
#endif

/*
 * We pad the end of the .dynstr section with a block of DYNSTR_EXTRA_PAD
 * bytes, and we insert DYNAMIC_EXTRA_ELTS unused items into the
 * .dynamic section (with value DT_NULL). This provides the resources needed
 * to add and/or alter string items in the .dynamic section, such as runpath.
 */
#define	DYNSTR_EXTRA_PAD	512
#define	DYNAMIC_EXTRA_ELTS	10

/*
 * Default relocation cache allocation unit. This number should be small
 * enough to not hurt memory use significantly, but large enough to avoid
 * the need for too many subsequent allocations.
 */
#define	REL_CACHEBUF_ALLOC	3000
#define	RELAUX_CACHEBUF_ALLOC	1500

/*
 * Given a symbol of a type that is allowed within a .SUNW_dynsymsort or
 * .SUNW_dyntlssort section, examine the symbol attributes to determine
 * if this particular symbol should be included or not.
 *
 * entry:
 *	The symbol must have an allowed type: Either a type verified by
 *	dynsymsort_symtype[] or STT_TLS.
 *
 *	_sdp - Pointer to symbol descriptor
 *	_sym - Pointer to symbol referenced by _sdp.
 *
 *	_sym is derivable from _sdp: _sdp->sd_sym
 *	However, most callers assign it to a local variable for efficiency,
 *	and this macro allows such a variable to be used within. If you
 *	don't have such a variable, supply _sdp->sd_sym.
 *
 * The tests used require some explanation:
 *
 *	(_sdp->sd_flags & FLG_SY_DYNSORT)
 *		Some special symbols are kept even if they don't meet the
 *		usual requirements. These symbols have the FLG_SY_DYNSORT
 *		bit set. If this bit isn't set then we look at the other
 *		attributes.
 *
 *	(((_sdp->sd_ref != REF_DYN_NEED) &&
 *		(_sdp->sd_sym->st_shndx != SHN_UNDEF))
 *	|| (_sdp->sd_flags & FLG_SY_MVTOCOMM))
 *		We do not want to include symbols that are not defined within
 *		the object we are creating. REF_DYN_NEED corresponds to those
 *		UNDEF items. However, if the symbol is the target of a copy
 *		relocation, then it effectively becomes defined within the
 *		object after all. FLG_SY_MVTOCOMM indicates a copy relocation,
 *		and prevents us from culling those exceptions.
 *
 *	(_sym->st_size != 0)
 *		Symbols with 0 length are labels injected by the compilers
 *		or the linker for purposes of code generation, and do
 *		not directly correspond to actual code. In fact, most of the
 *		symbols we mark with FLG_SY_DYNSORT need that flag set because
 *		they have size 0. This size test filters out the others.
 *
 *	!(_sdp->sd_flags & FLG_SY_NODYNSORT)
 *		Some symbols are not kept, even though they do meet the usual
 *		requirements. These symbols have FLG_SY_NODYNSORT set.
 *		For example, if there are weak and non-weak versions of a given
 *		symbol, we only want to keep one of them. So, we set
 *		FLG_SY_NODYNSORT on the one we don't want.
 */
#define	DYNSORT_TEST_ATTR(_sdp, _sym) \
	((_sdp->sd_flags & FLG_SY_DYNSORT) || \
	((((_sdp->sd_ref != REF_DYN_NEED) && \
		(_sdp->sd_sym->st_shndx != SHN_UNDEF)) || \
		(_sdp->sd_flags & FLG_SY_MVTOCOMM)) && \
	(_sym->st_size != 0) && \
	!(_sdp->sd_flags & FLG_SY_NODYNSORT)))

/*
 * We use output section descriptor counters to add up the number of
 * symbol indexes to put in the .SUNW_dynsort and .SUNW_dyntlssort sections.
 * Non-TLS symbols are counted by ofl->ofl_dynsymsortcnt, while TLS symbols are
 * counted by ofl->ofl_dyntlssortcnt. This computation is done inline in
 * several places. The DYNSORT_COUNT macro allows us to generate this from
 * a single description.
 *
 * entry:
 *	_sdp, _sym - As per DYNSORT_TEST_ATTR
 *	_type - Type of symbol (STT_*)
 *	_inc_or_dec_op - Either ++, or --. This specifies the operation
 *		to be applied to the counter, and determines whether we
 *		are adding, or removing, a symbol from .SUNW_dynsymsort.
 *
 * Note that _type is derivable from _sym: ELF_ST_TYPE(_sdp->sd_sym->st_info).
 * Most callers already have it in a variable, so this allows us to use that
 * variable. If you don't have such a variable, use ELF_ST_TYPE() as shown.
 */
#define	DYNSORT_COUNT(_sdp, _sym, _type, _inc_or_dec_op) \
{ \
	Word *_cnt_var; \
	\
	if (dynsymsort_symtype[_type]) {	/* Non-TLS counter */ \
		_cnt_var = &ofl->ofl_dynsymsortcnt; \
	} else if ((_type) == STT_TLS) {	/* TLS counter */ \
		_cnt_var = &ofl->ofl_dyntlssortcnt; \
	} else {				/* Don't count this symbol */ \
		_cnt_var = NULL; \
	} \
	if ((_cnt_var != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \
		(*_cnt_var)_inc_or_dec_op;	/* Increment/Decrement */ \
}

/*
 * The OFL_SWAP_RELOC macros are used to determine whether
 * relocation processing needs to swap the data being relocated.
 * It is an optimization to ld_swap_reloc_data(), as it avoids
 * the function call in the case where the linker host and the
 * target have the same byte order.
 */
#define	OFL_SWAP_RELOC_DATA(_ofl, _rel) \
	(((_ofl)->ofl_flags1 & FLG_OF1_ENCDIFF) && \
	ld_swap_reloc_data(_ofl, _rel))

/*
 * Define an AVL node for maintaining input section descriptors. AVL trees of
 * these descriptors are used to process group and COMDAT section.
 *
 * Pure COMDAT uses the input section name as the search key, while
 * SHT_GROUP sections use the name of a special signature symbol. We
 * support both by using the isd_name field to carry the name. An alternative
 * design would be to use a separate type for each use, saving the cost
 * of the unneeded pointer for pure COMDAT. We favor a single implementation
 * because we believe that SHT_GROUP comdat will be more common going forward,
 * particularly in the largest objects produced by C++ where SHT_GROUP is
 * needed to manage the complex section relationships. In contrast, we think
 * that pure COMDAT is both more rare, and used in smaller objects where the
 * cost of an extra pointer per node is relatively unimportant.
 */
typedef struct {
	avl_node_t	isd_avl;	/* avl book-keeping (see SGSOFFSETOF) */
	Is_desc		*isd_isp;	/* input section descriptor */
	const char	*isd_name;	/* name used as search key */
	uint_t		isd_hash;	/* input section name hash value */
} Isd_node;

/*
 * Type used to break down an input file path into its component parts,
 * as used by ld_place_section() to compare an input file path to
 * entrance criteria ec_files file strings.
 *
 * We define a path in the usual Unix '/' separated manner, augmented
 * with an optional archive member suffix enclosed in parenthesis:
 *
 *	/dir/.../dir/basename(armember)
 *
 * The basename is the final path component, and includes the archive
 * member, if present. The meaning of "object name" depends on whether or
 * not the file comes from an archive or not. If not an archive, it is the
 * same as the basename. If an archive, it is the name of the archive member
 * from within the file.
 *
 * Variables of this type are initialized with ld_place_path_info_init().
 */
typedef struct {
	const char	*ppi_path;	/* Full path */
	const char	*ppi_bname;	/* basename(ppi_path) */
	const char	*ppi_oname;	/* object name: Not NULL terminated */
	Boolean		ppi_isar;	/* TRUE if path has archive member */
	size_t		ppi_path_len;	/* strlen(ppi_path) */
	size_t		ppi_bname_len;	/* strlen(ppi_bname) */
	size_t		ppi_oname_len;	/* strlen(ppi_oname) */
} Place_path_info;

/*
 * Local data items.
 */
extern char		*Plibpath;
extern char		*Llibdir;
extern char		*Ulibdir;
extern APlist		*lib_support;
extern int		demangle_flag;
extern const Msg	reject[];
extern int		Verbose;
extern const int	ldynsym_symtype[];
extern const int	dynsymsort_symtype[];

/*
 * Local functions.
 */
extern char		*add_string(char *, char *);
extern const char	*demangle(const char *);
extern int		cap_names_match(Alist *, Alist *);

extern void		lds_atexit(Ofl_desc *, int);

/*
 * Note that libld has a long history of assuming that all allocations are
 * 0-initialized.  libld_malloc must maintain this.
 */
#define	libld_free(x)		free(x)
#define	libld_malloc(x)		calloc(1, x)
#define	libld_realloc(x, s)	realloc(x, s)
#define	libld_calloc(n, s)	calloc(n, s)

extern int		isdavl_compare(const void *, const void *);

extern Sdf_desc		*sdf_add(const char *, APlist **);
extern Sdf_desc		*sdf_find(const char *, APlist *);

#if	defined(_ELF64)

#define	ld_add_actrel		ld64_add_actrel
#define	ld_add_libdir		ld64_add_libdir
#define	ld_adj_movereloc	ld64_adj_movereloc
#define	ld_am_I_partial		ld64_am_I_partial
#define	ld_ar_member		ld64_ar_member
#define	ld_ar_setup		ld64_ar_setup
#define	ld_assign_got_TLS	ld64_assign_got_TLS
#define	ld_bswap_Word		ld64_bswap_Word
#define	ld_bswap_Xword		ld64_bswap_Xword
#define	ld_cap_add_family	ld64_cap_add_family
#define	ld_cap_move_symtoobj	ld64_cap_move_symtoobj
#define	ld_comdat_validate	ld64_comdat_validate
#define	ld_disp_errmsg		ld64_disp_errmsg
#define	ld_ent_check		ld64_ent_check
#define	ld_ent_lookup		ld64_ent_lookup
#define	ld_eprintf		ld64_eprintf
#define	ld_exit			ld64_exit
#define	ld_find_library		ld64_find_library
#define	ld_finish_libs		ld64_finish_libs
#define	ld_get_group		ld64_get_group
#define	ld_group_process	ld64_group_process
#define	ld_lib_setup		ld64_lib_setup
#define	ld_init_sighandler	ld64_init_sighandler
#define	ld_lcm			ld64_lcm
#define	ld_make_bss		ld64_make_bss
#define	ld_make_data		ld64_make_data
#define	ld_make_got		ld64_make_got
#define	ld_make_parexpn_data	ld64_make_parexpn_data
#define	ld_make_sunwmove	ld64_make_sunmove
#define	ld_make_text		ld64_make_text
#define	ld_map_out		ld64_map_out
#define	ld_map_parse		ld64_map_parse
#define	ld_map_post_process	ld64_map_post_process
#define	ld_open_outfile		ld64_open_outfile
#define	ld_os_first_isdesc	ld64_os_first_isdesc
#define	ld_place_path_info_init	ld64_place_path_info_init
#define	ld_place_section	ld64_place_section
#define	ld_process_archive	ld64_process_archive
#define	ld_process_files	ld64_process_files
#define	ld_process_flags	ld64_process_flags
#define	ld_process_ifl		ld64_process_ifl
#define	ld_process_move		ld64_process_move
#define	ld_process_open		ld64_process_open
#define	ld_process_ordered	ld64_process_ordered
#define	ld_process_sym_reloc	ld64_process_sym_reloc
#define	ld_reloc_enter		ld64_reloc_enter
#define	ld_reloc_GOT_relative	ld64_reloc_GOT_relative
#define	ld_reloc_plt		ld64_reloc_plt
#define	ld_reloc_remain_entry	ld64_reloc_remain_entry
#define	ld_reloc_set_aux_osdesc	ld64_reloc_set_aux_osdesc
#define	ld_reloc_set_aux_usym	ld64_reloc_set_aux_usym
#define	ld_reloc_sym_name	ld64_reloc_sym_name
#define	ld_reloc_targval_get	ld64_reloc_targval_get
#define	ld_reloc_targval_set	ld64_reloc_targval_set
#define	ld_sec_validate		ld64_sec_validate
#define	ld_seg_lookup		ld64_seg_lookup
#define	ld_sort_ordered		ld64_sort_ordered
#define	ld_stt_section_sym_name	ld64_stt_section_sym_name
#define	ld_sunw_ldmach		ld64_sunw_ldmach
#define	ld_sup_atexit		ld64_sup_atexit
#define	ld_sup_open		ld64_sup_open
#define	ld_sup_file		ld64_sup_file
#define	ld_sup_loadso		ld64_sup_loadso
#define	ld_sup_input_done	ld64_sup_input_done
#define	ld_sup_input_section	ld64_sup_input_section
#define	ld_sup_section		ld64_sup_section
#define	ld_sup_start		ld64_sup_start
#define	ld_swap_reloc_data	ld64_swap_reloc_data
#define	ld_sym_add_u		ld64_sym_add_u
#define	ld_sym_adjust_vis	ld64_sym_adjust_vis
#define	ld_sym_avl_comp		ld64_sym_avl_comp
#define	ld_sym_copy		ld64_sym_copy
#define	ld_sym_enter		ld64_sym_enter
#define	ld_sym_find		ld64_sym_find
#define	ld_sym_nodirect		ld64_sym_nodirect
#define	ld_sym_process		ld64_sym_process
#define	ld_sym_resolve		ld64_sym_resolve
#define	ld_sym_reducable	ld64_sym_reducable
#define	ld_sym_spec		ld64_sym_spec
#define	ld_targ			ld64_targ
#define	ld_targ_init_sparc	ld64_targ_init_sparc
#define	ld_targ_init_x86	ld64_targ_init_x86
#define	ld_unwind_make_hdr	ld64_unwind_make_hdr
#define	ld_unwind_populate_hdr	ld64_unwind_populate_hdr
#define	ld_unwind_register	ld64_unwind_register
#define	ld_vers_base		ld64_vers_base
#define	ld_vers_check_defs	ld64_vers_check_defs
#define	ld_vers_check_need	ld64_vers_check_need
#define	ld_vers_def_process	ld64_vers_def_process
#define	ld_vers_desc		ld64_vers_desc
#define	ld_vers_find		ld64_vers_find
#define	ld_vers_need_process	ld64_vers_need_process
#define	ld_vers_promote		ld64_vers_promote
#define	ld_vers_sym_process	ld64_vers_sym_process
#define	ld_vers_verify		ld64_vers_verify
#define	ld_wrap_enter		ld64_wrap_enter

#else

#define	ld_add_actrel		ld32_add_actrel
#define	ld_add_libdir		ld32_add_libdir
#define	ld_adj_movereloc	ld32_adj_movereloc
#define	ld_am_I_partial		ld32_am_I_partial
#define	ld_ar_member		ld32_ar_member
#define	ld_ar_setup		ld32_ar_setup
#define	ld_assign_got_TLS	ld32_assign_got_TLS
#define	ld_bswap_Word		ld32_bswap_Word
#define	ld_bswap_Xword		ld32_bswap_Xword
#define	ld_cap_add_family	ld32_cap_add_family
#define	ld_cap_move_symtoobj	ld32_cap_move_symtoobj
#define	ld_comdat_validate	ld32_comdat_validate
#define	ld_disp_errmsg		ld32_disp_errmsg
#define	ld_ent_check		ld32_ent_check
#define	ld_ent_lookup		ld32_ent_lookup
#define	ld_eprintf		ld32_eprintf
#define	ld_exit			ld32_exit
#define	ld_find_library		ld32_find_library
#define	ld_finish_libs		ld32_finish_libs
#define	ld_get_group		ld32_get_group
#define	ld_group_process	ld32_group_process
#define	ld_lib_setup		ld32_lib_setup
#define	ld_init_sighandler	ld32_init_sighandler
#define	ld_lcm			ld32_lcm
#define	ld_make_bss		ld32_make_bss
#define	ld_make_data		ld32_make_data
#define	ld_make_got		ld32_make_got
#define	ld_make_parexpn_data	ld32_make_parexpn_data
#define	ld_make_sunwmove	ld32_make_sunmove
#define	ld_make_text		ld32_make_text
#define	ld_map_out		ld32_map_out
#define	ld_map_parse		ld32_map_parse
#define	ld_map_post_process	ld32_map_post_process
#define	ld_open_outfile		ld32_open_outfile
#define	ld_os_first_isdesc	ld32_os_first_isdesc
#define	ld_place_path_info_init	ld32_place_path_info_init
#define	ld_place_section	ld32_place_section
#define	ld_process_archive	ld32_process_archive
#define	ld_process_files	ld32_process_files
#define	ld_process_flags	ld32_process_flags
#define	ld_process_ifl		ld32_process_ifl
#define	ld_process_move		ld32_process_move
#define	ld_process_open		ld32_process_open
#define	ld_process_ordered	ld32_process_ordered
#define	ld_process_sym_reloc	ld32_process_sym_reloc
#define	ld_reloc_enter		ld32_reloc_enter
#define	ld_reloc_GOT_relative	ld32_reloc_GOT_relative
#define	ld_reloc_plt		ld32_reloc_plt
#define	ld_reloc_remain_entry	ld32_reloc_remain_entry
#define	ld_reloc_set_aux_osdesc	ld32_reloc_set_aux_osdesc
#define	ld_reloc_set_aux_usym	ld32_reloc_set_aux_usym
#define	ld_reloc_sym_name	ld32_reloc_sym_name
#define	ld_reloc_targval_get	ld32_reloc_targval_get
#define	ld_reloc_targval_set	ld32_reloc_targval_set
#define	ld_sec_validate		ld32_sec_validate
#define	ld_seg_lookup		ld32_seg_lookup
#define	ld_sort_ordered		ld32_sort_ordered
#define	ld_stt_section_sym_name	ld32_stt_section_sym_name
#define	ld_sunw_ldmach		ld32_sunw_ldmach
#define	ld_sup_atexit		ld32_sup_atexit
#define	ld_sup_open		ld32_sup_open
#define	ld_sup_file		ld32_sup_file
#define	ld_sup_loadso		ld32_sup_loadso
#define	ld_sup_input_done	ld32_sup_input_done
#define	ld_sup_input_section	ld32_sup_input_section
#define	ld_sup_section		ld32_sup_section
#define	ld_sup_start		ld32_sup_start
#define	ld_swap_reloc_data	ld32_swap_reloc_data
#define	ld_sym_add_u		ld32_sym_add_u
#define	ld_sym_adjust_vis	ld32_sym_adjust_vis
#define	ld_sym_avl_comp		ld32_sym_avl_comp
#define	ld_sym_copy		ld32_sym_copy
#define	ld_sym_enter		ld32_sym_enter
#define	ld_sym_find		ld32_sym_find
#define	ld_sym_nodirect		ld32_sym_nodirect
#define	ld_sym_process		ld32_sym_process
#define	ld_sym_resolve		ld32_sym_resolve
#define	ld_sym_reducable	ld32_sym_reducable
#define	ld_sym_spec		ld32_sym_spec
#define	ld_targ			ld32_targ
#define	ld_targ_init_sparc	ld32_targ_init_sparc
#define	ld_targ_init_x86	ld32_targ_init_x86
#define	ld_unwind_make_hdr	ld32_unwind_make_hdr
#define	ld_unwind_populate_hdr	ld32_unwind_populate_hdr
#define	ld_unwind_register	ld32_unwind_register
#define	ld_vers_base		ld32_vers_base
#define	ld_vers_check_defs	ld32_vers_check_defs
#define	ld_vers_check_need	ld32_vers_check_need
#define	ld_vers_def_process	ld32_vers_def_process
#define	ld_vers_desc		ld32_vers_desc
#define	ld_vers_find		ld32_vers_find
#define	ld_vers_need_process	ld32_vers_need_process
#define	ld_vers_promote		ld32_vers_promote
#define	ld_vers_sym_process	ld32_vers_sym_process
#define	ld_vers_verify		ld32_vers_verify
#define	ld_wrap_enter		ld32_wrap_enter

#endif

extern void		dbg_cleanup(void);
extern int		dbg_setup(Ofl_desc *, const char *, int);

extern uintptr_t	ld_add_actrel(Word, Rel_desc *, Ofl_desc *);
extern uintptr_t	ld_add_libdir(Ofl_desc *, const char *);
extern void		ld_adj_movereloc(Ofl_desc *, Rel_desc *);
extern Sym_desc *	ld_am_I_partial(Rel_desc *, Xword);
extern void		ld_ar_member(Ar_desc *, Elf_Arsym *, Ar_aux *,
			    Ar_mem *);
extern Ar_desc		*ld_ar_setup(const char *, Elf *, Ofl_desc *);
extern uintptr_t	ld_assign_got_TLS(Boolean, Rel_desc *, Ofl_desc *,
			    Sym_desc *, Gotndx *, Gotref, Word, Word,
			    Word, Word);

extern Word		ld_bswap_Word(Word);
extern Xword		ld_bswap_Xword(Xword);

extern uintptr_t	ld_cap_add_family(Ofl_desc *, Sym_desc *, Sym_desc *,
			    Cap_group *, APlist **);
extern void		ld_cap_move_symtoobj(Ofl_desc *);

extern void		ld_comdat_validate(Ofl_desc *, Ifl_desc *);

extern void		ld_disp_errmsg(const char *, Rel_desc *, Ofl_desc *);

extern void		ld_ent_check(Ofl_desc *);
extern Ent_desc		*ld_ent_lookup(Ofl_desc *, const char *name,
			    avl_index_t *where);
extern void		ld_eprintf(Ofl_desc *, Error, const char *, ...);
extern int		ld_exit(Ofl_desc *);

extern uintptr_t	ld_find_library(const char *, Ofl_desc *);
extern uintptr_t	ld_finish_libs(Ofl_desc *);

extern const char	*ld_stt_section_sym_name(Is_desc *);

extern Group_desc	*ld_get_group(Ofl_desc *, Is_desc *);
extern uintptr_t	ld_group_process(Is_desc *, Ofl_desc *);

extern uintptr_t	ld_lib_setup(Ofl_desc *);

extern void		ld_init_sighandler(Ofl_desc *);

extern Xword		ld_lcm(Xword, Xword);

extern uintptr_t	ld_make_bss(Ofl_desc *, Xword, Xword, uint_t);
extern Is_desc		*ld_make_data(Ofl_desc *, size_t);
extern uintptr_t	ld_make_got(Ofl_desc *);
extern uintptr_t	ld_make_parexpn_data(Ofl_desc *, size_t, Xword);
extern uintptr_t	ld_make_sunwmove(Ofl_desc *, int);
extern Is_desc		*ld_make_text(Ofl_desc *, size_t);
extern void		ld_map_out(Ofl_desc *);
extern Boolean		ld_map_parse(const char *, Ofl_desc *);
extern Boolean		ld_map_post_process(Ofl_desc *);

extern uintptr_t	ld_open_outfile(Ofl_desc *);

extern Is_desc		*ld_os_first_isdesc(Os_desc *);
extern Place_path_info	*ld_place_path_info_init(Ofl_desc *, Ifl_desc *,
			    Place_path_info *);
extern Os_desc		*ld_place_section(Ofl_desc *, Is_desc *,
			    Place_path_info *path_info,  int, const char *);
extern Boolean		ld_process_archive(const char *, int, Ar_desc *,
			    Ofl_desc *);
extern uintptr_t	ld_process_files(Ofl_desc *, int, char **);
extern uintptr_t	ld_process_flags(Ofl_desc *, int, char **);
extern uintptr_t	ld_process_ifl(const char *, const char *, int, Elf *,
			    Word, Ofl_desc *, Rej_desc *, Ifl_desc **);
extern uintptr_t	ld_process_move(Ofl_desc *);
extern uintptr_t	ld_process_open(const char *, const char *, int *,
			    Ofl_desc *, Word, Rej_desc *, Ifl_desc **);
extern uintptr_t	ld_process_ordered(Ofl_desc *, Ifl_desc *,
			    Place_path_info *path_info,  Word);
extern uintptr_t	ld_process_sym_reloc(Ofl_desc *, Rel_desc *, Rel *,
			    Is_desc *, const char *, Word);

extern Rel_desc		*ld_reloc_enter(Ofl_desc *, Rel_cache *, Rel_desc *,
			    Word);
extern uintptr_t	ld_reloc_GOT_relative(Boolean, Rel_desc *, Ofl_desc *);
extern uintptr_t	ld_reloc_plt(Rel_desc *, Ofl_desc *);
extern void		ld_reloc_remain_entry(Rel_desc *, Os_desc *,
			    Ofl_desc *, Boolean *);
extern Boolean		ld_reloc_set_aux_osdesc(Ofl_desc *, Rel_desc *,
			    Os_desc *);
extern Boolean		ld_reloc_set_aux_usym(Ofl_desc *, Rel_desc *,
			    Sym_desc *);

extern const char	*ld_reloc_sym_name(Rel_desc *);
extern int		ld_reloc_targval_get(Ofl_desc *, Rel_desc *,
			    uchar_t *, Xword *);
extern int		ld_reloc_targval_set(Ofl_desc *, Rel_desc *,
			    uchar_t *, Xword);

extern Sg_desc		*ld_seg_lookup(Ofl_desc *, const char *,
			    avl_index_t *where);
extern void		ld_sec_validate(Ofl_desc *);
extern uintptr_t	ld_sort_ordered(Ofl_desc *);
extern Half		ld_sunw_ldmach();
extern void		ld_sup_atexit(Ofl_desc *, int);
extern void		ld_sup_open(Ofl_desc *, const char **, const char **,
			    int *, int, Elf **, Elf *ref, size_t,
			    const Elf_Kind);
extern void		ld_sup_file(Ofl_desc *, const char *, const Elf_Kind,
			    int flags, Elf *);
extern uintptr_t	ld_sup_loadso(Ofl_desc *, const char *);
extern void		ld_sup_input_done(Ofl_desc *);
extern void		ld_sup_section(Ofl_desc *, const char *, Shdr *, Word,
			    Elf_Data *, Elf *);
extern uintptr_t	ld_sup_input_section(Ofl_desc*, Ifl_desc *,
			    const char *, Shdr **, Word, Elf_Scn *, Elf *);
extern void		ld_sup_start(Ofl_desc *, const Half, const char *);
extern int		ld_swap_reloc_data(Ofl_desc *, Rel_desc *);
extern Sym_desc		*ld_sym_add_u(const char *, Ofl_desc *, Msg);
extern void		ld_sym_adjust_vis(Sym_desc *, Ofl_desc *);
extern int		ld_sym_avl_comp(const void *, const void *);
extern uintptr_t	ld_sym_copy(Sym_desc *);
extern Sym_desc		*ld_sym_enter(const char *, Sym *, Word, Ifl_desc *,
			    Ofl_desc *, Word, Word, sd_flag_t, avl_index_t *);
extern Sym_desc		*ld_sym_find(const char *, Word, avl_index_t *,
			    Ofl_desc *);
extern uintptr_t	ld_sym_nodirect(Is_desc *, Ifl_desc *, Ofl_desc *);
extern uintptr_t	ld_sym_process(Is_desc *, Ifl_desc *, Ofl_desc *);
extern uintptr_t	ld_sym_resolve(Sym_desc *, Sym *, Ifl_desc *,
			    Ofl_desc *, int, Word, sd_flag_t);
extern Boolean		ld_sym_reducable(Ofl_desc *, Sym_desc *);
extern uintptr_t	ld_sym_spec(Ofl_desc *);

extern Target		ld_targ;
extern const Target	*ld_targ_init_sparc(void);
extern const Target	*ld_targ_init_x86(void);

extern uintptr_t	ld_unwind_make_hdr(Ofl_desc *);
extern uintptr_t	ld_unwind_populate_hdr(Ofl_desc *);
extern uintptr_t	ld_unwind_register(Os_desc *, Ofl_desc *);

extern Ver_desc		*ld_vers_base(Ofl_desc *);
extern uintptr_t	ld_vers_check_defs(Ofl_desc *);
extern uintptr_t	ld_vers_check_need(Ofl_desc *);
extern uintptr_t	ld_vers_def_process(Is_desc *, Ifl_desc *, Ofl_desc *);
extern Ver_desc		*ld_vers_desc(const char *, Word, APlist **);
extern Ver_desc		*ld_vers_find(const char *, Word, APlist *);
extern uintptr_t	ld_vers_need_process(Is_desc *, Ifl_desc *, Ofl_desc *);
extern void		ld_vers_promote(Sym_desc *, Word, Ifl_desc *,
			    Ofl_desc *);
extern int		ld_vers_sym_process(Ofl_desc *, Is_desc *, Ifl_desc *);
extern int		ld_vers_verify(Ofl_desc *);
extern WrapSymNode	*ld_wrap_enter(Ofl_desc *, const char *);

extern uintptr_t	add_regsym(Sym_desc *, Ofl_desc *);
extern Word		hashbkts(Word);
extern Xword		lcm(Xword, Xword);

/*
 * Most platforms have both a 32 and 64-bit variant (e.g. EM_SPARC and
 * EM_SPARCV9). To support this, there many files in libld that are built
 * twice, once for ELFCLASS64 (_ELF64), and once for ELFCLASS32. In these
 * files, we sometimes want to supply one value for the ELFCLASS32 case
 * and another for ELFCLASS64. The LD_TARG_BYCLASS macro is used to do
 * this. It is called with both both alternatives, and yields the one
 * that applies to the current compilation environment.
 */
#ifdef	_ELF64
#define	LD_TARG_BYCLASS(_ec32, _ec64) (_ec64)
#else
#define	LD_TARG_BYCLASS(_ec32, _ec64) (_ec32)
#endif


#ifdef	__cplusplus
}
#endif

#endif /* _LIBLD_DOT_H */