xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/nlm32-i386.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* Support for 32-bit i386 NLM (NetWare Loadable Module)
2*3d8817e4Smiod    Copyright 1993, 1994, 2000, 2001, 2002, 2003, 2005
3*3d8817e4Smiod    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 #include "bfd.h"
22*3d8817e4Smiod #include "sysdep.h"
23*3d8817e4Smiod #include "libbfd.h"
24*3d8817e4Smiod 
25*3d8817e4Smiod #define ARCH_SIZE 32
26*3d8817e4Smiod 
27*3d8817e4Smiod #include "nlm/i386-ext.h"
28*3d8817e4Smiod #define Nlm_External_Fixed_Header	Nlm32_i386_External_Fixed_Header
29*3d8817e4Smiod 
30*3d8817e4Smiod #include "libnlm.h"
31*3d8817e4Smiod 
32*3d8817e4Smiod /* Adjust the reloc location by an absolute value.  */
33*3d8817e4Smiod 
34*3d8817e4Smiod static reloc_howto_type nlm_i386_abs_howto =
35*3d8817e4Smiod   HOWTO (0,			/* Type.  */
36*3d8817e4Smiod 	 0,			/* Rightshift.  */
37*3d8817e4Smiod 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
38*3d8817e4Smiod 	 32,			/* Bitsize.  */
39*3d8817e4Smiod 	 FALSE,			/* PC relative.  */
40*3d8817e4Smiod 	 0,			/* Bitpos.  */
41*3d8817e4Smiod 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
42*3d8817e4Smiod 	 0,			/* Special_function.  */
43*3d8817e4Smiod 	 "32",			/* Name.  */
44*3d8817e4Smiod 	 TRUE,			/* Partial_inplace.  */
45*3d8817e4Smiod 	 0xffffffff,		/* Source mask.  */
46*3d8817e4Smiod 	 0xffffffff,		/* Dest mask.  */
47*3d8817e4Smiod 	 FALSE);		/* PR rel_offset.  */
48*3d8817e4Smiod 
49*3d8817e4Smiod /* Adjust the reloc location by a PC relative displacement.  */
50*3d8817e4Smiod 
51*3d8817e4Smiod static reloc_howto_type nlm_i386_pcrel_howto =
52*3d8817e4Smiod   HOWTO (1,			/* Type.  */
53*3d8817e4Smiod 	 0,			/* Rightshift.  */
54*3d8817e4Smiod 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
55*3d8817e4Smiod 	 32,			/* Bitsize.  */
56*3d8817e4Smiod 	 TRUE,			/* PC relative.  */
57*3d8817e4Smiod 	 0,			/* Bitpos.  */
58*3d8817e4Smiod 	 complain_overflow_signed, /* Complain_on_overflow.  */
59*3d8817e4Smiod 	 0,			/* Special_function.  */
60*3d8817e4Smiod 	 "DISP32",		/* Name.  */
61*3d8817e4Smiod 	 TRUE,			/* Partial_inplace.  */
62*3d8817e4Smiod 	 0xffffffff,		/* Source mask.  */
63*3d8817e4Smiod 	 0xffffffff,		/* Dest mask.  */
64*3d8817e4Smiod 	 TRUE);			/* PR rel_offset.  */
65*3d8817e4Smiod 
66*3d8817e4Smiod /* Read a NetWare i386 reloc.  */
67*3d8817e4Smiod 
68*3d8817e4Smiod static bfd_boolean
nlm_i386_read_reloc(bfd * abfd,nlmNAME (symbol_type)* sym,asection ** secp,arelent * rel)69*3d8817e4Smiod nlm_i386_read_reloc (bfd *abfd,
70*3d8817e4Smiod 		     nlmNAME (symbol_type) *sym,
71*3d8817e4Smiod 		     asection **secp,
72*3d8817e4Smiod 		     arelent *rel)
73*3d8817e4Smiod {
74*3d8817e4Smiod   bfd_byte temp[4];
75*3d8817e4Smiod   bfd_vma val;
76*3d8817e4Smiod   const char *name;
77*3d8817e4Smiod 
78*3d8817e4Smiod   if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
79*3d8817e4Smiod     return FALSE;
80*3d8817e4Smiod 
81*3d8817e4Smiod   val = bfd_get_32 (abfd, temp);
82*3d8817e4Smiod 
83*3d8817e4Smiod   /* The value is an offset into either the code or data segment.
84*3d8817e4Smiod      This is the location which needs to be adjusted.
85*3d8817e4Smiod 
86*3d8817e4Smiod      If this is a relocation fixup rather than an imported symbol (the
87*3d8817e4Smiod      sym argument is NULL) then the high bit is 0 if the location
88*3d8817e4Smiod      needs to be adjusted by the address of the data segment, or 1 if
89*3d8817e4Smiod      the location needs to be adjusted by the address of the code
90*3d8817e4Smiod      segment.  If this is an imported symbol, then the high bit is 0
91*3d8817e4Smiod      if the location is 0 if the location should be adjusted by the
92*3d8817e4Smiod      offset to the symbol, or 1 if the location should adjusted by the
93*3d8817e4Smiod      absolute value of the symbol.
94*3d8817e4Smiod 
95*3d8817e4Smiod      The second most significant bit is 0 if the value is an offset
96*3d8817e4Smiod      into the data segment, or 1 if the value is an offset into the
97*3d8817e4Smiod      code segment.
98*3d8817e4Smiod 
99*3d8817e4Smiod      All this translates fairly easily into a BFD reloc.  */
100*3d8817e4Smiod 
101*3d8817e4Smiod   if (sym == NULL)
102*3d8817e4Smiod     {
103*3d8817e4Smiod       if ((val & NLM_HIBIT) == 0)
104*3d8817e4Smiod 	name = NLM_INITIALIZED_DATA_NAME;
105*3d8817e4Smiod       else
106*3d8817e4Smiod 	{
107*3d8817e4Smiod 	  name = NLM_CODE_NAME;
108*3d8817e4Smiod 	  val &=~ NLM_HIBIT;
109*3d8817e4Smiod 	}
110*3d8817e4Smiod       rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
111*3d8817e4Smiod       rel->howto = &nlm_i386_abs_howto;
112*3d8817e4Smiod     }
113*3d8817e4Smiod   else
114*3d8817e4Smiod     {
115*3d8817e4Smiod       /* In this case we do not need to set the sym_ptr_ptr field.  */
116*3d8817e4Smiod       rel->sym_ptr_ptr = NULL;
117*3d8817e4Smiod       if ((val & NLM_HIBIT) == 0)
118*3d8817e4Smiod 	rel->howto = &nlm_i386_pcrel_howto;
119*3d8817e4Smiod       else
120*3d8817e4Smiod 	{
121*3d8817e4Smiod 	  rel->howto = &nlm_i386_abs_howto;
122*3d8817e4Smiod 	  val &=~ NLM_HIBIT;
123*3d8817e4Smiod 	}
124*3d8817e4Smiod     }
125*3d8817e4Smiod 
126*3d8817e4Smiod   if ((val & (NLM_HIBIT >> 1)) == 0)
127*3d8817e4Smiod     *secp = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
128*3d8817e4Smiod   else
129*3d8817e4Smiod     {
130*3d8817e4Smiod       *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
131*3d8817e4Smiod       val &=~ (NLM_HIBIT >> 1);
132*3d8817e4Smiod     }
133*3d8817e4Smiod 
134*3d8817e4Smiod   rel->address = val;
135*3d8817e4Smiod   rel->addend = 0;
136*3d8817e4Smiod 
137*3d8817e4Smiod   return TRUE;
138*3d8817e4Smiod }
139*3d8817e4Smiod 
140*3d8817e4Smiod /* Write a NetWare i386 reloc.  */
141*3d8817e4Smiod 
142*3d8817e4Smiod static bfd_boolean
nlm_i386_write_import(bfd * abfd,asection * sec,arelent * rel)143*3d8817e4Smiod nlm_i386_write_import (bfd * abfd, asection * sec, arelent * rel)
144*3d8817e4Smiod {
145*3d8817e4Smiod   asymbol *sym;
146*3d8817e4Smiod   bfd_vma val;
147*3d8817e4Smiod   bfd_byte temp[4];
148*3d8817e4Smiod 
149*3d8817e4Smiod   /* NetWare only supports two kinds of relocs.  We should check
150*3d8817e4Smiod      special_function here, as well, but at the moment coff-i386
151*3d8817e4Smiod      relocs uses a special_function which does not affect what we do
152*3d8817e4Smiod      here.  */
153*3d8817e4Smiod   if (rel->addend != 0
154*3d8817e4Smiod       || rel->howto == NULL
155*3d8817e4Smiod       || rel->howto->rightshift != 0
156*3d8817e4Smiod       || rel->howto->size != 2
157*3d8817e4Smiod       || rel->howto->bitsize != 32
158*3d8817e4Smiod       || rel->howto->bitpos != 0
159*3d8817e4Smiod       || rel->howto->src_mask != 0xffffffff
160*3d8817e4Smiod       || rel->howto->dst_mask != 0xffffffff)
161*3d8817e4Smiod     {
162*3d8817e4Smiod       bfd_set_error (bfd_error_invalid_operation);
163*3d8817e4Smiod       return FALSE;
164*3d8817e4Smiod     }
165*3d8817e4Smiod 
166*3d8817e4Smiod   sym = *rel->sym_ptr_ptr;
167*3d8817e4Smiod 
168*3d8817e4Smiod   /* The value we write out is the offset into the appropriate
169*3d8817e4Smiod      segment.  This offset is the section vma, adjusted by the vma of
170*3d8817e4Smiod      the lowest section in that segment, plus the address of the
171*3d8817e4Smiod      relocation.  */
172*3d8817e4Smiod   val = bfd_get_section_vma (abfd, sec) + rel->address;
173*3d8817e4Smiod 
174*3d8817e4Smiod   /* The second most significant bit is 0 if the value is an offset
175*3d8817e4Smiod      into the data segment, or 1 if the value is an offset into the
176*3d8817e4Smiod      code segment.  */
177*3d8817e4Smiod   if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
178*3d8817e4Smiod     {
179*3d8817e4Smiod       val -= nlm_get_text_low (abfd);
180*3d8817e4Smiod       val |= NLM_HIBIT >> 1;
181*3d8817e4Smiod     }
182*3d8817e4Smiod   else
183*3d8817e4Smiod     val -= nlm_get_data_low (abfd);
184*3d8817e4Smiod 
185*3d8817e4Smiod   if (! bfd_is_und_section (bfd_get_section (sym)))
186*3d8817e4Smiod     {
187*3d8817e4Smiod       /* NetWare only supports absolute internal relocs.  */
188*3d8817e4Smiod       if (rel->howto->pc_relative)
189*3d8817e4Smiod 	{
190*3d8817e4Smiod 	  bfd_set_error (bfd_error_invalid_operation);
191*3d8817e4Smiod 	  return FALSE;
192*3d8817e4Smiod 	}
193*3d8817e4Smiod 
194*3d8817e4Smiod       /* The high bit is 1 if the reloc is against the code section, 0
195*3d8817e4Smiod 	 if against the data section.  */
196*3d8817e4Smiod       if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
197*3d8817e4Smiod 	val |= NLM_HIBIT;
198*3d8817e4Smiod     }
199*3d8817e4Smiod   else
200*3d8817e4Smiod     {
201*3d8817e4Smiod       /* The high bit is 1 if this is an absolute reloc, 0 if it is PC
202*3d8817e4Smiod 	 relative.  */
203*3d8817e4Smiod       if (! rel->howto->pc_relative)
204*3d8817e4Smiod 	val |= NLM_HIBIT;
205*3d8817e4Smiod       else
206*3d8817e4Smiod 	{
207*3d8817e4Smiod 	  /* PC relative relocs on NetWare must be pcrel_offset.  */
208*3d8817e4Smiod 	  if (! rel->howto->pcrel_offset)
209*3d8817e4Smiod 	    {
210*3d8817e4Smiod 	      bfd_set_error (bfd_error_invalid_operation);
211*3d8817e4Smiod 	      return FALSE;
212*3d8817e4Smiod 	    }
213*3d8817e4Smiod 	}
214*3d8817e4Smiod     }
215*3d8817e4Smiod 
216*3d8817e4Smiod   bfd_put_32 (abfd, val, temp);
217*3d8817e4Smiod   if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
218*3d8817e4Smiod     return FALSE;
219*3d8817e4Smiod 
220*3d8817e4Smiod   return TRUE;
221*3d8817e4Smiod }
222*3d8817e4Smiod 
223*3d8817e4Smiod /* I want to be able to use objcopy to turn an i386 a.out or COFF file
224*3d8817e4Smiod    into a NetWare i386 module.  That means that the relocs from the
225*3d8817e4Smiod    source file have to be mapped into relocs that apply to the target
226*3d8817e4Smiod    file.  This function is called by nlm_set_section_contents to give
227*3d8817e4Smiod    it a chance to rework the relocs.
228*3d8817e4Smiod 
229*3d8817e4Smiod    This is actually a fairly general concept.  However, this is not a
230*3d8817e4Smiod    general implementation.  */
231*3d8817e4Smiod 
232*3d8817e4Smiod static bfd_boolean
nlm_i386_mangle_relocs(bfd * abfd,asection * sec,const PTR data,bfd_vma offset,bfd_size_type count)233*3d8817e4Smiod nlm_i386_mangle_relocs (bfd *abfd,
234*3d8817e4Smiod 			asection *sec,
235*3d8817e4Smiod 			const PTR data,
236*3d8817e4Smiod 			bfd_vma offset,
237*3d8817e4Smiod 			bfd_size_type count)
238*3d8817e4Smiod {
239*3d8817e4Smiod   arelent **rel_ptr_ptr, **rel_end;
240*3d8817e4Smiod 
241*3d8817e4Smiod   rel_ptr_ptr = sec->orelocation;
242*3d8817e4Smiod   rel_end = rel_ptr_ptr + sec->reloc_count;
243*3d8817e4Smiod   for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
244*3d8817e4Smiod     {
245*3d8817e4Smiod       arelent *rel;
246*3d8817e4Smiod       asymbol *sym;
247*3d8817e4Smiod       bfd_vma addend;
248*3d8817e4Smiod 
249*3d8817e4Smiod       rel = *rel_ptr_ptr;
250*3d8817e4Smiod       sym = *rel->sym_ptr_ptr;
251*3d8817e4Smiod 
252*3d8817e4Smiod       /* Note that no serious harm will ensue if we fail to change a
253*3d8817e4Smiod 	 reloc.  We will wind up failing in nlm_i386_write_import.  */
254*3d8817e4Smiod 
255*3d8817e4Smiod       /* Make sure this reloc is within the data we have.  We only 4
256*3d8817e4Smiod 	 byte relocs here, so we insist on having 4 bytes.  */
257*3d8817e4Smiod       if (rel->address < offset
258*3d8817e4Smiod 	  || rel->address + 4 > offset + count)
259*3d8817e4Smiod 	continue;
260*3d8817e4Smiod 
261*3d8817e4Smiod       /* NetWare doesn't support reloc addends, so we get rid of them
262*3d8817e4Smiod 	 here by simply adding them into the object data.  We handle
263*3d8817e4Smiod 	 the symbol value, if any, the same way.  */
264*3d8817e4Smiod       addend = rel->addend + sym->value;
265*3d8817e4Smiod 
266*3d8817e4Smiod       /* The value of a symbol is the offset into the section.  If the
267*3d8817e4Smiod 	 symbol is in the .bss segment, we need to include the size of
268*3d8817e4Smiod 	 the data segment in the offset as well.  Fortunately, we know
269*3d8817e4Smiod 	 that at this point the size of the data section is in the NLM
270*3d8817e4Smiod 	 header.  */
271*3d8817e4Smiod       if (((bfd_get_section_flags (abfd, bfd_get_section (sym))
272*3d8817e4Smiod 	    & SEC_LOAD) == 0)
273*3d8817e4Smiod 	  && ((bfd_get_section_flags (abfd, bfd_get_section (sym))
274*3d8817e4Smiod 	       & SEC_ALLOC) != 0))
275*3d8817e4Smiod 	addend += nlm_fixed_header (abfd)->dataImageSize;
276*3d8817e4Smiod 
277*3d8817e4Smiod       if (addend != 0
278*3d8817e4Smiod 	  && rel->howto != NULL
279*3d8817e4Smiod 	  && rel->howto->rightshift == 0
280*3d8817e4Smiod 	  && rel->howto->size == 2
281*3d8817e4Smiod 	  && rel->howto->bitsize == 32
282*3d8817e4Smiod 	  && rel->howto->bitpos == 0
283*3d8817e4Smiod 	  && rel->howto->src_mask == 0xffffffff
284*3d8817e4Smiod 	  && rel->howto->dst_mask == 0xffffffff)
285*3d8817e4Smiod 	{
286*3d8817e4Smiod 	  bfd_vma val;
287*3d8817e4Smiod 
288*3d8817e4Smiod 	  val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
289*3d8817e4Smiod 	  val += addend;
290*3d8817e4Smiod 	  bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
291*3d8817e4Smiod 	  rel->addend = 0;
292*3d8817e4Smiod 	}
293*3d8817e4Smiod 
294*3d8817e4Smiod       /* NetWare uses a reloc with pcrel_offset set.  We adjust
295*3d8817e4Smiod 	 pc_relative relocs accordingly.  We are going to change the
296*3d8817e4Smiod 	 howto field, so we can only do this if the current one is
297*3d8817e4Smiod 	 compatible.  We should check special_function here, but at
298*3d8817e4Smiod 	 the moment coff-i386 uses a special_function which does not
299*3d8817e4Smiod 	 affect what we are doing here.  */
300*3d8817e4Smiod       if (rel->howto != NULL
301*3d8817e4Smiod 	  && rel->howto->pc_relative
302*3d8817e4Smiod 	  && ! rel->howto->pcrel_offset
303*3d8817e4Smiod 	  && rel->howto->rightshift == 0
304*3d8817e4Smiod 	  && rel->howto->size == 2
305*3d8817e4Smiod 	  && rel->howto->bitsize == 32
306*3d8817e4Smiod 	  && rel->howto->bitpos == 0
307*3d8817e4Smiod 	  && rel->howto->src_mask == 0xffffffff
308*3d8817e4Smiod 	  && rel->howto->dst_mask == 0xffffffff)
309*3d8817e4Smiod 	{
310*3d8817e4Smiod 	  bfd_vma val;
311*3d8817e4Smiod 
312*3d8817e4Smiod 	  /* When pcrel_offset is not set, it means that the negative
313*3d8817e4Smiod 	     of the address of the memory location is stored in the
314*3d8817e4Smiod 	     memory location.  We must add it back in.  */
315*3d8817e4Smiod 	  val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
316*3d8817e4Smiod 	  val += rel->address;
317*3d8817e4Smiod 	  bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
318*3d8817e4Smiod 
319*3d8817e4Smiod 	  rel->howto = &nlm_i386_pcrel_howto;
320*3d8817e4Smiod 	}
321*3d8817e4Smiod     }
322*3d8817e4Smiod 
323*3d8817e4Smiod   return TRUE;
324*3d8817e4Smiod }
325*3d8817e4Smiod 
326*3d8817e4Smiod /* Read a NetWare i386 import record.  */
327*3d8817e4Smiod 
328*3d8817e4Smiod static bfd_boolean
nlm_i386_read_import(bfd * abfd,nlmNAME (symbol_type)* sym)329*3d8817e4Smiod nlm_i386_read_import (bfd * abfd, nlmNAME (symbol_type) * sym)
330*3d8817e4Smiod {
331*3d8817e4Smiod   struct nlm_relent *nlm_relocs;	/* Relocation records for symbol.  */
332*3d8817e4Smiod   bfd_size_type rcount;			/* Number of relocs.  */
333*3d8817e4Smiod   bfd_byte temp[NLM_TARGET_LONG_SIZE];	/* Temporary 32-bit value.  */
334*3d8817e4Smiod   unsigned char symlength;		/* Length of symbol name.  */
335*3d8817e4Smiod   char *name;
336*3d8817e4Smiod 
337*3d8817e4Smiod   if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
338*3d8817e4Smiod       != sizeof (symlength))
339*3d8817e4Smiod     return FALSE;
340*3d8817e4Smiod   sym -> symbol.the_bfd = abfd;
341*3d8817e4Smiod   name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
342*3d8817e4Smiod   if (name == NULL)
343*3d8817e4Smiod     return FALSE;
344*3d8817e4Smiod   if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
345*3d8817e4Smiod     return FALSE;
346*3d8817e4Smiod   name[symlength] = '\0';
347*3d8817e4Smiod   sym -> symbol.name = name;
348*3d8817e4Smiod   sym -> symbol.flags = 0;
349*3d8817e4Smiod   sym -> symbol.value = 0;
350*3d8817e4Smiod   sym -> symbol.section = bfd_und_section_ptr;
351*3d8817e4Smiod   if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
352*3d8817e4Smiod     return FALSE;
353*3d8817e4Smiod   rcount = H_GET_32 (abfd, temp);
354*3d8817e4Smiod   nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
355*3d8817e4Smiod   if (!nlm_relocs)
356*3d8817e4Smiod     return FALSE;
357*3d8817e4Smiod   sym -> relocs = nlm_relocs;
358*3d8817e4Smiod   sym -> rcnt = 0;
359*3d8817e4Smiod   while (sym -> rcnt < rcount)
360*3d8817e4Smiod     {
361*3d8817e4Smiod       asection *section;
362*3d8817e4Smiod 
363*3d8817e4Smiod       if (! nlm_i386_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
364*3d8817e4Smiod 	return FALSE;
365*3d8817e4Smiod       nlm_relocs -> section = section;
366*3d8817e4Smiod       nlm_relocs++;
367*3d8817e4Smiod       sym -> rcnt++;
368*3d8817e4Smiod     }
369*3d8817e4Smiod   return TRUE;
370*3d8817e4Smiod }
371*3d8817e4Smiod 
372*3d8817e4Smiod /* Write out an external reference.  */
373*3d8817e4Smiod 
374*3d8817e4Smiod static bfd_boolean
nlm_i386_write_external(bfd * abfd,bfd_size_type count,asymbol * sym,struct reloc_and_sec * relocs)375*3d8817e4Smiod nlm_i386_write_external (bfd *abfd,
376*3d8817e4Smiod 			 bfd_size_type count,
377*3d8817e4Smiod 			 asymbol *sym,
378*3d8817e4Smiod 			 struct reloc_and_sec *relocs)
379*3d8817e4Smiod {
380*3d8817e4Smiod   unsigned int i;
381*3d8817e4Smiod   bfd_byte len;
382*3d8817e4Smiod   unsigned char temp[NLM_TARGET_LONG_SIZE];
383*3d8817e4Smiod 
384*3d8817e4Smiod   len = strlen (sym->name);
385*3d8817e4Smiod   if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
386*3d8817e4Smiod        != sizeof (bfd_byte))
387*3d8817e4Smiod       || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
388*3d8817e4Smiod     return FALSE;
389*3d8817e4Smiod 
390*3d8817e4Smiod   bfd_put_32 (abfd, count, temp);
391*3d8817e4Smiod   if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
392*3d8817e4Smiod     return FALSE;
393*3d8817e4Smiod 
394*3d8817e4Smiod   for (i = 0; i < count; i++)
395*3d8817e4Smiod     if (! nlm_i386_write_import (abfd, relocs[i].sec, relocs[i].rel))
396*3d8817e4Smiod       return FALSE;
397*3d8817e4Smiod 
398*3d8817e4Smiod   return TRUE;
399*3d8817e4Smiod }
400*3d8817e4Smiod 
401*3d8817e4Smiod #include "nlmswap.h"
402*3d8817e4Smiod 
403*3d8817e4Smiod static const struct nlm_backend_data nlm32_i386_backend =
404*3d8817e4Smiod {
405*3d8817e4Smiod   "NetWare Loadable Module\032",
406*3d8817e4Smiod   sizeof (Nlm32_i386_External_Fixed_Header),
407*3d8817e4Smiod   0,	/* Optional_prefix_size.  */
408*3d8817e4Smiod   bfd_arch_i386,
409*3d8817e4Smiod   0,
410*3d8817e4Smiod   FALSE,
411*3d8817e4Smiod   0,	/* Backend_object_p.  */
412*3d8817e4Smiod   0,	/* Write_prefix_func.  */
413*3d8817e4Smiod   nlm_i386_read_reloc,
414*3d8817e4Smiod   nlm_i386_mangle_relocs,
415*3d8817e4Smiod   nlm_i386_read_import,
416*3d8817e4Smiod   nlm_i386_write_import,
417*3d8817e4Smiod   0,	/* Set_public_section.  */
418*3d8817e4Smiod   0,	/* Set_public_offset.  */
419*3d8817e4Smiod   nlm_swap_fixed_header_in,
420*3d8817e4Smiod   nlm_swap_fixed_header_out,
421*3d8817e4Smiod   nlm_i386_write_external,
422*3d8817e4Smiod   0,	/* Write_export.  */
423*3d8817e4Smiod };
424*3d8817e4Smiod 
425*3d8817e4Smiod #define TARGET_LITTLE_NAME		"nlm32-i386"
426*3d8817e4Smiod #define TARGET_LITTLE_SYM		nlmNAME (i386_vec)
427*3d8817e4Smiod #define TARGET_BACKEND_DATA		& nlm32_i386_backend
428*3d8817e4Smiod 
429*3d8817e4Smiod #include "nlm-target.h"
430