From 6c534df0c9f1b653b392984d1757c2732492ba34 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 21 Apr 1994 16:13:01 +0000 Subject: * libnlm.h (struct nlm_obj_tdata): Add nlm_cygnus_section_hdr field. (nlm_cygnus_section_header): New accessor macro. * nlmcode.h (nlm_object_p): Free new tdata structure if failure. Add fixed sections before swapping in auxiliary headers. After adding sections, treat errors as real, not as wrong format. (nlm_swap_auxiliary_headers_in): Swap in the sections header; add sections to the BFD for each section it describes. (nlm_swap_auxiliary_headers_out): Swap out the sections header. (nlm_compute_section_file_positions): Account for the size of the sections header. --- bfd/ChangeLog | 14 ++++++ bfd/libnlm.h | 2 + bfd/nlmcode.h | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 155 insertions(+), 20 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 51c9156..c69b2c0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +Thu Apr 21 11:58:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * libnlm.h (struct nlm_obj_tdata): Add nlm_cygnus_section_hdr + field. + (nlm_cygnus_section_header): New accessor macro. + * nlmcode.h (nlm_object_p): Free new tdata structure if failure. + Add fixed sections before swapping in auxiliary headers. After + adding sections, treat errors as real, not as wrong format. + (nlm_swap_auxiliary_headers_in): Swap in the sections header; add + sections to the BFD for each section it describes. + (nlm_swap_auxiliary_headers_out): Swap out the sections header. + (nlm_compute_section_file_positions): Account for the size of the + sections header. + Wed Apr 20 16:45:51 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * coff-sparc.c (sparccoff_vec): Change minimum alignment power to diff --git a/bfd/libnlm.h b/bfd/libnlm.h index cf6885d..acdfcdf 100644 --- a/bfd/libnlm.h +++ b/bfd/libnlm.h @@ -91,6 +91,7 @@ struct nlm_obj_tdata Nlm_Internal_Copyright_Header nlm_copyright_hdr[1]; Nlm_Internal_Extended_Header nlm_extended_hdr[1]; Nlm_Internal_Custom_Header nlm_custom_hdr[1]; + Nlm_Internal_Cygnus_Section_Header nlm_cygnus_section_hdr[1]; /* BFD NLM symbols. */ nlmNAME(symbol_type) *nlm_symbols; /* Lowest text and data VMA values. */ @@ -122,6 +123,7 @@ struct nlm_obj_tdata #define nlm_copyright_header(bfd) (nlm_tdata(bfd) -> nlm_copyright_hdr) #define nlm_extended_header(bfd) (nlm_tdata(bfd) -> nlm_extended_hdr) #define nlm_custom_header(bfd) (nlm_tdata(bfd) -> nlm_custom_hdr) +#define nlm_cygnus_section_header(bfd) (nlm_tdata(bfd)->nlm_cygnus_section_hdr) #define nlm_get_symbols(bfd) (nlm_tdata(bfd) -> nlm_symbols) #define nlm_set_symbols(bfd, p) (nlm_tdata(bfd) -> nlm_symbols = (p)) #define nlm_set_text_low(bfd, i) (nlm_tdata(bfd) -> nlm_text_low = (i)) diff --git a/bfd/nlmcode.h b/bfd/nlmcode.h index 61e748f..6655a6f 100644 --- a/bfd/nlmcode.h +++ b/bfd/nlmcode.h @@ -38,6 +38,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define Nlm_External_Copyright_Header NlmNAME(External_Copyright_Header) #define Nlm_External_Extended_Header NlmNAME(External_Extended_Header) #define Nlm_External_Custom_Header NlmNAME(External_Custom_Header) +#define Nlm_External_Cygnus_Section_Header \ + NlmNAME(External_Cygnus_Section_Header) #define nlm_symbol_type nlmNAME(symbol_type) #define nlm_get_symtab_upper_bound nlmNAME(get_symtab_upper_bound) @@ -98,6 +100,7 @@ nlm_object_p (abfd) boolean (*backend_object_p) PARAMS ((bfd *)); PTR x_fxdhdr = NULL; Nlm_Internal_Fixed_Header *i_fxdhdrp; + struct nlm_obj_tdata *new_tdata = NULL; const char *signature; enum bfd_architecture arch; @@ -131,16 +134,20 @@ nlm_object_p (abfd) /* Allocate an instance of the nlm_obj_tdata structure and hook it up to the tdata pointer in the bfd. */ - nlm_tdata (abfd) = (struct nlm_obj_tdata *) - bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata)); - if (nlm_tdata (abfd) == NULL) + new_tdata = ((struct nlm_obj_tdata *) + bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata))); + if (new_tdata == NULL) { bfd_set_error (bfd_error_no_memory); goto got_no_match; } + nlm_tdata (abfd) = new_tdata; + i_fxdhdrp = nlm_fixed_header (abfd); nlm_swap_fixed_header_in (abfd, x_fxdhdr, i_fxdhdrp); + free (x_fxdhdr); + x_fxdhdr = NULL; /* Check to see if we have an NLM file for this backend by matching the NLM signature. */ @@ -162,29 +169,39 @@ nlm_object_p (abfd) /* There's no supported way to check for 32 bit versus 64 bit addresses, so ignore this distinction for now. (FIXME) */ - /* 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. */ + /* Swap in the rest of the required header. */ + if (!nlm_swap_variable_header_in (abfd)) + { + if (bfd_get_error () != bfd_error_system_call) + goto got_wrong_format_error; + else + goto got_no_match; + } - if (!nlm_swap_variable_header_in (abfd) - || !nlm_swap_auxiliary_headers_in (abfd) - || !add_bfd_section (abfd, NLM_CODE_NAME, - i_fxdhdrp->codeImageOffset, - i_fxdhdrp->codeImageSize, - (SEC_CODE | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS - | SEC_RELOC)) + /* Add the sections supplied by all NLM's, and then read in the + auxiliary headers. Reading the auxiliary headers may create + additional sections described in the cygnus_sections header. + From this point on we assume that we have an NLM, and do not + treat errors as indicating the wrong format. */ + + if (!add_bfd_section (abfd, NLM_CODE_NAME, + i_fxdhdrp->codeImageOffset, + i_fxdhdrp->codeImageSize, + (SEC_CODE | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_RELOC)) || !add_bfd_section (abfd, NLM_INITIALIZED_DATA_NAME, i_fxdhdrp->dataImageOffset, i_fxdhdrp->dataImageSize, - (SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS - | SEC_RELOC)) + (SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_RELOC)) || !add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME, (file_ptr) 0, i_fxdhdrp->uninitializedDataSize, SEC_ALLOC)) - goto got_wrong_format_error; + goto got_no_match; + + if (!nlm_swap_auxiliary_headers_in (abfd)) + goto got_no_match; if (nlm_fixed_header (abfd)->numberOfRelocationFixups != 0 || nlm_fixed_header (abfd)->numberOfExternalReferences != 0) @@ -198,14 +215,14 @@ nlm_object_p (abfd) if (arch != bfd_arch_unknown) bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0); - if (x_fxdhdr != NULL) - free (x_fxdhdr); return (abfd->xvec); got_wrong_format_error: bfd_set_error (bfd_error_wrong_format); got_no_match: nlm_tdata (abfd) = preserved_tdata; + if (new_tdata != NULL) + bfd_release (abfd, new_tdata); if (x_fxdhdr != NULL) free (x_fxdhdr); return (NULL); @@ -524,6 +541,90 @@ nlm_swap_auxiliary_headers_in (abfd) nlm_copyright_header (abfd)->copyrightMessageLength + 1) return (false); } + else if (strncmp (tempstr, "CyGnUsSeCs", 10) == 0) + { + Nlm_External_Cygnus_Section_Header thdr; + bfd_size_type len; + file_ptr pos; + bfd_byte *contents; + bfd_byte *p, *pend; + + if (bfd_read ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr)) + return false; + memcpy (nlm_cygnus_section_header (abfd)->stamp, thdr.stamp, + sizeof (thdr.stamp)); + nlm_cygnus_section_header (abfd)->offset = + get_word (abfd, (bfd_byte *) thdr.offset); + len = get_word (abfd, (bfd_byte *) thdr.length); + nlm_cygnus_section_header (abfd)->length = len; + + /* This data this header points to provides a list of the + sections which were in the original object file which was + converted to become an NLM. We locate those sections and + add them to the BFD. Note that this is likely to create + a second .text, .data and .bss section; retrieving the + sections by name will get the actual NLM sections, which + is what we want to happen. The sections from the + original file, which may be subsets of the NLM section, + can only be found using bfd_map_over_sections. */ + contents = (bfd_byte *) malloc (len); + if (contents == (bfd_byte *) NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + pos = bfd_tell (abfd); + if (bfd_seek (abfd, nlm_cygnus_section_header (abfd)->offset, + SEEK_SET) != 0 + || bfd_read (contents, len, 1, abfd) != len) + { + free (contents); + return false; + } + p = contents; + pend = p + len; + while (p < pend) + { + char *name; + size_t l; + file_ptr filepos; + bfd_size_type size; + asection *newsec; + + /* The format of this information is + null terminated section name + zeroes to adjust to 4 byte boundary + 4 byte section data file pointer + 4 byte section size + */ + + name = p; + l = strlen (name) + 1; + l = (l + 3) &~ 3; + p += l; + filepos = bfd_h_get_32 (abfd, p); + p += 4; + size = bfd_h_get_32 (abfd, p); + p += 4; + + newsec = bfd_make_section_anyway (abfd, name); + if (newsec == (asection *) NULL) + { + free (contents); + return false; + } + newsec->_raw_size = size; + if (filepos != 0) + { + newsec->filepos = filepos; + newsec->flags |= SEC_HAS_CONTENTS; + } + } + + free (contents); + if (bfd_seek (abfd, pos, SEEK_SET) != 0) + return false; + } else { break; @@ -719,6 +820,21 @@ nlm_swap_auxiliary_headers_out (abfd) return false; } + /* Write out the Cygnus debugging header if there is one. */ + if (find_nonzero ((PTR) nlm_cygnus_section_header (abfd), + sizeof (Nlm_Internal_Cygnus_Section_Header))) + { + Nlm_External_Cygnus_Section_Header thdr; + + memcpy (thdr.stamp, "CyGnUsSeCs", 10); + put_word (abfd, (bfd_vma) nlm_cygnus_section_header (abfd)->offset, + (bfd_byte *) thdr.offset); + put_word (abfd, (bfd_vma) nlm_cygnus_section_header (abfd)->length, + (bfd_byte *) thdr.length); + if (bfd_write ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr)) + return false; + } + return true; } @@ -1259,6 +1375,9 @@ nlm_compute_section_file_positions (abfd) sizeof (Nlm_Internal_Copyright_Header))) sofar += (sizeof (Nlm_External_Copyright_Header) + nlm_copyright_header (abfd)->copyrightMessageLength + 1); + if (find_nonzero ((PTR) nlm_cygnus_section_header (abfd), + sizeof (Nlm_Internal_Cygnus_Section_Header))) + sofar += sizeof (Nlm_External_Cygnus_Section_Header); /* Compute the section file positions in two passes. First get the sizes of the text and data sections, and then set the file -- cgit v1.1