ldc
ldc copied to clipboard
Bug with mov/lea in inline assembler
Code:
import std.stdio;
extern (C)
{
__gshared int xversion = 43;
export int asm_test()
{
asm
{
naked;
mov RAX, xversion;
// lea RAX, xversion;
// mov EAX, [RAX]; // also - crash
ret;
}
}
}
void main()
{
asm_test().writeln;
}
This code can be compiled only for Windows x86_64! On Linux, compilation failed with PIC error.
Base image address - 0x140000000
This code after compilation use invalid address of xversion
- it reduces address to 4byte, but not use RIP-relative access. Instead of mov RAX, [0x1400a1000]
generated mov RAX, [0x400a1000]
. Some bug with lea
Code on C++ work fine:
#include <iostream>
#include <ostream>
extern "C" {
static auto xversion = 43;
int asm_test() __attribute__((naked));
int asm_test(){
__asm{
mov RAX, xversion;
ret;
}
}
}
int main(){
std:: cout << asm_test() << std::endl;
return 0;
}
Compiled with clang++ -fms-extensions
. Flag -fms-extensions
used to write asm
with intal syntax, like on D.
Clang version - 13.0.1 ldc2 version - 1.28.1 (based on DMD v2.098.1 and LLVM 13.0.1)
P.S. dmd
can't compile this code on x86_64.
P.P.S. rizin can compile this instruction properly - 0x00000000 10 48a100100a4001000000 movabs rax, qword [0x1400a1000]
On Windows, you can probably make it work with [RIP + xversion]
instead of xversion
.
https://d.godbolt.org/z/WTafs6Tbv
On Linux with PIC, it's not so easy: https://d.godbolt.org/z/bbrTE76h1
Does clang++ create a PIC executable?
Note that this only applies to naked DMD-style inline asm. This can also be expressed in non-naked DMD asm, but still making the function naked (and so I guess analogous to your clang example):
import ldc.attributes;
export int asm_test2() @naked
{
asm
{
mov RAX, xversion;
ret;
}
}