OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Nov 20, 2017 12:21 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: GCC complains about not finding crtbegin.o and crtend.o
PostPosted: Wed Dec 05, 2012 7:49 am 
Offline
Member
Member

Joined: Wed Oct 01, 2008 1:55 pm
Posts: 2180
I almost have my cross-compiler based on newlib working, but when I try to compile an empty file like this:

Code:
void main()
{
    return 0;
}


ld complains about not finding crtbegin.o and crtend.o. Apart from ia64, I cannot find the crtbegin and crtend files in the newlib source-tree.

Any ideas why?

I first built GCC -without-headers, then I built libgcc and newlib, and finally I built GCC again.


Top
 Profile  
 
 Post subject: Re: GCC complains about not finding crtbegin.o and crtend.o
PostPosted: Wed Dec 05, 2012 9:16 am 
Offline
Member
Member
User avatar

Joined: Wed Dec 01, 2010 3:41 am
Posts: 1721
Location: Hong Kong
I guess crt is supposed to be provided by your OS, my crt.o is put into libgloss.a and it simply call constructor for global objects, prepare argument list, call main, then call destructors and _exit.


Top
 Profile  
 
 Post subject: Re: GCC complains about not finding crtbegin.o and crtend.o
PostPosted: Wed Dec 05, 2012 9:47 am 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 771
Location: London, UK
crtbegin/crtend are part of libgcc and you need to ask for them to be built. For old gcc (as per the OS Specific Toolchain article) you needed 'extra_parts="crtbegin.o crtend.o"' in gcc/config.gcc under the *-*-myos* section. From looking at the gcc 4.7.0 sources these have now been moved into libgcc, specifically have a look at the libgcc/config.host file and make the appropriate changes there.

Regards,
John.

_________________
Tysos | rpi-boot | EFI tools


Top
 Profile  
 
 Post subject: Re: GCC complains about not finding crtbegin.o and crtend.o
PostPosted: Tue Dec 18, 2012 3:57 pm 
Offline
Member
Member

Joined: Tue Nov 08, 2011 11:35 am
Posts: 453
Sorry for necroposting but I need to know whether I see some optical glitches or i'm still not mad and this is really in the first post.
> void main()
> return 0;
> void > return
I wonder if gcc didn't complain about that.


Top
 Profile  
 
 Post subject: Re: GCC complains about not finding crtbegin.o and crtend.o
PostPosted: Tue Dec 18, 2012 4:50 pm 
Offline
Member
Member

Joined: Wed Oct 01, 2008 1:55 pm
Posts: 2180
Nable wrote:
Sorry for necroposting but I need to know whether I see some optical glitches or i'm still not mad and this is really in the first post.
> void main()
> return 0;
> void > return
I wonder if gcc didn't complain about that.


I'm sure it does. :wink:


Top
 Profile  
 
 Post subject: Re: GCC complains about not finding crtbegin.o and crtend.o
PostPosted: Tue Dec 18, 2012 5:35 pm 
Offline
Member
Member
User avatar

Joined: Wed Mar 21, 2012 3:01 pm
Posts: 920
[Sorry for giving some details here that doesn't really belong in this thread, but it will allow others to find it through Google and it may even help you. I need to document this on the wiki.]

[Edit: These details are now documented on the wiki under http://wiki.osdev.org/Creating_a_C_Library#Program_Initialization]

crtbegin.o and crtend.o are provided by the compiler (may need to configure GCC to enable them). Note that you cannot provide a real implementation of these object files yourself. The purpose is to allow running global constructors/destructors (C++, or using the constructor function attribute) during process initialization and termination. GCC does this by maintaining tables of constructors and destructors somewhere internally, in a manner that doesn't allow anyone but GCC to link to them. Instead, GCC adds code that uses these tables in the .init and .fini sections of crtbegin.o and crtend.o. However, this code is just added as call instructions, and doesn't reside in a function. The missing piece is provided by the standard library, through the object files crti.o and crtn.o. The key is that through linker magic GCC makes sure to link files in this order: crti.o, crtbegin.o, your-program.o, crtend.o, crtn.o (I forgot, maybe I got crtend.o and crtbegin.o swapped). The idea is that crtbegin.o and crtend.o provide the bodies of the constructor/desctructor functions _init and _fini, but not the symbol itself nor the return instruction.

Hence an crti.s implementation will simply be (x86_64):
Code:
.section .init
.global _init
_init:
   push %rbp
   movq %rsp, %rbp
   /* gcc will nicely put the contents of crtbegin.o's .init section here. */

.section .fini
.global _fini
_fini:
   push %rbp
   movq %rsp, %rbp
   /* gcc will nicely put the contents of crtbegin.o's .fini section here. */

and a simple implementation of crtn.s will be (x86_64):
Code:
.section .init
   /* gcc will nicely put the contents of crtend.o's .init section here. */
   popq %rbp
   ret

.section .fini
   /* gcc will nicely put the contents of crtend.o's .fini section here. */
   popq %rbp
   ret


Then your crt0.s implementation can simply be something like:
Code:
.section .text
_start:
   call _init
   call main
   call exit # which calls _fini before really exiting


Now that we understand what crt0.o, crti.o, crtbegin.o, crtend.o, and crtn.o does, we can put the pieces together. If you don't need global constructor functions, you can simply 1) don't call _init and _fini, as you don't have those then 2) make empty crti.o and crtn.o if your cross-compiler links them in - if using newlib you should really set this up, but your miles may vary 3) use the crtbegin.o and crtend.o as provided by your cross-compiler and simply disregard them.

You can change details of how these files are linked in by modifying your OS-specific toolchain in the gcc/config directory. You can search for STARTFILE_SPEC for examples, or look at gcc/config/gnu-user.h that does what I discussed here. Note that shared libraries use a similar method, but different. I need to look into that. Normally, the compiler will provide crtbegin.o and crtend.o, and you provide crti.o, crtn.o and, crt0.o yourself. (Again newlib needs to be configured or something. I use my own libc and did the above.)

Note that some third party software relies on global constructors, even if written in C, by using the GCC constructor function attribute. For instance, binutils uses this to set up some variables, leading a crash if the constructor was never called. If you don't call _init and _fini, then such software will build, but it may fail mysteriously at run-time.

Hopefully this is of use and otherwise serves as documentation. Feel free to ask me if you need more details on how this works.


Oh and --without-headers? I use a neat trick where I install the headers manually before building the cross-compiler (I made a make target that installs them without needing a compiler). Then I can directly build the real cross-compiler and save the time needed to bootstrap. ;)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 17 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group