mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-29 06:50:32 +00:00
Removed a ppc hack from cofflink, promoted some types to libcoff-in.h
This commit is contained in:
parent
4bdd9722a6
commit
13d1a4dda9
@ -1,3 +1,22 @@
|
||||
Mon Jan 29 11:34:36 1996 Kim Knuttila <krk@cygnus.com>
|
||||
|
||||
* 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 <ian@cygnus.com>
|
||||
|
||||
* syms.c: Include "bfdlink.h".
|
||||
|
631
bfd/coff-ppc.c
631
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)))
|
||||
{
|
||||
#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,8 +1924,13 @@ dump_toc(vfile)
|
||||
if (t->offset <= global_toc_size + thunk_size)
|
||||
cat = "IAT reference ";
|
||||
else
|
||||
{
|
||||
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,
|
||||
" %04lx (%d)", t->offset, t->offset - 32768);
|
||||
@ -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 |
|
||||
|
193
bfd/cofflink.c
193
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)
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (o->reloc_count > max_output_reloc_count)
|
||||
max_output_reloc_count = o->reloc_count;
|
||||
@ -750,19 +612,20 @@ _bfd_coff_final_link (abfd, info)
|
||||
|
||||
/* Allocate some buffers used while linking. */
|
||||
finfo.internal_syms = ((struct internal_syment *)
|
||||
malloc (max_sym_count
|
||||
bfd_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));
|
||||
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
|
||||
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)
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
139
bfd/libcoff-in.h
139
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
|
||||
|
||||
|
139
bfd/libcoff.h
139
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user