TMS320C28x Optimizing C/C++ Compiler v15.9.0.STS User's Guide
SPRU514 - REVISED SEPTEMBER, 2015

4 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 TMS320C28x Assembly Language Tools User's Guide.

4.1 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.

4.1.1 Invoking the Linker Separately

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

cl2000 --run_linker {--rom_model | --ram_model} filenames
[options] [--output_file=name.out] --library=library [lnk.cmd]
cl2000 --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 cl2000 --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 TMS320C28x 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 TMS320C28x 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:

cl2000 --run_linker --rom_model prog1 prog2 prog3 --output_file=prog.out --library=rts2800_ml.lib

4.1.2 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:

cl2000filenames [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:

cl2000 prog1.c prog2.c prog3.c --run_linker --rom_model --output_file=prog.out --library=rts2800_ml.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 C2000_C_OPTION environment variable

4.1.3 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 C2000_C_OPTION environment variable and want to selectively disable linking with the --compile_only option on the command line.

4.2 Linker Code Optimizations

4.2.1 Generating Function Subsections (--gen_func_subsections Compiler Option)

The compiler translates a source module into an object file. It may place all of the functions into a single code section, or it may create multiple code sections. The benefit of multiple code sections is that the linker may omit unused functions from the executable.

When the linker collects code to be placed into an executable file, it cannot split code sections. If the compiler did not use multiple code sections, and any function in a particular module needs to be linked into the executable, then all functions in that module are linked in, even if they are not used.

An example is a library .obj file that contains a signed divide routine and an unsigned divide routine. If the application requires only signed division, then only the signed divide routine is required for linking. If only one code section was used, both the signed and unsigned routines are linked in since they exist in the same .obj file.

The --gen_func_subsections compiler option remedies this problem by placing each function in a file in its own subsection. Thus, only the functions that are referenced in the application are linked into the final executable. This can result in an overall code size reduction.

4.3 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 TMS320C28x Assembly Language Tools User's Guide

4.3.1 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.

4.3.1.1 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

cl2000 --issue_remarks main.c --run_linker --rom_model <Linking>remark: linking in "libc.a"remark: linking in "rts2800_ml.lib" in place of "libc.a"
4.3.1.2 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 C2000_C_DIR environment variable for the named library. You can use the --library linker option on the command line or in a command file.

cl2000 --run_linker {--rom_model | --ram_model} filenames --library=libraryname
4.3.1.3 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.

4.3.2 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. Set up status and configuration registers
  2. Set up the stack and secondary system stack
  3. Process the .cinit run-time initialization table to autoinitialize global variables (when using the --rom_model option)
  4. Call all global object constructors (.pinit)
  5. Call the main() function
  6. 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.

4.3.3 Initialization by the Interrupt Vector

If your C/C++ program begins running at RESET, you must set up the RESET vector to branch to a suitable bootstrap routine, such as _c_int00. You must also make sure the interrupt vectors are included in the project, typically by using the --undef_sym linker option to make a symbol at the start of the interrupt vector a root linker object.

A sample interrupt vector is provided in vectors.obj in rts2800_ml.lib. For C28x, the first few lines of the vector are:

.def _Reset .ref _c_int00 _Reset: .vec _c_int00, USE_RETA

4.3.4 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 7.9.2.4 discusses the format of the global constructor table.

4.3.5 Specifying the Type of Global Variable Initialization

The C/C++ compiler produces data tables for initializing global variables. Section 7.9.2.1 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 Section 7.9.2.2).
  • Global variables are initialized at load time. Use the --ram_model linker option (see Section 7.9.2.3).

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). The following list outlines the linking conventions used with --rom_model or --ram_model:

  • The symbol _c_int00 is defined as the program entry point; it identifies the beginning of the C/C++ boot routine in boot.obj. When you use --rom_model or --ram_model, _c_int00 is automatically referenced, ensuring that boot.obj is automatically linked in from the run-time-support library.
  • The initialization output section is padded with a termination record so that the loader (load-time initialization) or the boot routine (run-time initialization) knows when to stop reading the initialization tables.
  • When initializing at load time (the --ram_model option), the following occur:
    • The linker sets the initialization table symbol to -1. This indicates that the initialization tables are not in memory, so no initialization is performed at run time.
    • The STYP_COPY flag is set in the initialization table section header. STYP_COPY is the special attribute that tells the loader to perform autoinitialization directly and not to load the initialization table into memory. The linker does not allocate space in memory for the initialization table.
  • When autoinitializing at run time (--rom_model option), the linker defines the initialization table symbol as the starting address of the initialization table. The boot routine uses this symbol as the starting point for autoinitialization.

4.3.6 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 7.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 Restrictions
.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. Program
.econst Global and static const variables that are explicitly initialized and contain string literals. String literals are placed in the .econst:.string subsection to enable greater link-time placement control. Anywhere in data
.pinit Table of constructors to be called at startup. Program
.switch Jump tables for large switch statements. Program with -mt option
Data without -mt option
.text Executable code and constants. Program

Table 4-2 Uninitialized Sections Created by the Compiler

Name Contents Restrictions
.ebss Global and static variables Anywhere in data
.stack Stack Low 64K
.esysmem Memory for malloc functions (heap) Anywhere in data

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. With the exception of .text, the initialized and uninitialized sections created by the compiler cannot be allocated into internal program memory.

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

4.3.7 A Sample Linker Command File

Example 4-2 shows a typical linker command file that links a C program. The command file in this example is named lnk.cmd. It links three object files (a.obj, b.obj, and c.obj) and creates a program (prog.out) and a map file (prog.map).

To link the program, enter the following:

cl2000 --run_linker lnk.cmd

The MEMORY and possibly the SECTIONS directives, might require modification to work with your system. See the TMS320C28x Assembly Language Tools User's Guide for more information on these directives.

Example 4-2 Linker Command File

a.obj b.obj c.obj /* Input filenames */ --output_file=prog.out /* Options */ --map_file=prog.map --library=rts2800_ml.lib /* Get run-time support */ MEMORY /* MEMORY directive */ { RAM: origin = 100h length = 0100h ROM: origin = 01000h length = 0100h } SECTIONS /* SECTIONS directive */ { .text: > ROM .data: > ROM .ebss: > RAM .pinit: > ROM .cinit: > ROM .switch: > ROM .econst: > RAM .stack: > RAM .esysmem: > RAM

4.4 Linking C28x and C2XLP Code

The error in the C28x linker to prevent linking code with a 64-word page size (C28x) and a 128-word page size (C2XLP) has been changed to a warning. It is possible to call a C2XLP assembly function from C28x C/C++ code. One possible way is to replace the call to the C2XLP function with a veneer function that correctly sets up the arguments and call stack for the C2XLP code. For example, to make a call to a C2XLP function expecting five integer arguments, change the C28x code to:

extern void foo_veneer(int, int, int, int, int); void bar() { /* replace the C2XLP call with a veneer call */ /* foo(1, 2, 3, 4, 5); */ foo_veneer(1, 2, 3, 4, 5); }

Example 4-3 illustrates how the veneer function might look:

Example 4-3 Veneer Function for Linking C2xx and C2XLP Code

.sect ".text" .global _foo_veneer .global _foo _foo_veneer: ;save registers PUSH AR1:AR0 PUSH AR3:AR2 PUSH AR5:AR4 ;set the size of the C2XLP frame (including args size) ADDB SP,#10 ;push args onto the C2XLP frame MOV *-SP[10],AL ;copy arg 1 MOV *-SP[9],AH ;copy arg 2 MOV *-SP[8],AR4 ;copy arg 3 MOV *-SP[7],AR5 ;copy arg 4 MOV AL,*-SP[19] MOV *-SP[6],AL ;copy arg 5 ;save the return address MOV *-SP[5],#_label ;set AR1,ARP MOV AL,SP SUBB AL,#3 MOV AR1,AL NOP *ARP1 ;jump to C2XLP function LB _foo _label: ;restore register POP AR5:AR4 POP AR3:AR2 POP AR1:AR0LRETR

Since the veneer function frame will act as the frame for all C2XLP calls, it is necessary to add sufficient size to the frame for any subsequent calls made by the first C2XLP function.

Global variables will be placed in the .ebss sections for C28x C/C++ code. A C2XLP .ebss section is not guaranteed to begin on a 128-word boundary when linked with C28x code. To avoid this problem, define a new section, change the C2XLP globals to the new section, and update the linker command file to ensure this new section begins at a 128-word boundary.

Submit Documentation Feedback

Copyright© 2015, 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.