diff options
author | Michael Brown <mcb30@ipxe.org> | 2015-03-04 18:48:19 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2015-03-05 00:59:38 +0000 |
commit | fbc4ba4b4ed13cc86cb8fdea0bac6c3be0164ed5 (patch) | |
tree | a0c504e297806aa88e89a04e694333a7c5172757 /src/include/compiler.h | |
parent | 86ae6e6c1836e43993a14db278398fc54e5419bd (diff) | |
download | ipxe-fbc4ba4b4ed13cc86cb8fdea0bac6c3be0164ed5.tar.gz |
[build] Fix the REQUIRE_SYMBOL mechanism
At some point in the past few years, binutils became more aggressive
at removing unused symbols. To function as a symbol requirement, a
relocation record must now be in a section marked with @progbits and
must not be in a section which gets discarded during the link (either
via --gc-sections or via /DISCARD/).
Update REQUIRE_SYMBOL() to generate relocation records meeting these
criteria. To minimise the impact upon the final binary size, we use
existing symbols (specified via the REQUIRING_SYMBOL() macro) as the
relocation targets where possible. We use R_386_NONE or R_X86_64_NONE
relocation types to prevent any actual unwanted relocation taking
place. Where no suitable symbol exists for REQUIRING_SYMBOL() (such
as in config.c), the macro PROVIDE_REQUIRING_SYMBOL() can be used to
generate a one-byte-long symbol to act as the relocation target.
If there are versions of binutils for which this approach fails, then
the fallback will probably involve killing off REQUEST_SYMBOL(),
redefining REQUIRE_SYMBOL() to use the current definition of
REQUEST_SYMBOL(), and postprocessing the linked ELF file with
something along the lines of "nm -u | wc -l" to check that there are
no undefined symbols remaining.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include/compiler.h')
-rw-r--r-- | src/include/compiler.h | 149 |
1 files changed, 107 insertions, 42 deletions
diff --git a/src/include/compiler.h b/src/include/compiler.h index f877ebcec..ca82f9523 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -57,54 +57,101 @@ * @{ */ -/** Provide a symbol within this object file */ +/** + * Provide a symbol within this object file + * + * @v symbol Symbol name + */ #ifdef ASSEMBLY -#define PROVIDE_SYMBOL( _sym ) \ - .section ".provided", "a", @nobits ; \ - .hidden _sym ; \ - .globl _sym ; \ - _sym: ; \ +#define PROVIDE_SYMBOL( symbol ) \ + .section ".provided", "a", @nobits ; \ + .hidden symbol ; \ + .globl symbol ; \ + symbol: ; \ .previous -#else /* ASSEMBLY */ -#define PROVIDE_SYMBOL( _sym ) \ - char _sym[0] \ +#else +#define PROVIDE_SYMBOL( symbol ) \ + char symbol[0] \ __attribute__ (( section ( ".provided" ) )) -#endif /* ASSEMBLY */ +#endif -/** Require a symbol within this object file +/** + * Request a symbol + * + * @v symbol Symbol name * - * The symbol is referenced by a relocation in a discarded section, so - * if it is not available at link time the link will fail. + * Request a symbol to be included within the link. If the symbol + * cannot be found, the link will succeed anyway. */ #ifdef ASSEMBLY -#define REQUIRE_SYMBOL( _sym ) \ - .section ".discard", "a", @progbits ; \ - .extern _sym ; \ - .long _sym ; \ - .previous -#else /* ASSEMBLY */ -#define REQUIRE_SYMBOL( _sym ) \ - extern char _sym; \ - static char * _C2 ( _C2 ( __require_, _sym ), _C2 ( _, __LINE__ ) ) \ - __attribute__ (( section ( ".discard" ), used )) \ - = &_sym +#define REQUEST_SYMBOL( symbol ) \ + .equ __request_ ## symbol, symbol +#else +#define REQUEST_SYMBOL( symbol ) \ + __asm__ ( ".equ __request_" #symbol ", " #symbol ) #endif -/** Request that a symbol be available at runtime +/** + * Require a symbol * - * The requested symbol is entered as undefined into the symbol table - * for this object, so the linker will pull in other object files as - * necessary to satisfy the reference. However, the undefined symbol - * is not referenced in any relocations, so the link can still succeed - * if no file contains it. + * @v symbol Symbol name + * + * Require a symbol to be included within the link. If the symbol + * cannot be found, the link will fail. + * + * To use this macro within a file, you must also specify the file's + * "requiring symbol" using the REQUIRING_SYMBOL() or + * PROVIDE_REQUIRING_SYMBOL() macros. */ #ifdef ASSEMBLY -#define REQUEST_SYMBOL( _sym ) \ - .equ __need_ ## _sym, _sym -#else /* ASSEMBLY */ -#define REQUEST_SYMBOL( _sym ) \ - __asm__ ( ".equ\t__need_" #_sym ", " #_sym ) -#endif /* ASSEMBLY */ +#define REQUIRE_SYMBOL( symbol ) \ + .reloc __requiring_symbol__, RELOC_TYPE_NONE, symbol +#else +#define REQUIRE_SYMBOL( symbol ) \ + __asm__ ( ".reloc __requiring_symbol__, " \ + _S2 ( RELOC_TYPE_NONE ) ", " #symbol ) +#endif + +/** + * Specify the file's requiring symbol + * + * @v symbol Symbol name + * + * REQUIRE_SYMBOL() works by defining a dummy relocation record + * against a nominated "requiring symbol". The presence of the + * nominated requiring symbol will drag in all of the symbols + * specified using REQUIRE_SYMBOL(). + */ +#ifdef ASSEMBLY +#define REQUIRING_SYMBOL( symbol ) \ + .equ __requiring_symbol__, symbol +#else +#define REQUIRING_SYMBOL( symbol ) \ + __asm__ ( ".equ __requiring_symbol__, " #symbol ) +#endif + +/** + * Provide a file's requiring symbol + * + * If the file contains no symbols that can be used as the requiring + * symbol, you can provide a dummy one-byte-long symbol using + * PROVIDE_REQUIRING_SYMBOL(). + */ +#ifdef ASSEMBLY +#define PROVIDE_REQUIRING_SYMBOL() \ + .section ".tbl.requiring_symbols", "a", @progbits ; \ + __requiring_symbol__: .byte 0 ; \ + .size __requiring_symbol__, . - __requiring_symbol__ ; \ + .previous +#else +#define PROVIDE_REQUIRING_SYMBOL() \ + __asm__ ( ".section \".tbl.requiring_symbols\", " \ + " \"a\", @progbits\n" \ + "__requiring_symbol__:\t.byte 0\n" \ + ".size __requiring_symbol__, " \ + " . - __requiring_symbol__\n" \ + ".previous" ) +#endif /** @} */ @@ -119,11 +166,29 @@ /** Always provide the symbol for the current object (defined by -DOBJECT) */ PROVIDE_SYMBOL ( OBJECT_SYMBOL ); -/** Explicitly require another object */ -#define REQUIRE_OBJECT( _obj ) REQUIRE_SYMBOL ( obj_ ## _obj ) +/** + * Request an object + * + * @v object Object name + * + * Request an object to be included within the link. If the object + * cannot be found, the link will succeed anyway. + */ +#define REQUEST_OBJECT( object ) REQUEST_SYMBOL ( obj_ ## object ) -/** Pull in another object if it exists */ -#define REQUEST_OBJECT( _obj ) REQUEST_SYMBOL ( obj_ ## _obj ) +/** + * Require an object + * + * @v object Object name + * + * Require an object to be included within the link. If the object + * cannot be found, the link will fail. + * + * To use this macro within a file, you must also specify the file's + * "requiring symbol" using the REQUIRING_SYMBOL() or + * PROVIDE_REQUIRING_SYMBOL() macros. + */ +#define REQUIRE_OBJECT( object ) REQUIRE_SYMBOL ( obj_ ## object ) /** @} */ @@ -685,8 +750,8 @@ int __debug_disable; /** @} */ -/* This file itself is under GPLv2-or-later */ -FILE_LICENCE ( GPL2_OR_LATER ); +/* This file itself is under GPLv2+/UBDL */ +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <bits/compiler.h> |