--split-by-reloc, --split-by-file extensions. --unique option.
This commit is contained in:
parent
1bd916895e
commit
a854a4a7c8
30
ld/ChangeLog
30
ld/ChangeLog
@ -1,3 +1,33 @@
|
||||
2000-09-05 Alan Modra <alan@linuxcare.com.au>
|
||||
|
||||
* ld.h (ld_config_type): Add unique_orphan_sections.
|
||||
* lexsup.c (OPTION_UNIQUE): Define.
|
||||
(ld_options): Add "--unique".
|
||||
(parse_args): Handle it.
|
||||
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Don't
|
||||
search for an existing output section if unique_orphan_sections is
|
||||
set. Make use of bfd_get_unique_section_name rather than
|
||||
duplicating code here.
|
||||
* ld.texinfo: Describe --unique.
|
||||
|
||||
* lexsup.c (ld_options): Make split-by-reloc arg optional. Add
|
||||
optional arg to split-by-file.
|
||||
(parse_args): Handle them.
|
||||
* ld.texinfo: Update description of these options.
|
||||
* ldwrite.c (clone_section): Pass in the section name. Replace
|
||||
local code with bfd_get_unique_section_name.
|
||||
(split_sections): Tidy code and comments. Use a list traversal
|
||||
more appropriate to the list construction. Handle cooked section
|
||||
sizes. Split when split_by_reloc reached rather than exceeded.
|
||||
Track section size and split when split_by_file reached. Fix
|
||||
link_order_tail (even though it's not used).
|
||||
(ldwrite): Modify condition for calling split_sections to suit
|
||||
changed split_by_reloc and split_by_file.
|
||||
* ldmain.c (main): Init config.split_by_reloc and
|
||||
config.split_by_file to -1.
|
||||
* ld.h (ld_config_type): Change split_by_reloc to unsigned.
|
||||
Change split_by_file to bfd_size_type.
|
||||
|
||||
2000-09-02 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* configure.in: Increase version number to 2.10.91.
|
||||
|
@ -1012,23 +1012,28 @@ gld${EMULATION_NAME}_place_orphan (file, s)
|
||||
lang_statement_list_type *old = NULL;
|
||||
lang_statement_list_type add;
|
||||
etree_type *address;
|
||||
const char *secname, *ps = NULL;
|
||||
const char *secname;
|
||||
const char *outsecname;
|
||||
const char *ps = NULL;
|
||||
lang_output_section_statement_type *os;
|
||||
|
||||
secname = bfd_get_section_name (s->owner, s);
|
||||
|
||||
if (! config.unique_orphan_sections)
|
||||
{
|
||||
/* Look through the script to see where to place this section. */
|
||||
os = lang_output_section_find (secname);
|
||||
|
||||
if (os != NULL
|
||||
&& os->bfd_section != NULL
|
||||
&& ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)
|
||||
&& ((s->flags ^ os->bfd_section->flags)
|
||||
& (SEC_LOAD | SEC_ALLOC)) == 0)
|
||||
{
|
||||
/* We have already placed a section with this name. */
|
||||
wild_doit (&os->children, s, os, file);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hold_text.os == NULL)
|
||||
hold_text.os = lang_output_section_find (".text");
|
||||
@ -1087,24 +1092,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
|
||||
loadable or allocateable characteristics. */
|
||||
outsecname = secname;
|
||||
if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
|
||||
{
|
||||
unsigned int len;
|
||||
char *newname;
|
||||
unsigned int i;
|
||||
|
||||
len = strlen (outsecname);
|
||||
newname = xmalloc (len + 5);
|
||||
strcpy (newname, outsecname);
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
sprintf (newname + len, "%d", i);
|
||||
++i;
|
||||
}
|
||||
while (bfd_get_section_by_name (output_bfd, newname) != NULL);
|
||||
|
||||
outsecname = newname;
|
||||
}
|
||||
outsecname = bfd_get_unique_section_name (output_bfd, outsecname, NULL);
|
||||
|
||||
if (place != NULL)
|
||||
{
|
||||
|
8
ld/ld.h
8
ld/ld.h
@ -206,8 +206,12 @@ typedef struct
|
||||
|
||||
boolean stats;
|
||||
|
||||
int split_by_reloc;
|
||||
boolean split_by_file;
|
||||
/* If set, orphan input sections will be mapped to separate output
|
||||
sections. */
|
||||
boolean unique_orphan_sections;
|
||||
|
||||
unsigned int split_by_reloc;
|
||||
bfd_size_type split_by_file;
|
||||
} ld_config_type;
|
||||
|
||||
extern ld_config_type config;
|
||||
|
@ -692,6 +692,14 @@ with @samp{-Ur}; once the constructor table has been built, it cannot
|
||||
be added to. Use @samp{-Ur} only for the last partial link, and
|
||||
@samp{-r} for the others.
|
||||
|
||||
@kindex --unique
|
||||
@item --unique
|
||||
Creates a separate output section for every orphan input section. This
|
||||
option prevents the normal merging of orphan input sections with the same
|
||||
name. An orphan section is one not specifically mentioned in a linker
|
||||
script, so this option along with a custom linker script allows any
|
||||
selection of input sections to be merged while others are kept separate.
|
||||
|
||||
@kindex -v
|
||||
@kindex -V
|
||||
@kindex --version
|
||||
@ -1135,22 +1143,23 @@ everything else. This is to prevent gaps between symbols due to
|
||||
alignment constraints.
|
||||
|
||||
@kindex --split-by-file
|
||||
@item --split-by-file
|
||||
@item --split-by-file [@var{size}]
|
||||
Similar to @code{--split-by-reloc} but creates a new output section for
|
||||
each input file.
|
||||
each input file when @var{size} is reached. @var{size} defaults to a
|
||||
size of 1 if not given.
|
||||
|
||||
@kindex --split-by-reloc
|
||||
@item --split-by-reloc @var{count}
|
||||
Trys to creates extra sections in the output file so that no single
|
||||
@item --split-by-reloc [@var{count}]
|
||||
Tries to creates extra sections in the output file so that no single
|
||||
output section in the file contains more than @var{count} relocations.
|
||||
This is useful when generating huge relocatable for downloading into
|
||||
This is useful when generating huge relocatable files for downloading into
|
||||
certain real time kernels with the COFF object file format; since COFF
|
||||
cannot represent more than 65535 relocations in a single section. Note
|
||||
that this will fail to work with object file formats which do not
|
||||
support arbitrary sections. The linker will not split up individual
|
||||
input sections for redistribution, so if a single input section contains
|
||||
more than @var{count} relocations one output section will contain that
|
||||
many relocations.
|
||||
many relocations. @var{count} defaults to a value of 32768.
|
||||
|
||||
@kindex --stats
|
||||
@item --stats
|
||||
|
@ -200,6 +200,8 @@ main (argc, argv)
|
||||
config.build_constructors = true;
|
||||
config.dynamic_link = false;
|
||||
config.has_shared = false;
|
||||
config.split_by_reloc = (unsigned) -1;
|
||||
config.split_by_file = (bfd_size_type) -1;
|
||||
command_line.force_common_definition = false;
|
||||
command_line.interpreter = NULL;
|
||||
command_line.rpath = NULL;
|
||||
|
142
ld/ldwrite.c
142
ld/ldwrite.c
@ -1,5 +1,5 @@
|
||||
/* ldwrite.c -- write out the linked file
|
||||
Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
|
||||
Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 2000
|
||||
Free Software Foundation, Inc.
|
||||
Written by Steve Chamberlain sac@cygnus.com
|
||||
|
||||
@ -33,7 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "ldmain.h"
|
||||
|
||||
static void build_link_order PARAMS ((lang_statement_union_type *));
|
||||
static asection *clone_section PARAMS ((bfd *, asection *, int *));
|
||||
static asection *clone_section PARAMS ((bfd *, asection *, const char *, int *));
|
||||
static void split_sections PARAMS ((bfd *, struct bfd_link_info *));
|
||||
|
||||
/* Build link_order structures for the BFD linker. */
|
||||
@ -297,40 +297,35 @@ build_link_order (statement)
|
||||
/* 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 */
|
||||
creating new output sections with all the right bits. */
|
||||
#define TESTIT 1
|
||||
static asection *
|
||||
clone_section (abfd, s, count)
|
||||
clone_section (abfd, s, name, count)
|
||||
bfd *abfd;
|
||||
asection *s;
|
||||
const char *name;
|
||||
int *count;
|
||||
{
|
||||
char sname[8]; /* ?? find the name for this size */
|
||||
char template[6];
|
||||
char *sname;
|
||||
asection *n;
|
||||
struct bfd_link_hash_entry *h;
|
||||
/* Invent a section name - use first five
|
||||
chars of base section name and a digit suffix */
|
||||
do
|
||||
{
|
||||
unsigned 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, xstrdup (sname));
|
||||
/* Invent a section name from the first five chars of the base
|
||||
section name and a digit suffix. */
|
||||
strncpy (template, name, sizeof (template) - 1);
|
||||
template[sizeof (template) - 1] = '\0';
|
||||
sname = bfd_get_unique_section_name (abfd, template, count);
|
||||
|
||||
/* Create a symbol of the same name */
|
||||
n = bfd_make_section_anyway (abfd, sname);
|
||||
|
||||
/* Create a symbol of the same name. */
|
||||
|
||||
h = bfd_link_hash_lookup (link_info.hash,
|
||||
sname, true, true, false);
|
||||
h->type = bfd_link_hash_defined;
|
||||
h->u.def.value = 0;
|
||||
h->u.def.section = n ;
|
||||
|
||||
h->u.def.section = n;
|
||||
|
||||
n->flags = s->flags;
|
||||
n->vma = s->vma;
|
||||
@ -409,27 +404,27 @@ split_sections (abfd, info)
|
||||
asection *original_sec;
|
||||
int nsecs = abfd->section_count;
|
||||
sanity_check (abfd);
|
||||
/* look through all the original sections */
|
||||
/* Look through all the original sections. */
|
||||
for (original_sec = abfd->sections;
|
||||
original_sec && nsecs;
|
||||
original_sec = original_sec->next, nsecs--)
|
||||
{
|
||||
boolean first = true;
|
||||
int count = 0;
|
||||
int lines = 0;
|
||||
int relocs = 0;
|
||||
struct bfd_link_order **pp;
|
||||
unsigned int lines = 0;
|
||||
unsigned int relocs = 0;
|
||||
bfd_size_type sec_size = 0;
|
||||
struct bfd_link_order *l;
|
||||
struct bfd_link_order *p;
|
||||
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))
|
||||
/* Count up the relocations and line entries to see if anything
|
||||
would be too big to fit. Accumulate section size too. */
|
||||
for (l = NULL, p = cursor->link_order_head; p != NULL; p = l->next)
|
||||
{
|
||||
struct bfd_link_order *p = *pp;
|
||||
int thislines = 0;
|
||||
int thisrelocs = 0;
|
||||
unsigned int thislines = 0;
|
||||
unsigned int thisrelocs = 0;
|
||||
bfd_size_type thissize = 0;
|
||||
if (p->type == bfd_indirect_link_order)
|
||||
{
|
||||
asection *sec;
|
||||
@ -443,63 +438,81 @@ split_sections (abfd, info)
|
||||
if (info->relocateable)
|
||||
thisrelocs = sec->reloc_count;
|
||||
|
||||
if (sec->_cooked_size != 0)
|
||||
thissize = sec->_cooked_size;
|
||||
else
|
||||
thissize = sec->_raw_size;
|
||||
|
||||
}
|
||||
else if (info->relocateable
|
||||
&& (p->type == bfd_section_reloc_link_order
|
||||
|| p->type == bfd_symbol_reloc_link_order))
|
||||
thisrelocs++;
|
||||
|
||||
if (! first
|
||||
&& (thisrelocs + relocs > config.split_by_reloc
|
||||
|| thislines + lines > config.split_by_reloc
|
||||
|| config.split_by_file))
|
||||
if (l != NULL
|
||||
&& (thisrelocs + relocs >= config.split_by_reloc
|
||||
|| thislines + lines >= config.split_by_reloc
|
||||
|| thissize + sec_size >= 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;
|
||||
/* Create a new section and put this link order and the
|
||||
following link orders into it. */
|
||||
bfd_vma shift_offset;
|
||||
asection *n;
|
||||
|
||||
/* change the size of the original section and
|
||||
update the vma of the new one */
|
||||
n = clone_section (abfd, cursor, original_sec->name, &count);
|
||||
|
||||
/* Attach the link orders to the new section and snip
|
||||
them off from the old section. */
|
||||
n->link_order_head = p;
|
||||
n->link_order_tail = cursor->link_order_tail;
|
||||
cursor->link_order_tail = l;
|
||||
l->next = NULL;
|
||||
l = p;
|
||||
|
||||
/* 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;
|
||||
shift_offset = p->offset;
|
||||
if (cursor->_cooked_size != 0)
|
||||
{
|
||||
n->_cooked_size = cursor->_cooked_size - shift_offset;
|
||||
cursor->_cooked_size = shift_offset;
|
||||
}
|
||||
n->_raw_size = cursor->_raw_size - shift_offset;
|
||||
cursor->_raw_size = shift_offset;
|
||||
|
||||
vma += cursor->_raw_size;
|
||||
vma += shift_offset;
|
||||
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)
|
||||
/* Run down the chain and change the output section to
|
||||
the right one, update the offsets too. */
|
||||
do
|
||||
{
|
||||
l->offset -= shift_offset;
|
||||
if (l->type == bfd_indirect_link_order)
|
||||
p->offset -= shift_offset;
|
||||
if (p->type == bfd_indirect_link_order)
|
||||
{
|
||||
l->u.indirect.section->output_section = n;
|
||||
l->u.indirect.section->output_offset = l->offset;
|
||||
p->u.indirect.section->output_section = n;
|
||||
p->u.indirect.section->output_offset = p->offset;
|
||||
}
|
||||
l = l->next;
|
||||
p = p->next;
|
||||
}
|
||||
while (p);
|
||||
|
||||
dump ("after snip", cursor, n);
|
||||
cursor = n;
|
||||
relocs = thisrelocs;
|
||||
lines = thislines;
|
||||
sec_size = thissize;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = p;
|
||||
relocs += thisrelocs;
|
||||
lines += thislines;
|
||||
sec_size += thissize;
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
sanity_check (abfd);
|
||||
@ -509,11 +522,12 @@ void
|
||||
ldwrite ()
|
||||
{
|
||||
/* Reset error indicator, which can typically something like invalid
|
||||
format from openning up the .o files */
|
||||
format from opening up the .o files. */
|
||||
bfd_set_error (bfd_error_no_error);
|
||||
lang_for_each_statement (build_link_order);
|
||||
|
||||
if (config.split_by_reloc || config.split_by_file)
|
||||
if (config.split_by_reloc != (unsigned) -1
|
||||
|| config.split_by_file != (bfd_size_type) -1)
|
||||
split_sections (output_bfd, &link_info);
|
||||
if (!bfd_final_link (output_bfd, &link_info))
|
||||
{
|
||||
|
22
ld/lexsup.c
22
ld/lexsup.c
@ -125,6 +125,7 @@ int parsing_defsym = 0;
|
||||
#define OPTION_INIT (OPTION_NO_UNDEFINED + 1)
|
||||
#define OPTION_FINI (OPTION_INIT + 1)
|
||||
#define OPTION_SECTION_START (OPTION_FINI + 1)
|
||||
#define OPTION_UNIQUE (OPTION_SECTION_START + 1)
|
||||
|
||||
/* The long options. This structure is used for both the option
|
||||
parsing and the help text. */
|
||||
@ -224,6 +225,8 @@ static const struct ld_option ld_options[] =
|
||||
'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
|
||||
{ {"undefined", required_argument, NULL, 'u'},
|
||||
'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES },
|
||||
{ {"unique", no_argument, NULL, OPTION_UNIQUE},
|
||||
'\0', NULL, N_("Don't merge orphan sections with the same name"), TWO_DASHES },
|
||||
{ {"Ur", no_argument, NULL, OPTION_UR},
|
||||
'\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
|
||||
{ {"version", no_argument, NULL, OPTION_VERSION},
|
||||
@ -326,10 +329,10 @@ static const struct ld_option ld_options[] =
|
||||
'\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
|
||||
{ {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
|
||||
'\0', NULL, NULL, NO_HELP },
|
||||
{ {"split-by-file", no_argument, NULL, OPTION_SPLIT_BY_FILE},
|
||||
'\0', NULL, N_("Split output sections for each file"), TWO_DASHES },
|
||||
{ {"split-by-reloc", required_argument, NULL, OPTION_SPLIT_BY_RELOC},
|
||||
'\0', N_("COUNT"), N_("Split output sections every COUNT relocs"), TWO_DASHES },
|
||||
{ {"split-by-file", optional_argument, NULL, OPTION_SPLIT_BY_FILE},
|
||||
'\0', N_("[=SIZE]"), N_("Split output sections every SIZE octets"), TWO_DASHES },
|
||||
{ {"split-by-reloc", optional_argument, NULL, OPTION_SPLIT_BY_RELOC},
|
||||
'\0', N_("[=COUNT]"), N_("Split output sections every COUNT relocs"), TWO_DASHES },
|
||||
{ {"stats", no_argument, NULL, OPTION_STATS},
|
||||
'\0', NULL, N_("Print memory usage statistics"), TWO_DASHES },
|
||||
{ {"task-link", required_argument, NULL, OPTION_TASK_LINK},
|
||||
@ -917,6 +920,9 @@ parse_args (argc, argv)
|
||||
case 'u':
|
||||
ldlang_add_undef (optarg);
|
||||
break;
|
||||
case OPTION_UNIQUE:
|
||||
config.unique_orphan_sections = true;
|
||||
break;
|
||||
case OPTION_VERBOSE:
|
||||
ldversion (1);
|
||||
version_printed = true;
|
||||
@ -1005,10 +1011,16 @@ the GNU General Public License. This program has absolutely no warranty.\n"));
|
||||
add_ysym (optarg);
|
||||
break;
|
||||
case OPTION_SPLIT_BY_RELOC:
|
||||
if (optarg != NULL)
|
||||
config.split_by_reloc = strtoul (optarg, NULL, 0);
|
||||
else
|
||||
config.split_by_reloc = 32768;
|
||||
break;
|
||||
case OPTION_SPLIT_BY_FILE:
|
||||
config.split_by_file = true;
|
||||
if (optarg != NULL)
|
||||
config.split_by_file = bfd_scan_vma (optarg, NULL, 0);
|
||||
else
|
||||
config.split_by_file = 1;
|
||||
break;
|
||||
case OPTION_CHECK_SECTIONS:
|
||||
command_line.check_section_addresses = true;
|
||||
|
Loading…
Reference in New Issue
Block a user