MarcusMathiassen / thi

A C like programming language
0 stars 0 forks source link

linux support? #1

Open ghost opened 5 years ago

ghost commented 5 years ago

Hello I was quite interested to test the thi programming language on Linux, but I didn't get further than segmentation fault. Here is the example code that gives segfault:

def print(msg u8*)
    msg_len = strlen(msg)
    asm
        mov     rax, 0x2000004
        mov     rdi, 1
        mov     rsi, %msg
        mov     rdx, %msg_len
        syscall

def strlen(x u8*) s64 => i = x while *x++ {} x-i

def main(argc s32, argv u8**) s32
    print("hello world\n")

Gdb output:

Reading symbols from ./hello...(no debugging symbols found)...done. (gdb) r Starting program: /home/0verse/thi/hello

Program received signal SIGSEGV, Segmentation fault. 0x0000000000401083 in strlen.l0 ()

I could not comple thi with debug info, since I got this error:

/bin/ld: cannot find /lib/clang/8.0.0/lib/linux/libclang_rt.asan-x86_64.a: No such file or directory clang-8: error: linker command failed with exit code 1 (use -v to see invocation)

Thi compiler doesn't create executable for this code either:

extern puts (u8*)  s32

def main(argc s32, argv u8**) s32
    puts("hello")
MarcusMathiassen commented 5 years ago

Yeah, i’m working on Linux compilation. The compiler at this point generates macOS specific x64 assembly so there is some work to be done.

Looking out your debug build error message it seems like you are missing address sanitizer in Clang. If you remove the "-fsanitize=address” flag at least that error should go away.

I'll see if i can get at least your basic example up and runnning.

ghost commented 5 years ago

I've built thi successfully with dev script without -fsanitize=address but the tests_basic_setup.thi still gives segfault. I think I need to compile some linux packages with debug info in order to give more leading information.

MarcusMathiassen commented 5 years ago

Change "0x2000004" in the first example to "1". Different conventions on linux and macOS. It should then print the message followed by a segfault. The segfault doesnt happen on macOS so i need to check that our further.

The second example needs a link to libc:

extern puts (u8*)  s32
link "-lc"
def main(argc s32, argv u8**) s32
    puts("hello")

See if that works. But first you need to "git pull" i added some linux specific code.

ghost commented 5 years ago

I didn't mention that I'm using musl libc based linux, which is why the second doesn't execute. file shows:

test_puts: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, not stripped

file thi shows:

thi: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, with debug_info, not stripped

ghost commented 5 years ago

I've symlinked /lib/ld-musl-x86_64.so.1 to /lib/ld64.so.1, and I can execute the example, which works, but still gives segfault at the end:

0verse@0verse:~/thi # ./test_puts
hello Segmentation fault

MarcusMathiassen commented 5 years ago

Great, at least it works the same for both of us. The segfault i am unsure of, something linux specific requirements on exit maybe.

ghost commented 5 years ago

I think thi compiler need an option to link with debug info, since gdb doesn't give any useful lead:

Reading symbols from ./test_basic_setup...(no debugging symbols found)...done. (gdb) r Starting program: /home/0verse/thi/test_basic_setup

Program received signal SIGSEGV, Segmentation fault. 0x0000000000000001 in ?? () (gdb) bt

0 0x0000000000000001 in ?? ()

1 0x00007fffffffed8c in ?? ()

2 0x0000000000000000 in ?? ()

the binary lacks debug info:

0verse@0verse:~/thi # file ./test_basic_setup
./test_basic_setup: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

ghost commented 5 years ago

I tried this:

nasm -f elf64 -g test_basic_setup.s 
ld -o test_basic_setup test_basic_setup.o

ld complains:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000

I still get segfault.

The second example, ld complains:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000 ld: test_puts.o:test_puts.s:12: undefined reference to `puts'

MarcusMathiassen commented 5 years ago

Yeah, that is surely needed. Right now the easiest and quickest way to debug is through the generated assembly file. I run "debug_s" on the .s file and change it until i get the desired output. "debug_s" is a simple script atm so you may need to manually change it to fit your linking options etc.

You need to add "-e main" to your ld command to specify the entry label.

ghost commented 5 years ago

I've adapted the debus_s for linux:

#!/bin/bash
nasm -f elf64 -F dwarf -g $1 -o test.o

flags="-lc -Bdynamic"

ld -o test test.o -e main $flags
./test
echo $?
# rm ./test
rm ./test.o

Now the binary is dynamically linked and has debu info. file test:

test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, with debug_info, not stripped

However still no lead on gdb.

MarcusMathiassen commented 5 years ago

You wont get any useful debug information out of -g on nasm. It needs to be explicitly added in the codegen phase of the compiler.

When it comes to the segfault, i believe it has to do with the calling convention on linux. Some cleanup of registers is required before/after the call instruction and there may be some alignment requirements too.

ghost commented 5 years ago

I have adapted the test_basic_setup.thi file for linux(see the PR) and it prints "hello world" followed by a segfault. So I believe the linux support is basically working fine.

MarcusMathiassen commented 5 years ago

Could you try getting the 'test_window' test running? It's a OpenGL application using GLFW and GLEW.

ghost commented 5 years ago

Sure, I'll give it a shot tomorrow.

ghost commented 5 years ago

I'm getting linker issues, possible since I'm using musl libc. Here is the debug_s output:

ld: test.o: in function drawTriangle.begin': test_window.s:1922: undefined reference toglBegin' ld: test_window.s:1938: undefined reference to glColor3f' ld: test_window.s:1979: undefined reference toglVertex2f' ld: test_window.s:1995: undefined reference to glColor3f' ld: test_window.s:2018: undefined reference toglVertex2f' ld: test_window.s:2034: undefined reference to glColor3f' ld: test_window.s:2069: undefined reference toglVertex2f' ld: test_window.s:2070: undefined reference to glEnd' ld: test.o: in functionmain.begin': test_window.s:2099: undefined reference to glfwInit' ld: test.o: in functionmain.l0': test_window.s:2117: undefined reference to glfwWindowHint' ld: test_window.s:2124: undefined reference toglfwWindowHint' ld: test_window.s:2140: undefined reference to glfwCreateWindow' ld: test_window.s:2149: undefined reference toglfwMakeContextCurrent' ld: test_window.s:2150: undefined reference to glewInit' ld: test.o: in functionmain.l4': test_window.s:2237: undefined reference to glfwGetKey' ld: test.o: in functionmain.l6': test_window.s:2268: undefined reference to glfwGetKey' ld: test.o: in functionmain.l8': test_window.s:2299: undefined reference to glfwGetKey' ld: test.o: in functionmain.l10': test_window.s:2330: undefined reference to glfwGetKey' ld: test.o: in functionmain.l12': test_window.s:2361: undefined reference to glfwGetKey' ld: test.o:test_window.s:2392: more undefined references toglfwGetKey' follow ld: test.o: in function main.l16': test_window.s:2489: undefined reference toglClearColor' ld: test_window.s:2493: undefined reference to glfwWindowShouldClose' ld: test.o: in functionmain.l18': test_window.s:2511: undefined reference to glfwGetKey' ld: test.o: in functionmain.l20': test_window.s:2531: undefined reference to glClear' ld: test_window.s:2532: undefined reference toglfwPollEvents' ld: test_window.s:2539: undefined reference to glfwGetKey' ld: test.o: in functionmain.l22': test_window.s:2570: undefined reference to glfwGetKey' ld: test.o: in functionmain.l24': test_window.s:2601: undefined reference to glfwGetKey' ld: test.o: in functionmain.l26': test_window.s:2632: undefined reference to glfwGetKey' ld: test.o: in functionmain.l28': test_window.s:2663: undefined reference to glfwGetKey' ld: test.o:test_window.s:2694: more undefined references toglfwGetKey' follow ld: test.o: in function main.l32': test_window.s:2750: undefined reference toglfwSwapBuffers' ld: test.o: in function main.end': test_window.s:2761: undefined reference toglfwTerminate' ./debug_s: line 20: ./test: No such file or directory 127

ghost commented 5 years ago

undefined reference was fixed by adding additional linker options to the debug_s:

LD_FLAGS="-e main -lc -Bdynamic -lGL -lglfw -lGLEW"

However I got a segfault when running the test. Here is the gdb info:

Reading symbols from ./test...done. (gdb) r Starting program: /home/0verse/thi/test

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7f8113f in strspn () from /lib/ld-musl-x86_64.so.1 (gdb) bt

0 0x00007ffff7f8113f in strspn () from /lib/ld-musl-x86_64.so.1

1 0x0000000000000000 in ?? ()

Musl libc strspn.c GNU libc strspn.c

ghost commented 5 years ago

I tested test_window.thi on ubuntu and I got segfault as well, here is the debug info:

Reading symbols from ./test... (gdb) r Starting program: /home/sofia/thi/test [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7e4decd in _IO_str_init_static_internal (sf=sf@entry=0x7fffffffd958, > pstart=pstart@entry=0x40b060 "") at strops.c:41 41 strops.c: No such file or directory. (gdb) bt

0 0x00007ffff7e4decd in _IO_str_init_static_internal (sf=sf@entry=0x7fffffffd9>

size=size@entry=29, pstart=pstart@entry=0x40b060 "") at strops.c:41

1 0x00007ffff7e46487 in __vsnprintf_internal (string=0x40b060 "", maxlen=

args=args@entry=0x7fffffffdad8, mode_flags=2) at vsnprintf.c:113

2 0x00007ffff7ee880c in ___snprintf_chk (s=, maxlen=

format=<optimized out>) at snprintf_chk.c:38

3 0x00007ffff7276526 in xcb_connect_to_display_with_auth_info () from /usr/lib>

4 0x00007ffff76efcd2 in _XConnectXCB () from /usr/lib/x86_64-linux-gnu/libX11.>

5 0x00007ffff76e0892 in XOpenDisplay () from /usr/lib/x86_64-linux-gnu/libX11.>

6 0x00007ffff7b143fa in ?? () from /usr/lib/x86_64-linux-gnu/libglfw.so.3

7 0x00007ffff7b0fb3d in glfwInit () from /usr/lib/x86_64-linux-gnu/libglfw.so.3

8 0x000000000040345e in main.begin () at test_window.s:2099

9 0x0000000000000000 in ?? ()

runtest output for test_window: https://pastebin.com/qe7wMzAs runtest output for test_basic_setup_linux: https://pastebin.com/fXPckMH5