1
1
mirror of https://github.com/rui314/mold.git synced 2024-10-04 08:37:28 +03:00

[ELF] Handle TLS common symbols

Fixes https://github.com/rui314/mold/issues/447
This commit is contained in:
Rui Ueyama 2022-04-21 13:44:12 +08:00
parent ec062f7241
commit cf850f8993
2 changed files with 47 additions and 5 deletions

View File

@ -1060,10 +1060,14 @@ void ObjectFile<E>::convert_common_symbols(Context<E> &ctx) {
if (!has_common_symbol)
return;
OutputSection<E> *osec =
OutputSection<E> *common =
OutputSection<E>::get_instance(ctx, ".common", SHT_NOBITS,
SHF_WRITE | SHF_ALLOC);
OutputSection<E> *tls_common =
OutputSection<E>::get_instance(ctx, ".tls_common", SHT_NOBITS,
SHF_WRITE | SHF_ALLOC | SHF_TLS);
for (i64 i = this->first_global; i < this->elf_syms.size(); i++) {
if (!this->elf_syms[i].is_common())
continue;
@ -1079,17 +1083,20 @@ void ObjectFile<E>::convert_common_symbols(Context<E> &ctx) {
elf_sections2.push_back({});
ElfShdr<E> &shdr = elf_sections2.back();
memset(&shdr, 0, sizeof(shdr));
shdr.sh_flags = SHF_ALLOC;
bool is_tls = (sym.get_type() == STT_TLS);
shdr.sh_flags = is_tls ? (SHF_ALLOC | SHF_TLS) : SHF_ALLOC;
shdr.sh_type = SHT_NOBITS;
shdr.sh_size = this->elf_syms[i].st_size;
shdr.sh_addralign = this->elf_syms[i].st_value;
i64 idx = this->elf_sections.size() + elf_sections2.size() - 1;
std::unique_ptr<InputSection<E>> isec =
std::make_unique<InputSection<E>>(ctx, *this, ".common", idx);
isec->output_section = osec;
std::make_unique<InputSection<E>>(ctx, *this,
is_tls ? ".tls_common" : ".common",
idx);
isec->output_section = is_tls ? tls_common : common;
sym.file = this;
sym.shndx = idx;

35
test/elf/tls-common.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/bash
export LC_ALL=C
set -e
CC="${CC:-cc}"
CXX="${CXX:-c++}"
GCC="${GCC:-gcc}"
GXX="${GXX:-g++}"
OBJDUMP="${OBJDUMP:-objdump}"
MACHINE="${MACHINE:-$(uname -m)}"
testname=$(basename "$0" .sh)
echo -n "Testing $testname ... "
cd "$(dirname "$0")"/../..
mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t
cat <<EOF | $GCC -o $t/a.o -c -xassembler -
.globl foo
.tls_common foo,4,4
EOF
cat <<EOF | $CC -o $t/b.o -c -xc -std=c11 -
#include <stdio.h>
extern _Thread_local int foo;
int main() {
printf("foo=%d\n", foo);
}
EOF
$CC -B. -o $t/exe $t/a.o $t/b.o
$QEMU $t/exe | grep -q '^foo=0$'
echo OK