#define sipi __use_text16 ( sipi )
/** 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 */
extern uint16_t __text16 ( sipi_ds );
/* The linker defines these symbols for us */
extern char _textdata[];
extern char _etextdata[];
-extern char _text16_memsz[];
-#define _text16_memsz ( ( size_t ) _text16_memsz )
-extern char _data16_memsz[];
-#define _data16_memsz ( ( size_t ) _data16_memsz )
+extern size_t ABS_SYMBOL ( _text16_memsz );
+#define _text16_memsz ABS_VALUE ( _text16_memsz )
+extern size_t ABS_SYMBOL ( _data16_memsz );
+#define _data16_memsz ABS_VALUE ( _data16_memsz )
/**
* Hide region of memory from system memory map
static int int_1a_hooked = 0;
/** Real-mode code segment size */
-extern char _text16_memsz[];
-#define _text16_memsz ( ( size_t ) _text16_memsz )
+extern size_t ABS_SYMBOL ( _text16_memsz );
+#define _text16_memsz ABS_VALUE ( _text16_memsz )
/** Real-mode data segment size */
-extern char _data16_memsz[];
-#define _data16_memsz ( ( size_t ) _data16_memsz )
+extern size_t ABS_SYMBOL (_data16_memsz );
+#define _data16_memsz ABS_VALUE ( _data16_memsz )
/** PXENV_UNDI_TRANSMIT API call profiler */
static struct profiler pxe_api_tx_profiler __profiler =
memcpy ( &sipi_regs, regs, sizeof ( sipi_regs ) );
/* 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 );
FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
/** Build timestamp (generated by linker) */
-extern char _build_timestamp[];
+extern unsigned long ABS_SYMBOL ( _build_timestamp );
/** Build ID (generated by linker) */
-extern char _build_id[];
+extern unsigned long ABS_SYMBOL ( _build_id );
/** Build timestamp */
-unsigned long build_timestamp = ( ( unsigned long ) _build_timestamp );
+unsigned long build_timestamp = ABS_VALUE_INIT ( _build_timestamp );
/** Build ID */
-unsigned long build_id = ( ( unsigned long ) _build_id );
+unsigned long build_id = ABS_VALUE_INIT ( _build_id );
/** Product major version */
const int product_major_version = VERSION_MAJOR;
#undef CERT
#define CERT( _index, _path ) \
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" \
"\nstored_cert_" #_index "_data:\n\t" \
".incbin \"" _path "\"\n\t" \
#undef CERT
#define CERT( _index, _path ) { \
.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[] = {
CERT_ALL
/* Raw 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"
"\nprivate_key_data:\n\t"
#ifdef PRIVATE_KEY
.refcnt = REF_INIT ( ref_no_free ),
.builder = {
.data = private_key_data,
- .len = ( ( size_t ) private_key_len ),
+ .len = ABS_VALUE_INIT ( private_key_len ),
},
};
#undef EMBED
#define EMBED( _index, _path, _name ) \
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" \
"\nembedded_image_" #_index "_data:\n\t" \
".incbin \"" _path "\"\n\t" \
.name = _name, \
.flags = ( IMAGE_STATIC | IMAGE_STATIC_NAME ), \
.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[] = {
EMBED_ALL
#define ARRAY_SIZE(array) ( sizeof (array) / sizeof ( (array)[0] ) )
#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
*