Differencebetween Crtbegin.O, Crtbegint.O and Crtbegins.O

What is the difference between crtbegin.o, crtbeginT.o and crtbeginS.o?

I will quote it following, in case that URL disappears.


Mini FAQ about the misc libc/gcc crt files.

Some definitions:
PIC - position independent code (-fPIC)
PIE - position independent executable (-fPIE -pie)
crt - C runtime

crt0.o crt1.o etc...
Some systems use crt0.o, while some use crt1.o (and a few even use crt2.o
or higher). Most likely due to a transitionary phase that some targets
went through. The specific number is otherwise entirely arbitrary -- look
at the internal gcc port code to figure out what your target expects. All
that matters is that whatever gcc has encoded, your C library better use
the same name.

This object is expected to contain the _start symbol which takes care of
bootstrapping the initial execution of the program. What exactly that
entails is highly libc dependent and as such, the object is provided by
the C library and cannot be mixed with other ones.

On uClibc/glibc systems, this object initializes very early ABI requirements
(like the stack or frame pointer), setting up the argc/argv/env values, and
then passing pointers to the init/fini/main funcs to the internal libc main
which in turn does more general bootstrapping before finally calling the real
main function.

glibc ports call this file 'start.S' while uClibc ports call this crt0.S or
crt1.S (depending on what their gcc expects).

crti.o
Defines the function prologs for the .init and .fini sections (with the _init
and _fini symbols respectively). This way they can be called directly. These
symbols also trigger the linker to generate DT_INIT/DT_FINI dynamic ELF tags.

These are to support the old style constructor/destructor system where all
.init/.fini sections get concatenated at link time. Not to be confused with
newer prioritized constructor/destructor .init_array/.fini_array sections and
DT_INIT_ARRAY/DT_FINI_ARRAY ELF tags.

glibc ports used to call this 'initfini.c', but now use 'crti.S'. uClibc
also uses 'crti.S'.

crtn.o
Defines the function epilogs for the .init/.fini sections. See crti.o.

glibc ports used to call this 'initfini.c', but now use 'crtn.S'. uClibc
also uses 'crtn.S'.

Scrt1.o
Used in place of crt1.o when generating PIEs.
gcrt1.o
Used in place of crt1.o when generating code with profiling information.
Compile with -pg. Produces output suitable for the gprof util.
Mcrt1.o
Like gcrt1.o, but is used with the prof utility. glibc installs this as
a dummy file as it's useless on linux systems.

crtbegin.o
GCC uses this to find the start of the constructors.
crtbeginS.o
Used in place of crtbegin.o when generating shared objects/PIEs.
crtbeginT.o
Used in place of crtbegin.o when generating static executables.
crtend.o
GCC uses this to find the start of the destructors.
crtendS.o
Used in place of crtend.o when generating shared objects/PIEs.

General linking order:
crt1.o crti.o crtbegin.o [-L paths] [user objects] [gcc libs] [C libs] [gcc libs] crtend.o crtn.o

What's the usage of Mcrt1.o and Scrt1.o?

Files of the form *crt*.o are invariably C runtime startup code (the bulk of the C runtime tends to exist in libraries, the startup code is an object file as it's always needed).

The description of the various types can be found here, copied below to make the answer self-contained. First some definitions:

Mini FAQ about the misc libc/gcc crt files.

Some definitions:
PIC - position independent code (-fPIC)
PIE - position independent executable (-fPIE -pie)
crt - C runtime

Then the various startup object files:

crt0.o
Older style of the initial runtime code ? Usually not generated anymore
with Linux toolchains, but often found in bare metal toolchains. Serves
same purpose as crt1.o (see below).
crt1.o
Newer style of the initial runtime code. Contains the _start symbol which
sets up the env with argc/argv/libc _init/libc _fini before jumping to the
libc main. glibc calls this file 'start.S'.
crti.o
Defines the function prolog; _init in the .init section and _fini in the
.fini section. glibc calls this 'initfini.c'.
crtn.o
Defines the function epilog. glibc calls this 'initfini.c'.
Scrt1.o
Used in place of crt1.o when generating PIEs.
gcrt1.o
Used in place of crt1.o when generating code with profiling information.
Compile with -pg. Produces output suitable for the gprof util.
Mcrt1.o
Like gcrt1.o, but is used with the prof utility. glibc installs this as
a dummy file as it's useless on linux systems.

And some others:

crtbegin.o
GCC uses this to find the start of the constructors.
crtbeginS.o
Used in place of crtbegin.o when generating shared objects/PIEs.
crtbeginT.o
Used in place of crtbegin.o when generating static executables.
crtend.o
GCC uses this to find the start of the destructors.
crtendS.o
Used in place of crtend.o when generating shared objects/PIEs.

Finally, common linking order:

General linking order:
crt1.o crti.o crtbegin.o [-L paths] [user objects] [gcc libs]
[C libs] [gcc libs] crtend.o crtn.o

How does the linker know which archives to link together?


we could get the last line from the output which generates the ELF binary

That in fact isn't the actual command that generates the ELF binary. collect in turn invokes ld, and that command generates the binary.

how does the linker know that these files should be linked

It doesn't. GCC told it (by supplying them on command line).

GCC has a compiled-in specs file, which is a domain-specific language little program, that tells GCC what arguments it should supply to the linker.

You can examine the built-in specs with gcc -dumpspecs. You will see that the program is actually quite complicated, and that crtbegin.o is only used when -static and -pie or -shared are not. The -shared implies crtbeginS.o, and -static implies crtbeginT.o.

if I don't want to use the standard C library

Use -nostdlib flag in that case.

given a directory of object files that contain the definitions of these functions, how to know the files that are needed to pass to the linker

The ones that define functions that you use. This might help.

What does start address mean for dynamic library?

Just as in a program, the start address (a.k.a entry point address) of a shared library is simply
the start address of the .text segment, containing all the executable
code.

Here's a toy shared library too illustrate:

foo.c

#include <stdio.h>

void foo(void)
{
printf(__func__);
}

Compile and link:

$ gcc -Wall -Wextra -fPIC -c foo.c
$ gcc -shared -o libfoo.so foo.o -Wl,-Map=libfoo.map

Let's see its start address:

$ objdump -f libfoo.so 

libfoo.so: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000000530

We requested a linker map file, libfoo.map, when we linked the SO. Here's
the .text section from that map file:

.text           0x0000000000000530       0xf2
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
.text 0x0000000000000530 0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
.text 0x0000000000000530 0xda /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
.text 0x000000000000060a 0x18 foo.o
0x000000000000060a foo
.text 0x0000000000000622 0x0 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
.text 0x0000000000000622 0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
*(.gnu.warning)

As per objdump, it starts at address 0x530. It is 0xf2 bytes long. From the five
files that the linker loaded:

 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
foo.o
/usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o

The input .text section of crti.o was empty and contributed 0 bytes.
Then crtbeginS.o contributed 0xda bytes, but no symbols. Then foo.o
contributed 0x18 bytes at address 0x60a, including the symbol foo. Then
crtendS.o and crtn.o each contributed 0 bytes. 0xda + 0x18 = 0xf2. (The
files that had empty .text sections will have contributed something to
other output sections, not shown).

So, at the start address of the library we find the code crtbeginS.o,
which is C runtime initialization code - the shared library version -
for finding global constructor functions (i.e. constructors of any C++
global objects or C functions qualified
with __attribute((constructor))). See this question and answer.

In summary, the start address of the shared library enters that library's contribution
to the runtime initialization of the program with which it is dynamically linked.

Trouble building gcc on 64bit RHEL5

It seems your folder /foo/lib/gcc/x86_64-unknown-linux-gnu/lib64 where libgcc_s.so is not included. For the sake of experiment do this:

gcc-4.0 -v t.cc -L/foo/lib/gcc/x86_64-unknown-linux-gnu/lib64

Why are there multiple libgcc.a shipped with android NDK, which one should be used to link with?


  • thumb refers to the instruction set (most ARM processors have different runtime-switchable operating modes that give you different instruction sets). Non-thumb presumably means arm.
  • hard refers to an ABI-variant determining how floating-point arguments are passed to functions (this is now deprecated AFAIK).
  • The libraries not having armv7-a in the path are presumably for the now-deprecated armeabi (i.e. ARMv5TE).

ld: cannot find crt1.o: No such file or directory

Just try a simple puts("Hello world") compiling with cc hello.c (no other options). If still have same issue most likely your toolchain is wrongly installed, else, check the linker options, may you are setting to not find standard libraries.

Hope it helps.



Related Topics



Leave a reply



Submit