Linking and Executing Programs This chapter provides information about linking and executing Apex Embedded for Tornado programs.
The following topics are covered in this chapter:
- Linking
- Tornado Information
- Linking in Detail
- Incorporating C/C++ Code Into Your Ada Application
- Importing C++ Functions
- Linking With C Archives
- Executing and Debugging a Program
LinkingWhen the Compile > Link menu item is selected, the link command is automatically constructed and the Rational linker that performs the linking is invoked.
Tornado InformationApex requires information about the Tornado installation in order to perform the following operations:
- Run, debug, or download a program
- Link an application that includes C/C++ code
- Query Tornado for the currently registered targets
- Execute the Tornado launch command
The required information is obtained with two switches in the Policy/Switches file:
By default these switches reference target-specific environment variables. For example, for the PowerPC these switch entries in the Policy/Switches file look like this:
WIND_BASE: <$APEX_WIND_BASE_PPC> WIND_REGISTRY: <$APEX_WIND_REGISTRY_PPC>
The two environment variables are automatically set during apexinit. Their values are determined during product installation.
WIND_BASE is set to a directory in the Tornado product containing three specific subdirectories, host, share, and target.
WIND_REGISTRY is the name of the machine on which the Tornado registry daemon is running.
You can change the values in a particular view by changing the entry in the Policy/Switches file. For example:
WIND_BASE: /vwo/cots/vxworks/tornado_2.0/sol_ppc WIND_REGISTRY: sparky
Linking in DetailSelective Linking
The Apex Embedded linker excludes subprograms from the final executable image if those subprograms cannot be called by the main program. For example, consider package Text_Io, which contains numerous subprograms for performing text input/output operations. If you do not use selective linking when using package Text_Io, all the subprograms contained in the package are linked with your application. Selective linking links only those subprograms from package Text_Io that your application uses.
Continuing with the example, suppose that you are using package Text_Io to display a simple sign-on message. The appropriate line of code looks like this:
text_io.put_line("The Embedded Fribulator Controller");
By using selective linking, your program contains only that portion of package Text_Io required to support the Put_Line function. The remaining subprograms in package Text_Io (Delete, Reset, Set, Set_Input, New_Line, Get, Get_Line, etc.) are eliminated from the executable during the linking process.
The purpose of selective linking is to encourage the construction of general purpose and reusable code. All operations related to a particular function can be grouped together. Because the linker includes only those functions used by an application, you eliminate any size or download penalties normally incurred by having unnecessary functions included.
Selective linking is achieved as follows. The Embedded linker does a transitive closure of the relocation tables, starting with the symbol specified by the Entry option (usually __start). Each object file generated by the Apex compiler is divided into sections: Text for all instructions, Const for read-only data, Data for initialized data that can be written during execution, Bss for uninitialized data areas. The Apex compiler splits each Text, Const, Data and Bss section into subsections. For Text, a subsection is a subprogram but for Const, Data and Bss a subsection is a named data section with an external name. For example, the data sections that have names ending with the suffixes ..Const and ..Static, are all treated as subsections. Externally named objects, exception tables and the tables generated by the linker are all treated as subsections. When the linker performs the transitive closure of the relocation tables, all subsections that are referenced by symbolic relocation are tagged as needed. Any subsection not referenced is removed from the image.
The linker recognizes an Include option to force a reference to a symbol and guarantee that the subsection containing that symbol is included in the executable. This is used for example, if an interrupt handler is loaded at a specific memory address to which the interrupt vector is already pointing. Although the interrupt handler is not referenced by any part of the executable, it must be downloaded to handle interrupts.
Another example of using the Include option is to include debugging routines that print complex data structures and are called from the debugger. Normally, selective linking eliminates these debugger routines because they are not called from the main program but the Include option includes the routines in the image.
The only other option available for selective linking is the No_Optimize option. When specified, No_Optimize turns off selective linking.
The Linker Description File
Note: The linker description file is generated by Apex and normally the object files identified in the OBJECT section are given full path names. Under some circumstances the user may want to identify additional object files that are not included in the Ada closure of their program. A fully rooted pathname may be used to identify these object files in the OBJECTS section, but a relative pathname may also be used. If the pathname begins with "./" then "." is interpreted as the full pathname of the directory containing the generated linker description file. A relative pathname without a leading "./" may also be given; in this case it is interpreted relative to the directory where the Embedded linker is invoked.
The linker description file controls the memory layout of your program and other details of the linking process.
The Linker Description File is located by the prelinker for the main subprogram main_unit.2.ada by first looking for the file main_unit.des. If main_unit.des is not found, the file identified by the LINKER_DESCRIPTION_FILE switch is used.
Normally the LINKER_DESCRIPTION_FILE is defined once for each board configuration and it is not required to supply program unique linker description files.
The Apex prelinker processes the linker description file, translating unit names to object files, and adding all the objects from the Ada closure of the main program. Apex then invokes the Embedded linker with the new description to produce the final executable object.
The linker description file generated by the prelinker resides in .Rational/Compilation and has the same name as the file that contains the main unit with the .ada suffix replaced with .des.
Linker Description File Format
- Syntax
- Names in the Linker Description File
- Options Declaration
- User-Specified Objects Declaration
- Group Declaration
- Void Groups
- Image Groups
- Exception Group
- For Clauses
Syntax
The overall syntax of the linker description file is as follows.
options option [; option...] ; end options; objects object [; object...] ; end objects; group group_id is section [; section...] ; end group; group image_group_id is image group_id; for group_id use [align alignment] at address_spec;
Options, Objects and Group declarations must be made in the order shown in the preceding list. Only one options declaration is allowed, so it must be first. Only one Objects declaration is allowed, it must follow the options declaration. Any of the declarations can be omitted as long as their order is preserved.
Use as many Group declarations and as many For clauses as necessary. Each For clause is associated with a specific Group declaration and must immediately follow that Group declaration, so Group declarations and For clauses can be intermixed in the description file. There is more detail in Options Declaration. For information about including additional files in the link, see User-Specified Objects Declaration.
Names in the Linker Description File
When constructing a description file for linker options, a reserved word must have exactly the letters shown, however the letters can be either lower or upper case.
A meta name standing for an identifier in a syntax description is shown in lower case italics (for example, option, number, symbol_id, etc.).
Processing of all non-keyword identifiers is case sensitive. An identifier begins with a letter and can continue with letters, slashes, dots, underscore and digits.
All numeric values must be specified as unsigned strings of hexadecimal digits (for example 1234, 0FFFF). The first character of a numeric value must be a decimal digit or 0x.
All optional items are shown in square brackets. For example,
[ALIGN number]
indicates optional use of the Alignment clause.
A comment in a description file begins with double hyphens. Just as in Ada, the remainder of the line is ignored. Comments appear anywhere except inside of lexical elements.
Options Declaration
Linker options are specified in the file using an Options declaration. If present, Options must be the first declaration in the file.
options option [; option...] ; end options;
The keywords in an Options declaration are
Each of these is described in more detail in the following sections.
Define
define symbol_id number;
An absolute symbol is declared whose name is symbol_id and whose address is number. The symbol_id is an identifier. The absolute symbol definition overrides any symbol with the same name occurring in an input object file. Use this keyword to override a symbol definition or to provide an explicit definition for an otherwise unresolved reference.
define An_Unresolved_Ref 7cadfee;This example tells the linker to put the symbol An_Unresolved_Ref in the symbol table and give it the absolute address 07cadfee.
Entry
entry entry_id;
This keyword tells the linker the starting symbol, the entry point, of the executable image. The value of entry_id is placed in the VOX header information to inform debuggers and loaders of the starting address. entry_id can be any symbol. If no Entry option is specified, the default starting symbol is __start. For example:
entry My_Start;
This example tells the linker that the address of the symbol My_Start is the entry point of the executable file.
Include
include symbol_id;
This keyword, with symbol_id, ensures that the subsection indicated by symbol_id is linked into the executable, even if it is normally eliminated by selective linking. For example:
include _VME0_isr;
Long_Calls
long_calls;
When a call from one subprogram to another spans more than the maximum offset allowed by the call instruction a link time error message will be emitted. The Long_Calls option may be used to tell the linker to replace the call to the destination subprogram by a call to a generated routine that will load the destination address into a register and jump indirect through the register. On most machines this will take several instructions.
The Tornado environment supports a relocating downloader. In large memory environments it is possible that a downloaded program might be farther than the maximum amount supported by the relocation type for a call. If this happens the download will fail and a message like the following will be generated by the Tornado relocating downloader:
"WTX error 0x10034 (loader relocation offset too large)
For this reason the Long_Calls option is also supported for the linker when generating relocatable objects for Tornado. In this case all calls whose destination is not defined in the relocatable image are assumed to be Long_Calls.
This option is currently supported for PowerPC, and MIPS.
Map
map;
This keyword tells the linker to produce a symbol map. The linker uses the root filename of the executable file but with the suffix .map.
No_Optimize
no_optimize;
By default, the linker removes all object file sections that are not referenced (using external symbol references). The link map lists deleted sections. The No_Optimize keyword suppresses this optimization. If No_Optimize is specified, then sections that are normally deleted are included and fully linked in the resulting executable image.
Relocatable_Program
relocatable_program;
Change the default behavior of the linker so that the resultant object module is left in a relocatable form.
Strip
strip;
Do not include the symbol table or string table in the executable file output by the Embedded linker. The symbol table and string table are not loaded into target memory but are used by the symbolic debugger. Symbolic debugging is not possible if this option is used.
User-Specified Objects Declaration
A user-specified Objects declaration in a linker description file indicates additional object files to include in the link.
The Embedded linker takes as input relocatable object (VOX) files. The syntax for the Objects declaration where object is the filename of an object file is:
objects object [; object...] ; end objects;
Ada object files need not be named explicitly in the Objects declaration. Use Ada unit names in place of object files names. This is the recommended method of specifying objects in the description file. Each Ada unit name is looked up in the view and replaced it with the appropriate object files.
Group Declaration
The Group declaration tells the Embedded linker how the program is loaded into memory. Each Group declaration can have a For clause associated with it that tells the linker where to place that group in memory.
To give context to how the Group declaration works, the following table lists what an object file can contain. Each object file that is input to the Embedded linker can contain the following kinds of sections:
Text machine instructions
Const constant initialized data (read only)
Data initialized data (read/write)
Void uninitialized data
Bss uninitialized data
With the default Group declarations, the linker builds an executable program that contains four groups corresponding to these four sections. The linker does this by collecting together the Text sections from all of the object files into one group of text. The same is true for Const, Data and Bss. This grouping is a natural one because many embedded system applications put the Text and Const into ROM.
The linker provides the user complete control of where each section from each object file is placed in memory.
The syntax for a Group declaration is:
group group_id is section; [section;] end group;
All of the sections that are named are collected in one group and that group is named group_id. Each of the sections in a group must be of the same kind: Text, Const, Data, Void or Bss.
Name a specific section or specific sections in the two forms listed under "Specific Sections."
Name larger collections of sections, called default sections, in the forms listed under "Default Sections".
Specific Sections
- 1 . object_filename'Text
object_filename'Const
object_filename'Data
object_filename'Void
object_filename'BssThis form identifies a specific section of a particular object file. The object_filename must be specified in the Objects declaration and the path name in the Group declaration must be identical to the path name in the Objects declaration.
- 2 . unit_name'Text
unit_name'Const
unit_name'Data
unit_name'Void
unit_name'Bssunit_name must be a unit that is in one of the Apex views on the search path. This form indicates all of the sections of the given type that comprise the unit.
Default Sections
- 3 . archive_name'Text
archive_name'Const
archive_name'Data
archive_name'Void (<size_in_bytes>)
archive_name'BssName objects that are located in the RTS archive or any archive library with the simple object filename. Alternatively, archive_name'section indicates all sections that are brought in from the archive.
- 4 . Text
Const
Data
Void
BssThe Text, Const, Data, Void and Bss sections without prefixes refer to all sections not explicitly named in any other Group directive.
Void Groups
A Void group is an uninitialized data group just like Bss. Void groups are generated by the linker and are used as a placeholder to prevent the linker from allocating another group at the specified address. The only difference between a Void group and a Bss group is that the runtime system does not attempt to zero a Void group. A Void group is generated by the linker for:
- A void group created by a GROUP declaration containing just a VOID section. For example, the following group declaration will leave a 0100 byte hole at 040000:
group VOID_GROUP is void(0100); -- size of group is 0100 bytes. end group; for VOID_GROUP use at 040000;
- The image area associated with a data IMAGE group
Image Groups
Image groups provide a RAM copy of a ROM group. Image groups are designed for two purposes.
- Statically initialized data variables cannot be allocated in ROM because write access can be required.
- Because statically initialized data variables can be modified by execution of a program, the variables must either be dynamically reinitialized or the program must be reloaded before it is rerun.
The initial values of the data variables are placed in one group and an image of the group is allocated and initialized by copying the initial values to the image. For example,
group data_group is --the initial values for all data; --statically initialized variables end group; group data_group_image is image data_group;
The startup routine then copies Data_Group to Data_Group_Image before execution of the program. The Embedded linker ensures that all references to objects and symbols in Data_Group refer to the image.
Exception Group
The Exception group is a constant group built by the linker and contains the compacted exception tables used during exception processing. Its size is not known until all of the other groups in the memory image have been allocated target addresses in the memory image. Normally, the Exception group is placed at the end of the memory image due to this unusual constraint.
If, for some reason, the user wants to put the Exception group somewhere other than the end of the memory image, special actions are required.
- 1 . Link the program to determine the size of the Exception group (__Exception_Group).
- 2 . Allocate a hole in the memory image for the Exception group by modifying the linker description file:
GROUP group_before_execution_group IS ... END GROUP; FOR group_before_execution_group USE AT *;
GROUP group_after_execution_group IS ...END GROUP; FOR group_after_execution_group USE AT *;
- 3 . Insert the Exception group where the hole was allocated:
FOR __EXCEPTION_GROUP USE AT group_before_exception_group'LAST;
For Clauses
The For clause is used to locate a group at a particular memory address or relative to another group. The syntax is
for group_id use [align alignment] at address [..address]
address is either absolute or relative. Absolute addresses are hexadecimal numbers, while relative addresses have the following formats:
* current address
* + number current address plus number
An asterisk indicates the current address relative to previous For clauses. Groups without an accompanying For clause are located in the first free block of memory starting at the origin.
The default alignment is the largest of the alignments of all of the sections in the group. On most RISC targets, the default alignment generated is 8. Examples:
- 1 . for Bss_Group use at 01000;
Locate group Bss_Group at physical address hexadecimal 01000
- 2 . for Bss_Group use at 01000 .. 01FFF;
Locate group Bss_Group at physical address range 01000 .. 01FFF, padding at the end of the group if necessary, up to and including address 01FFF. An error message is generated if the group cannot fit in the specified range. If an address range is specified for a group and the size of the range is larger than the size of the group, null padding is added at the end of the group. The null padding is represented by bytes of zero.
- 3 . for Bss_Group use at * .. * + 0FFF;
Same as example (2), except the starting address of the group is the current address.
- 4 . for Bss_Group use align 01000 at * .. * + 01FFF;
Same as example (3) except starting address for Bss_Group is aligned on a multiple of 01000.
Incorporating C/C++ Code Into Your Ada ApplicationThere are several steps required to incorporate C/C++ code into your Ada application.
- 1 . Create a C/C++ view.
Use File > New > New View to create a C/C++ view.
- 2 . Code your C/C++ view.
Bring your C/C++ code into your new view, and code the view with Compile > Code.
% code .
Note: You cannot call C++ code directly from Ada code. You must provide a C interface to be called from the Ada code.
- 3 . Enable C++ linking in your Ada view.
You need to do this step, even if you're only incorporating C code into your Ada application. From a directory viewer in your Ada view, select Compile > Maintenance > Enable C++ Linking.... This prompts you for a C++ model. Be sure to enter the same model that was used to create your C/C++ view.
- 4 . Import your C/C++ view into your Ada view.
With your view selected in a directory viewer, select Control > Change View Properties. Enter the full path to your C/C++ view into the Add: section of the dialog and click Add. Then click OK or apply.
- 5 . Link your Ada Application
Select Compile > Link and link your Ada application as you normally would.
Importing C++ FunctionsIn C++, You can define the normal C names for a simple C++ function using the syntax:
extern "C" {...}
pragma Import (C, f);
Linking With C ArchivesC programs compiled with the Rational C compiler can be linked with your Ada programs. If they are compiled with the -g option, the Rational debugger is fully functional.
Warning: Compiling a C object with the -g option of a non-Rational compiler has no effect once the object has been converted to VOX format. The symbolics generated by non-Rational C compilers are not of the form used by the Rational debugger and they are discarded during conversion.
However, you can link your Ada program with C archives that have been produced by a non-Rational compiler. Follow these steps:
- 1 . Extract the individual C objects. This produces a list of .o files.
- 2 . Use Tools > Convert to convert each .o file to a VOX format.
- 3 . Use Tools > Shell to get a command window and a.mkvar to produce a new C archive.
apex_compiler_tool/a.mkvar [-cv] archive_file object_file_list
This command produces a VOX archive file and must have a .var extension. The -c (create), the default, and -v (verbose) options are optional.
- 4 . To link with your Ada program, list the archive with the NON_ADA_LINKAGE switch.
Executing and Debugging a ProgramYou can execute a program with the GUI or the command line. With the GUI, select File > Run. With the command line, use the apex_execute command.
You can debug a program with the GUI or the command line. With the GUI, select File > Debug. With the command line, use the apex_debug command.
The apex_execute and apex_debug commands are discussed in detail in the Rational Apex Embedded Command Reference.
Warning: For the current release of this product, passing of parameters to your program is limited. You can pass integer parameters only (no strings) when using apex_execute or File > Run. You can not pass any parameters when using apex_debug or File > Debug or File > Run with the Debug Toggle set. If you wish to debug your program while passing it parameters you should do the following:
If using apex_debug, type the options after r:
>r options
If using File > Debug, start your program's execution by typing the following in the Command window:
r options
Linking and Executing Programs
Apex Embedded for Tornado support Tornado II. Tornado 3.0/VxWorks AE is supported for PowerPC and Intel Architecture only. The APEX_WIND_BASE_{processor} session switch where processor is PPC, INTEL, MIPS or SIXTYEIGHT is used by Apex to identify the installation of the WindRiver Tornado installation. Normally this information is provided during post install and shared by all users.
It is possible for an individual user to override this session switch (like any other session switch) using the Tools > Session > Environment dialog from the directory viewer.
The use of the APEX_WIND_BASE_{processor} switch and the ability to override the default has not changed from previous releases. What is new in 4.0 is the following:
Tornado II versus Tornado 3.0 AE is automatically detected using the file: $WIND_BASE/target/h/version.h
For Tornado II it looks like this:
#define VXWORKS_VERSION "5.4"
For Tornado 3.0 AE it looks like this:
#define RUNTIME_NAME "VxWorks AE" #define RUNTIME_VERSION "1.0 FCS"
VXWORKS_VERSION is not used by Tornado 3.0 AE even though they have retained the define of the variable name.
Apex uses this information to select the appropriate version of the target control tools.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2002, Rational Software Corporation. All rights reserved. |