diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/libnlm.h | 81 | ||||
-rw-r--r-- | bfd/nlm32-i386.c | 136 | ||||
-rw-r--r-- | bfd/nlm32-sparc.c | 400 | ||||
-rw-r--r-- | bfd/nlmcode.h | 442 |
4 files changed, 758 insertions, 301 deletions
diff --git a/bfd/libnlm.h b/bfd/libnlm.h index 53199bc..22d779d 100644 --- a/bfd/libnlm.h +++ b/bfd/libnlm.h @@ -117,14 +117,41 @@ struct nlm_obj_tdata #define nlm_relocation_fixups(bfd) (nlm_tdata(bfd) -> nlm_reloc_fixups) #define nlm_relocation_fixup_secs(bfd) (nlm_tdata(bfd)->nlm_reloc_fixup_secs) +/* This is used when writing out the external relocs. */ + +struct reloc_and_sec +{ + arelent *rel; + asection *sec; +}; + /* We store some function pointer in the backend structure. This lets different NLM targets share most of the same code, while providing slightly different code where necessary. */ struct nlm_backend_data { - /* Machine architecture. */ + /* Signature for this backend. */ + char signature[NLM_SIGNATURE_SIZE]; + /* Size of the fixed header. */ + bfd_size_type fixed_header_size; + /* Size of optional prefix for this backend. Some backend may + require this to be a function, but so far a constant is OK. This + is for a prefix which precedes the standard NLM fixed header. */ + bfd_size_type optional_prefix_size; + /* Architecture. */ enum bfd_architecture arch; + /* Machine. */ + long mach; + /* Some NLM formats have a prefix on the file. If this function is + not NULL, it will be called by nlm_object_p. It should return + true if this file could match this format, and it should leave + the BFD such that a bfd_read will pick up the fixed header. */ + boolean (*nlm_backend_object_p) PARAMS ((bfd *)); + /* Write out the prefix. This function may be NULL. This must + write out the same number of bytes as is in the field + optional_prefix_size. */ + boolean (*nlm_write_prefix) PARAMS ((bfd *)); /* Read a relocation fixup from abfd. The reloc information is machine specific. The second argument is the symbol if this is an import, or NULL if this is a reloc fixup. This function @@ -134,25 +161,69 @@ struct nlm_backend_data import symbol. */ boolean (*nlm_read_reloc) PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); - /* Write a relocation fixup to abfd. */ - boolean (*nlm_write_reloc) PARAMS ((bfd *, asection *, arelent *)); /* To make objcopy to an i386 NLM work, the i386 backend needs a chance to work over the relocs. This is a bit icky. */ boolean (*nlm_mangle_relocs) PARAMS ((bfd *, asection *, PTR data, bfd_vma offset, bfd_size_type count)); + /* Read an import record from abfd. It would be nice if this + were in a machine-dependent format, but it doesn't seem to be. */ + boolean (*nlm_read_import) PARAMS ((bfd *, nlmNAME(symbol_type) *)); + /* Write an import record to abfd. */ + boolean (*nlm_write_import) PARAMS ((bfd *, asection *, arelent *)); + /* Set the section for a public symbol. This may be NULL, in which + case a default method will be used. */ + boolean (*nlm_set_public_section) PARAMS ((bfd *, nlmNAME(symbol_type) *)); + /* Get the offset to write out for a public symbol. This may be + NULL, in which case a default method will be used. */ + bfd_vma (*nlm_get_public_offset) PARAMS ((bfd *, asymbol *)); + /* Swap the fixed header in and out */ + void (*nlm_swap_fhdr_in) PARAMS ((bfd *, + PTR, + Nlm_Internal_Fixed_Header *)); + void (*nlm_swap_fhdr_out) PARAMS ((bfd *, + struct nlm_internal_fixed_header *, + PTR)); + /* Write out an external reference. */ + boolean (*nlm_write_external) PARAMS ((bfd *, bfd_size_type, + asymbol *, + struct reloc_and_sec *)); }; #define nlm_backend(bfd) \ ((struct nlm_backend_data *)((bfd) -> xvec -> backend_data)) +#define nlm_signature(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> signature : "") +#define nlm_fixed_header_size(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> fixed_header_size : 0) +#define nlm_optional_prefix_size(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> optional_prefix_size : 0) #define nlm_architecture(bfd) \ (nlm_backend(bfd) ? nlm_backend(bfd) -> arch : bfd_arch_unknown) +#define nlm_machine(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> mach : 0) +#define nlm_backend_object_p_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_backend_object_p : 0) +#define nlm_write_prefix_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_prefix : 0) #define nlm_read_reloc_func(bfd) \ (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_read_reloc : 0) -#define nlm_write_reloc_func(bfd) \ - (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_reloc : 0) #define nlm_mangle_relocs_func(bfd) \ (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_mangle_relocs : 0) +#define nlm_read_import_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_read_import : 0) +#define nlm_write_import_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_import : 0) +#define nlm_set_public_section_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_set_public_section : 0) +#define nlm_get_public_offset_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_get_public_offset : 0) +#define nlm_swap_fixed_header_in_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_swap_fhdr_in : 0) +#define nlm_swap_fixed_header_out_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_swap_fhdr_out : 0) +#define nlm_write_external_func(bfd) \ + (nlm_backend(bfd) ? nlm_backend(bfd) -> nlm_write_external : 0) /* The NLM code, data, and uninitialized sections have no names defined in the NLM, but bfd wants to give them names, so use the traditional diff --git a/bfd/nlm32-i386.c b/bfd/nlm32-i386.c index 20328b1..45260c5 100644 --- a/bfd/nlm32-i386.c +++ b/bfd/nlm32-i386.c @@ -22,14 +22,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "libbfd.h" #define ARCH_SIZE 32 + +#include "nlm/i386-ext.h" +#define Nlm_External_Fixed_Header Nlm32_i386_External_Fixed_Header + #include "libnlm.h" static boolean nlm_i386_read_reloc PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); -static boolean nlm_i386_write_reloc +static boolean nlm_i386_write_import PARAMS ((bfd *, asection *, arelent *)); static boolean nlm_i386_mangle_relocs PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type)); +static boolean nlm_i386_read_import + PARAMS ((bfd *, nlmNAME(symbol_type) *)); +static boolean nlm_i386_write_external + PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); /* Adjust the reloc location by an absolute value. */ @@ -146,7 +154,7 @@ nlm_i386_read_reloc (abfd, sym, secp, rel) /* Write a NetWare i386 reloc. */ static boolean -nlm_i386_write_reloc (abfd, sec, rel) +nlm_i386_write_import (abfd, sec, rel) bfd *abfd; asection *sec; arelent *rel; @@ -165,7 +173,6 @@ nlm_i386_write_reloc (abfd, sec, rel) || rel->howto->size != 2 || rel->howto->bitsize != 32 || rel->howto->bitpos != 0 - || ! rel->howto->partial_inplace || rel->howto->src_mask != 0xffffffff || rel->howto->dst_mask != 0xffffffff) { @@ -264,7 +271,7 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count) sym = *rel->sym_ptr_ptr; /* Note that no serious harm will ensue if we fail to change a - reloc. We will wind up failing in nlm_i386_write_reloc. */ + reloc. We will wind up failing in nlm_i386_write_import. */ /* Make sure this reloc is within the data we have. We only 4 byte relocs here, so we insist on having 4 bytes. */ @@ -283,7 +290,7 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count) that at this point the size of the data section is in the NLM header. */ if (((bfd_get_section_flags (abfd, bfd_get_section (sym)) - & (SEC_CODE | SEC_DATA)) == 0) + & SEC_LOAD) == 0) && ((bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_ALLOC) != 0)) addend += nlm_fixed_header (abfd)->dataImageSize; @@ -294,15 +301,14 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count) && rel->howto->size == 2 && rel->howto->bitsize == 32 && rel->howto->bitpos == 0 - && rel->howto->partial_inplace && rel->howto->src_mask == 0xffffffff && rel->howto->dst_mask == 0xffffffff) { bfd_vma val; - val = bfd_get_32 (abfd, (char *) data + rel->address - offset); + val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset); val += addend; - bfd_put_32 (abfd, val, (char *) data + rel->address - offset); + bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset); rel->addend = 0; } @@ -319,7 +325,6 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count) && rel->howto->size == 2 && rel->howto->bitsize == 32 && rel->howto->bitpos == 0 - && rel->howto->partial_inplace && rel->howto->src_mask == 0xffffffff && rel->howto->dst_mask == 0xffffffff) { @@ -328,9 +333,9 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count) /* When pcrel_offset is not set, it means that the negative of the address of the memory location is stored in the memory location. We must add it back in. */ - val = bfd_get_32 (abfd, (char *) data + rel->address - offset); + val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset); val += rel->address; - bfd_put_32 (abfd, val, (char *) data + rel->address - offset); + bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset); rel->howto = &nlm_i386_pcrel_howto; } @@ -339,12 +344,117 @@ nlm_i386_mangle_relocs (abfd, sec, data, offset, count) return true; } +/* Read a NetWare i386 import record */ +static boolean +nlm_i386_read_import (abfd, sym) + bfd *abfd; + nlmNAME(symbol_type) *sym; +{ + struct nlm_relent *nlm_relocs; /* relocation records for symbol */ + bfd_size_type rcount; /* number of relocs */ + bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */ + unsigned char symlength; /* length of symbol name */ + + if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd) + != sizeof (symlength)) + { + bfd_error = system_call_error; + return (false); + } + sym -> symbol.the_bfd = abfd; + sym -> symbol.name = bfd_alloc (abfd, symlength + 1); + if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd) + != symlength) + { + bfd_error = system_call_error; + return (false); + } + sym -> symbol.flags = 0; + sym -> symbol.value = 0; + sym -> symbol.section = &bfd_und_section; + if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp)) + { + bfd_error = system_call_error; + return (false); + } + rcount = bfd_h_get_32 (abfd, temp); + nlm_relocs = ((struct nlm_relent *) + bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); + sym -> relocs = nlm_relocs; + sym -> rcnt = 0; + while (sym -> rcnt < rcount) + { + asection *section; + + if (nlm_i386_read_reloc (abfd, sym, §ion, + &nlm_relocs -> reloc) + == false) + return false; + nlm_relocs -> section = section; + nlm_relocs++; + sym -> rcnt++; + } + return true; +} + +/* Write out an external reference. */ + +static boolean +nlm_i386_write_external (abfd, count, sym, relocs) + bfd *abfd; + bfd_size_type count; + asymbol *sym; + struct reloc_and_sec *relocs; +{ + int i; + bfd_byte len; + unsigned char temp[NLM_TARGET_LONG_SIZE]; + + len = strlen (sym->name); + if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte)) + || bfd_write (sym->name, len, 1, abfd) != len) + { + bfd_error = system_call_error; + return false; + } + + bfd_put_32 (abfd, count, temp); + if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp)) + { + bfd_error = system_call_error; + return false; + } + + for (i = 0; i < count; i++) + { + if (nlm_i386_write_import (abfd, relocs[i].sec, + relocs[i].rel) == false) + return false; + } + + return true; +} + +#include "nlmswap.h" + static const struct nlm_backend_data nlm32_i386_backend = { + "NetWare Loadable Module\032", + sizeof (Nlm32_i386_External_Fixed_Header), + 0, /* optional_prefix_size */ bfd_arch_i386, + 0, + 0, /* backend_object_p */ + 0, /* write_prefix_func */ nlm_i386_read_reloc, - nlm_i386_write_reloc, - nlm_i386_mangle_relocs + nlm_i386_mangle_relocs, + nlm_i386_read_import, + nlm_i386_write_import, + 0, /* set_public_section */ + 0, /* get_public_offset */ + nlm_swap_fixed_header_in, + nlm_swap_fixed_header_out, + nlm_i386_write_external, }; #define TARGET_LITTLE_NAME "nlm32-i386" diff --git a/bfd/nlm32-sparc.c b/bfd/nlm32-sparc.c new file mode 100644 index 0000000..ff0571b --- /dev/null +++ b/bfd/nlm32-sparc.c @@ -0,0 +1,400 @@ +/* Support for 32-bit SPARC NLM (NetWare Loadable Module) + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#define ARCH_SIZE 32 + +#include "nlm/sparc32-ext.h" +#define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header + +#include "libnlm.h" + +static boolean nlm_sparc_read_reloc + PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); +static boolean nlm_sparc_write_reloc + PARAMS ((bfd *, asection *, arelent *)); +static boolean nlm_sparc_mangle_relocs + PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type)); +static boolean nlm_sparc_read_import + PARAMS ((bfd *, nlmNAME(symbol_type) *)); +static boolean nlm_sparc_write_import + PARAMS ((bfd *, asection *, arelent *)); +static boolean nlm_sparc_write_external + PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); + +enum reloc_type + { + R_SPARC_NONE = 0, + R_SPARC_8, R_SPARC_16, R_SPARC_32, + R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, + R_SPARC_WDISP30, R_SPARC_WDISP22, + R_SPARC_HI22, R_SPARC_22, + R_SPARC_13, R_SPARC_LO10, + R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, + R_SPARC_PC10, R_SPARC_PC22, + R_SPARC_WPLT30, + R_SPARC_COPY, + R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, + R_SPARC_RELATIVE, + R_SPARC_UA32, + R_SPARC_max + }; + +#if 0 +static CONST char *CONST reloc_type_names[] = +{ + "R_SPARC_NONE", + "R_SPARC_8", "R_SPARC_16", "R_SPARC_32", + "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32", + "R_SPARC_WDISP30", "R_SPARC_WDISP22", + "R_SPARC_HI22", "R_SPARC_22", + "R_SPARC_13", "R_SPARC_LO10", + "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", + "R_SPARC_PC10", "R_SPARC_PC22", + "R_SPARC_WPLT30", + "R_SPARC_COPY", + "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", + "R_SPARC_RELATIVE", + "R_SPARC_UA32", +}; +#endif + +static reloc_howto_type nlm32_sparc_howto_table[] = +{ + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, 0,"R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,0,"R_SPARC_8", false,0,0x000000ff,true), + HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,0,"R_SPARC_16", false,0,0x0000ffff,true), + HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,0,"R_SPARC_32", false,0,0xffffffff,true), + HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", false,0,0x000000ff,true), + HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", false,0,0x0000ffff,true), + HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", false,0,0x00ffffff,true), + HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", false,0,0x3fffffff,true), + HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", false,0,0x003fffff,true), + HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, 0,"R_SPARC_HI22", false,0,0x003fffff,true), + HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_22", false,0,0x003fffff,true), + HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_13", false,0,0x00001fff,true), + HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, 0,"R_SPARC_LO10", false,0,0x000003ff,true), + HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", false,0,0x000003ff,true), + HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", false,0,0x00001fff,true), + HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", false,0,0x003fffff,true), + HOWTO(R_SPARC_PC10, 0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_PC10", false,0,0x000003ff,true), + HOWTO(R_SPARC_PC22, 0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_PC22", false,0,0x003fffff,true), + HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", false,0,0x00000000,true), + HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_COPY", false,0,0x00000000,true), + HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",false,0,0x00000000,true), + HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",false,0,0x00000000,true), + HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",false,0,0x00000000,true), + HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_UA32", false,0,0x00000000,true), +}; + +/* Read a NetWare sparc reloc. */ + +struct nlm32_sparc_reloc_ext { + unsigned char offset[4]; + unsigned char addend[4]; + unsigned char type[1]; + unsigned char pad1[3]; +}; + +static boolean +nlm_sparc_read_reloc (abfd, sym, secp, rel) + bfd *abfd; + nlmNAME(symbol_type) *sym; + asection **secp; + arelent *rel; +{ + bfd_byte temp[4]; + bfd_vma val, addend; + const char *name; + int index; + unsigned int type; + struct nlm32_sparc_reloc_ext tmp_reloc; + + if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12) { + bfd_error = system_call_error; + return false; + } + + *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME); + + val = bfd_get_32 (abfd, tmp_reloc.offset); + addend = bfd_get_32 (abfd, tmp_reloc.addend); + type = bfd_get_8 (abfd, tmp_reloc.type); + + rel->address = val; + rel->addend = addend; + rel->howto = NULL; + + for (index = 0; + index < sizeof(nlm32_sparc_howto_table) / sizeof(reloc_howto_type); + index++) + if (nlm32_sparc_howto_table[index].type == type) { + rel->howto = &nlm32_sparc_howto_table[index]; + break; + } + +#ifdef DEBUG + fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n", + __FILE__, rel->address, rel->addend, type, rel->howto); +#endif + return true; + +} + +/* Write a NetWare sparc reloc. */ + +static boolean +nlm_sparc_write_reloc (abfd, sec, rel) + bfd *abfd; + asection *sec; + arelent *rel; +{ + bfd_vma val; + struct nlm32_sparc_reloc_ext tmp_reloc = {0}; + int index; + int type = -1; + reloc_howto_type *tmp; + + + for (index = 0; + index < sizeof (nlm32_sparc_howto_table) / sizeof(reloc_howto_type); + index++) { + tmp = &nlm32_sparc_howto_table[index]; + + if (tmp->rightshift == rel->howto->rightshift + && tmp->size == rel->howto->size + && tmp->bitsize == rel->howto->bitsize + && tmp->pc_relative == rel->howto->pc_relative + && tmp->bitpos == rel->howto->bitpos + && tmp->src_mask == rel->howto->src_mask + && tmp->dst_mask == rel->howto->dst_mask) { + type = tmp->type; + break; + } + } + if (type == -1) + abort(); + + /* + * Netware wants a list of relocs for each address. + * Format is: + * long offset + * long addend + * char type + * That should be it. + */ + + /* The value we write out is the offset into the appropriate + segment. This offset is the section vma, adjusted by the vma of + the lowest section in that segment, plus the address of the + relocation. */ + val = bfd_get_section_vma (abfd, sec) + rel->address; + +#ifdef DEBUG + fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n", + __FILE__, val, rel->addend, rel->howto->type); +#endif + bfd_put_32 (abfd, val, tmp_reloc.offset); + bfd_put_32 (abfd, rel->addend, tmp_reloc.addend); + bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type); + + if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12) + { + abort(); + } + + return true; +} + +/* Mangle relocs for SPARC NetWare. We can just use the standard + SPARC relocs. */ + +static boolean +nlm_sparc_mangle_relocs (abfd, sec, data, offset, count) + bfd *abfd; + asection *sec; + PTR data; + bfd_vma offset; + bfd_size_type count; +{ + return true; +} + +/* Read a NetWare sparc import record */ +static boolean +nlm_sparc_read_import (abfd, sym) + bfd *abfd; + nlmNAME(symbol_type) *sym; +{ + struct nlm_relent *nlm_relocs; /* relocation records for symbol */ + bfd_size_type rcount; /* number of relocs */ + bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */ + unsigned char symlength; /* length of symbol name */ + + /* + * First, read in the number of relocation + * entries for this symbol + */ + if (bfd_read ((PTR) temp, 4, 1, abfd) + != 4) + { + bfd_error = system_call_error; + return (false); + } + + rcount = bfd_get_32 (abfd, temp); + + /* + * Next, read in the length of the symbol + */ + + if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd) + != sizeof (symlength)) + { + bfd_error = system_call_error; + return (false); + } + sym -> symbol.the_bfd = abfd; + sym -> symbol.name = bfd_alloc (abfd, symlength + 1); + + /* + * Then read in the symbol + */ + + if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd) + != symlength) + { + bfd_error = system_call_error; + return (false); + } + sym -> symbol.flags = 0; + sym -> symbol.value = 0; + sym -> symbol.section = &bfd_und_section; + + /* + * Next, start reading in the relocs. + */ + + nlm_relocs = ((struct nlm_relent *) + bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); + sym -> relocs = nlm_relocs; + sym -> rcnt = 0; + while (sym -> rcnt < rcount) + { + asection *section; + + if (nlm_sparc_read_reloc (abfd, sym, §ion, + &nlm_relocs -> reloc) + == false) + return false; + nlm_relocs -> section = section; + nlm_relocs++; + sym -> rcnt++; + } + return true; +} + +static boolean +nlm_sparc_write_import (abfd, sec, rel) + bfd *abfd; + asection *sec; + arelent *rel; +{ + char temp[4]; + + bfd_put_32 (abfd, (*rel->sym_ptr_ptr)->value, temp); + bfd_write ((PTR)temp, 4, 1, abfd); + bfd_put_32 (abfd, 1, temp); + bfd_write ((PTR)temp, 4, 1, abfd); + if (nlm_sparc_write_reloc (abfd, sec, rel) == false) + return false; + return true; +} + +/* Write out an external reference. */ + +static boolean +nlm_sparc_write_external (abfd, count, sym, relocs) + bfd *abfd; + bfd_size_type count; + asymbol *sym; + struct reloc_and_sec *relocs; +{ + int i; + bfd_byte len; + unsigned char temp[NLM_TARGET_LONG_SIZE]; + + bfd_put_32 (abfd, count, temp); + if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp)) + { + bfd_error = system_call_error; + return false; + } + + len = strlen (sym->name); + if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte)) + || bfd_write (sym->name, len, 1, abfd) != len) + { + bfd_error = system_call_error; + return false; + } + + for (i = 0; i < count; i++) + { + if (nlm_sparc_write_reloc (abfd, relocs[i].sec, + relocs[i].rel) == false) + return false; + } + + return true; +} + +#undef nlm_swap_fixed_header_in +#undef nlm_swap_fixed_header_out + +#include "nlmswap.h" + +static const struct nlm_backend_data nlm32_sparc_backend = +{ + "NetWare SPARC Module \032", + sizeof (Nlm32_sparc_External_Fixed_Header), + 0, /* optional_prefix_size */ + bfd_arch_sparc, + 0, + 0, /* backend_object_p */ + 0, /* write_prefix_func */ + nlm_sparc_read_reloc, + nlm_sparc_mangle_relocs, + nlm_sparc_read_import, + nlm_sparc_write_import, + 0, /* set_public_section */ + 0, /* get_public_offset */ + nlm_swap_fixed_header_in, + nlm_swap_fixed_header_out, + nlm_sparc_write_external, +}; + +#define TARGET_BIG_NAME "nlm32-sparc" +#define TARGET_BIG_SYM nlmNAME(sparc_vec) +#define TARGET_BACKEND_DATA &nlm32_sparc_backend + +#include "nlm-target.h" diff --git a/bfd/nlmcode.h b/bfd/nlmcode.h index 7944d5f..b7568a5 100644 --- a/bfd/nlmcode.h +++ b/bfd/nlmcode.h @@ -51,14 +51,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define nlm_set_section_contents nlmNAME(set_section_contents) #define nlm_write_object_contents nlmNAME(write_object_contents) +#define nlm_swap_fixed_header_in(abfd,src,dst) \ + (nlm_swap_fixed_header_in_func(abfd))(abfd,src,dst) +#define nlm_swap_fixed_header_out(abfd,src,dst) \ + (nlm_swap_fixed_header_out_func(abfd))(abfd,src,dst) + /* Forward declarations of static functions */ static boolean add_bfd_section PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword)); -static void nlm_swap_fixed_header_in - PARAMS ((bfd *, Nlm_External_Fixed_Header *, Nlm_Internal_Fixed_Header *)); -static void nlm_swap_fixed_header_out - PARAMS ((bfd *, Nlm_Internal_Fixed_Header *, Nlm_External_Fixed_Header *)); static boolean nlm_swap_variable_header_in PARAMS ((bfd *)); static boolean nlm_swap_variable_header_out @@ -92,63 +93,73 @@ static int nlm_external_reloc_compare bfd_target * DEFUN (nlm_object_p, (abfd), bfd * abfd) { - Nlm_External_Fixed_Header x_fxdhdr; /* Nlm file header, external form */ - Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form */ + struct nlm_obj_tdata *preserved_tdata = nlm_tdata (abfd); + boolean (*backend_object_p) PARAMS ((bfd *)); + PTR x_fxdhdr; + Nlm_Internal_Fixed_Header *i_fxdhdrp; + const char *signature; enum bfd_architecture arch; + /* Some NLM formats have a prefix before the standard NLM fixed + header. */ + backend_object_p = nlm_backend_object_p_func (abfd); + if (backend_object_p) + { + if (! (*backend_object_p) (abfd)) + goto got_wrong_format_error; + } + /* Read in the fixed length portion of the NLM header in external format. */ - if (bfd_read ((PTR) &x_fxdhdr, sizeof (x_fxdhdr), 1, abfd) != - sizeof (x_fxdhdr)) + x_fxdhdr = alloca (nlm_fixed_header_size (abfd)); + + if (bfd_read ((PTR) x_fxdhdr, nlm_fixed_header_size (abfd), 1, abfd) != + nlm_fixed_header_size (abfd)) { bfd_error = system_call_error; - return (NULL); + goto got_no_match; } - /* Check to see if we have an NLM file by matching the NLM signature. */ + /* Allocate an instance of the nlm_obj_tdata structure and hook it up to + the tdata pointer in the bfd. */ - if (strncmp (x_fxdhdr.signature, NLM_SIGNATURE, NLM_SIGNATURE_SIZE) != 0) + nlm_tdata (abfd) = (struct nlm_obj_tdata *) + bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata)); + if (nlm_tdata (abfd) == NULL) { - bfd_error = wrong_format; - return (NULL); + bfd_error = no_memory; + goto got_no_match; } + i_fxdhdrp = nlm_fixed_header (abfd); + nlm_swap_fixed_header_in (abfd, x_fxdhdr, i_fxdhdrp); + + /* Check to see if we have an NLM file for this backend by matching + the NLM signature. */ + + signature = nlm_signature (abfd); + if (signature != NULL + && *signature != '\0' + && strncmp ((char *) i_fxdhdrp->signature, signature, + NLM_SIGNATURE_SIZE) != 0) + goto got_wrong_format_error; + /* There's no supported way to discover the endianess of an NLM, so test for a sane version number after doing byte swapping appropriate for this XVEC. (Hack alert!) */ - if (get_word (abfd, (bfd_byte *) x_fxdhdr.version) > 0xFFFF) - { - bfd_error = wrong_format; - return (NULL); - } + if (i_fxdhdrp->version > 0xFFFF) + goto got_wrong_format_error; /* There's no supported way to check for 32 bit versus 64 bit addresses, so ignore this distinction for now. (FIXME) */ - /* Allocate an instance of the nlm_obj_tdata structure and hook it up to - the tdata pointer in the bfd. - FIXME: If we later decide this isn't the right format and the bfd - already had valid tdata, we've just blown away the tdata we wanted - to save for the right format. */ - - nlm_tdata (abfd) = (struct nlm_obj_tdata *) - bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata)); - if (nlm_tdata (abfd) == NULL) - { - bfd_error = no_memory; - return (NULL); - } - /* FIXME: Any return(NULL) exits below here will leak memory (tdata). And a memory leak also means we lost the real tdata info we wanted to save, because it was in the leaked memory. */ /* Swap in the rest of the fixed length header. */ - i_fxdhdrp = nlm_fixed_header (abfd); - nlm_swap_fixed_header_in (abfd, &x_fxdhdr, i_fxdhdrp); - if (!nlm_swap_variable_header_in (abfd) || !nlm_swap_auxiliary_headers_in (abfd) || !add_bfd_section (abfd, NLM_CODE_NAME, @@ -165,10 +176,7 @@ DEFUN (nlm_object_p, (abfd), bfd * abfd) (file_ptr) 0, i_fxdhdrp -> uninitializedDataSize, SEC_ALLOC)) - { - bfd_error = wrong_format; - return (NULL); - } + goto got_wrong_format_error; if (nlm_fixed_header (abfd)->numberOfRelocationFixups != 0 || nlm_fixed_header (abfd)->numberOfExternalReferences != 0) @@ -183,6 +191,12 @@ DEFUN (nlm_object_p, (abfd), bfd * abfd) bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0); return (abfd -> xvec); + + got_wrong_format_error: + bfd_error = wrong_format; + got_no_match: + nlm_tdata (abfd) = preserved_tdata; + return (NULL); } /* Add a section to the bfd. */ @@ -210,124 +224,6 @@ DEFUN (add_bfd_section, (abfd, name, offset, size, flags), return (true); } -/* Translate an NLM fixed length file header in external format into an NLM - file header in internal format. */ - -static void -DEFUN (nlm_swap_fixed_header_in, (abfd, src, dst), - bfd * abfd AND - Nlm_External_Fixed_Header * src AND - Nlm_Internal_Fixed_Header * dst) -{ - memcpy (dst -> signature, src -> signature, NLM_SIGNATURE_SIZE); - memcpy (dst -> moduleName, src -> moduleName, NLM_MODULE_NAME_SIZE); - dst -> version = - get_word (abfd, (bfd_byte *) src -> version); - dst -> codeImageOffset = - get_word (abfd, (bfd_byte *) src -> codeImageOffset); - dst -> codeImageSize = - get_word (abfd, (bfd_byte *) src -> codeImageSize); - dst -> dataImageOffset = - get_word (abfd, (bfd_byte *) src -> dataImageOffset); - dst -> dataImageSize = - get_word (abfd, (bfd_byte *) src -> dataImageSize); - dst -> uninitializedDataSize = - get_word (abfd, (bfd_byte *) src -> uninitializedDataSize); - dst -> customDataOffset = - get_word (abfd, (bfd_byte *) src -> customDataOffset); - dst -> customDataSize = - get_word (abfd, (bfd_byte *) src -> customDataSize); - dst -> moduleDependencyOffset = - get_word (abfd, (bfd_byte *) src -> moduleDependencyOffset); - dst -> numberOfModuleDependencies = - get_word (abfd, (bfd_byte *) src -> numberOfModuleDependencies); - dst -> relocationFixupOffset = - get_word (abfd, (bfd_byte *) src -> relocationFixupOffset); - dst -> numberOfRelocationFixups = - get_word (abfd, (bfd_byte *) src -> numberOfRelocationFixups); - dst -> externalReferencesOffset = - get_word (abfd, (bfd_byte *) src -> externalReferencesOffset); - dst -> numberOfExternalReferences = - get_word (abfd, (bfd_byte *) src -> numberOfExternalReferences); - dst -> publicsOffset = - get_word (abfd, (bfd_byte *) src -> publicsOffset); - dst -> numberOfPublics = - get_word (abfd, (bfd_byte *) src -> numberOfPublics); - dst -> debugInfoOffset = - get_word (abfd, (bfd_byte *) src -> debugInfoOffset); - dst -> numberOfDebugRecords = - get_word (abfd, (bfd_byte *) src -> numberOfDebugRecords); - dst -> codeStartOffset = - get_word (abfd, (bfd_byte *) src -> codeStartOffset); - dst -> exitProcedureOffset = - get_word (abfd, (bfd_byte *) src -> exitProcedureOffset); - dst -> checkUnloadProcedureOffset = - get_word (abfd, (bfd_byte *) src -> checkUnloadProcedureOffset); - dst -> moduleType = - get_word (abfd, (bfd_byte *) src -> moduleType); - dst -> flags = - get_word (abfd, (bfd_byte *) src -> flags); -} - -/* Translate an NLM fixed length file header in internal format into - an NLM file header in external format. */ - -static void -DEFUN (nlm_swap_fixed_header_out, (abfd, src, dst), - bfd * abfd AND - Nlm_Internal_Fixed_Header * src AND - Nlm_External_Fixed_Header * dst) -{ - memcpy (dst -> signature, src -> signature, NLM_SIGNATURE_SIZE); - memcpy (dst -> moduleName, src -> moduleName, NLM_MODULE_NAME_SIZE); - put_word (abfd, (bfd_vma) src -> version, - (bfd_byte *) dst -> version); - put_word (abfd, (bfd_vma) src -> codeImageOffset, - (bfd_byte *) dst -> codeImageOffset); - put_word (abfd, (bfd_vma) src -> codeImageSize, - (bfd_byte *) dst -> codeImageSize); - put_word (abfd, (bfd_vma) src -> dataImageOffset, - (bfd_byte *) dst -> dataImageOffset); - put_word (abfd, (bfd_vma) src -> dataImageSize, - (bfd_byte *) dst -> dataImageSize); - put_word (abfd, (bfd_vma) src -> uninitializedDataSize, - (bfd_byte *) dst -> uninitializedDataSize); - put_word (abfd, (bfd_vma) src -> customDataOffset, - (bfd_byte *) dst -> customDataOffset); - put_word (abfd, (bfd_vma) src -> customDataSize, - (bfd_byte *) dst -> customDataSize); - put_word (abfd, (bfd_vma) src -> moduleDependencyOffset, - (bfd_byte *) dst -> moduleDependencyOffset); - put_word (abfd, (bfd_vma) src -> numberOfModuleDependencies, - (bfd_byte *) dst -> numberOfModuleDependencies); - put_word (abfd, (bfd_vma) src -> relocationFixupOffset, - (bfd_byte *) dst -> relocationFixupOffset); - put_word (abfd, (bfd_vma) src -> numberOfRelocationFixups, - (bfd_byte *) dst -> numberOfRelocationFixups); - put_word (abfd, (bfd_vma) src -> externalReferencesOffset, - (bfd_byte *) dst -> externalReferencesOffset); - put_word (abfd, (bfd_vma) src -> numberOfExternalReferences, - (bfd_byte *) dst -> numberOfExternalReferences); - put_word (abfd, (bfd_vma) src -> publicsOffset, - (bfd_byte *) dst -> publicsOffset); - put_word (abfd, (bfd_vma) src -> numberOfPublics, - (bfd_byte *) dst -> numberOfPublics); - put_word (abfd, (bfd_vma) src -> debugInfoOffset, - (bfd_byte *) dst -> debugInfoOffset); - put_word (abfd, (bfd_vma) src -> numberOfDebugRecords, - (bfd_byte *) dst -> numberOfDebugRecords); - put_word (abfd, (bfd_vma) src -> codeStartOffset, - (bfd_byte *) dst -> codeStartOffset); - put_word (abfd, (bfd_vma) src -> exitProcedureOffset, - (bfd_byte *) dst -> exitProcedureOffset); - put_word (abfd, (bfd_vma) src -> checkUnloadProcedureOffset, - (bfd_byte *) dst -> checkUnloadProcedureOffset); - put_word (abfd, (bfd_vma) src -> moduleType, - (bfd_byte *) dst -> moduleType); - put_word (abfd, (bfd_vma) src -> flags, - (bfd_byte *) dst -> flags); -} - /* Read and swap in the variable length header. All the fields must exist in the NLM, and must exist in the order they are read here. */ @@ -537,7 +433,7 @@ static boolean DEFUN (nlm_swap_auxiliary_headers_in, (abfd), bfd * abfd) { - unsigned char tempstr [16]; + char tempstr [16]; long position; for (;;) @@ -623,6 +519,10 @@ DEFUN (nlm_swap_auxiliary_headers_in, (abfd), get_word (abfd, (bfd_byte *) thdr.sharedPublicsOffset); nlm_extended_header (abfd) -> sharedPublicsCount = get_word (abfd, (bfd_byte *) thdr.sharedPublicsCount); + nlm_extended_header (abfd) -> sharedDebugRecordOffset = + get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordOffset); + nlm_extended_header (abfd) -> sharedDebugRecordCount = + get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordCount); nlm_extended_header (abfd) -> SharedInitializationOffset = get_word (abfd, (bfd_byte *) thdr.sharedInitializationOffset); nlm_extended_header (abfd) -> SharedExitProcedureOffset = @@ -661,7 +561,6 @@ DEFUN (nlm_swap_auxiliary_headers_in, (abfd), } else if (strncmp (tempstr, "CoPyRiGhT=", 10) == 0) { - Nlm_External_Copyright_Header thdr; if (bfd_read ((PTR) &nlm_copyright_header (abfd)->stamp, sizeof (nlm_copyright_header (abfd)->stamp), 1, abfd) @@ -806,6 +705,12 @@ nlm_swap_auxiliary_headers_out (abfd) (bfd_vma) nlm_extended_header (abfd) -> sharedPublicsCount, (bfd_byte *) thdr.sharedPublicsCount); put_word (abfd, + (bfd_vma) nlm_extended_header (abfd) -> sharedDebugRecordOffset, + (bfd_byte *) thdr.sharedDebugRecordOffset); + put_word (abfd, + (bfd_vma) nlm_extended_header (abfd) -> sharedDebugRecordCount, + (bfd_byte *) thdr.sharedDebugRecordCount); + put_word (abfd, (bfd_vma) nlm_extended_header (abfd) -> SharedInitializationOffset, (bfd_byte *) thdr.sharedInitializationOffset); put_word (abfd, @@ -1026,10 +931,9 @@ nlm_slurp_symbol_table (abfd) nlm_symbol_type *sym; /* Pointer to current bfd symbol */ unsigned char symlength; /* Symbol length read into here */ unsigned char symtype; /* Type of debugging symbol */ - bfd_size_type rcount; /* Number of relocs */ bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Symbol offsets read into here */ - boolean (*read_reloc_func) PARAMS ((bfd *, nlm_symbol_type *, asection **, - arelent *)); + boolean (*read_import_func) PARAMS ((bfd *, nlm_symbol_type *)); + boolean (*set_public_section_func) PARAMS ((bfd *, nlm_symbol_type *)); if (nlm_get_symbols (abfd) != NULL) return (true); @@ -1066,6 +970,7 @@ nlm_slurp_symbol_table (abfd) termination of the loop leaves the symcount correct for the symbols that were read. */ + set_public_section_func = nlm_set_public_section_func (abfd); symcount = i_fxdhdrp -> numberOfPublics; while (abfd -> symcount < symcount) { @@ -1083,6 +988,8 @@ nlm_slurp_symbol_table (abfd) bfd_error = system_call_error; return (false); } + /* Cast away const. */ + ((char *) (sym -> symbol.name))[symlength] = '\0'; if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp)) { bfd_error = system_call_error; @@ -1090,17 +997,27 @@ nlm_slurp_symbol_table (abfd) } sym -> symbol.flags = BSF_GLOBAL | BSF_EXPORT; sym -> symbol.value = get_word (abfd, temp); - if (sym -> symbol.value & NLM_HIBIT) + if (set_public_section_func) { - sym -> symbol.value &= ~NLM_HIBIT; - sym -> symbol.flags |= BSF_FUNCTION; - sym -> symbol.section = - bfd_get_section_by_name (abfd, NLM_CODE_NAME); + /* Most backends can use the code below, but unfortunately + some use a different scheme. */ + if ((*set_public_section_func) (abfd, sym) == false) + return false; } else { - sym -> symbol.section = - bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); + if (sym -> symbol.value & NLM_HIBIT) + { + sym -> symbol.value &= ~NLM_HIBIT; + sym -> symbol.flags |= BSF_FUNCTION; + sym -> symbol.section = + bfd_get_section_by_name (abfd, NLM_CODE_NAME); + } + else + { + sym -> symbol.section = + bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); + } } sym -> rcnt = 0; abfd -> symcount++; @@ -1137,6 +1054,8 @@ nlm_slurp_symbol_table (abfd) bfd_error = system_call_error; return (false); } + /* Cast away const. */ + ((char *) (sym -> symbol.name))[symlength] = '\0'; sym -> symbol.flags = BSF_LOCAL; sym -> symbol.value = get_word (abfd, temp); if (symtype == 0) @@ -1163,8 +1082,8 @@ nlm_slurp_symbol_table (abfd) /* Read in the import records. We can only do this if we know how to read relocs for this target. */ - read_reloc_func = nlm_read_reloc_func (abfd); - if (read_reloc_func != NULL) + read_import_func = nlm_read_import_func (abfd); + if (read_import_func != NULL) { if (bfd_seek (abfd, i_fxdhdrp -> externalReferencesOffset, SEEK_SET) == -1) @@ -1176,50 +1095,10 @@ nlm_slurp_symbol_table (abfd) symcount += i_fxdhdrp -> numberOfExternalReferences; while (abfd -> symcount < symcount) { - struct nlm_relent *nlm_relocs; - - if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd) - != sizeof (symlength)) - { - bfd_error = system_call_error; - return (false); - } - sym -> symbol.the_bfd = abfd; - sym -> symbol.name = bfd_alloc (abfd, symlength + 1); - if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd) - != symlength) - { - bfd_error = system_call_error; - return (false); - } - sym -> symbol.flags = 0; - sym -> symbol.value = 0; - sym -> symbol.section = &bfd_und_section; - if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp)) - { - bfd_error = system_call_error; - return (false); - } - rcount = get_word (abfd, temp); - nlm_relocs = ((struct nlm_relent *) - bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); - sym -> relocs = nlm_relocs; - sym -> rcnt = 0; - while (sym -> rcnt < rcount) - { - asection *section; - - if ((*read_reloc_func) (abfd, sym, §ion, - &nlm_relocs -> reloc) - == false) - return false; - nlm_relocs -> section = section; - nlm_relocs++; - sym -> rcnt++; - } - - abfd -> symcount++; + if ((*read_import_func) (abfd, sym) == false) + return false; sym++; + abfd->symcount++; } } @@ -1444,7 +1323,7 @@ nlm_compute_section_file_positions (abfd) abfd->output_has_begun = true; /* The fixed header. */ - sofar = sizeof (Nlm_External_Fixed_Header); + sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd); /* The variable header. */ sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength) @@ -1644,12 +1523,6 @@ nlm_set_section_contents (abfd, section, location, offset, count) /* We need to sort a list of relocs associated with sections when we write out the external relocs. */ -struct reloc_and_sec -{ - arelent *rel; - asection *sec; -}; - static int nlm_external_reloc_compare (p1, p2) const void *p1; @@ -1694,20 +1567,23 @@ boolean nlm_write_object_contents (abfd) bfd *abfd; { - Nlm_External_Fixed_Header fixed_header; asection *sec; - boolean (*write_reloc_func) PARAMS ((bfd *, asection *, arelent *)); + boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *)); bfd_size_type external_reloc_count, internal_reloc_count, i, c; struct reloc_and_sec *external_relocs; asymbol **sym_ptr_ptr; file_ptr last; + boolean (*write_prefix_func) PARAMS ((bfd *)); + unsigned char *fixed_header = alloca (nlm_fixed_header_size (abfd)); if (abfd->output_has_begun == false && nlm_compute_section_file_positions (abfd) == false) return false; /* Write out the variable length headers. */ - if (bfd_seek (abfd, sizeof (Nlm_External_Fixed_Header), SEEK_SET) != 0) + if (bfd_seek (abfd, + nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd), + SEEK_SET) != 0) { bfd_error = system_call_error; return false; @@ -1738,7 +1614,7 @@ nlm_write_object_contents (abfd) /* The format of the relocation entries is dependent upon the particular target. We use an external routine to write the reloc out. */ - write_reloc_func = nlm_write_reloc_func (abfd); + write_import_func = nlm_write_import_func (abfd); /* Write out the internal relocation fixups. While we're looping over the relocs, we also count the external relocs, which is @@ -1753,15 +1629,12 @@ nlm_write_object_contents (abfd) continue; /* We can only represent relocs within a code or data - section. */ + section. We ignore them for a debugging section. */ if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0) - { - bfd_error = invalid_operation; - return false; - } + continue; - /* We need to know how to write out relocs. */ - if (write_reloc_func == NULL) + /* We need to know how to write out imports */ + if (write_import_func == NULL) { bfd_error = invalid_operation; return false; @@ -1780,7 +1653,7 @@ nlm_write_object_contents (abfd) if (bfd_get_section (sym) != &bfd_und_section) { ++internal_reloc_count; - if ((*write_reloc_func) (abfd, sec, rel) == false) + if ((*write_import_func) (abfd, sec, rel) == false) return false; } else @@ -1843,24 +1716,13 @@ nlm_write_object_contents (abfd) { arelent *rel; asymbol *sym; - bfd_byte len; bfd_size_type j, cnt; - bfd_byte temp[NLM_TARGET_LONG_SIZE]; ++c; rel = external_relocs[i].rel; sym = *rel->sym_ptr_ptr; - len = strlen (sym->name); - if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) - != sizeof (bfd_byte)) - || bfd_write (sym->name, len, 1, abfd) != len) - { - bfd_error = system_call_error; - return false; - } - cnt = 0; for (j = i; (j < external_reloc_count @@ -1868,30 +1730,25 @@ nlm_write_object_contents (abfd) j++) ++cnt; - put_word (abfd, (bfd_vma) cnt, temp); - if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp)) - { - bfd_error = system_call_error; - return false; - } + if ((*nlm_write_external_func (abfd)) (abfd, cnt, sym, + &external_relocs[i]) + == false) + return false; - while (cnt-- != 0) - { - if ((*write_reloc_func) (abfd, external_relocs[i].sec, - external_relocs[i].rel) == false) - return false; - ++i; - } + i += cnt; } + nlm_fixed_header (abfd)->numberOfExternalReferences = c; /* Write out the public symbols (exports). */ sym_ptr_ptr = bfd_get_outsymbols (abfd); if (sym_ptr_ptr != (asymbol **) NULL) { + bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *)); asymbol **sym_end; nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd); + get_public_offset_func = nlm_get_public_offset_func (abfd); c = 0; sym_end = sym_ptr_ptr + bfd_get_symcount (abfd); for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++) @@ -1918,24 +1775,33 @@ nlm_write_object_contents (abfd) return false; } - offset = bfd_asymbol_value (sym); - sec = sym->section; - if (sec->flags & SEC_CODE) - { - offset -= nlm_get_text_low (abfd); - offset |= NLM_HIBIT; - } - else if (sec->flags & (SEC_DATA | SEC_ALLOC)) + if (get_public_offset_func) { - /* SEC_ALLOC is for the .bss section. */ - offset -= nlm_get_data_low (abfd); + /* Most backends can use the code below, but + unfortunately some use a different scheme. */ + offset = (*get_public_offset_func) (abfd, sym); } else { - /* We can't handle an exported symbol that is not in the - code or data segment. */ - bfd_error = invalid_operation; - return false; + offset = bfd_asymbol_value (sym); + sec = sym->section; + if (sec->flags & SEC_CODE) + { + offset -= nlm_get_text_low (abfd); + offset |= NLM_HIBIT; + } + else if (sec->flags & (SEC_DATA | SEC_ALLOC)) + { + /* SEC_ALLOC is for the .bss section. */ + offset -= nlm_get_data_low (abfd); + } + else + { + /* We can't handle an exported symbol that is not in + the code or data segment. */ + bfd_error = invalid_operation; + return false; + } } put_word (abfd, offset, temp); @@ -1983,17 +1849,16 @@ nlm_write_object_contents (abfd) ++c; - offset = bfd_asymbol_value (sym); + offset = sym->value; sec = sym->section; if (sec->flags & SEC_CODE) + type = 1; + else if (sec->flags & SEC_DATA) + type = 0; + else if (sec->flags & SEC_ALLOC) { - offset -= nlm_get_text_low (abfd); - type = 1; - } - else if (sec->flags & (SEC_DATA | SEC_ALLOC)) - { - offset -= nlm_get_data_low (abfd); type = 0; + offset += nlm_fixed_header (abfd)->dataImageSize; } else type = 2; @@ -2048,7 +1913,7 @@ nlm_write_object_contents (abfd) /* At this point everything has been written out except the fixed header. */ - memcpy (nlm_fixed_header (abfd)->signature, NLM_SIGNATURE, + memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd), NLM_SIGNATURE_SIZE); nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION; nlm_fixed_header (abfd)->codeStartOffset = @@ -2063,10 +1928,21 @@ nlm_write_object_contents (abfd) nlm_fixed_header (abfd)->checkUnloadProcedureOffset -= nlm_get_text_low (abfd); - nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), &fixed_header); - if (bfd_seek (abfd, 0, SEEK_SET) != 0 - || (bfd_write (&fixed_header, sizeof fixed_header, 1, abfd) - != sizeof fixed_header)) + if (bfd_seek (abfd, 0, SEEK_SET) != 0) + return false; + + write_prefix_func = nlm_write_prefix_func (abfd); + if (write_prefix_func) + { + if ((*write_prefix_func) (abfd) == false) + return false; + } + + BFD_ASSERT (bfd_tell (abfd) == nlm_optional_prefix_size (abfd)); + + nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header); + if (bfd_write (fixed_header, nlm_fixed_header_size (abfd), 1, abfd) + != nlm_fixed_header_size (abfd)) { bfd_error = system_call_error; return false; |