RTS Linker does not handle initialization of cyclic objects correctly
While working on #21068 (closed) I stumbled across a subtle bug in the RTS linker's current treatment of initializers. Specifically, we currently mark a loaded object's text as executable (e.g. by flushing its m32 allocator) in ocTryLoad
, which is the same function which is responsible for running initializers. This can be problematic in the case where we have a situation where a static library contains a set of recursive objects:
- object
A
has depends upon symbols in objectB
- object
B
has an initializer that depends upon objectA
- we try to load object
A
The linker will:
- start resolving object
A
- encounter the reference to object
B
, loading it - resolve object
B
- run object
B
's initializer - the initializer will attempt to call into object
A
, which hasn't been fully resolved (and therefore protected)
This situation results from the handling of C stubs described in !7528 (closed). The solution here is to introduce a new phase of linking, "initialization", after resolution.