Make a simple CRT0 in C or assembly
Asked Answered
M

1

7

I'm back with C/C++ and ASM and I want to play a little bit with fire. I found out that when you compile and link code into an executable for Windows it is dynamically linked to some libraries that must exists on any computer where that application is expected to run. You can specify the compiler to not link against them and create your own libraries for that.

Apart from that (and please, correct me if I'm wrong in everything I say here) there's an object file that is always complied and linked along the main code of our app. It is the crt0.o (the C runtime) file and, as I know, it prepares the stack, get argc and argv and call the main function (and maybe other things). I also believe it is the first piece of code called by the system when executing the application.

So, I am trying to create a simple crt0.obj and link it against a simple C++ object file

int main(int argc, char** argv) {
    return 0; 
}

I use GCC and I want to make use of no standard library, so my command looks like:

g++ -s -nostartfiles -nodefaultlibs -nostdlib testapp.cpp -o test.exe crt0.o

I suppose that the -nostartfiles directive is what tells the linker to not embed the default crt0.o, so it expects me to give every definition for any function and handle the start-up of the application. I am a little confused here.

Anyway, I want to create a very basic crt0 object file, that will be enough for GCC to create my executable, and for the system to start it. I know there are many code files (C and ASM) on the Internet but I want to write my own in order to learn how it works. More than code what I need is a little help on what must it do and how to compile/link in order to achieve it. If you know any helpful link that is also very appreciated.

My doubts are:
1. How does the compiler/link create the final file from my code and the C runtime? Do I have to call the main function from crt0.o (using an extern directive)? When I execute g++ -s -nostartfiles -nodefaultlibs -nostdlib testapp.cpp -o test.exe I get "*undefined reference to __main*" error. Is the main function defined in the crt0.o file? It's strange that if I change int main by int start I don't get any error. What does that mean?
2. Which are the essential operations that a crt0 must contain (like getting command-line arguments, calling main)?
3. My code file is CPP and the crt0 is a piece of assembly inside a C file (compiled with GCC). I will post some "frankencode" I managed to create from pieces I found and partially understood:

// crt0.c
__asm(".section .text\n" 
".global _start\n"
"_start:\n"
"mov $0, %ebp\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"push %esi\n"
"push %edi\n"
"call _init\n"
"pop %edi\n"
"pop %esi\n"
"call main\n"
"movl %eax, %edi\n"
"call exit\n"
".section .init\n"
".global _init\n"
"_init:\n"
"push %ebp\n"
"mov %esp, %ebp\n"
".section .fini\n"
".global _fini\n"
"_fini:\n"
"push %ebp\n"
"mov %esp, %ebp\n");

4.) So, in this file, I made some calls to initialization functions. The init and fini functions are already created (they look like simple constructors and destructors, I don't know) There's also the main function, which I don't know how is related to the .cpp main function. I mean, am I supposed to import it? I get undefined reference errors for both main and exit functions.
5.) Must the c0 have a specific format or contain a specific function so the system find its start?

Well, I don't see it difficult to make a small crt0 and make the compiler attach it to the executable, but there are some things I am not able to see correctly. I hope somebody can help me fit all this together. Thanks

Maxillary answered 23/2, 2013 at 16:42 Comment(7)
What is your ACTUAL goal here?Floppy
Create a simple crt0 in C, link it against a C++ file and make that file run only with that.Maxillary
Yes, but do you for example expect to be able to do cout << "hello world!\n", call rand(), call new/delete or use objects with static storage duration, etc, etc? These are all things that are prepared during startup.Floppy
No, just to be able to run the main function, nothing else.Maxillary
So all you really need to do is call main from a _start:. Assuming you don't need argc and argv which also come under the list of things that are set up by CRT0.Floppy
Yes. I may add more initialization functions before main later, but for now I just want to see that I can create a simple int main() function and I don't need any library or stuff, apart from my small crt0Maxillary
You may want to have a look to microsoft.com/msj/archive/S569.aspx, msdn.microsoft.com/library/bb985746.aspx and benshoof.org/blog/minicrt.Branch
F
1

I don't have a windows machine to test on, but this should be the basic bits you need:

#// crt0.c
__asm(".section .text\n" 
".global _start\n"
"_start:\n"
"mov $0, %ebp\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"call main\n"
"pop  %ebp\n"
"ret\n");

Edit: empty __main:

__asm(".global __main\n"
      "__main:\n" 
      "ret\n");
Floppy answered 23/2, 2013 at 16:59 Comment(2)
Yes, but I get "undefined reference to __main" when I compile the cpp containing the main function. So, I don't know how to make the compiler know where to find the main that I call from this code.Maxillary
If you disassemble your main.o, does it make a call to __main by any chance? I think MingW does that to call some of the constructors and such things. In which case, you'll have to add the code I've edited in above [code in comments turn to mush...]Floppy

© 2022 - 2024 — McMap. All rights reserved.