x64: basic mach-o and arm64 support
parent
818be80581
commit
845e8decce
|
@ -24,14 +24,13 @@ pub type FNMove = fn (x f32, y f32, z voidptr)
|
||||||
pub type FNChar = fn (c u32, x voidptr)
|
pub type FNChar = fn (c u32, x voidptr)
|
||||||
|
|
||||||
pub struct Event {
|
pub struct Event {
|
||||||
pub:
|
pub mut:
|
||||||
frame_count u64
|
frame_count u64
|
||||||
typ sapp.EventType
|
typ sapp.EventType
|
||||||
key_code KeyCode
|
key_code KeyCode
|
||||||
char_code u32
|
char_code u32
|
||||||
key_repeat bool
|
key_repeat bool
|
||||||
modifiers u32
|
modifiers u32
|
||||||
pub mut:
|
|
||||||
mouse_button sapp.MouseButton
|
mouse_button sapp.MouseButton
|
||||||
mouse_x f32
|
mouse_x f32
|
||||||
mouse_y f32
|
mouse_y f32
|
||||||
|
|
|
@ -31,6 +31,8 @@ mut:
|
||||||
debug_pos int
|
debug_pos int
|
||||||
errors []errors.Error
|
errors []errors.Error
|
||||||
warnings []errors.Warning
|
warnings []errors.Warning
|
||||||
|
syms []Symbol
|
||||||
|
relocs []Reloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// string_addr map[string]i64
|
// string_addr map[string]i64
|
||||||
|
@ -173,6 +175,15 @@ fn (mut g Gen) write_string(s string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) write_string_with_padding(s string, max int) {
|
||||||
|
for c in s {
|
||||||
|
g.write8(int(c))
|
||||||
|
}
|
||||||
|
for _ in 0 .. max - s.len {
|
||||||
|
g.write8(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) inc(reg Register) {
|
fn (mut g Gen) inc(reg Register) {
|
||||||
g.write16(0xff49)
|
g.write16(0xff49)
|
||||||
match reg {
|
match reg {
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Assembler program to print "Hello World!"
|
||||||
|
// to stdout.
|
||||||
|
//
|
||||||
|
// X0-X2 - parameters to Unix system calls
|
||||||
|
// X16 - Mach System Call function number
|
||||||
|
//
|
||||||
|
|
||||||
|
.global _start // Provide program starting address to linker
|
||||||
|
.align 4 // Make sure everything is aligned properly
|
||||||
|
|
||||||
|
// Setup the parameters to print hello world
|
||||||
|
// and then call the Kernel to do it.
|
||||||
|
_start: mov X0, #1 // 1 = StdOut
|
||||||
|
adr X0, helloworld // string to print
|
||||||
|
//mov X2, #13 // length of our string
|
||||||
|
bl _puts
|
||||||
|
//mov X16, #4 // Unix write system call
|
||||||
|
//svc #0x80 // Call kernel to output the string
|
||||||
|
|
||||||
|
// Setup the parameters to exit the program
|
||||||
|
// and then call the kernel to do it.
|
||||||
|
mov X0, #0 // Use 0 return code
|
||||||
|
mov X16, #1 // System call number 1 terminates this program
|
||||||
|
svc #0x80 // Call kernel to terminate the program
|
||||||
|
|
||||||
|
helloworld: .ascii "Hello World!\n"
|
|
@ -0,0 +1,281 @@
|
||||||
|
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module x64
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
const (
|
||||||
|
S_ATTR_SOME_INSTRUCTIONS = 0x00000400
|
||||||
|
S_ATTR_PURE_INSTRUCTIONS = 0x80000000
|
||||||
|
S_ATTR_EXT_RELOC = 0x00000200
|
||||||
|
S_ATTR_LOC_RELOC = 0x00000100
|
||||||
|
//
|
||||||
|
MACHO_SYMCMD_SIZE = 0x18
|
||||||
|
MACHO_D_SIZE = 0x50
|
||||||
|
LC_SYMTAB = 0x2
|
||||||
|
LC_DYMSYMTAB = 0xB
|
||||||
|
)
|
||||||
|
|
||||||
|
struct Symbol {
|
||||||
|
str_entry int
|
||||||
|
symbol_typ int
|
||||||
|
section int
|
||||||
|
desc int
|
||||||
|
val i64
|
||||||
|
name string
|
||||||
|
is_ext bool
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Reloc {
|
||||||
|
addr int
|
||||||
|
pcrel int
|
||||||
|
len int
|
||||||
|
ext int
|
||||||
|
typ int
|
||||||
|
snum int // symbol index (if ext) or infile section number
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) generate_macho_header() {
|
||||||
|
g.write32(0xfeedfacf) // MH_MAGIC_64
|
||||||
|
g.write32(0x0100000c) // CPU_TYPE_ARM64
|
||||||
|
g.write32(0x00000000) // CPU_SUBTYPE_ARM64_ALL
|
||||||
|
g.write32(0x00000001) // MH_OBJECT
|
||||||
|
g.write32(0x00000004) // # of load commands
|
||||||
|
g.write32(0x118) // size of load commands
|
||||||
|
// g.write32(0x00002000) // MH_SUBSECTIONS_VIA_SYMBOLS
|
||||||
|
g.write32(0) // MH_SUBSECTIONS_VIA_SYMBOLS
|
||||||
|
g.write32(0) // reserved
|
||||||
|
////
|
||||||
|
g.write32(0x19) // LC_SEGMENT_64
|
||||||
|
g.write32(0x98) // command size
|
||||||
|
g.zeroes(16) // segment name
|
||||||
|
g.write64(0) // VM address
|
||||||
|
g.write64(0x25) // VM size
|
||||||
|
g.write64(0x138) // file offset
|
||||||
|
g.write64(0x25) // file size
|
||||||
|
g.write32(0x7) // max vm protection
|
||||||
|
g.write32(0x7) // initial vm protection
|
||||||
|
g.write32(0x1) // # of sections
|
||||||
|
g.write32(0) // flags
|
||||||
|
////
|
||||||
|
g.write_string_with_padding('__text', 16) // section name
|
||||||
|
g.write_string_with_padding('__TEXT', 16) // segment name
|
||||||
|
g.write64(0) // address
|
||||||
|
g.write64(0x25) // size
|
||||||
|
g.write32(0x138) // offset
|
||||||
|
g.write32(0x4) // alignment
|
||||||
|
g.write32(0x160) // relocation offset
|
||||||
|
g.write32(0x1) // # of relocations
|
||||||
|
g.write32(x64.S_ATTR_SOME_INSTRUCTIONS | x64.S_ATTR_PURE_INSTRUCTIONS)
|
||||||
|
g.write32(0)
|
||||||
|
g.write32(0)
|
||||||
|
g.write32(0)
|
||||||
|
/// ???
|
||||||
|
g.write32(0x32)
|
||||||
|
g.write32(0x18)
|
||||||
|
|
||||||
|
g.write32(0x01)
|
||||||
|
g.write32(0x000b0000)
|
||||||
|
g.write32(0)
|
||||||
|
g.write32(0)
|
||||||
|
// LC_SYMTAB
|
||||||
|
g.sym_table_command()
|
||||||
|
//
|
||||||
|
g.write32(x64.LC_DYMSYMTAB)
|
||||||
|
g.write32(x64.MACHO_D_SIZE)
|
||||||
|
g.write32(0)
|
||||||
|
g.write32(2)
|
||||||
|
g.write32(2)
|
||||||
|
g.write32(1)
|
||||||
|
g.write32(3)
|
||||||
|
g.write32(1)
|
||||||
|
for _ in 0 .. 12 {
|
||||||
|
g.write32(0)
|
||||||
|
}
|
||||||
|
// g.write32(0x77777777)
|
||||||
|
// assembly
|
||||||
|
g.mov_arm(.x0, 1)
|
||||||
|
g.adr()
|
||||||
|
g.bl()
|
||||||
|
g.mov_arm(.x0, 0)
|
||||||
|
g.mov_arm(.x16, 1)
|
||||||
|
g.svc()
|
||||||
|
//
|
||||||
|
g.write_string('Hello WorlD!\n')
|
||||||
|
g.write8(0) // padding?
|
||||||
|
g.write8(0)
|
||||||
|
g.write8(0)
|
||||||
|
g.write_relocs()
|
||||||
|
g.sym_table()
|
||||||
|
g.sym_string_table()
|
||||||
|
g.write8(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) generate_macho_footer() {
|
||||||
|
// Create the binary
|
||||||
|
mut f := os.create(g.out_name) or { panic(err) }
|
||||||
|
os.chmod(g.out_name, 0o775) // make it an executable
|
||||||
|
f.write_bytes(g.buf.data, g.buf.len)
|
||||||
|
f.close()
|
||||||
|
// println('\narm64 mach-o binary has been successfully generated')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sym_table_command() {
|
||||||
|
g.syms << Symbol{
|
||||||
|
str_entry: 0x19
|
||||||
|
symbol_typ: 0xe
|
||||||
|
section: 1
|
||||||
|
val: 0
|
||||||
|
name: '_start'
|
||||||
|
is_ext: true
|
||||||
|
}
|
||||||
|
g.syms << Symbol{
|
||||||
|
str_entry: 0x0e
|
||||||
|
symbol_typ: 0xe
|
||||||
|
// symbol_typ: SYM_DEF
|
||||||
|
section: 1
|
||||||
|
val: 0x18
|
||||||
|
name: '_puts'
|
||||||
|
is_ext: false
|
||||||
|
}
|
||||||
|
g.syms << Symbol{
|
||||||
|
str_entry: 0x01
|
||||||
|
symbol_typ: 0xf
|
||||||
|
// symbol_typ: SYM_DEF
|
||||||
|
section: 1
|
||||||
|
// val: 0x27
|
||||||
|
val: 0
|
||||||
|
name: 'helloworld'
|
||||||
|
is_ext: false
|
||||||
|
}
|
||||||
|
g.syms << Symbol{
|
||||||
|
str_entry: 0x08
|
||||||
|
symbol_typ: 0x1
|
||||||
|
// symbol_typ: SYM_DEF
|
||||||
|
section: 0
|
||||||
|
// val: 0x27
|
||||||
|
val: 0
|
||||||
|
name: 'ltmp1'
|
||||||
|
is_ext: false
|
||||||
|
}
|
||||||
|
g.write32(x64.LC_SYMTAB)
|
||||||
|
g.write32(x64.MACHO_SYMCMD_SIZE)
|
||||||
|
sym_table_offset := 0x168
|
||||||
|
g.write32(sym_table_offset)
|
||||||
|
g_syms_len := 4
|
||||||
|
g.write32(g_syms_len)
|
||||||
|
str_offset := 0x1a8
|
||||||
|
g.write32(str_offset)
|
||||||
|
str_size := 0x20
|
||||||
|
g.write32(str_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) zeroes(n int) {
|
||||||
|
for _ in 0 .. n {
|
||||||
|
g.buf << 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Register2 {
|
||||||
|
x0
|
||||||
|
x1
|
||||||
|
x2
|
||||||
|
x3
|
||||||
|
x4
|
||||||
|
x5
|
||||||
|
x6
|
||||||
|
x7
|
||||||
|
x8
|
||||||
|
x9
|
||||||
|
x10
|
||||||
|
x11
|
||||||
|
x12
|
||||||
|
x13
|
||||||
|
x14
|
||||||
|
x15
|
||||||
|
x16
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) mov_arm(reg Register2, val u64) {
|
||||||
|
m := u64(0xffff)
|
||||||
|
x := u64(val)
|
||||||
|
// println('========')
|
||||||
|
// println(x & ~m)
|
||||||
|
// println(x & ~(m << 16))
|
||||||
|
// g.write32(0x777777)
|
||||||
|
r := int(reg)
|
||||||
|
if r == 0 && val == 1 {
|
||||||
|
g.write32(0xd2800020)
|
||||||
|
} else if r == 0 {
|
||||||
|
g.write32(0xd2800000)
|
||||||
|
} else if r == 16 {
|
||||||
|
g.write32(0xd2800030)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if 1 ^ (x & ~m) != 0 {
|
||||||
|
// println('yep')
|
||||||
|
g.write32(int(u64(0x52800000) | u64(r) | x << 5))
|
||||||
|
g.write32(0x88888888)
|
||||||
|
g.write32(int(u64(0x52800000) | u64(r) | x >> 11))
|
||||||
|
} else if 1 ^ (x & ~(m << 16)) != 0 {
|
||||||
|
// g.write32(int(u64(0x52800000) | u64(r) | x >> 11))
|
||||||
|
// println('yep2')
|
||||||
|
// g.write32(0x52a00000 | r | val >> 11)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) adr() {
|
||||||
|
g.write32(0x100000a0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) bl() {
|
||||||
|
// g.write32(0xa9400000)
|
||||||
|
g.write32(0x94000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) svc() {
|
||||||
|
g.write32(0xd4001001)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) write_relocs() {
|
||||||
|
g.write32(0x8)
|
||||||
|
g.write32(0x2d000003)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sym_table() {
|
||||||
|
// strings first
|
||||||
|
for sym in g.syms {
|
||||||
|
// if !sym.is_ext {
|
||||||
|
g.write_symbol(sym)
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
// now fns (external syms)
|
||||||
|
/*
|
||||||
|
for sym in g.syms {
|
||||||
|
if sym.is_ext {
|
||||||
|
g.write_symbol(sym)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) write_symbol(s Symbol) {
|
||||||
|
// g.write8(0x77)
|
||||||
|
g.write32(s.str_entry)
|
||||||
|
g.write8(s.symbol_typ)
|
||||||
|
g.write8(s.section)
|
||||||
|
g.write8(0)
|
||||||
|
g.write8(0)
|
||||||
|
g.write64(s.val)
|
||||||
|
// g.write16(s.desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sym_string_table() {
|
||||||
|
g.zeroes(1)
|
||||||
|
for sym in g.syms {
|
||||||
|
g.write_string(sym.name)
|
||||||
|
g.write8(0)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import v.gen.x64
|
||||||
|
import v.pref
|
||||||
|
import v.table
|
||||||
|
|
||||||
|
fn test_macho() {
|
||||||
|
mut g := x64.Gen{
|
||||||
|
pref: &pref.Preferences{}
|
||||||
|
out_name: 'test.bin'
|
||||||
|
table: &table.Table{}
|
||||||
|
}
|
||||||
|
g.generate_macho_header()
|
||||||
|
g.generate_macho_footer()
|
||||||
|
}
|
Loading…
Reference in New Issue