forked from LadybirdBrowser/ladybird
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LibELF: Add headers describing the TLS layout of each architecture
All of our architectures sadly use a slightly different TLS layout. These headers try to abstract the differences in a nice way.
- Loading branch information
Showing
4 changed files
with
202 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Copyright (c) 2024, Sönke Holz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <AK/BitCast.h> | ||
#include <AK/StdLibExtraDetails.h> | ||
#include <AK/Types.h> | ||
|
||
namespace ELF { | ||
|
||
struct ThreadControlBlock { | ||
// Variant I of the ELF TLS data structures requires that the TCB has to contain a pointer to the dtv at offset 0. | ||
// This member is unused, as we currently only support static TLS blocks. | ||
void* dynamic_thread_vector; | ||
|
||
FlatPtr padding; | ||
}; | ||
|
||
// The TCB needs to have a size of 2 * sizeof(FlatPtr) on AArch64. | ||
static_assert(AssertSize<ThreadControlBlock, 2 * sizeof(FlatPtr)>()); | ||
|
||
static constexpr size_t TLS_VARIANT = 1; | ||
static constexpr size_t TLS_DTV_OFFSET = 0; | ||
static constexpr size_t TLS_TP_STATIC_TLS_BLOCK_OFFSET = sizeof(ThreadControlBlock); | ||
|
||
// AArch64 ELF TLS Layout | ||
// | ||
// [TCB][static TLS.....] | ||
// ^tp (tpidr_el0) | ||
|
||
inline size_t calculate_static_tls_region_size(size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_alignment; | ||
return sizeof(ThreadControlBlock) + tls_template_size; | ||
} | ||
|
||
inline FlatPtr calculate_tp_value_from_static_tls_region_address(FlatPtr static_tls_region_address, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_template_size; | ||
(void)tls_alignment; | ||
return static_tls_region_address; | ||
} | ||
|
||
inline ThreadControlBlock* get_tcb_pointer_from_thread_pointer(FlatPtr thread_pointer) | ||
{ | ||
return bit_cast<ThreadControlBlock*>(thread_pointer); | ||
} | ||
|
||
inline void* get_pointer_to_first_static_tls_block_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_template_size; | ||
(void)tls_alignment; | ||
return bit_cast<void*>(thread_pointer + sizeof(ThreadControlBlock)); | ||
} | ||
|
||
inline void* get_pointer_to_static_tls_region_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_template_size; | ||
(void)tls_alignment; | ||
return bit_cast<void*>(thread_pointer); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright (c) 2024, Sönke Holz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <AK/BitCast.h> | ||
#include <AK/Types.h> | ||
|
||
namespace ELF { | ||
|
||
struct ThreadControlBlock { | ||
// NOTE: "ELF Handling For Thread-Local Storage" says that when using variant I of the data structures (which RISC-V does), | ||
// the TCB has to have a pointer to the dtv at offset 0. | ||
// However, that document also says that the thread pointer has to point to the TCB. | ||
// It's probably still a good idea to put the dtv pointer at offset 0. | ||
// This member is unused, as we currently only support static TLS blocks. | ||
void* dynamic_thread_vector; | ||
}; | ||
|
||
static constexpr size_t TLS_VARIANT = 1; | ||
static constexpr size_t TLS_DTV_OFFSET = 0x800; | ||
static constexpr size_t TLS_TP_STATIC_TLS_BLOCK_OFFSET = 0; | ||
|
||
// RISC-V ELF TLS Layout | ||
// The padding is needed so tp is correctly aligned. | ||
// | ||
// [..padding..][TCB][static TLS.....] | ||
// ^tp | ||
|
||
inline size_t calculate_static_tls_region_size(size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
return align_up_to(sizeof(ThreadControlBlock), tls_alignment) + tls_template_size; | ||
} | ||
|
||
inline FlatPtr calculate_tp_value_from_static_tls_region_address(FlatPtr static_tls_region_address, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_template_size; | ||
return static_tls_region_address + align_up_to(sizeof(ThreadControlBlock), tls_alignment); | ||
} | ||
|
||
inline ThreadControlBlock* get_tcb_pointer_from_thread_pointer(FlatPtr thread_pointer) | ||
{ | ||
return bit_cast<ThreadControlBlock*>(thread_pointer - sizeof(ThreadControlBlock)); | ||
} | ||
|
||
inline void* get_pointer_to_first_static_tls_block_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_template_size; | ||
(void)tls_alignment; | ||
return bit_cast<void*>(thread_pointer); | ||
} | ||
|
||
inline void* get_pointer_to_static_tls_region_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
(void)tls_template_size; | ||
return bit_cast<void*>(thread_pointer - align_up_to(sizeof(ThreadControlBlock), tls_alignment)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright (c) 2024, Sönke Holz <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <AK/BitCast.h> | ||
#include <AK/Types.h> | ||
|
||
namespace ELF { | ||
|
||
struct ThreadControlBlock { | ||
// The %fs segment register is the thread pointer register on x86-64. | ||
// x86-64 uses variant II of the TLS data structures described in "ELF Handling For Thread-Local Storage", | ||
// which requires the thread pointer to point to the TCB. | ||
// That document also requires that the pointer shall be accessible with "movq %fs:0, %<reg>", | ||
// so the first member in the TCB has to be a copy of the thread pointer. | ||
void* thread_pointer; | ||
|
||
// Variant II requires that the TCB has to contain a pointer to the dtv at an unspecified offset. | ||
// This member is unused, as we currently only support static TLS blocks. | ||
void* dynamic_thread_vector; | ||
}; | ||
|
||
static constexpr size_t TLS_VARIANT = 2; | ||
static constexpr size_t TLS_DTV_OFFSET = 0; | ||
static constexpr size_t TLS_TP_STATIC_TLS_BLOCK_OFFSET = 0; | ||
|
||
// x86-64 ELF TLS Layout | ||
// The padding is needed so tp (fs_base) is correctly aligned. | ||
// | ||
// [.....static TLS][..padding..][TCB] | ||
// ^tp (fs_base) | ||
|
||
inline size_t calculate_static_tls_region_size(size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
return align_up_to(tls_template_size, tls_alignment) + sizeof(ThreadControlBlock); | ||
} | ||
|
||
inline FlatPtr calculate_tp_value_from_static_tls_region_address(FlatPtr static_tls_region_address, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
return static_tls_region_address + align_up_to(tls_template_size, tls_alignment); | ||
} | ||
|
||
inline ThreadControlBlock* get_tcb_pointer_from_thread_pointer(FlatPtr thread_pointer) | ||
{ | ||
return bit_cast<ThreadControlBlock*>(thread_pointer); | ||
} | ||
|
||
inline void* get_pointer_to_first_static_tls_block_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
return bit_cast<void*>(thread_pointer - align_up_to(tls_template_size, tls_alignment)); | ||
} | ||
|
||
inline void* get_pointer_to_static_tls_region_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment) | ||
{ | ||
return bit_cast<void*>(thread_pointer - align_up_to(tls_template_size, tls_alignment)); | ||
} | ||
|
||
} |