Page 1 of 1

Executables misbehaving

Posted: Sat Nov 09, 2024 11:58 am
by qwr
Hello! Last time i asked for help here, i got a very nice and helpful response. Now i am having a different problem.

So, i have implemented a really simple syscall mechanism, which uses interrupts and has support for arguments and returns.
Trying to execute the syscalls inside the main.c file, from the kernel, results in expected things happening. Stuff prints, pixels are drawn, etc. So:

Code: Select all

sys_print_func("hello from a syscall"); // <--- this works
sys_draw_pixel_func(0, 0, red); // <--- this also works
Trying, however, to use the same syscalls and functions in a program (flat binary) and executing it, yields in unexpected things happening. It prints garbage out, the garbage being dynamic.
Doing an objdump on the binary, i see something peculiar, mainly:
Disassembly of section .data:

Code: Select all

0000000000000000 <.data>:
   0:	31 c0                	xor    %eax,%eax
   2:	48 89 fa             	mov    %rdi,%rdx
   5:	cd 10                	int    $0x10
   7:	c3                   	ret
What is happening, i'd guess, is that it is triggering the syscall interrupt while not setting the values right, so the syscall tries to print whatever it is in the current RDX.
I, however, am unsure on how to fix it.

The code can be found here:
program being ran and functions definitions for it:
https://github.com/theoriginalgrasshopp ... ernal/apps
the makefile and linker script for generating the binary can be found in this directory:
https://github.com/theoriginalgrasshopp ... R/external
the syscall code can be found in this file:
https://github.com/theoriginalgrasshopp ... c/syscalls
the way of executing, said binary (while temporary), can be found in this file
https://github.com/theoriginalgrasshopp ... e/binary.c

Regards,
qwr

Re: Executables misbehaving

Posted: Sat Nov 09, 2024 5:21 pm
by Octocontrabass
You're jumping to the first byte of your binary, but the first byte of your binary is sys_print_func() instead of _start().

Ideally you'd use a format like ELF instead of a flat binary. ELF has headers to tell you the correct way to load and jump to a binary.

If you really want to make the flat binary work, write a stub in assembly that jumps to the intended entry point and tell the linker to place that stub at the beginning of the binary.

Your flat binary may not work correctly if you don't load it at the address specified here.

Re: Executables misbehaving

Posted: Sun Nov 10, 2024 9:02 am
by qwr
Understood. I, too, thought that flat binaries were REALLY basic.
Do i, however, need a virtual memory management? Or is it possible to load elf executables and run them without any
virtual memory?

Re: Executables misbehaving

Posted: Sun Nov 10, 2024 6:08 pm
by Octocontrabass
You don't need virtual memory to use ELF.

If you'll always load your binary to the same address, you can put that address in your linker script.

You can tell the linker to keep relocations with "-q" (or "-Wl,-q" using GCC) and then apply the relocations when you load the binary.

If you have (or want to write) the necessary startup code, you can compile with "-fpie" and link with "--static-pie" and build binaries that will relocate themselves. GCC expects the startup code to be part of your C standard library.

If you have (or want to write) a dynamic linker, you can compile with "-fpie" and link with "-pie" and use your dynamic linker to relocate binaries when you load them.