Skip to content

Startup files explained

Edmunt Pienkowsky edited this page May 24, 2024 · 5 revisions

Types of startup files

There are two types of startup files:

startup file type Object files
libgcc‑based crtbegin.o, crtbeginS.o, crtbeginT.o, crtend.o, crtendS.o
libc‑based crtn.o, crt1.o, Mcrt1.o, rcrt1.o, gcrt1.o, Scrt1.o, crti.o, grcrt1.o

Usually they are located in two different folders and provided by two different packages.

# libgcc
$ dpkg -S crtbegin.o
libgcc-12-dev:amd64: /usr/lib/gcc/x86_64-linux-gnu/12/crtbegin.o

# libc
$ dpkg -S crt1.o
libc6-dev:amd64: /usr/lib/x86_64-linux-gnu/Mcrt1.o
libc6-dev:amd64: /usr/lib/x86_64-linux-gnu/rcrt1.o
libc6-dev:amd64: /usr/lib/x86_64-linux-gnu/gcrt1.o
libc6-dev:amd64: /usr/lib/x86_64-linux-gnu/Scrt1.o
libc6-dev:amd64: /usr/lib/x86_64-linux-gnu/grcrt1.o
libc6-dev:amd64: /usr/lib/x86_64-linux-gnu/crt1.o

Note

We will refer to all files listed here as startup files even though some of them contain finalization code. The distinction between startup and finalization code is not important here.

Tip

You may invoke gcc with -print-file-name=fname option to obtain full path to startup file. For example:

$ arm-linux-gnueabihf-gcc -print-file-name=crtbegin.o
/usr/lib/gcc-cross/arm-linux-gnueabihf/12/crtbegin.o

GCC's resolution order of startup files

GCC's default search directories

gcc invoked with -print-search-dirs option displays default search directories:

$ arm-linux-gnueabihf-gcc -print-search-dirs
install: /usr/lib/gcc-cross/arm-linux-gnueabihf/12/
programs: =/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/bin/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/bin/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/bin/
libraries: =/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/lib/:/lib/arm-linux-gnueabihf/12/:/lib/arm-linux-gnueabihf/:/lib/:/usr/lib/arm-linux-gnueabihf/12/:/usr/lib/arm-linux-gnueabihf/:/usr/lib/

This option may be used alongside with --sysroot one:

$ arm-linux-gnueabihf-gcc --sysroot=/home/vscode/sysroot -print-search-dirs
install: /usr/lib/gcc-cross/arm-linux-gnueabihf/12/
programs: =/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/bin/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/bin/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/bin/
libraries: =/usr/lib/gcc-cross/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/12/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/12/../../../../arm-linux-gnueabihf/lib/:/home/vscode/sysroot/lib/arm-linux-gnueabihf/12/:/home/vscode/sysroot/lib/arm-linux-gnueabihf/:/home/vscode/sysroot/lib/:/home/vscode/sysroot/usr/lib/arm-linux-gnueabihf/12/:/home/vscode/sysroot/usr/lib/arm-linux-gnueabihf/:/home/vscode/sysroot/usr/lib/

Startup files resolution order

For startup files resolution order is:

  1. Directory listed in install list.

    This is the location of libgcc‑based startup files. This directory may also be at first position of libraries list.

  2. Directories listed in libraries list.

    libc‑based startup files usually are located at directory pointed by first or second item on this list.

Other directories specified by -L option aren't taken into account.

The gcc-search-dirs.cmake script

This script invokes gcc with -print-search-dirs and then displays output of this command in a more human‑readable form. Basicaly this script:

  • normalizes paths,
  • removes paths to non-existing directories,
  • translates paths to real paths without symlinks (real_path attribute),
  • displays output as a formatted JSON.

For example command:

cmake -P cmake/gcc-search-dirs.cmake arm-none-linux-gnueabihf

outputs:

{
  "search_dirs" : 
  {
    "install" : "/home/vscode/arm-none-linux-gnueabihf/lib/gcc/arm-none-linux-gnueabihf/13.2.1",
    "libraries" : 
    [
      "/home/vscode/arm-none-linux-gnueabihf/lib/gcc",
      "/home/vscode/arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/lib",
      {
        "path" : "/home/vscode/sysroot/lib",
        "real_path" : "/home/vscode/sysroot/usr/lib"
      },
      "/home/vscode/sysroot/usr/lib"
    ],
    "programs" : 
    [
      "/home/vscode/arm-none-linux-gnueabihf/libexec/gcc",
      "/home/vscode/arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/bin"
    ],
    "startup_files" : 
    [
      {
        "path" : "/home/vscode/arm-none-linux-gnueabihf/lib/gcc/arm-none-linux-gnueabihf/13.2.1",
        "startup" : "libgcc.distrib"
      },
      "/home/vscode/arm-none-linux-gnueabihf/lib/gcc",
      "/home/vscode/arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/lib",
      {
        "path" : "/home/vscode/sysroot/lib",
        "real_path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      },
      {
        "path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      }
    ]
  },
  "sysroot" : "/home/vscode/sysroot",
  "version" : "arm-none-linux-gnueabihf-gcc (Arm GNU Toolchain 13.2.rel1 (Build arm-13.7)) 13.2.1 20231009"
}

Arguments

This script takes two optional arguments.

  1. The first argument is a name or path to gcc. Its default value is just gcc. Three special values are also accepted: arm-linux-gnueabihf, arm-none-linux-gnueabihf and armv6-unknown-linux-gnueabihf.
  2. The second argument is a path to sysroot. Its default value is ~/sysroot (if exists) or just / (no sysroot).

Invoking script via (go-)task

If you have (go-)task installed you may run gcc-search-dirs.cmake script in a more convenient way.

# arm-linux-gnueabihf
task arm-linux-gnueabihf:gcc-search-dirs

# arm-none-linux-gnueabihf
task arm-none-linux-gnueabihf:gcc-search-dirs

# arm-none-linux-gnueabihf - no sysroot
task arm-none-linux-gnueabihf:gcc-search-dirs -- /

Note

(go-)task is installed on devcontainer by default.

Usage

Invoking script without arguments

cmake -P cmake/gcc-search-dirs.cmake
{
  "multiarch" : "x86_64-linux-gnu",
  "search_dirs" : 
  {
    "install" : "/usr/lib/gcc/x86_64-linux-gnu/12",
    "libraries" : 
    [
      "/usr/lib/gcc/x86_64-linux-gnu/12",
      "/usr/lib/x86_64-linux-gnu",
      "/usr/lib",
      {
        "path" : "/lib/x86_64-linux-gnu",
        "real_path" : "/usr/lib/x86_64-linux-gnu"
      },
      {
        "path" : "/lib",
        "real_path" : "/usr/lib"
      }
    ],
    "programs" : [ "/usr/lib/gcc/x86_64-linux-gnu/12", "/usr/lib/gcc/x86_64-linux-gnu" ],
    "startup_files" : 
    [
      {
        "path" : "/usr/lib/gcc/x86_64-linux-gnu/12",
        "startup" : "libgcc"
      },
      {
        "path" : "/usr/lib/x86_64-linux-gnu",
        "startup" : "libc"
      },
      "/usr/lib",
      {
        "path" : "/lib/x86_64-linux-gnu",
        "real_path" : "/usr/lib/x86_64-linux-gnu",
        "startup" : "libc"
      },
      {
        "path" : "/lib",
        "real_path" : "/usr/lib"
      }
    ]
  },
  "version" : "gcc (Debian 12.2.0-14) 12.2.0"
}

Displaying search dirs of arm-linux-gnueabihf cross-compiler with sysroot

cmake -P cmake/gcc-search-dirs.cmake arm-linux-gnueabihf
{
  "multiarch" : "arm-linux-gnueabihf",
  "search_dirs" : 
  {
    "install" : "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
    "libraries" : 
    [
      "/usr/arm-linux-gnueabihf/lib",
      {
        "path" : "/home/vscode/sysroot/lib/arm-linux-gnueabihf",
        "real_path" : "/home/vscode/sysroot/usr/lib"
      },
      {
        "path" : "/home/vscode/sysroot/lib",
        "real_path" : "/home/vscode/sysroot/usr/lib"
      },
      {
        "path" : "/home/vscode/sysroot/usr/lib/arm-linux-gnueabihf",
        "real_path" : "/home/vscode/sysroot/usr/lib"
      },
      "/home/vscode/sysroot/usr/lib"
    ],
    "programs" : 
    [
      "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
      "/usr/lib/gcc-cross/arm-linux-gnueabihf",
      "/usr/arm-linux-gnueabihf/bin"
    ],
    "startup_files" : 
    [
      {
        "path" : "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
        "startup" : "libgcc.distrib"
      },
      {
        "path" : "/usr/arm-linux-gnueabihf/lib",
        "startup" : "libc.distrib"
      },
      {
        "path" : "/home/vscode/sysroot/lib/arm-linux-gnueabihf",
        "real_path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      },
      {
        "path" : "/home/vscode/sysroot/lib",
        "real_path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      },
      {
        "path" : "/home/vscode/sysroot/usr/lib/arm-linux-gnueabihf",
        "real_path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      },
      {
        "path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      }
    ]
  },
  "sysroot" : "/home/vscode/sysroot",
  "version" : "arm-linux-gnueabihf-gcc (Debian 12.2.0-14) 12.2.0"
}

Displaying search dirs of arm-linux-gnueabihf cross-compiler without sysroot

cmake -P cmake/gcc-search-dirs.cmake arm-linux-gnueabihf /
{
  "multiarch" : "arm-linux-gnueabihf",
  "search_dirs" : 
  {
    "install" : "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
    "libraries" : 
    [
      "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
      "/usr/arm-linux-gnueabihf/lib",
      {
        "path" : "/lib/arm-linux-gnueabihf",
        "real_path" : "/usr/lib/arm-linux-gnueabihf"
      },
      {
        "path" : "/lib",
        "real_path" : "/usr/lib"
      },
      "/usr/lib/arm-linux-gnueabihf",
      "/usr/lib"
    ],
    "programs" : 
    [
      "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
      "/usr/lib/gcc-cross/arm-linux-gnueabihf",
      "/usr/arm-linux-gnueabihf/bin"
    ],
    "startup_files" : 
    [
      {
        "path" : "/usr/lib/gcc-cross/arm-linux-gnueabihf/12",
        "startup" : "libgcc.distrib"
      },
      {
        "path" : "/usr/arm-linux-gnueabihf/lib",
        "startup" : "libc.distrib"
      },
      {
        "path" : "/lib/arm-linux-gnueabihf",
        "real_path" : "/usr/lib/arm-linux-gnueabihf"
      },
      {
        "path" : "/lib",
        "real_path" : "/usr/lib"
      },
      "/usr/lib/arm-linux-gnueabihf",
      "/usr/lib"
    ]
  },
  "version" : "arm-linux-gnueabihf-gcc (Debian 12.2.0-14) 12.2.0"
}

Displaying search dirs of CLang cross-compiler

cmake -P cmake/gcc-search-dirs.cmake armv6-unknown-linux-gnueabihf
{
  "search_dirs" : 
  {
    "libraries" : 
    [
      "/usr/lib/llvm-19/lib/clang/19",
      {
        "path" : "/home/vscode/sysroot/lib",
        "real_path" : "/home/vscode/sysroot/usr/lib"
      },
      "/home/vscode/sysroot/usr/lib"
    ],
    "programs" : "/usr/lib/llvm-19/bin",
    "startup_files" : 
    [
      "/usr/lib/llvm-19/lib/clang/19",
      {
        "path" : "/home/vscode/sysroot/lib",
        "real_path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      },
      {
        "path" : "/home/vscode/sysroot/usr/lib",
        "startup" : [ "libgcc", "libc" ]
      }
    ]
  },
  "sysroot" : "/home/vscode/sysroot",
  "version" : "Debian clang version 19.0.0 (++20240520105323+9f62775038b9-1~exp1~20240520225459.725)"
}