diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b076c001fd..70bc39a23c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +Mon Jan 29 11:34:36 1996 Kim Knuttila + + * cofflink.c: removed the POWERPC_LE_PE hack, promoted some types + and made a few static functions externs. + + * coff-ppc.c (ppc_bfd_coff_final_link): new function, replaces the + POWERPC_LE_PE hack in cofflink. + + * libcoff-in.h: promoted the following from cofflink.c to allow + _bfd_coff_final_link to be overridden - STRING_SIZE_SIZE, + coff_debug_merge_element, struct coff_debug_merge_type, + coff_debug_merge_hash_entry, coff_debug_merge_hash_table, + coff_debug_merge_hash_table_init, coff_debug_merge_hash_table_free, + coff_debug_merge_hash_lookup, coff_link_section_info, + coff_final_link_info, coff_debug_merge_hash_newfunc, + coff_write_global_sym, coff_link_input_bfd, coff_reloc_link_order. + + * libcoff.h: re-gen'd + Fri Jan 26 18:33:35 1996 Ian Lance Taylor * syms.c: Include "bfdlink.h". diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c index 00509a3059..76c20569da 100644 --- a/bfd/coff-ppc.c +++ b/bfd/coff-ppc.c @@ -1,5 +1,5 @@ /* BFD back-end for PowerPC Microsoft Portable Executable files. - Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. Original version pieced together by Kim Knuttila (krk@cygnus.com) @@ -34,6 +34,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "sysdep.h" + #include "libbfd.h" #include "obstack.h" @@ -1234,9 +1235,10 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, #ifdef DEBUG_RELOC fprintf(stderr, - "pe_ppc_relocate_section (%s) for %s \n", + "pe_ppc_relocate_section (%s) for %s in bfd %s\n", TARGET_LITTLE_NAME, - input_section->name); + input_section->name, + input_bfd->filename); #endif @@ -1337,6 +1339,8 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, } else { +fprintf(stderr, + "missing %s\n",h->root.root.root.string); if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.root.string, input_bfd, input_section, rel->r_vaddr - input_section->vma))) @@ -1370,8 +1374,9 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, #ifdef TOC_DEBUG fprintf(stderr, - "BFD of toc owner %p, section addr of %s %p\n", - bfd_of_toc_owner, TOC_SECTION_NAME, toc_section); + "BFD of toc owner %p (%s), section addr of %s %p\n", + bfd_of_toc_owner, bfd_of_toc_owner->filename, + TOC_SECTION_NAME, toc_section); #endif if ( toc_section == NULL ) @@ -1443,8 +1448,12 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, our_toc_offset = h->toc_offset; if ((r_flags & IMAGE_REL_PPC_TOCDEFN) - == IMAGE_REL_PPC_TOCDEFN + == IMAGE_REL_PPC_TOCDEFN ) +#if 0 + /* This is wrong. If tocdefn is on, we must unconditionally + assume the following path */ && IS_UNALLOCATED(our_toc_offset)) +#endif { /* This is unbelievable cheese. Some knowledgable asm hacker has decided to use r2 as a base for loading @@ -1460,10 +1469,21 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, dll linkage, takes advantage of that and considers the IAT to be part of the toc, thus saving a load. */ +#ifdef DEBUG_RELOC + fprintf(stderr, + "TOCDEFN is on, (%s) (%p) our_toc_offset = %x\n", + name, h, our_toc_offset); +#endif + our_toc_offset = val - (toc_section->output_section->vma + toc_section->output_offset); +#ifdef DEBUG_RELOC + fprintf(stderr, + " our_toc_offset set to %x\n", our_toc_offset); +#endif + /* The size must still fit in a 16bit displacment */ if (our_toc_offset >= 65535) { @@ -1632,6 +1652,38 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, struct coff_link_hash_entry *myh = 0; const char *name = 0; DUMP_RELOC2(howto->name, rel); + + if (strncmp(".idata$2",input_section->name,8) == 0 && first_thunk_address == 0) + { + /* set magic values */ + int idata5offset; + struct coff_link_hash_entry *myh = 0; + myh = coff_link_hash_lookup (coff_hash_table (info), + "__idata5_magic__", + false, false, true); + first_thunk_address = myh->root.u.def.value + + sec->output_section->vma + + sec->output_offset - + pe_data(output_bfd)->pe_opthdr.ImageBase; + + idata5offset = myh->root.u.def.value; + myh = coff_link_hash_lookup (coff_hash_table (info), + "__idata6_magic__", + false, false, true); + + thunk_size = myh->root.u.def.value - idata5offset; + myh = coff_link_hash_lookup (coff_hash_table (info), + "__idata4_magic__", + false, false, true); + import_table_size = myh->root.u.def.value; +#ifdef DEBUG_RELOC + fprintf(stderr, + "first computation triggered fta %x, ts %d(%x), its %d(%x)\n", + first_thunk_address, thunk_size, thunk_size, import_table_size, + import_table_size); +#endif + } + if (h == 0) { /* it is a file local symbol */ sym = syms + symndx; @@ -1686,6 +1738,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, "__idata4_magic__", false, false, true); import_table_size = myh->root.u.def.value; +#ifdef DEBUG_RELOC + + fprintf(stderr, + "second computation triggered fta %x, ts %d(%x), its %d(%x)\n", + first_thunk_address, thunk_size, thunk_size, import_table_size, + import_table_size); +#endif } } } @@ -1789,18 +1848,38 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_vaddr - input_section->vma))) - return false; + { +#ifdef DEBUG_RELOC + fprintf(stderr, + "pe_ppc_relocate_section (%s) for %s in bfd %s RETURNING TRUE\n", + TARGET_LITTLE_NAME, + input_section->name, + input_bfd->filename); + +#endif + return false; + } } } } +#ifdef DEBUG_RELOC + fprintf(stderr, + "pe_ppc_relocate_section (%s) for %s in bfd %s RETURNING TRUE\n", + TARGET_LITTLE_NAME, + input_section->name, + input_bfd->filename); + +#endif + return true; } + #ifdef COFF_IMAGE_WITH_PE -long int global_toc_size = 0; +long int global_toc_size = 4; bfd* bfd_of_toc_owner = 0; @@ -1845,7 +1924,12 @@ dump_toc(vfile) if (t->offset <= global_toc_size + thunk_size) cat = "IAT reference "; else - cat = "Out of bounds!"; + { + fprintf(file, + "**** global_toc_size %d(%x), thunk_size %d(%x)\n", + global_toc_size, global_toc_size, thunk_size, thunk_size); + cat = "Out of bounds!"; + } } fprintf(file, @@ -2467,6 +2551,7 @@ ppc_coff_swap_sym_in_hook (); #define coff_bfd_reloc_type_lookup ppc_coff_reloc_type_lookup #define coff_rtype_to_howto coff_ppc_rtype_to_howto #define coff_relocate_section coff_ppc_relocate_section +#define coff_bfd_final_link ppc_bfd_coff_final_link #ifndef COFF_IMAGE_WITH_PE #define coff_swap_sym_in_hook ppc_coff_swap_sym_in_hook @@ -2506,10 +2591,8 @@ ppc_coff_swap_sym_in_hook (abfd, ext1, in1) SYMENT *ext = (SYMENT *)ext1; struct internal_syment *in = (struct internal_syment *)in1; -#if 0 if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */ return; -#endif if (strcmp(in->_n._n_name, ".toc") == 0) { @@ -2550,6 +2633,528 @@ ppc_coff_swap_sym_in_hook (abfd, ext1, in1) } #endif +boolean +ppc_bfd_coff_final_link (); + +#ifndef COFF_IMAGE_WITH_PE + +static boolean +ppc_do_last(abfd) + bfd *abfd; +{ + if (abfd == bfd_of_toc_owner) + return true; + else + return false; +} + +static bfd * +ppc_get_last() +{ + return bfd_of_toc_owner; +} + +/* this piece of machinery exists only to guarantee that the bfd that holds + the toc section is written last. + + This does depend on bfd_make_section attaching a new section to the + end of the section list for the bfd. + + This is otherwise intended to be functionally the same as + cofflink.c:_bfd_coff_final_link(). It is specifically different only + where the POWERPC_LE_PE macro modifies the code. It is left in as a + precise form of comment. krk@cygnus.com +*/ +#define POWERPC_LE_PE + + +/* Do the final link step. */ + +boolean +ppc_bfd_coff_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + bfd_size_type symesz; + struct coff_final_link_info finfo; + boolean debug_merge_allocated; + asection *o; + struct bfd_link_order *p; + size_t max_sym_count; + size_t max_lineno_count; + size_t max_reloc_count; + size_t max_output_reloc_count; + size_t max_contents_size; + file_ptr rel_filepos; + unsigned int relsz; + file_ptr line_filepos; + unsigned int linesz; + bfd *sub; + bfd_byte *external_relocs = NULL; + char strbuf[STRING_SIZE_SIZE]; + + symesz = bfd_coff_symesz (abfd); + + finfo.info = info; + finfo.output_bfd = abfd; + finfo.strtab = NULL; + finfo.section_info = NULL; + finfo.last_file_index = -1; + finfo.internal_syms = NULL; + finfo.sec_ptrs = NULL; + finfo.sym_indices = NULL; + finfo.outsyms = NULL; + finfo.linenos = NULL; + finfo.contents = NULL; + finfo.external_relocs = NULL; + finfo.internal_relocs = NULL; + debug_merge_allocated = false; + + coff_data (abfd)->link_info = info; + + finfo.strtab = _bfd_stringtab_init (); + if (finfo.strtab == NULL) + goto error_return; + + if (! coff_debug_merge_hash_table_init (&finfo.debug_merge)) + goto error_return; + debug_merge_allocated = true; + + /* Compute the file positions for all the sections. */ + if (! abfd->output_has_begun) + bfd_coff_compute_section_file_positions (abfd); + + /* Count the line numbers and relocation entries required for the + output file. Set the file positions for the relocs. */ + rel_filepos = obj_relocbase (abfd); + relsz = bfd_coff_relsz (abfd); + max_contents_size = 0; + max_lineno_count = 0; + max_reloc_count = 0; + + for (o = abfd->sections; o != NULL; o = o->next) + { + o->reloc_count = 0; + o->lineno_count = 0; + for (p = o->link_order_head; p != NULL; p = p->next) + { + + if (p->type == bfd_indirect_link_order) + { + asection *sec; + + sec = p->u.indirect.section; + + if (info->strip == strip_none + || info->strip == strip_some) + o->lineno_count += sec->lineno_count; + + if (info->relocateable) + o->reloc_count += sec->reloc_count; + + if (sec->_raw_size > max_contents_size) + max_contents_size = sec->_raw_size; + if (sec->lineno_count > max_lineno_count) + max_lineno_count = sec->lineno_count; + if (sec->reloc_count > max_reloc_count) + max_reloc_count = sec->reloc_count; + } + else if (info->relocateable + && (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order)) + ++o->reloc_count; + } + if (o->reloc_count == 0) + o->rel_filepos = 0; + else + { + o->flags |= SEC_RELOC; + o->rel_filepos = rel_filepos; + rel_filepos += o->reloc_count * relsz; + } + } + + /* If doing a relocateable link, allocate space for the pointers we + need to keep. */ + if (info->relocateable) + { + unsigned int i; + + /* We use section_count + 1, rather than section_count, because + the target_index fields are 1 based. */ + finfo.section_info = + ((struct coff_link_section_info *) + bfd_malloc ((abfd->section_count + 1) + * sizeof (struct coff_link_section_info))); + if (finfo.section_info == NULL) + goto error_return; + for (i = 0; i <= abfd->section_count; i++) + { + finfo.section_info[i].relocs = NULL; + finfo.section_info[i].rel_hashes = NULL; + } + } + + /* We now know the size of the relocs, so we can determine the file + positions of the line numbers. */ + line_filepos = rel_filepos; + linesz = bfd_coff_linesz (abfd); + max_output_reloc_count = 0; + for (o = abfd->sections; o != NULL; o = o->next) + { + if (o->lineno_count == 0) + o->line_filepos = 0; + else + { + o->line_filepos = line_filepos; + line_filepos += o->lineno_count * linesz; + } + + if (o->reloc_count != 0) + { + /* We don't know the indices of global symbols until we have + written out all the local symbols. For each section in + the output file, we keep an array of pointers to hash + table entries. Each entry in the array corresponds to a + reloc. When we find a reloc against a global symbol, we + set the corresponding entry in this array so that we can + fix up the symbol index after we have written out all the + local symbols. + + Because of this problem, we also keep the relocs in + memory until the end of the link. This wastes memory, + but only when doing a relocateable link, which is not the + common case. */ + BFD_ASSERT (info->relocateable); + finfo.section_info[o->target_index].relocs = + ((struct internal_reloc *) + bfd_malloc (o->reloc_count * sizeof (struct internal_reloc))); + finfo.section_info[o->target_index].rel_hashes = + ((struct coff_link_hash_entry **) + bfd_malloc (o->reloc_count + * sizeof (struct coff_link_hash_entry *))); + if (finfo.section_info[o->target_index].relocs == NULL + || finfo.section_info[o->target_index].rel_hashes == NULL) + goto error_return; + + if (o->reloc_count > max_output_reloc_count) + max_output_reloc_count = o->reloc_count; + } + + /* Reset the reloc and lineno counts, so that we can use them to + count the number of entries we have output so far. */ + o->reloc_count = 0; + o->lineno_count = 0; + } + + obj_sym_filepos (abfd) = line_filepos; + + /* Figure out the largest number of symbols in an input BFD. Take + the opportunity to clear the output_has_begun fields of all the + input BFD's. */ + max_sym_count = 0; + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + { + size_t sz; + + sub->output_has_begun = false; + sz = obj_raw_syment_count (sub); + if (sz > max_sym_count) + max_sym_count = sz; + } + + /* Allocate some buffers used while linking. */ + finfo.internal_syms = ((struct internal_syment *) + bfd_malloc (max_sym_count + * sizeof (struct internal_syment))); + finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count + * sizeof (asection *)); + finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long)); + finfo.outsyms = ((bfd_byte *) + bfd_malloc ((size_t) ((max_sym_count + 1) * symesz))); + finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count + * bfd_coff_linesz (abfd)); + finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); + finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz); + if (! info->relocateable) + finfo.internal_relocs = ((struct internal_reloc *) + bfd_malloc (max_reloc_count + * sizeof (struct internal_reloc))); + if ((finfo.internal_syms == NULL && max_sym_count > 0) + || (finfo.sec_ptrs == NULL && max_sym_count > 0) + || (finfo.sym_indices == NULL && max_sym_count > 0) + || finfo.outsyms == NULL + || (finfo.linenos == NULL && max_lineno_count > 0) + || (finfo.contents == NULL && max_contents_size > 0) + || (finfo.external_relocs == NULL && max_reloc_count > 0) + || (! info->relocateable + && finfo.internal_relocs == NULL + && max_reloc_count > 0)) + goto error_return; + + /* We now know the position of everything in the file, except that + we don't know the size of the symbol table and therefore we don't + know where the string table starts. We just build the string + table in memory as we go along. We process all the relocations + for a single input file at once. */ + obj_raw_syment_count (abfd) = 0; + + if (coff_backend_info (abfd)->_bfd_coff_start_final_link) + { + if (! bfd_coff_start_final_link (abfd, info)) + goto error_return; + } + + for (o = abfd->sections; o != NULL; o = o->next) + { + for (p = o->link_order_head; p != NULL; p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_coff_flavour)) + { + sub = p->u.indirect.section->owner; +#ifdef POWERPC_LE_PE + if (! sub->output_has_begun && !ppc_do_last(sub)) +#else + if (! sub->output_has_begun) +#endif + { + if (! coff_link_input_bfd (&finfo, sub)) + goto error_return; + sub->output_has_begun = true; + } + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! coff_reloc_link_order (abfd, &finfo, o, p)) + goto error_return; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + goto error_return; + } + } + } + +#ifdef POWERPC_LE_PE + { + extern bfd* ppc_get_last(); + bfd* last_one = ppc_get_last(); + if (last_one) + { + if (! coff_link_input_bfd (&finfo, last_one)) + goto error_return; + } + last_one->output_has_begun = true; + } +#endif + + /* Free up the buffers used by coff_link_input_bfd. */ + + coff_debug_merge_hash_table_free (&finfo.debug_merge); + debug_merge_allocated = false; + + if (finfo.internal_syms != NULL) + { + free (finfo.internal_syms); + finfo.internal_syms = NULL; + } + if (finfo.sec_ptrs != NULL) + { + free (finfo.sec_ptrs); + finfo.sec_ptrs = NULL; + } + if (finfo.sym_indices != NULL) + { + free (finfo.sym_indices); + finfo.sym_indices = NULL; + } + if (finfo.linenos != NULL) + { + free (finfo.linenos); + finfo.linenos = NULL; + } + if (finfo.contents != NULL) + { + free (finfo.contents); + finfo.contents = NULL; + } + if (finfo.external_relocs != NULL) + { + free (finfo.external_relocs); + finfo.external_relocs = NULL; + } + if (finfo.internal_relocs != NULL) + { + free (finfo.internal_relocs); + finfo.internal_relocs = NULL; + } + + /* The value of the last C_FILE symbol is supposed to be the symbol + index of the first external symbol. Write it out again if + necessary. */ + if (finfo.last_file_index != -1 + && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd)) + { + finfo.last_file.n_value = obj_raw_syment_count (abfd); + bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file, + (PTR) finfo.outsyms); + if (bfd_seek (abfd, + (obj_sym_filepos (abfd) + + finfo.last_file_index * symesz), + SEEK_SET) != 0 + || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz) + return false; + } + + /* Write out the global symbols. */ + finfo.failed = false; + coff_link_hash_traverse (coff_hash_table (info), coff_write_global_sym, + (PTR) &finfo); + if (finfo.failed) + goto error_return; + + /* The outsyms buffer is used by coff_write_global_sym. */ + if (finfo.outsyms != NULL) + { + free (finfo.outsyms); + finfo.outsyms = NULL; + } + + if (info->relocateable) + { + /* Now that we have written out all the global symbols, we know + the symbol indices to use for relocs against them, and we can + finally write out the relocs. */ + external_relocs = ((bfd_byte *) + bfd_malloc (max_output_reloc_count * relsz)); + if (external_relocs == NULL) + goto error_return; + + for (o = abfd->sections; o != NULL; o = o->next) + { + struct internal_reloc *irel; + struct internal_reloc *irelend; + struct coff_link_hash_entry **rel_hash; + bfd_byte *erel; + + if (o->reloc_count == 0) + continue; + + irel = finfo.section_info[o->target_index].relocs; + irelend = irel + o->reloc_count; + rel_hash = finfo.section_info[o->target_index].rel_hashes; + erel = external_relocs; + for (; irel < irelend; irel++, rel_hash++, erel += relsz) + { + if (*rel_hash != NULL) + { + BFD_ASSERT ((*rel_hash)->indx >= 0); + irel->r_symndx = (*rel_hash)->indx; + } + bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel); + } + + if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0 + || bfd_write ((PTR) external_relocs, relsz, o->reloc_count, + abfd) != relsz * o->reloc_count) + goto error_return; + } + + free (external_relocs); + external_relocs = NULL; + } + + /* Free up the section information. */ + if (finfo.section_info != NULL) + { + unsigned int i; + + for (i = 0; i < abfd->section_count; i++) + { + if (finfo.section_info[i].relocs != NULL) + free (finfo.section_info[i].relocs); + if (finfo.section_info[i].rel_hashes != NULL) + free (finfo.section_info[i].rel_hashes); + } + free (finfo.section_info); + finfo.section_info = NULL; + } + + /* Write out the string table. */ + if (obj_raw_syment_count (abfd) != 0) + { + if (bfd_seek (abfd, + (obj_sym_filepos (abfd) + + obj_raw_syment_count (abfd) * symesz), + SEEK_SET) != 0) + return false; + +#if STRING_SIZE_SIZE == 4 + bfd_h_put_32 (abfd, + _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE, + (bfd_byte *) strbuf); +#else + #error Change bfd_h_put_32 +#endif + + if (bfd_write (strbuf, 1, STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE) + return false; + + if (! _bfd_stringtab_emit (abfd, finfo.strtab)) + return false; + } + + _bfd_stringtab_free (finfo.strtab); + + /* Setting bfd_get_symcount to 0 will cause write_object_contents to + not try to write out the symbols. */ + bfd_get_symcount (abfd) = 0; + + return true; + + error_return: + if (debug_merge_allocated) + coff_debug_merge_hash_table_free (&finfo.debug_merge); + if (finfo.strtab != NULL) + _bfd_stringtab_free (finfo.strtab); + if (finfo.section_info != NULL) + { + unsigned int i; + + for (i = 0; i < abfd->section_count; i++) + { + if (finfo.section_info[i].relocs != NULL) + free (finfo.section_info[i].relocs); + if (finfo.section_info[i].rel_hashes != NULL) + free (finfo.section_info[i].rel_hashes); + } + free (finfo.section_info); + } + if (finfo.internal_syms != NULL) + free (finfo.internal_syms); + if (finfo.sec_ptrs != NULL) + free (finfo.sec_ptrs); + if (finfo.sym_indices != NULL) + free (finfo.sym_indices); + if (finfo.outsyms != NULL) + free (finfo.outsyms); + if (finfo.linenos != NULL) + free (finfo.linenos); + if (finfo.contents != NULL) + free (finfo.contents); + if (finfo.external_relocs != NULL) + free (finfo.external_relocs); + if (finfo.internal_relocs != NULL) + free (finfo.internal_relocs); + if (external_relocs != NULL) + free (external_relocs); + return false; +} +#endif /* The transfer vectors that lead the outside world to all of the above. */ @@ -2560,8 +3165,8 @@ TARGET_LITTLE_SYM = { TARGET_LITTLE_NAME, /* name or coff-arm-little */ bfd_target_coff_flavour, - false, /* data byte order is little */ - false, /* header byte order is little */ + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ (HAS_RELOC | EXEC_P | /* FIXME: object flags */ HAS_LINENO | HAS_DEBUG | @@ -2607,8 +3212,8 @@ TARGET_BIG_SYM = { TARGET_BIG_NAME, bfd_target_coff_flavour, - true, /* data byte order is big */ - true, /* header byte order is big */ + BFD_ENDIAN_BIG, /* data byte order is big */ + BFD_ENDIAN_BIG, /* header byte order is big */ (HAS_RELOC | EXEC_P | /* FIXME: object flags */ HAS_LINENO | HAS_DEBUG | diff --git a/bfd/cofflink.c b/bfd/cofflink.c index 78baf88657..2de8f988b8 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -27,134 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "coff/internal.h" #include "libcoff.h" -#define STRING_SIZE_SIZE (4) - -/* We use a hash table to merge identical enum, struct, and union - definitions in the linker. */ - -/* Information we keep for a single element (an enum value, a - structure or union field) in the debug merge hash table. */ - -struct coff_debug_merge_element -{ - /* Next element. */ - struct coff_debug_merge_element *next; - - /* Name. */ - const char *name; - - /* Type. */ - unsigned int type; - - /* Symbol index for complex type. */ - long tagndx; -}; - -/* A linked list of debug merge entries for a given name. */ - -struct coff_debug_merge_type -{ - /* Next type with the same name. */ - struct coff_debug_merge_type *next; - - /* Class of type. */ - int class; - - /* Symbol index where this type is defined. */ - long indx; - - /* List of elements. */ - struct coff_debug_merge_element *elements; -}; - -/* Information we store in the debug merge hash table. */ - -struct coff_debug_merge_hash_entry -{ - struct bfd_hash_entry root; - - /* A list of types with this name. */ - struct coff_debug_merge_type *types; -}; - -/* The debug merge hash table. */ - -struct coff_debug_merge_hash_table -{ - struct bfd_hash_table root; -}; - -/* Initialize a COFF debug merge hash table. */ - -#define coff_debug_merge_hash_table_init(table) \ - (bfd_hash_table_init (&(table)->root, coff_debug_merge_hash_newfunc)) - -/* Free a COFF debug merge hash table. */ - -#define coff_debug_merge_hash_table_free(table) \ - (bfd_hash_table_free (&(table)->root)) - -/* Look up an entry in a COFF debug merge hash table. */ - -#define coff_debug_merge_hash_lookup(table, string, create, copy) \ - ((struct coff_debug_merge_hash_entry *) \ - bfd_hash_lookup (&(table)->root, (string), (create), (copy))) - -/* Information we keep for each section in the output file when doing - a relocateable link. */ - -struct coff_link_section_info -{ - /* The relocs to be output. */ - struct internal_reloc *relocs; - /* For each reloc against a global symbol whose index was not known - when the reloc was handled, the global hash table entry. */ - struct coff_link_hash_entry **rel_hashes; -}; - -/* Information that we pass around while doing the final link step. */ - -struct coff_final_link_info -{ - /* General link information. */ - struct bfd_link_info *info; - /* Output BFD. */ - bfd *output_bfd; - /* Used to indicate failure in traversal routine. */ - boolean failed; - /* Hash table for long symbol names. */ - struct bfd_strtab_hash *strtab; - /* When doing a relocateable link, an array of information kept for - each output section, indexed by the target_index field. */ - struct coff_link_section_info *section_info; - /* Symbol index of last C_FILE symbol (-1 if none). */ - long last_file_index; - /* Contents of last C_FILE symbol. */ - struct internal_syment last_file; - /* Hash table used to merge debug information. */ - struct coff_debug_merge_hash_table debug_merge; - /* Buffer large enough to hold swapped symbols of any input file. */ - struct internal_syment *internal_syms; - /* Buffer large enough to hold sections of symbols of any input file. */ - asection **sec_ptrs; - /* Buffer large enough to hold output indices of symbols of any - input file. */ - long *sym_indices; - /* Buffer large enough to hold output symbols for any input file. */ - bfd_byte *outsyms; - /* Buffer large enough to hold external line numbers for any input - section. */ - bfd_byte *linenos; - /* Buffer large enough to hold any input section. */ - bfd_byte *contents; - /* Buffer large enough to hold external relocs of any input section. */ - bfd_byte *external_relocs; - /* Buffer large enough to hold swapped relocs of any input section. */ - struct internal_reloc *internal_relocs; -}; - -static struct bfd_hash_entry *coff_debug_merge_hash_newfunc - PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); static boolean coff_link_add_object_symbols PARAMS ((bfd *, struct bfd_link_info *)); static boolean coff_link_check_archive_element @@ -162,13 +34,6 @@ static boolean coff_link_check_archive_element static boolean coff_link_check_ar_symbols PARAMS ((bfd *, struct bfd_link_info *, boolean *)); static boolean coff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *)); -static boolean coff_link_input_bfd - PARAMS ((struct coff_final_link_info *, bfd *)); -static boolean coff_write_global_sym - PARAMS ((struct coff_link_hash_entry *, PTR)); -static boolean coff_reloc_link_order - PARAMS ((bfd *, struct coff_final_link_info *, asection *, - struct bfd_link_order *)); /* Create an entry in a COFF linker hash table. */ @@ -242,7 +107,7 @@ _bfd_coff_link_hash_table_create (abfd) /* Create an entry in a COFF debug merge hash table. */ -static struct bfd_hash_entry * +struct bfd_hash_entry * coff_debug_merge_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; @@ -562,11 +427,11 @@ _bfd_coff_final_link (abfd, info) boolean debug_merge_allocated; asection *o; struct bfd_link_order *p; - size_t max_contents_size; size_t max_sym_count; size_t max_lineno_count; size_t max_reloc_count; size_t max_output_reloc_count; + size_t max_contents_size; file_ptr rel_filepos; unsigned int relsz; file_ptr line_filepos; @@ -613,12 +478,14 @@ _bfd_coff_final_link (abfd, info) max_contents_size = 0; max_lineno_count = 0; max_reloc_count = 0; + for (o = abfd->sections; o != NULL; o = o->next) { o->reloc_count = 0; o->lineno_count = 0; for (p = o->link_order_head; p != NULL; p = p->next) { + if (p->type == bfd_indirect_link_order) { asection *sec; @@ -662,14 +529,12 @@ _bfd_coff_final_link (abfd, info) /* We use section_count + 1, rather than section_count, because the target_index fields are 1 based. */ - finfo.section_info = ((struct coff_link_section_info *) - malloc ((abfd->section_count + 1) - * sizeof (struct coff_link_section_info))); + finfo.section_info = + ((struct coff_link_section_info *) + bfd_malloc ((abfd->section_count + 1) + * sizeof (struct coff_link_section_info))); if (finfo.section_info == NULL) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; for (i = 0; i <= abfd->section_count; i++) { finfo.section_info[i].relocs = NULL; @@ -710,17 +575,14 @@ _bfd_coff_final_link (abfd, info) BFD_ASSERT (info->relocateable); finfo.section_info[o->target_index].relocs = ((struct internal_reloc *) - malloc (o->reloc_count * sizeof (struct internal_reloc))); + bfd_malloc (o->reloc_count * sizeof (struct internal_reloc))); finfo.section_info[o->target_index].rel_hashes = ((struct coff_link_hash_entry **) - malloc (o->reloc_count + bfd_malloc (o->reloc_count * sizeof (struct coff_link_hash_entry *))); if (finfo.section_info[o->target_index].relocs == NULL || finfo.section_info[o->target_index].rel_hashes == NULL) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; if (o->reloc_count > max_output_reloc_count) max_output_reloc_count = o->reloc_count; @@ -750,20 +612,21 @@ _bfd_coff_final_link (abfd, info) /* Allocate some buffers used while linking. */ finfo.internal_syms = ((struct internal_syment *) - malloc (max_sym_count - * sizeof (struct internal_syment))); - finfo.sec_ptrs = (asection **) malloc (max_sym_count * sizeof (asection *)); - finfo.sym_indices = (long *) malloc (max_sym_count * sizeof (long)); + bfd_malloc (max_sym_count + * sizeof (struct internal_syment))); + finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count + * sizeof (asection *)); + finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long)); finfo.outsyms = ((bfd_byte *) - malloc ((size_t) ((max_sym_count + 1) * symesz))); - finfo.linenos = (bfd_byte *) malloc (max_lineno_count + bfd_malloc ((size_t) ((max_sym_count + 1) * symesz))); + finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count * bfd_coff_linesz (abfd)); - finfo.contents = (bfd_byte *) malloc (max_contents_size); - finfo.external_relocs = (bfd_byte *) malloc (max_reloc_count * relsz); + finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); + finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz); if (! info->relocateable) finfo.internal_relocs = ((struct internal_reloc *) - malloc (max_reloc_count - * sizeof (struct internal_reloc))); + bfd_malloc (max_reloc_count + * sizeof (struct internal_reloc))); if ((finfo.internal_syms == NULL && max_sym_count > 0) || (finfo.sec_ptrs == NULL && max_sym_count > 0) || (finfo.sym_indices == NULL && max_sym_count > 0) @@ -774,10 +637,7 @@ _bfd_coff_final_link (abfd, info) || (! info->relocateable && finfo.internal_relocs == NULL && max_reloc_count > 0)) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; /* We now know the position of everything in the file, except that we don't know the size of the symbol table and therefore we don't @@ -899,12 +759,10 @@ _bfd_coff_final_link (abfd, info) /* Now that we have written out all the global symbols, we know the symbol indices to use for relocs against them, and we can finally write out the relocs. */ - external_relocs = (bfd_byte *) malloc (max_output_reloc_count * relsz); + external_relocs = ((bfd_byte *) + bfd_malloc (max_output_reloc_count * relsz)); if (external_relocs == NULL) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; for (o = abfd->sections; o != NULL; o = o->next) { @@ -1083,12 +941,9 @@ process_embedded_commands (output_bfd, info, abfd) if (!sec) return 1; - copy = malloc ((size_t) sec->_raw_size); + copy = bfd_malloc ((size_t) sec->_raw_size); if (!copy) - { - bfd_set_error (bfd_error_no_memory); - return 0; - } + return 0; if (! bfd_get_section_contents(abfd, sec, copy, 0, sec->_raw_size)) { free (copy); @@ -1160,7 +1015,7 @@ process_embedded_commands (output_bfd, info, abfd) /* Link an input file into the linker output file. This function handles all the sections and relocations of the input file at once. */ -static boolean +boolean coff_link_input_bfd (finfo, input_bfd) struct coff_final_link_info *finfo; bfd *input_bfd; @@ -2045,7 +1900,7 @@ coff_link_input_bfd (finfo, input_bfd) /* Write out a global symbol. Called via coff_link_hash_traverse. */ -static boolean +boolean coff_write_global_sym (h, data) struct coff_link_hash_entry *h; PTR data; @@ -2176,7 +2031,7 @@ coff_write_global_sym (h, data) /* Handle a link order which is supposed to generate a reloc. */ -static boolean +boolean coff_reloc_link_order (output_bfd, finfo, output_section, link_order) bfd *output_bfd; struct coff_final_link_info *finfo; diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h index ce993b2745..9201e42bf3 100644 --- a/bfd/libcoff-in.h +++ b/bfd/libcoff-in.h @@ -299,7 +299,133 @@ extern void bfd_perform_slip PARAMS ((bfd *abfd, unsigned int slip, asection *input_section, bfd_vma val)); -/* Functions in cofflink.c. */ +/* Functions and types in cofflink.c. */ + +#define STRING_SIZE_SIZE (4) +#define POWERPC_LE_PE +/* We use a hash table to merge identical enum, struct, and union + definitions in the linker. */ + +/* Information we keep for a single element (an enum value, a + structure or union field) in the debug merge hash table. */ + +struct coff_debug_merge_element +{ + /* Next element. */ + struct coff_debug_merge_element *next; + + /* Name. */ + const char *name; + + /* Type. */ + unsigned int type; + + /* Symbol index for complex type. */ + long tagndx; +}; + +/* A linked list of debug merge entries for a given name. */ + +struct coff_debug_merge_type +{ + /* Next type with the same name. */ + struct coff_debug_merge_type *next; + + /* Class of type. */ + int class; + + /* Symbol index where this type is defined. */ + long indx; + + /* List of elements. */ + struct coff_debug_merge_element *elements; +}; + +/* Information we store in the debug merge hash table. */ + +struct coff_debug_merge_hash_entry +{ + struct bfd_hash_entry root; + + /* A list of types with this name. */ + struct coff_debug_merge_type *types; +}; + +/* The debug merge hash table. */ + +struct coff_debug_merge_hash_table +{ + struct bfd_hash_table root; +}; + +/* Initialize a COFF debug merge hash table. */ + +#define coff_debug_merge_hash_table_init(table) \ + (bfd_hash_table_init (&(table)->root, coff_debug_merge_hash_newfunc)) + +/* Free a COFF debug merge hash table. */ + +#define coff_debug_merge_hash_table_free(table) \ + (bfd_hash_table_free (&(table)->root)) + +/* Look up an entry in a COFF debug merge hash table. */ + +#define coff_debug_merge_hash_lookup(table, string, create, copy) \ + ((struct coff_debug_merge_hash_entry *) \ + bfd_hash_lookup (&(table)->root, (string), (create), (copy))) + +/* Information we keep for each section in the output file when doing + a relocateable link. */ + +struct coff_link_section_info +{ + /* The relocs to be output. */ + struct internal_reloc *relocs; + /* For each reloc against a global symbol whose index was not known + when the reloc was handled, the global hash table entry. */ + struct coff_link_hash_entry **rel_hashes; +}; + +/* Information that we pass around while doing the final link step. */ + +struct coff_final_link_info +{ + /* General link information. */ + struct bfd_link_info *info; + /* Output BFD. */ + bfd *output_bfd; + /* Used to indicate failure in traversal routine. */ + boolean failed; + /* Hash table for long symbol names. */ + struct bfd_strtab_hash *strtab; + /* When doing a relocateable link, an array of information kept for + each output section, indexed by the target_index field. */ + struct coff_link_section_info *section_info; + /* Symbol index of last C_FILE symbol (-1 if none). */ + long last_file_index; + /* Contents of last C_FILE symbol. */ + struct internal_syment last_file; + /* Hash table used to merge debug information. */ + struct coff_debug_merge_hash_table debug_merge; + /* Buffer large enough to hold swapped symbols of any input file. */ + struct internal_syment *internal_syms; + /* Buffer large enough to hold sections of symbols of any input file. */ + asection **sec_ptrs; + /* Buffer large enough to hold output indices of symbols of any + input file. */ + long *sym_indices; + /* Buffer large enough to hold output symbols for any input file. */ + bfd_byte *outsyms; + /* Buffer large enough to hold external line numbers for any input + section. */ + bfd_byte *linenos; + /* Buffer large enough to hold any input section. */ + bfd_byte *contents; + /* Buffer large enough to hold external relocs of any input section. */ + bfd_byte *external_relocs; + /* Buffer large enough to hold swapped relocs of any input section. */ + struct internal_reloc *internal_relocs; +}; extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); @@ -323,6 +449,17 @@ extern boolean _bfd_coff_generic_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **)); +extern struct bfd_hash_entry *coff_debug_merge_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +extern boolean coff_write_global_sym + PARAMS ((struct coff_link_hash_entry *, PTR)); +extern boolean coff_link_input_bfd + PARAMS ((struct coff_final_link_info *, bfd *)); +extern boolean coff_reloc_link_order + PARAMS ((bfd *, struct coff_final_link_info *, asection *, + struct bfd_link_order *)); + + #define coff_get_section_contents_in_window \ _bfd_generic_get_section_contents_in_window diff --git a/bfd/libcoff.h b/bfd/libcoff.h index 6cb948ad0d..3412c92d49 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -299,7 +299,133 @@ extern void bfd_perform_slip PARAMS ((bfd *abfd, unsigned int slip, asection *input_section, bfd_vma val)); -/* Functions in cofflink.c. */ +/* Functions and types in cofflink.c. */ + +#define STRING_SIZE_SIZE (4) +#define POWERPC_LE_PE +/* We use a hash table to merge identical enum, struct, and union + definitions in the linker. */ + +/* Information we keep for a single element (an enum value, a + structure or union field) in the debug merge hash table. */ + +struct coff_debug_merge_element +{ + /* Next element. */ + struct coff_debug_merge_element *next; + + /* Name. */ + const char *name; + + /* Type. */ + unsigned int type; + + /* Symbol index for complex type. */ + long tagndx; +}; + +/* A linked list of debug merge entries for a given name. */ + +struct coff_debug_merge_type +{ + /* Next type with the same name. */ + struct coff_debug_merge_type *next; + + /* Class of type. */ + int class; + + /* Symbol index where this type is defined. */ + long indx; + + /* List of elements. */ + struct coff_debug_merge_element *elements; +}; + +/* Information we store in the debug merge hash table. */ + +struct coff_debug_merge_hash_entry +{ + struct bfd_hash_entry root; + + /* A list of types with this name. */ + struct coff_debug_merge_type *types; +}; + +/* The debug merge hash table. */ + +struct coff_debug_merge_hash_table +{ + struct bfd_hash_table root; +}; + +/* Initialize a COFF debug merge hash table. */ + +#define coff_debug_merge_hash_table_init(table) \ + (bfd_hash_table_init (&(table)->root, coff_debug_merge_hash_newfunc)) + +/* Free a COFF debug merge hash table. */ + +#define coff_debug_merge_hash_table_free(table) \ + (bfd_hash_table_free (&(table)->root)) + +/* Look up an entry in a COFF debug merge hash table. */ + +#define coff_debug_merge_hash_lookup(table, string, create, copy) \ + ((struct coff_debug_merge_hash_entry *) \ + bfd_hash_lookup (&(table)->root, (string), (create), (copy))) + +/* Information we keep for each section in the output file when doing + a relocateable link. */ + +struct coff_link_section_info +{ + /* The relocs to be output. */ + struct internal_reloc *relocs; + /* For each reloc against a global symbol whose index was not known + when the reloc was handled, the global hash table entry. */ + struct coff_link_hash_entry **rel_hashes; +}; + +/* Information that we pass around while doing the final link step. */ + +struct coff_final_link_info +{ + /* General link information. */ + struct bfd_link_info *info; + /* Output BFD. */ + bfd *output_bfd; + /* Used to indicate failure in traversal routine. */ + boolean failed; + /* Hash table for long symbol names. */ + struct bfd_strtab_hash *strtab; + /* When doing a relocateable link, an array of information kept for + each output section, indexed by the target_index field. */ + struct coff_link_section_info *section_info; + /* Symbol index of last C_FILE symbol (-1 if none). */ + long last_file_index; + /* Contents of last C_FILE symbol. */ + struct internal_syment last_file; + /* Hash table used to merge debug information. */ + struct coff_debug_merge_hash_table debug_merge; + /* Buffer large enough to hold swapped symbols of any input file. */ + struct internal_syment *internal_syms; + /* Buffer large enough to hold sections of symbols of any input file. */ + asection **sec_ptrs; + /* Buffer large enough to hold output indices of symbols of any + input file. */ + long *sym_indices; + /* Buffer large enough to hold output symbols for any input file. */ + bfd_byte *outsyms; + /* Buffer large enough to hold external line numbers for any input + section. */ + bfd_byte *linenos; + /* Buffer large enough to hold any input section. */ + bfd_byte *contents; + /* Buffer large enough to hold external relocs of any input section. */ + bfd_byte *external_relocs; + /* Buffer large enough to hold swapped relocs of any input section. */ + struct internal_reloc *internal_relocs; +}; extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); @@ -323,6 +449,17 @@ extern boolean _bfd_coff_generic_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **)); +extern struct bfd_hash_entry *coff_debug_merge_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +extern boolean coff_write_global_sym + PARAMS ((struct coff_link_hash_entry *, PTR)); +extern boolean coff_link_input_bfd + PARAMS ((struct coff_final_link_info *, bfd *)); +extern boolean coff_reloc_link_order + PARAMS ((bfd *, struct coff_final_link_info *, asection *, + struct bfd_link_order *)); + + #define coff_get_section_contents_in_window \ _bfd_generic_get_section_contents_in_window