This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ld: Add '--defined' command line option.


Add a new command line option '--defined' to the linker.  This option
operates identically to the '--undefined' option, except that if the
symbol is not defined in the final output file then the linker will exit
with an error.

When making use of --gc-section, or just when trying to pull in parts of
a library, it is not uncommon for a user to use the '--undefined'
command line option to specify a symbol that the user then expects to be
defined by one of the object files supplied to the link.

However, if for any reason the symbol is not satisfied by an object
provided to the link the user will be left with an undefined symbol in
the output file, instead of a defined symbol.

In some cases the above behaviour is what the user wants, in other cases
though we can do better.  The '--defined' option tries to fill this
gap.  The symbol passed to the '--defined' option is treated exactly as
if the symbol was passed to '--undefined', however, before the linker
exits a check is made that all symbols passed to '--defined' are
actually defined, if any are not then the link will fail with an error.

ld/ChangeLog:

	* ld.texinfo (Options): Document --defined option.
	* ldlang.c (struct require_defined_symbol): New structure.
	(require_defined_symbol_list): New variable.
	(ldlang_add_require_defined): New function.
	(ldlang_check_require_defined_symbols): New function.
	(lang_process): Check required symbols are defined.
	* ldlang.h (ldlang_add_require_defined): Declare.
	* ldlex.h (enum option_values): Add OPTION_REQUIRE_DEFINED_SYMBOL.
	* lexsup.c (ld_options): Add '--defined' entry.
	(parse_args): Handle '--defined' entry.

ld/testsuite/ChangeLog:

	* ld-elf/elf.exp: Add test of --defined option.
	* ld-elf/defined.err: New file.
	* ld-elf/defined.nm: New file.
	* ld-elf/defined.s: New file.
---
 ld/ChangeLog                    | 13 +++++++++++
 ld/ld.texinfo                   |  9 +++++++
 ld/ldlang.c                     | 52 +++++++++++++++++++++++++++++++++++++++++
 ld/ldlang.h                     |  2 ++
 ld/ldlex.h                      |  1 +
 ld/lexsup.c                     |  6 +++++
 ld/testsuite/ChangeLog          |  7 ++++++
 ld/testsuite/ld-elf/defined.err |  1 +
 ld/testsuite/ld-elf/defined.nm  |  3 +++
 ld/testsuite/ld-elf/defined.s   |  9 +++++++
 ld/testsuite/ld-elf/elf.exp     |  9 +++++++
 11 files changed, 112 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/defined.err
 create mode 100644 ld/testsuite/ld-elf/defined.nm
 create mode 100644 ld/testsuite/ld-elf/defined.s

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 3dd0a6f..8ac1280 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,16 @@
+2015-07-15  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* ld.texinfo (Options): Document --defined option.
+	* ldlang.c (struct require_defined_symbol): New structure.
+	(require_defined_symbol_list): New variable.
+	(ldlang_add_require_defined): New function.
+	(ldlang_check_require_defined_symbols): New function.
+	(lang_process): Check required symbols are defined.
+	* ldlang.h (ldlang_add_require_defined): Declare.
+	* ldlex.h (enum option_values): Add OPTION_REQUIRE_DEFINED_SYMBOL.
+	* lexsup.c (ld_options): Add '--defined' entry.
+	(parse_args): Handle '--defined' entry.
+
 2015-07-14  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Make
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index b48396d..5a844f8 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -973,6 +973,15 @@ modules from standard libraries.  @samp{-u} may be repeated with
 different option arguments to enter additional undefined symbols.  This
 option is equivalent to the @code{EXTERN} linker script command.
 
+@kindex --defined=@var{symbol}
+@cindex defined symbol
+@item --defined=@var{symbol}
+Require that @var{symbol} is defined in the output file.  This option
+is the same as @samp{--undefined} except that if @var{symbol} is not
+defined in the output file then the linker will issue an error and
+exit.  The same effect can be achieved in a linker script by using
+@code{EXTERN}, @code{ASSERT} and @code{DEFINED} together.
+
 @kindex -Ur
 @cindex constructors
 @item -Ur
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b816d69..0d6419d 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3413,6 +3413,55 @@ lang_place_undefineds (void)
     insert_undefined (ptr->name);
 }
 
+/* Structure used to build the list of symbols that the user has required
+   be defined.  */
+
+struct require_defined_symbol
+{
+  const char *name;
+  struct require_defined_symbol *next;
+};
+
+/* The list of symbols that the user has required be defined.  */
+
+static struct require_defined_symbol *require_defined_symbol_list;
+
+/* Add a new symbol NAME to the list of symbols that are required to be
+   defined.  */
+
+void
+ldlang_add_require_defined (const char * const name)
+{
+  struct require_defined_symbol *ptr;
+
+  ldlang_add_undef (name, TRUE);
+  ptr = (struct require_defined_symbol *) stat_alloc (sizeof (*ptr));
+  ptr->next = require_defined_symbol_list;
+  ptr->name = strdup (name);
+  require_defined_symbol_list = ptr;
+}
+
+/* Check that all symbols the user required to be defined, are defined,
+   raise an error if we find a symbol that is not defined.  */
+
+static void
+ldlang_check_require_defined_symbols (void)
+{
+  struct require_defined_symbol *ptr;
+
+  for (ptr = require_defined_symbol_list; ptr != NULL; ptr = ptr->next)
+    {
+      struct bfd_link_hash_entry *h;
+
+      h = bfd_link_hash_lookup (link_info.hash, ptr->name,
+                                FALSE, FALSE, TRUE);
+      if (h == NULL
+          || (h->type != bfd_link_hash_defined
+              && h->type != bfd_link_hash_defweak))
+        einfo(_("%P%X: required symbol `%s' not defined\n"), ptr->name);
+    }
+}
+
 /* Check for all readonly or some readwrite sections.  */
 
 static void
@@ -6805,6 +6854,9 @@ lang_process (void)
   if (command_line.check_section_addresses)
     lang_check_section_addresses ();
 
+  /* Check any required symbols are known.  */
+  ldlang_check_require_defined_symbols ();
+
   lang_end ();
 }
 
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 475cf71..4b7e65d 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -609,6 +609,8 @@ extern lang_output_section_statement_type *next_matching_output_section_statemen
   (lang_output_section_statement_type *, int);
 extern void ldlang_add_undef
   (const char *const, bfd_boolean);
+extern void ldlang_add_require_defined
+  (const char *const);
 extern void lang_add_output_format
   (const char *, const char *, const char *, int);
 extern void lang_list_init
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 7885de0..59bd14f 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -143,6 +143,7 @@ enum option_values
   OPTION_PUSH_STATE,
   OPTION_POP_STATE,
   OPTION_PRINT_MEMORY_USAGE,
+  OPTION_REQUIRE_DEFINED_SYMBOL,
 };
 
 /* The initial parser states.  */
diff --git a/ld/lexsup.c b/ld/lexsup.c
index b884d9a..9744bdf 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -212,6 +212,9 @@ static const struct ld_option ld_options[] =
   { {"undefined", required_argument, NULL, 'u'},
     'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"),
     TWO_DASHES },
+  { {"defined", required_argument, NULL, OPTION_REQUIRE_DEFINED_SYMBOL},
+    '\0', N_("SYMBOL"), N_("Require SYMBOL be defined in the final output"),
+    TWO_DASHES },
   { {"unique", optional_argument, NULL, OPTION_UNIQUE},
     '\0', N_("[=SECTION]"),
     N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES },
@@ -1247,6 +1250,9 @@ parse_args (unsigned argc, char **argv)
 	case 'u':
 	  ldlang_add_undef (optarg, TRUE);
 	  break;
+        case OPTION_REQUIRE_DEFINED_SYMBOL:
+          ldlang_add_require_defined (optarg);
+	  break;
 	case OPTION_UNIQUE:
 	  if (optarg != NULL)
 	    lang_add_unique (optarg);
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index c279cbd..48bc54f 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-07-15  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* ld-elf/elf.exp: Add test of --defined option.
+	* ld-elf/defined.err: New file.
+	* ld-elf/defined.nm: New file.
+	* ld-elf/defined.s: New file.
+
 2015-07-14  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* ld-elf/zlibbegin.rS: Updated to .debug_.* with the
diff --git a/ld/testsuite/ld-elf/defined.err b/ld/testsuite/ld-elf/defined.err
new file mode 100644
index 0000000..f147d02
--- /dev/null
+++ b/ld/testsuite/ld-elf/defined.err
@@ -0,0 +1 @@
+.*: required symbol `xxx' not defined
diff --git a/ld/testsuite/ld-elf/defined.nm b/ld/testsuite/ld-elf/defined.nm
new file mode 100644
index 0000000..29a6506
--- /dev/null
+++ b/ld/testsuite/ld-elf/defined.nm
@@ -0,0 +1,3 @@
+[0-9a-f]+ T _start
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-elf/defined.s b/ld/testsuite/ld-elf/defined.s
new file mode 100644
index 0000000..99a18ec
--- /dev/null
+++ b/ld/testsuite/ld-elf/defined.s
@@ -0,0 +1,9 @@
+        .section ".text", "ax"
+        .global _start
+_start:
+        nop
+
+        .section ".text.1", "ax"
+        .global foo
+foo:
+        nop
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index d1a70ea..5542fa8 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -164,6 +164,15 @@ if { [istarget *-*-*linux*]
 
 set LDFLAGS $old_ldflags
 
+run_ld_link_tests {
+    { "Check defined option with undefined symbol"
+        "--gc-sections --defined=xxx" "" "" {defined.s}
+        {{ld defined.err}} "defined.x"}
+    { "Check defined option with defined symbol"
+        "--gc-sections --defined=foo" "" "" {defined.s}
+        {{nm "-n" defined.nm}} "defined.x"}
+}
+
 # The following tests require running the executable generated by ld.
 if ![isnative] {
     return
-- 
2.4.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]