ARM Optimizing C/C++ Compiler v16.12.0.STS User's Guide
SPNU151N - REVISED DECEMBER 2016

Linking C/C++ Code

The C/C++ compiler and assembly language tools provide two methods for linking your programs:
  • You can compile individual modules and link them together. This method is especially useful when you have multiple source files.
  • You can compile and link in one step. This method is useful when you have a single source module.

This chapter describes how to invoke the linker with each method. It also discusses special requirements of linking C/C++ code, including the run-time-support libraries, specifying the type of initialization, and allocating the program into memory. For a complete description of the linker, see the ARM Assembly Language Tools User's Guide.

Invoking the Linker Through the Compiler (-z Option)

This section explains how to invoke the linker after you have compiled and assembled your programs: as a separate step or as part of the compile step.

Invoking the Linker Separately

This is the general syntax for linking C/C++ programs as a separate step:

armcl --run_linker {--rom_model | --ram_model} filenames
[options] [--output_file=name.out] --library=library [lnk.cmd]
armcl --run_linker The command that invokes the linker.
--rom_model | --ram_model Options that tell the linker to use special conventions defined by the C/C++ environment. When you use armcl --run_linker, you must use --rom_model or --ram_model. The --rom_model option uses automatic variable initialization at run time; the --ram_model option uses variable initialization at load time.
filenames Names of object files, linker command files, or archive libraries. The default extension for all input files is .obj; any other extension must be explicitly specified. The linker can determine whether the input file is an object or ASCII file that contains linker commands. The default output filename is a.out, unless you use the --output_file option to name the output file.
options Options affect how the linker handles your object files. Linker options can only appear after the --run_linker option on the command line, but otherwise may be in any order. (Options are discussed in detail in the ARM Assembly Language Tools User's Guide.)
--output_file=name.out Names the output file.
--library=library Identifies the appropriate archive library containing C/C++ run-time-support and floating-point math functions, or linker command files. If you are linking C/C++ code, you must use a run-time-support library. You can use the libraries included with the compiler, or you can create your own run-time-support library. If you have specified a run-time-support library in a linker command file, you do not need this parameter. The --library option's short form is -l.
lnk.cmd Contains options, filenames, directives, or commands for the linker.

When you specify a library as linker input, the linker includes and links only those library members that resolve undefined references. The linker uses a default allocation algorithm to allocate your program into memory. You can use the MEMORY and SECTIONS directives in the linker command file to customize the allocation process. For information, see the ARM Assembly Language Tools User's Guide.

You can link a C/C++ program consisting of object files prog1.obj, prog2.obj, and prog3.obj, with an executable object file filename of prog.out with the command:

armcl --run_linker --rom_model prog1 prog2 prog3 --output_file=prog.out --library=rtsv4_A_be_eabi.lib

Invoking the Linker as Part of the Compile Step

This is the general syntax for linking C/C++ programs as part of the compile step:

armclfilenames [options] --run_linker {--rom_model | --ram_model} filenames
[options] [--output_file=name.out] --library=library [lnk.cmd]

The --run_linker option divides the command line into the compiler options (the options before --run_linker) and the linker options (the options following --run_linker). The --run_linker option must follow all source files and compiler options on the command line.

All arguments that follow --run_linker on the command line are passed to the linker. These arguments can be linker command files, additional object files, linker options, or libraries. These arguments are the same as described in Section 4.1.1.

All arguments that precede --run_linker on the command line are compiler arguments. These arguments can be C/C++ source files, assembly files, or compiler options. These arguments are described in Section 2.2.

You can compile and link a C/C++ program consisting of object files prog1.c, prog2.c, and prog3.c, with an executable object file filename of prog.out with the command:

armcl prog1.c prog2.c prog3.c --run_linker --rom_model --output_file=prog.out --library=rtsv4_A_be_eabi.lib

NOTE

Order of Processing Arguments in the Linker

The order in which the linker processes arguments is important. The compiler passes arguments to the linker in the following order:

  1. Object filenames from the command line
  2. Arguments following the --run_linker option on the command line
  3. Arguments following the --run_linker option from the TI_ARM_C_OPTION environment variable

Disabling the Linker (--compile_only Compiler Option)

You can override the --run_linker option by using the --compile_only compiler option. The -run_linker option's short form is -z and the --compile_only option's short form is -c.

The --compile_only option is especially helpful if you specify the --run_linker option in the TI_ARM_C_OPTION environment variable and want to selectively disable linking with the --compile_only option on the command line.

Linker Code Optimizations

These techniques are used to further optimize your code.

Generate List of Dead Functions (--generate_dead_funcs_list Option)

In order to facilitate the removal of unused code, the linker generates a feedback file containing a list of functions that are never referenced. The feedback file must be used the next time you compile the source files. The syntax for the --generate_dead_funcs_list option is:

--generate_dead_funcs_list= filename

If filename is not specified, a default filename of dead_funcs.txt is used.

Proper creation and use of the feedback file entails the following steps:

  1. Compile all source files using the --gen_func_subsections compiler option. For example:
  2. armcl file1.c file2.c --gen_func_subsections
  3. During the linker, use the --generate_dead_funcs_list option to generate the feedback file based on the generated object files. For example:
  4. armcl --run_linker file1.obj file2.obj --generate_dead_funcs_list=feedback.txt

    Alternatively, you can combine steps 1 and 2 into one step. When you do this, you are not required to specify --gen_func_subsections when compiling the source files as this is done for you automatically. For example:

    armcl file1.c file2.c --run_linker --generate_dead_funcs_list=feedback.txt
  5. Once you have the feedback file, rebuild the source. Give the feedback file to the compiler using the --use_dead_funcs_list option. This option forces each dead function listed in the file into its own subsection. For example:
  6. armcl file1.c file2.c --use_dead_funcs_list=feedback.txt
  7. Invoke the linker with the newly built object files. The linker removes the subsections. For example:
  8. armcl --run_linker file1.obj file2.obj

    Alternatively, you can combine steps 3 and 4 into one step. For example:

    armcl file1.c file2.c --use_dead_funcs_list=feedback.txt --run_linker

NOTE

Dead Functions Feedback

The format of the feedback file generated with --generate_dead_funcs_list is tightly controlled. It must be generated by the linker in order to be processed correctly by the compiler. The format of this file may change over time, so the file contains a version format number to allow backward compatibility.

Generating Aggregate Data Subsections (--gen_data_subsections Compiler Option)

Similarly to code sections described in the previous section, data can either be placed in a single section or multiple sections. The benefit of multiple data sections is that the linker may omit unused data structures from the executable. By default, the --gen_data_subsections option is on. This option causes aggregate data—arrays, structs, and unions—to be placed in separate subsections of the data section.

Controlling the Linking Process

Regardless of the method you choose for invoking the linker, special requirements apply when linking C/C++ programs. You must:

  • Include the compiler's run-time-support library
  • Specify the type of boot-time initialization
  • Determine how you want to allocate your program into memory

This section discusses how these factors are controlled and provides an example of the standard default linker command file. For more information about how to operate the linker, see the linker description in the ARM Assembly Language Tools User's Guide

Including the Run-Time-Support Library

You must link all C/C++ programs with a run-time-support library. The library contains standard C/C++ functions as well as functions used by the compiler to manage the C/C++ environment. The following sections describe two methods for including the run-time-support library.

Automatic Run-Time-Support Library Selection

The linker assumes you are using the C and C++ conventions if either the --rom_model or --ram_model linker option is specified, or if the link step includes the compile step for a C or C++ file, or if you link against the index library libc.a.

If the linker assumes you are using the C and C++ conventions and the entry point for the program (normally c_int00) is not resolved by any specified object file or library, the linker attempts to automatically include the most compatible run-time-support library for your program. The run-time-support library chosen by the compiler is searched after any other libraries specified with the --library option on the command line or in the linker command file. If libc.a is explicitly used, the appropriate run-time-support library is included in the search order where libc.a is specified.

You can disable the automatic selection of a run-time-support library by using the --disable_auto_rts option.

If the --issue_remarks option is specified before the --run_linker option during the linker, a remark is generated indicating which run-time support library was linked in. If a different run-time-support library is desired than the one reported by --issue_remarks, you must specify the name of the desired run-time-support library using the --library option and in your linker command files when necessary.

Example 4-1 Using the --issue_remarks Option

armcl --code_state=16 --issue_remarks main.c --run_linker --rom_model <Linking>remark: linking in "libc.a"remark: linking in "rtsv4_A_be_eabi.lib" in place of "libc.a"

Manual Run-Time-Support Library Selection

You can bypass automatic library selection by explicitly specifying the desired run-time-support library to use. Use the --library linker option to specify the name of the library. The linker will search the path specified by the --search_path option and then the TI_ARM_C_DIR environment variable for the named library. You can use the --library linker option on the command line or in a command file.

armcl --run_linker {--rom_model | --ram_model} filenames --library=libraryname

Library Order for Searching for Symbols

Generally, you should specify the run-time-support library as the last name on the command line because the linker searches libraries for unresolved references in the order that files are specified on the command line. If any object files follow a library, references from those object files to that library are not resolved. You can use the --reread_libs option to force the linker to reread all libraries until references are resolved. Whenever you specify a library as linker input, the linker includes and links only those library members that resolve undefined references.

By default, if a library introduces an unresolved reference and multiple libraries have a definition for it, then the definition from the same library that introduced the unresolved reference is used. Use the --priority option if you want the linker to use the definition from the first library on the command line that contains the definition.

Run-Time Initialization

You must link all C/C++ programs with code to initialize and execute the program called a bootstrap routine. The bootstrap routine is responsible for the following tasks:

  1. Switch to user mode and sets up the user mode stack
  2. Set up status and configuration registers
  3. Set up the stack and secondary system stack
  4. Process special binit copy table, if present.
  5. Process the run-time initialization table to autoinitialize global variables (when using the --rom_model option)
  6. Call all global constructors
  7. Call the main() function
  8. Call exit() when main() returns

NOTE

The _c_int00 Symbol

If you use the --ram_model or --rom_model link option, _c_int00 is automatically defined as the entry point for the program. Otherwise, an entry point is not automatically selected and you will receive a linker warning.

Initialization of Cinit and Watchdog Timer Hold

You can use the --cinit_hold_wdt option to specify whether the watchdog timer should be held (on) or not held (off) during cinit auto-initialization. Setting this option causes an RTS auto-initialization routine to be linked in with the program to handle the desired watchdog timer behavior.

Global Object Constructors

Global C++ variables that have constructors and destructors require their constructors to be called during program initialization and their destructors to be called during program termination. The C++ compiler produces a table of constructors to be called at startup.

Constructors for global objects from a single module are invoked in the order declared in the source code, but the relative order of objects from different object files is unspecified.

Global constructors are called after initialization of other global variables and before the main() function is called. Global destructors are invoked during the exit run-time support function, similar to functions registered through atexit.

Section 6.10.3.6 discusses the format of the global constructor table for EABI mode.

Specifying the Type of Global Variable Initialization

The C/C++ compiler produces data tables for initializing global variables. Section 6.10.3.4 discusses the format of these initialization tables. The initialization tables are used in one of the following ways:

  • Global variables are initialized at run time. Use the --rom_model linker option (see ).
  • Global variables are initialized at load time. Use the --ram_model linker option (see ).

When you link a C/C++ program, you must use either the --rom_model or --ram_model option. These options tell the linker to select initialization at run time or load time. When you compile and link programs, the --rom_model option is the default. If used, the --rom_model option must follow the --run_linker option (see Section 4.1).

For details on linking conventions for EABI used with --rom_model and --ram_model, see Section 6.10.3.3 and Section 6.10.3.5, respectively.

NOTE

Boot Loader

A loader is not included as part of the C/C++ compiler tools. You can use the ARM simulator or emulator with the source debugger as a loader. See the "Program Loading and Running" chapter of the ARM Assembly Language Tools User's Guide for more about boot loading.

Specifying Where to Allocate Sections in Memory

The compiler produces relocatable blocks of code and data. These blocks, called sections, are allocated in memory in a variety of ways to conform to a variety of system configurations. See Section 6.1.1 for a complete description of how the compiler uses these sections.

The compiler creates two basic kinds of sections: initialized and uninitialized. Table 4-1 summarizes the initialized sections. Table 4-2 summarizes the uninitialized sections.

Table 4-1 Initialized Sections Created by the Compiler

Name Contents
.binit Boot time copy tables (See the Assembly Language Tools User's Guide for information on BINIT in linker command files.)
.cinit Tables for explicitly initialized global and static variables.
.const Global and static const variables that are explicitly initialized.
.data Global and static non-const variables that are explicitly initialized.
.init_array Table of constructors to be called at startup.
.text Executable code and constants. Also contains string literals and switch tables. See Section 6.1.1 for exceptions.

Table 4-2 Uninitialized Sections Created by the Compiler

Name Contents
.bss Uninitialized global and static variables
.cio Buffers for stdio functions from the run-time support library
.stack Stack
.sysmem Memory pool (heap) for dynamic memory allocation (malloc, etc)

When you link your program, you must specify where to allocate the sections in memory. In general, initialized sections are linked into ROM or RAM; uninitialized sections are linked into RAM.

The linker provides MEMORY and SECTIONS directives for allocating sections. For more information about allocating sections into memory, see the ARM Assembly Language Tools User's Guide.

A Sample Linker Command File

Example 4-2 shows a typical linker command file that links a 32-bit C program. The command file in this example is named lnk32.cmd and lists several link options:

--rom_model Tells the linker to use autoinitialization at run time
--stack_size Tells the linker to set the C stack size at 0x8000 bytes
--heap_size Tells the linker to set the heap size to 0x2000 bytes

To link the program, use the following syntax:

armcl --run_linker object_file(s) --output_file outfile --map_file mapfile lnk32.cmd

Example 4-2 Linker Command File

--rom_model /* LINK USING C CONVENTIONS */ --stack_size=0x8000 /* SOFTWARE STACK SIZE */ --heap_size=0x2000 /* HEAP AREA SIZE */ /* SPECIFY THE SYSTEM MEMORY MAP */ MEMORY { P_MEM : org = 0x00000000 len = 0x00030000 /* PROGRAM MEMORY (ROM) */ D_MEM : org = 0x00030000 len = 0x00050000 /* DATA MEMORY (RAM) */ } /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */ SECTIONS { .intvecs : {} > 0x0 /* INTERRUPT VECTORS */ .bss : {} > D_MEM /* GLOBAL & STATIC VARS */ .sysmem : {} > D_MEM /* DYNAMIC MEMORY ALLOCATION AREA */ .stack : {} > D_MEM /* SOFTWARE SYSTEM STACK */ .text : {} > P_MEM /* CODE */ .cinit : {} > P_MEM /* INITIALIZATION TABLES */ .const : {} > P_MEM /* CONSTANT DATA */ .pinit : {} > P_MEM /* TEMPLATE INITIALIZATION TABLES */
Back to Top

Submit Documentation Feedback

Copyright© 2016, Texas Instruments Incorporated. An IMPORTANT NOTICE for this document addresses availability, warranty, changes, use in safety-critical applications, intellectual property matters and other important disclaimers.