summaryrefslogtreecommitdiffstats
path: root/src/build/linker/linker.C
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2015-11-23 17:20:35 -0600
committerPatrick Williams <iawillia@us.ibm.com>2015-12-11 15:30:27 -0600
commit105660534e02cb3223dcba7d4f7d6a1ad0433317 (patch)
tree5714c489f496f1ec9067c636ce4efd1d1638dd1e /src/build/linker/linker.C
parent697c2f5339b9419fadfdc4d2bd09a985ef7a4e9f (diff)
downloadtalos-hostboot-105660534e02cb3223dcba7d4f7d6a1ad0433317.tar.gz
talos-hostboot-105660534e02cb3223dcba7d4f7d6a1ad0433317.zip
Linker support for thread-local storage
RTC: 124148 Change-Id: I6f9b1a654c5a19bb0a27ecb6179af27f2b783671 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22312 Tested-by: Jenkins Server Reviewed-by: Richard J. Knight <rjknight@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/build/linker/linker.C')
-rw-r--r--src/build/linker/linker.C61
1 files changed, 56 insertions, 5 deletions
diff --git a/src/build/linker/linker.C b/src/build/linker/linker.C
index af5b7c543..167da1858 100644
--- a/src/build/linker/linker.C
+++ b/src/build/linker/linker.C
@@ -95,6 +95,9 @@ struct Symbol
VARIABLE = 0x10,
RELATIVE = 0x20,
+
+ TLS_MODULE = 0x40,
+ TLS_OFFSET = 0x80,
};
};
@@ -126,7 +129,8 @@ struct Object
unsigned long offset; //!< output file offset of image start
unsigned long base_addr; //!< output file base address
FILE * iv_output; //!< output file handle
-
+ ssize_t tls_module; //!< module id of this module's
+ // thread local storage.
/**
* Read the object from it's file and extract bfd, text, & data image
* @param[in] i_file : file path
@@ -187,10 +191,15 @@ struct Object
uint64_t find_fini_symbol();
/**
+ * Get the TLS ID of this module.
+ */
+ size_t get_tls_module();
+
+ /**
* CTOR default
*/
Object() : image(NULL), offset(0), base_addr(0), iv_output(NULL),
- text(), rodata(), data() {}
+ text(), rodata(), data(), tls_module(-1) {}
/**
* CTOR
@@ -199,7 +208,7 @@ struct Object
*/
Object(unsigned long i_baseAddr, FILE* i_out)
: image(NULL), offset(0), base_addr(i_baseAddr), iv_output(i_out),
- text(), rodata(), data() {}
+ text(), rodata(), data(), tls_module(-1) {}
};
inline bool Object::isELF()
@@ -280,6 +289,8 @@ set<string> all_symbols;
set<string> weak_symbols_to_check;
bool includes_extended_image = false;
+size_t next_tls_id = 0;
+
//-----------------------------------------------------------------------------
// MAIN
//-----------------------------------------------------------------------------
@@ -757,6 +768,14 @@ bool Object::read_relocation()
{
s.type |= Symbol::FUNCTION;
}
+ else if (loc[i]->howto->name == string("R_PPC64_DTPMOD64"))
+ {
+ s.type |= Symbol::TLS_MODULE;
+ }
+ else if (loc[i]->howto->name == string("R_PPC64_DTPREL64"))
+ {
+ s.type |= Symbol::TLS_OFFSET;
+ }
this->relocs.push_back(s);
cout << "\tSymbol: " << loc[i]->sym_ptr_ptr[0]->name;
@@ -792,6 +811,8 @@ bool Object::perform_local_relocations()
uint64_t address = 0;
char data[sizeof(uint64_t)];
+ bool needs_relocation = true;
+
fseek(iv_output, offset + i->address, SEEK_SET);
fread(data, sizeof(uint64_t), 1, iv_output);
@@ -814,9 +835,29 @@ bool Object::perform_local_relocations()
relocation += symbol_addr;
}
- address = relocation + base_addr; //dgxxa
+ if (i->type & Symbol::TLS_MODULE)
+ {
+ // Set value to TLS module.
+ address = get_tls_module();
+ needs_relocation = false;
+ relocation = address;
+ }
+ else if (i->type & Symbol::TLS_OFFSET)
+ {
+ // Set value to TLS offset.
+ address = i->addend;
+ needs_relocation = false;
+ relocation = address;
+ }
+ else // Perform relocation.
+ {
+ address = relocation + base_addr; //dgxxa
+ }
bfd_putb64(address, data);
- if(!base_addr) all_relocations.push_back(offset + i->address);
+ if((!base_addr) && (needs_relocation))
+ {
+ all_relocations.push_back(offset + i->address);
+ }
fseek(iv_output, offset + i->address, SEEK_SET);
fwrite(data, sizeof(uint64_t), 1, iv_output);
@@ -969,6 +1010,16 @@ uint64_t Object::find_fini_symbol()
offset + base_addr + rodata.vma_offset;
}
+//-----------------------------------------------------------------------------
+
+size_t Object::get_tls_module()
+{
+ if (tls_module < 0)
+ tls_module = next_tls_id++;
+
+ return tls_module;
+}
+
//-----------------------------------------------------------------------------
OpenPOWER on IntegriCloud