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