1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#if defined(__MWERKS__) && !defined(__private_extern__)
24#define __private_extern__ __declspec(private_extern)
25#endif
26
27/*
28 * Global types, variables and routines declared in the file sections.c.
29 *
30 * The following include file need to be included before this file:
31 * #include <sys/loader.h>
32 * #include "ld.h"
33 * #include "objects.h"
34 */
35
36/*
37 * The fields of the segment command in a merged segment are set and
38 * maintained as follows:
39 *	cmd		set in layout_segments() (layout)
40 *	cmdsize		set in layout_segments() (layout)
41 *	segname		set when the merged segment is created (pass1)
42 *	vmaddr		set in process_segments() or layout_segments() (layout)
43 *	vmsize		set in layout_segments() (layout)
44 *	fileoff		set in layout_segments() (layout)
45 *	filesize	set in layout_segments() (layout)
46 *	maxprot		set in process_segments() or layout_segments() (layout)
47 *	initprot	set in process_segments() or layout_segments() (layout)
48 *	nsects		incremented as each section is merged (pass1)
49 *	flags		set to 0 in process_segments and SG_NORELOC
50 *			 conditionally or'ed in in pass2() (pass2)
51 */
52struct merged_segment {
53    struct segment_command sg;	/* The output file's segment structure. */
54    struct merged_section	/* The list of section that contain contents */
55	*content_sections;	/*  that is non-zerofill sections. */
56    struct merged_section	/* The list of zerofill sections. */
57	*zerofill_sections;
58    char *filename;		/* File this segment is in, the output file */
59				/*  or a fixed VM shared library */
60    enum bool addr_set;		/* TRUE when address of this segment is set */
61    enum bool prot_set;		/* TRUE when protection of this segment is set*/
62    enum bool split_dylib;	/* TRUE when this segment is from a dylib */
63				/*  which is MH_SPLIT_SEGS */
64    enum bool debug_only;	/* TRUE if segment contains sections with the */
65				/*  S_ATTR_DEBUG attribute */
66#ifdef RLD
67    long set_num;		/* Object set this segment first appears in. */
68#endif /* RLD */
69    struct merged_segment *next;/* The next segment in the list. */
70};
71
72/*
73 * The fields of the section structure in a merged section are set and
74 * maintained as follows:
75 *	sectname	set when the merged segment is created (pass1)
76 *	segname		set when the merged segment is created (pass1)
77 *	addr		set in layout_segments (layout)
78 *	size		accumulated to the total size (pass1)
79 *	offset		set in layout_segments (layout)
80 *	align		merged to the maximum alignment (pass1)
81 *	reloff		set in layout_segments (layout)
82 *	nreloc		accumulated to the total count (pass1)
83 *	flags		set when the merged segment is created (pass1)
84 *	reserved1	zeroed when created in merged_section (pass1)
85 *	reserved2	zeroed when created in merged_section (pass1)
86 */
87struct merged_section {
88    struct section s;		/* The output file's section structure. */
89    unsigned long output_sectnum;/* Section number in the output file. */
90    unsigned long output_nrelocs;/* The current number of relocation entries */
91				/*  written to the output file in pass2 for */
92				/*  this section */
93    /* These two fields are used to help set the SG_NORELOC flag */
94    enum bool relocated;	/* This section was relocated */
95    enum bool referenced;	/* This section was referenced by a relocation*/
96				/*  entry (local or through a symbol). */
97    /* The literal_* fields are used only if this section is a literal section*/
98    void (*literal_merge)();	/* The routine to merge the literals. */
99    void (*literal_output)();	/* The routine to write the literals. */
100    void (*literal_free)();	/* The routine to free the literals. */
101    void (*literal_order)();	/* The routine to order the literals. */
102    void (*literal_reset_live)(); /* The routine to reset literal data before
103				     only the live literals are re-merged */
104    void *literal_data;		/* A pointer to a block of data to help merge */
105				/*  and hold the literals. */
106    /* These three fields are used only if this section is created from a file*/
107    char *contents_filename;	/* File name for the contents of the section */
108				/*  if it is created from a file, else NULL */
109    char *file_addr;		/* address the above file is mapped at */
110    unsigned long file_size;	/* size of above file as returned by stat(2) */
111
112    /* These three fields are used only if this section has a -sectorder file */
113    char *order_filename;	/* File name that contains the order that */
114				/*  symbols are to loaded in this section */
115    char *order_addr;		/* address the above file is mapped at */
116    unsigned long order_size;	/* size of above file as returned by stat(2) */
117    struct order_load_map	/* the load map for printing with -M */
118	*order_load_maps;
119    unsigned long
120	norder_load_maps;	/* size of the above map */
121#ifdef RLD
122    long set_num;		/* Object set this section first appears in. */
123#endif /* RLD */
124    /* These four are used for output_for_dyld only if this is a non-regular
125       section that will have relocation entries */
126    unsigned long iextrel;	/* index into output external reloc entries */
127    unsigned long nextrel;	/* number of output external reloc entries */
128    unsigned long ilocrel;	/* index into output local reloc entries */
129    unsigned long nlocrel;	/* number of output local reloc entries */
130    struct merged_section *next;/* The next section in the list. */
131};
132
133/*
134 * This is the load map (-M) for sections that have had their sections orders
135 * with -sectorder option.
136 */
137struct order_load_map {
138    char *archive_name;		/* archive name */
139    char *object_name;		/* object name */
140    char *symbol_name;		/* symbol name */
141    unsigned long value;	/* symbol's value */
142    struct section_map
143	*section_map;		/* section map to relocate symbol's value */
144    unsigned long size;		/* size of symbol in the input file */
145    unsigned long order;	/* order the symbol appears in the section */
146    struct load_order *load_order; /* the load_order for this map entry */
147};
148
149/* the pointer to the head of the output file's section list */
150__private_extern__ struct merged_segment *merged_segments;
151#ifdef RLD
152__private_extern__ struct merged_segment *original_merged_segments;
153#endif /* RLD */
154
155/* the total number relocation entries */
156__private_extern__ unsigned long nreloc;
157
158/*
159 * This is set to TRUE if any of the input objects do not have the
160 * MH_SUBSECTIONS_VIA_SYMBOLS bit set in the mach_header flags field.
161 */
162__private_extern__ enum bool some_non_subsection_via_symbols_objects;
163
164__private_extern__ void merge_sections(
165    void);
166__private_extern__ void remove_debug_segments(
167    void);
168__private_extern__ void merge_literal_sections(
169    enum bool redo_live);
170__private_extern__ void layout_ordered_sections(
171    void);
172__private_extern__ enum bool is_literal_output_offset_live(
173    struct merged_section *ms,
174    unsigned long output_offset);
175__private_extern__ void parse_order_line(
176    char *line,
177    char **archive_name,
178    char **object_name,
179    char **symbol_name,
180    struct merged_section *ms,
181    unsigned long line_number);
182__private_extern__ void resize_live_sections(
183    void);
184__private_extern__ void relayout_relocs(
185    void);
186__private_extern__ void output_literal_sections(
187    void);
188__private_extern__ void output_sections_from_files(
189    void);
190__private_extern__ void output_section(
191    struct section_map *map);
192__private_extern__ unsigned long pass2_nsect_merged_symbol_section_type(
193    struct merged_symbol *merged_symbol);
194__private_extern__ void nop_pure_instruction_scattered_sections(
195    void);
196__private_extern__ void flush_scatter_copied_sections(
197    void);
198__private_extern__ void live_marking(
199    void);
200__private_extern__ struct fine_reloc *get_fine_reloc_for_merged_symbol(
201    struct merged_symbol *merged_symbol,
202    struct section_map **local_map);
203__private_extern__ unsigned long r_symbolnum_from_r_value(
204    unsigned long r_value,
205    struct object_file *obj);
206__private_extern__ struct merged_section *create_merged_section(
207    struct section *s);
208__private_extern__ struct merged_segment *lookup_merged_segment(
209    char *segname);
210__private_extern__ struct merged_section *lookup_merged_section(
211    char *segname,
212    char *sectname);
213__private_extern__ enum bool is_merged_symbol_coalesced(
214    struct merged_symbol *merged_symbol);
215__private_extern__ int qsort_load_order_values(
216    const struct load_order *load_order1,
217    const struct load_order *load_order2);
218__private_extern__ unsigned long align_to_input_mod(
219    unsigned long output_offset,
220    unsigned long input_offset,
221    unsigned long align);
222#ifdef RLD
223__private_extern__ void reset_merged_sections(
224    void);
225__private_extern__ void zero_merged_sections_sizes(
226    void);
227__private_extern__ void remove_merged_sections(
228    void);
229#endif /* RLD */
230
231#ifdef DEBUG
232__private_extern__ void print_merged_sections(
233    char *string);
234__private_extern__ void print_merged_section_stats(
235    void);
236__private_extern__ void print_name_arrays(
237    void);
238__private_extern__ void print_load_order(
239    struct load_order *load_order,
240    unsigned long nload_order,
241    struct merged_section *ms,
242    struct object_file *object_file,
243    char *string);
244#endif /* DEBUG */
245