So I just completed
http://wiki.osdev.org/Porting_Newlib. I realize that page does not have the best advice and glosses over libgloss (sorry) but it seems to work just fine for my purposes. I'm interested to see if what I did seems fine for basic purposes. Note that I only cared about getting newlib working and I didn't do anything in the way of OS specific toolchain.
- Compile binutils and GCC with --with-sysroot pointing to some directory
- Follow the above link
- Have a implementation-defined list of indices for system calls and have each stub call an implementation-defined software interrupt with arguments, i.e:
Code:
#define sys_write 4
int write(int file, char *ptr, int len) {
int res;
asm volatile("int $0x80" : "=a" (res) : "0" (sys_write), "b" ((int)file), "c" ((long)ptr), "d" ((int)len));
return res;
}
Real code would wrap this in a macro
- Compile and install newlib files to the sysroot
- Treat 0x80 like any other interrupt and add an assembly stub/to the IDT
- In the ISR handler, if it's interrupt 0x80, pass the regs to the system call handler
- Check regs->eax for the system call type; call the corresponding function with the rest of the GPRs as arguments
- Link against -lc -lm (I have the feeling this is not necessary, so I screwed up somewhere)
Code:
write(1, "Test", sizeof("Test"));
seems to work just fine.
What I'm looking to do next is to figure out how to replace newlib's malloc with liballoc (I already have liballoc working kernel-wise) as it seems sbrk is not very popular nowadays. This would ostensibly make testing parts of the library easier before I get userspace working.
Sidenote:
From my search it seems other people are having problems with sbrk and need to zero out the BSS. I'm guessing this only becomes a problem when you enter userspace. For now my stub looks like this:
Code:
caddr_t sbrk(int incr) {
errno = ENOMEM;
return (caddr_t) -1;
}
which I mirror'd after the linux man page.