}
tlsg = linklookup(ctxt, "runtime.tlsg", 0);
- tlsg->type = STLSBSS;
+ // For most ports, runtime.tlsg is a placeholder symbol for TLS
+ // relocation. However, the Android and Darwin ports need it to
+ // be a real variable. Instead of hard-coding which platforms
+ // need it to be a real variable, we set the type to STLSBSS only
+ // when the runtime has not declared its type already.
+ if(tlsg->type == 0)
+ tlsg->type = STLSBSS;
tlsg->size = PtrSize;
tlsg->hide = 1;
tlsg->reachable = 1;
// runtime.tlsg is special.
// Its "address" is the offset from the TLS thread pointer
// to the thread-local g and m pointers.
- // Emit a TLS relocation instead of a standard one.
- if(rel->sym == ctxt->tlsg) {
+ // Emit a TLS relocation instead of a standard one if it's
+ // typed STLSBSS.
+ if(rel->sym == ctxt->tlsg && ctxt->tlsg->type == STLSBSS) {
rel->type = R_TLS;
if(ctxt->flag_shared)
rel->add += ctxt->pc - p->pcrel->pc - 8 - rel->siz;
// On android, runtime.tlsg is a normal variable.
// TLS offset is computed in x_cgo_inittls.
+#ifdef GOOS_android
+#define TLSG_IS_VARIABLE
+#endif
// save_g saves the g register into pthread-provided
// thread-local memory, so that we can call externally compiled
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
// thread-local storage for g.
-#ifdef GOOS_android
+#ifdef TLSG_IS_VARIABLE
MOVW runtime·tlsg(SB), R11
#else
MOVW $runtime·tlsg(SB), R11
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
// thread-local storage for g.
-#ifdef GOOS_android
+#ifdef TLSG_IS_VARIABLE
MOVW runtime·tlsg(SB), R11
#else
MOVW $runtime·tlsg(SB), R11
ADD R11, R0
MOVW 0(R0), g
RET
+
+#ifdef TLSG_IS_VARIABLE
+GLOBL runtime·tlsg+0(SB), NOPTR, $4
+#endif