# std.os.windows.tls: Set \`AddressOfCallBacks\` to \`&\_\_xl_a \+ 1\`\. · gitcafe/zig

[View on GitCafe](https://git.cafe/gitcafe/zig/commit/cb1fffb29eae6eafd46c87d3950911f496288ab2)

Repository: [gitcafe/zig](https://git.cafe/gitcafe/zig)

Visibility: public

Requested revision: cb1fffb29eae6eafd46c87d3950911f496288ab2

Requested commit: cb1fffb29eae6eafd46c87d3950911f496288ab2

Commit: cb1fffb29eae6eafd46c87d3950911f496288ab2

Tree: 5ccef985fde813ba6d5380107e67e68365132b7e

Author: Alex Rønne Petersen

Committer: Alex Rønne Petersen

## Message

```
std.os.windows.tls: Set `AddressOfCallBacks` to `&__xl_a + 1`.

`__xl_a` is just a global variable containing a null function pointer. There's
nothing magical about it or its name at all.

The section names used on `__xl_a` and `__xl_b` (`.CRT$XLA` and `.CRT$XLZ`) are
the real magic here. The compiler emits TLS variables into `.CRT$XL<x>`
sections, where `x` is an uppercase letter between A and Z (exclusive). The
linker then sorts those sections alphabetically (due to the `$`), and the result
is a neat array of TLS initialization callbacks between `__xl_a` and `__xl_z`.

That array is null-terminated, though! Normally, `__xl_z` serves as the null
terminator; however, by pointing `AddressesOfCallBacks` to `__xl_a`, which just
contains a null function pointer, we've effectively made it so that the PE
loader will just immediately stop invoking TLS callbacks. Fix that by pointing
to the first actual TLS callback instead (or `__xl_z` if there are none).

```

## Parents

- [1d8fca0060ecfe700df7722e6763de94e2bd0b51](https://git.cafe/gitcafe/zig/commit/1d8fca0060ecfe700df7722e6763de94e2bd0b51?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zig/tree/cb1fffb29eae6eafd46c87d3950911f496288ab2?format=markdown)
