summaryrefslogtreecommitdiffstats
path: root/linkers
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2023-06-08 13:51:03 +1000
committerChris Johns <chrisj@rtems.org>2023-08-17 12:53:30 +1000
commitaba4d3b8daa9fbb63dff9e1f99fe76572186ef77 (patch)
tree1dc74b8d4032751f81e3c96294f574cd65de77be /linkers
parenttester: Use shorter SHA512 encoding (diff)
downloadrtems-tools-aba4d3b8daa9fbb63dff9e1f99fe76572186ef77.tar.bz2
linker: Add TLS support to the symbol table generator
Updates #4920
Diffstat (limited to 'linkers')
-rw-r--r--linkers/rtems-syms.cpp179
1 files changed, 134 insertions, 45 deletions
diff --git a/linkers/rtems-syms.cpp b/linkers/rtems-syms.cpp
index e5170e1..c72ee55 100644
--- a/linkers/rtems-syms.cpp
+++ b/linkers/rtems-syms.cpp
@@ -60,10 +60,22 @@ static const char* c_header[] =
" * Automatically generated. Do not edit..",
" */",
"",
+ "#include <stddef.h>",
+ "#include <stdint.h>",
+ "",
+ "extern void* rtems_rtl_tls_get_base (void);",
+ "",
"extern const unsigned char rtems__rtl_base_globals[];",
"extern const unsigned int rtems__rtl_base_globals_size[];",
"",
- "void rtems_rtl_base_sym_global_add (const unsigned char* , unsigned int );",
+ "typedef size_t (*rtems_rtl_tls_offset_func)(void);",
+ "typedef struct rtems_rtl_tls_offset {",
+ " size_t index;",
+ " rtems_rtl_tls_offset_func offset;",
+ "} rtems_rtl_tls_offset;",
+ "",
+ "void rtems_rtl_base_sym_global_add (const unsigned char* , unsigned int,",
+ " rtems_rtl_tls_offset*, size_t );",
"",
"asm(\".section \\\".rodata\\\"\");",
"",
@@ -78,35 +90,60 @@ static const char* c_header[] =
0
};
-static const char* c_trailer[] =
+static const char* c_sym_table_end[] =
{
"asm(\" .byte 0\");",
"asm(\" .ascii \\\"\\xde\\xad\\xbe\\xef\\\"\");",
-#if BROKEN_ON_SOME_ASSEMBLERS
- "asm(\" .type rtems__rtl_base_globals, #object\");",
- "asm(\" .size rtems__rtl_base_globals, . - rtems__rtl_base_globals\");",
-#endif
"",
+ 0
+};
+
+static const char* c_tls_call_table_start[] =
+{
+ "rtems_rtl_tls_offset rtems_rtl_tls_offsets[] = {",
+ 0
+};
+
+static const char* c_tls_call_table_end[] =
+{
+ "};",
+ "#define RTEMS_RTL_TLS_OFFSETS_NUM " \
+ "(sizeof(rtems_rtl_tls_offsets) / (sizeof(rtems_rtl_tls_offsets[0])))",
+ "",
+ 0
+};
+
+static const char* c_trailer[] =
+{
"/*",
" * Symbol table size.",
" */",
"asm(\" .align 4\");",
"asm(\" .local rtems__rtl_base_globals_size\");",
-#if BROKEN_ON_SOME_ASSEMBLERS
- "asm(\" .type rtems__rtl_base_globals_size, #object\");",
- "asm(\" .size rtems__rtl_base_globals_size, 4\");",
-#endif
"asm(\"rtems__rtl_base_globals_size:\");",
"asm(\" .long rtems__rtl_base_globals_size - rtems__rtl_base_globals\");",
"",
0
};
+static const char* c_rtl_call_body_embeded[] =
+{
+ "{",
+ " rtems_rtl_base_sym_global_add (&rtems__rtl_base_globals[0],",
+ " rtems__rtl_base_globals_size[0],",
+ " &rtems_rtl_tls_offsets[0],",
+ " RTEMS_RTL_TLS_OFFSETS_NUM);",
+ "}",
+ 0
+};
+
static const char* c_rtl_call_body[] =
{
"{",
" rtems_rtl_base_sym_global_add (&rtems__rtl_base_globals[0],",
- " rtems__rtl_base_globals_size[0]);",
+ " rtems__rtl_base_globals_size[0],",
+ " NULL",
+ " 0);",
"}",
0
};
@@ -140,7 +177,7 @@ c_embedded_trailer (rld::process::tempfile& c)
{
c.write_line ("void rtems_rtl_base_global_syms_init(void);");
c.write_line ("void rtems_rtl_base_global_syms_init(void)");
- temporary_file_paint (c, c_rtl_call_body);
+ temporary_file_paint (c, c_rtl_call_body_embeded);
}
/**
@@ -214,16 +251,27 @@ symbol_filter::filter (const rld::symbols::symtab& symbols,
struct output_sym
{
+ enum struct output_mode {
+ symbol,
+ tls_func,
+ tls_call_table
+ };
rld::process::tempfile& c;
const bool embed;
const bool weak;
-
- output_sym(rld::process::tempfile& c,
- bool embed,
- bool weak)
- : c (c),
- embed (embed),
- weak (weak) {
+ const output_mode mode;
+ size_t& index;
+
+ output_sym(rld::process::tempfile& c_,
+ bool embed_,
+ bool weak_,
+ output_mode mode_,
+ size_t& index_)
+ : c (c_),
+ embed (embed_),
+ weak (weak_),
+ mode (mode_),
+ index (index_) {
}
void operator ()(const rld::symbols::symtab::value_type& value);
@@ -240,34 +288,56 @@ output_sym::operator ()(const rld::symbols::symtab::value_type& value)
if (weak && sym.value () == 0)
return;
- c.write_line ("asm(\" .asciz \\\"" + sym.name () + "\\\"\");");
-
- if (sym.type() == STT_TLS)
- {
- c.write_line ("asm(\" .type \\\"" + sym.name () + "\\\", %tls_object\");");
- }
-
- if (embed)
- {
- c.write_line ("#if __SIZEOF_POINTER__ == 8");
- c.write_line ("asm(\" .quad " + sym.name () + "\");");
- c.write_line ("#else");
- c.write_line ("asm(\" .long " + sym.name () + "\");");
- c.write_line ("#endif");
- }
- else
- {
- std::stringstream oss;
- oss << std::hex << std::setfill ('0') << std::setw (8) << sym.value ();
- c.write_line ("#if __SIZEOF_POINTER__ == 8");
- c.write_line ("asm(\" .quad 0x" + oss.str () + "\");");
- c.write_line ("#else");
- c.write_line ("asm(\" .long 0x" + oss.str () + "\");");
- c.write_line ("#endif");
+ switch (mode) {
+ case output_mode::symbol:
+ default:
+ /*
+ * Set TLS value to 0. It is filled in at run time by the call
+ * table.
+ */
+ c.write_line ("asm(\" .asciz \\\"" + sym.name () + "\\\"\");");
+ {
+ std::string val;
+ if (sym.type () == STT_TLS) {
+ val = "0";
+ } else {
+ if (embed) {
+ val = sym.name ();
+ } else {
+ std::stringstream oss;
+ oss << std::hex << std::setfill ('0') << std::setw (8) << sym.value ();
+ val = oss.str ();
+ }
+ }
+ c.write_line ("#if __SIZEOF_POINTER__ == 8");
+ c.write_line ("asm(\" .quad " + val + "\");");
+ c.write_line ("#else");
+ c.write_line ("asm(\" .long " + val + "\");");
+ c.write_line ("#endif");
+ }
+ break;
+ case output_mode::tls_func:
+ if (sym.type () == STT_TLS) {
+ c.write_line ("#define RTEMS_TLS_INDEX_" + sym.name () + " " + std::to_string(index));
+ c.write_line ("static size_t rtems_rtl_tls_" + sym.name () + "(void) {");
+ c.write_line (" extern __thread void* " + sym.name () + ";");
+ c.write_line (" const void* tls_base = rtems_rtl_tls_get_base ();");
+ c.write_line (" const void* tls_addr = (void*) &" + sym.name () + ";");
+ c.write_line (" return tls_addr - tls_base;");
+ c.write_line ("}");
+ c.write_line ("");
+ }
+ break;
+ case output_mode::tls_call_table:
+ if (sym.type () == STT_TLS) {
+ c.write_line (" { RTEMS_TLS_INDEX_" + sym.name () +
+ ", rtems_rtl_tls_" + sym.name () + " },");
+ }
+ break;
}
+ ++index;
}
-
static void
generate_c (rld::process::tempfile& c,
rld::symbols::symtab& symbols,
@@ -281,9 +351,28 @@ generate_c (rld::process::tempfile& c,
* longer weak and should be consider a global symbol. You cannot link a
* global symbol with the same in a dynamically loaded module.
*/
+ size_t index = 0;
std::for_each (symbols.begin (),
symbols.end (),
- output_sym (c, embed, false));
+ output_sym (c, embed, false,
+ output_sym::output_mode::symbol, index));
+
+ temporary_file_paint (c, c_sym_table_end);
+
+ if (embed) {
+ index = 0;
+ std::for_each (symbols.begin (),
+ symbols.end (),
+ output_sym (c, embed, false,
+ output_sym::output_mode::tls_func, index));
+ temporary_file_paint (c, c_tls_call_table_start);
+ index = 0;
+ std::for_each (symbols.begin (),
+ symbols.end (),
+ output_sym (c, embed, false,
+ output_sym::output_mode::tls_call_table, index));
+ temporary_file_paint (c, c_tls_call_table_end);
+ }
temporary_file_paint (c, c_trailer);