diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-07-15 18:37:30 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-08-04 10:00:05 +0100 |
commit | 0a61824343c98b9440fe13752f800d65f765c4c1 (patch) | |
tree | b4a6e80aed76a598ca778adb188cc257c8c74a46 /ld/ldlang.c | |
parent | 96e9210fd6fecc1926559dbfa45e7c7c59f7d821 (diff) | |
download | gdb-0a61824343c98b9440fe13752f800d65f765c4c1.zip gdb-0a61824343c98b9440fe13752f800d65f765c4c1.tar.gz gdb-0a61824343c98b9440fe13752f800d65f765c4c1.tar.bz2 |
ld: Add '--require-defined' command line option.
Add a new command line option '--require-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 '--require-defined' option tries to fill
this gap. The symbol passed to the '--require-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
'--require-defined' are actually defined, if any are not then the link
will fail with an error.
ld/ChangeLog:
* ld.texinfo (Options): Document --require-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 '--require-defined' entry.
(parse_args): Handle '--require-defined' entry.
* NEWS: Mention new '--require-defined' option.
ld/testsuite/ChangeLog:
* ld-undefined/require-defined-1.d: New file.
* ld-undefined/require-defined-2.d: New file.
* ld-undefined/require-defined-3.d: New file.
* ld-undefined/require-defined-4.d: New file.
* ld-undefined/require-defined-5.d: New file.
* ld-undefined/require-defined.exp: New file.
* ld-undefined/require-defined.s: New file.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 52 |
1 files changed, 52 insertions, 0 deletions
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 (); } |