Syscall/sysenter on LLVM
Posting an answer here since exa has put up a bounty.
I realized this was somewhat a silly question to ask after Ross Ridge's comments, and some playing around with clang.
Let's assume we have the following program, which uses inline assembly to directly call write()
.
#include <stdio.h>
int main(void)
{
char *buf = "test\n";
ssize_t n;
asm volatile (
"movl $0x00000002, %%edi\n" /* first argument == stderr */
"movl $0x00000006, %%edx\n" /* third argument == number of bytes */
"movl $1, %%eax\n" /* syscall number == write on amd64 linux */
"syscall\n"
: "=A"(n) /* %rax: return value */
: "S"(buf)); /* %rsi: second argument == address of data to write */
return n;
}
We can compile this with either gcc
or clang
and get roughly the same result.
$ gcc -o syscall.gcc syscall.c
$ clang -o syscall.clang syscall.c
$ ./syscall.gcc
test
$ ./syscall.clang
test
If we wish to see the exact LLVM instructions which would be used to emit this code, we can simply use the -emit-llvm
flag. As you can see, there is a call i64 asm sideeffect
line which has the full inline assembly string.
$ clang -S -emit-llvm syscall.c
$ cat syscall.ll
; ModuleID = 'syscall.c'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@.str = private unnamed_addr constant [6 x i8] c"test\0A\00", align 1
; Function Attrs: nounwind uwtable
define i32 @main() #0 {
%1 = alloca i32, align 4
%buf = alloca i8*, align 8
%n = alloca i64, align 8
store i32 0, i32* %1
store i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i8** %buf, align 8
%2 = load i8** %buf, align 8
%3 = call i64 asm sideeffect "movl $$0x00000002, %edi\0Amovl $$0x00000006, %edx\0Amovl $$1, %eax\0Asyscall\0A", "=A,{si},~{dirflag},~{fpsr},~{flags}"(i8* %2) #1, !srcloc !1
store i64 %3, i64* %n, align 8
%4 = load i64* %n, align 8
%5 = trunc i64 %4 to i32
ret i32 %5
}
attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }
!llvm.ident = !{!0}
!0 = metadata !{metadata !"Ubuntu clang version 3.5-1ubuntu1 (trunk) (based on LLVM 3.5)"}
!1 = metadata !{i32 134, i32 197, i32 259, i32 312}
OS-independent LLVM IR system calls
Absolutely not. LLVM is a compiler backend; it does not concern itself with system calls. System calls are usually employed inside the platform's C library, which implements them with a mixture of low-level C and target-specific assembly. System calls are both OS and target (CPU) dependent.
As for more materials on studying this stuff - you have my sympathy. It's not a well documented area, because 99.9% of programmers never need to operate at this level. I suggest you start picking up some basic assembly programming and go from there.
Can LLVM-based languages be used in OS development?
LLVM is an abstract machine. As such, it does not directly allow you to access certain hardware registers. However, you can still use inline assembly (through the call asm
LLVM bitcode mnemonic) or program the few functions that need access to fixed hardware registers in assembly and call them from your LLVM code.
Related Topics
Emacs, Linux and International Keyboard Layouts
Mmap: Will the Mapped File Be Loaded into Memory Immediately
Is There Any Significant Difference Between Tcp_Cork and Tcp_Nodelay in This Use-Case
Bash And/Or .Bashrc Not Working Properly After Su or Ssh Login Unless Run "Bash" Command
What Is File Hole and How Can It Be Used
Go Http Server Testing Ab VS Wrk So Much Difference in Result
Linux Udp Max Size of Receive Buffer
The Address Where Filename Has Been Loaded Is Missing [Gdb]
Is It Safe to Issue Blocking Write() Calls on the Same Tcp Socket from Multiple Threads
How to Get Notified for Ip Address Changes Automatically
Creating a Raw Printer Queue in Cups (Host) and Adding Them Through Cups (Client)
Redirecting Man Page Output to File Results in Double Letters in Words
Shell Script Calls Sudo; How to Suppress the Password Prompt
Adding a New System Call in Linux Kernel 3.3
Difference Between Completion Variables and Semaphores
How to Debug Mex Code with Eclipse