1 /* Support for 32-bit Alpha NLM (NetWare Loadable Module)
2 Copyright 1993, 1994, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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,
32 #include "nlm/alpha-ext.h"
33 #define Nlm_External_Fixed_Header Nlm32_alpha_External_Fixed_Header
37 static bfd_boolean nlm_alpha_backend_object_p
39 static bfd_boolean nlm_alpha_write_prefix
41 static bfd_boolean nlm_alpha_read_reloc
42 PARAMS ((bfd
*, nlmNAME(symbol_type
) *, asection
**, arelent
*));
43 static bfd_boolean nlm_alpha_mangle_relocs
44 PARAMS ((bfd
*, asection
*, const PTR
, bfd_vma
, bfd_size_type
));
45 static bfd_boolean nlm_alpha_read_import
46 PARAMS ((bfd
*, nlmNAME(symbol_type
) *));
47 static bfd_boolean nlm_alpha_write_import
48 PARAMS ((bfd
*, asection
*, arelent
*));
49 static bfd_boolean nlm_alpha_set_public_section
50 PARAMS ((bfd
*, nlmNAME(symbol_type
) *));
51 static bfd_vma nlm_alpha_get_public_offset
52 PARAMS ((bfd
*, asymbol
*));
53 static bfd_boolean nlm_alpha_write_external
54 PARAMS ((bfd
*, bfd_size_type
, asymbol
*, struct reloc_and_sec
*));
56 /* Alpha NLM's have a prefix header before the standard NLM. This
57 function reads it in, verifies the version, and seeks the bfd to
58 the location before the regular NLM header. */
61 nlm_alpha_backend_object_p (abfd
)
64 struct nlm32_alpha_external_prefix_header s
;
67 if (bfd_bread ((PTR
) &s
, (bfd_size_type
) sizeof s
, abfd
) != sizeof s
)
70 if (H_GET_32 (abfd
, s
.magic
) != NLM32_ALPHA_MAGIC
)
73 /* FIXME: Should we check the format number? */
75 /* Skip to the end of the header. */
76 size
= H_GET_32 (abfd
, s
.size
);
77 if (bfd_seek (abfd
, size
, SEEK_SET
) != 0)
83 /* Write out the prefix. */
86 nlm_alpha_write_prefix (abfd
)
89 struct nlm32_alpha_external_prefix_header s
;
91 memset (&s
, 0, sizeof s
);
92 H_PUT_32 (abfd
, NLM32_ALPHA_MAGIC
, s
.magic
);
93 H_PUT_32 (abfd
, 2, s
.format
);
94 H_PUT_32 (abfd
, sizeof s
, s
.size
);
95 if (bfd_bwrite ((PTR
) &s
, (bfd_size_type
) sizeof s
, abfd
) != sizeof s
)
100 /* How to process the various reloc types. */
102 static reloc_howto_type nlm32_alpha_howto_table
[] =
104 /* Reloc type 0 is ignored by itself. However, it appears after a
105 GPDISP reloc to identify the location where the low order 16 bits
106 of the gp register are loaded. */
107 HOWTO (ALPHA_R_IGNORE
, /* type */
109 0, /* size (0 = byte, 1 = short, 2 = long) */
111 FALSE
, /* pc_relative */
113 complain_overflow_dont
, /* complain_on_overflow */
114 0, /* special_function */
116 FALSE
, /* partial_inplace */
119 FALSE
), /* pcrel_offset */
121 /* A 32 bit reference to a symbol. */
122 HOWTO (ALPHA_R_REFLONG
, /* type */
124 2, /* size (0 = byte, 1 = short, 2 = long) */
126 FALSE
, /* pc_relative */
128 complain_overflow_bitfield
, /* complain_on_overflow */
129 0, /* special_function */
130 "REFLONG", /* name */
131 TRUE
, /* partial_inplace */
132 0xffffffff, /* src_mask */
133 0xffffffff, /* dst_mask */
134 FALSE
), /* pcrel_offset */
136 /* A 64 bit reference to a symbol. */
137 HOWTO (ALPHA_R_REFQUAD
, /* type */
139 4, /* size (0 = byte, 1 = short, 2 = long) */
141 FALSE
, /* pc_relative */
143 complain_overflow_bitfield
, /* complain_on_overflow */
144 0, /* special_function */
145 "REFQUAD", /* name */
146 TRUE
, /* partial_inplace */
147 0xffffffffffffffff, /* src_mask */
148 0xffffffffffffffff, /* dst_mask */
149 FALSE
), /* pcrel_offset */
151 /* A 32 bit GP relative offset. This is just like REFLONG except
152 that when the value is used the value of the gp register will be
154 HOWTO (ALPHA_R_GPREL32
, /* type */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
158 FALSE
, /* pc_relative */
160 complain_overflow_bitfield
, /* complain_on_overflow */
161 0, /* special_function */
162 "GPREL32", /* name */
163 TRUE
, /* partial_inplace */
164 0xffffffff, /* src_mask */
165 0xffffffff, /* dst_mask */
166 FALSE
), /* pcrel_offset */
168 /* Used for an instruction that refers to memory off the GP
169 register. The offset is 16 bits of the 32 bit instruction. This
170 reloc always seems to be against the .lita section. */
171 HOWTO (ALPHA_R_LITERAL
, /* type */
173 2, /* size (0 = byte, 1 = short, 2 = long) */
175 FALSE
, /* pc_relative */
177 complain_overflow_signed
, /* complain_on_overflow */
178 0, /* special_function */
179 "LITERAL", /* name */
180 TRUE
, /* partial_inplace */
181 0xffff, /* src_mask */
182 0xffff, /* dst_mask */
183 FALSE
), /* pcrel_offset */
185 /* This reloc only appears immediately following a LITERAL reloc.
186 It identifies a use of the literal. It seems that the linker can
187 use this to eliminate a portion of the .lita section. The symbol
188 index is special: 1 means the literal address is in the base
189 register of a memory format instruction; 2 means the literal
190 address is in the byte offset register of a byte-manipulation
191 instruction; 3 means the literal address is in the target
192 register of a jsr instruction. This does not actually do any
194 HOWTO (ALPHA_R_LITUSE
, /* type */
196 2, /* size (0 = byte, 1 = short, 2 = long) */
198 FALSE
, /* pc_relative */
200 complain_overflow_dont
, /* complain_on_overflow */
201 0, /* special_function */
203 FALSE
, /* partial_inplace */
206 FALSE
), /* pcrel_offset */
208 /* Load the gp register. This is always used for a ldah instruction
209 which loads the upper 16 bits of the gp register. The next reloc
210 will be an IGNORE reloc which identifies the location of the lda
211 instruction which loads the lower 16 bits. The symbol index of
212 the GPDISP instruction appears to actually be the number of bytes
213 between the ldah and lda instructions. This gives two different
214 ways to determine where the lda instruction is; I don't know why
215 both are used. The value to use for the relocation is the
216 difference between the GP value and the current location; the
217 load will always be done against a register holding the current
219 HOWTO (ALPHA_R_GPDISP
, /* type */
221 2, /* size (0 = byte, 1 = short, 2 = long) */
223 TRUE
, /* pc_relative */
225 complain_overflow_dont
, /* complain_on_overflow */
226 0, /* special_function */
228 TRUE
, /* partial_inplace */
229 0xffff, /* src_mask */
230 0xffff, /* dst_mask */
231 TRUE
), /* pcrel_offset */
233 /* A 21 bit branch. The native assembler generates these for
234 branches within the text segment, and also fills in the PC
235 relative offset in the instruction. It seems to me that this
236 reloc, unlike the others, is not partial_inplace. */
237 HOWTO (ALPHA_R_BRADDR
, /* type */
239 2, /* size (0 = byte, 1 = short, 2 = long) */
241 TRUE
, /* pc_relative */
243 complain_overflow_signed
, /* complain_on_overflow */
244 0, /* special_function */
246 FALSE
, /* partial_inplace */
248 0x1fffff, /* dst_mask */
249 FALSE
), /* pcrel_offset */
251 /* A hint for a jump to a register. */
252 HOWTO (ALPHA_R_HINT
, /* type */
254 2, /* size (0 = byte, 1 = short, 2 = long) */
256 FALSE
, /* pc_relative */
258 complain_overflow_dont
, /* complain_on_overflow */
259 0, /* special_function */
261 TRUE
, /* partial_inplace */
262 0x3fff, /* src_mask */
263 0x3fff, /* dst_mask */
264 FALSE
), /* pcrel_offset */
266 /* 16 bit PC relative offset. */
267 HOWTO (ALPHA_R_SREL16
, /* type */
269 1, /* size (0 = byte, 1 = short, 2 = long) */
271 TRUE
, /* pc_relative */
273 complain_overflow_signed
, /* complain_on_overflow */
274 0, /* special_function */
276 TRUE
, /* partial_inplace */
277 0xffff, /* src_mask */
278 0xffff, /* dst_mask */
279 FALSE
), /* pcrel_offset */
281 /* 32 bit PC relative offset. */
282 HOWTO (ALPHA_R_SREL32
, /* type */
284 2, /* size (0 = byte, 1 = short, 2 = long) */
286 TRUE
, /* pc_relative */
288 complain_overflow_signed
, /* complain_on_overflow */
289 0, /* special_function */
291 TRUE
, /* partial_inplace */
292 0xffffffff, /* src_mask */
293 0xffffffff, /* dst_mask */
294 FALSE
), /* pcrel_offset */
296 /* A 64 bit PC relative offset. */
297 HOWTO (ALPHA_R_SREL64
, /* type */
299 4, /* size (0 = byte, 1 = short, 2 = long) */
301 TRUE
, /* pc_relative */
303 complain_overflow_signed
, /* complain_on_overflow */
304 0, /* special_function */
306 TRUE
, /* partial_inplace */
307 0xffffffffffffffff, /* src_mask */
308 0xffffffffffffffff, /* dst_mask */
309 FALSE
), /* pcrel_offset */
311 /* Push a value on the reloc evaluation stack. */
312 HOWTO (ALPHA_R_OP_PUSH
, /* type */
314 0, /* size (0 = byte, 1 = short, 2 = long) */
316 FALSE
, /* pc_relative */
318 complain_overflow_dont
, /* complain_on_overflow */
319 0, /* special_function */
320 "OP_PUSH", /* name */
321 FALSE
, /* partial_inplace */
324 FALSE
), /* pcrel_offset */
326 /* Store the value from the stack at the given address. Store it in
327 a bitfield of size r_size starting at bit position r_offset. */
328 HOWTO (ALPHA_R_OP_STORE
, /* type */
330 4, /* size (0 = byte, 1 = short, 2 = long) */
332 FALSE
, /* pc_relative */
334 complain_overflow_dont
, /* complain_on_overflow */
335 0, /* special_function */
336 "OP_STORE", /* name */
337 FALSE
, /* partial_inplace */
339 0xffffffffffffffff, /* dst_mask */
340 FALSE
), /* pcrel_offset */
342 /* Subtract the reloc address from the value on the top of the
344 HOWTO (ALPHA_R_OP_PSUB
, /* type */
346 0, /* size (0 = byte, 1 = short, 2 = long) */
348 FALSE
, /* pc_relative */
350 complain_overflow_dont
, /* complain_on_overflow */
351 0, /* special_function */
352 "OP_PSUB", /* name */
353 FALSE
, /* partial_inplace */
356 FALSE
), /* pcrel_offset */
358 /* Shift the value on the top of the relocation stack right by the
360 HOWTO (ALPHA_R_OP_PRSHIFT
, /* type */
362 0, /* size (0 = byte, 1 = short, 2 = long) */
364 FALSE
, /* pc_relative */
366 complain_overflow_dont
, /* complain_on_overflow */
367 0, /* special_function */
368 "OP_PRSHIFT", /* name */
369 FALSE
, /* partial_inplace */
372 FALSE
), /* pcrel_offset */
374 /* Adjust the GP value for a new range in the object file. */
375 HOWTO (ALPHA_R_GPVALUE
, /* type */
377 0, /* size (0 = byte, 1 = short, 2 = long) */
379 FALSE
, /* pc_relative */
381 complain_overflow_dont
, /* complain_on_overflow */
382 0, /* special_function */
383 "GPVALUE", /* name */
384 FALSE
, /* partial_inplace */
387 FALSE
) /* pcrel_offset */
390 static reloc_howto_type nlm32_alpha_nw_howto
=
391 HOWTO (ALPHA_R_NW_RELOC
, /* type */
393 0, /* size (0 = byte, 1 = short, 2 = long) */
395 FALSE
, /* pc_relative */
397 complain_overflow_dont
, /* complain_on_overflow */
398 0, /* special_function */
399 "NW_RELOC", /* name */
400 FALSE
, /* partial_inplace */
403 FALSE
); /* pcrel_offset */
405 /* Read an Alpha NLM reloc. This routine keeps some static data which
406 it uses when handling local relocs. This only works correctly
407 because all the local relocs are read at once. */
410 nlm_alpha_read_reloc (abfd
, sym
, secp
, rel
)
412 nlmNAME(symbol_type
) *sym
;
416 static bfd_vma gp_value
;
417 static bfd_vma lita_address
;
418 struct nlm32_alpha_external_reloc ext
;
421 int r_type
, r_extern
, r_offset
, r_size
;
422 asection
*code_sec
, *data_sec
;
424 /* Read the reloc from the file. */
425 if (bfd_bread (&ext
, (bfd_size_type
) sizeof ext
, abfd
) != sizeof ext
)
428 /* Swap in the reloc information. */
429 r_vaddr
= H_GET_64 (abfd
, ext
.r_vaddr
);
430 r_symndx
= H_GET_32 (abfd
, ext
.r_symndx
);
432 BFD_ASSERT (bfd_little_endian (abfd
));
434 r_type
= ((ext
.r_bits
[0] & RELOC_BITS0_TYPE_LITTLE
)
435 >> RELOC_BITS0_TYPE_SH_LITTLE
);
436 r_extern
= (ext
.r_bits
[1] & RELOC_BITS1_EXTERN_LITTLE
) != 0;
437 r_offset
= ((ext
.r_bits
[1] & RELOC_BITS1_OFFSET_LITTLE
)
438 >> RELOC_BITS1_OFFSET_SH_LITTLE
);
439 /* Ignore the reserved bits. */
440 r_size
= ((ext
.r_bits
[3] & RELOC_BITS3_SIZE_LITTLE
)
441 >> RELOC_BITS3_SIZE_SH_LITTLE
);
443 /* Fill in the BFD arelent structure. */
444 code_sec
= bfd_get_section_by_name (abfd
, NLM_CODE_NAME
);
445 data_sec
= bfd_get_section_by_name (abfd
, NLM_INITIALIZED_DATA_NAME
);
448 /* External relocations are only used for imports. */
449 BFD_ASSERT (sym
!= NULL
);
450 /* We don't need to set sym_ptr_ptr for this case. It is set in
451 nlm_canonicalize_reloc. */
452 rel
->sym_ptr_ptr
= NULL
;
457 /* Internal relocations are only used for local relocation
458 fixups. If they are not NW_RELOC or GPDISP or IGNORE, they
459 must be against .text or .data. */
460 BFD_ASSERT (r_type
== ALPHA_R_NW_RELOC
|| sym
== NULL
);
461 if (r_type
== ALPHA_R_NW_RELOC
462 || r_type
== ALPHA_R_GPDISP
463 || r_type
== ALPHA_R_IGNORE
)
465 rel
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
468 else if (r_symndx
== ALPHA_RELOC_SECTION_TEXT
)
470 rel
->sym_ptr_ptr
= code_sec
->symbol_ptr_ptr
;
471 BFD_ASSERT (bfd_get_section_vma (abfd
, code_sec
) == 0);
474 else if (r_symndx
== ALPHA_RELOC_SECTION_DATA
)
476 rel
->sym_ptr_ptr
= data_sec
->symbol_ptr_ptr
;
477 rel
->addend
= - bfd_get_section_vma (abfd
, data_sec
);
482 rel
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
487 /* We use the address to determine whether the reloc is in the .text
488 or .data section. R_NW_RELOC relocs don't really have a section,
489 so we put them in .text. */
490 if (r_type
== ALPHA_R_NW_RELOC
491 || r_vaddr
< bfd_section_size (abfd
, code_sec
))
494 rel
->address
= r_vaddr
;
499 rel
->address
= r_vaddr
- bfd_section_size (abfd
, code_sec
);
502 /* We must adjust the addend based on the type. */
503 BFD_ASSERT ((r_type
>= 0 && r_type
<= ALPHA_R_GPVALUE
)
504 || r_type
== ALPHA_R_NW_RELOC
);
512 /* The PC relative relocs do not seem to use the section VMA as
513 a negative addend. */
517 case ALPHA_R_GPREL32
:
518 /* Copy the gp value for this object file into the addend, to
519 ensure that we are not confused by the linker. */
521 rel
->addend
+= gp_value
;
524 case ALPHA_R_LITERAL
:
525 BFD_ASSERT (! r_extern
);
526 rel
->addend
+= lita_address
;
531 /* The LITUSE and GPDISP relocs do not use a symbol, or an
532 addend, but they do use a special code. Put this code in the
534 rel
->addend
= r_symndx
;
535 rel
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
538 case ALPHA_R_OP_STORE
:
539 /* The STORE reloc needs the size and offset fields. We store
540 them in the addend. */
541 BFD_ASSERT (r_offset
< 256 && r_size
< 256);
542 rel
->addend
= (r_offset
<< 8) + r_size
;
545 case ALPHA_R_OP_PUSH
:
546 case ALPHA_R_OP_PSUB
:
547 case ALPHA_R_OP_PRSHIFT
:
548 /* The PUSH, PSUB and PRSHIFT relocs do not actually use an
549 address. I believe that the address supplied is really an
551 rel
->addend
= r_vaddr
;
554 case ALPHA_R_GPVALUE
:
555 /* Record the new gp value. */
556 gp_value
+= r_symndx
;
557 rel
->addend
= gp_value
;
561 /* If the type is ALPHA_R_IGNORE, make sure this is a reference
562 to the absolute section so that the reloc is ignored. For
563 some reason the address of this reloc type is not adjusted by
564 the section vma. We record the gp value for this object file
565 here, for convenience when doing the GPDISP relocation. */
566 rel
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
567 rel
->address
= r_vaddr
;
568 rel
->addend
= gp_value
;
571 case ALPHA_R_NW_RELOC
:
572 /* If this is SETGP, we set the addend to 0. Otherwise we set
573 the addend to the size of the .lita section (this is
574 r_symndx) plus 1. We have already set the address of the
576 if (r_size
== ALPHA_R_NW_RELOC_SETGP
)
581 else if (r_size
== ALPHA_R_NW_RELOC_LITA
)
583 lita_address
= r_vaddr
;
584 rel
->addend
= r_symndx
+ 1;
588 rel
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
595 if (r_type
== ALPHA_R_NW_RELOC
)
596 rel
->howto
= &nlm32_alpha_nw_howto
;
598 rel
->howto
= &nlm32_alpha_howto_table
[r_type
];
603 /* Mangle Alpha NLM relocs for output. */
606 nlm_alpha_mangle_relocs (abfd
, sec
, data
, offset
, count
)
607 bfd
*abfd ATTRIBUTE_UNUSED
;
608 asection
*sec ATTRIBUTE_UNUSED
;
609 const PTR data ATTRIBUTE_UNUSED
;
610 bfd_vma offset ATTRIBUTE_UNUSED
;
611 bfd_size_type count ATTRIBUTE_UNUSED
;
616 /* Read an ALPHA NLM import record */
619 nlm_alpha_read_import (abfd
, sym
)
621 nlmNAME(symbol_type
) *sym
;
623 struct nlm_relent
*nlm_relocs
; /* relocation records for symbol */
624 bfd_size_type rcount
; /* number of relocs */
625 bfd_byte temp
[NLM_TARGET_LONG_SIZE
]; /* temporary 32-bit value */
626 unsigned char symlength
; /* length of symbol name */
630 if (bfd_bread ((PTR
) &symlength
, (bfd_size_type
) sizeof (symlength
), abfd
)
631 != sizeof (symlength
))
633 sym
-> symbol
.the_bfd
= abfd
;
634 name
= bfd_alloc (abfd
, (bfd_size_type
) symlength
+ 1);
637 if (bfd_bread (name
, (bfd_size_type
) symlength
, abfd
) != symlength
)
639 name
[symlength
] = '\0';
640 sym
-> symbol
.name
= name
;
641 sym
-> symbol
.flags
= 0;
642 sym
-> symbol
.value
= 0;
643 sym
-> symbol
.section
= bfd_und_section_ptr
;
644 if (bfd_bread ((PTR
) temp
, (bfd_size_type
) sizeof (temp
), abfd
)
647 rcount
= H_GET_32 (abfd
, temp
);
648 amt
= rcount
* sizeof (struct nlm_relent
);
649 nlm_relocs
= (struct nlm_relent
*) bfd_alloc (abfd
, amt
);
652 sym
-> relocs
= nlm_relocs
;
654 while (sym
-> rcnt
< rcount
)
658 if (! nlm_alpha_read_reloc (abfd
, sym
, §ion
, &nlm_relocs
-> reloc
))
660 nlm_relocs
-> section
= section
;
668 /* Write an Alpha NLM reloc. */
671 nlm_alpha_write_import (abfd
, sec
, rel
)
679 int r_type
, r_extern
, r_offset
, r_size
;
680 struct nlm32_alpha_external_reloc ext
;
682 sym
= *rel
->sym_ptr_ptr
;
684 /* Get values for the relocation fields. */
685 r_type
= rel
->howto
->type
;
686 if (r_type
!= ALPHA_R_NW_RELOC
)
688 r_vaddr
= bfd_get_section_vma (abfd
, sec
) + rel
->address
;
689 if ((sec
->flags
& SEC_CODE
) == 0)
690 r_vaddr
+= bfd_section_size (abfd
,
691 bfd_get_section_by_name (abfd
,
693 if (bfd_is_und_section (bfd_get_section (sym
)))
701 if (bfd_get_section_flags (abfd
, bfd_get_section (sym
)) & SEC_CODE
)
702 r_symndx
= ALPHA_RELOC_SECTION_TEXT
;
704 r_symndx
= ALPHA_RELOC_SECTION_DATA
;
713 r_symndx
= rel
->addend
;
716 case ALPHA_R_OP_STORE
:
717 r_size
= rel
->addend
& 0xff;
718 r_offset
= (rel
->addend
>> 8) & 0xff;
721 case ALPHA_R_OP_PUSH
:
722 case ALPHA_R_OP_PSUB
:
723 case ALPHA_R_OP_PRSHIFT
:
724 r_vaddr
= rel
->addend
;
728 r_vaddr
= rel
->address
;
737 /* r_type == ALPHA_R_NW_RELOC */
738 r_vaddr
= rel
->address
;
739 if (rel
->addend
== 0)
742 r_size
= ALPHA_R_NW_RELOC_SETGP
;
746 r_symndx
= rel
->addend
- 1;
747 r_size
= ALPHA_R_NW_RELOC_LITA
;
753 /* Swap out the relocation fields. */
754 H_PUT_64 (abfd
, r_vaddr
, ext
.r_vaddr
);
755 H_PUT_32 (abfd
, r_symndx
, ext
.r_symndx
);
757 BFD_ASSERT (bfd_little_endian (abfd
));
759 ext
.r_bits
[0] = ((r_type
<< RELOC_BITS0_TYPE_SH_LITTLE
)
760 & RELOC_BITS0_TYPE_LITTLE
);
761 ext
.r_bits
[1] = ((r_extern
? RELOC_BITS1_EXTERN_LITTLE
: 0)
762 | ((r_offset
<< RELOC_BITS1_OFFSET_SH_LITTLE
)
763 & RELOC_BITS1_OFFSET_LITTLE
));
765 ext
.r_bits
[3] = ((r_size
<< RELOC_BITS3_SIZE_SH_LITTLE
)
766 & RELOC_BITS3_SIZE_LITTLE
);
768 /* Write out the relocation. */
769 if (bfd_bwrite (&ext
, (bfd_size_type
) sizeof ext
, abfd
) != sizeof ext
)
775 /* Alpha NetWare does not use the high bit to determine whether a
776 public symbol is in the code segment or the data segment. Instead,
777 it just uses the address. The set_public_section and
778 get_public_offset routines override the default code which uses the
781 /* Set the section for a public symbol. */
784 nlm_alpha_set_public_section (abfd
, sym
)
786 nlmNAME(symbol_type
) *sym
;
788 asection
*code_sec
, *data_sec
;
790 code_sec
= bfd_get_section_by_name (abfd
, NLM_CODE_NAME
);
791 data_sec
= bfd_get_section_by_name (abfd
, NLM_INITIALIZED_DATA_NAME
);
792 if (sym
->symbol
.value
< bfd_section_size (abfd
, code_sec
))
794 sym
->symbol
.section
= code_sec
;
795 sym
->symbol
.flags
|= BSF_FUNCTION
;
799 sym
->symbol
.section
= data_sec
;
800 sym
->symbol
.value
-= bfd_section_size (abfd
, code_sec
);
801 /* The data segment had better be aligned. */
802 BFD_ASSERT ((bfd_section_size (abfd
, code_sec
) & 0xf) == 0);
807 /* Get the offset to write out for a public symbol. */
810 nlm_alpha_get_public_offset (abfd
, sym
)
811 bfd
*abfd ATTRIBUTE_UNUSED
;
814 return bfd_asymbol_value (sym
);
817 /* Write an Alpha NLM external symbol. */
820 nlm_alpha_write_external (abfd
, count
, sym
, relocs
)
824 struct reloc_and_sec
*relocs
;
828 unsigned char temp
[NLM_TARGET_LONG_SIZE
];
831 len
= strlen (sym
->name
);
832 if ((bfd_bwrite (&len
, (bfd_size_type
) sizeof (bfd_byte
), abfd
)
833 != sizeof (bfd_byte
))
834 || bfd_bwrite (sym
->name
, (bfd_size_type
) len
, abfd
) != len
)
837 bfd_put_32 (abfd
, count
+ 2, temp
);
838 if (bfd_bwrite (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
841 /* The first two relocs for each external symbol are the .lita
842 address and the GP value. */
843 r
.sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
844 r
.howto
= &nlm32_alpha_nw_howto
;
846 r
.address
= nlm_alpha_backend_data (abfd
)->lita_address
;
847 r
.addend
= nlm_alpha_backend_data (abfd
)->lita_size
+ 1;
848 if (! nlm_alpha_write_import (abfd
, (asection
*) NULL
, &r
))
851 r
.address
= nlm_alpha_backend_data (abfd
)->gp
;
853 if (! nlm_alpha_write_import (abfd
, (asection
*) NULL
, &r
))
856 for (i
= 0; i
< count
; i
++)
858 if (! nlm_alpha_write_import (abfd
, relocs
[i
].sec
, relocs
[i
].rel
))
867 static const struct nlm_backend_data nlm32_alpha_backend
=
869 "NetWare Alpha Module \032",
870 sizeof (Nlm32_alpha_External_Fixed_Header
),
871 sizeof (struct nlm32_alpha_external_prefix_header
),
874 TRUE
, /* no uninitialized data permitted by Alpha NetWare. */
875 nlm_alpha_backend_object_p
,
876 nlm_alpha_write_prefix
,
877 nlm_alpha_read_reloc
,
878 nlm_alpha_mangle_relocs
,
879 nlm_alpha_read_import
,
880 nlm_alpha_write_import
,
881 nlm_alpha_set_public_section
,
882 nlm_alpha_get_public_offset
,
883 nlm_swap_fixed_header_in
,
884 nlm_swap_fixed_header_out
,
885 nlm_alpha_write_external
,
886 0, /* write_export */
889 #define TARGET_LITTLE_NAME "nlm32-alpha"
890 #define TARGET_LITTLE_SYM nlmNAME(alpha_vec)
891 #define TARGET_BACKEND_DATA &nlm32_alpha_backend
893 #include "nlm-target.h"