Fix for PR 19070 - add ability to detect and generate errors when sections

overlap.
This commit is contained in:
Nick Clifton 1999-02-11 16:14:01 +00:00
parent 39c80401ec
commit 22f94ab06c
10 changed files with 320 additions and 27 deletions

View File

@ -1,3 +1,20 @@
1999-02-11 Nick Clifton <nickc@cygnus.com>
* ldlang.c (lang_check_section_addresses): New function: Check
addresses assigned to section for overlaps.
(lang_process): Call lang_check_section_addresses if suitable.
* ld.h: Add new boolean field to args_type structure:
'check_section_addresses'.
* ldmain.c: Initialise check_section_addresses field to true.
* lexsup.c: Add new command line options '--no-check-sections' and
'--check-sections'.
* ld.texinfo: Document new command line options '--check-sections'
and '--no-check-sections'.
1999-02-08 Nick Clifton <nickc@cygnus.com>
* configure.tgt: Add support for StrongARM target.

View File

@ -1,5 +1,5 @@
/* Linker command language support.
Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
@ -152,6 +152,7 @@ static void lang_gc_wild
static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
static void lang_gc_sections PARAMS ((void));
static void lang_do_version_exports_section PARAMS ((void));
static void lang_check_section_addresses PARAMS ((void));
/* EXPORTS */
@ -2272,6 +2273,61 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
return dot;
}
/* Check to see if any allocated sections overlap with other allocated
sections. This can happen when the linker script specifically specifies
the output section addresses of the two sections. */
static void
lang_check_section_addresses ()
{
asection * s;
/* Scan all sections in the output list. */
for (s = output_bfd->sections; s != NULL; s = s->next)
/* Ignore sections which are not loaded or which have no contents. */
if ((bfd_get_section_flags (output_bfd, s) & (SEC_ALLOC | SEC_LOAD))
&& bfd_section_size (output_bfd, s) != 0)
{
asection * os;
/* Once we reach section 's' stop our seach. This prevents two
warning messages from being produced, one for 'section A overlaps
section B' and one for 'section B overlaps section A'. */
for (os = output_bfd->sections; os != s; os = os->next)
{
bfd_vma s_start;
bfd_vma s_end;
bfd_vma os_start;
bfd_vma os_end;
/* Only consider loadable sections with real contents. */
if (((bfd_get_section_flags (output_bfd, os)
& (SEC_ALLOC | SEC_LOAD)) == 0)
|| bfd_section_size (output_bfd, os) == 0)
continue;
/* We must check the sections' LMA addresses not their
VMA addresses because overlay sections can have
overlapping VMAs but they must have distinct LMAs. */
s_start = bfd_section_lma (output_bfd, s);
os_start = bfd_section_lma (output_bfd, os);
s_end = s_start + bfd_section_size (output_bfd, s) - 1;
os_end = os_start + bfd_section_size (output_bfd, os) - 1;
/* Look for an overlap. */
if ((s_end < os_start) || (s_start > os_end))
continue;
einfo (_(\
"%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
s->name, s_start, s_end, os->name, os_start, os_end);
/* Once we have found one overlap for this section,
stop looking for others. */
break;
}
}
}
/* This variable indicates whether bfd_relax_section should be called
again. */
@ -2421,7 +2477,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
since unallocated sections do not contribute to the region's
overall size in memory. */
if (os->region != (lang_memory_region_type *) NULL
&& bfd_get_section_flags (output_bfd, os->bfd_section) & SEC_ALLOC)
&& (bfd_get_section_flags (output_bfd, os->bfd_section)
& (SEC_ALLOC | SEC_LOAD)))
{
os->region->current = dot;
@ -3713,6 +3770,11 @@ lang_process ()
abs_output_section,
(fill_type) 0, (bfd_vma) 0);
/* Make sure that the section addresses make sense. */
if (! link_info.relocateable
&& command_line.check_section_addresses)
lang_check_section_addresses ();
/* Final stuffs */
ldemul_finish ();

View File

@ -199,6 +199,7 @@ main (argc, argv)
command_line.interpreter = NULL;
command_line.rpath = NULL;
command_line.warn_mismatch = true;
command_line.check_section_addresses = true;
link_info.callbacks = &link_callbacks;
link_info.relocateable = false;
@ -246,9 +247,6 @@ main (argc, argv)
einfo (_("%P%F: -r and -shared may not be used together\n"));
}
if (command_line.gc_sections && config.dynamic_link)
einfo("%P%F: --gc-sections may only be performed for static links\n");
/* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I
don't see how else this can be handled, since in this case we
must preserve all externally visible symbols. */

View File

@ -101,7 +101,8 @@ int parsing_defsym = 0;
#define OPTION_VERBOSE (OPTION_UR + 1)
#define OPTION_VERSION (OPTION_VERBOSE + 1)
#define OPTION_VERSION_SCRIPT (OPTION_VERSION + 1)
#define OPTION_WARN_COMMON (OPTION_VERSION_SCRIPT + 1)
#define OPTION_VERSION_EXPORTS_SECTION (OPTION_VERSION_SCRIPT + 1)
#define OPTION_WARN_COMMON (OPTION_VERSION_EXPORTS_SECTION + 1)
#define OPTION_WARN_CONSTRUCTORS (OPTION_WARN_COMMON + 1)
#define OPTION_WARN_MULTIPLE_GP (OPTION_WARN_CONSTRUCTORS + 1)
#define OPTION_WARN_ONCE (OPTION_WARN_MULTIPLE_GP + 1)
@ -113,6 +114,8 @@ int parsing_defsym = 0;
#define OPTION_FORCE_EXE_SUFFIX (OPTION_WRAP + 1)
#define OPTION_GC_SECTIONS (OPTION_FORCE_EXE_SUFFIX + 1)
#define OPTION_NO_GC_SECTIONS (OPTION_GC_SECTIONS + 1)
#define OPTION_CHECK_SECTIONS (OPTION_NO_GC_SECTIONS + 1)
#define OPTION_NO_CHECK_SECTIONS (OPTION_CHECK_SECTIONS + 1)
/* The long options. This structure is used for both the option
parsing and the help text. */
@ -158,6 +161,10 @@ static const struct ld_option ld_options[] =
'e', N_("ADDRESS"), N_("Set start address"), TWO_DASHES },
{ {"export-dynamic", no_argument, NULL, OPTION_EXPORT_DYNAMIC},
'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
{ {"EB", no_argument, NULL, OPTION_EB},
'\0', NULL, N_("Link big-endian objects"), ONE_DASH },
{ {"EL", no_argument, NULL, OPTION_EL},
'\0', NULL, N_("Link little-endian objects"), ONE_DASH },
{ {"auxiliary", required_argument, NULL, 'f'},
'f', N_("SHLIB"), N_("Auxiliary filter for shared object symbol table"),
TWO_DASHES },
@ -165,12 +172,6 @@ static const struct ld_option ld_options[] =
'F', N_("SHLIB"), N_("Filter for shared object symbol table"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
'g', NULL, N_("Ignored"), ONE_DASH },
{ {"gc-sections", no_argument, NULL, OPTION_GC_SECTIONS},
'\0', NULL, N_("Remove unused sections on certain targets"),
TWO_DASHES },
{ {"no-gc-sections", no_argument, NULL, OPTION_NO_GC_SECTIONS},
'\0', NULL, N_("(Don't) Remove unused sections on certain targets"),
TWO_DASHES },
{ {"gpsize", required_argument, NULL, 'G'},
'G', N_("SIZE"), N_("Small data size (if no size, same as --shared)"),
TWO_DASHES },
@ -192,7 +193,9 @@ static const struct ld_option ld_options[] =
{ {"output", required_argument, NULL, 'o'},
'o', N_("FILE"), N_("Set output file name"), TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
'O', NULL, N_("Ignored"), ONE_DASH },
'O', NULL, N_("Optimize output file"), ONE_DASH },
{ {"Qy", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
{ {"relocateable", no_argument, NULL, 'r'},
'r', NULL, N_("Generate relocateable output"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
@ -210,6 +213,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 },
{ {"Ur", no_argument, NULL, OPTION_UR},
'\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"version", no_argument, NULL, OPTION_VERSION},
'v', NULL, N_("Print version information"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
@ -246,20 +251,27 @@ static const struct ld_option ld_options[] =
'\0', NULL, NULL, ONE_DASH },
{ {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC},
'\0', NULL, N_("Bind global references locally"), ONE_DASH },
{ {"check-sections", no_argument, NULL, OPTION_CHECK_SECTIONS},
'\0', NULL, N_("Check section addresses for overlaps (default)"), TWO_DASHES },
{ {"no-check-sections", no_argument, NULL, OPTION_NO_CHECK_SECTIONS},
'\0', NULL, N_("Do not check section addresses for overlaps"),
TWO_DASHES },
{ {"cref", no_argument, NULL, OPTION_CREF},
'\0', NULL, N_("Output cross reference table"), TWO_DASHES },
{ {"defsym", required_argument, NULL, OPTION_DEFSYM},
'\0', N_("SYMBOL=EXPRESSION"), N_("Define a symbol"), TWO_DASHES },
{ {"dynamic-linker", required_argument, NULL, OPTION_DYNAMIC_LINKER},
'\0', N_("PROGRAM"), N_("Set the dynamic linker to use"), TWO_DASHES },
{ {"EB", no_argument, NULL, OPTION_EB},
'\0', NULL, N_("Link big-endian objects"), ONE_DASH },
{ {"EL", no_argument, NULL, OPTION_EL},
'\0', NULL, N_("Link little-endian objects"), ONE_DASH },
{ {"embedded-relocs", no_argument, NULL, OPTION_EMBEDDED_RELOCS},
'\0', NULL, N_("Generate embedded relocs"), TWO_DASHES},
{ {"force-exe-suffix", no_argument, NULL, OPTION_FORCE_EXE_SUFFIX},
'\0', NULL, N_("Force generation of file with .exe suffix"), TWO_DASHES},
{ {"gc-sections", no_argument, NULL, OPTION_GC_SECTIONS},
'\0', NULL, N_("Remove unused sections (on some targets)"),
TWO_DASHES },
{ {"no-gc-sections", no_argument, NULL, OPTION_NO_GC_SECTIONS},
'\0', NULL, N_("Don't remove unused sections (default)"),
TWO_DASHES },
{ {"help", no_argument, NULL, OPTION_HELP},
'\0', NULL, N_("Print option help"), TWO_DASHES },
{ {"Map", required_argument, NULL, OPTION_MAP},
@ -278,8 +290,6 @@ static const struct ld_option ld_options[] =
'\0', N_("TARGET"), N_("Specify target of output file"), TWO_DASHES },
{ {"qmagic", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for Linux compatibility"), ONE_DASH },
{ {"Qy", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
{ {"relax", no_argument, NULL, OPTION_RELAX},
'\0', NULL, N_("Relax branches on certain targets"), TWO_DASHES },
{ {"retain-symbols-file", required_argument, NULL,
@ -313,14 +323,16 @@ static const struct ld_option ld_options[] =
'\0', N_("ADDRESS"), N_("Set address of .data section"), ONE_DASH },
{ {"Ttext", required_argument, NULL, OPTION_TTEXT},
'\0', N_("ADDRESS"), N_("Set address of .text section"), ONE_DASH },
{ {"Ur", no_argument, NULL, OPTION_UR},
'\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"verbose", no_argument, NULL, OPTION_VERBOSE},
'\0', NULL, N_("Output lots of information during link"), TWO_DASHES },
{ {"dll-verbose", no_argument, NULL, OPTION_VERBOSE}, /* Linux. */
'\0', NULL, NULL, NO_HELP },
{ {"version-script", required_argument, NULL, OPTION_VERSION_SCRIPT },
'\0', N_("FILE"), N_("Read version information script"), TWO_DASHES },
{ {"version-exports-section", required_argument, NULL,
OPTION_VERSION_EXPORTS_SECTION },
'\0', N_("SYMBOL"), N_("Take export symbols list from .exports, using SYMBOL as the version."),
TWO_DASHES },
{ {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
'\0', NULL, N_("Warn about duplicate common symbols"), TWO_DASHES },
{ {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
@ -636,6 +648,9 @@ parse_args (argc, argv)
something, or can we create a new option to do that
(with a syntax similar to -defsym)?
getopt can't handle two args to an option without kludges. */
/* Enable optimizations of output files. */
link_info.optimize = strtoul (optarg, NULL, 0) ? true : false;
break;
case 'o':
lang_add_output (optarg, 0);
@ -677,14 +692,36 @@ parse_args (argc, argv)
command_line.rpath = buystring (optarg);
else
{
size_t rpath_len = strlen (command_line.rpath);
size_t optarg_len = strlen (optarg);
char *buf;
char *cp = command_line.rpath;
buf = xmalloc (strlen (command_line.rpath)
+ strlen (optarg)
+ 2);
sprintf (buf, "%s:%s", command_line.rpath, optarg);
free (command_line.rpath);
command_line.rpath = buf;
/* First see whether OPTARG is already in the path. */
do
{
size_t idx = 0;
while (optarg[idx] != '\0' && optarg[idx] == cp[idx])
++idx;
if (optarg[idx] == '\0'
&& (cp[idx] == '\0' || cp[idx] == ':'))
/* We found it. */
break;
/* Not yet found. */
cp = strchr (cp, ':');
if (cp != NULL)
++cp;
}
while (cp != NULL);
if (cp == NULL)
{
buf = xmalloc (rpath_len + optarg_len + 2);
sprintf (buf, "%s:%s", command_line.rpath, optarg);
free (command_line.rpath);
command_line.rpath = buf;
}
}
break;
case OPTION_RPATH_LINK:
@ -812,6 +849,12 @@ the GNU General Public License. This program has absolutely no warranty.\n"));
yyparse ();
}
break;
case OPTION_VERSION_EXPORTS_SECTION:
/* This option records a version symbol to be applied to the
symbols listed for export to be found in the object files
.exports sections. */
command_line.version_exports_section = optarg;
break;
case OPTION_WARN_COMMON:
config.warn_common = true;
break;
@ -858,6 +901,12 @@ the GNU General Public License. This program has absolutely no warranty.\n"));
case OPTION_SPLIT_BY_FILE:
config.split_by_file = true;
break;
case OPTION_CHECK_SECTIONS:
command_line.check_section_addresses = true;
break;
case OPTION_NO_CHECK_SECTIONS:
command_line.check_section_addresses = false;
break;
case '(':
if (ingroup)
{

View File

@ -37,6 +37,7 @@ ld-shared
ld-srec
ld-undefined
ld-versados
ld-checks
Things-to-lose:

View File

@ -1,3 +1,23 @@
1999-02-11 Nick Clifton <nickc@cygnus.com>
* ld-checks: New directory: Tests for the linker's
--check-sections option.
* ld-checks/checks.exp: New file.
* ld-checks/script: Bogus linker script.
* ld-checks/asm.s: Simple test assembler file.
Tue Feb 2 19:15:02 1999 Catherine Moore <clm@cygnus.com>
* ld-selective/selective.exp: Disable test for unsupported
targets. Change tests to check for absence of symbols instead
of address zero.
Mon Jan 18 03:44:52 1999 Ian Lance Taylor <ian@cygnus.com>
* config/default.exp (get_link_files): Quote target_triplet and CC
when invoking shell.
(get_target_emul): Likewise.
1999-01-03 Ken Raeburn <raeburn@cygnus.com>
* config/default.exp (get_link_files, get_target_emul): New procs;

View File

@ -0,0 +1,45 @@
# .Sanitize for ld dejagnu testsuites
# Each directory to survive it's way into a release will need a file
# like this one called "./.Sanitize". All keyword lines must exist,
# and must exist in the order specified by this file. Each directory
# in the tree will be processed, top down, in the following order..
# Hash started lines like this one are comments and will be deleted
# before anything else is done. Blank lines will also be squashed
# out.
# The lines between the "Do-first:" line and the "Things-to-keep:"
# line are executed as a /bin/sh shell script before anything else is
# done in this directory.
Do-first:
# All files listed between the "Things-to-keep:" line and the
# "Do-last:" line will be kept. All other files will be removed.
# Directories listed in this section will have their own Sanitize
# called. Directories not listed will be removed in their entirety
# with rm -rf.
Things-to-keep:
asm.s
script
checks.exp
Things-to-lose:
# The lines between the "Do-last:" line and the end of the file
# are executed as a /bin/sh shell script after everything else is
# done.
Do-last:
for i in * ; do
if test ! -d $i && (grep sanitize $i > /dev/null) ; then
echo '***' Some mentions of Sanitize are still left in $i! 1>&2
fi
done
#eof

View File

@ -0,0 +1,21 @@
.section .foo,"ax",@progbits
.global foo
foo:
.word 0x12345678
.section .bar,"ax",@progbits
.global bar
bar:
.word 0x87654321
.section .overlay1,"ax",@progbits;
.global jim
jim:
.word 0xdeadbeef
.section .overlay2,"ax",@progbits
.global harry
harry:
.word 0x99119911

View File

@ -0,0 +1,72 @@
# Expect script for LD section checks tests
# Copyright (C) 1999 Free Software Foundation
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Written by Nick Clifton (nickc@cygnus.com)
proc section_check {} {
global ld_flags
global as
global ld
global srcdir
global subdir
set test "check sections"
set ldflags "--check-sections"
if { ![ld_assemble $as $srcdir/$subdir/asm.s tmpdir/asm.o]} {
unresolved $test
return
}
if ![ld_simple_link $ld tmpdir/asm.x "$ldflags tmpdir/asm.o"] {
fail "$test : using default linker script"
} else {
pass $test
}
# Change the linker flags so that our "buggy" linker
# script is used.
set ldflags "--check-sections -T $srcdir/$subdir/script -e foo"
# Perform the equivalent of invoking ld_simple_link
# except that we need to massage the output futher.
catch "exec $ld -o tmpdir/asm.x $ldflags tmpdir/asm.o" exec_output
set exec_output [prune_warnings $exec_output]
# Make sure that we got some output from the linker
if [string match "" $exec_output] then {
fail "$test - error message expected but not found"
}
# Now remove our expected error message
regsub -all ".*: section .bar .* overlaps section .foo .*" $exec_output "" exec_output
# And check to see if anything else, (unexpected) was left
if [string match "" $exec_output] then {
pass $test
} else {
verbose -log "Unexpected linker message(s): $exec_output"
fail "$test - using erroneous linker script"
}
}
section_check

View File

@ -0,0 +1,8 @@
SECTIONS {
.foo 0x100 : { *(.foo) }
.bar 0x100 : AT (0x100) { *(.bar) }
.overlay1 0x100 : AT (0x4000) { *(.overlay1) }
.overlay2 0x100 : AT (0x4004) { *(.overlay2) }
}