mirror of
https://github.com/ipxe/ipxe
synced 2025-12-30 13:11:11 +03:00
[build] Formalise mechanism for accessing absolute symbols
In a position-dependent executable, where all addresses are fixed
at link time, we can use the standard technique as documented by
GNU ld to get the value of an absolute symbol, e.g.:
extern char _my_symbol[];
printf ( "Absolute symbol value is %x\n", ( ( int ) _my_symbol ) );
This technique may not work in a position-independent executable.
When dynamic relocations are applied, the runtime addresses will no
longer be equal to the link-time addresses. If the code to obtain the
address of _my_symbol uses PC-relative addressing, then it will
calculate the runtime "address" of the absolute symbol, which will no
longer be equal the the link-time "address" (i.e. the correct value)
of the absolute symbol.
Define macros ABS_SYMBOL(), ABS_VALUE_INIT(), and ABS_VALUE() that
provide access to the correct values of absolute symbols even in
position-independent code, and use these macros wherever absolute
symbols are accessed.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -365,7 +365,8 @@ extern char __text16_array ( sipi, [] );
|
|||||||
#define sipi __use_text16 ( sipi )
|
#define sipi __use_text16 ( sipi )
|
||||||
|
|
||||||
/** Length of startup IPI real-mode handler */
|
/** Length of startup IPI real-mode handler */
|
||||||
extern char sipi_len[];
|
extern size_t ABS_SYMBOL ( sipi_len );
|
||||||
|
#define sipi_len ABS_VALUE ( sipi_len )
|
||||||
|
|
||||||
/** Startup IPI real-mode handler copy of real-mode data segment */
|
/** Startup IPI real-mode handler copy of real-mode data segment */
|
||||||
extern uint16_t __text16 ( sipi_ds );
|
extern uint16_t __text16 ( sipi_ds );
|
||||||
|
|||||||
@@ -76,10 +76,10 @@ extern struct segoff __text16 ( int15_vector );
|
|||||||
/* The linker defines these symbols for us */
|
/* The linker defines these symbols for us */
|
||||||
extern char _textdata[];
|
extern char _textdata[];
|
||||||
extern char _etextdata[];
|
extern char _etextdata[];
|
||||||
extern char _text16_memsz[];
|
extern size_t ABS_SYMBOL ( _text16_memsz );
|
||||||
#define _text16_memsz ( ( size_t ) _text16_memsz )
|
#define _text16_memsz ABS_VALUE ( _text16_memsz )
|
||||||
extern char _data16_memsz[];
|
extern size_t ABS_SYMBOL ( _data16_memsz );
|
||||||
#define _data16_memsz ( ( size_t ) _data16_memsz )
|
#define _data16_memsz ABS_VALUE ( _data16_memsz )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide region of memory from system memory map
|
* Hide region of memory from system memory map
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ extern void pxe_int_1a ( void );
|
|||||||
static int int_1a_hooked = 0;
|
static int int_1a_hooked = 0;
|
||||||
|
|
||||||
/** Real-mode code segment size */
|
/** Real-mode code segment size */
|
||||||
extern char _text16_memsz[];
|
extern size_t ABS_SYMBOL ( _text16_memsz );
|
||||||
#define _text16_memsz ( ( size_t ) _text16_memsz )
|
#define _text16_memsz ABS_VALUE ( _text16_memsz )
|
||||||
|
|
||||||
/** Real-mode data segment size */
|
/** Real-mode data segment size */
|
||||||
extern char _data16_memsz[];
|
extern size_t ABS_SYMBOL (_data16_memsz );
|
||||||
#define _data16_memsz ( ( size_t ) _data16_memsz )
|
#define _data16_memsz ABS_VALUE ( _data16_memsz )
|
||||||
|
|
||||||
/** PXENV_UNDI_TRANSMIT API call profiler */
|
/** PXENV_UNDI_TRANSMIT API call profiler */
|
||||||
static struct profiler pxe_api_tx_profiler __profiler =
|
static struct profiler pxe_api_tx_profiler __profiler =
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ void setup_sipi ( unsigned int vector, uint32_t handler,
|
|||||||
memcpy ( &sipi_regs, regs, sizeof ( sipi_regs ) );
|
memcpy ( &sipi_regs, regs, sizeof ( sipi_regs ) );
|
||||||
|
|
||||||
/* Copy real-mode handler */
|
/* Copy real-mode handler */
|
||||||
copy_to_real ( ( vector << 8 ), 0, sipi, ( ( size_t ) sipi_len ) );
|
copy_to_real ( ( vector << 8 ), 0, sipi, sipi_len );
|
||||||
}
|
}
|
||||||
|
|
||||||
PROVIDE_IOMAP_INLINE ( pages, io_to_bus );
|
PROVIDE_IOMAP_INLINE ( pages, io_to_bus );
|
||||||
|
|||||||
@@ -49,16 +49,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
|
FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
|
||||||
|
|
||||||
/** Build timestamp (generated by linker) */
|
/** Build timestamp (generated by linker) */
|
||||||
extern char _build_timestamp[];
|
extern unsigned long ABS_SYMBOL ( _build_timestamp );
|
||||||
|
|
||||||
/** Build ID (generated by linker) */
|
/** Build ID (generated by linker) */
|
||||||
extern char _build_id[];
|
extern unsigned long ABS_SYMBOL ( _build_id );
|
||||||
|
|
||||||
/** Build timestamp */
|
/** Build timestamp */
|
||||||
unsigned long build_timestamp = ( ( unsigned long ) _build_timestamp );
|
unsigned long build_timestamp = ABS_VALUE_INIT ( _build_timestamp );
|
||||||
|
|
||||||
/** Build ID */
|
/** Build ID */
|
||||||
unsigned long build_id = ( ( unsigned long ) _build_id );
|
unsigned long build_id = ABS_VALUE_INIT ( _build_id );
|
||||||
|
|
||||||
/** Product major version */
|
/** Product major version */
|
||||||
const int product_major_version = VERSION_MAJOR;
|
const int product_major_version = VERSION_MAJOR;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#undef CERT
|
#undef CERT
|
||||||
#define CERT( _index, _path ) \
|
#define CERT( _index, _path ) \
|
||||||
extern char stored_cert_ ## _index ## _data[]; \
|
extern char stored_cert_ ## _index ## _data[]; \
|
||||||
extern char stored_cert_ ## _index ## _len[]; \
|
extern size_t ABS_SYMBOL ( stored_cert_ ## _index ## _len ); \
|
||||||
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t" \
|
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t" \
|
||||||
"\nstored_cert_" #_index "_data:\n\t" \
|
"\nstored_cert_" #_index "_data:\n\t" \
|
||||||
".incbin \"" _path "\"\n\t" \
|
".incbin \"" _path "\"\n\t" \
|
||||||
@@ -59,7 +59,7 @@ CERT_ALL
|
|||||||
#undef CERT
|
#undef CERT
|
||||||
#define CERT( _index, _path ) { \
|
#define CERT( _index, _path ) { \
|
||||||
.data = stored_cert_ ## _index ## _data, \
|
.data = stored_cert_ ## _index ## _data, \
|
||||||
.len = ( size_t ) stored_cert_ ## _index ## _len, \
|
.len = ABS_VALUE_INIT ( stored_cert_ ## _index ## _len ), \
|
||||||
},
|
},
|
||||||
static struct asn1_cursor certstore_raw[] = {
|
static struct asn1_cursor certstore_raw[] = {
|
||||||
CERT_ALL
|
CERT_ALL
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
|
|
||||||
/* Raw private key data */
|
/* Raw private key data */
|
||||||
extern char private_key_data[];
|
extern char private_key_data[];
|
||||||
extern char private_key_len[];
|
extern size_t ABS_SYMBOL ( private_key_len );
|
||||||
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t"
|
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t"
|
||||||
"\nprivate_key_data:\n\t"
|
"\nprivate_key_data:\n\t"
|
||||||
#ifdef PRIVATE_KEY
|
#ifdef PRIVATE_KEY
|
||||||
@@ -68,7 +68,7 @@ struct private_key private_key = {
|
|||||||
.refcnt = REF_INIT ( ref_no_free ),
|
.refcnt = REF_INIT ( ref_no_free ),
|
||||||
.builder = {
|
.builder = {
|
||||||
.data = private_key_data,
|
.data = private_key_data,
|
||||||
.len = ( ( size_t ) private_key_len ),
|
.len = ABS_VALUE_INIT ( private_key_len ),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#undef EMBED
|
#undef EMBED
|
||||||
#define EMBED( _index, _path, _name ) \
|
#define EMBED( _index, _path, _name ) \
|
||||||
extern char embedded_image_ ## _index ## _data[]; \
|
extern char embedded_image_ ## _index ## _data[]; \
|
||||||
extern char embedded_image_ ## _index ## _len[]; \
|
extern size_t ABS_SYMBOL ( embedded_image_ ## _index ## _len ); \
|
||||||
__asm__ ( ".section \".data\", \"aw\", " PROGBITS "\n\t" \
|
__asm__ ( ".section \".data\", \"aw\", " PROGBITS "\n\t" \
|
||||||
"\nembedded_image_" #_index "_data:\n\t" \
|
"\nembedded_image_" #_index "_data:\n\t" \
|
||||||
".incbin \"" _path "\"\n\t" \
|
".incbin \"" _path "\"\n\t" \
|
||||||
@@ -34,7 +34,7 @@ EMBED_ALL
|
|||||||
.name = _name, \
|
.name = _name, \
|
||||||
.flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
|
.flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
|
||||||
.rwdata = embedded_image_ ## _index ## _data, \
|
.rwdata = embedded_image_ ## _index ## _data, \
|
||||||
.len = ( size_t ) embedded_image_ ## _index ## _len, \
|
.len = ABS_VALUE_INIT ( embedded_image_ ## _index ## _len ), \
|
||||||
},
|
},
|
||||||
static struct image embedded_images[] = {
|
static struct image embedded_images[] = {
|
||||||
EMBED_ALL
|
EMBED_ALL
|
||||||
|
|||||||
@@ -662,6 +662,97 @@ char __debug_disable(OBJECT) = ( DBGLVL_MAX & ~DBGLVL_DFLT );
|
|||||||
#define ARRAY_SIZE(array) ( sizeof (array) / sizeof ( (array)[0] ) )
|
#define ARRAY_SIZE(array) ( sizeof (array) / sizeof ( (array)[0] ) )
|
||||||
#endif /* ASSEMBLY */
|
#endif /* ASSEMBLY */
|
||||||
|
|
||||||
|
/** @defgroup abs Absolute symbols
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#ifndef ASSEMBLY
|
||||||
|
|
||||||
|
/** Declare an absolute symbol (e.g. a value defined by a linker script)
|
||||||
|
*
|
||||||
|
* Use as e.g.:
|
||||||
|
*
|
||||||
|
* extern int ABS_SYMBOL ( _my_symbol );
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ABS_SYMBOL( name ) name[]
|
||||||
|
|
||||||
|
/** Get value of an absolute symbol for use in a static initializer
|
||||||
|
*
|
||||||
|
* Use as e.g.:
|
||||||
|
*
|
||||||
|
* extern int ABS_SYMBOL ( _my_symbol );
|
||||||
|
* static int my_symbol = ABS_VALUE_INIT ( _my_symbol );
|
||||||
|
*
|
||||||
|
* Note that the declared type must be at least as large as a pointer
|
||||||
|
* type, since the compiler sees the absolute symbol as being an
|
||||||
|
* address.
|
||||||
|
*/
|
||||||
|
#define ABS_VALUE_INIT( name ) ( ( typeof ( name[0] ) ) name )
|
||||||
|
|
||||||
|
/** Get value of an absolute symbol
|
||||||
|
*
|
||||||
|
* In a position-dependent executable, where all addresses are fixed
|
||||||
|
* at link time, we can use the standard technique as documented by
|
||||||
|
* GNU ld, e.g.:
|
||||||
|
*
|
||||||
|
* extern char _my_symbol[];
|
||||||
|
*
|
||||||
|
* printf ( "Absolute symbol value is %x\n", ( ( int ) _my_symbol ) );
|
||||||
|
*
|
||||||
|
* This technique may not work in a position-independent executable.
|
||||||
|
* When dynamic relocations are applied, the runtime addresses will no
|
||||||
|
* longer be equal to the link-time addresses. If the code to obtain
|
||||||
|
* the address of _my_symbol uses PC-relative addressing, then it
|
||||||
|
* will calculate the runtime "address" of the absolute symbol, which
|
||||||
|
* will no longer be equal the the link-time "address" (i.e. the
|
||||||
|
* correct value) of the absolute symbol.
|
||||||
|
*
|
||||||
|
* We can work around this by instead declaring a static variable to
|
||||||
|
* contain the absolute value, and returning the contents of this
|
||||||
|
* static variable:
|
||||||
|
*
|
||||||
|
* extern char _my_symbol[];
|
||||||
|
* static void * volatile my_symbol = _my_symbol;
|
||||||
|
*
|
||||||
|
* printf ( "Absolute symbol value is %x\n", ( ( int ) my_symbol ) );
|
||||||
|
*
|
||||||
|
* The value of the static variable cannot possibly use PC-relative
|
||||||
|
* addressing (since there is no applicable program counter for
|
||||||
|
* non-code), and so will instead be filled in with the correct
|
||||||
|
* absolute value at link time. (No dynamic relocation will be
|
||||||
|
* generated that might change its value, since the symbol providing
|
||||||
|
* the value is an absolute symbol.)
|
||||||
|
*
|
||||||
|
* This second technique will work for both position-dependent and
|
||||||
|
* position-independent code, but incurs the unnecssary overhead of an
|
||||||
|
* additional static variable in position-dependent code. The
|
||||||
|
* ABS_VALUE() macro abstracts away these differences, using the most
|
||||||
|
* efficient available technique. Use as e.g.:
|
||||||
|
*
|
||||||
|
* extern int ABS_SYMBOL ( _my_symbol );
|
||||||
|
* #define my_symbol ABS_VALUE ( _my_symbol )
|
||||||
|
*
|
||||||
|
* printf ( "Absolute symbol value is %x\n", my_symbol );
|
||||||
|
*
|
||||||
|
* The ABS_VALUE() macro uses the (otherwise redundant) type declared
|
||||||
|
* on the ABS_SYMBOL() array to automatically determine the correct
|
||||||
|
* type for the ABS_VALUE() expression.
|
||||||
|
*
|
||||||
|
* Unlike ABS_VALUE_INIT(), there is no restriction that the type must
|
||||||
|
* be at least as large as a pointer type.
|
||||||
|
*/
|
||||||
|
#ifndef __pie__
|
||||||
|
#define ABS_VALUE( name ) ( ( typeof ( name[0] ) ) ( intptr_t ) name )
|
||||||
|
#else
|
||||||
|
#define ABS_VALUE( name ) ( { \
|
||||||
|
static void * volatile static_ ## name = name; \
|
||||||
|
( ( typeof ( name[0] ) ) ( intptr_t ) static_ ## name ); \
|
||||||
|
} )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ASSEMBLY */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup licences Licence declarations
|
* @defgroup licences Licence declarations
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user