2 * Written in the D programming language.
3 * This module provides bionic-specific support for sections.
5 * Copyright: Copyright Martin Nowak 2012-2013.
6 * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
7 * Authors: Martin Nowak
8 * Source: $(DRUNTIMESRC src/rt/_sections_android.d)
11 module rt.sections_android;
13 version (CRuntime_Bionic):
16 debug(PRINTF) import core.stdc.stdio;
17 import core.stdc.stdlib : malloc, free;
18 import rt.deh, rt.minfo;
19 import core.sys.posix.pthread;
20 import core.stdc.stdlib : calloc;
21 import core.stdc.string : memcpy;
25 static int opApply(scope int delegate(ref SectionGroup) dg)
30 static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
35 @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
37 return _moduleGroup.modules;
40 @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
45 @property immutable(FuncTable)[] ehTables() const nothrow @nogc
47 auto pbeg = cast(immutable(FuncTable)*)&__start_deh;
48 auto pend = cast(immutable(FuncTable)*)&__stop_deh;
49 return pbeg[0 .. pend - pbeg];
52 @property inout(void[])[] gcRanges() inout nothrow @nogc
58 ModuleGroup _moduleGroup;
62 void initSections() nothrow @nogc
64 pthread_key_create(&_tlsKey, null);
66 auto mbeg = cast(immutable ModuleInfo**)&__start_minfo;
67 auto mend = cast(immutable ModuleInfo**)&__stop_minfo;
68 _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]);
70 auto pbeg = cast(void*)&_tlsend;
71 auto pend = cast(void*)&__bss_end__;
72 _sections._gcRanges[0] = pbeg[0 .. pend - pbeg];
75 void finiSections() nothrow @nogc
77 pthread_key_delete(_tlsKey);
80 void[]* initTLSRanges() nothrow @nogc
82 return &getTLSBlock();
85 void finiTLSRanges(void[]* rng) nothrow @nogc
91 void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
93 dg(rng.ptr, rng.ptr + rng.length);
96 /* NOTE: The Bionic C library ignores thread-local data stored in the normal
97 * .tbss/.tdata ELF sections, which are marked with the SHF_TLS/STT_TLS
98 * flags. So instead we roll our own by keeping TLS data in the
99 * .tdata/.tbss sections but removing the SHF_TLS/STT_TLS flags, and
100 * access the TLS data using this function and the _tlsstart/_tlsend
101 * symbols as delimiters.
103 * This function is called by the code emitted by the compiler. It
104 * is expected to translate an address in the TLS static data to
105 * the corresponding address in the TLS dynamic per-thread data.
110 // NB: the compiler mangles this function as '___tls_get_addr'
111 // even though it is extern(D)
112 extern(D) void* ___tls_get_addr( void* p ) nothrow @nogc
114 debug(PRINTF) printf(" ___tls_get_addr input - %p\n", p);
115 immutable offset = cast(size_t)(p - cast(void*)&_tlsstart);
116 auto tls = getTLSBlockAlloc();
117 assert(offset < tls.length);
118 return tls.ptr + offset;
123 extern(C) void* __tls_get_addr( void** p ) nothrow @nogc
125 debug(PRINTF) printf(" __tls_get_addr input - %p\n", *p);
126 immutable offset = cast(size_t)(*p - cast(void*)&_tlsstart);
127 auto tls = getTLSBlockAlloc();
128 assert(offset < tls.length);
129 return tls.ptr + offset;
133 static assert( false, "Android architecture not supported." );
137 __gshared pthread_key_t _tlsKey;
139 ref void[] getTLSBlock() nothrow @nogc
141 auto pary = cast(void[]*)pthread_getspecific(_tlsKey);
144 pary = cast(void[]*).calloc(1, (void[]).sizeof);
145 if (pthread_setspecific(_tlsKey, pary) != 0)
147 import core.stdc.stdio;
148 perror("pthread_setspecific failed with");
155 ref void[] getTLSBlockAlloc() nothrow @nogc
157 auto pary = &getTLSBlock();
160 auto pbeg = cast(void*)&_tlsstart;
161 auto pend = cast(void*)&_tlsend;
162 auto p = .malloc(pend - pbeg);
163 memcpy(p, pbeg, pend - pbeg);
164 *pary = p[0 .. pend - pbeg];
169 __gshared SectionGroup _sections;
173 /* Symbols created by the compiler/linker and inserted into the
174 * object file that 'bracket' sections.