1/*
2 * Copyright (c) 1999 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#ifdef SHLIB
24#include "shlib.h"
25#endif /* SHLIB */
26/*
27 * This file contains the routines to do relocation for SPARC processor architecture.
28 */
29#include <stdlib.h>
30#if !(defined(KLD) && defined(__STATIC__))
31#include <stdio.h>
32#include <mach/mach.h>
33#else /* defined(KLD) && defined(__STATIC__) */
34#include <mach/kern_return.h>
35#endif /* !(defined(KLD) && defined(__STATIC__)) */
36#include <string.h>
37#include <stdarg.h>
38#include <mach-o/loader.h>
39#include <mach-o/reloc.h>
40#include <mach-o/sparc/reloc.h>
41#include <mach-o/nlist.h>
42#include "stuff/bool.h"
43#include "stuff/bytesex.h"
44
45#include "ld.h"
46#include "live_refs.h"
47#include "objects.h"
48#include "sections.h"
49#include "pass1.h"
50#include "symbols.h"
51#include "pass2.h"
52#include "generic_reloc.h"
53#include "sparc_reloc.h"
54#include "indirect_sections.h"
55#include "dylibs.h"
56
57#define U_ABS(l) (((long)(l))<0 ? (unsigned long)(-(l)) : (l))
58
59#undef DEBUG1
60
61/*
62 * sparc_reloc() relocates the contents of the specified section for the
63 * relocation entries using the section map from the current object (cur_obj).
64 */
65__private_extern__
66void
67sparc_reloc(
68char *contents,
69struct relocation_info *relocs,
70struct section_map *section_map)
71{
72    unsigned long i, j, symbolnum, value, input_pc, output_pc;
73    unsigned long instruction, immediate;
74    struct nlist *nlists;
75    char *strings;
76    enum bool force_extern_reloc;
77    struct undefined_map *undefined_map;
78    struct merged_symbol *merged_symbol;
79    struct section_map *local_map, *pair_local_map;
80    struct relocation_info *reloc, *pair_reloc;
81    struct scattered_relocation_info *sreloc, *spair_reloc;
82    unsigned long r_address, r_symbolnum, r_pcrel, r_length, r_extern,
83		  r_scattered, r_value, pair_r_symbolnum, pair_r_value;
84    enum reloc_type_sparc r_type, pair_r_type;
85    unsigned long other_half;
86    unsigned long offset;
87
88#if defined(DEBUG) || defined(RLD)
89	/*
90	 * The compiler "warnings: ... may be used uninitialized in this
91	 * function" can safely be ignored
92	 */
93	merged_symbol = NULL;
94	local_map = NULL;
95	instruction = 0;
96	other_half = 0;
97	immediate = 0;
98	offset = 0;
99	pair_r_symbolnum = 0;
100	pair_r_value = 0;
101	pair_local_map = NULL;
102#endif /* defined(DEBUG) || defined(RLD) */
103
104	for(i = 0; i < section_map->s->nreloc; i++){
105	    force_extern_reloc = FALSE;
106	    /*
107	     * Break out the fields of the relocation entry and set pointer to
108	     * the type of relocation entry it is (for updating later).
109	     */
110	    if((relocs[i].r_address & R_SCATTERED) != 0){
111		sreloc = (struct scattered_relocation_info *)(relocs + i);
112		reloc = NULL;
113		r_scattered = 1;
114		r_address = sreloc->r_address;
115		r_pcrel = sreloc->r_pcrel;
116		r_length = sreloc->r_length;
117		r_value = sreloc->r_value;
118		r_type = (enum reloc_type_sparc)sreloc->r_type;
119		r_extern = 0;
120		/*
121		 * Since the r_value field is reserved in a SPARC_RELOC_PAIR
122		 * type to report the correct error a check for a stray
123		 * SPARC_RELOC_PAIR relocation types needs to be done before
124		 * it is assumed that r_value is legal.  A SPARC_RELOC_PAIR
125		 * follows SPARC_RELOC_{HI22,LO10,SECTDIFF, HI22_SECTDIFF,LO10_SECTDIFF}
126		 * relocation types and it is an error to see one otherwise.
127		 */
128		if(r_type == SPARC_RELOC_PAIR){
129		    error_with_cur_obj("stray relocation SPARC_RELOC_PAIR entry "
130			"(%lu) in section (%.16s,%.16s)", i,
131			section_map->s->segname, section_map->s->sectname);
132		    continue;
133		}
134		/* calculate the r_symbolnum (n_sect) from the r_value */
135		r_symbolnum = 0;
136		for(j = 0; j < cur_obj->nsection_maps; j++){
137		    if(r_value >= cur_obj->section_maps[j].s->addr &&
138		       r_value < cur_obj->section_maps[j].s->addr +
139				 cur_obj->section_maps[j].s->size){
140			r_symbolnum = j + 1;
141			break;
142		    }
143		}
144		if(r_symbolnum == 0){
145		    /*
146		     * The edge case where the last address past then end of
147		     * of the last section is referenced.
148		     */
149		    for(j = 0; j < cur_obj->nsection_maps; j++){
150			if(r_value == cur_obj->section_maps[j].s->addr +
151				      cur_obj->section_maps[j].s->size){
152			    r_symbolnum = j + 1;
153			    break;
154			}
155		    }
156		    if(r_symbolnum == 0){
157			error_with_cur_obj("r_value (0x%x) field of relocation "
158			    "entry %lu in section (%.16s,%.16s) out of range",
159			    (unsigned int)r_value, i, section_map->s->segname,
160			    section_map->s->sectname);
161			return;
162		    }
163		}
164	    }
165	    else{
166		reloc = relocs + i;
167		sreloc = NULL;
168		r_scattered = 0;
169		r_address = reloc->r_address;
170		r_pcrel = reloc->r_pcrel;
171		r_length = reloc->r_length;
172		r_extern = reloc->r_extern;
173		r_symbolnum = reloc->r_symbolnum;
174		r_type = (enum reloc_type_sparc)reloc->r_type;
175		r_value = 0;
176	    }
177	    /*
178	     * SPARC_RELOC_PAIR relocation types only follows SPARC_RELOC_
179	     * {HI22,LO10,SECTDIFFi,HI22_SECTDIFF,LO10_SECTDIFF}
180	     * relocation types and it is an error to
181	     * see one otherwise.
182	     */
183	    if(r_type == SPARC_RELOC_PAIR){
184		error_with_cur_obj("stray relocation SPARC_RELOC_PAIR entry "
185		    "(%lu) in section (%.16s,%.16s)", i,
186		    section_map->s->segname, section_map->s->sectname);
187		continue;
188	    }
189	    /*
190	     * The r_address field is really an offset into the contents of the
191	     * section and must reference something inside the section (Note
192	     * that this is not the case for SPARC_RELOC_PAIR entries but this
193	     * can't be one with the above checks).
194	     */
195	    if(r_address >= section_map->s->size){
196		error_with_cur_obj("r_address (0x%x) field of relocation entry "
197		    "%lu in section (%.16s,%.16s) out of range",
198		    (unsigned int)r_address, i, section_map->s->segname,
199		    section_map->s->sectname);
200		return;
201	    }
202	    /*
203	     * If this relocation type is to have a pair make sure it is there
204	     * and then break out it's fields.
205	     */
206	    pair_r_type = (enum reloc_type_sparc)0;
207	    pair_reloc = NULL;
208	    spair_reloc = NULL;
209	    if(r_type == SPARC_RELOC_HI22 || r_type == SPARC_RELOC_LO10) {
210		if(i + 1 < section_map->s->nreloc){
211		    pair_reloc = relocs + i + 1;
212		    if((pair_reloc->r_address & R_SCATTERED) != 0){
213			spair_reloc = (struct scattered_relocation_info *)
214				      pair_reloc;
215			pair_reloc  = NULL;
216			pair_r_type = (enum reloc_type_sparc)
217				      spair_reloc->r_type;
218			other_half  = spair_reloc->r_address;
219		    }
220		    else{
221			pair_r_type = (enum reloc_type_sparc)
222				      pair_reloc->r_type;
223			other_half  = pair_reloc->r_address;
224		    }
225		}
226		if((pair_reloc == NULL && spair_reloc == NULL) ||
227		   pair_r_type != SPARC_RELOC_PAIR){
228		    error_with_cur_obj("relocation entry (%lu) in section "
229			"(%.16s,%.16s) missing following associated "
230			"SPARC_RELOC_PAIR entry", i, section_map->s->segname,
231			section_map->s->sectname);
232		    continue;
233		}
234	    }
235	    else if(r_type == SPARC_RELOC_SECTDIFF ||
236		    r_type == SPARC_RELOC_HI22_SECTDIFF ||
237		    r_type == SPARC_RELOC_LO10_SECTDIFF){
238		if(r_scattered != 1){
239		    error_with_cur_obj("relocation entry (%lu) in section "
240			"(%.16s,%.16s) r_type is SPARC_RELOC_SECTDIFF but "
241			"relocation entry not scattered type", i,
242			section_map->s->segname, section_map->s->sectname);
243		    continue;
244		}
245		if(i + 1 < section_map->s->nreloc){
246		    pair_reloc = relocs + i + 1;
247		    if((pair_reloc->r_address & R_SCATTERED) != 0){
248			spair_reloc = (struct scattered_relocation_info *)
249				      pair_reloc;
250			pair_reloc = NULL;
251			pair_r_type = (enum reloc_type_sparc)
252				      spair_reloc->r_type;
253			pair_r_value = spair_reloc->r_value;
254			other_half  = spair_reloc->r_address;
255		    }
256		    else{
257			error_with_cur_obj("relocation entry (%lu) in section "
258			    "(%.16s,%.16s) following associated relocation "
259			    "entry not scattered type", i,
260			    section_map->s->segname, section_map->s->sectname);
261			continue;
262		    }
263		}
264		if((pair_reloc == NULL && spair_reloc == NULL) ||
265		   pair_r_type != SPARC_RELOC_PAIR){
266		    error_with_cur_obj("relocation entry (%lu) in section "
267			"(%.16s,%.16s) missing following associated "
268			"SPARC_RELOC_PAIR entry", i, section_map->s->segname,
269			section_map->s->sectname);
270		    continue;
271		}
272		/*
273		 * Calculate the pair_r_symbolnum (n_sect) from the
274		 * pair_r_value.
275		 */
276		pair_r_symbolnum = 0;
277		for(j = 0; j < cur_obj->nsection_maps; j++){
278		    if(pair_r_value >= cur_obj->section_maps[j].s->addr &&
279		       pair_r_value < cur_obj->section_maps[j].s->addr +
280				 cur_obj->section_maps[j].s->size){
281			pair_r_symbolnum = j + 1;
282			break;
283		    }
284		}
285		if(pair_r_symbolnum == 0){
286		    error_with_cur_obj("r_value (0x%x) field of relocation "
287			"entry %lu in section (%.16s,%.16s) out of range",
288			(unsigned int)r_value, i + 1, section_map->s->segname,
289			section_map->s->sectname);
290		    return;
291		}
292	    }
293	    /*
294	     * If r_extern is set this relocation entry is an external entry
295	     * else it is a local entry (or scattered entry).
296	     */
297	    input_pc = section_map->s->addr + r_address;
298
299	    if(r_extern){
300		/*
301		 * This is an external relocation entry.  So the value to be
302		 * added to the item to be relocated is the value of the symbol.
303		 * r_symbolnum is an index into the input file's symbol table
304		 * of the symbol being refered to.  The symbol must be an
305		 * undefined or coalesced symbol to be used in an external
306		 * relocation entry.
307		 */
308		if(r_symbolnum >= cur_obj->symtab->nsyms){
309		    error_with_cur_obj("r_symbolnum (%lu) field of external "
310			"relocation entry %lu in section (%.16s,%.16s) out of "
311			"range", r_symbolnum, i, section_map->s->segname,
312			section_map->s->sectname);
313		    return;
314		}
315		symbolnum = r_symbolnum;
316		undefined_map = bsearch(&symbolnum, cur_obj->undefined_maps,
317		    cur_obj->nundefineds, sizeof(struct undefined_map),
318		    (int (*)(const void *, const void *))undef_bsearch);
319		if(undefined_map != NULL){
320		    merged_symbol = undefined_map->merged_symbol;
321		}
322		else{
323		    nlists = (struct nlist *)(cur_obj->obj_addr +
324					      cur_obj->symtab->symoff);
325		    strings = (char *)(cur_obj->obj_addr +
326				       cur_obj->symtab->stroff);
327		    if((nlists[symbolnum].n_type & N_EXT) != N_EXT){
328			error_with_cur_obj("r_symbolnum (%lu) field of external"
329			    " relocation entry %lu in section (%.16s,%.16s) "
330			    "refers to a non-external symbol", symbolnum, i,
331			    section_map->s->segname, section_map->s->sectname);
332			return;
333		    }
334		    /*
335		     * We must allow and create references to defined global
336		     * coalesced symbols with external relocation entries so
337		     * that the dynamic linker can relocate all references to
338		     * the same symbol.
339		     */
340		    if((nlists[symbolnum].n_type & N_TYPE) == N_SECT &&
341		       (cur_obj->section_maps[nlists[symbolnum].n_sect-1].
342			s->flags & SECTION_TYPE) == S_COALESCED){
343			merged_symbol = lookup_symbol(strings +
344					     nlists[symbolnum].n_un.n_strx);
345			if(merged_symbol->name_len == 0){
346			    fatal("internal error, in sparc_reloc() failed to "
347			          "lookup coalesced symbol %s", strings +
348				  nlists[symbolnum].n_un.n_strx);
349			}
350		    }
351		    else{
352			if((nlists[symbolnum].n_type & N_EXT) != N_EXT ||
353			   (nlists[symbolnum].n_type & N_TYPE) != N_UNDF){
354			    error_with_cur_obj("r_symbolnum (%lu) field of "
355				"external relocation entry %lu in section "
356				"(%.16s,%.16s) refers to a non-undefined "
357				"symbol", symbolnum, i, section_map->s->segname,
358				 section_map->s->sectname);
359			    return;
360			}
361			print_obj_name(cur_obj);
362			fatal("internal error, in sparc_reloc() symbol index "
363			    "%lu in above file not in undefined map",symbolnum);
364		    }
365		}
366		if((merged_symbol->nlist.n_type & N_TYPE) == N_SECT &&
367		   (get_output_section(merged_symbol->nlist.n_sect)->
368		    flags & SECTION_TYPE) == S_COALESCED){
369		    if(((merged_symbol->nlist.n_type & N_PEXT) == N_PEXT &&
370			keep_private_externs == FALSE) ||
371		       dynamic == FALSE ||
372		       (output_for_dyld && has_dynamic_linker_command))
373			force_extern_reloc = FALSE;
374		    else
375			force_extern_reloc = TRUE;
376		}
377		/*
378		 * If this is an indirect symbol resolve indirection (all chains
379		 * of indirect symbols have been resolved so that they point at
380		 * a symbol that is not an indirect symbol).
381		 */
382		if(merged_symbol->nlist.n_type == (N_EXT | N_INDR))
383		    merged_symbol = (struct merged_symbol *)
384				    merged_symbol->nlist.n_value;
385		/*
386		 * If the symbol is undefined (or common) or a global coalesced
387		 * symbol where we need to force an external relocation entry
388		 * and we are not prebinding no relocation is done.  Or if the
389		 * output file is a multi module MH_DYLIB no relocation is done
390		 * unless the symbol is a private extern or we are prebinding.
391		 */
392		if(((merged_symbol->nlist.n_type & N_TYPE) == N_UNDF) ||
393		   (force_extern_reloc == TRUE && prebinding == FALSE) ||
394		   ((filetype == MH_DYLIB && multi_module_dylib == TRUE) &&
395		    (((merged_symbol->nlist.n_type & N_PEXT) != N_PEXT) &&
396		     prebinding == FALSE) ) )
397		    value = 0;
398		else{
399		    value = merged_symbol->nlist.n_value;
400		    /*
401		     * To know which type (local or scattered) of relocation
402		     * entry to convert this one to (if relocation entries are
403		     * saved) the offset to be added to the symbol's value is
404		     * needed to see if it reaches outside the block in which
405		     * the symbol is in.  In here if the offset is not zero then
406		     * it is assumed to reach out of the block and a scattered
407		     * relocation entry is used.
408		     */
409		    if(r_type == SPARC_RELOC_VANILLA){
410			switch(r_length){
411			case 0: /* byte */
412			    offset = get_byte((char *)(contents + r_address));
413			    break;
414			case 1: /* word (2 byte) */
415			    offset = get_short((short *)(contents + r_address));
416			    break;
417			case 2: /* long (4 byte) */
418			    offset = get_long((long *)(contents + r_address));
419			    break;
420			default:
421			    /* the error check is catched below */
422			    break;
423			}
424			if(r_pcrel)
425			    offset += input_pc;
426		    }
427		    else{
428			instruction = get_long((long *)(contents + r_address));
429			switch(r_type){
430			case SPARC_RELOC_HI22:
431			    offset = ((instruction & 0x3fffff) << 10) |
432			      (other_half & 0x3ff);
433			    break;
434			case SPARC_RELOC_LO10:
435			    offset = (instruction & 0x3ff) |
436			      ((other_half & 0x3fffff) << 10);
437			    break;
438			case SPARC_RELOC_WDISP22:
439			    offset = (instruction & 0x3fffff);
440			    /* sign extend offset */
441			    if ((offset & 0x200000) != 0)
442			      offset |= 0xffc00000;
443			    offset <<= 2; /* offset is long boundary */
444			    offset += input_pc;
445			    break;
446			case SPARC_RELOC_WDISP30:
447			    offset = (instruction & 0x3fffffff);
448			    offset <<= 2; /* offset is on a long boundary */
449			    offset += input_pc;
450			    break;
451			default:
452			    /* the error check is caught below */
453			    break;
454			}
455		    }
456		}
457
458		if(merged_symbol->nlist.n_type == (N_EXT | N_SECT))
459		    output_sections[merged_symbol->nlist.n_sect]->referenced =
460									   TRUE;
461	    }
462	    else{
463		/*
464		 * This is a local relocation entry (the value to which the item
465		 * to be relocated is refering to is defined in section number
466		 * r_symbolnum).  So the address of that section in the input
467		 * file is subtracted and the value of that section in the
468		 * output is added to the item being relocated.
469		 */
470		value = 0;
471		/*
472		 * If the symbol is not in any section the value to be added to
473		 * the item to be relocated is the zero above and any pc
474		 * relative change in value added below.
475		 */
476		if(r_symbolnum != R_ABS){
477		    if(r_symbolnum > cur_obj->nsection_maps){
478			error_with_cur_obj("r_symbolnum (%lu) field of local "
479			    "relocation entry %lu in section (%.16s,%.16s) "
480			    "out of range", r_symbolnum, i,
481			    section_map->s->segname, section_map->s->sectname);
482			return;
483		    }
484		    local_map = &(cur_obj->section_maps[r_symbolnum - 1]);
485		    local_map->output_section->referenced = TRUE;
486		    if(local_map->s->flags & S_ATTR_DEBUG){
487			error_with_cur_obj("illegal reference to debug section,"
488			    " from non-debug section (%.16s,%.16s) via "
489			    "relocation entry (%lu) to section (%.16s,%.16s)",
490			    section_map->s->segname, section_map->s->sectname,
491			    i, local_map->s->segname, local_map->s->sectname);
492			return;
493		    }
494		    pair_local_map = NULL;
495
496		    if(r_type == SPARC_RELOC_SECTDIFF ||
497		       r_type == SPARC_RELOC_HI22_SECTDIFF ||
498		       r_type == SPARC_RELOC_LO10_SECTDIFF){
499			pair_local_map =
500			    &(cur_obj->section_maps[pair_r_symbolnum - 1]);
501			pair_local_map->output_section->referenced = TRUE;
502			if(pair_local_map->s->flags & S_ATTR_DEBUG){
503			    error_with_cur_obj("illegal reference to debug "
504				"section, from non-debug section (%.16s,%.16s) "
505				"via relocation entry (%lu) to section (%.16s,"
506				"%.16s)", section_map->s->segname,
507				section_map->s->sectname, i,
508				pair_local_map->s->segname,
509				pair_local_map->s->sectname);
510			    return;
511			}
512		    }
513		    if(local_map->nfine_relocs == 0 &&
514		       (pair_local_map == NULL ||
515			pair_local_map->nfine_relocs == 0) ){
516			if(r_type == SPARC_RELOC_SECTDIFF ||
517			   r_type == SPARC_RELOC_HI22_SECTDIFF ||
518			   r_type == SPARC_RELOC_LO10_SECTDIFF){
519			    value = - local_map->s->addr
520				    + (local_map->output_section->s.addr +
521				       local_map->offset)
522				    + pair_local_map->s->addr
523				    - (pair_local_map->output_section->s.addr +
524				       pair_local_map->offset);
525			}
526			else{
527			    value = - local_map->s->addr
528				    + (local_map->output_section->s.addr +
529				       local_map->offset);
530			}
531		    }
532		    else{
533			/*
534			 * For items to be relocated that refer to a section
535			 * with fine relocation the value is set (not adjusted
536			 * with addition).  So the new value is directly
537			 * calculated from the old value.
538			 */
539			if(r_pcrel) {
540			    if(section_map->nfine_relocs == 0)
541				output_pc = section_map->output_section->s.addr
542					    + section_map->offset +
543					    r_address;
544			    else
545			      output_pc = section_map->output_section->s.addr +
546				fine_reloc_output_offset(section_map, r_address);
547			}
548			else{
549			    input_pc = 0;
550			    output_pc = 0;
551			}
552			/*
553			 * Get the value of the expresion of the item to be
554			 * relocated.
555			 */
556			if(r_type == SPARC_RELOC_VANILLA ||
557			   r_type == SPARC_RELOC_SECTDIFF){
558			    switch(r_length){
559			    case 0: /* byte */
560				value = get_byte((char *)(contents +
561							  r_address));
562				break;
563			    case 1: /* word (2 byte) */
564				value = get_short((short *)(contents +
565							    r_address));
566				break;
567			    case 2: /* long (4 byte) */
568				value = get_long((long *)(contents +
569							  r_address));
570				break;
571			    default:
572				/* the error check is catched below */
573				break;
574			    }
575			}
576			else{
577			    instruction = get_long((long *)(contents +
578							    r_address));
579			    switch(r_type){
580			    case SPARC_RELOC_HI22:
581			    case SPARC_RELOC_HI22_SECTDIFF:
582				value = ((instruction & 0x3fffff) << 10) |
583				  (other_half & 0x3ff) ;
584				break;
585			    case SPARC_RELOC_LO10:
586			    case SPARC_RELOC_LO10_SECTDIFF:
587				value = (instruction & 0x3ff) |
588				  ((other_half & 0x3fffff) << 10);
589				break;
590			    case SPARC_RELOC_WDISP22:
591				value = (instruction & 0x3fffff);
592				if ((value & 0x200000) != 0)
593				  value |= 0xffc00000;
594				value <<= 2;
595				break;
596			    case SPARC_RELOC_WDISP30:
597				value = (instruction & 0x3fffffff);
598				value <<= 2;
599				break;
600			    default:
601				/* the error check is caught below */
602				break;
603			    }
604			}
605			if(r_type == SPARC_RELOC_SECTDIFF ||
606			   r_type == SPARC_RELOC_HI22_SECTDIFF ||
607			   r_type == SPARC_RELOC_LO10_SECTDIFF){
608			    /*
609			     * For SPARC_RELOC_SECTDIFF's the item to be
610			     * relocated, in value, is the value of the
611			     * expression:
612			     *     r_value - pair_r_value + offset
613			     * To set the value of the relocated expression,
614			     * it is set from relocating the two r_value's and
615			     * adding back in the offset.  So here get the
616			     * offset from the value of the expression.
617			     */
618			    value += input_pc; /* adjust for pcrel */
619			    offset = value - r_value + pair_r_value;
620
621			    /*
622			     * Now build up the value of the relocated
623			     * expression one part at a time.  First set the
624			     * new value to the relocated r_value.
625			     */
626		    	    if(local_map->nfine_relocs != 0){
627				/*
628				 * Check to see if this reference is legal with
629				 * respect to indirect sections.
630				 */
631				legal_reference(section_map, r_address,
632				    local_map, r_value - local_map->s->addr +
633				    offset, i, TRUE);
634				value = fine_reloc_output_address(local_map,
635					    r_value - local_map->s->addr,
636					    local_map->output_section->s.addr);
637			    }
638			    else{
639				value = local_map->output_section->s.addr +
640					local_map->offset +
641					r_value - local_map->s->addr;
642			    }
643			    /* Second subtract the relocated pair_r_value. */
644			    if(pair_local_map->nfine_relocs != 0){
645				/*
646				 * Check to see if this reference is legal with
647				 * respect to indirect sections.
648				 */
649				legal_reference(section_map, r_address,
650				    pair_local_map, pair_r_value -
651				    pair_local_map->s->addr, i, TRUE);
652				value -=
653				    fine_reloc_output_address(pair_local_map,
654					pair_r_value - pair_local_map->s->addr,
655				        pair_local_map->output_section->s.addr);
656			    }
657			    else{
658				value -=
659				    pair_local_map->output_section->s.addr +
660				    pair_local_map->offset +
661				    pair_r_value - pair_local_map->s->addr;
662			    }
663			    /* Third add in the offset. */
664			    value += offset;
665			    value -= output_pc; /* adjust for pcrel */
666			}
667			else{
668			    /*
669			     * If the relocation entry is not a scattered
670			     * relocation entry then the relocation is based on
671			     * the value of value of the expresion of the item
672			     * to be relocated.  If it is a scattered relocation
673			     * entry then the relocation is based on the r_value
674			     * in the relocation entry and the offset part of
675			     * the expression at the item to be relocated is
676			     * extracted so it can be added after the relocation
677			     * is done.
678			     */
679			    value += input_pc;
680			    if(r_scattered == 0){
681				r_value = value;
682				offset = 0;
683			    }
684			    else{
685				offset = value - r_value;
686			    }
687			    /*
688			     * Check to see if this reference is legal with
689			     * respect to indirect sections.
690			     */
691			    legal_reference(section_map, r_address, local_map,
692				    r_value - local_map->s->addr + offset, i,
693				    FALSE);
694			    value = fine_reloc_output_address(local_map,
695					r_value - local_map->s->addr,
696					local_map->output_section->s.addr);
697			    value -= output_pc;
698			    value += offset;
699			}
700			if(r_type == SPARC_RELOC_VANILLA ||
701			   r_type == SPARC_RELOC_SECTDIFF){
702			    switch(r_length){
703			    case 0: /* byte */
704				if( (value & 0xffffff00) &&
705				   ((value & 0xffffff80) != 0xffffff80))
706				    error_with_cur_obj("relocation for entry "
707					"%lu in section (%.16s,%.16s) does not "
708					"fit in 1 byte", i,
709					section_map->s->segname,
710					section_map->s->sectname);
711				set_byte((char *)(contents + r_address), value);
712				break;
713			    case 1: /* word (2 byte) */
714				if( (value & 0xffff0000) &&
715				   ((value & 0xffff8000) != 0xffff8000))
716				    error_with_cur_obj("relocation for entry "
717					"%lu in section (%.16s,%.16s) does not "
718					"fit in 2 bytes", i,
719					section_map->s->segname,
720					section_map->s->sectname);
721				set_short((short *)(contents + r_address),
722					  value);
723				break;
724			    case 2: /* long (4 byte) */
725				set_long((long *)(contents + r_address), value);
726				break;
727			    default:
728				error_with_cur_obj("r_length field of "
729				    "relocation entry %lu in section (%.16s,"
730				    "%.16s) invalid", i,
731				    section_map->s->segname,
732				    section_map->s->sectname);
733				return;
734			    }
735			}
736			else{
737			    switch(r_type){
738			    case SPARC_RELOC_HI22:
739			    case SPARC_RELOC_HI22_SECTDIFF:
740				other_half = value & 0x3ff;
741				instruction = (instruction & 0xffc00000) |
742					      ((value >> 10) & 0x3fffff);
743				break;
744			    case SPARC_RELOC_LO10:
745			    case SPARC_RELOC_LO10_SECTDIFF:
746				other_half = (value >> 10) & 0x3fffff;
747				instruction = (instruction & 0xfffffc00) |
748					      (value & 0x3ff);
749				break;
750			      case SPARC_RELOC_WDISP22:
751				if ((value & 0xff800000) != 0xff800000 &&
752				    (value & 0xff800000) != 0x00000000)
753				    error_with_cur_obj("relocation overflow "
754					"for relocation entry %lu in section "
755					"(%.16s,%.16s) (displacement too large)"
756					, i, section_map->s->segname,
757					section_map->s->sectname);
758				value >>= 2;
759				instruction = (instruction & 0xffc00000) |
760				  (value & 0x003fffff);
761				break;
762			      case SPARC_RELOC_WDISP30:
763				value >>= 2;
764				instruction = (instruction & 0xc0000000) |
765				  (value & 0x3fffffff);
766				break;
767			    default:
768				error_with_cur_obj("r_type field of "
769				    "relocation entry %lu in section (%.16s,"
770				    "%.16s) invalid", i,
771				    section_map->s->segname,
772				    section_map->s->sectname);
773				return;
774			    }
775			    set_long((long *)(contents + r_address),
776				     instruction);
777			}
778
779			goto update_reloc;
780		    }
781		}
782	    }
783	    if(r_pcrel){
784		/*
785		 * This is a relocation entry is also pc relative which means
786		 * the value of the pc will get added to it when it is executed.
787		 * The item being relocated has the value of the pc in the input
788		 * file subtracted from it.  So to relocate this the value of
789		 * pc in the input file is added and then value of the output
790		 * pc is subtracted (since the offset into the section remains
791		 * constant it is not added in and then subtracted out).
792		 */
793		if(section_map->nfine_relocs == 0)
794		    value += + section_map->s->addr + /* r_address */
795		             - (section_map->output_section->s.addr +
796				section_map->offset /* + r_address */);
797		else
798		    value += + section_map->s->addr + r_address
799			     - (section_map->output_section->s.addr +
800			        fine_reloc_output_offset(section_map,
801							 r_address));
802	    }
803	    if(r_type == SPARC_RELOC_VANILLA ||
804	       r_type == SPARC_RELOC_SECTDIFF){
805		switch(r_length){
806		case 0: /* byte */
807		    value += get_byte((char *)(contents + r_address));
808		    if( (value & 0xffffff00) &&
809		       ((value & 0xffffff80) != 0xffffff80))
810			error_with_cur_obj("relocation for entry %lu in section"
811			    " (%.16s,%.16s) does not fit in 1 byte", i,
812			    section_map->s->segname, section_map->s->sectname);
813		    set_byte((char *)(contents + r_address), value);
814		    break;
815		case 1: /* word (2 byte) */
816		    value += get_short((short *)(contents + r_address));
817		    if( (value & 0xffff0000) &&
818		       ((value & 0xffff8000) != 0xffff8000))
819			error_with_cur_obj("relocation for entry %lu in section"
820			    " (%.16s,%.16s) does not fit in 2 bytes", i,
821			    section_map->s->segname, section_map->s->sectname);
822		    set_short((short *)(contents + r_address), value);
823		    break;
824		case 2: /* long (4 byte) */
825		    value += get_long((long *)(contents + r_address));
826		    set_long((long *)(contents + r_address), value);
827		    break;
828		default:
829		    error_with_cur_obj("r_length field of relocation entry %lu "
830			"in section (%.16s,%.16s) invalid", i,
831			section_map->s->segname, section_map->s->sectname);
832		    return;
833		}
834	    }
835	    /*
836	     * Do SPARC specific relocation based on the r_type.
837	     */
838	    else {
839		instruction = get_long((long *)(contents + r_address));
840		switch(r_type){
841		case SPARC_RELOC_HI22_SECTDIFF:
842		    immediate = ((instruction & 0x3fffff) << 10) | other_half;
843		    immediate += value;
844		    instruction = (instruction & 0xffc00000) |
845				  ((immediate >> 10) & 0x3fffff);
846		    other_half = immediate & 0x3ff;
847		    break;
848
849		case SPARC_RELOC_HI22:
850		    immediate = ((instruction & 0x3fffff) << 10) | other_half;
851		    immediate += value;
852		    instruction = (instruction & 0xffc00000) |
853				  ((immediate >> 10) & 0x3fffff);
854		    other_half = immediate & 0x3ff;
855		    break;
856		case SPARC_RELOC_LO10:
857		    immediate = (instruction & 0x3ff) | (other_half << 10);
858		    immediate += value;
859		    instruction = (instruction & 0xfffffc00) |
860					(immediate & 0x3ff);
861		    other_half = (immediate >> 10) & 0x3fffff;
862		    break;
863		case SPARC_RELOC_LO10_SECTDIFF:
864		    immediate = (instruction & 0x3ff) | (other_half << 10);
865		    immediate += value;
866		    instruction = (instruction & 0xfffffc00) |
867				  (immediate & 0x3ff);
868		    other_half = (immediate >> 10) & 0x3fffff;
869		    break;
870		  case SPARC_RELOC_WDISP22:
871		    immediate = (instruction & 0x3fffff);
872		    if ((immediate & 0x200000) != 0)
873		      immediate |= 0xffc00000;
874		    immediate <<= 2;
875		    immediate += value;
876		    if ((immediate & 0xff800000) != 0xff800000 &&
877		      (immediate & 0xff800000) != 0x00)
878			error_with_cur_obj("relocation overflow for relocation "
879			    "entry %lu in section (%.16s,%.16s) (displacement "
880			    "too large)", i, section_map->s->segname,
881			    section_map->s->sectname);
882		    immediate >>= 2;
883		    instruction = (instruction & 0xffc00000) |
884					(immediate & 0x3fffff);
885		    break;
886		  case SPARC_RELOC_WDISP30:
887		    immediate = (instruction & 0x3fffffff);
888		    immediate <<= 2;
889		    immediate += value;
890		    immediate >>= 2;
891		    instruction = (instruction & 0xc0000000) |
892					(immediate & 0x3fffffff);
893		    break;
894		default:
895		    error_with_cur_obj("r_type field of relocation entry %lu "
896			"in section (%.16s,%.16s) invalid", i,
897			section_map->s->segname, section_map->s->sectname);
898		    continue;
899		}
900		set_long((long *)(contents + r_address), instruction);
901	    }
902
903	    /*
904	     * If relocation entries are to be saved in the output file then
905	     * update the entry for the output file.
906	     */
907update_reloc:
908	    ;
909#ifndef RLD
910	    if(save_reloc || output_for_dyld){
911		if(r_extern){
912		    /*
913		     * If we are prebinding and this is a lazy pointer section
914		     * change the relocation entry to a SPARC_RELOC_PB_LA_PTR
915		     * type.  This stuffs the value of the lazy pointer as it
916		     * wouldn't be prebound in the r_value field.  So if the
917		     * prebounding can't be used at runtime the value of the
918		     * lazy pointer will get set back to the r_value by dyld.
919		     */
920		    if(prebinding == TRUE &&
921		       (section_map->s->flags & SECTION_TYPE) ==
922			S_LAZY_SYMBOL_POINTERS){
923			sreloc = (struct scattered_relocation_info *)reloc;
924			r_scattered = 1;
925			sreloc->r_scattered = r_scattered;
926			sreloc->r_address = r_address;
927			sreloc->r_pcrel = r_pcrel;
928			sreloc->r_length = r_length;
929			sreloc->r_type = SPARC_RELOC_PB_LA_PTR;
930			sreloc->r_value = value;
931		    }
932		    /*
933		     * For external relocation entries that the symbol is
934		     * defined (not undefined or common) but not when we are
935		     * forcing an external relocation entry for a global
936		     * coalesced symbol and if the output file is not a multi
937		     * module MH_DYLIB or the symbol is a private extern, it is
938		     * changed to a local relocation entry using the section
939		     * that symbol is defined in.  If still undefined or forcing
940		     * an external relocation entry for a global coalesced
941		     * symbol, then the index of the symbol in the output file
942		     * is set into r_symbolnum.
943		     */
944		    else if((merged_symbol->nlist.n_type & N_TYPE) != N_UNDF &&
945		            (merged_symbol->nlist.n_type & N_TYPE) != N_PBUD &&
946		            force_extern_reloc == FALSE &&
947		            ((filetype != MH_DYLIB ||
948			      multi_module_dylib == FALSE) ||
949			     (merged_symbol->nlist.n_type & N_PEXT) == N_PEXT)){
950			reloc->r_extern = 0;
951			/*
952			 * If this symbol was in the base file then no futher
953			 * relocation can ever be done (the symbols in the base
954			 * file are fixed). Or if the symbol was an absolute
955			 * symbol.
956			 */
957			if(merged_symbol->definition_object == base_obj ||
958			   (merged_symbol->nlist.n_type & N_TYPE) == N_ABS){
959				reloc->r_symbolnum = R_ABS;
960			}
961			else{
962			    /*
963			     * The symbol that this relocation entry is refering
964			     * to is defined so convert this external relocation
965			     * entry into a local or scattered relocation entry.
966			     * If the item to be relocated has an offset added
967			     * to the symbol's value and the output is not for
968			     * dyld make it a scattered relocation entry else
969			     * make it a local relocation entry.
970			     */
971			    if(offset == 0 || output_for_dyld){
972				reloc->r_symbolnum =merged_symbol->nlist.n_sect;
973			    }
974			    else{
975				sreloc = (struct scattered_relocation_info *)
976					 reloc;
977				r_scattered = 1;
978				sreloc->r_scattered = r_scattered;
979				sreloc->r_address = r_address;
980				sreloc->r_pcrel = r_pcrel;
981				sreloc->r_length = r_length;
982				sreloc->r_type = r_type;
983				sreloc->r_value = merged_symbol->nlist.n_value;
984			    }
985			}
986		    }
987		    else{
988			reloc->r_symbolnum =
989				      merged_symbol_output_index(merged_symbol);
990		    }
991		}
992		else if(r_scattered == 0){
993		    /*
994		     * If we are prebinding and this is a lazy pointer section
995		     * change the relocation entry to a SPARC_RELOC_PB_LA_PTR
996		     * type.  This stuffs the value of the lazy pointer as it
997		     * wouldn't be prebound in the r_value field.  So if the
998		     * prebounding can't be used at runtime the value of the
999		     * lazy pointer will get set back to the r_value by dyld.
1000		     */
1001		    if(prebinding == TRUE &&
1002		       (section_map->s->flags & SECTION_TYPE) ==
1003			S_LAZY_SYMBOL_POINTERS){
1004			sreloc = (struct scattered_relocation_info *)reloc;
1005			r_scattered = 1;
1006			sreloc->r_scattered = r_scattered;
1007			sreloc->r_address = r_address;
1008			sreloc->r_pcrel = r_pcrel;
1009			sreloc->r_length = r_length;
1010			sreloc->r_type = SPARC_RELOC_PB_LA_PTR;
1011			sreloc->r_value = value;
1012		    }
1013		    /*
1014		     * For local relocation entries the section number is
1015		     * changed to the section number in the output file.
1016		     */
1017		    else if(reloc->r_symbolnum != R_ABS){
1018			if(local_map->nfine_relocs == 0){
1019			    reloc->r_symbolnum =
1020				      local_map->output_section->output_sectnum;
1021			}
1022			else{
1023			    reloc->r_symbolnum =
1024				fine_reloc_output_sectnum(local_map,
1025						r_value - local_map->s->addr);
1026			}
1027		    }
1028		}
1029		else{
1030		    /*
1031		     * This is a scattered relocation entry.  If the output is
1032		     * for dyld convert it to a local relocation entry so as
1033		     * to not overflow the 24-bit r_address field in a scattered
1034		     * relocation entry.  The overflow would happen in
1035		     * reloc_output_for_dyld() in sections.c when it adjusts
1036		     * the r_address fields of the relocation entries.
1037		     */
1038		    if(output_for_dyld){
1039			reloc = (struct relocation_info *)sreloc;
1040			r_scattered = 0;
1041			reloc->r_address = r_address;
1042			reloc->r_pcrel = r_pcrel;
1043			reloc->r_extern = 0;
1044			reloc->r_length = r_length;
1045			reloc->r_type = r_type;
1046			if(local_map->nfine_relocs == 0){
1047			    reloc->r_symbolnum =
1048				      local_map->output_section->output_sectnum;
1049			}
1050			else{
1051			    reloc->r_symbolnum =
1052				fine_reloc_output_sectnum(local_map,
1053						r_value - local_map->s->addr);
1054			}
1055		    }
1056		    else{
1057			/*
1058			 * For scattered relocation entries the r_value field is
1059			 * relocated.
1060			 */
1061			if(local_map->nfine_relocs == 0)
1062			    sreloc->r_value +=
1063					   - local_map->s->addr
1064					   + local_map->output_section->s.addr +
1065					   local_map->offset;
1066			else
1067			    sreloc->r_value =
1068					fine_reloc_output_address(local_map,
1069						r_value - local_map->s->addr,
1070					   local_map->output_section->s.addr);
1071		    }
1072		}
1073		/*
1074		 * If this section that the reloation is being done for has fine
1075		 * relocation then the offset in the r_address field has to be
1076		 * set to where it will end up in the output file.  Otherwise
1077		 * it simply has to have the offset to where this contents
1078		 * appears in the output file.
1079		 */
1080		if(r_scattered == 0){
1081		    if(section_map->nfine_relocs == 0){
1082			reloc->r_address += section_map->offset;
1083		    }
1084		    else{
1085			reloc->r_address = fine_reloc_output_offset(section_map,
1086								    r_address);
1087		    }
1088		}
1089		else{
1090		    if(section_map->nfine_relocs == 0){
1091			sreloc->r_address += section_map->offset;
1092		    }
1093		    else{
1094			sreloc->r_address =fine_reloc_output_offset(section_map,
1095								    r_address);
1096		    }
1097		}
1098		/*
1099		 * If their was a paired relocation entry then update the
1100		 * paired relocation entry.
1101		 */
1102		if(pair_r_type == SPARC_RELOC_PAIR){
1103		    if(pair_reloc != NULL)
1104			pair_reloc->r_address = other_half;
1105		    else if(spair_reloc != NULL){
1106			if(r_type == SPARC_RELOC_SECTDIFF ||
1107			   r_type == SPARC_RELOC_HI22_SECTDIFF ||
1108			   r_type == SPARC_RELOC_LO10_SECTDIFF){
1109			    /*
1110			     * For SPARC_RELOC_SECTDIFF relocation entries (which
1111			     * are always scattered types) the r_value field is
1112			     * relocated.
1113			     */
1114			    if(pair_local_map->nfine_relocs == 0)
1115				spair_reloc->r_value +=
1116				    - pair_local_map->s->addr
1117				    + (pair_local_map->output_section->s.addr +
1118				       pair_local_map->offset);
1119			    else
1120				spair_reloc->r_value =
1121				    fine_reloc_output_address(pair_local_map,
1122					pair_r_value - pair_local_map->s->addr,
1123					pair_local_map->output_section->s.addr);
1124			    if(r_type == SPARC_RELOC_HI22_SECTDIFF ||
1125			       r_type == SPARC_RELOC_LO10_SECTDIFF)
1126				spair_reloc->r_address = other_half;
1127			}
1128			else{
1129			    spair_reloc->r_address = other_half;
1130			}
1131		    }
1132		    else{
1133			fatal("internal error, in sparc_reloc() pair_r_type "
1134			    "is SPARC_RELOC_PAIR but pair_reloc and spair_reloc "
1135			    "are NULL");
1136		    }
1137		}
1138	    }
1139#endif /* !defined(RLD) */
1140	    /*
1141	     * If their was a paired relocation entry then it has been processed
1142	     * so skip it by incrementing the index of the relocation entry that
1143	     * is being processed.
1144	     */
1145	    if(pair_r_type == SPARC_RELOC_PAIR)
1146		i++;
1147	}
1148}
1149