s390x: Implement tls_value (#4616)
Implement the tls_value for s390 in the ELF general-dynamic mode. Notable differences to the x86_64 implementation are: - We use a __tls_get_offset libcall instead of __tls_get_addr. - The current thread pointer (stored in a pair of access registers) needs to be added to the result of __tls_get_offset. - __tls_get_offset has a variant ABI that requires the address of the GOT (global offset table) is passed in %r12. This means we need a new libcall entries for __tls_get_offset. In addition, we also need a way to access _GLOBAL_OFFSET_TABLE_. The latter is a "magic" symbol with a well-known name defined by the ABI and recognized by the linker. This patch introduces a new ExternalName::KnownSymbol variant to support such names (originally due to @afonso360). We also need to emit a relocation on a symbol placed in a constant pool, as well as an extra relocation on the call to __tls_get_offset required for TLS linker optimization. Needed by the cg_clif frontend.
This commit is contained in:
@@ -121,6 +121,7 @@ pub struct ObjectModule {
|
||||
relocs: Vec<SymbolRelocs>,
|
||||
libcalls: HashMap<ir::LibCall, SymbolId>,
|
||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
||||
known_symbols: HashMap<ir::KnownSymbol, SymbolId>,
|
||||
function_alignment: u64,
|
||||
per_function_section: bool,
|
||||
anon_func_number: u64,
|
||||
@@ -141,6 +142,7 @@ impl ObjectModule {
|
||||
relocs: Vec::new(),
|
||||
libcalls: HashMap::new(),
|
||||
libcall_names: builder.libcall_names,
|
||||
known_symbols: HashMap::new(),
|
||||
function_alignment: builder.function_alignment,
|
||||
per_function_section: builder.per_function_section,
|
||||
anon_func_number: 0,
|
||||
@@ -547,6 +549,28 @@ impl ObjectModule {
|
||||
symbol
|
||||
}
|
||||
}
|
||||
// These are "magic" names well-known to the linker.
|
||||
// They require special treatment.
|
||||
ir::ExternalName::KnownSymbol(ref known_symbol) => {
|
||||
if let Some(symbol) = self.known_symbols.get(known_symbol) {
|
||||
*symbol
|
||||
} else {
|
||||
let symbol = match known_symbol {
|
||||
ir::KnownSymbol::ElfGlobalOffsetTable => self.object.add_symbol(Symbol {
|
||||
name: "_GLOBAL_OFFSET_TABLE_".as_bytes().to_vec(),
|
||||
value: 0,
|
||||
size: 0,
|
||||
kind: SymbolKind::Data,
|
||||
scope: SymbolScope::Unknown,
|
||||
weak: false,
|
||||
section: SymbolSection::Undefined,
|
||||
flags: SymbolFlags::None,
|
||||
}),
|
||||
};
|
||||
self.known_symbols.insert(*known_symbol, symbol);
|
||||
symbol
|
||||
}
|
||||
}
|
||||
_ => panic!("invalid ExternalName {}", name),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user