llvm / llvm/llvm-project

[ORC] Convenience support for COFF external calls and `__imp_` (dllimport) symbols.

Open
#190,122 6 comments 0 reactions 0 assignees View on GitHub
jitlink
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

For calls to external symbols JITLink usually auto-creates a Global Offset Table (GOT) entry and Procedure Linkage Table (PLT) stub. The GOT entry holds the address of the external, and the PLT stub is an indirect branch that uses the address stored in the GOT entry.

My understanding (COFF experts, come at me!) is that in COFF things are more complicated. External references may be annotated with `dllimport` (permitting some compiler optimizations for external references), and stubs would typically be provided by an import library.

Consider the following example:

```c
void foo(void);
__declspec(dllimport) void bar(void);

void ex(void) {
foo();
bar();
}
```
When compiled with `clang --target=x86_64-pc-windows -S -o - ex.c` this generates:
```asm
ex:
...
callq foo
callq *__imp_bar(%rip) ; access via __imp_ allowed, as declared dllimport
```

Assume that `foo` and `bar` are provided by two different DLLs (`foo.dll` and `bar.dll` respectively). Each of these DLLs will have a corresponding import library (`foo.lib` and `bar.lib`) that define an `__imp_` symbol (containing the address of the _real_ definition), and a thunk symbol with the original name that just branches indirectly through the `__imp_` symbol. E.g. `foo.lib` will contain definitions equivalent to:
```asm
__imp_foo:
.quad


...
foo: ; foo thunk
jmpq *__imp_foo(%rip)
```

All of this leaves us with a challenge for JITlink. Normally we'd try to match the native linking model, and in that case we should insist that COFF JITs supply import libraries for all external symbols that they want to call. We want to _support_ this mode, because one of the goals of ORC is to _fail to link whenever the corresponding static program would have failed to link_.

On the other hand it's common for LLVM JIT users to want to be able to call functions in the host executable (an import library would _not_ usually be produced for this, I guess), and plenty of JIT clients are "JIT only" and won't want to deal with the headache of building import libraries for purely JIT use cases.

So: We should probably provide a magical "import symbol generator" plugin that synthesizes `__imp_` symbols and thunks on demand (basically the same way the GOT/PLT support works for ELF and MachO today). The big questions are (1) should this be on-by-default, and (2) how can clients toggle it on/off? (see https://github.com/llvm/llvm-project/issues/190121).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.