1 /* Support for 32-bit Alpha NLM (NetWare Loadable Module)
2    Copyright 1993, 1994, 2000, 2001, 2002, 2003, 2004, 2005
3    Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support.
5 
6    This file is part of BFD, the Binary File Descriptor library.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21 
22 /* This file describes the 32 bit Alpha NLM format.  You might think
23    that an Alpha chip would use a 64 bit format, but, for some reason,
24    it doesn't.  */
25 
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "libbfd.h"
29 
30 #define ARCH_SIZE 32
31 
32 #include "nlm/alpha-ext.h"
33 #define Nlm_External_Fixed_Header	Nlm32_alpha_External_Fixed_Header
34 
35 #include "libnlm.h"
36 
37 /* Alpha NLM's have a prefix header before the standard NLM.  This
38    function reads it in, verifies the version, and seeks the bfd to
39    the location before the regular NLM header.  */
40 
41 static bfd_boolean
42 nlm_alpha_backend_object_p (bfd *abfd)
43 {
44   struct nlm32_alpha_external_prefix_header s;
45   file_ptr size;
46 
47   if (bfd_bread (&s, (bfd_size_type) sizeof s, abfd) != sizeof s)
48     return FALSE;
49 
50   if (H_GET_32 (abfd, s.magic) != NLM32_ALPHA_MAGIC)
51     return FALSE;
52 
53   /* FIXME: Should we check the format number?  */
54 
55   /* Skip to the end of the header.  */
56   size = H_GET_32 (abfd, s.size);
57   if (bfd_seek (abfd, size, SEEK_SET) != 0)
58     return FALSE;
59 
60   return TRUE;
61 }
62 
63 /* Write out the prefix.  */
64 
65 static bfd_boolean
66 nlm_alpha_write_prefix (bfd *abfd)
67 {
68   struct nlm32_alpha_external_prefix_header s;
69 
70   memset (&s, 0, sizeof s);
71   H_PUT_32 (abfd, NLM32_ALPHA_MAGIC, s.magic);
72   H_PUT_32 (abfd, 2, s.format);
73   H_PUT_32 (abfd, sizeof s, s.size);
74   if (bfd_bwrite (&s, (bfd_size_type) sizeof s, abfd) != sizeof s)
75     return FALSE;
76   return TRUE;
77 }
78 
79 #define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1)
80 
81 /* How to process the various reloc types.  */
82 
83 static reloc_howto_type nlm32_alpha_howto_table[] =
84 {
85   /* Reloc type 0 is ignored by itself.  However, it appears after a
86      GPDISP reloc to identify the location where the low order 16 bits
87      of the gp register are loaded.  */
88   HOWTO (ALPHA_R_IGNORE,	/* Type.  */
89 	 0,			/* Rightshift.  */
90 	 0,			/* Size (0 = byte, 1 = short, 2 = long).  */
91 	 8,			/* Bitsize.  */
92 	 FALSE,			/* PC_relative.  */
93 	 0,			/* Bitpos.  */
94 	 complain_overflow_dont, /* Complain_on_overflow.  */
95 	 0,			/* Special_function.  */
96 	 "IGNORE",		/* Name.  */
97 	 FALSE,			/* Partial_inplace.  */
98 	 0,			/* Source mask.  */
99 	 0,			/* Dest mask.  */
100 	 FALSE),		/* PCrel_offset.  */
101 
102   /* A 32 bit reference to a symbol.  */
103   HOWTO (ALPHA_R_REFLONG,	/* Type.  */
104 	 0,			/* Rightshift.  */
105 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
106 	 32,			/* Bitsize.  */
107 	 FALSE,			/* PC_relative.  */
108 	 0,			/* Bitpos.  */
109 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
110 	 0,			/* Special_function.  */
111 	 "REFLONG",		/* Name.  */
112 	 TRUE,			/* Partial_inplace.  */
113 	 0xffffffff,		/* Source mask.  */
114 	 0xffffffff,		/* Dest mask.  */
115 	 FALSE),		/* PCrel_offset.  */
116 
117   /* A 64 bit reference to a symbol.  */
118   HOWTO (ALPHA_R_REFQUAD,	/* Type.  */
119 	 0,			/* Rightshift.  */
120 	 4,			/* Size (0 = byte, 1 = short, 2 = long).  */
121 	 64,			/* Bitsize.  */
122 	 FALSE,			/* PC_relative.  */
123 	 0,			/* Bitpos.  */
124 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
125 	 0,			/* Special_function.  */
126 	 "REFQUAD",		/* Name.  */
127 	 TRUE,			/* Partial_inplace.  */
128 	 ONES (64),		/* Source mask.  */
129 	 ONES (64),		/* Dest mask.  */
130 	 FALSE),		/* PCrel_offset.  */
131 
132   /* A 32 bit GP relative offset.  This is just like REFLONG except
133      that when the value is used the value of the gp register will be
134      added in.  */
135   HOWTO (ALPHA_R_GPREL32,	/* Type.  */
136 	 0,			/* Rightshift.  */
137 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
138 	 32,			/* Bitsize.  */
139 	 FALSE,			/* PC_relative.  */
140 	 0,			/* Bitpos.  */
141 	 complain_overflow_bitfield, /* Complain_on_overflow.  */
142 	 0,			/* Special_function.  */
143 	 "GPREL32",		/* Name.  */
144 	 TRUE,			/* Partial_inplace.  */
145 	 0xffffffff,		/* Source mask.  */
146 	 0xffffffff,		/* Dest mask.  */
147 	 FALSE),		/* PCrel_offset.  */
148 
149   /* Used for an instruction that refers to memory off the GP
150      register.  The offset is 16 bits of the 32 bit instruction.  This
151      reloc always seems to be against the .lita section.  */
152   HOWTO (ALPHA_R_LITERAL,	/* Type.  */
153 	 0,			/* Rightshift.  */
154 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
155 	 16,			/* Bitsize.  */
156 	 FALSE,			/* PC_relative.  */
157 	 0,			/* Bitpos.  */
158 	 complain_overflow_signed, /* Complain_on_overflow.  */
159 	 0,			/* Special_function.  */
160 	 "LITERAL",		/* Name.  */
161 	 TRUE,			/* Partial_inplace.  */
162 	 0xffff,		/* Source mask.  */
163 	 0xffff,		/* Dest mask.  */
164 	 FALSE),		/* PCrel_offset.  */
165 
166   /* This reloc only appears immediately following a LITERAL reloc.
167      It identifies a use of the literal.  It seems that the linker can
168      use this to eliminate a portion of the .lita section.  The symbol
169      index is special: 1 means the literal address is in the base
170      register of a memory format instruction; 2 means the literal
171      address is in the byte offset register of a byte-manipulation
172      instruction; 3 means the literal address is in the target
173      register of a jsr instruction.  This does not actually do any
174      relocation.  */
175   HOWTO (ALPHA_R_LITUSE,	/* Type.  */
176 	 0,			/* Rightshift.  */
177 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
178 	 32,			/* Bitsize.  */
179 	 FALSE,			/* PC_relative.  */
180 	 0,			/* Bitpos.  */
181 	 complain_overflow_dont, /* Complain_on_overflow.  */
182 	 0,			/* Special_function.  */
183 	 "LITUSE",		/* Name.  */
184 	 FALSE,			/* Partial_inplace.  */
185 	 0,			/* Source mask.  */
186 	 0,			/* Dest mask.  */
187 	 FALSE),		/* PCrel_offset.  */
188 
189   /* Load the gp register.  This is always used for a ldah instruction
190      which loads the upper 16 bits of the gp register.  The next reloc
191      will be an IGNORE reloc which identifies the location of the lda
192      instruction which loads the lower 16 bits.  The symbol index of
193      the GPDISP instruction appears to actually be the number of bytes
194      between the ldah and lda instructions.  This gives two different
195      ways to determine where the lda instruction is; I don't know why
196      both are used.  The value to use for the relocation is the
197      difference between the GP value and the current location; the
198      load will always be done against a register holding the current
199      address.  */
200   HOWTO (ALPHA_R_GPDISP,	/* Type.  */
201 	 16,			/* Rightshift.  */
202 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
203 	 16,			/* Bitsize.  */
204 	 TRUE,			/* PC_relative.  */
205 	 0,			/* Bitpos.  */
206 	 complain_overflow_dont, /* Complain_on_overflow.  */
207 	 0,			/* Special_function.  */
208 	 "GPDISP",		/* Name.  */
209 	 TRUE,			/* Partial_inplace.  */
210 	 0xffff,		/* Source mask.  */
211 	 0xffff,		/* Dest mask.  */
212 	 TRUE),			/* PCrel_offset.  */
213 
214   /* A 21 bit branch.  The native assembler generates these for
215      branches within the text segment, and also fills in the PC
216      relative offset in the instruction.  It seems to me that this
217      reloc, unlike the others, is not partial_inplace.  */
218   HOWTO (ALPHA_R_BRADDR,	/* Type.  */
219 	 2,			/* Rightshift.  */
220 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
221 	 21,			/* Bitsize.  */
222 	 TRUE,			/* PC_relative.  */
223 	 0,			/* Bitpos.  */
224 	 complain_overflow_signed, /* Complain_on_overflow.  */
225 	 0,			/* Special_function.  */
226 	 "BRADDR",		/* Name.  */
227 	 FALSE,			/* Partial_inplace.  */
228 	 0,			/* Source mask.  */
229 	 0x1fffff,		/* Dest mask.  */
230 	 FALSE),		/* PCrel_offset.  */
231 
232   /* A hint for a jump to a register.  */
233   HOWTO (ALPHA_R_HINT,		/* Type.  */
234 	 2,			/* Rightshift.  */
235 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
236 	 14,			/* Bitsize.  */
237 	 FALSE,			/* PC_relative.  */
238 	 0,			/* Bitpos.  */
239 	 complain_overflow_dont, /* Complain_on_overflow.  */
240 	 0,			/* Special_function.  */
241 	 "HINT",		/* Name.  */
242 	 TRUE,			/* Partial_inplace.  */
243 	 0x3fff,		/* Source mask.  */
244 	 0x3fff,		/* Dest mask.  */
245 	 FALSE),		/* PCrel_offset.  */
246 
247   /* 16 bit PC relative offset.  */
248   HOWTO (ALPHA_R_SREL16,	/* Type.  */
249 	 0,			/* Rightshift.  */
250 	 1,			/* Size (0 = byte, 1 = short, 2 = long).  */
251 	 16,			/* Bitsize.  */
252 	 TRUE,			/* PC_relative.  */
253 	 0,			/* Bitpos.  */
254 	 complain_overflow_signed, /* Complain_on_overflow.  */
255 	 0,			/* Special_function.  */
256 	 "SREL16",		/* Name.  */
257 	 TRUE,			/* Partial_inplace.  */
258 	 0xffff,		/* Source mask.  */
259 	 0xffff,		/* Dest mask.  */
260 	 FALSE),		/* PCrel_offset.  */
261 
262   /* 32 bit PC relative offset.  */
263   HOWTO (ALPHA_R_SREL32,	/* Type.  */
264 	 0,			/* Rightshift.  */
265 	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
266 	 32,			/* Bitsize.  */
267 	 TRUE,			/* PC_relative.  */
268 	 0,			/* Bitpos.  */
269 	 complain_overflow_signed, /* Complain_on_overflow.  */
270 	 0,			/* Special_function.  */
271 	 "SREL32",		/* Name.  */
272 	 TRUE,			/* Partial_inplace.  */
273 	 0xffffffff,		/* Source mask.  */
274 	 0xffffffff,		/* Dest mask.  */
275 	 FALSE),		/* PCrel_offset.  */
276 
277   /* A 64 bit PC relative offset.  */
278   HOWTO (ALPHA_R_SREL64,	/* Type.  */
279 	 0,			/* Rightshift.  */
280 	 4,			/* Size (0 = byte, 1 = short, 2 = long).  */
281 	 64,			/* Bitsize.  */
282 	 TRUE,			/* PC_relative.  */
283 	 0,			/* Bitpos.  */
284 	 complain_overflow_signed, /* Complain_on_overflow.  */
285 	 0,			/* Special_function.  */
286 	 "SREL64",		/* Name.  */
287 	 TRUE,			/* Partial_inplace.  */
288 	 ONES (64),		/* Source mask.  */
289 	 ONES (64),		/* Dest mask.  */
290 	 FALSE),		/* PCrel_offset.  */
291 
292   /* Push a value on the reloc evaluation stack.  */
293   HOWTO (ALPHA_R_OP_PUSH,	/* Type.  */
294 	 0,			/* Rightshift.  */
295 	 0,			/* Size (0 = byte, 1 = short, 2 = long).  */
296 	 0,			/* Bitsize.  */
297 	 FALSE,			/* PC_relative.  */
298 	 0,			/* Bitpos.  */
299 	 complain_overflow_dont, /* Complain_on_overflow.  */
300 	 0,			/* Special_function.  */
301 	 "OP_PUSH",		/* Name.  */
302 	 FALSE,			/* Partial_inplace.  */
303 	 0,			/* Source mask.  */
304 	 0,			/* Dest mask.  */
305 	 FALSE),		/* PCrel_offset.  */
306 
307   /* Store the value from the stack at the given address.  Store it in
308      a bitfield of size r_size starting at bit position r_offset.  */
309   HOWTO (ALPHA_R_OP_STORE,	/* Type.  */
310 	 0,			/* Rightshift.  */
311 	 4,			/* Size (0 = byte, 1 = short, 2 = long).  */
312 	 64,			/* Bitsize.  */
313 	 FALSE,			/* PC_relative.  */
314 	 0,			/* Bitpos.  */
315 	 complain_overflow_dont, /* Complain_on_overflow.  */
316 	 0,			/* Special_function.  */
317 	 "OP_STORE",		/* Name.  */
318 	 FALSE,			/* Partial_inplace.  */
319 	 0,			/* Source mask.  */
320 	 ONES (64),		/* Dest mask.  */
321 	 FALSE),		/* PCrel_offset.  */
322 
323   /* Subtract the reloc address from the value on the top of the
324      relocation stack.  */
325   HOWTO (ALPHA_R_OP_PSUB,	/* Type.  */
326 	 0,			/* Rightshift.  */
327 	 0,			/* Size (0 = byte, 1 = short, 2 = long).  */
328 	 0,			/* Bitsize.  */
329 	 FALSE,			/* PC_relative.  */
330 	 0,			/* Bitpos.  */
331 	 complain_overflow_dont, /* Complain_on_overflow.  */
332 	 0,			/* Special_function.  */
333 	 "OP_PSUB",		/* Name.  */
334 	 FALSE,			/* Partial_inplace.  */
335 	 0,			/* Source mask.  */
336 	 0,			/* Dest mask.  */
337 	 FALSE),		/* PCrel_offset.  */
338 
339   /* Shift the value on the top of the relocation stack right by the
340      given value.  */
341   HOWTO (ALPHA_R_OP_PRSHIFT,	/* Type.  */
342 	 0,			/* Rightshift.  */
343 	 0,			/* Size (0 = byte, 1 = short, 2 = long).  */
344 	 0,			/* Bitsize.  */
345 	 FALSE,			/* PC_relative.  */
346 	 0,			/* Bitpos.  */
347 	 complain_overflow_dont, /* Complain_on_overflow.  */
348 	 0,			 /* Special_function.  */
349 	 "OP_PRSHIFT",		/* Name.  */
350 	 FALSE,			/* Partial_inplace.  */
351 	 0,			/* Source mask.  */
352 	 0,			/* Dest mask.  */
353 	 FALSE),		/* PCrel_offset.  */
354 
355   /* Adjust the GP value for a new range in the object file.  */
356   HOWTO (ALPHA_R_GPVALUE,	/* Type.  */
357 	 0,			/* Rightshift.  */
358 	 0,			/* Size (0 = byte, 1 = short, 2 = long).  */
359 	 0,			/* Bitsize.  */
360 	 FALSE,			/* PC_relative.  */
361 	 0,			/* Bitpos.  */
362 	 complain_overflow_dont, /* Complain_on_overflow.  */
363 	 0,			/* Special_function.  */
364 	 "GPVALUE",		/* Name.  */
365 	 FALSE,			/* Partial_inplace.  */
366 	 0,			/* Source mask.  */
367 	 0,			/* Dest mask.  */
368 	 FALSE)			/* PCrel_offset.  */
369 };
370 
371 static reloc_howto_type nlm32_alpha_nw_howto =
372   HOWTO (ALPHA_R_NW_RELOC,	/* Type.  */
373 	 0,			/* Rightshift.  */
374 	 0,			/* Size (0 = byte, 1 = short, 2 = long).  */
375 	 0,			/* Bitsize.  */
376 	 FALSE,			/* PC_relative.  */
377 	 0,			/* Bitpos.  */
378 	 complain_overflow_dont, /* Complain_on_overflow.  */
379 	 0,			/* Special_function.  */
380 	 "NW_RELOC",		/* Name.  */
381 	 FALSE,			/* Partial_inplace.  */
382 	 0,			/* Source mask.  */
383 	 0,			/* Dest mask.  */
384 	 FALSE);		/* PCrel_offset.  */
385 
386 /* Read an Alpha NLM reloc.  This routine keeps some static data which
387    it uses when handling local relocs.  This only works correctly
388    because all the local relocs are read at once.  */
389 
390 static bfd_boolean
391 nlm_alpha_read_reloc (bfd *abfd,
392 		      nlmNAME (symbol_type) *sym,
393 		      asection **secp,
394 		      arelent *rel)
395 {
396   static bfd_vma gp_value;
397   static bfd_vma lita_address;
398   struct nlm32_alpha_external_reloc ext;
399   bfd_vma r_vaddr;
400   long r_symndx;
401   int r_type, r_extern, r_offset, r_size;
402   asection *code_sec, *data_sec;
403 
404   /* Read the reloc from the file.  */
405   if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
406     return FALSE;
407 
408   /* Swap in the reloc information.  */
409   r_vaddr = H_GET_64 (abfd, ext.r_vaddr);
410   r_symndx = H_GET_32 (abfd, ext.r_symndx);
411 
412   BFD_ASSERT (bfd_little_endian (abfd));
413 
414   r_type = ((ext.r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
415 	    >> RELOC_BITS0_TYPE_SH_LITTLE);
416   r_extern = (ext.r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
417   r_offset = ((ext.r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
418 	      >> RELOC_BITS1_OFFSET_SH_LITTLE);
419   /* Ignore the reserved bits.  */
420   r_size = ((ext.r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
421 	    >> RELOC_BITS3_SIZE_SH_LITTLE);
422 
423   /* Fill in the BFD arelent structure.  */
424   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
425   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
426   if (r_extern)
427     {
428       /* External relocations are only used for imports.  */
429       BFD_ASSERT (sym != NULL);
430       /* We don't need to set sym_ptr_ptr for this case.  It is set in
431 	 nlm_canonicalize_reloc.  */
432       rel->sym_ptr_ptr = NULL;
433       rel->addend = 0;
434     }
435   else
436     {
437       /* Internal relocations are only used for local relocation
438 	 fixups.  If they are not NW_RELOC or GPDISP or IGNORE, they
439 	 must be against .text or .data.  */
440       BFD_ASSERT (r_type == ALPHA_R_NW_RELOC || sym == NULL);
441       if (r_type == ALPHA_R_NW_RELOC
442 	  || r_type == ALPHA_R_GPDISP
443 	  || r_type == ALPHA_R_IGNORE)
444 	{
445 	  rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
446 	  rel->addend = 0;
447 	}
448       else if (r_symndx == ALPHA_RELOC_SECTION_TEXT)
449 	{
450 	  rel->sym_ptr_ptr = code_sec->symbol_ptr_ptr;
451 	  BFD_ASSERT (bfd_get_section_vma (abfd, code_sec) == 0);
452 	  rel->addend = 0;
453 	}
454       else if (r_symndx == ALPHA_RELOC_SECTION_DATA)
455 	{
456 	  rel->sym_ptr_ptr = data_sec->symbol_ptr_ptr;
457 	  rel->addend = - bfd_get_section_vma (abfd, data_sec);
458 	}
459       else
460 	{
461 	  BFD_ASSERT (0);
462 	  rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
463 	  rel->addend = 0;
464 	}
465     }
466 
467   /* We use the address to determine whether the reloc is in the .text
468      or .data section.  R_NW_RELOC relocs don't really have a section,
469      so we put them in .text.  */
470   if (r_type == ALPHA_R_NW_RELOC
471       || r_vaddr < code_sec->size)
472     {
473       *secp = code_sec;
474       rel->address = r_vaddr;
475     }
476   else
477     {
478       *secp = data_sec;
479       rel->address = r_vaddr - code_sec->size;
480     }
481 
482   /* We must adjust the addend based on the type.  */
483   BFD_ASSERT ((r_type >= 0 && r_type <= ALPHA_R_GPVALUE)
484 	      || r_type == ALPHA_R_NW_RELOC);
485 
486   switch (r_type)
487     {
488     case ALPHA_R_BRADDR:
489     case ALPHA_R_SREL16:
490     case ALPHA_R_SREL32:
491     case ALPHA_R_SREL64:
492       /* The PC relative relocs do not seem to use the section VMA as
493 	 a negative addend.  */
494       rel->addend = 0;
495       break;
496 
497     case ALPHA_R_GPREL32:
498       /* Copy the gp value for this object file into the addend, to
499 	 ensure that we are not confused by the linker.  */
500       if (! r_extern)
501 	rel->addend += gp_value;
502       break;
503 
504     case ALPHA_R_LITERAL:
505       BFD_ASSERT (! r_extern);
506       rel->addend += lita_address;
507       break;
508 
509     case ALPHA_R_LITUSE:
510     case ALPHA_R_GPDISP:
511       /* The LITUSE and GPDISP relocs do not use a symbol, or an
512 	 addend, but they do use a special code.  Put this code in the
513 	 addend field.  */
514       rel->addend = r_symndx;
515       rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
516       break;
517 
518     case ALPHA_R_OP_STORE:
519       /* The STORE reloc needs the size and offset fields.  We store
520 	 them in the addend.  */
521       BFD_ASSERT (r_offset < 256 && r_size < 256);
522       rel->addend = (r_offset << 8) + r_size;
523       break;
524 
525     case ALPHA_R_OP_PUSH:
526     case ALPHA_R_OP_PSUB:
527     case ALPHA_R_OP_PRSHIFT:
528       /* The PUSH, PSUB and PRSHIFT relocs do not actually use an
529 	 address.  I believe that the address supplied is really an
530 	 addend.  */
531       rel->addend = r_vaddr;
532       break;
533 
534     case ALPHA_R_GPVALUE:
535       /* Record the new gp value.  */
536       gp_value += r_symndx;
537       rel->addend = gp_value;
538       break;
539 
540     case ALPHA_R_IGNORE:
541       /* If the type is ALPHA_R_IGNORE, make sure this is a reference
542 	 to the absolute section so that the reloc is ignored.  For
543 	 some reason the address of this reloc type is not adjusted by
544 	 the section vma.  We record the gp value for this object file
545 	 here, for convenience when doing the GPDISP relocation.  */
546       rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
547       rel->address = r_vaddr;
548       rel->addend = gp_value;
549       break;
550 
551     case ALPHA_R_NW_RELOC:
552       /* If this is SETGP, we set the addend to 0.  Otherwise we set
553 	 the addend to the size of the .lita section (this is
554 	 r_symndx) plus 1.  We have already set the address of the
555 	 reloc to r_vaddr.  */
556       if (r_size == ALPHA_R_NW_RELOC_SETGP)
557 	{
558 	  gp_value = r_vaddr;
559 	  rel->addend = 0;
560 	}
561       else if (r_size == ALPHA_R_NW_RELOC_LITA)
562 	{
563 	  lita_address = r_vaddr;
564 	  rel->addend = r_symndx + 1;
565 	}
566       else
567 	BFD_ASSERT (0);
568       rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
569       break;
570 
571     default:
572       break;
573     }
574 
575   if (r_type == ALPHA_R_NW_RELOC)
576     rel->howto = &nlm32_alpha_nw_howto;
577   else
578     rel->howto = &nlm32_alpha_howto_table[r_type];
579 
580   return TRUE;
581 }
582 
583 /* Mangle Alpha NLM relocs for output.  */
584 
585 static bfd_boolean
586 nlm_alpha_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
587 			 asection *sec ATTRIBUTE_UNUSED,
588 			 const void * data ATTRIBUTE_UNUSED,
589 			 bfd_vma offset ATTRIBUTE_UNUSED,
590 			 bfd_size_type count ATTRIBUTE_UNUSED)
591 {
592   return TRUE;
593 }
594 
595 /* Read an ALPHA NLM import record.  */
596 
597 static bfd_boolean
598 nlm_alpha_read_import (bfd *abfd, nlmNAME (symbol_type) * sym)
599 {
600   struct nlm_relent *nlm_relocs;	/* Relocation records for symbol.  */
601   bfd_size_type rcount;			/* Number of relocs.  */
602   bfd_byte temp[NLM_TARGET_LONG_SIZE];	/* Temporary 32-bit value.  */
603   unsigned char symlength;		/* Length of symbol name.  */
604   char *name;
605   bfd_size_type amt;
606 
607   if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
608       != sizeof (symlength))
609     return FALSE;
610   sym -> symbol.the_bfd = abfd;
611   name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
612   if (name == NULL)
613     return FALSE;
614   if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
615     return FALSE;
616   name[symlength] = '\0';
617   sym -> symbol.name = name;
618   sym -> symbol.flags = 0;
619   sym -> symbol.value = 0;
620   sym -> symbol.section = bfd_und_section_ptr;
621   if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd)
622       != sizeof (temp))
623     return FALSE;
624   rcount = H_GET_32 (abfd, temp);
625   amt = rcount * sizeof (struct nlm_relent);
626   nlm_relocs = bfd_alloc (abfd, amt);
627   if (!nlm_relocs)
628     return FALSE;
629   sym -> relocs = nlm_relocs;
630   sym -> rcnt = 0;
631   while (sym -> rcnt < rcount)
632     {
633       asection *section;
634 
635       if (! nlm_alpha_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
636 	return FALSE;
637       nlm_relocs -> section = section;
638       nlm_relocs++;
639       sym -> rcnt++;
640     }
641 
642   return TRUE;
643 }
644 
645 /* Write an Alpha NLM reloc.  */
646 
647 static bfd_boolean
648 nlm_alpha_write_import (bfd * abfd, asection * sec, arelent * rel)
649 {
650   asymbol *sym;
651   bfd_vma r_vaddr;
652   long r_symndx;
653   int r_type, r_extern, r_offset, r_size;
654   struct nlm32_alpha_external_reloc ext;
655 
656   sym = *rel->sym_ptr_ptr;
657 
658   /* Get values for the relocation fields.  */
659   r_type = rel->howto->type;
660   if (r_type != ALPHA_R_NW_RELOC)
661     {
662       r_vaddr = bfd_get_section_vma (abfd, sec) + rel->address;
663       if ((sec->flags & SEC_CODE) == 0)
664 	r_vaddr += bfd_get_section_by_name (abfd, NLM_CODE_NAME) -> size;
665       if (bfd_is_und_section (bfd_get_section (sym)))
666 	{
667 	  r_extern = 1;
668 	  r_symndx = 0;
669 	}
670       else
671 	{
672 	  r_extern = 0;
673 	  if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
674 	    r_symndx = ALPHA_RELOC_SECTION_TEXT;
675 	  else
676 	    r_symndx = ALPHA_RELOC_SECTION_DATA;
677 	}
678       r_offset = 0;
679       r_size = 0;
680 
681       switch (r_type)
682 	{
683 	case ALPHA_R_LITUSE:
684 	case ALPHA_R_GPDISP:
685 	  r_symndx = rel->addend;
686 	  break;
687 
688 	case ALPHA_R_OP_STORE:
689 	  r_size = rel->addend & 0xff;
690 	  r_offset = (rel->addend >> 8) & 0xff;
691 	  break;
692 
693 	case ALPHA_R_OP_PUSH:
694 	case ALPHA_R_OP_PSUB:
695 	case ALPHA_R_OP_PRSHIFT:
696 	  r_vaddr = rel->addend;
697 	  break;
698 
699 	case ALPHA_R_IGNORE:
700 	  r_vaddr = rel->address;
701 	  break;
702 
703 	default:
704 	  break;
705 	}
706     }
707   else
708     {
709       /* r_type == ALPHA_R_NW_RELOC.  */
710       r_vaddr = rel->address;
711       if (rel->addend == 0)
712 	{
713 	  r_symndx = 0;
714 	  r_size = ALPHA_R_NW_RELOC_SETGP;
715 	}
716       else
717 	{
718 	  r_symndx = rel->addend - 1;
719 	  r_size = ALPHA_R_NW_RELOC_LITA;
720 	}
721       r_extern = 0;
722       r_offset = 0;
723     }
724 
725   /* Swap out the relocation fields.  */
726   H_PUT_64 (abfd, r_vaddr, ext.r_vaddr);
727   H_PUT_32 (abfd, r_symndx, ext.r_symndx);
728 
729   BFD_ASSERT (bfd_little_endian (abfd));
730 
731   ext.r_bits[0] = ((r_type << RELOC_BITS0_TYPE_SH_LITTLE)
732 		   & RELOC_BITS0_TYPE_LITTLE);
733   ext.r_bits[1] = ((r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0)
734 		   | ((r_offset << RELOC_BITS1_OFFSET_SH_LITTLE)
735 		      & RELOC_BITS1_OFFSET_LITTLE));
736   ext.r_bits[2] = 0;
737   ext.r_bits[3] = ((r_size << RELOC_BITS3_SIZE_SH_LITTLE)
738 		   & RELOC_BITS3_SIZE_LITTLE);
739 
740   /* Write out the relocation.  */
741   if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
742     return FALSE;
743 
744   return TRUE;
745 }
746 
747 /* Alpha NetWare does not use the high bit to determine whether a
748    public symbol is in the code segment or the data segment.  Instead,
749    it just uses the address.  The set_public_section and
750    get_public_offset routines override the default code which uses the
751    high bit.  */
752 
753 /* Set the section for a public symbol.  */
754 
755 static bfd_boolean
756 nlm_alpha_set_public_section (bfd * abfd, nlmNAME (symbol_type) * sym)
757 {
758   asection *code_sec, *data_sec;
759 
760   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
761   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
762   if (sym->symbol.value < code_sec->size)
763     {
764       sym->symbol.section = code_sec;
765       sym->symbol.flags |= BSF_FUNCTION;
766     }
767   else
768     {
769       sym->symbol.section = data_sec;
770       sym->symbol.value -= code_sec->size;
771       /* The data segment had better be aligned.  */
772       BFD_ASSERT ((code_sec->size & 0xf) == 0);
773     }
774   return TRUE;
775 }
776 
777 /* Get the offset to write out for a public symbol.  */
778 
779 static bfd_vma
780 nlm_alpha_get_public_offset (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym)
781 {
782   return bfd_asymbol_value (sym);
783 }
784 
785 /* Write an Alpha NLM external symbol.  */
786 
787 static bfd_boolean
788 nlm_alpha_write_external (bfd *abfd,
789 			  bfd_size_type count,
790 			  asymbol *sym,
791 			  struct reloc_and_sec *relocs)
792 {
793   bfd_size_type i;
794   bfd_byte len;
795   unsigned char temp[NLM_TARGET_LONG_SIZE];
796   arelent r;
797 
798   len = strlen (sym->name);
799   if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
800        != sizeof (bfd_byte))
801       || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
802     return FALSE;
803 
804   bfd_put_32 (abfd, count + 2, temp);
805   if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
806     return FALSE;
807 
808   /* The first two relocs for each external symbol are the .lita
809      address and the GP value.  */
810   r.sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
811   r.howto = &nlm32_alpha_nw_howto;
812 
813   r.address = nlm_alpha_backend_data (abfd)->lita_address;
814   r.addend = nlm_alpha_backend_data (abfd)->lita_size + 1;
815   if (! nlm_alpha_write_import (abfd, NULL, &r))
816     return FALSE;
817 
818   r.address = nlm_alpha_backend_data (abfd)->gp;
819   r.addend = 0;
820   if (! nlm_alpha_write_import (abfd, NULL, &r))
821     return FALSE;
822 
823   for (i = 0; i < count; i++)
824     if (! nlm_alpha_write_import (abfd, relocs[i].sec, relocs[i].rel))
825       return FALSE;
826 
827   return TRUE;
828 }
829 
830 #include "nlmswap.h"
831 
832 static const struct nlm_backend_data nlm32_alpha_backend =
833 {
834   "NetWare Alpha Module   \032",
835   sizeof (Nlm32_alpha_External_Fixed_Header),
836   sizeof (struct nlm32_alpha_external_prefix_header),
837   bfd_arch_alpha,
838   0,
839   TRUE, /* No uninitialized data permitted by Alpha NetWare.  */
840   nlm_alpha_backend_object_p,
841   nlm_alpha_write_prefix,
842   nlm_alpha_read_reloc,
843   nlm_alpha_mangle_relocs,
844   nlm_alpha_read_import,
845   nlm_alpha_write_import,
846   nlm_alpha_set_public_section,
847   nlm_alpha_get_public_offset,
848   nlm_swap_fixed_header_in,
849   nlm_swap_fixed_header_out,
850   nlm_alpha_write_external,
851   0,	/* Write_export.  */
852 };
853 
854 #define TARGET_LITTLE_NAME		"nlm32-alpha"
855 #define TARGET_LITTLE_SYM		nlmNAME (alpha_vec)
856 #define TARGET_BACKEND_DATA		& nlm32_alpha_backend
857 
858 #include "nlm-target.h"
859