7 USING THE LINKER

This chapter contains the following sections:

Introduction

Linking Process
Phase 1: Linking
Phase 2: Locating
Linker Optimizations

Calling the Linker

Linking with Libraries
How the Linker Searches Libraries
Specifying Libraries to the Linker
How the Linker Extracts Objects from the LibraryLibraries

Incremental Linking

Controlling the Linker with a Script
Purpose of the Linker Script Language
EDE and LSL
Structure of a Linker Script File
The Architecture Definition: Self-Designd Cores
The Derivative Definition: Self-Designd Processors
The Memory Definition: Defining External Memory
The Section Layout Definition: Locating Sections
The Processor Definition: Using Multi-Processor Systems

Linker Labels

Generating a Map File

Linker Error Messages

7.1 Introduction

The linker ltc is a combined linker/locator. The linker phase combines relocatable object files (.o files, generated by the assembler), and libraries into a single relocatable linker object file (.out). The locator phase assigns absolute addresses to the linker object file and creates an absolute object file which you can load into a target processor. From this point the term linker is used for the combined linker/locator.

The linker takes the following files for input and output:

Figure 7-1: ltc Linker

This chapter first describes the linking process. Then it describes how to call the linker and how to use its options. An extensive list of all options and their descriptions is included in section 4.3 , Linker Options, of the Reference Guide.

To gain even more control over the link process, you can write a script for the linker. This chapter shortly describes the purpose and basic principles of the Linker Script Language (LSL) on the basis of an example. A complete description of the LSL is included in Chapter 7 , Linker Script Language, of the Reference Guide.

Finally, a few important features are described such as overlaying and choosing among various output formats.

7.2 Linking Process

The linker combines and transforms relocatable object files (.o) into a single absolute object file. This process consists of two phases: the linking phase and the locating phase.

In the first phase the linker combines the supplied relocatable object files and libraries into a single relocatable object file. In the second phase, the linker assigns absolute addresses to the object file so it can actually be loaded into a target.

Glossary of terms

Term Definition
Absolute object file Object code in which addresses have fixed absolute values, ready to load into a target.
Address A specification of a location in an address space.
Address space The set of possible addresses in a given space. A core can support multiple spaces, for example in a Harvard architecture the addresses that identify the location of an instruction refer to code space, whereas addresses that identify the location of a data object refer to a data space.
Architecture A description of the characteristics of a core that are of interest for the linker. This encompasses the logical address space(s) and the internal bus structure. Given this information the linker can convert logical addresses into physical addresses.
Copy table A section created by the linker. This section contains data that specifies how the startup code initializes the data and BSS sections. For each section the copy table contains the following fields:
- action: defines whether a section is copied or zeroed
- destination: defines the section's address in RAM.
- source: defines the sections address in ROM,
zero for BSS sections
- length: defines the size of the section in MAUs
Core An instance of one or more core architectures.
Derivative The design of a processor. A description of one or more core architectures including internal memory and any number of buses.
Library Collection of relocatable object files. Usually each object file in a library contains one symbol definition
(for example, a function).
Logical address An address as encoded in an instruction word, an address generated by a core (CPU).
LSL file The set of linker script files that are passed to the linker.
MAU Minimum Addressable Unit. For a given processor the amount of memory loaded between an address and the next address. This is not necessarily a byte or a word.
Object code The binary machine language representation of the C source.
Physical address An addresses generated by the memory system.
Processor An instance of one or more derivatives. Usually implemented as a (custom) chip, but can also be implemented on an FPGA, in which case the derivative can be designed by the developer.
Relocatable object file Object code in which addresses are represented by symbols and thus relocatable.
Relocation The process of assigning absolute addresses.
Relocation information Information about how the linker must modify the machine code instructions when it relocates addresses.
Section A group of instructions and/or data objects that occupy a contiguous range of addresses.
Section attributes Attributes that define how the section should be linked or located.
Target The hardware board on which an application is executing. A board contains at least one processor. However, a complex target may contain multiple processors and external memory and may be shared between processors.
Unresolved reference A reference to a symbol for which the linker did not find a definition yet.

Table 7-1: Glossary of terms

7.2.1 Phase 1: Linking

The linker takes one or more relocatable object files and/or libraries as input. A relocatable object file, as generated by the assembler, contains the following information:

The linker's first task is to resolve the external references between the supplied relocatable object files and/or libraries. Its second task is to combine the supplied relocatable object files into a single relocatable linker object file.

The linker starts its task by scanning all specified relocatable object files and libraries. If the linker encounters an unresolved symbol, it remembers its name and continues scanning. The symbol may be defined elsewhere in the same file, or in one of the other files or libraries that you specified to the linker. If the symbol is defined in a library, the linker extracts the object file with the symbol definition from the library. This way the linker collects all definitions and references of all of the symbols.

With this information, the linker combines the object code of all relocatable object files. The linker combines sections with the same section name and attributes into single sections, starting each section at address zero. The linker also substitutes (external) symbol references by (relocatable) numerical addresses where possible. At the end of the linking phase, the linker either writes the results to a file (a single relocatable object file) or keeps the results in memory for further processing during the locating phase.

The resulting file of the linking phase is a single relocatable object file (.out). If this file contains unresolved references, you can link this file with other relocatable object files (.o) or libraries (.a) to resolve the remaining unresolved references.

With the linker command line option --link-only, you can tell the linker to only perform this linking phase and skip the locating phase. The linker complains if any unresolved references are left.

7.2.2 Phase 2: Locating

In the locating phase, the linker assigns absolute addresses to the object code, placing each section in a specific part of the target memory. The linker also replaces references to symbols by the actual address of those symbols. The resulting file is an absolute object file which you can actually load into a target memory. Optionally, when the resulting file should be loaded into a ROM device the linker creates a so-called copy table section which is used by the startup code to initialize the data and BSS sections.

Code modification

When the linker assigns absolute addresses to the object code, it needs to modify this code according to certain rules or relocation expressions to reflect the new addresses. These relocation expressions are stored in the relocatable object file. Consider the following snippet of x86 code that moves the contents of variable a to variable b via the eax register:

Now assume that the linker links this code so that the section in which a is located is relocated by 0x10000 bytes, and b turns out to be at 0x9A12. The linker modifies the code to be:

These adjustments affect instructions, but keep in mind that any pointers in the data part of a relocatable object file have to be modified as well.

The linker can produce its output in different file formats. The default ELF/DWARF2 format (.elf) contains an image of the executable code and data, and can contain additional debug information. The Intel-Hex format (.hex) and Motorola S-record format (.sre) only contain an image of the executable code and data. You can specify a format with the options -F (--format) and -c (--chip-format).

Via a so-called linker script file you can gain complete control over the linker. The script language used to describe these features is called the Linker Script Language (LSL). You can define:

Instead of writing your own linker script file, you can use the standard linker script files with architecture descriptions for the TriCore.

See also section 7.6 , Controlling the Linker with a Script.

7.2.3 Linker Optimizations

During the linking and locating phase, the linker looks for opportunities to optimize the object code. Both code size and execution speed can be optimized. To enable or disable optimizations:

1. From the Project menu, select Project Options...

2. Expand the Linker entry and select Optimization.

You can enable or disable the optimizations described below. The command line option for each optimization is given in brackets.

See also option -O (--optimize) in section 4.3, Linker Options, in Chapter Tool Options of the TriCore Reference Guide.

First fit decreasing (option -Ol/-OL)

When the physical memory is fragmented or when address spaces are nested it may be possible that a given application cannot be located although the size of available physical memory is larger than the sum of the section sizes. Enable the first-fit-decreasing optimization when this occurs and re-link your application.

The linker's default behavior is to place sections in the order that is specified in the LSL file. This also applies to sections within an unrestricted group. If a memory range is partially filled and a section must be located that is larger than the remainder of this range, then the section and all subsequent sections are placed in a next memory range. As a result of this gaps occur at the end of a memory range.

When the first-fit-decreasing optimization is enabled the linker will first place the largest sections in the smallest memory ranges that can contain the section. Small sections are located last and can likely fit in the remaining gaps.

Copy table compression (option -Ot/-OT)

The startup code initializes the application's data and BSS areas. The information about which memory addresses should be zeroed (bss) and which memory ranges should be copied from ROM to RAM is stored in the copy table.

When this optimization is enabled the linker will try to locate sections in such a way that the copy table is as small as possible thereby reducing the application's ROM image.

7.3 Calling the Linker

EDE uses a makefile to build your entire project. This means that you cannot run only the linker. However, you can set options specific for the linker. After you have build your project, the output files of the linking step are available in your project directory.

To link your program, click either one of the following buttons:

Builds your entire project but only updates files that are out-of-date or have been changed since the previous build, which saves time.

Builds your entire project unconditionally. All steps necessary to obtain the final .elf file are performed.

To get access to the linker options:

1. From the Project menu, select Project Options...

2. Expand the Linker entry. Select the subentries and set the options in the various pages.

The following linker options are available:

EDE options Command line
Output Format
Output formats -Fformat -cformat[:addr_size]
Script File
Select linker script file -dfile
Map File
Generate a map file (.map) -M
Suboptions for the Generate a map file option -mflags
Libraries
Link default C libraries
Use non-trapping floating point library
Use trapping floating point library
-lx
-lfp
-lfpt
Rescan libraries to solve unresolved exernals --no-rescan
Libraries library files
Optimization
Use a 'first fit decreasing' algorithm
Emit smart restrictions to reduce copy table size
-Ol/-OL (= on/off)
-Ot/-OT
Warnings
Report all warnings
Suppress all warnings
Suppress specific warnings
no option -w
-w
-wnum[,num]...
Treat warnings as errors --warnings-as-errors
Miscellaneous
Include symbolic debug information -S (strip debug)
Print the name of each file as it is processed -v
Link case sensitive (required for C language) --case-sensitive
Dump processor and memory info from LSL file --lsl-dump[=file]
Additional command line options options

Table 7-2: Linker options

The following options are only available on the command line:

Description Command line
Display invocation syntax -?
Define preprocessor macro -Dmacro[=def ]
Show description of diagnostic(s) --diag=[fmt:]{all|nr,...}
Specify a symbol as unresolved external -esymbol
Redirect errors to a file with extension .elk --error-file[=file]
Read options from file -f file
Scan libraries in given order --first-library-first
Search only in -L directories, not in default path --ignore-default-
library-path
Keep output files after errors -k
Link only, do not locate --link-only
Check LSL file(s) and exit --lsl-check
Do not generate ROM copy -N
Locate all ROM sections in RAM --non-romable
Name of the resulting output file -o file
Link incrementally -r
Display version header only -V

Table 7-3: Linker command line options

The invocation syntax on the command line is:

When you are linking multiple files (either relocatable object files (.o) or libraries (.a), it is important to specify the files in the right order. This is explained in Section 7.4.1, Specifying Libraries to the Linker

For a complete overview of all options with extensive description, see section 4.3, Linker Options, of the Reference Guide.

7.4 Linking with Libraries

There are two kinds of libraries: system libraries and user libraries.

System library

The system libraries are installed in subdirectories of the c:\ctc\lib directory. An overview of the system libraries is given in the following table.

Library to link Description
libc.a C library
(With full printf/scanf functionality. Some functions require the floating point library. Also includes the startup code.)
libcs.a C library single precision (compiler option -F)
(With full printf/scanf functionality. Some functions require the floating point library. Also includes the startup code.)
libcs_fpu.a C library single precision with FPU instructions (compiler option -F and --fpu-present)
libfp.a Floating point library (non-trapping)
libfpt.a Floating point library (trapping)
(Control program option -fptrap)
libfp_fpu.a Floating point library (non-trapping, with FPU instructions)
(Compiler option --fpu-present)
libfpt_fpu.a Floating point library (trapping, with FPU instructions)
(Control program option -fptrap, compiler option --fpu-present)
librt.a Run-time library

Table 7-4: Overview of libraries

For more information on these libraries see section 3.12, Libraries, in Chapter TriCore C Language.

When you want to link system libraries, you must specify this with the option -l. With the option -lc you specify the system library libc.a.

User library

You can also create your own libraries. Section 8.4 , Archiver, in Chapter Using the Utilities, describes how you can use the archiver to create your own library with object modules. To link user libraries, specify their filenames on the command line.

7.4.1 Specifying Libraries to the Linker

In EDE you can specify both system and user libraries.

Link a system library with EDE

To specify to link the default C libraries:

1. From the Project menu, select Project Options...

2. Expand the Linker entry and select Libraries.

3. Select Link default C libraries.

4. Select a floating-point library: non-trapping or trapping.

5. Click OK to accept the linker options.

The invocation syntax on the command line is for example:

Link a user library in EDE

To specify your own libraries:

1. From the Project menu, select Project Options...

2. Expand the Linker entry and select Libraries.

3. Add your libraries to the Libraries field and click OK to accept the linker options.

The invocation syntax on the command line is for example:

If the library resides in a subdirectory, specify that directory with the library name:

Library order

The order in which libraries appear on the command line is important. By default the linker processes object files and libraries in the order in which they appear at the command line. With the option --first-library-first you can tell the linker to scan the libraries from left to right, and extract symbols from the first library where the linker finds it.

Example:

If the file test.o calls a function which is both present in a.a and b.a, normally the function in b.a would be extracted. With this option the linker first tries to extract the symbol from the first library a.a.

7.4.2 How the Linker Searches Libraries

System libraries

You can specify the location of system libraries (specified with option -l) in several ways. The linker searches the specified locations in the following order:

1. The linker first looks in the directories that are specified in the Directories dialog (-L option). If you specify the -L option without a pathname, the linker stops searching after this step.

2. When the linker did not find the library (because it is not in the specified library directory or because no directory is specified), it looks which paths were set during installation. You can still change these paths if you like.

See environment variables LIBTC1V1_2, LIBTC1V1_3 and LIBTC2 in section 1.3.2, Configuring the Command Line Environment, in Chapter Software Installation.

3. When the linker did not find the library, it tries the default ctc\lib directory which was created during installation (or a processor specific sub-directory).

User library

If you use your own library, the linker searches the library in the current directory only.

7.4.3 How the Linker Extracts Objects from Libraries

A library built with artc always contains an index part at the beginning of the library. The linker scans this index while searching for unresolved externals. However, to keep the index as small as possible, only the defined symbols of the library members are recorded in this area.

When the linker finds a symbol that matches an unresolved external, the corresponding object file is extracted from the library and is processed. After processing the object file, the remaining library index is searched. If after a complete search unresolved externals are introduced, the library index will be scanned again.

The -v option shows how libraries have been searched and which objects have been extracted.

Resolving symbols

If you are linking from libraries, only the objects that contain symbol definition(s) to which you refer, are extracted from the library. This implies that if you invoke the linker like:

nothing is linked and no output file will be produced, because there are no unresolved symbols when the linker searches through mylib.a.

It is possible to force a symbol as external (unresolved symbol) with the option -e:

In this case the linker searches for the symbol main in the library and (if found) extracts the object that contains main. If this module contains new unresolved symbols, the linker looks again in mylib.a. This process repeats until no new unresolved symbols are found.

7.5 Incremental Linking

With the TriCore linker ltc it is possible to link incrementally. Incremental linking means that you link some, but not all .o modules to a relocatable object file .out. In this case the linker does not perform the locating phase. With the second invocation, you specify both new .o files and the .out file you had created with the first invocation.

Incremental linking is only possible on the command line.

This links the file test1.o and generates the file test.out. This file is used again and linked together with test2.o to create the file task1.elf (the default name if no output filename is given in the default ELF/DWARF 2 format).

With incremental linking it is normal to have unresolved references in the output file until all .o files are linked and the final .out or .elf file has been reached. The option -r for incremental linking also suppresses warnings and errors because of unresolved symbols.

7.6 Controlling the Linker with a Script

With EDE or the options on the command line you can control the linker to a certain degree. However, when you exactly want to determine where your sections will be located, how much memory is available, which sorts of memory are available, and so on, you can write a script.

The language for the script is called the Linker Script Language, or shortly LSL. You can specify the script file to the linker, which reads it and locates your application exactly as defined in the script. If you do not specify your own script file, the linker always reads a standard script file which is supplied with the toolchain.

7.6.1 Purpose of the Linker Script Language

The Linker Script Language (LSL) serves three purposes:

1. It provides the linker with a definition of the target's core architecture and its internal memory (this is called the derivative). These definitions are written by Altium and supplied with the toolchain.

2. It provides the linker with a specification of the external memory attached to the target processor. The template extmem.lsl is supplied with the toolchain.

3. It provides the linker with information on how your application should be located in memory. This gives you, for example, the possibility to create overlaying sections.

The linker accepts multiple LSL files. You can use the specifications of the TriCore architectures and derivatives that Altium has supplied in the include.lsl directory. Do not change these files.

If you attached external memory to a derivative you must specify this in a separate LSL file and pass both the LSL file that describes the derivative's architecture and your LSL file that contains the memory specification to the linker. Next you may also want to specify how sections should be located and overlaid.

LSL has its own syntax. In addition, you can use the standard ANSI C preprocessor keywords because the linker sends the script file first to the C preprocessor before it starts interpreting the script.

The complete syntax is described in Chapter 7, Linker Script Language, in the Reference Guide.

7.6.2 EDE and LSL

In EDE you can specify the size of the stack and heap; the physical memory attached to the processor; identify that particular address ranges are reserved; and specify which sections are located where in memory. EDE translates your input into an LSL file that is stored in the project directory under the name project.lsl and passes this file to the linker.

If you want to learn more about LSL you can inspect the generated file project.lsl. To change the LSL settings:

1. From the Project menu, select Project Options...

2. Expand the Linker entry and select Script File.

3. Make your changes.

Each time you close the Project Options dialog the file project.lsl is updated and you can immediately see how your settings are encoded in LSL.

Note that EDE supports ChromaCoding (applying color coding to text) and template expansion when you edit LSL files.

7.6.3 Structure of a Linker Script File

A script file consists of several definitions. The definitions can appear in any order.

The architecture definition (required)

In essence an architecture definition describes how the linker should convert virtual addresses into physical addresses for a given type of core. If the core supports multiple address spaces, then for each space the linker must know how to perform this conversion. In this context a physical address is an offset on a given internal or external bus. Additionally the architecture definition contains information about items such as the (hardware) stack and the interrupt vector table.

This specification is normally written by Altium. For each TriCore core architecture, a separate LSL file is provided. These are tc1v1_2.lsl, tc1v1_3.lsl, and tc2.lsl.

The architecture definition of the LSL file should not be changed by you unless you also modify the core's hardware architecture. If the LSL file describes a multi-core system an architecture definition must be available for each different type of core.

The derivative definition (required)

The derivative definition describes the configuration of the internal (on-chip) bus and memory system. Basically it tells the linker how to convert offsets on the busses specified in the architecture definition into offsets in internal memory. A derivative definition must be present in an LSL file. Microcontrollers and DSPs often have internal memory and I/O sub-systems apart from one or more cores. The design of such a chip is called a derivative.

Altium provides LSL descriptions of supported derivatives, along with "SFR files", which provide easy access to registers in I/O sub-systems from C and assembly programs. When you build an ASIC or use a derivative that is not (yet) supported by the TASKING tools, you may have to write a derivative definition.

The processor definition

The processor definition describes an instance of a derivative. Typically the processor definition instantiates one derivative only (single-core processor). A processor that contains multiple cores having the same (homogeneous) or different (heterogeneous) architecture can also be described by instantiating multiple derivatives of the same or different types in separate processor definitions.

If for a derivative 'A' no processor is defined in the LSL file, the linker automatically creates a processor named 'A' of derivative 'A'. This is why for single-processor applications it is enough to specify the derivative in the LSL file, for example with -dtc1920a.lsl.

The memory and bus definitions (optional)

Memory and bus definition are used within the context of a derivative definition to specify internal memory and on-chip busses. In the context of a board specification the memory and bus definitions are used to define external (off-chip) memory and busses. Given the above definitions the linker can convert a logical address into an offset into an on-chip or off-chip memory device.

The board specification

The processor definition and memory and bus definitions together form a board specification. LSL provides language constructs to easily describe single-core and heterogeneous or homogeneous multi-core systems. The board specification describes all characteristics of your target board's system busses, memory devices, I/O sub-systems, and cores that are of interest to the linker. Based on the information provided in the board specification the linker can for each core:

The section layout definition (optional)

The optional section layout definition enables you to exactly control where input sections are located. Features are provided such as: the ability to place sections at a given load-address or run-time address, to place sections in a given order, and to overlay code and/or data sections.

Example: Skeleton of a Linker Script File

A linker script file that defines a derivative "X'" based on the TC1V1.3 architecture, its external memory and how sections are located in memory, may have the following skeleton:

7.6.4 The Architecture Definition: Self-Designed Cores

Although you will probably not need to program the architecture definition (unless you are building your own processor core) it helps to understand the Linker Script Language and how the definitions are interrelated.

Within an architecture definition the characteristics of a target processor core that are important for the linking process are defined. These include:

Address spaces

A logical address space is a memory range for which the core has a separate way to encode an address into instructions. For example, the Tricore's 32-bit linear address space encloses 16 24-bit sub-spaces and 16 14-bit sub-spaces. See also the Tricore Architecture Manual sections "Memory Model" and "Addressing Model".

Most microcontrollers and DSPs support multiple address spaces. An address space is a range of addresses starting from zero. Normally, the size of an address space is to 2N, with N the number of bits used to encode the addresses.

The relation of an address space with another address space can be one of the following:

Address spaces (even nested) can have different minimal addressable units (MAU), alignment restrictions, and page sizes.

The TriCore architecture in LSL notation

The best way to program the architecture definition, is to start with a drawing. The following figure shows a part of the TriCore architecture:

Figure 7-2: Scheme of (part of) the TriCore architecture

The figure shows three address spaces called linear, abs24 and pcp_code. The address space abs24 is a subset of the address space linear. All address spaces have attributes like a number that identifies the logical space (id), a MAU and an alignment. In LSL notation the definition of these address spaces looks as follows:

The keyword map corresponds with the arrows in the drawing. You can map:

Next the two internal busses, named fpi_bus and pcp_code_bus must be defined in LSL:

This completes the LSL code in the architecture definition. Note that all code above goes into the architecture definition, thus between:

architecture TC1V1.3
{
All code above goes here.
}

7.6.5 The Derivative Definition: Self-Designed Processors

Although you will probably not need to program the derivative definition (unless you are building your own processor) it helps to understand the Linker Script Language and how the definitions are interrelated.

A derivative is the design of a processor, as implemented on a chip. It can be an ASIC or a generic design and comprises one or more cores and on-chip memory. The derivative definition includes:

Core

Each derivative must have a specification of its core architecture in LSL:

Bus

Each derivative must contain a bus definition for connecting external memory. In this example, the bus fpi_bus maps to the bus fpi_bus defined in the architecture definition of core tc:

Memory

Figure 7-3: Internal memory definition for a derivative

According to the drawing, the TriCore contains internal memory called pcode with a size 0x04000 (16k). This is physical memory which is mapped to the internal bus pcp_code_bus and to the fpi_bus, so both the tc unit and the pcp can access the memory:

This completes the LSL code in the derivative definition. Note that all code above goes into the derivative definition, thus between:

derivative X // name of derivative
{
All code above goes here.
}

If you want to create a custom derivative and you want to use EDE to select sections, the core of the derivative must be called "tc", since EDE uses this name in the generated LSL file. If you want to specify external memory in EDE, the custom derivative must contain a bus named "fpi_bus" for the same reason. In EDE you have to define a target processor as specified in section 5.5 , Specifying a Target Processor, in Chapter Using the Compiler.

7.6.6 The Memory Definition: Defining External Memory

Once the processor is defined in LSL, you may want to extend the processor with external (or off-chip) memory. You need to specify the location and size of the physical external memory devices in the target system.

The principle is the same as defining the core's architecture but now you need to fill the memory definition:

Figure 7-4: Adding external memory to the TriCore architecture

Suppose your embedded system has 16k of external ROM, named code_rom and 2k of external NVRAM, named my_nvsram. (See figure above.) Both memories are connected to the bus fpi_bus. In LSL this looks like follows:

The memory my_nvsram is connected to the bus with an offset of 0xc0000000:

7.6.7 The Section Layout Definition: Locating Sections

Once you have defined the internal core architecture and optional external memory, you can actually define where your application must be located in the physical memory.

During compilation, the compiler divides the application into sections. Sections have a name, an indication in which address space it should be located and attributes like writable or read-only.

In the section layout definition you can exactly define how input sections are placed in address spaces, relative to each other, and what their absolute run-time and load-time addresses will be. To illustrate section placement the following example of a C program is used:

Example: section propagation through the toolchain

To illustrate section placement, the following example of a C program (bat.c) is used. The program prints the number of times it has been executed.

The compiler assigns names and attributes to sections. With the #pragma section all "name" the compiler's default section naming convention is overruled and a section with the name non_volatile is defined. In this section the battery back-upped data is stored.

By default the compiler creates the section .zbss.bat. uninitialized_data to store uninitialized data objects. The section prefix ".zbss" tells the linker to locate the section in address space abs18 and that the section content should be filled with zeros at startup.

As a result of the #pragma section all "non_volatile", the data objects between the pragma pair are placed in .zbss.non_volatile. Note that ".zbss" sections are cleared at startup. However, battery back-upped sections should not be cleared and therefore we will change this section attribute using the LSL.

The generated assembly may look like:

Section placement

The number of invocations of the example program should be saved in non-volatile (battery back-upped) memory. This is the memory my_nvsram from the example in the previous section.

To control the locating of sections, you need to write one or more section definitions in the LSL file. At least one for each address space where you want to change the default behavior of the linker. In our example, we need to locate sections in the address space abs18:

To locate sections, you must create a group in which you select sections from your program. For the battery back-up example, we need to define one group, which contains the section .zbss_non_volatile. All other sections are located using the defaults specified in the architecture
definition. Section .zbss_non_volatile should be placed in non-volatile ram. To achieve this, the run address refers to our non-volatile memory called my_nvsram. Furthermore, the section should not be cleared and therefore the attribute s (scratch) is assigned to the group:

This completes the LSL file for the sample architecture and sample program. You can now call the linker with this file and the sample program to obtain an application that works for this architecture.

For a complete description of the Linker Script Language, refer to Chapter 7, Linker Script Language, in the Reference Guide.

7.6.8 The Processor Definition: Using Multi-Processor Systems

The processor definition is only needed when you write an LSL-file for a multi-processor embedded system. In the processor definition you can instantiate one or more cores and couple them to one of the architectures as defined in the architecture definition.

7.7 Linker Labels

The linker creates labels that you can use to refer to from within the application software. Some of these labels are real labels at the beginning or the end of a section. Other labels have a second function, these labels are used to address generated data in the locating phase. The data is only generated if the label is used.

Linker labels are labels starting with _lc_. The linker assigns addresses to the following labels when they are referenced:

Label Description
_lc_cp Start of copy table. Same as _lc_ub_table. The copy table gives the source and destination addresses of sections to be copied. This table will be generated by the linker only if this label is used.
_lc_bh Begin of heap. Same as _lc_ub_heap.
_lc_eh End of heap. Same as _lc_ue_heap.
_lc_u_name User defined label. The label must be defined in the LSL file. For example, "_lc_u_int_tab" = (INTTAB);
_lc_ub_name _lc_b_name Begin of section name. Also used to mark the begin of the stack or heap or copy table.
_lc_ue_name _lc_e_name End of section name. Also used to mark the begin of the stack or heap.
_lc_cb_name Start address of an overlay section in ROM.
_lc_ce_name End address of an overlay section in ROM.
_lc_gb_name Begin of group name. This label appears in the output file even if no reference to the label exist in the input file.
_lc_ge_name End of group name. This label appears in the output file even if no reference to the label exist in the input file.

Table 7-5: Linker labels

The linker only allocates space for the stack and/or heap when a reference to either of the section labels exists in one of the input object files.

Example

Suppose in an LSL you have defined a user stack section with the name "ustack" (with the keyword stack). You can refer to the begin and end of the stack from your C source as follows:

From assembly you can refer to the end of the user stack with:

7.8 Generating a Map File

The map file is an additional output file that contains information about the location of sections and symbols. With the options in the Map File page of the Linker entry in the Project Options dialog you choose to generate a map file or to skip it (-M option). You can also customize the type of information that should be included in the map file (-m option).

See section 5.2 , Section 5.1, Linker Map File Format, in Chapter List File Formats of the Reference Guide for an explanation of the format of the map file.

Linker option -M (Generate map file)

Linker option -m (Map file formatting options)

Example:

With this command the list file test.map is created.

7.9 Linker Error Messages

The linker produces error messages of the following types:

F Fatal errors

After a fatal error the linker immediately aborts the link/locate process.

E Errors

Errors are reported, but the linker continues linking and locating. No output files are produced unless you have set the linker option --keep-output-files.

W Warnings

Warning messages do not result into an erroneous output file. They are meant to draw your attention to assumptions of the linker for a situation which may not be correct. You can control warnings in the Linker | Warnings page of the Project | Project Options... menu (linker option -w ).

I Information

Verbose information messages do not indicate an error but tell something about a process or the state of the linker. To see verbose information, use the linker option -v.

S System errors

System errors occur when internal consistency checks fail and should never occur. When you still receive the system error message

please report the error number and as many details as possible about the context in which the error occurred. The following helps you to prepare an e-mail using EDE:

1. From the Help menu, select Technical Support -> Prepare Email...

2. Fill out the the form. State the error number and attach relevant files.

3. Click the Copy to Email client button to open your email application.

4. Finish the e-mail and send it.

Display detailed information on diagnostics

1. In the Help menu, enable the option Show Help on Tool Errors.

2. In the Build tab of the Output window, double-click on an error or warning message.

ltc --diag=[format:]{all | number,...}

See linker option --diag in section 4.3, Linker Options in Chapter Tool Options of the TriCore Reference Guide.


Copyright © 2003 Altium BV