* coff-arm.c: Don't include obstack.h.
This commit is contained in:
parent
8f6462bc08
commit
8e2eebc8c8
1 changed files with 68 additions and 605 deletions
673
bfd/coff-arm.c
673
bfd/coff-arm.c
|
@ -153,7 +153,6 @@ coff_arm_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
|
|||
}
|
||||
|
||||
#define TARGET_UNDERSCORE '_'
|
||||
/* #define TARGET_UNDERSCORE '\0' */
|
||||
|
||||
#ifndef PCRELOFFSET
|
||||
#define PCRELOFFSET true
|
||||
|
@ -730,7 +729,7 @@ arm_reloc_type_lookup(abfd,code)
|
|||
static long int global_thumb_glue_size = 0;
|
||||
static long int global_arm_glue_size = 0;
|
||||
|
||||
static bfd * bfd_of_glue_owner = 0;
|
||||
static bfd * bfd_of_glue_owner = NULL;
|
||||
|
||||
/* some typedefs for holding instructions */
|
||||
typedef unsigned long int insn32;
|
||||
|
@ -802,9 +801,8 @@ find_thumb_glue (info, name, input_bfd)
|
|||
char * name;
|
||||
bfd * input_bfd;
|
||||
{
|
||||
char *tmp_name = 0;
|
||||
|
||||
struct coff_link_hash_entry *myh = 0;
|
||||
char * tmp_name = 0;
|
||||
struct coff_link_hash_entry * myh = 0;
|
||||
|
||||
tmp_name = ((char *)
|
||||
bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME)));
|
||||
|
@ -959,8 +957,8 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
struct internal_syment *syms;
|
||||
asection **sections;
|
||||
{
|
||||
struct internal_reloc *rel;
|
||||
struct internal_reloc *relend;
|
||||
struct internal_reloc * rel;
|
||||
struct internal_reloc * relend;
|
||||
|
||||
rel = relocs;
|
||||
relend = rel + input_section->reloc_count;
|
||||
|
@ -1096,7 +1094,9 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
|
||||
if ((my_offset & 0x01) == 0x01)
|
||||
{
|
||||
if (INTERWORK_SET (h_sec->owner) && ! INTERWORK_FLAG (h_sec->owner))
|
||||
if (h_sec->owner != NULL
|
||||
&& INTERWORK_SET (h_sec->owner)
|
||||
&& ! INTERWORK_FLAG (h_sec->owner))
|
||||
_bfd_error_handler ("%s: warning: interworking not enabled.",
|
||||
bfd_get_filename (h_sec->owner));
|
||||
|
||||
|
@ -1165,7 +1165,9 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
|
||||
if ((my_offset & 0x01) == 0x01)
|
||||
{
|
||||
if (INTERWORK_SET (h_sec->owner) && ! INTERWORK_FLAG (h_sec->owner))
|
||||
if (h->sec_owner != NULL
|
||||
&& INTERWORK_SET (h_sec->owner)
|
||||
&& ! INTERWORK_FLAG (h_sec->owner))
|
||||
_bfd_error_handler ("%s: warning: interworking not enabled.",
|
||||
bfd_get_filename (h_sec->owner));
|
||||
|
||||
|
@ -1201,7 +1203,7 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
-4;
|
||||
|
||||
tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr - input_section->vma);
|
||||
|
||||
|
||||
bfd_put_32 (output_bfd,
|
||||
insert_thumb_branch (tmp, ret_offset),
|
||||
contents + rel->r_vaddr - input_section->vma);
|
||||
|
@ -1465,11 +1467,13 @@ boolean
|
|||
arm_allocate_interworking_sections (info)
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
asection *s;
|
||||
bfd_byte *foo;
|
||||
asection * s;
|
||||
bfd_byte * foo;
|
||||
#if 0
|
||||
static char test_char = '1';
|
||||
|
||||
if ( global_arm_glue_size != 0 )
|
||||
#endif
|
||||
|
||||
if (global_arm_glue_size != 0)
|
||||
{
|
||||
BFD_ASSERT (bfd_of_glue_owner != NULL);
|
||||
|
||||
|
@ -1477,8 +1481,10 @@ arm_allocate_interworking_sections (info)
|
|||
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
foo = (bfd_byte *) bfd_alloc(bfd_of_glue_owner, global_arm_glue_size);
|
||||
memset(foo, test_char, global_arm_glue_size);
|
||||
foo = (bfd_byte *) bfd_alloc (bfd_of_glue_owner, global_arm_glue_size);
|
||||
#if 0
|
||||
memset (foo, test_char, global_arm_glue_size);
|
||||
#endif
|
||||
|
||||
s->_raw_size = s->_cooked_size = global_arm_glue_size;
|
||||
s->contents = foo;
|
||||
|
@ -1492,8 +1498,10 @@ arm_allocate_interworking_sections (info)
|
|||
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
foo = (bfd_byte *) bfd_alloc(bfd_of_glue_owner, global_thumb_glue_size);
|
||||
memset(foo, test_char, global_thumb_glue_size);
|
||||
foo = (bfd_byte *) bfd_alloc (bfd_of_glue_owner, global_thumb_glue_size);
|
||||
#if 0
|
||||
memset (foo, test_char, global_thumb_glue_size);
|
||||
#endif
|
||||
|
||||
s->_raw_size = s->_cooked_size = global_thumb_glue_size;
|
||||
s->contents = foo;
|
||||
|
@ -1565,7 +1573,6 @@ record_thumb_to_arm_glue (info, h)
|
|||
char * tmp_name;
|
||||
struct coff_link_hash_entry * myh;
|
||||
|
||||
|
||||
BFD_ASSERT (bfd_of_glue_owner != NULL);
|
||||
|
||||
s = bfd_get_section_by_name (bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
|
||||
|
@ -1850,7 +1857,7 @@ coff_arm_bfd_merge_private_bfd_data (ibfd, obfd)
|
|||
}
|
||||
|
||||
|
||||
/* Display the flags field */
|
||||
/* Display the flags field. */
|
||||
|
||||
static boolean
|
||||
coff_arm_bfd_print_private_bfd_data (abfd, ptr)
|
||||
|
@ -1978,7 +1985,6 @@ coff_arm_bfd_copy_private_bfd_data (src, dest)
|
|||
*must* match the definitions on gcc/config/arm/semi.h. */
|
||||
#define LOCAL_LABEL_PREFIX "."
|
||||
#define USER_LABEL_PREFIX "_"
|
||||
/* #define USER_LABEL_PREFIX "" */
|
||||
|
||||
static boolean
|
||||
coff_arm_is_local_label_name (abfd, name)
|
||||
|
@ -2015,31 +2021,12 @@ coff_arm_is_local_label_name (abfd, name)
|
|||
|
||||
#define coff_bfd_is_local_label_name coff_arm_is_local_label_name
|
||||
#define coff_adjust_symndx coff_arm_adjust_symndx
|
||||
|
||||
#ifndef COFF_WITH_PE
|
||||
#define coff_bfd_final_link coff_arm_bfd_final_link
|
||||
#define coff_bfd_merge_private_bfd_data coff_arm_bfd_merge_private_bfd_data
|
||||
#define coff_bfd_print_private_bfd_data coff_arm_bfd_print_private_bfd_data
|
||||
#define coff_bfd_set_private_flags coff_arm_bfd_set_private_flags
|
||||
#define coff_bfd_copy_private_bfd_data coff_arm_bfd_copy_private_bfd_data
|
||||
#endif
|
||||
|
||||
#include "coffcode.h"
|
||||
|
||||
static boolean
|
||||
arm_do_last (abfd)
|
||||
bfd * abfd;
|
||||
{
|
||||
if (abfd == bfd_of_glue_owner)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
arm_get_last()
|
||||
{
|
||||
return bfd_of_glue_owner;
|
||||
}
|
||||
|
||||
/* This piece of machinery exists only to guarantee that the bfd that holds
|
||||
the glue section is written last.
|
||||
|
@ -2047,551 +2034,54 @@ arm_get_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 ARM_HACKS macro modifies the code. It is left in as a
|
||||
precise form of comment. krk@cygnus.com */
|
||||
krk@cygnus.com */
|
||||
|
||||
#define ARM_HACKS
|
||||
|
||||
/* Do the final link step. */
|
||||
|
||||
static boolean
|
||||
coff_arm_bfd_final_link (abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
boolean
|
||||
coff_arm_link_output_has_begun (sub)
|
||||
bfd * sub;
|
||||
{
|
||||
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.last_bf_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;
|
||||
|
||||
/* Mark all sections which are to be included in the
|
||||
link. This will normally be every section. We need
|
||||
to do this so that we can identify any sections which
|
||||
the linker has decided to not include. */
|
||||
sec->linker_mark = true;
|
||||
|
||||
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 ARM_HACKS
|
||||
if (! sub->output_has_begun && !arm_do_last(sub))
|
||||
#else
|
||||
if (! sub->output_has_begun)
|
||||
#endif
|
||||
{
|
||||
if (! _bfd_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 (! _bfd_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 ARM_HACKS
|
||||
{
|
||||
extern bfd* arm_get_last();
|
||||
bfd* last_one = arm_get_last();
|
||||
if (last_one)
|
||||
{
|
||||
if (! _bfd_coff_link_input_bfd (&finfo, last_one))
|
||||
goto error_return;
|
||||
last_one->output_has_begun = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free up the buffers used by _bfd_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), _bfd_coff_write_global_sym,
|
||||
(PTR) &finfo);
|
||||
if (finfo.failed)
|
||||
goto error_return;
|
||||
|
||||
/* The outsyms buffer is used by _bfd_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;
|
||||
}
|
||||
|
||||
/* If we have optimized stabs strings, output them. */
|
||||
if (coff_hash_table (info)->stab_info != NULL)
|
||||
{
|
||||
if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return (sub->output_has_begun || sub == bfd_of_glue_owner);
|
||||
}
|
||||
|
||||
boolean
|
||||
coff_arm_final_link_postscript (abfd, pfinfo)
|
||||
bfd * abfd;
|
||||
struct coff_final_link_info * pfinfo;
|
||||
{
|
||||
if (bfd_of_glue_owner != NULL)
|
||||
{
|
||||
if (! _bfd_coff_link_input_bfd (pfinfo, bfd_of_glue_owner))
|
||||
return false;
|
||||
bfd_of_glue_owner->output_has_begun = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#define coff_link_output_has_begun coff_arm_link_output_has_begun
|
||||
#define coff_final_link_postscript coff_arm_final_link_postscript
|
||||
#endif
|
||||
|
||||
#define coff_SWAP_sym_in arm_bfd_coff_swap_sym_in
|
||||
|
||||
static void coff_swap_sym_in PARAMS ((bfd *, PTR, PTR));
|
||||
|
||||
/* Sepcial version of symbol swapper, used to grab a bfd
|
||||
onto which the glue sections can be attached. */
|
||||
static void
|
||||
arm_bfd_coff_swap_sym_in (abfd, ext1, in1)
|
||||
bfd *abfd;
|
||||
PTR ext1;
|
||||
PTR in1;
|
||||
bfd * abfd;
|
||||
PTR ext1;
|
||||
PTR in1;
|
||||
{
|
||||
SYMENT *ext = (SYMENT *)ext1;
|
||||
struct internal_syment *in = (struct internal_syment *)in1;
|
||||
flagword flags;
|
||||
register asection *s;
|
||||
register asection * s;
|
||||
|
||||
if( ext->e.e_name[0] == 0) {
|
||||
in->_n._n_n._n_zeroes = 0;
|
||||
in->_n._n_n._n_offset = bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
|
||||
}
|
||||
else {
|
||||
#if SYMNMLEN != E_SYMNMLEN
|
||||
-> Error, we need to cope with truncating or extending SYMNMLEN!;
|
||||
#else
|
||||
memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
|
||||
#endif
|
||||
}
|
||||
in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value);
|
||||
in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
|
||||
if (sizeof(ext->e_type) == 2){
|
||||
in->n_type = bfd_h_get_16(abfd, (bfd_byte *) ext->e_type);
|
||||
}
|
||||
else {
|
||||
in->n_type = bfd_h_get_32(abfd, (bfd_byte *) ext->e_type);
|
||||
}
|
||||
in->n_sclass = bfd_h_get_8(abfd, ext->e_sclass);
|
||||
in->n_numaux = bfd_h_get_8(abfd, ext->e_numaux);
|
||||
/* Do the normal swap in. */
|
||||
coff_swap_sym_in (abfd, ext1, in1);
|
||||
|
||||
if (bfd_of_glue_owner != 0) /* we already have a toc, so go home */
|
||||
if (bfd_of_glue_owner != NULL) /* we already have a toc, so go home */
|
||||
return;
|
||||
|
||||
/* save the bfd for later allocation */
|
||||
/* Save the bfd for later allocation. */
|
||||
bfd_of_glue_owner = abfd;
|
||||
|
||||
s = bfd_get_section_by_name (bfd_of_glue_owner ,
|
||||
|
@ -2612,7 +2102,7 @@ arm_bfd_coff_swap_sym_in (abfd, ext1, in1)
|
|||
}
|
||||
}
|
||||
|
||||
s = bfd_get_section_by_name ( bfd_of_glue_owner , THUMB2ARM_GLUE_SECTION_NAME);
|
||||
s = bfd_get_section_by_name (bfd_of_glue_owner , THUMB2ARM_GLUE_SECTION_NAME);
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
|
@ -2632,34 +2122,7 @@ arm_bfd_coff_swap_sym_in (abfd, ext1, in1)
|
|||
return;
|
||||
}
|
||||
|
||||
static bfd_coff_backend_data arm_bfd_coff_std_swap_table =
|
||||
{
|
||||
coff_swap_aux_in, arm_bfd_coff_swap_sym_in, coff_swap_lineno_in,
|
||||
coff_swap_aux_out, coff_swap_sym_out,
|
||||
coff_swap_lineno_out, coff_swap_reloc_out,
|
||||
coff_swap_filehdr_out, coff_swap_aouthdr_out,
|
||||
coff_swap_scnhdr_out,
|
||||
FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ,
|
||||
#ifdef COFF_LONG_FILENAMES
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
#ifdef COFF_LONG_SECTION_NAMES
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
COFF_DEFAULT_SECTION_ALIGNMENT_POWER,
|
||||
coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
|
||||
coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
|
||||
coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
|
||||
coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
|
||||
coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
|
||||
coff_sym_is_global, coff_compute_section_file_positions,
|
||||
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
|
||||
coff_adjust_symndx, coff_link_add_one_symbol
|
||||
};
|
||||
#include "coffcode.h"
|
||||
|
||||
const bfd_target
|
||||
#ifdef TARGET_LITTLE_SYM
|
||||
|
@ -2721,7 +2184,7 @@ armcoff_little_vec =
|
|||
BFD_JUMP_TABLE_LINK (coff),
|
||||
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||
|
||||
& arm_bfd_coff_std_swap_table,
|
||||
(PTR) & bfd_coff_std_swap_table,
|
||||
};
|
||||
|
||||
const bfd_target
|
||||
|
@ -2784,5 +2247,5 @@ armcoff_big_vec =
|
|||
BFD_JUMP_TABLE_LINK (coff),
|
||||
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||
|
||||
& arm_bfd_coff_std_swap_table,
|
||||
(PTR) & bfd_coff_std_swap_table,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue