Which would you....
Which would you....
Its finally time to make my OS a self-compiling system.
I used tcc to make my os, and I was wondering what path others have chosen to go to make their own/steal a compiler. TCC is relativlely easy to port, as well as obviously having 100% compatibility with code generated ( I replaced the stdlib with my own OS's implementation [ Basic ] ).
I've seen others using FASM, but I'd prefer to focus on C generation.
As well, its wonderfully small size is perfect for a floppy-based os.
Any suggestions?
I used tcc to make my os, and I was wondering what path others have chosen to go to make their own/steal a compiler. TCC is relativlely easy to port, as well as obviously having 100% compatibility with code generated ( I replaced the stdlib with my own OS's implementation [ Basic ] ).
I've seen others using FASM, but I'd prefer to focus on C generation.
As well, its wonderfully small size is perfect for a floppy-based os.
Any suggestions?
Speaking personally, I would love to get GCC working on my OS - I am more than a year away from that at the moment, though!
I would say that if you are familiar with a particular toolchain's internals, that is the way to go. If you are porting a C compiler, I guess you automatically get an assembler too - don't worry about FASM if that's not ultimately the way you want to go.
Well done for getting to the stage where you are thinking about being self-supporting though!
Cheers,
Adam
I would say that if you are familiar with a particular toolchain's internals, that is the way to go. If you are porting a C compiler, I guess you automatically get an assembler too - don't worry about FASM if that's not ultimately the way you want to go.
Well done for getting to the stage where you are thinking about being self-supporting though!
Cheers,
Adam
once newlib
once you use newlib on your os, eventually you can port GCC
oh microsoft, microsoft, what souls you have dismayed
-
- Member
- Posts: 2566
- Joined: Sun Jan 14, 2007 9:15 pm
- Libera.chat IRC: miselin
- Location: Sydney, Australia (I come from a land down under!)
- Contact:
I'm getting around to porting the toolchain to my OS. I have a fully functional port of the Newlib at the moment, I'm just now trying to get my shell to talk to my console driver without crashing... Once that's done I'll be able to start thinking about running programs from a command line (with arguments), once that's done I can start thinking about porting binutils.
Re: Which would you....
You're about a month or two ahead of me, I think. Which, unfortunately, means that I don't have any useful suggestions. I agree with your methods, so far -- I'm intending to steal & eventually rewrite tcc, probably the same with NASM, and definitely write my own linker (I'm using my own executable format). I'll probably do the assembler first .OrOS wrote:It's finally time to make my OS a self-compiling system.
I used tcc ...
Any suggestions?
Eventually I'll port GCC -- but it's a big bloated monster, I don't like its optimizations, and I prefer intel syntax for my asm.
I agree on every point, I have no interest at all in using gcc on my os, and since I want to keep it minimal ( floppy based ) theres no way I could fit it in any case ( However, I was thinking of a ramfs-based package system - load files on demand from an external device ( ie, hd0, fd0, et0 [ Which I haven't done yet...no ether stack at all ] )
Oh? Any specs/advantages over the common formats?(I'm using my own executable format).
As I understand it, almost all executable formats accomplish the same thing, but ...
Since it's mine, I don't have to put in any legacy BS like the PE/COFF format has,
The main parts of the executable header are human readable, unlike ELF
A fully functional header (with no symbol table) adds as little as 40 bytes to the executable over the raw machine language
Until I write my linker, it takes about 30 seconds to type a complete header (as a separate segment) onto the front of an assembler file by hand (since it's human readable)
The way I've started it, it should be completely extensible, using tagged sections, later -- so I can add whatever the hell I need to, when I can figure out what it is that I need
And the main advantage, that I don't think the other formats can manage at all, is the concept of a fixed error-recovery entrypoint, that is known by the scheduler and error handling manager. If a program gets an exception of any sort, instead of just killing the program (maybe with a core dump or unreadable debug screen) -- the system can call the app's own error recovery code, and that code can take one last shot at trying to save your work and/or saving USEFUL debug info, before the app dies.
Since it's mine, I don't have to put in any legacy BS like the PE/COFF format has,
The main parts of the executable header are human readable, unlike ELF
A fully functional header (with no symbol table) adds as little as 40 bytes to the executable over the raw machine language
Until I write my linker, it takes about 30 seconds to type a complete header (as a separate segment) onto the front of an assembler file by hand (since it's human readable)
The way I've started it, it should be completely extensible, using tagged sections, later -- so I can add whatever the hell I need to, when I can figure out what it is that I need
And the main advantage, that I don't think the other formats can manage at all, is the concept of a fixed error-recovery entrypoint, that is known by the scheduler and error handling manager. If a program gets an exception of any sort, instead of just killing the program (maybe with a core dump or unreadable debug screen) -- the system can call the app's own error recovery code, and that code can take one last shot at trying to save your work and/or saving USEFUL debug info, before the app dies.
A) With traditional signal(), not all signals can be caught -- and the ones that can are mostly software generated -- my deal is to give apps an opportunity to catch all HARDWARE generated exceptions
B) For each signal() that can be caught, you have to catch each one separately (annoying)
C) A GPF (for example) will crash your app with no possiblilty of catching with a signal() error routine, but my explicit error handler will ALWAYS give an app a chance to do what it can.
B) For each signal() that can be caught, you have to catch each one separately (annoying)
C) A GPF (for example) will crash your app with no possiblilty of catching with a signal() error routine, but my explicit error handler will ALWAYS give an app a chance to do what it can.
Code: Select all
jamesmol@aubergine:~/test> objdump -d a.out
a.out: file format elf32-i386
Disassembly of section .text:
08048080 <.text>:
8048080: fa cli
jamesmol@aubergine:~/test> ./a.out
Segmentation fault
Only SIGSTOP and SIGTERM, to my knowledge.bewing wrote:A) With traditional signal(), not all signals can be caught...
I think it is a bad idea to have hardware exceptions caught by userspace. One, it opens the door for all kinds of security breaches, and two, handling hardware exceptions is what the kernel's interrupt handlers are for, really....my deal is to give apps an opportunity to catch all HARDWARE generated exceptions
You could enable a userspace application to register a callback hook which gets called once the kernel handled the hardware exception.
You're free to add a function not in the C or POSIX standards that allows a "generic" signal handler to be registered.B) For each signal() that can be caught, you have to catch each one separately (annoying)
As already said, a SIGSEGV can be caught. But generally, there is very little you can do in your application, because it usually points to your programming being screwed up in the first place...C) A GPF (for example) will crash your app with no possiblilty of catching with a signal() error routine, but my explicit error handler will ALWAYS give an app a chance to do what it can.
Every good solution is obvious once you've found it.