1*3d8817e4Smiod /* BFD back-end for i386 a.out binaries under LynxOS.
2*3d8817e4Smiod    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2001, 2002,
3*3d8817e4Smiod    2003 Free Software Foundation, Inc.
4*3d8817e4Smiod 
5*3d8817e4Smiod This file is part of BFD, the Binary File Descriptor library.
6*3d8817e4Smiod 
7*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
8*3d8817e4Smiod it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
10*3d8817e4Smiod (at your option) any later version.
11*3d8817e4Smiod 
12*3d8817e4Smiod This program is distributed in the hope that it will be useful,
13*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*3d8817e4Smiod GNU General Public License for more details.
16*3d8817e4Smiod 
17*3d8817e4Smiod You should have received a copy of the GNU General Public License
18*3d8817e4Smiod along with this program; if not, write to the Free Software
19*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20*3d8817e4Smiod 
21*3d8817e4Smiod #define N_SHARED_LIB(x) 0
22*3d8817e4Smiod 
23*3d8817e4Smiod #define TEXT_START_ADDR 0
24*3d8817e4Smiod #define TARGET_PAGE_SIZE 4096
25*3d8817e4Smiod #define SEGMENT_SIZE TARGET_PAGE_SIZE
26*3d8817e4Smiod #define DEFAULT_ARCH bfd_arch_i386
27*3d8817e4Smiod 
28*3d8817e4Smiod /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
29*3d8817e4Smiod    remove whitespace added here, and thus will fail to concatenate
30*3d8817e4Smiod    the tokens.  */
31*3d8817e4Smiod #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
32*3d8817e4Smiod #define TARGETNAME "a.out-i386-lynx"
33*3d8817e4Smiod 
34*3d8817e4Smiod #include "bfd.h"
35*3d8817e4Smiod #include "sysdep.h"
36*3d8817e4Smiod #include "libbfd.h"
37*3d8817e4Smiod 
38*3d8817e4Smiod #ifndef WRITE_HEADERS
39*3d8817e4Smiod #define WRITE_HEADERS(abfd, execp)					      \
40*3d8817e4Smiod       {									      \
41*3d8817e4Smiod 	bfd_size_type text_size; /* dummy vars */			      \
42*3d8817e4Smiod 	file_ptr text_end;						      \
43*3d8817e4Smiod 	if (adata(abfd).magic == undecided_magic)			      \
44*3d8817e4Smiod 	  NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);     \
45*3d8817e4Smiod     									      \
46*3d8817e4Smiod 	execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	      \
47*3d8817e4Smiod 	execp->a_entry = bfd_get_start_address (abfd);			      \
48*3d8817e4Smiod     									      \
49*3d8817e4Smiod 	execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		      \
50*3d8817e4Smiod 			   obj_reloc_entry_size (abfd));		      \
51*3d8817e4Smiod 	execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		      \
52*3d8817e4Smiod 			   obj_reloc_entry_size (abfd));		      \
53*3d8817e4Smiod 	NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes);	      \
54*3d8817e4Smiod 									      \
55*3d8817e4Smiod 	if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0		      \
56*3d8817e4Smiod 	    || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
57*3d8817e4Smiod 			  abfd) != EXEC_BYTES_SIZE)			      \
58*3d8817e4Smiod 	  return FALSE;							      \
59*3d8817e4Smiod 	/* Now write out reloc info, followed by syms and strings */	      \
60*3d8817e4Smiod   									      \
61*3d8817e4Smiod 	if (bfd_get_symcount (abfd) != 0) 				      \
62*3d8817e4Smiod 	    {								      \
63*3d8817e4Smiod 	      if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET)    \
64*3d8817e4Smiod 		  != 0)							      \
65*3d8817e4Smiod 	        return FALSE;						      \
66*3d8817e4Smiod 									      \
67*3d8817e4Smiod 	      if (! NAME(aout,write_syms) (abfd)) return FALSE;		      \
68*3d8817e4Smiod 									      \
69*3d8817e4Smiod 	      if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET)   \
70*3d8817e4Smiod 		  != 0)							      \
71*3d8817e4Smiod 	        return FALSE;						      \
72*3d8817e4Smiod 									      \
73*3d8817e4Smiod 	      if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd)))   \
74*3d8817e4Smiod 		return FALSE;						      \
75*3d8817e4Smiod 	      if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET)   \
76*3d8817e4Smiod 		  != 0)							      \
77*3d8817e4Smiod 	        return 0;						      \
78*3d8817e4Smiod 									      \
79*3d8817e4Smiod 	      if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd)))   \
80*3d8817e4Smiod 		return FALSE;						      \
81*3d8817e4Smiod 	    }								      \
82*3d8817e4Smiod       }
83*3d8817e4Smiod #endif
84*3d8817e4Smiod 
85*3d8817e4Smiod #include "libaout.h"
86*3d8817e4Smiod #include "aout/aout64.h"
87*3d8817e4Smiod 
88*3d8817e4Smiod void NAME (lynx,swap_std_reloc_out)
89*3d8817e4Smiod   PARAMS ((bfd *, arelent *, struct reloc_std_external *));
90*3d8817e4Smiod void NAME (lynx,swap_ext_reloc_out)
91*3d8817e4Smiod   PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
92*3d8817e4Smiod void NAME (lynx,swap_ext_reloc_in)
93*3d8817e4Smiod   PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
94*3d8817e4Smiod 	   bfd_size_type));
95*3d8817e4Smiod void NAME (lynx,swap_std_reloc_in)
96*3d8817e4Smiod   PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
97*3d8817e4Smiod 	   bfd_size_type));
98*3d8817e4Smiod bfd_boolean NAME (lynx,slurp_reloc_table)
99*3d8817e4Smiod   PARAMS ((bfd *, sec_ptr, asymbol **));
100*3d8817e4Smiod bfd_boolean NAME (lynx,squirt_out_relocs)
101*3d8817e4Smiod   PARAMS ((bfd *, asection *));
102*3d8817e4Smiod long NAME (lynx,canonicalize_reloc)
103*3d8817e4Smiod   PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
104*3d8817e4Smiod 
105*3d8817e4Smiod #ifdef LYNX_CORE
106*3d8817e4Smiod 
107*3d8817e4Smiod char *lynx_core_file_failing_command ();
108*3d8817e4Smiod int lynx_core_file_failing_signal ();
109*3d8817e4Smiod bfd_boolean lynx_core_file_matches_executable_p ();
110*3d8817e4Smiod const bfd_target *lynx_core_file_p ();
111*3d8817e4Smiod 
112*3d8817e4Smiod #define	MY_core_file_failing_command lynx_core_file_failing_command
113*3d8817e4Smiod #define	MY_core_file_failing_signal lynx_core_file_failing_signal
114*3d8817e4Smiod #define	MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
115*3d8817e4Smiod #define	MY_core_file_p lynx_core_file_p
116*3d8817e4Smiod 
117*3d8817e4Smiod #endif /* LYNX_CORE */
118*3d8817e4Smiod 
119*3d8817e4Smiod 
120*3d8817e4Smiod #define KEEPIT udata.i
121*3d8817e4Smiod 
122*3d8817e4Smiod extern reloc_howto_type aout_32_ext_howto_table[];
123*3d8817e4Smiod extern reloc_howto_type aout_32_std_howto_table[];
124*3d8817e4Smiod 
125*3d8817e4Smiod /* Standard reloc stuff */
126*3d8817e4Smiod /* Output standard relocation information to a file in target byte order. */
127*3d8817e4Smiod 
128*3d8817e4Smiod void
129*3d8817e4Smiod NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
130*3d8817e4Smiod      bfd *abfd;
131*3d8817e4Smiod      arelent *g;
132*3d8817e4Smiod      struct reloc_std_external *natptr;
133*3d8817e4Smiod {
134*3d8817e4Smiod   int r_index;
135*3d8817e4Smiod   asymbol *sym = *(g->sym_ptr_ptr);
136*3d8817e4Smiod   int r_extern;
137*3d8817e4Smiod   unsigned int r_length;
138*3d8817e4Smiod   int r_pcrel;
139*3d8817e4Smiod   int r_baserel, r_jmptable, r_relative;
140*3d8817e4Smiod   unsigned int r_addend;
141*3d8817e4Smiod   asection *output_section = sym->section->output_section;
142*3d8817e4Smiod 
143*3d8817e4Smiod   PUT_WORD (abfd, g->address, natptr->r_address);
144*3d8817e4Smiod 
145*3d8817e4Smiod   r_length = g->howto->size;	/* Size as a power of two */
146*3d8817e4Smiod   r_pcrel = (int) g->howto->pc_relative;	/* Relative to PC? */
147*3d8817e4Smiod   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
148*3d8817e4Smiod   r_baserel = 0;
149*3d8817e4Smiod   r_jmptable = 0;
150*3d8817e4Smiod   r_relative = 0;
151*3d8817e4Smiod 
152*3d8817e4Smiod   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
153*3d8817e4Smiod 
154*3d8817e4Smiod   /* name was clobbered by aout_write_syms to be symbol index */
155*3d8817e4Smiod 
156*3d8817e4Smiod   /* If this relocation is relative to a symbol then set the
157*3d8817e4Smiod      r_index to the symbols index, and the r_extern bit.
158*3d8817e4Smiod 
159*3d8817e4Smiod      Absolute symbols can come in in two ways, either as an offset
160*3d8817e4Smiod      from the abs section, or as a symbol which has an abs value.
161*3d8817e4Smiod      check for that here
162*3d8817e4Smiod   */
163*3d8817e4Smiod 
164*3d8817e4Smiod 
165*3d8817e4Smiod   if (bfd_is_com_section (output_section)
166*3d8817e4Smiod       || bfd_is_abs_section (output_section)
167*3d8817e4Smiod       || bfd_is_und_section (output_section))
168*3d8817e4Smiod     {
169*3d8817e4Smiod       if (bfd_abs_section_ptr->symbol == sym)
170*3d8817e4Smiod 	{
171*3d8817e4Smiod 	  /* Whoops, looked like an abs symbol, but is really an offset
172*3d8817e4Smiod 	     from the abs section */
173*3d8817e4Smiod 	  r_index = 0;
174*3d8817e4Smiod 	  r_extern = 0;
175*3d8817e4Smiod 	}
176*3d8817e4Smiod       else
177*3d8817e4Smiod 	{
178*3d8817e4Smiod 	  /* Fill in symbol */
179*3d8817e4Smiod 	  r_extern = 1;
180*3d8817e4Smiod 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
181*3d8817e4Smiod 	}
182*3d8817e4Smiod     }
183*3d8817e4Smiod   else
184*3d8817e4Smiod     {
185*3d8817e4Smiod       /* Just an ordinary section */
186*3d8817e4Smiod       r_extern = 0;
187*3d8817e4Smiod       r_index = output_section->target_index;
188*3d8817e4Smiod     }
189*3d8817e4Smiod 
190*3d8817e4Smiod   /* now the fun stuff */
191*3d8817e4Smiod   if (bfd_header_big_endian (abfd))
192*3d8817e4Smiod     {
193*3d8817e4Smiod       natptr->r_index[0] = r_index >> 16;
194*3d8817e4Smiod       natptr->r_index[1] = r_index >> 8;
195*3d8817e4Smiod       natptr->r_index[2] = r_index;
196*3d8817e4Smiod       natptr->r_type[0] =
197*3d8817e4Smiod 	(r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
198*3d8817e4Smiod 	| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
199*3d8817e4Smiod 	| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
200*3d8817e4Smiod 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
201*3d8817e4Smiod 	| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
202*3d8817e4Smiod 	| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
203*3d8817e4Smiod     }
204*3d8817e4Smiod   else
205*3d8817e4Smiod     {
206*3d8817e4Smiod       natptr->r_index[2] = r_index >> 16;
207*3d8817e4Smiod       natptr->r_index[1] = r_index >> 8;
208*3d8817e4Smiod       natptr->r_index[0] = r_index;
209*3d8817e4Smiod       natptr->r_type[0] =
210*3d8817e4Smiod 	(r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
211*3d8817e4Smiod 	| (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
212*3d8817e4Smiod 	| (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
213*3d8817e4Smiod 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
214*3d8817e4Smiod 	| (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
215*3d8817e4Smiod 	| (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
216*3d8817e4Smiod     }
217*3d8817e4Smiod }
218*3d8817e4Smiod 
219*3d8817e4Smiod 
220*3d8817e4Smiod /* Extended stuff */
221*3d8817e4Smiod /* Output extended relocation information to a file in target byte order. */
222*3d8817e4Smiod 
223*3d8817e4Smiod void
224*3d8817e4Smiod NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
225*3d8817e4Smiod      bfd *abfd;
226*3d8817e4Smiod      arelent *g;
227*3d8817e4Smiod      register struct reloc_ext_external *natptr;
228*3d8817e4Smiod {
229*3d8817e4Smiod   int r_index;
230*3d8817e4Smiod   int r_extern;
231*3d8817e4Smiod   unsigned int r_type;
232*3d8817e4Smiod   unsigned int r_addend;
233*3d8817e4Smiod   asymbol *sym = *(g->sym_ptr_ptr);
234*3d8817e4Smiod   asection *output_section = sym->section->output_section;
235*3d8817e4Smiod 
236*3d8817e4Smiod   PUT_WORD (abfd, g->address, natptr->r_address);
237*3d8817e4Smiod 
238*3d8817e4Smiod   r_type = (unsigned int) g->howto->type;
239*3d8817e4Smiod 
240*3d8817e4Smiod   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
241*3d8817e4Smiod 
242*3d8817e4Smiod 
243*3d8817e4Smiod   /* If this relocation is relative to a symbol then set the
244*3d8817e4Smiod      r_index to the symbols index, and the r_extern bit.
245*3d8817e4Smiod 
246*3d8817e4Smiod      Absolute symbols can come in in two ways, either as an offset
247*3d8817e4Smiod      from the abs section, or as a symbol which has an abs value.
248*3d8817e4Smiod      check for that here
249*3d8817e4Smiod      */
250*3d8817e4Smiod 
251*3d8817e4Smiod   if (bfd_is_com_section (output_section)
252*3d8817e4Smiod       || bfd_is_abs_section (output_section)
253*3d8817e4Smiod       || bfd_is_und_section (output_section))
254*3d8817e4Smiod     {
255*3d8817e4Smiod       if (bfd_abs_section_ptr->symbol == sym)
256*3d8817e4Smiod 	{
257*3d8817e4Smiod 	  /* Whoops, looked like an abs symbol, but is really an offset
258*3d8817e4Smiod 	 from the abs section */
259*3d8817e4Smiod 	  r_index = 0;
260*3d8817e4Smiod 	  r_extern = 0;
261*3d8817e4Smiod 	}
262*3d8817e4Smiod       else
263*3d8817e4Smiod 	{
264*3d8817e4Smiod 	  r_extern = 1;
265*3d8817e4Smiod 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
266*3d8817e4Smiod 	}
267*3d8817e4Smiod     }
268*3d8817e4Smiod   else
269*3d8817e4Smiod     {
270*3d8817e4Smiod       /* Just an ordinary section */
271*3d8817e4Smiod       r_extern = 0;
272*3d8817e4Smiod       r_index = output_section->target_index;
273*3d8817e4Smiod     }
274*3d8817e4Smiod 
275*3d8817e4Smiod 
276*3d8817e4Smiod   /* now the fun stuff */
277*3d8817e4Smiod   if (bfd_header_big_endian (abfd))
278*3d8817e4Smiod     {
279*3d8817e4Smiod       natptr->r_index[0] = r_index >> 16;
280*3d8817e4Smiod       natptr->r_index[1] = r_index >> 8;
281*3d8817e4Smiod       natptr->r_index[2] = r_index;
282*3d8817e4Smiod       natptr->r_type[0] =
283*3d8817e4Smiod 	(r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
284*3d8817e4Smiod 	| (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
285*3d8817e4Smiod     }
286*3d8817e4Smiod   else
287*3d8817e4Smiod     {
288*3d8817e4Smiod       natptr->r_index[2] = r_index >> 16;
289*3d8817e4Smiod       natptr->r_index[1] = r_index >> 8;
290*3d8817e4Smiod       natptr->r_index[0] = r_index;
291*3d8817e4Smiod       natptr->r_type[0] =
292*3d8817e4Smiod 	(r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
293*3d8817e4Smiod 	| (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
294*3d8817e4Smiod     }
295*3d8817e4Smiod 
296*3d8817e4Smiod   PUT_WORD (abfd, r_addend, natptr->r_addend);
297*3d8817e4Smiod }
298*3d8817e4Smiod 
299*3d8817e4Smiod /* BFD deals internally with all things based from the section they're
300*3d8817e4Smiod    in. so, something in 10 bytes into a text section  with a base of
301*3d8817e4Smiod    50 would have a symbol (.text+10) and know .text vma was 50.
302*3d8817e4Smiod 
303*3d8817e4Smiod    Aout keeps all it's symbols based from zero, so the symbol would
304*3d8817e4Smiod    contain 60. This macro subs the base of each section from the value
305*3d8817e4Smiod    to give the true offset from the section */
306*3d8817e4Smiod 
307*3d8817e4Smiod 
308*3d8817e4Smiod #define MOVE_ADDRESS(ad)       						\
309*3d8817e4Smiod   if (r_extern) {							\
310*3d8817e4Smiod    /* undefined symbol */						\
311*3d8817e4Smiod      cache_ptr->sym_ptr_ptr = symbols + r_index;			\
312*3d8817e4Smiod      cache_ptr->addend = ad;						\
313*3d8817e4Smiod      } else {								\
314*3d8817e4Smiod     /* defined, section relative. replace symbol with pointer to    	\
315*3d8817e4Smiod        symbol which points to section  */				\
316*3d8817e4Smiod     switch (r_index) {							\
317*3d8817e4Smiod     case N_TEXT:							\
318*3d8817e4Smiod     case N_TEXT | N_EXT:						\
319*3d8817e4Smiod       cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;	\
320*3d8817e4Smiod       cache_ptr->addend = ad  - su->textsec->vma;			\
321*3d8817e4Smiod       break;								\
322*3d8817e4Smiod     case N_DATA:							\
323*3d8817e4Smiod     case N_DATA | N_EXT:						\
324*3d8817e4Smiod       cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;	\
325*3d8817e4Smiod       cache_ptr->addend = ad - su->datasec->vma;			\
326*3d8817e4Smiod       break;								\
327*3d8817e4Smiod     case N_BSS:								\
328*3d8817e4Smiod     case N_BSS | N_EXT:							\
329*3d8817e4Smiod       cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;	\
330*3d8817e4Smiod       cache_ptr->addend = ad - su->bsssec->vma;				\
331*3d8817e4Smiod       break;								\
332*3d8817e4Smiod     default:								\
333*3d8817e4Smiod     case N_ABS:								\
334*3d8817e4Smiod     case N_ABS | N_EXT:							\
335*3d8817e4Smiod      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
336*3d8817e4Smiod       cache_ptr->addend = ad;						\
337*3d8817e4Smiod       break;								\
338*3d8817e4Smiod     }									\
339*3d8817e4Smiod   }     								\
340*3d8817e4Smiod 
341*3d8817e4Smiod void
342*3d8817e4Smiod NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
343*3d8817e4Smiod      bfd *abfd;
344*3d8817e4Smiod      struct reloc_ext_external *bytes;
345*3d8817e4Smiod      arelent *cache_ptr;
346*3d8817e4Smiod      asymbol **symbols;
347*3d8817e4Smiod      bfd_size_type symcount ATTRIBUTE_UNUSED;
348*3d8817e4Smiod {
349*3d8817e4Smiod   int r_index;
350*3d8817e4Smiod   int r_extern;
351*3d8817e4Smiod   unsigned int r_type;
352*3d8817e4Smiod   struct aoutdata *su = &(abfd->tdata.aout_data->a);
353*3d8817e4Smiod 
354*3d8817e4Smiod   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
355*3d8817e4Smiod 
356*3d8817e4Smiod   r_index = bytes->r_index[1];
357*3d8817e4Smiod   r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
358*3d8817e4Smiod   r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
359*3d8817e4Smiod     >> RELOC_EXT_BITS_TYPE_SH_BIG;
360*3d8817e4Smiod 
361*3d8817e4Smiod   cache_ptr->howto = aout_32_ext_howto_table + r_type;
362*3d8817e4Smiod   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
363*3d8817e4Smiod }
364*3d8817e4Smiod 
365*3d8817e4Smiod void
366*3d8817e4Smiod NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
367*3d8817e4Smiod      bfd *abfd;
368*3d8817e4Smiod      struct reloc_std_external *bytes;
369*3d8817e4Smiod      arelent *cache_ptr;
370*3d8817e4Smiod      asymbol **symbols;
371*3d8817e4Smiod      bfd_size_type symcount ATTRIBUTE_UNUSED;
372*3d8817e4Smiod {
373*3d8817e4Smiod   int r_index;
374*3d8817e4Smiod   int r_extern;
375*3d8817e4Smiod   unsigned int r_length;
376*3d8817e4Smiod   int r_pcrel;
377*3d8817e4Smiod   int r_baserel, r_jmptable, r_relative;
378*3d8817e4Smiod   struct aoutdata *su = &(abfd->tdata.aout_data->a);
379*3d8817e4Smiod 
380*3d8817e4Smiod   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
381*3d8817e4Smiod 
382*3d8817e4Smiod   r_index = bytes->r_index[1];
383*3d8817e4Smiod   r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
384*3d8817e4Smiod   r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
385*3d8817e4Smiod   r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
386*3d8817e4Smiod   r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
387*3d8817e4Smiod   r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
388*3d8817e4Smiod   r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
389*3d8817e4Smiod     >> RELOC_STD_BITS_LENGTH_SH_BIG;
390*3d8817e4Smiod 
391*3d8817e4Smiod   cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
392*3d8817e4Smiod   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
393*3d8817e4Smiod 
394*3d8817e4Smiod   MOVE_ADDRESS (0);
395*3d8817e4Smiod }
396*3d8817e4Smiod 
397*3d8817e4Smiod /* Reloc hackery */
398*3d8817e4Smiod 
399*3d8817e4Smiod bfd_boolean
400*3d8817e4Smiod NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
401*3d8817e4Smiod      bfd *abfd;
402*3d8817e4Smiod      sec_ptr asect;
403*3d8817e4Smiod      asymbol **symbols;
404*3d8817e4Smiod {
405*3d8817e4Smiod   bfd_size_type count;
406*3d8817e4Smiod   bfd_size_type reloc_size;
407*3d8817e4Smiod   PTR relocs;
408*3d8817e4Smiod   arelent *reloc_cache;
409*3d8817e4Smiod   size_t each_size;
410*3d8817e4Smiod 
411*3d8817e4Smiod   if (asect->relocation)
412*3d8817e4Smiod     return TRUE;
413*3d8817e4Smiod 
414*3d8817e4Smiod   if (asect->flags & SEC_CONSTRUCTOR)
415*3d8817e4Smiod     return TRUE;
416*3d8817e4Smiod 
417*3d8817e4Smiod   if (asect == obj_datasec (abfd))
418*3d8817e4Smiod     {
419*3d8817e4Smiod       reloc_size = exec_hdr (abfd)->a_drsize;
420*3d8817e4Smiod       goto doit;
421*3d8817e4Smiod     }
422*3d8817e4Smiod 
423*3d8817e4Smiod   if (asect == obj_textsec (abfd))
424*3d8817e4Smiod     {
425*3d8817e4Smiod       reloc_size = exec_hdr (abfd)->a_trsize;
426*3d8817e4Smiod       goto doit;
427*3d8817e4Smiod     }
428*3d8817e4Smiod 
429*3d8817e4Smiod   bfd_set_error (bfd_error_invalid_operation);
430*3d8817e4Smiod   return FALSE;
431*3d8817e4Smiod 
432*3d8817e4Smiod doit:
433*3d8817e4Smiod   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
434*3d8817e4Smiod     return FALSE;
435*3d8817e4Smiod   each_size = obj_reloc_entry_size (abfd);
436*3d8817e4Smiod 
437*3d8817e4Smiod   count = reloc_size / each_size;
438*3d8817e4Smiod 
439*3d8817e4Smiod 
440*3d8817e4Smiod   reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
441*3d8817e4Smiod   if (!reloc_cache && count != 0)
442*3d8817e4Smiod     return FALSE;
443*3d8817e4Smiod 
444*3d8817e4Smiod   relocs = (PTR) bfd_alloc (abfd, reloc_size);
445*3d8817e4Smiod   if (!relocs && reloc_size != 0)
446*3d8817e4Smiod     {
447*3d8817e4Smiod       free (reloc_cache);
448*3d8817e4Smiod       return FALSE;
449*3d8817e4Smiod     }
450*3d8817e4Smiod 
451*3d8817e4Smiod   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
452*3d8817e4Smiod     {
453*3d8817e4Smiod       bfd_release (abfd, relocs);
454*3d8817e4Smiod       free (reloc_cache);
455*3d8817e4Smiod       return FALSE;
456*3d8817e4Smiod     }
457*3d8817e4Smiod 
458*3d8817e4Smiod   if (each_size == RELOC_EXT_SIZE)
459*3d8817e4Smiod     {
460*3d8817e4Smiod       register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
461*3d8817e4Smiod       unsigned int counter = 0;
462*3d8817e4Smiod       arelent *cache_ptr = reloc_cache;
463*3d8817e4Smiod 
464*3d8817e4Smiod       for (; counter < count; counter++, rptr++, cache_ptr++)
465*3d8817e4Smiod 	{
466*3d8817e4Smiod 	  NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
467*3d8817e4Smiod 					(bfd_size_type) bfd_get_symcount (abfd));
468*3d8817e4Smiod 	}
469*3d8817e4Smiod     }
470*3d8817e4Smiod   else
471*3d8817e4Smiod     {
472*3d8817e4Smiod       register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
473*3d8817e4Smiod       unsigned int counter = 0;
474*3d8817e4Smiod       arelent *cache_ptr = reloc_cache;
475*3d8817e4Smiod 
476*3d8817e4Smiod       for (; counter < count; counter++, rptr++, cache_ptr++)
477*3d8817e4Smiod 	{
478*3d8817e4Smiod 	  NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
479*3d8817e4Smiod 					(bfd_size_type) bfd_get_symcount (abfd));
480*3d8817e4Smiod 	}
481*3d8817e4Smiod 
482*3d8817e4Smiod     }
483*3d8817e4Smiod 
484*3d8817e4Smiod   bfd_release (abfd, relocs);
485*3d8817e4Smiod   asect->relocation = reloc_cache;
486*3d8817e4Smiod   asect->reloc_count = count;
487*3d8817e4Smiod   return TRUE;
488*3d8817e4Smiod }
489*3d8817e4Smiod 
490*3d8817e4Smiod 
491*3d8817e4Smiod 
492*3d8817e4Smiod /* Write out a relocation section into an object file.  */
493*3d8817e4Smiod 
494*3d8817e4Smiod bfd_boolean
495*3d8817e4Smiod NAME(lynx,squirt_out_relocs) (abfd, section)
496*3d8817e4Smiod      bfd *abfd;
497*3d8817e4Smiod      asection *section;
498*3d8817e4Smiod {
499*3d8817e4Smiod   arelent **generic;
500*3d8817e4Smiod   unsigned char *native, *natptr;
501*3d8817e4Smiod   size_t each_size;
502*3d8817e4Smiod 
503*3d8817e4Smiod   unsigned int count = section->reloc_count;
504*3d8817e4Smiod   bfd_size_type natsize;
505*3d8817e4Smiod 
506*3d8817e4Smiod   if (count == 0)
507*3d8817e4Smiod     return TRUE;
508*3d8817e4Smiod 
509*3d8817e4Smiod   each_size = obj_reloc_entry_size (abfd);
510*3d8817e4Smiod   natsize = count;
511*3d8817e4Smiod   natsize *= each_size;
512*3d8817e4Smiod   native = (unsigned char *) bfd_zalloc (abfd, natsize);
513*3d8817e4Smiod   if (!native)
514*3d8817e4Smiod     return FALSE;
515*3d8817e4Smiod 
516*3d8817e4Smiod   generic = section->orelocation;
517*3d8817e4Smiod 
518*3d8817e4Smiod   if (each_size == RELOC_EXT_SIZE)
519*3d8817e4Smiod     {
520*3d8817e4Smiod       for (natptr = native;
521*3d8817e4Smiod 	   count != 0;
522*3d8817e4Smiod 	   --count, natptr += each_size, ++generic)
523*3d8817e4Smiod 	NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
524*3d8817e4Smiod     }
525*3d8817e4Smiod   else
526*3d8817e4Smiod     {
527*3d8817e4Smiod       for (natptr = native;
528*3d8817e4Smiod 	   count != 0;
529*3d8817e4Smiod 	   --count, natptr += each_size, ++generic)
530*3d8817e4Smiod 	NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
531*3d8817e4Smiod     }
532*3d8817e4Smiod 
533*3d8817e4Smiod   if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
534*3d8817e4Smiod     {
535*3d8817e4Smiod       bfd_release (abfd, native);
536*3d8817e4Smiod       return FALSE;
537*3d8817e4Smiod     }
538*3d8817e4Smiod   bfd_release (abfd, native);
539*3d8817e4Smiod 
540*3d8817e4Smiod   return TRUE;
541*3d8817e4Smiod }
542*3d8817e4Smiod 
543*3d8817e4Smiod /* This is stupid.  This function should be a boolean predicate */
544*3d8817e4Smiod long
545*3d8817e4Smiod NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
546*3d8817e4Smiod      bfd *abfd;
547*3d8817e4Smiod      sec_ptr section;
548*3d8817e4Smiod      arelent **relptr;
549*3d8817e4Smiod      asymbol **symbols;
550*3d8817e4Smiod {
551*3d8817e4Smiod   arelent *tblptr = section->relocation;
552*3d8817e4Smiod   unsigned int count;
553*3d8817e4Smiod 
554*3d8817e4Smiod   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
555*3d8817e4Smiod     return -1;
556*3d8817e4Smiod 
557*3d8817e4Smiod   if (section->flags & SEC_CONSTRUCTOR)
558*3d8817e4Smiod     {
559*3d8817e4Smiod       arelent_chain *chain = section->constructor_chain;
560*3d8817e4Smiod       for (count = 0; count < section->reloc_count; count++)
561*3d8817e4Smiod 	{
562*3d8817e4Smiod 	  *relptr++ = &chain->relent;
563*3d8817e4Smiod 	  chain = chain->next;
564*3d8817e4Smiod 	}
565*3d8817e4Smiod     }
566*3d8817e4Smiod   else
567*3d8817e4Smiod     {
568*3d8817e4Smiod       tblptr = section->relocation;
569*3d8817e4Smiod 
570*3d8817e4Smiod       for (count = 0; count++ < section->reloc_count;)
571*3d8817e4Smiod 	{
572*3d8817e4Smiod 	  *relptr++ = tblptr++;
573*3d8817e4Smiod 	}
574*3d8817e4Smiod     }
575*3d8817e4Smiod   *relptr = 0;
576*3d8817e4Smiod 
577*3d8817e4Smiod   return section->reloc_count;
578*3d8817e4Smiod }
579*3d8817e4Smiod 
580*3d8817e4Smiod #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
581*3d8817e4Smiod 
582*3d8817e4Smiod #include "aout-target.h"
583