blob: 2d2cbe305b017a7866ce3cd222bb1e0aa00183e0 [file] [log] [blame]
Ryan Prichard45d13492019-01-03 02:51:30 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "private/bionic_elf_tls.h"
30
Ryan Prichard48097552019-01-06 18:24:10 -080031#include <async_safe/log.h>
Ryan Prichard45d13492019-01-03 02:51:30 -080032#include <sys/param.h>
Ryan Prichard48097552019-01-06 18:24:10 -080033#include <unistd.h>
Ryan Prichard45d13492019-01-03 02:51:30 -080034
35#include "private/bionic_macros.h"
36#include "private/bionic_tls.h"
37
Ryan Prichard48097552019-01-06 18:24:10 -080038// Search for a TLS segment in the given phdr table. Returns true if it has a
39// TLS segment and false otherwise.
40bool __bionic_get_tls_segment(const ElfW(Phdr)* phdr_table, size_t phdr_count,
41 ElfW(Addr) load_bias, const char* mod_name,
42 TlsSegment* out) {
43 for (size_t i = 0; i < phdr_count; ++i) {
44 const ElfW(Phdr)& phdr = phdr_table[i];
45 if (phdr.p_type == PT_TLS) {
46 // N.B. The size does not need to be a multiple of the alignment. With
47 // ld.bfd (or after using binutils' strip), the TLS segment's size isn't
48 // rounded up.
49 size_t alignment = phdr.p_align;
50 if (alignment == 0 || !powerof2(alignment)) {
51 async_safe_fatal("error: \"%s\": TLS segment alignment is not a power of 2: %zu",
52 mod_name, alignment);
53 }
54 // Bionic only respects TLS alignment up to one page.
55 alignment = MIN(alignment, PAGE_SIZE);
56 *out = TlsSegment {
57 phdr.p_memsz,
58 alignment,
59 reinterpret_cast<void*>(load_bias + phdr.p_vaddr),
60 phdr.p_filesz,
61 };
62 return true;
63 }
64 }
65 return false;
66}
67
Ryan Prichard45d13492019-01-03 02:51:30 -080068void StaticTlsLayout::reserve_tcb() {
69 offset_bionic_tcb_ = reserve_type<bionic_tcb>();
70}
71
72void StaticTlsLayout::reserve_bionic_tls() {
73 offset_bionic_tls_ = reserve_type<bionic_tls>();
74}
75
76void StaticTlsLayout::finish_layout() {
77 // Round the offset up to the alignment.
78 offset_ = round_up_with_overflow_check(offset_, alignment_);
79}
80
81// The size is not required to be a multiple of the alignment. The alignment
82// must be a positive power-of-two.
83size_t StaticTlsLayout::reserve(size_t size, size_t alignment) {
84 offset_ = round_up_with_overflow_check(offset_, alignment);
85 const size_t result = offset_;
86 if (__builtin_add_overflow(offset_, size, &offset_)) overflowed_ = true;
87 alignment_ = MAX(alignment_, alignment);
88 return result;
89}
90
91size_t StaticTlsLayout::round_up_with_overflow_check(size_t value, size_t alignment) {
92 const size_t old_value = value;
93 value = __BIONIC_ALIGN(value, alignment);
94 if (value < old_value) overflowed_ = true;
95 return value;
96}