Merge branch 'pcrel' into devel2
This commit is contained in:
commit
738025ab43
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
151
ld/ldlang.c
151
ld/ldlang.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue