Newer
Older
minerva / Userland / Libraries / LibELF / Arch / aarch64 / tls.h
@minerva minerva on 13 Jul 1 KB Initial commit
/*
 * Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
 *
 * 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);
}

}