diff --git a/src/asm/Assembler.go b/src/asm/Assembler.go new file mode 100644 index 0000000..8369cc5 --- /dev/null +++ b/src/asm/Assembler.go @@ -0,0 +1,8 @@ +package asm + +import "bytes" + +type Assembler struct { + Code bytes.Buffer + Data bytes.Buffer +} diff --git a/src/asm/x64/AppendUint32.go b/src/asm/x64/AppendUint32.go new file mode 100644 index 0000000..52cb813 --- /dev/null +++ b/src/asm/x64/AppendUint32.go @@ -0,0 +1,11 @@ +package x64 + +import "io" + +// AppendUint32 appends a 32 bit number in Little Endian to the given writer. +func AppendUint32(w io.ByteWriter, number uint32) { + w.WriteByte(byte(number)) + w.WriteByte(byte(number >> 8)) + w.WriteByte(byte(number >> 16)) + w.WriteByte(byte(number >> 24)) +} diff --git a/src/asm/x64/MoveRegNum32.go b/src/asm/x64/MoveRegNum32.go new file mode 100644 index 0000000..64a22bb --- /dev/null +++ b/src/asm/x64/MoveRegNum32.go @@ -0,0 +1,10 @@ +package x64 + +import ( + "io" +) + +func MoveRegNum32(w io.ByteWriter, register byte, number uint32) { + w.WriteByte(0xb8 + register) + AppendUint32(w, number) +} diff --git a/src/asm/x64/Syscall.go b/src/asm/x64/Syscall.go new file mode 100644 index 0000000..3c22056 --- /dev/null +++ b/src/asm/x64/Syscall.go @@ -0,0 +1,10 @@ +package x64 + +import ( + "io" +) + +func Syscall(w io.ByteWriter) { + w.WriteByte(0x0f) + w.WriteByte(0x05) +} diff --git a/src/build/Build.go b/src/build/Build.go index 0d3df91..58bc7ff 100644 --- a/src/build/Build.go +++ b/src/build/Build.go @@ -2,23 +2,24 @@ package build import ( "bufio" - "bytes" "os" "path/filepath" "strings" + "git.akyoto.dev/cli/q/src/asm" + "git.akyoto.dev/cli/q/src/asm/x64" "git.akyoto.dev/cli/q/src/directory" "git.akyoto.dev/cli/q/src/elf" "git.akyoto.dev/cli/q/src/errors" "git.akyoto.dev/cli/q/src/log" + "git.akyoto.dev/cli/q/src/register" + "git.akyoto.dev/cli/q/src/syscall" ) // Build describes a compiler build. type Build struct { Name string Directory string - Code bytes.Buffer - Data bytes.Buffer WriteExecutable bool } @@ -39,11 +40,26 @@ func (build *Build) Run() error { return err } - if build.WriteExecutable { - return writeToDisk(build.Executable(), build.Code.Bytes(), build.Data.Bytes()) + if !build.WriteExecutable { + return nil } - return nil + final := asm.Assembler{} + code := &final.Code + data := &final.Data + + x64.MoveRegNum32(code, register.Syscall0, syscall.Write) + x64.MoveRegNum32(code, register.Syscall1, 1) + x64.MoveRegNum32(code, register.Syscall2, 0x4000a2) + x64.MoveRegNum32(code, register.Syscall3, 6) + x64.Syscall(code) + + x64.MoveRegNum32(code, register.Syscall0, syscall.Exit) + x64.MoveRegNum32(code, register.Syscall1, 0) + x64.Syscall(code) + + data.WriteString("Hello\n") + return writeToDisk(build.Executable(), code.Bytes(), data.Bytes()) } // Compile compiles all the functions. @@ -66,19 +82,6 @@ func (build *Build) Compile() error { log.Info.Println(file) }) - build.Code.Write([]byte{ - 0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1 - 0xbf, 0x01, 0x00, 0x00, 0x00, // mov edi, 1 - 0xbe, 0xa2, 0x00, 0x40, 0x00, // mov esi, 0x4000a2 - 0xba, 0x06, 0x00, 0x00, 0x00, // mov edx, 6 - 0x0f, 0x05, // syscall - - 0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, 60 - 0xbf, 0x00, 0x00, 0x00, 0x00, // mov edi, 0 - 0x0f, 0x05, // syscall - }) - - build.Data.Write([]byte{'H', 'e', 'l', 'l', 'o', '\n'}) return nil } diff --git a/src/elf/Header.go b/src/elf/Header.go index 49b231c..089bf00 100644 --- a/src/elf/Header.go +++ b/src/elf/Header.go @@ -5,8 +5,7 @@ const ( TypeExecutable = 2 ArchitectureAMD64 = 0x3E HeaderSize = 64 - CacheLineSize = 64 - Align = CacheLineSize + Align = 16 ) // Header contains general information. diff --git a/src/register/General.go b/src/register/General.go new file mode 100644 index 0000000..4358735 --- /dev/null +++ b/src/register/General.go @@ -0,0 +1,20 @@ +package register + +const ( + R0 = iota + R1 + R2 + R3 + R4 + R5 + R6 + R7 + R8 + R9 + R10 + R11 + R12 + R13 + R14 + R15 +) diff --git a/src/register/Named.go b/src/register/Named.go new file mode 100644 index 0000000..80d2ae7 --- /dev/null +++ b/src/register/Named.go @@ -0,0 +1,12 @@ +package register + +const ( + RAX = R0 + RCX = R1 + RDX = R2 + RBX = R3 + RSP = R4 + RBP = R5 + RSI = R6 + RDI = R7 +) diff --git a/src/register/Syscall_amd64.go b/src/register/Syscall_amd64.go new file mode 100644 index 0000000..62cc6e5 --- /dev/null +++ b/src/register/Syscall_amd64.go @@ -0,0 +1,11 @@ +package register + +const ( + Syscall0 = R0 + Syscall1 = R7 + Syscall2 = R6 + Syscall3 = R2 + Syscall4 = R10 + Syscall5 = R8 + Syscall6 = R9 +) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go new file mode 100644 index 0000000..c2175b8 --- /dev/null +++ b/src/syscall/syscall_linux.go @@ -0,0 +1,333 @@ +package syscall + +const ( + Read = iota + Write + Open + Close + Stat + Fstat + Lstat + Poll + Lseek + Mmap + Mprotect + Munmap + Brk + Rt_sigaction + Rt_sigprocmask + Rt_sigreturn + Ioctl + Pread64 + Pwrite64 + Readv + Writev + Access + Pipe + Select + Sched_yield + Mremap + Msync + Mincore + Madvise + Shmget + Shmat + Shmctl + Dup + Dup2 + Pause + Nanosleep + Getitimer + Alarm + Setitimer + Getpid + Sendfile + Socket + Connect + Accept + Sendto + Recvfrom + Sendmsg + Recvmsg + Shutdown + Bind + Listen + Getsockname + Getpeername + Socketpair + Setsockopt + Getsockopt + Clone + Fork + Vfork + Execve + Exit + Wait4 + Kill + Uname + Semget + Semop + Semctl + Shmdt + Msgget + Msgsnd + Msgrcv + Msgctl + Fcntl + Flock + Fsync + Fdatasync + Truncate + Ftruncate + Getdents + Getcwd + Chdir + Fchdir + Rename + Mkdir + Rmdir + Creat + Link + Unlink + Symlink + Readlink + Chmod + Fchmod + Chown + Fchown + Lchown + Umask + Gettimeofday + Getrlimit + Getrusage + Sysinfo + Times + Ptrace + Getuid + Syslog + Getgid + Setuid + Setgid + Geteuid + Getegid + Setpgid + Getppid + Getpgrp + Setsid + Setreuid + Setregid + Getgroups + Setgroups + Setresuid + Getresuid + Setresgid + Getresgid + Getpgid + Setfsuid + Setfsgid + Getsid + Capget + Capset + Rt_sigpending + Rt_sigtimedwait + Rt_sigqueueinfo + Rt_sigsuspend + Sigaltstack + Utime + Mknod + Uselib + Personality + Ustat + Statfs + Fstatfs + Sysfs + Getpriority + Setpriority + Sched_setparam + Sched_getparam + Sched_setscheduler + Sched_getscheduler + Sched_get_priority_max + Sched_get_priority_min + Sched_rr_get_interval + Mlock + Munlock + Mlockall + Munlockall + Vhangup + Modify_ldt + Pivot_root + Sysctl + Prctl + Arch_prctl + Adjtimex + Setrlimit + Chroot + Sync + Acct + Settimeofday + Mount + Umount2 + Swapon + Swapoff + Reboot + Sethostname + Setdomainname + Iopl + Ioperm + Create_module + Init_module + Delete_module + Get_kernel_syms + Query_module + Quotactl + Nfsservctl + Getpmsg + Putpmsg + Afs_syscall + Tuxcall + Security + Gettid + Readahead + Setxattr + Lsetxattr + Fsetxattr + Getxattr + Lgetxattr + Fgetxattr + Listxattr + Llistxattr + Flistxattr + Removexattr + Lremovexattr + Fremovexattr + Tkill + Time + Futex + Sched_setaffinity + Sched_getaffinity + Set_thread_area + Io_setup + Io_destroy + Io_getevents + Io_submit + Io_cancel + Get_thread_area + Lookup_dcookie + Epoll_create + Epoll_ctl_old + Epoll_wait_old + Remap_file_pages + Getdents64 + Set_tid_address + Restart_syscall + Semtimedop + Fadvise64 + Timer_create + Timer_settime + Timer_gettime + Timer_getoverrun + Timer_delete + Clock_settime + Clock_gettime + Clock_getres + Clock_nanosleep + Exit_group + Epoll_wait + Epoll_ctl + Tgkill + Utimes + Vserver + Mbind + Set_mempolicy + Get_mempolicy + Mq_open + Mq_unlink + Mq_timedsend + Mq_timedreceive + Mq_notify + Mq_getsetattr + Kexec_load + Waitid + Add_key + Request_key + Keyctl + Ioprio_set + Ioprio_get + Inotify_init + Inotify_add_watch + Inotify_rm_watch + Migrate_pages + Openat + Mkdirat + Mknodat + Fchownat + Futimesat + Newfstatat + Unlinkat + Renameat + Linkat + Symlinkat + Readlinkat + Fchmodat + Faccessat + Pselect6 + Ppoll + Unshare + Set_robust_list + Get_robust_list + Splice + Tee + Sync_file_range + Vmsplice + Move_pages + Utimensat + Epoll_pwait + Signalfd + Timerfd_create + Eventfd + Fallocate + Timerfd_settime + Timerfd_gettime + Accept4 + Signalfd4 + Eventfd2 + Epoll_create1 + Dup3 + Pipe2 + Inotify_init1 + Preadv + Pwritev + Rt_tgsigqueueinfo + Perf_event_open + Recvmmsg + Fanotify_init + Fanotify_mark + Prlimit64 + Name_to_handle_at + Open_by_handle_at + Clock_adjtime + Syncfs + Sendmmsg + Setns + Getcpu + Process_vm_readv + Process_vm_writev + Kcmp + Finit_module + Sched_setattr + Sched_getattr + Renameat2 + Seccomp + Getrandom + Memfd_create + Kexec_file_load + Bpf + Stub_execveat + Userfaultfd + Membarrier + Mlock2 + Copy_file_range + Preadv2 + Pwritev2 +)