* ld.h (split_by_reloc, split_by_file): New flags.

* ldwrite.c  (clone_section, split_sections): New functions.
	* lexsup.c (parse_args): Understand new split options.
This commit is contained in:
Steve Chamberlain 1994-12-19 22:16:27 +00:00
parent 847a01cd4c
commit 885ae6b979
2 changed files with 251 additions and 27 deletions

View File

@ -1,3 +1,18 @@
Mon Dec 19 14:02:13 1994 Steve Chamberlain (sac@jonny.cygnus.com)
* ld.h (split_by_reloc, split_by_file): New flags.
* ldwrite.c (clone_section, split_sections): New functions.
* lexsup.c (parse_args): Understand new split options.
start-sanitize-arc
Tue Dec 13 16:45:18 1994 Doug Evans <dje@canuck.cygnus.com>
* configure.in (arc-elf): New target.
* Makefile.in (earcelf.c): New target.
* config/arc-elf.mt: New file.
* emulparms/arcelf.sh: New file.
end-sanitize-arc
Fri Dec 9 17:22:55 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
* scripttempl/elf.sc: Move .ctors and .dtors from .text segment to

View File

@ -44,42 +44,46 @@ build_link_order (statement)
switch (statement->header.type)
{
case lang_data_statement_enum:
/* FIXME: This should probably build a link_order, but instead
it just does the output directly. */
{
bfd_vma value = statement->data_statement.value;
bfd_byte play_area[QUAD_SIZE];
unsigned int size = 0;
asection *output_section = statement->data_statement.output_section;
asection *output_section;
struct bfd_link_order *link_order;
bfd_vma value;
output_section = statement->data_statement.output_section;
ASSERT (output_section->owner == output_bfd);
link_order = bfd_new_link_order (output_bfd, output_section);
if (link_order == NULL)
einfo ("%P%F: bfd_new_link_order failed");
link_order->type = bfd_data_link_order;
link_order->offset = statement->data_statement.output_vma;
link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
value = statement->data_statement.value;
ASSERT (output_section->owner == output_bfd);
switch (statement->data_statement.type)
{
case QUAD:
bfd_put_64 (output_bfd, value, play_area);
size = QUAD_SIZE;
bfd_put_64 (output_bfd, value, link_order->u.data.contents);
link_order->size = QUAD_SIZE;
break;
case LONG:
bfd_put_32 (output_bfd, value, play_area);
size = LONG_SIZE;
bfd_put_32 (output_bfd, value, link_order->u.data.contents);
link_order->size = LONG_SIZE;
break;
case SHORT:
bfd_put_16 (output_bfd, value, play_area);
size = SHORT_SIZE;
bfd_put_16 (output_bfd, value, link_order->u.data.contents);
link_order->size = SHORT_SIZE;
break;
case BYTE:
bfd_put_8 (output_bfd, value, play_area);
size = BYTE_SIZE;
bfd_put_8 (output_bfd, value, link_order->u.data.contents);
link_order->size = BYTE_SIZE;
break;
default:
abort ();
}
if (! bfd_set_section_contents (output_bfd, output_section,
play_area,
statement->data_statement.output_vma,
size))
einfo ("%P%X: writing data failed: %E\n");
}
break;
@ -196,12 +200,217 @@ build_link_order (statement)
/* Call BFD to write out the linked file. */
/**********************************************************************/
/* Wander around the input sections, make sure that
we'll never try and create an output section with more relocs
than will fit.. Do this by always assuming the worst case, and
creating new output sections with all the right bits */
#define TESTIT 1
static asection *
clone_section (abfd, s, count)
bfd *abfd;
asection *s;
int *count;
{
#define SSIZE 8
char sname[SSIZE]; /* ?? find the name for this size */
asection *n;
/* Invent a section name - use first five
chars of base section name and a digit suffix */
do
{
int i;
char b[6];
for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
b[i] = s->name[i];
b[i] = 0;
sprintf (sname, "%s%d", b, (*count)++);
}
while (bfd_get_section_by_name (abfd, sname));
n = bfd_make_section_anyway (abfd, strdup (sname));
n->flags = s->flags;
n->vma = s->vma;
n->user_set_vma = s->user_set_vma;
n->lma = s->lma;
n->_cooked_size = 0;
n->_raw_size = 0;
n->output_offset = s->output_offset;
n->output_section = n;
n->orelocation = 0;
n->reloc_count = 0;
return n;
}
#if TESTING
static void
ds (s)
asection *s;
{
struct bfd_link_order *l = s->link_order_head;
printf ("vma %x size %x\n", s->vma, s->_raw_size);
while (l)
{
if (l->type == bfd_indirect_link_order)
{
printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
}
else
{
printf ("%8x something else\n", l->offset);
}
l = l->next;
}
printf ("\n");
}
dump (s, a1, a2)
char *s;
asection *a1;
asection *a2;
{
printf ("%s\n", s);
ds (a1);
ds (a2);
}
static void
sanity_check (abfd)
bfd *abfd;
{
asection *s;
for (s = abfd->sections; s; s = s->next)
{
struct bfd_link_order *p;
bfd_vma prev = 0;
for (p = s->link_order_head; p; p = p->next)
{
if (p->offset > 100000)
abort ();
if (p->offset < prev)
abort ();
prev = p->offset;
}
}
}
#else
#define sanity_check(a)
#define dump(a, b, c)
#endif
void
split_sections (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
asection *original_sec;
int nsecs = abfd->section_count;
sanity_check (abfd);
/* look through all the original sections */
for (original_sec = abfd->sections;
original_sec && nsecs;
original_sec = original_sec->next, nsecs--)
{
int count = 0;
int lines = 0;
int relocs = 0;
struct bfd_link_order **pp;
bfd_vma vma = original_sec->vma;
bfd_vma shift_offset = 0;
asection *cursor = original_sec;
/* count up the relocations and line entries to see if
anything would be too big to fit */
for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next))
{
struct bfd_link_order *p = *pp;
int thislines = 0;
int thisrelocs = 0;
if (p->type == bfd_indirect_link_order)
{
asection *sec;
sec = p->u.indirect.section;
if (info->strip == strip_none
|| info->strip == strip_some)
thislines = sec->lineno_count;
if (info->relocateable)
thisrelocs = sec->reloc_count;
}
else if (info->relocateable
&& (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order))
thisrelocs++;
if (thisrelocs + relocs > config.split_by_reloc
|| thislines + lines > config.split_by_reloc
|| config.split_by_file)
{
/* create a new section and put this link order and the
following link orders into it */
struct bfd_link_order *l = p;
asection *n = clone_section (abfd, cursor, &count);
*pp = NULL; /* Snip off link orders from old section */
n->link_order_head = l; /* attach to new section */
pp = &n->link_order_head;
/* change the size of the original section and
update the vma of the new one */
dump ("before snip", cursor, n);
n->_raw_size = cursor->_raw_size - l->offset;
cursor->_raw_size = l->offset;
vma += cursor->_raw_size;
n->lma = n->vma = vma;
shift_offset = l->offset;
/* run down the chain and change the output section to
the right one, update the offsets too */
while (l)
{
l->offset -= shift_offset;
if (l->type == bfd_indirect_link_order)
{
l->u.indirect.section->output_section = n;
l->u.indirect.section->output_offset = l->offset;
}
l = l->next;
}
dump ("after snip", cursor, n);
cursor = n;
relocs = thisrelocs;
lines = thislines;
}
else
{
relocs += thisrelocs;
lines += thislines;
}
}
}
sanity_check (abfd);
}
/**********************************************************************/
void
ldwrite ()
{
lang_for_each_statement (build_link_order);
if (! bfd_final_link (output_bfd, &link_info))
if (config.split_by_reloc || config.split_by_file)
split_sections (output_bfd, &link_info);
if (!bfd_final_link (output_bfd, &link_info))
einfo ("%F%P: final link failed: %E\n", output_bfd);
if (config.map_file)
@ -228,7 +437,7 @@ print_symbol_table ()
static void
print_file_stuff (f)
lang_input_statement_type * f;
lang_input_statement_type *f;
{
fprintf (config.map_file, " %s\n", f->filename);
if (f->just_syms_flag)
@ -289,7 +498,7 @@ print_symbol (p, ignore)
|| p->type == bfd_link_hash_warning)
p = p->u.i.link;
switch (p->type)
switch (p->type)
{
case bfd_link_hash_new:
abort ();
@ -297,16 +506,16 @@ print_symbol (p, ignore)
case bfd_link_hash_undefined:
fprintf (config.map_file, "undefined ");
fprintf (config.map_file, "%s ", p->root.string);
print_nl ();
print_nl ();
break;
case bfd_link_hash_weak:
fprintf (config.map_file, "weak ");
fprintf (config.map_file, "%s ", p->root.string);
print_nl ();
print_nl ();
break;
case bfd_link_hash_defined:
case bfd_link_hash_defined:
{
asection *defsec = p->u.def.section;
@ -324,7 +533,7 @@ print_symbol (p, ignore)
}
fprintf (config.map_file, " %s ", p->root.string);
}
print_nl ();
print_nl ();
break;
case bfd_link_hash_common: