Merge branch 'pcrel' into devel2

This commit is contained in:
bebbo 2017-05-19 17:20:25 +02:00
commit 738025ab43
4 changed files with 156 additions and 97 deletions

View File

@ -1411,6 +1411,7 @@ amiga_write_object_contents (abfd)
int *index_map,max_hunk=-1;
sec_ptr data_sec,p;
unsigned long i,n[5];
sec_ptr text_sec = 0;
/* Distinguish UNITS, LOAD Files
Write out hunks+relocs+HUNK_EXT+HUNK_DEBUG (GNU format) */
@ -1422,6 +1423,27 @@ amiga_write_object_contents (abfd)
if (!index_map)
return FALSE;
for (idx = 0, p = abfd->sections; p != NULL; p = p->next)
if (!strcmp(p->name, ".bss") && !strcmp(p->output_section->name, ".text"))
text_sec = p->output_section;
if (text_sec)
for (idx = 0, p = abfd->sections; p != NULL; p = p->next)
if (strcmp(p->name, ".text") && p->_raw_size)
{
unsigned ns = text_sec->_raw_size + p->_raw_size;
char * c = (char *)bfd_zalloc(abfd, ns);
memcpy(c, text_sec->contents, text_sec->_raw_size);
if (p->contents)
memcpy(c + text_sec->_raw_size, p->contents, p->_raw_size);
text_sec->contents = c;
text_sec->_raw_size = ns;
p->_raw_size = 0;
text_sec->_cooked_size += p->_cooked_size;
p->_cooked_size = 0;
}
for (idx=0, p=abfd->sections; p!=NULL; p=p->next)
index_map[idx++] = p->index;

View File

@ -43,7 +43,6 @@ the sun3 backend only in these details:
o The routine to get the relocated section contents is
@code{get_relocated_section_contents}.
This ensures that the link is performed properly, but has the side effect of
loosing performance.
The amiga bfd code uses the same functions since they check for the used flavour.
@ -115,7 +114,6 @@ my_add_to PARAMS ((arelent *, PTR, int, int));
static void amiga_update_target_section PARAMS ((sec_ptr));
static bfd_reloc_status_type
amiga_perform_reloc PARAMS ((bfd *, arelent *, PTR, sec_ptr, bfd *, char **));
static void aout_update_target_section PARAMS ((sec_ptr));
static bfd_reloc_status_type
aout_perform_reloc PARAMS ((bfd *, arelent *, PTR, sec_ptr, bfd *, char **));
static bfd_boolean
@ -373,6 +371,35 @@ amiga_update_target_section (target_section)
}
}
/* For pc-relative linking place .bss symbols in the .data section.
* Then place all .data symbols into .text section
*/
static void
amiga_update_target_section_pcrel(target_section)
sec_ptr target_section;
{
amiga_update_target_section(target_section);
/* If target->out is .data, add the value of the .text section to
sym->value and set new output_section */
/* If we access a symbol in the .data section, we have to convert
this to an access to .text section */
/* This is done through a change to the output section of
the symbol.. */
if (!strcmp(target_section->output_section->name, ".data"))
{
/* get value for .data section */
bfd *ibfd;
sec_ptr s;
ibfd = target_section->output_section->owner;
for (s = ibfd->sections; s != NULL; s = s->next)
if (!strcmp(s->name, ".text"))
{
target_section->output_offset += s->_raw_size;
target_section->output_section = s;
}
}
}
/* Perform an Amiga relocation */
static bfd_reloc_status_type
@ -452,13 +479,18 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message)
{
ret=bfd_reloc_undefined;
}
#if 0
else if (sec->output_section!=target_section->output_section) /* Error */
{
DPRINT(5,("pc relative, but out-of-range\n"));
ret=bfd_reloc_outofrange;
}
#endif
else /* Same section */
{
if (sec->output_section != target_section->output_section)
amiga_update_target_section_pcrel(target_section);
DPRINT(5,("PC relative\n"));
relocation = sym->value + target_section->output_offset
- (r->address + sec->output_offset);
@ -520,34 +552,6 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message)
}
/* For base-relative linking place .bss symbols in the .data section. */
static void
aout_update_target_section (target_section)
sec_ptr target_section;
{
/* If target->out is .bss, add the value of the .data section to
sym->value and set new output_section */
/* If we access a symbol in the .bss section, we have to convert
this to an access to .data section */
/* This is done through a change to the output section of
the symbol.. */
if (!strcmp(target_section->output_section->name,".bss"))
{
/* get value for .data section */
bfd *ibfd;
sec_ptr s;
ibfd=target_section->output_section->owner;
for (s=ibfd->sections;s!=NULL;s=s->next)
if (!strcmp(s->name,".data"))
{
target_section->output_offset+=s->_raw_size;
target_section->output_section=s;
}
}
}
/* Perform an a.out relocation */
static bfd_reloc_status_type
aout_perform_reloc (abfd, r, data, sec, obfd, error_message)
@ -644,7 +648,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message)
else
{
if (amiga_base_relative)
aout_update_target_section (target_section);
amiga_update_target_section (target_section);
relocation=0;
copy=TRUE;
}
@ -661,15 +665,21 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message)
case H_PC32:
if (bfd_is_abs_section(target_section)) /* Ref to absolute hunk */
relocation=sym->value;
#if 0
else if (sec->output_section!=target_section->output_section) /* Error */
{
DPRINT(5,("pc relative, but out-of-range\n"));
ret=bfd_reloc_outofrange;
}
#endif
else /* Same section */
{
if (sec->output_section != target_section->output_section)
amiga_update_target_section_pcrel(target_section);
relocation = sym->value + target_section->output_offset
- sec->output_offset;
- sec->output_offset
+ r->addend
;
}
break;
@ -699,7 +709,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message)
}
else /* Target section and sec need not be the same.. */
{
aout_update_target_section (target_section);
amiga_update_target_section (target_section);
relocation = sym->value + target_section->output_offset
- (AMIGA_DATA(target_section->output_section->owner))->a4init;

View File

@ -1865,8 +1865,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
/* Ignore a redefinition of an absolute symbol to the
same value; it's harmless. */
if (h->type == bfd_link_hash_defined
&& bfd_is_abs_section (msec)
&& bfd_is_abs_section (section)
&& ((bfd_is_abs_section (msec)
&& bfd_is_abs_section (section)) || msec == section)
&& value == mval)
break;

View File

@ -1532,7 +1532,10 @@ load_symbols (entry, place)
char **matching;
if (entry->loaded)
return TRUE;
{
bfd_link_add_symbols (entry->the_bfd, &link_info);
return TRUE;
}
ldfile_open_file (entry);
@ -1984,82 +1987,106 @@ ldlang_open_output (statement)
}
}
/*
* Count the undefined symbols.
*/
static unsigned
count_undef (void)
{
unsigned count = 0;
for (struct bfd_link_hash_entry * p = link_info.hash->undefs; p; p = p->next)
{
if (p->type == bfd_link_hash_undefined || p->type == bfd_link_hash_undefweak)
++count;
}
return count;
}
/* Open all the input files. */
static void
open_input_bfds (s, force)
lang_statement_union_type *s;
open_input_bfds (_s, force)
lang_statement_union_type *_s;
bfd_boolean force;
{
for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
/* SBF: add more passes to resolve symbols with already loaded libs / files.
* Stop is count of undefined symbols does not change.
*/
for (unsigned pass = 0; _s;)
{
switch (s->header.type)
for (lang_statement_union_type *s = _s; s != (lang_statement_union_type *) NULL; s = s->header.next)
{
case lang_constructors_statement_enum:
open_input_bfds (constructor_list.head, force);
break;
case lang_output_section_statement_enum:
open_input_bfds (s->output_section_statement.children.head, force);
break;
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols. */
if (s->wild_statement.filename
&& ! wildcardp (s->wild_statement.filename))
(void) lookup_name (s->wild_statement.filename);
open_input_bfds (s->wild_statement.children.head, force);
break;
case lang_group_statement_enum:
{
struct bfd_link_hash_entry *undefs;
if (pass && s->header.type != lang_input_statement_enum)
continue;
/* We must continually search the entries in the group
until no new symbols are added to the list of undefined
symbols. */
do
{
undefs = link_info.hash->undefs_tail;
open_input_bfds (s->group_statement.children.head, TRUE);
}
while (undefs != link_info.hash->undefs_tail);
}
break;
case lang_target_statement_enum:
current_target = s->target_statement.target;
break;
case lang_input_statement_enum:
if (s->input_statement.real)
switch (s->header.type)
{
lang_statement_list_type add;
case lang_constructors_statement_enum:
open_input_bfds (constructor_list.head, force);
break;
case lang_output_section_statement_enum:
open_input_bfds (s->output_section_statement.children.head, force);
break;
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols. */
if (s->wild_statement.filename && !wildcardp (s->wild_statement.filename))
(void) lookup_name (s->wild_statement.filename);
open_input_bfds (s->wild_statement.children.head, force);
break;
case lang_group_statement_enum:
{
struct bfd_link_hash_entry *undefs;
s->input_statement.target = current_target;
/* We must continually search the entries in the group
until no new symbols are added to the list of undefined
symbols. */
/* If we are being called from within a group, and this
is an archive which has already been searched, then
force it to be researched unless the whole archive
has been loaded already. */
if (force
&& !s->input_statement.whole_archive
&& s->input_statement.loaded
&& bfd_check_format (s->input_statement.the_bfd,
bfd_archive))
s->input_statement.loaded = FALSE;
lang_list_init (&add);
if (! load_symbols (&s->input_statement, &add))
config.make_executable = FALSE;
if (add.head != NULL)
do
{
undefs = link_info.hash->undefs_tail;
open_input_bfds (s->group_statement.children.head, TRUE);
}
while (undefs != link_info.hash->undefs_tail);
}
break;
case lang_target_statement_enum:
current_target = s->target_statement.target;
break;
case lang_input_statement_enum:
if (s->input_statement.real)
{
*add.tail = s->header.next;
s->header.next = add.head;
lang_statement_list_type add;
s->input_statement.target = current_target;
/* If we are being called from within a group, and this
is an archive which has already been searched, then
force it to be researched unless the whole archive
has been loaded already. */
if (force && !s->input_statement.whole_archive && s->input_statement.loaded
&& bfd_check_format (s->input_statement.the_bfd, bfd_archive))
s->input_statement.loaded = FALSE;
lang_list_init (&add);
if (!load_symbols (&s->input_statement, &add))
config.make_executable = FALSE;
if (add.head != NULL)
{
*add.tail = s->header.next;
s->header.next = add.head;
}
}
break;
default:
break;
}
break;
default:
break;
}
unsigned n = count_undef ();
if (pass == n)
break;
pass = n;
}
}