Multi Building Applications For Embedded Cmpe490documentsghsbuildarmpdfmulti
Multi Building Applications For Embedded Cmpe490documentsghsbuildarmpdfmulti
Embedded ARM
PubID: 10379
October 24, 2005
Contents
1 Introduction 1
The MULTI Integrated Development Environment 2
The MULTI Launcher 4
MULTI Workspaces 5
The MULTI 4.0 Document Set 6
About This Book 7
The MULTI Builder 8
The C and C++ Compiler Driver 9
The Optimizing Compilers 9
The asarm Assembler 10
The ax Librarian 10
The elxr Linker 11
Optimized Libraries and Header Files 11
Utility Programs 11
The CodeBalance Optimization Wizard 11
ARM Recommended Reading 12
Online Help 13
Viewing Help on Windows Systems 13
Viewing Help on UNIX Systems 14
Conventions Used in This Book 15
Index 683
Introduction
The MULTI IDE includes graphical tools for each part of the software
development process. The following tools can be launched from within the IDE
or as separate stand-alone programs:
• IDE launcher
MULTI Launcher (mstart) — The gateway to the MULTI IDE, which
allows you to quickly launch any of the primary MULTI tools, access
open windows, and manage MULTI workspaces
• Editing tools
MULTI Editor (me) — A graphical editor for modifying text files
Checkout Browser (mcobrowse) — A graphical viewer for files
managed under a version control system
Diff Viewer (diffview) — A graphical viewer that displays differences
between two text files
Hex Editor (mhexedit) — A graphical editor for modifying binary files
• Building tools
MULTI Builder (mbuild) — A graphical interface for managing and
building projects
CodeBalance (codebalance) — A graphical interface for automating the
process of optimizing an executable for size or speed
INTEGRATE (integrate) — A graphical utility for configuring tasks,
connections, and kernel objects across multiple address spaces when
using the INTEGRITY RTOS
Linker Directives File Editor (mldedit) — A graphical editor for
creating and modifying linker directives files
• Debugging tools
MULTI Debugger (multi) — A graphical source-level debugger
EventAnalyzer (mevgui) — A graphical viewer for monitoring
the complex real-time interactions of an embedded RTOS such as
INTEGRITY or ThreadX
ResourceAnalyzer (wperf) — A graphical viewer for monitoring
the CPU and memory usage of an embedded system running the
INTEGRITY RTOS
Script Debugger (mscriptdbg) — A graphical debugger for writing,
recording, and debugging scripts containing MULTI commands
Serial Terminal (mterminal) — A serial terminal emulator for
connecting to serial ports on embedded devices
• Miscellaneous and administrative tools
Bug Report (gbugrpt) — A utility for providing system configuration
and tool version information to the Green Hills support staff
Green Hills Probe Administrator (gpadmin) — A graphical interface
for configuring and managing Green Hills Debug Probes (Slingshots,
Green Hills Probes, and/or SuperTrace Probes)
Graphical Utilities (wgutils) — A collection of utilities for analyzing
and performing various operations on object files, libraries, and
executables produced with the Green Hills toolchain
MULTI License Administrator (mlmadmin) — A graphical utility for
managing Green Hills tools licenses
You can also launch the Green Hills License Administrator and (if installed) the
Green Hills Probe Administrator from the Utilities menu.
MULTI Workspaces
The MULTI Launcher allows you to create and use workspaces. A MULTI
workspace is a virtual area where the tools, files, and actions required for a
particular project can be organized, accessed, and executed.
These books, and any others you may have received (for example, for the
INTEGRITY or ThreadX operating system, or for the Green Hills Debug
Probes) are available in the following formats:
• A printed book
• Online help, accessible from most MULTI windows via the Help →
Manuals menu (see “Online Help” on page 13)
• An electronic PDF, available in the manuals subdirectory of your installation
Note New or updated information may have become available while this
book was in production. For additional material that was not available at press
time, or for revisions that may have become necessary since this book was
printed, please check your CD-ROM for Release Notes, README files, and
other supplementary documentation.
• Part I: Using the MULTI Builder and Compiler Drivers — documents how
to use the MULTI Builder or compiler drivers to control the toolchain.
Includes an introduction to the Builder and compiler drivers, discussions of
commonly-used features of the compiler for your target environment, and
descriptions of all the Builder and driver options.
• Part II: Using Advanced Tools — documents the other elements of the
toolchain — the assembler, linker, librarian, and utility programs.
• Part III: Language Reference — documents the Green Hills implementation
of high level languages, including macros, #pragmas, libraries, headers,
and optimizations.
• creating and organizing high-level and assembly language source files, object
files, libraries, and supplementary files, and for setting file dependencies.
• specifying build options to control how code will be processed by the
toolchain.
• invoking the Green Hills compilers, assembler, linker, and other utilities to
build an executable.
To get started using the Builder, see Chapter 2, “The MULTI Builder”.
To get started using the driver, see Chapter 3, “The Compiler Driver”.
Note The ARM compiler defaults to binary code generation, which allows the
compiler to produce object files directly, without invoking the assembler, and
results in reduced compilation times.
The ax Librarian
The Green Hills librarian, ax, combines object files into a library file.
Libraries can be searched by the linker for object files to resolve external
references. A module from a library is included in a program only if it is
referenced in the program.
The librarian is ordinarily invoked from the Builder or compiler driver (see
“Creating Libraries” on page 72). For information about invoking the librarian
directly, and for a detailed description of its operations, see Chapter 10, “The
ax Librarian”.
During linking, the relocation section of each input file resolves its external text
and data references with files containing the required text and data.
Utility Programs
The Green Hills Utility Programs allow you to analyze and perform various
operations on object files, libraries, and executables produced with the Green
Hills toolchain. For more information, see Chapter 11, “Utility Programs”.
Online Help
The MULTI online help system provides three different types of online help:
If you are using the MULTI Editor, you can also open context-sensitive
help about a button or a menu item by selecting Help → Identify and then
clicking the button or selecting the menu item.
• Debugger command help — You can obtain help information about a
specific MULTI Debugger command by typing help command_name
in the Debugger command pane. This will open the online version of the
MULTI: Debugging book on the section that documents the specified
command. You can also type usage command_name to print to the
command pane the basic syntax of the specified command.
There are two panes in the HTML Help viewer. The right-hand pane displays
the contents of a selected help page. You can click any underlined link that
appears in right-hand pane to jump to pages about other related topics. The
left-hand pane provides the following three navigation tabs:
• Contents — Displays the chapter and section headings for the manual
being viewed. Click a plus or minus icon to show or hide headings for
embedded sections. Click a heading to display the associated help page in
the right-hand pane.
• Index — Displays index entries for the manual. Double-click an index entry
to display its help page in the right-hand pane.
• Search — Provides an interface that allows you to search for specific words
in the manual. Enter a word or phrase in the text box and click List Topics
to display a list of pages related to your search string. Double-click any
entry in the list to display the entry’s help page in the right-hand pane.
The Java Runtime Environment that is included with MULTI has been
configured to use fonts common to most X Window servers. However,
some X Window servers may not display Oracle Help for Java properly. To
configure fonts for the Java Runtime Environment, edit the font.properties
file that is located in the jre/lib directory of your MULTI installation (for
more information, see the Sun Microsystems Java web site).
• Web Browser Help — Displays hypertext version of manuals, including
tables of contents and index entries. In GUI mode, netscape is the default
browser. If netscape is installed on your system and the executable is in
your path, no further configuration should be necessary. In non-GUI mode, a
copy of lynx running inside of an xterm will be used as the default browser.
If you have xterm in your path, no further configuration should be necessary.
For information about using an alternate web browser, see “Using a Custom
Web Browser with UNIX” in Chapter 8, “Configuring and Customizing
MULTI” in the MULTI: Editing Files and Configuring the IDE book.
The square brackets and the ellipsis should not appear in the actual command
you enter.
The MULTI Builder is a graphical tool that organizes your source and other
input files, and controls the tools needed to compile your software project.
The term project is used to encompass all of the files which are used to build
your application. Projects are controlled using Green Hills project files (*.gpj),
which are similar to makefiles, and which maintain file dependencies and set
the options used in building.
• From the MULTI Launcher, click the Builder button ( ) and select either
an existing project or Create Project.
• (Windows) Double-click the MULTI Builder icon.
• Enter multi filename.gpj on the command line if the MULTI Builder is
in your path.
Note This chapter describes the new default interface to the MULTI Builder.
For information about the legacy Builder interface, see MULTI: Legacy
Building Tools.
• Title Bar — Displays the location of the current project. In the screen above,
the project is default.gpj, which is the default project name when you first
run the Builder.
• Menu Bar — For a complete list of all the menu items, see Chapter 6, “The
Builder GUI Reference”.
• Toolbar — The buttons on the Builder toolbar are documented along with
their menu equivalents in Chapter 6, “The Builder GUI Reference”.
• File Shortcut Bar — Allows you to quickly locate or build files and projects.
For more information, see “Using the File Shortcut Bar” on page 63.
• Source Pane — Displays the files and subprojects of the current project. The
name of each file, its type, and any Builder options set in it are shown.
Projects (*.gpj) have a small plus or minus sign to their left, which allows
you to expand or contract their contents.
• Shortcut Menu — You can access the shortcut menu by right-clicking
anywhere in the source pane. This context-sensitive menu allows you to
perform several Builder operations.
• Output Pane — Displays information about the current status of the build
process.
• Status Bar — Displays status information, which includes a description of
the button which the mouse is presently over.
• Target Indicator — Displays the currently selected build target architecture.
To start the Builder from the command line on a specific project file, cd to the
directory where your project files are located, and enter:
multi filename.gpj
where filename is the project file (*.gpj) of your project’s program, subproject,
or library that you want to open. For more information about project files, see
“Working with Project Files” on page 31.
If you start the Builder without specifying any parameters, the Launcher is
started.
On Windows, you can drag and drop a top-level project file (usually called
default.gpj) to a MULTI icon to open it.
The New Project Wizard automatically generates all the project files
necessary to compile an example application. This project can be built,
downloaded to your target or simulator, and opened in the Debugger so that
you can explore many of the features of MULTI.
To get started, see “Creating a New Project: The New Project Wizard”
on page 24.
• Once you have created an example project and are comfortable with the
Builder you can begin adding your own files to the skeleton project structure
generated by the New Project Wizard. For more information about adding
files to your project, and organizing your project structure, see “Working
with Project Files” on page 31.
• You may want to set various Builder options to control exactly how your
project will be built. Builder options are set through the Options window.
For more information, see:
Selecting a Target
Selecting a Project
Note The layout that you choose is the one that will be used during linking,
but the New Project Wizard provides a number of linker directives files (in
subproject resource.gpj), so that you can change the layout conveniently
at later stages of development. For more information, see “Working with
Linker Directives Files” on page 43.
Once you have completed this screen, click Next, and the following screen
will appear:
Once you have completed this screen, click Next. If you have selected a project
that includes both C and C++ code, then the following screen will appear
(otherwise, go to “Setting Optimizations and Run-Time Checks” on page 29):
• which dialect of the C++ language to use. The default is Standard C++.
• how the compiler will process template instantiations. The default is never
to force instantiations.
• if C++ exception handling is enabled. The default is to disable exceptions.
• if the compiler will treat for-loop initialization variables as existing beyond
the end of the loop’s scope. The default is for these variables to go out of
scope at the end of the loop.
• if the compiler will instantiate templates automatically. The default is to
enable this feature.
• if the compiler will implicitly include templates. The default is to enable
this feature.
Once you have completed this screen, click Next, and the following screen
will appear:
• how your project will be optimized. You can instruct the compiler to optimize
generally (making your program both smaller and faster), or specifically for
size or speed. The default is to not perform any optimizations.
• if run-time error checking will be enabled. The default is to disable this
feature.
• if run-time memory checking will be enabled. The default is to disable
this feature
• if performance analysis information (for use with the MULTI Profiler) is
enabled. The default is to disable this feature.
Once you have completed this screen, click Finish, and the New Project
Wizard will exit and return you to the Builder opened on the new project.
• Click the Build button ( ), to build your project. You can follow the
progress of the build in the Output pane at the bottom of the main Builder
window.
• Click the Connect button ( ), to open the Connection Chooser. The New
Project Wizard has created a connection type called:
• Name: the name of each file, and its position in the project hierarchy.
• Type: the type of file, usually determined from its extension.
• Options: the compiler options that are set at this level of the hierarchy.
The Source pane pictured below shows the files generated by the New Project
Wizard for the example project Hello World:
Project files are text files that list program source files, subprojects, and other
files that make up a program or a project. Each source file is listed along with
its type in brackets ([]), if that type cannot be discerned by the Builder from
the file’s extension. Source files and other project file entries can be followed
by the project options used when building that file. Project options appear on
subsequent lines and indented in the project file.
Various special options can only be set in the top-level project file. These
include, but are not limited to, primaryTarget, customization, gbuildDir,
defaultBuildOptions, and macro. These options should only be set or modified
from the Builder, as they are not documented.
• Resource Files:
Linker Directives (.ld, .lnk) — Linker directives file that contains a
memory map for the target board and a section map for the program.
For more information, see “Working with Linker Directives Files” on
page 43.
Board Setup (.mbs,.dbs) — Setup script file for initializing your target
board.
Memory Layout (.mdf) — Memory layout for your target board for
use by the Debugger.
Target Connections (.con) — Target configuration information for
connecting to a simulator or to your board via appropriate debug servers.
Double-click this file to open the Connection Organizer (see Chapter 3,
“Connecting to Your Target” in the MULTI: Debugging book).
Text (.txt) — Generic text files. This type is used by default for
unclassified file extensions.
Header (.h, .hh, .H, .h++, .hxx, .hpp) — C and C++ header files.
Portable Document Format (.pdf) — Adobe PDF files.
Script (.rc) — MULTI command scripts.
You should start by adding a Program project file (*.gpj) for each program in
your project. You may also add other project files. These include Library
projects for building libraries, Subproject projects for conceptually grouping
source files, and even additional Project projects for more complex groupings.
To create a new program which is a direct child of the top-level project (usually
named default.gpj):
The four main types of project file that you may want to create are:
• Program — Create a project file of this type when the source files it will
contain are intended to be compiled into an executable.
• Subproject — Create a project file of this type inside a Program, Library
or Subproject when you want to organize your source files into conceptual
units. If your source code is organized into subdirectories, we recommend
that you create a subproject in each subdirectory, so that the program
hierarchy displayed in the Builder reflects the organization of your source
file structure.
This type of project does not generate any output in its own right. Instead,
its source files are compiled and then either added to the containing Library
or linked into the containing Program.
• Library — Create a project file of this type when you want to produce a
library file. A Program will be linked against all the Library projects
it contains.
• Project — Create a project file of this type to contain a project inside
another project. This allows you to create quite complex hierarchies. Files
contained within a Project do not affect its parents.
For a complete list of project and other file types, see “Builder File Types”
on page 32.
When creating your project hierarchy, be aware that files inherit compiler
options from parent project files. For example, if a program, masterfoo.gpj,
contains a subproject, subfoo.gpj, then subfoo.gpj is a child that inherits
options from the parent, masterfoo.gpj. If subfoo.gpj contains a source file,
foo.c, then foo.c inherits options from masterfoo.gpj and from subfoo.gpj. For
information about setting options, see “Setting Builder Options” on page 50.
1. Select the location within the hierarchy where you want to add the file.
2. Click the Add button ( ) or right-click and select the appropriate Add
File action.
3. In the file chooser, browse to the source file and click Add.
(UNIX) To add multiple files quickly, you can specify a file pattern using the
wildcard characters asterisk (*) and question mark (?) in the file chooser.
Add. The name of the file appears in the Source pane, but the actual file
does not yet exist.
4. Double-click the name of the new source file to open it in the MULTI
Editor.
5. Edit and save the new file.
1. Select the location within the hierarchy where you want to add the library.
2. Click the Add button ( ) or right-click and select the appropriate Add
File action.
3. In the file chooser, select a directory and enter the name of the project
file for the new library (with a .gpj extension). We recommend that your
library’s project file is located in the same directory as its source files
and that the name of the project file is the same name as the library (but
with a .gpj extension).
4. Click the Add button.
5. Right-click the newly created project file and select Set Type from the
context-sensitive menu.
6. Choose Library from the drop-down list, and click OK.
7. Add any appropriate source files to the new library project, and click the
Save button ( ) to save your changes.
Note This method should primarily be used for libraries for which source code
is unavailable. Library projects should usually be used instead since the source
files will be rebuilt as necessary.
! Warning Never manually add Green Hills provided target libraries to your
project (e.g. libind.a). The compiler will link in the correct target libraries
for your configuration when the appropriate Builder options are set.
To add a header file in your project hierarchy, add the file in the same manner
as adding a source file.
If your header files are located in separate directories, you can add explicit
include directories; however, this is often not necessary:
1. Right-click the project file for the program or library you are building and
select Set Options from the context-sensitive menu.
2. Select the Project category, and double-click the Include Directories
option.
3. Enter the path to the header file, and click OK.
We recommend that you retain the default classifications, and use file extensions
as specified in “Builder File Types” on page 32. However, if you need to
manually override the Builder’s choice of type, you can:
1. Right-click the file and select Set Type from the context-sensitive menu.
2. Choose the appropriate type from the drop-down list and click OK. The
entry in the type column will change accordingly.
You can cut and paste files within the source pane using Ctrl + X and Ctrl + V or
the Cut ( ) and Paste ( ) buttons.
To paste files, select the file immediately above where you want the files to be
added and click the Paste ( ) button.
Note You can select multiple files to cut as long as they are all contained within
the same project.
You can access graphical interfaces to assist you in editing certain file types, by
right-clicking them and selecting Grahically Edit:
• Use the File Shortcut Bar by selecting either Find: or Next:, then enter the
name of an input (e.g. hello.c) or output (e.g. hello.o) file in your project
and press Enter.
Find: — does a fast search though the project, so it is the best choice
when there is only one match or when any match is sufficient.
Next: — performs a slower, depth-first search through the project
starting at your current selection to find the next occurrence, so it is
good for more complex projects.
For more information, see “Using the File Shortcut Bar” on page 63.
• You can also search the visually expanded portion of the Source pane for
options and files. Press Ctrl + F and type a search string to search forwards,
or Ctrl + B and type a search string to search backwards. The Builder
searches incrementally as you type. Press Ctrl + F or Ctrl + B to look at the
next or previous instance of a string. To exit the search mode, press Esc.
Searching in Files
The Builder supports searching for a text string in all the searchable files in
a program. If you select an individual source file, then only that file will be
searched. If you select a .gpj file, then all the files referenced by that file will
be searched.
To begin a search, select Edit → Search in ... to open the Search in Selected
Files dialog box.
Enter the search string in the text box (or use the drop-down list to select recent
search strings) and select any of the following searching options, if desired:
• Case sensitive — The search will only find text that matches the case of the
search string exactly. If this box is not selected, the search will ignore case
when searching for a match. This box is selected by default.
• Whole word — The search will only find text that matches as a whole word.
For example, if this box is selected, a search for word would not match
sword. This box is cleared by default.
• Use Regular Expressions — The search treats the text you enter in the text
box as a regular expression. If this box is not selected, the search treats the
text you enter as a fixed string. This box is selected by default.
After you have entered the search string and set your searching options, click
Search to perform the search. A Search in Files Results window will open
when the search is complete. See the next section for a description of this
window.
Note The Search in Files capability works by running the GNU grep utility.
A copy of GNU grep is installed along with MULTI. However, GNU grep is
not part of MULTI and is not distributed under the same license as MULTI.
For more information about the GNU General Public License, under which
GNU grep is distributed, refer to the file gnugrep.txt, which is located in the
copyright directory of the MULTI installation.
• Results Pane — Contains three columns that display information about the
matching lines in the files searched.
File column — Displays the filename of the matching line. Place your
mouse pointer over this field to display the path to the file, if available,
in a tooltip.
Line column — Displays the line number of the matching line.
Text column — Displays the text of the matching line.
• Status Pane — Contains a description of the search and displays any errors
printed by the GNU grep utility.
• Stop Search button — Stops the current search. This does not dismiss the
results window; the results collected before the search was stopped will
continue to be displayed. This button becomes unavailable when the search
is complete.
• Close button — Dismisses the results window.
• Status Bar — Displays the progress of the search. Located at the bottom
of the window, this bar will display either Searching, Search completed,
or Search stopped.
You can double-click any line in the search results window to open an Editor
on the specified file and line.
Note Although Search in Files is available from the Builder, the Debugger, and
the Editor, the functionality differs slightly across these tools. The descriptions
above apply to searches performed from the Builder. See the MULTI:
Debugging book and the MULTI: Editing Files and Configuring the IDE book
for more information about searching from the Debugger and the Editor.
• a memory map — which lists the starting address and size of each region of
memory that will be used to contain program code.
• a section map — which lists the program sections, and specifies the memory
regions that they will be loaded into.
Linker directives files may also define constants and special symbols, which the
linker will use when linking and loading your executable. For more information
about the file format, see “Linker Directives Files” on page 285.
The following default linker directives files are generated automatically when
you create a new project for the Standalone operating system and are placed
within the resource.gpj project file:
Depending on how you set the Program Layout field on the Link Options
screen of the New Project Wizard (see “Setting Link Options” on page 26),
one of these files will have been copied to your program project file (e.g.
hello.gpj) for use at link-time. To change the .ld file used for linking, remove
the current linker directives file from the project and insert the new one.
Note These default files are automatically generated by the New Project
Wizard by combining the generic section maps in the install_dir/target/arm
directory together with a board-specific memory map taken from
install_dir/target/arm/target_dir.
You may need to edit these default files to add new memory regions or sections
or to change their attributes. To edit a file:
• The left-hand Hierarchy pane displays memory regions and sections and
their attributes in a tree structure. Memory regions are at the root of the tree,
and the sections they contain (together with any appropriate expressions) are
displayed as their children. Section attributes are shown as children of the
sections. Sections which are not located in a memory region are grouped in
a Global Memory Region for display purposes.
• The right-hand Layout pane displays memory regions and sections as visual
objects. Memory regions are laid out in order as colored rectangles, with
the region at the lowest address in memory shown at the top. The display
attempts to scale them to an appropriate length, but they may be stretched in
order to accommodate the display of sections. Sections are shown as white
rectangles inside their appropriate regions.
• The Name of the region, which is often used to describe the type of memory
(DRAM, Flash, etc)
• Its Origin or start address, which may be specified in hex or decimal form.
The dot symbol (“.”) specifies that this region will begin at the first address
available after the end of the previous memory region.
• Its Length, which may be specified in hex, decimal or as an expression.
• Whether the region is the Global Memory Region. This optional feature
provides backwards compatibility with old linker directives files in which
sections were allocated to specific addresses in memory rather than to
named memory regions. Such directly-allocated sections will be displayed
by the Linker Directives File Editor in a region called the Global Memory
Region. This is for display purposes only — these sections will not have an
associated memory region in the .ld file viewed in a text editor.
• The list of Sections that will be loaded into the region. The buttons to the
right of the section list allow you to:
Editing a Section
Double-click a section in the left or right pane to open it in the Section dialog
box for editing:
• The Name of the section, which conventionally begins with a dot and is
lowercase.
• Its Start Addr. If no start address is given, or if it is specified as a dot (“.”),
then the section will begin at the next available address in its memory region.
• The Section Attributes portion of the dialog box allows you to specify
various attributes to the section (for full documentation of these attributes,
see “Section Attributes” on page 292):
Selecting one of Clear, No Clear, and Default specifies how the section
will be treated by the run-time clear table, which can be used to initialize
a section to a particular value at startup.
Selecting Absolute specifies that the section start address is absolute and
must not be moved.
Selecting No Load specifies that the section will be linked to in order to
resolve symbols, but that its data will not be loaded into memory.
Load Addr specifies an address to load the section into (necessary only
if this is different from the address it is linked to).
Pad specifies a number of bytes of padding to be inserted at the start
of the section.
Max Size will generate an error if the section is larger than the specified
size.
Max End Addr will generate an error if the end of the section is at an
address higher than the specified address.
Min Size will generate an error if the section is smaller than the specified
size.
Min End Addr instructs the linker to pad the end of the section if it does
not reach the specified address.
• Selecting ROM Copy specifies that this section is to be loaded into ROM,
but will be copied to RAM at startup for execution. You must additionally
specify:
• The Additional Attributes text box allows you to specify other attributes
not available elsewhere in the interface.
Once you have made all your necessary changes, click to save and exit.
Editing an Expression
Double-click an expression in the left pane to open it in the Expression dialog
box for editing:
Enter or edit the expression as appropriate, and click OK to save your changes.
• Switches — which have two or more settings from which you choose only
one (for example Optimization Strategy and Debugging Level).
• Combination Switches — which have multiple settings from which you
choose all, none, or any combination (for example Run-Time Error
Checking and MISRA C).
• Strings — which accept a single string value (for example Output File
Name and Start Address Symbol).
• Lists — which accept multiple string values (for example Include
Directories and Library Directories).
Detailed descriptions of all the Builder options, together with their compiler
driver equivalents are provided in Chapter 5, “Builder and Driver Options”. The
following sections provide a general guide to setting options.
To set or edit an option on any of the tabs, double-click it and select a setting
or enter a value in the dialog.
The present value or setting of the option is displayed in the Value column.
Options can be set at different levels of the Build hierarchy, and an option
set in a *.gpj file is inherited by all the files contained in that *.gpj file (see
“Inheriting Options from Parent Build Files” on page 61). Each value appears
in one of three colors:
• Values in printed in gray and which appear in parentheses are default values
that have not been explicitly set anywhere in the project. Note that not all
options have default values, and that some defaults may change depending
upon other option settings.
• Values printed in black are inherited from a parent file. You can override
inherited values by setting the option to a new value in the present file.
• Values printed in blue are set in the present file.
This tab lists only the common options that most users will need to control.
Categories can be expanded or contracted by clicking the plus or minus sign to
their left. Double-click an option to edit it.
This tab lists all of the Builder Options, categorized by type or associated tool.
The pane on the left displays the category structure. Click a category in order to
display the options it contains in the pane on the right.
This tab displays those options that have been set in, or are inherited by, this
file, together with their current settings.
If the option has already been set at this or a higher level of the project
hierarchy, its present setting is displayed in the Value field, and the file in which
it was set is displayed in the Set In field.
1. Select a value from the drop-down list. The Set In field will change to
display the current file’s name.
2. Click OK to complete setting the option and return to the Options window.
If a sub-option has already been set at this or a higher level of the project
hierarchy, its present setting is displayed in the left-hand column, and the file in
which it was set is displayed in the Set In column. Sub-options set higher in the
project hierarchy, are printed in black and have an arrow pointing up and to the
left in the left-hand column. Those set in the present file, are printed in blue,
and those that have not been set are printed in gray.
1. Click the symbol in the left-hand column. These symbols toggle between:
• — not set
• — enabled
• — disabled
The line for the sub-option will turn blue, and the Set In field will change
to display the current file’s name.
You can enable or disable all of the sub-options with the All toggle
( )
2. Edit other sub-options as appropriate, and then click OK to return to the
Options window.
If the option has already been set at this or a higher level of the project
hierarchy, its present setting is displayed in the Value field, the file in which
it was set is displayed in the Set In field, and the Override Inherited check
box is displayed.
1. Enter an appropriate string in the Value field (if the option has already
been set, you must select the Override Inherited check box before you
can access the Value field). If the option requires a directory or filename as
a value, then a folder icon ( ) is displayed, which you can use to navigate
to the appropriate file or directory.
2. The Set In field will change to display the current file’s name. Click OK
to complete setting the option and return to the Options window.
If the option has already had values assigned to it at this or a higher level of the
project hierarchy, its present settings are displayed in the Value field, and the
file in which each was set is displayed in the Set In field.
1. Click the value you want to delete to select it, and then click the delete
button ( ).
1. Click the Add button ( ) and enter an appropriate string in the text box.
If the option requires a directory or filename as a value, then a folder
button ( ) is displayed, which you can use to navigate to the appropriate
file or directory.
2. The new value is appended to the bottom of the list and the current file’s
name appears in its Set In field. Click OK to complete setting the option
and return to the Options window.
• The Command Line tab, which shows the driver options that will be passed
to the compiler when you build the selected file:
Enter an option name or part of a name in the Option to search for text box,
and click the Search button. By default, the Builder will search all three of:
To set a macro, from the main Builder window select Edit → Set Build Macros
to open the Set Build Macros dialog box:
Example 1.
The root directory of the project in this example is C:\src. To define a macro
called top to represent the root directory:
The include files for the project are located in C:\src\include. To specify this
include directory to the Builder using the top macro:
To import a variable:
After a variable is imported, you can use the variable’s name to stand in for its
string value by using $VARNAME anywhere in a builder option where you want
to have the value of VARNAME substituted.
The Builder tracks changes to the environment variables you import so that
your entire project is rebuilt whenever you modify the value of an imported
environment variable.
Example 2.
Note Macros and imports are only valid if they are set in the top-level project.
If you use the GUI for setting builder option macros or importing environment
variables, then the macros and imports are always saved in the top-level project.
This behavior is different from the Set Options dialog box where the options
are set on whichever file is selected.
• If the options are specific to the current project, select the parent’s project
file, and then set the options. For example, if child.gpj is a subproject of
master.gpj, select master.gpj, and then set the options. These options are
written to the parent project file. If you reuse the child’s project file in a
different project, the options will not be carried over into the new project.
• If the options are specific to the subproject file itself, select the subproject
(child.gpj), and then set the options. These options are written to the child
project file, and therefore will be set for that project file regardless of what
parent it currently belongs to.
• To set an option for an individual file, select the file and set the options.
• To set an option for a group of files, select the project file that contains the
files in the Builder’s hierarchy of your project, then set the options. The
options are set in the project file; all files below the project file, including its
source files, will inherit these options.
• To build your entire project, select the top-level project (usually named
default.gpj), in the Source pane, and click the Build button ( ).
• To build a specific subproject, executable, or library, select the appropriate
project file, right-click it, and select Build selected file.
• To build an individual source, select it, right-click it, and select Compile
selected file.
In each case, the Builder will invoke all the appropriate tools. You can follow
the progress of the build in the Output pane at the bottom of the Builder
window. If the build is successful, then its completion will be reported here. If
errors occur, then a Build Progress window will open:
You can modify or obtain extra information about the build process, by selecting
Build → Advanced Build to open the Advanced Build dialog box (for full
documentation, see “The Advanced Build Dialog Box” on page 230):
• To remove any previous output files before beginning the build, select the
Clean all output before building check box, and click the Build button.
• To see a dry-run of the build, without actually executing any commands or
modifying any files, select the Show build without execution check box,
and click the Build button.
• To see the commands that the Builder executes as it builds, select the Show
tool commands check box, and click the Build button.
The bar has two components, a drop-down list that enables you to specify
whether you want to Build, Find, or [Find] Next, and a text field in which
you can enter parameters as follows:
Build: options files
Builds any files specified. You may also specify gbuild options (see “The gbuild
Utility Program” on page 336).
For example, to delete all previous output files, and then build the projects foo.gpj
and bar.gpj, you would select the Build: setting and enter the following:
Note The file specified must be the complete base name (including any
extension but excluding any path), and may be any one of:
The Select One project, traps.gpj, can build a program that uses only the
processor-specific file, traps.ppc or traps.mip, for the specified target
processor.
If you have multiple files that are specific to a single processor, create multiple
Select One projects. Suppose the program in the above example also uses
bdriver.ppc and bdriver.mip. In this case, you would need another Select One
project, bdriver.gpj.
The driver is the command line wrapper for various toolchain components.
The driver enables you to manually specify which source files you want to
compile and/or all of the source files that are necessary to link your program.
This chapter explains how to use the driver and introduces some of the
most important tasks it can perform. Like the Builder, it can control all the
components of the Green Hills toolchain necessary to produce an executable
from high-level source files:
• The optimizing compilers for C and C++, which compile high-level source
files into ARM assembly language files.
• The asarm assembler, which translates ARM assembly files into object files.
• The elxr linker, which links object files (including object files in libraries)
together to generate an executable.
In addition, the driver accepts many other forms of input files (see “Working
with Input Files” on page 69) and can produce many different forms of output,
including using the ax librarian to combine object files together into libraries
(see “Generating Other Output File Types” on page 71).
where:
If your source files contain mixed ARM/Thumb code, you can invoke either
an ARM, or a Thumb compiler driver.
• file is one or more of the following:
C or C++ source file
Assembly source file
Object file or library of object files
Linker directives file (see “Passing Linker Directives Files to the Driver”
on page 70)
• -option is one or more compiler driver options. All the options are
case-sensitive (for example -o renames the output file, while -O enables
general optimizations), and most are host-independent. Many of the most
commonly used options are discussed in this chapter. All of the driver
options are listed and explained in Chapter 5, “Builder and Driver Options”.
Files and options are listed on the command line, separated by spaces.
The driver reads all options before processing any files. When two options
represent different choices for the same feature, the later choice overrides the
earlier one. If it encounters an unrecognized or invalid option, the driver will
ignore it and issue a warning.
After reading the options, the driver processes files in the order they appear
on the command line. If an error occurs in one file, processing will continue
with the next file. If no errors occur, all object files and libraries will be linked
together according to the order specified on the command line.
To build an executable from a C source file called hello.c, use the C driver,
ccarm, and enter the following:
ccarm hello.c
To build an executable from a C++ source file called hello.cxx, use the C++
driver, cxarm, and enter the following:
cxarm hello.cxx
In each case, an executable file called a.out is generated, together with the
following additional files: hello.o, a.map, a.dnm and a.dla
The hello.o file is the object file which results from passing hello.c to the
compiler and assembler. Whenever the driver generates an executable from a C
or C++ file, or from an assembly language file, it retains the intermediate object
files for future re-use. The a.map file is a map file produced by the linker. The
a.dnm and a.dla files contain basic debugging information for use with the
MULTI Debugger. For instructions on generating full debugging information
for MULTI, see “Generating Debugging Information” on page 91.
To build an executable from multiple source files, list the files on the command
line, separated by spaces, as follows:
ccarm hello.c foo.c bar.c
This command generates an executable called a.out, the debugging files a.dnm
and a.dla, a map file a.map, and three object files, hello.o, foo.o, and bar.o.
Note The example command lines in this section, and in the remainder of
this chapter, are shown using the C driver, ccarm. They will also work with
the other drivers.
In addition to high-level language source files, the driver can also process
assembly language files, object files, and libraries. The diagram below shows
how these files are passed to the various tools in the toolchain.
The following is a partial list of file extensions which the driver recognizes:
Note On a command line, you can use the -filetype option to override the
default type associated with the filename. For example:
ccarm -filetype.cc hello.i
Source files of different languages can be included within the same executable
by using the Advanced→Advanced Project Options→Input Languages or
-language options. For more information, see “Advanced Project Options”
on page 198.
You can edit the default files to specify your own layout. For full documentation
of the syntax, see “Linker Directives Files” on page 285).
To pass a .ld file to the driver, add it to the command line as follows (no option
is required; the file is recognized by its extension):
ccarm hello.c mylinkfile.ld
To instruct the compiler to halt the build process after the compiler has
generated assembly files, use the -S option as follows:
ccarm hello.c -S
To instruct the compiler to halt the build process after the compiler has
generated assembly files and the assembler has translated them to object files,
use the -c option as follows:
ccarm hello.c -c
Creating Libraries
You can pass high-level source files, assembly language files, and object files
to the driver, and instruct it to collect them into a library. The driver invokes
the compiler and/or the assembler (if required) to produce object files, and then
invokes the librarian to combine these object files into a library.
To instruct the driver to create a library from the C source file hello.c and the
object file foo.o, use the -archive option as follows:
ccarm hello.c foo.o -archive -o libfoo.a -G
This command produces a library of object files called libfoo.a, which contains
two object files, hello.o and foo.o.
Note When using the -archive option to create a library, you must use the -o
option to specify a name for it. The name must be in the form libfile.a. The
-G option is optional, but should be passed if you intend to use the MULTI
Debugger.
To update an object file already included in a library, pass the new version to
the driver with the -archive option, as follows:
ccarm hello.c -archive -o libfoo.a
To perform other operations on libraries, you must invoke ax directly. For more
information, see Chapter 10, “The ax Librarian”.
Note These options only apply to the compiler driver and cannot be set from
the Builder.
-archive
Runs the ax librarian to generate a library (instead of running the linker to
generate an executable program). For more information, see “Creating Libraries”
on page 72.
-c
Produces an object file (called input-file.o) for each source file.
-E
Runs the preprocessor and writes the preprocessed file output to stdout. This
option can be useful when debugging preprocessor macros and #include files.
-Q
Produces only an inline file (called input-file.inf) for each source file. These files
contain partially compiled code for functions generated during the first pass of the
inliner, together with the list of the include files that the source file depends on
(and are used by automatic dependency checking).
-S
Produces an assembly file (called input-file.s) for each source file.
-syntax
Checks the syntax without generating code.
Note See also the driver options associated with the Linker→Generate
Additional Output option in “Linker Options” on page 183.
.lst
An assembler source listing that is written by the toolchain, and read only by the
user. See “Assembler Options” on page 180.
.map
A map file generated by the linker that contains information about how the program
is laid out in memory. .map is written by the toolchain, and only read by the user.
See “Linker Output Analysis” on page 189.
.mem
An additional copy of the executable image that has been translated by the
gmemfile utility. .mem is written by the toolchain, and read by non-GHS utility
programs. See “Linker Options” on page 183.
.run
An additional copy of the executable image that has been translated by the gsrec
utility. .run is written by the toolchain, and read by non-GHS utility programs. See
“Linker Options” on page 183.
.time
Files that are generated by the builder when the file being processed does not
generate an output file. This allows the builder to track if and when the item was
last processed for dependency tracking. .time is read and written only by the
toolchain.
Note These options only apply to the compiler driver and cannot be set from
the Builder.
@file
Instructs the driver to read command line arguments from file.
-#
Displays the command lines generated by the driver (which are used to call the
compiler, assembler, and/or linker for processing the input files) without executing
them. For compatibility purposes, this option can also be entered as -dryrun or
--driver_debug.
-help
Displays a list of some of the more commonly-used options with brief descriptions.
-v
Displays the command lines generated by the driver as it calls the compiler,
assembler, and/or linker for processing the input files.
All characters in the file other than spaces, tabs, newline characters, and double
quotes are literal.
• If the argument begins with a ", then everything on the line up to the next "
will be part of the argument, and those quotes will be discarded.
• Otherwise, if a " is in the middle of an argument, the " will NOT be
discarded, but will cause any whitespace on the line up to the next " to
be included in the argument.
Note Due to limitations in the command line parser, the -bsp and -layout
options cannot be entered in a driver options file and must be placed directly on
the driver command line, either before or after any @file.
Example 1.
• pass files hello.c, foo.c, and bar.c to the compiler, assembler, and linker
• generate MULTI debugging information (-G)
• compile the files in such a way as to maximize the speed of the final
executable, including using two-pass inlining (-Ospeed -OI)
• name the output executable foo (-o foo)
• generate code tailored to the instruction set associated with the Intel
IQ80310 board, and assign the program to memory regions of that
board using a board-specific linker directives files (-bsp=iq80310
-layout=romrun)
Note You cannot include comments in a command file that you pass to the
compiler driver with this option. Do not use this option to read a file containing
assembler or linker options. Instead, use -asmcmd=file (see “Assembler
Options” on page 180) or -lnkcmd=file (“Linker Options” on page 183) to pass
the file directly to the assembler or the linker, respectively. Note that linker
directive files should be passed to the linker by using a known suffix, such as
.ld or .lnk, rather than using this option.
Using makefiles
The Green Hills compiler drivers are completely compatible with makefiles.
This section discusses the basic issues involved in porting existing makefiles
for use with Green Hills projects.
To convert this makefile for use with ccarm, you would need to make the
following changes:
bigprog: $(OFILES)
$(CC) $(LFLAGS) $(OFILES) -o $@
To convert this makefile for use with ccarm, you would need to change the
macros as follows:
• Change:
CC=qcc
to:
CC=ccarm
• Change:
CFLAGS=-g -I../include -DITERATIONS=3 -O3
to:
CFLAGS=-G -I../include -DITERATIONS=3 -Ospeed -OI
In this example, two C files, one ARM assembly file, and one C++ file are
linked together into a single executable:
OFILES=myprog.o utils1.o utils2.o interface.o
myprog: $(OFILES)
qcc $(OFILES) -o myprog
utils2.o: utils1.s
qasm -c utils1.s
interface.o: interface.cpp
qc++ -c interface.cpp
Porting this example to use cxarm is easy because the Green Hills drivers
recognize filename extensions and invoke the correct compiler or assembler
automatically. Consequently, you would simply need to change all references to
qcc, qasm, and qc++ to cxarm, so that the makefile would read as follows:
OFILES=myprog.o utils1.o utils2.o interface.o
myprog: $(OFILES)
cxarm $(OFILES) -o myprog
utils2.o: utils1.s
cxarm -c utils1.s
interface.o: interface.cpp
cxarm -c interface.cpp
This chapter describes the ARM target environment, and provides information
about some of the more commonly used Builder and driver options used to
access and control features of that environment.
The Green Hills ARM compiler, assembler, and linker comply with the ARM
Embedded Application Binary Interface specification (ARM EABI).
ARM Characteristics
The ARM memory is byte-addressed with 32-bit addresses. Bits are numbered
with bit zero as the least significant bit.
By default, the ARM compiler uses little endian byte ordering, in which the
least significant byte of a multiple-byte value is stored at the lowest address.
The reverse byte order, big endian, is also supported.
Floating-point values use IEEE-754 format (32 and 64 bits) and are in the same
byte order as other values, except when an FPA hardware floating-point unit
is used. In that case, all floating-point values are represented in big endian
byte order.
By default, the ARM chip uses software floating point, which means the
compiler emits library calls to perform most floating-point arithmetic operations.
In C and C++, bitfields are allocated starting at the lowest memory address.
Bitfields begin at the least significant bit in little endian mode and at the most
significant bit in big endian mode.Each structure, union, and array is aligned to
the maximum alignment requirement of any of its components.
Data types long long and unsigned long long are 64 bits, aligned
to 4 bytes, and are held in pairs of 32-bit registers.
The following table describes data type alignments for C and C++.
C/C++ data type Size Alignment
char 8 8
short 16 16
int 32 32
long 32 32
long long 64 32
float 32 32
double 64 32
long double 64 32
* (pointer) 32 32
enum (default) 32 32
Note To reduce the size and alignment of the enum type to 8 or 16 bits where
possible:
Register Usage
The ARM processor has sixteen 32-bit registers accessible for integer values.
Structure Packing
The Green Hills compilers always allocate fields of a structure in the order
specified in the declaration. It may be necessary for the compiler to insert one
or more bytes of padding to ensure that a field begins at an offset from the
beginning of the structure that is a multiple of the alignment of that field. The
alignment of a field is determined by its type. The maximum alignment of a field
is 4 bytes. This alignment applies to fields of type float, int, long, long
long, and double, as well as all fields with pointer types. Fields of type
short have 2-byte alignment and fields of type char have 1-byte alignment.
Packing is a feature that reduces the maximum padding the compiler will
insert between fields. If a structure is packed to 2 bytes, then each field has
a maximum alignment of 2 bytes, and at most 1 byte of padding will ever
be inserted between fields. The structure itself will also have a maximum
alignment of 2 bytes.
Example 1.
struct s {
char c;
int i, j;
} a;
#pragma pack(2)
struct s x;
struct s2 {
char c;
int i, j;
} b;
#pragma pack()
struct s2 y;
The size of a and the size of x are both 12. Three bytes of padding appear
between field c and field i. Since struct s was already declared, the
directive #pragma pack(2) does not affect the declaration of x.
The size of b and the size of y are both 10. One byte of padding appears
between field c and field i. Since struct s2 was already declared,
#pragma pack() does not affect the declaration of y.
Note The use of the #pragma pack() directive may generate structures in
which some of the fields are not fully aligned. The compiler can automatically
generate code to access unaligned fields correctly, but such accesses may be
inefficient. Furthermore, it is not legal to access the address of an unaligned
field. This problem may come up more frequently in Thumb mode.
Many of the most popular ARM boards are supported through tailored linker
directives files that greatly simplify the process of linking and loading an
executable. To specify a particular target board:
When creating a new project with the New Project Wizard (see
“Creating a New Project: The New Project Wizard” on page 24),
choose the appropriate target board. To subsequently change your
target in the Builder, click Edit → Set Build Target, and choose a
target from the Target Selector dialog box.
To specify a target board with the driver, pass the -bsp board option.
To obtain a list of supported boards, enter -bsp=? (or -bsp=\? in many
shells).
If your board is not supported, you should specify your target processor instead.
Specifying a target processor enables the driver to determine the most efficient
instruction set to use in code generation.
As the compiler and assembler translate each C or other high-level language file
into an object file, they also generate associated debugging information. For
each object file created, a separate file with the same name but a .dbo extension
is produced to hold this information. After the executable is linked together,
these individual debugging information files are combined into a structure that
can be quickly searched and incrementally loaded.
In the diagram, the files foo.c and bar.c are passed to the toolchain, which
generates files foo.o and bar.o and links them together to generate an executable,
baz. In addition, the debugging information files foo.dbo and bar.dbo are
generated and passed to the dblink utility, which also extracts the executable’s
namelist information (via the gnm utility), and generates the following two files:
Note
Coverage Profiling
To obtain Coverage (also known as Block Count) profiling information:
Rebuild your application. If linker errors result, you may need to review
the settings for your board in the Target-Driven Timing Profiling source
files mentioned in the preceding.
4. Open your application in the debugger, enable profiling and run your
program in the usual way. For more information about profiling, see
Chapter 15, “Using the Profiler” in the MULTI: Debugging book.
For information about these and other optimization options, see “Optimization
Options” on page 143. For detailed descriptions of the various optimizations,
see Chapter 19, “Optimization Descriptions”.
Note For information about the headers and libraries provided with your
distribution, see Chapter 16, “Libraries and Header Files”.
If your project is of any size or complexity, you will probably want to create
your own libraries of frequently used functions, and to instruct the compiler
to link against them. While the compiler knows where to find the standard
libraries and header files provided with your distribution and automates linking
against them, you must tell it where it should search for your own headers and
libraries. At link-time, the linker will attempt to resolve external references in
the source files you pass to it by linking against your libraries before searching
the standard libraries.
You can specify multiple directories. The compiler searches the directories in
the order in which they are specified.
The compiler searches for header files included with the various types of
#include directive in the following ways:
• If the #include directive specifies a full path to the header file (cases A
and B above), the compiler searches:
in that location only. It does not search for another version of the file in
any other directory.
• If the #include directive specifies only a filename or a partial path for the
header file, and uses quotes (case C above), the compiler searches:
in the directory of the source file that contains the #include directive,
and then
in any directories specified with the Project→Include Directories
option (-Idirectory), in the order in which they appear on the command
line, and then
in the default directories (see “C and C++ Header File Directories” on
page 549).
• If the #include directive specifies only a filename or a partial path for the
header file, and uses angle brackets (case D above), the compiler searches:
in any directories specified with the Project→Include Directories
option (-Idirectory), in the order in which they appear on the command
line, and then
in the default directories (see “C and C++ Header File Directories” on
page 549).
includes -Isys -I- -Iinc. In this case, the compiler searches for
include files in the inc directory, but not in the sys directory.
Note Using #include "header" can create problems if you keep source
files and header files in the same directory and then make local copies of either
source files or header files. For example, suppose you are working with a local
copy of a header file but do not have local copies of all source files. When
the compiler processes a non-local source file with a #include "header"
directive, it finds the non-local header file in the directory of the non-local
source file before it finds the local copy of the header file.
The simplest way to avoid this problem is to always keep your source files
and header files in different directories. If your source files and header files
must share a directory, you can avoid problems by always using #include
<header> instead of #include "header".
If you must use #include "header", you can specify a dash (-) in the
Project→Include Directories list (-I- ) to force the compiler to process the
directive as it does the #include <header> directive. When this appears
anywhere on the command line, the compiler does not look in the directory
containing the source files, regardless of which #include directive is used in
the source files.
You can control the most commonly used features of the assembler with Builder
and driver options. For example, to instruct the assembler to produce a source
listing file:
For a list of all the assembler-specific Builder and driver options, see
“Assembler Options” on page 180. For detailed documentation of the
assembler, see Chapter 7, “The asarm Assembler”.
You can control the most commonly used features of the linker with Builder
and driver options. For example, to instruct the linker to strip the executable
after linking:
For a list of all the linker-specific Builder and driver options, see “Linker
Options” on page 183. For detailed documentation of the linker, see Chapter
9, “The elxr Linker”.
Thumb Mode
Certain ARM processors support the execution of Thumb code, which is a 16
bit restricted interface to the 32-bit ARM processor. Every Thumb instruction
maps to an equivalent ARM instruction, with identical behavior. Choosing to
do so can decrease code size by sacrificing execution time. Since Thumb code
is more compact, switching from ARM to Thumb typically reduces overall
code size (by up to 35 percent), and increases the total number of instructions
required. Consequently, execution time may increase by up to 30 percent.
When both size and speed are important, we recommend that you selectively
use the smaller, slower Thumb code only for those sections of code which
are executed infrequently.It is possible to mix ARM and Thumb encodings in
the same application.
• ARM7TM
• ARM9
• ARM9E
• ARM10
• XScale
• ARM11
ARM6, ARM7, ARM8, and StrongARM do not support Thumb mode.
Attempting to use Thumb mode on CPU’s that lack Thumb support results
in a build error.
Mixed ARM/Thumb
.nothumb
.globl armcode
armcode:
stmfd sp!,{r0}
For correct disassembly, a global label must appear at every mode change. This
restriction may be removed in the future.
• Ensure that each assembly routine that may be called from a mixed mode
has only one return instruction located at the end of the routine, or that
the routine returns with the bx instruction. If a routine has multiple return
points, the linker can patch only the last return point. The routine must end
in one of the following instructions:
ldmfd sp!, {..., pc} (ARM)
pop {..., pc} (Thumb)
bx reg
mov pc, lr
• Explicitly specify the symbol size using a .size directive in the assembly
source, and tag it as a function with .type.
Example 1.
.text
.align 4
.globl sample_func
sample_func:
...
...
.type sample_func,$function
.size sample_func,.-sample_func
Linker Behavior
The linker has built-in support for mixed-mode application development.
If the linker determines that there are calls between functions of different types
(16-bit versus 32-bit) within the application, it will modify the program to
switch modes appropriately.
In order to determine the exit instruction of a called function that may require
patching, the linker depends on two restrictions:
• The function has only one exit point, which is contained in the last
instructions of the function.
• The size of the function is known at link time.
For code written in high-level languages, the Green Hills ARM compiler
enforces these two restrictions. If you are hand-coding mixed ARM/Thumb
assembly code, see “Switching Between Thumb and ARM in Assembly Files”
on page 102 to ensure that your code meets the linker’s criteria.
• Call analysis
• Coverage analysis
• Memory leak reporting
• Hardware Floating-Point — Only software floating point is supported. Since
the calling convention differs between hardware and software floating
point with regard to floating point parameters, intercalls from arm code
compiled for hardware floating point to thumb functions requiring floating
point parameters and vice versa are not permitted. When mixing hardware
floating point arm code with software floating point thumb code, you should
avoid directly passing floating point parameters for intercalled functions.
You can pass VFP floating point values by reference to software floating
point functions, as the representation in memory is identical.
Program Sections
Program sections are labeled collections of program objects. The compiler
assigns all data and text objects to the appropriate sections at compile time.
The standard program sections are:
Note The compiler will, by default, place variables that are explicitly
initialized to zero into .bss. To place such objects in .data instead, set
the Target→Memory Models→Placement of Zero-Initialized Data option
to Place Zero-Initialized Data in .data (-no_discard_zero_initializers) (see
“Memory Models” on page 133). In contrast, the optimizer may reallocate
certain uninitialized variables from .bss into .data. For information about
this optimization and how to control it, see “Data Definition Movement” on
page 646. Variables placed in user-defined sections with the #pragma ghs
section directive are not affected.
The linker collects all data for each named section and locates that section in
memory, guided by a section map that is defined in a user-supplied or default
linker directives file. The section map specifies the desired location of each
section and the order of the sections in the final output file.
You can also create sections, assign them to specific regions of memory, and
assign variables to them.
The linker provides definitions for several symbols that, if referenced and
not defined, are given certain addresses corresponding to the final image.
These symbols are constructed by prepending the strings __ghsbegin and
__ghsend to the name of each section in the final image, and changing the
periods (“.”) in the section names to underscores (_). For example, for a section
• Create named sections, and assign them to memory regions using a linker
directives file.
• Assign variables to specific sections using the #pragma ghs section
directive, which has the following syntax:
#pragma ghs section[secttype="sectname"[,secttype="sectname"]...]
The following statement removes all mappings and restores the section
assignment rules to their initial state:
#pragma ghs section
Mappings affect variables at the point at which they are defined. The section in
which each variable is placed is determined by the mapping in the source file.
One can place different variables in different sections by interspersing section
#pragma directives among the variable declarations. The compiler determines
which section each variable would normally fall into and then checks whether
variables of that type have a mapping. If so, the section specified in the mapping
is used in place of the default.
The variable foo is normally placed into the .data section because it is
initialized to an explicit value. However, if this line of code were preceded
by the following:
#pragma ghs section data=".mydata"
then the variable foo would be placed in the section .mydata instead.
Specifying a user-defined section for the .rodata section type places certain
read-only (const) variables into the specified section. The eligible objects
depend on the specific target system and compile-time options. Typically, these
include const variables and string literals.
Example 1.
Note In some environments, only one text section is allowed. This means
that #pragma ghs section text="text1" must appear in the
file before any functions. It also means that #pragma ghs section
text=default and #pragma ghs section should not be used after the
text section has been renamed.
• Programs that copy all of their sections from ROM to RAM at startup will
execute more quickly, but will require more RAM.
• Programs that copy as few sections as possible from ROM to RAM at startup
will require less RAM, but will execute more slowly.
Default linker directives files and options are provided to manage the location
of program sections. To specify a particular layout when creating a project
with the New Project Wizard (see “Creating a New Project: The New Project
Wizard” on page 24), set the Program Layout option (on the Link Options
screen) to one of the following settings:
Whichever layout you choose, the New Project Wizard will create all three
.ld files and place them in the src/resource.gpj subproject. To change your
program layout, simply copy the relevant file into your project, and delete
whatever other .ld file was previously there.
Note For information about manually editing linker directives files to control
this feature, see “Modifying your Section Map for Speed or Size” on page 297.
PIC involves the calculation of the address of any object in a .text section,
typically a function label. Addresses in C can appear as:
• Local branches
• Normal function calls
• Far function calls
• Switch statements
• Function pointers
Instructions that implement local branches and normal function calls are relative
to the program counter (PC) and therefore are inherently position-independent;
no additional code is needed to achieve position independent code. To achieve
position independent code for far function calls, switch statements, and function
pointers, the compiler must generate additional code.
When you enable PIC, the linker suppresses errors that identify overlapping
sections.
Alternatively, you can use the grun utility with the -text offset option to run the
simulator. For example, to run myprog as above, enter:
grun -text 0x100000 simarm -- myprog
For more information about the grun utility, see “The grun Utility Program”
on page 378.
• Use the -text option when starting the MULTI Debugger from the command
line. For example, to start debugging a PIC program myprog with the PIC
base address set to 0x100000, enter:
multi -text 0x100000 myprog
• Set the _TEXT variable while the Debugger is running. For example,
suppose you open a PIC program myprog in the Debugger and want to set
the PIC base address to 0x100000. In the Debugger command pane, enter:
_TEXT=0x100000
To reduce the number of library variants, Green Hills embedded system libraries
are built with PIC enabled. Therefore, the same libraries can build both PIC
and non-PIC executables. PIC addressing calculations are made relative to the
PC register.
When you enable PID, the linker suppresses errors that identify overlapping
sections.
Alternatively, you can use the grun utility with the -data offset option to run the
simulator. For example, to run myprog as above, enter:
grun -data 0x200000 simarm -- myprog
For more information about the grun utility, see “The grun Utility Program”
on page 378.
• Use the -data option when starting the Debugger from the command line.
For example, to start debugging a PID program myprog with the PID base
address set to 0x200000, enter:
multi -data 0x200000 myprog
• Set the _DATA variable while the Debugger is running. For example, to set
the PID base address to 0x200000, enter the following in the Debugger
command pane, enter:
_DATA=0x200000
To avoid this problem, the compiler provides support for far function calls. The
compiler generates a series of instructions to place the address of the called
function into a register before using an instruction to call the function. This
method allows you to reach a function anywhere in the address space of the
processor, but it requires additional code size and processor time.
Call Patching
In most cases, the linker is able to detect out of range calls, and inserts veneers
to the far function as necessary. This method is the default behavior of the
linker and does not require the setting of options or modification of source code.
A far call using this method requires two branches, one to the veneer and one to
the function itself, which may reduce execution speed for the call. Nonetheless,
this is generally the recommended method for making far function calls on
the ARM architecture. This method impacts code size and run time less than
using the Target→Memory Models→Far Calls option, because only those
calls that are out-of-range are affected.
This option instructs the compiler to generate a far function call for every
call (with no need for modifications to the source code), unless the option is
overridden by one of the other methods specified below. This method should
only be used when far call patching is not an effective solution.
Note that in certain cases, such as when both the caller and callee are located in
the same file, the compiler may be able to determine that a far function call is
unnecessary, and so perform a near call regardless of the #pragma directive.
Function Declaration
The keywords __nearcall and __farcall may be placed in the
declaration of a function to specify the type of function call to be used for that
function. These keywords override the setting implied by either the #pragma
directive or the command line option. For example:
__nearcall int nearfunc();
__farcall int farfunc();
The syntax requires that __nearcall and __farcall be placed before the
function return type. If the function returns a pointer, then the __nearcall or
__farcall keyword must be placed before the first asterisk (*).
This allows the use of the (otherwise illegal) C/C++ register keyword to
place global variables in registers using the following syntax:
register int i; /* file scope implies global */
Note The syntax register static int i is still illegal, because it can
cause a possible register numbering problem when compiling multiple files.
These registers are initialized to zero by the startup module. The data type of the
variable can be any integral or pointer type where a local variable of that type
would be eligible for allocation to a register. It must not be explicitly initialized,
and its address should never be taken. The program must be compiled with
the Green Hills startup code.
Global registers are permanent registers, so functions compiled with this option
can call (but not be called by) functions compiled without it, including third
party object files and libraries. A function may not access variables allocated to
global registers unless all functions in the call chain before it were compiled
with the global registers reserved. The easiest way to guarantee this is to
compile all files with this option. However, since the Green Hills libraries are
not compiled with this option, it is not safe to use variables allocated to global
registers in library callback routines (such as the user-supplied comparison
function called by the stdlib.h functions bsearch() and qsort()). It is
also generally not safe to use variables allocated to global registers in interrupt
functions, as such interrupts may be triggered asynchronously.
If you want to share the same global registers across compilations, consider
placing them into a single #include file, which is always included first in all
compilations to ensure consistency.
Other Topics
You can use either of the following methods to declare a function as an interrupt
routine:
The compiler uses a .org assembler directive to place the address of the
named function in the memory location that the ARM processor reserves for
the exception type represented by constant_integer.
Example 1.
Note This feature is supported only when using a Green Hills assembler and
is not available in binary code generation mode. You must ensure that the call
destination is within range of the vector or unpredictable behavior may result.
A function declared with the __swi keyword is not itself a top level interrupt
handler; it is a function that is expected to be called by a separate SWI interrupt
handler when the matching value field is detected. A top level SWI interrupt
handler intended to dispatch different exception values can be declared with
#pragma intvect or it may already be initialized outside the program.
For memory-mapped I/O, the variables that correspond to the memory locations
should be kept in one or more sections that contain only memory-mapped
locations. These sections should not be initialized during program startup.
With this approach, the variable definition can be placed in a source file of
its own. This file is compiled to an object file that is shared among different
projects that need to refer to this I/O device. Each project needs the object file,
an entry in the section map to position the section, and a header file to define
the struct type.
In addition, you can then display the named variable in a MULTI Debugger data
explorer to provide ongoing displays of the state of the I/O registers, and edit
the fields of the data explorer to cause writes to the I/O registers. This displays
and a section map entry in the linker directives file such as:
SECTIONS {
...
.uartsec NOCLEAR 0x1000 :
...
}
Note The NOCLEAR attribute in the linker directives file prevents the
.uartsec section from being cleared to zeros at startup.
Code can then refer to the registers as uart.Tx, uart.Rx, and uart.CSR.
Within MULTI, the command view uart views a window showing the
contents of the UART registers.
Since MULTI must perform read operations to display this data, this approach
is not suitable for registers that are sensitive to read and write operations (that
is, registers for which accessing a register triggers an activity or referencing a
data location near the register causes problems). Such registers or data locations
are often declared in C/C++ with the volatile qualifier.
source directory for a source file, then in the development group’s group source
directory, and finally in a multi-group global source directory. Viewpathing is
available on UNIX only.
You must run all tools from your root node, the current working directory that is
a subdirectory of the first element in the viewpath.
Viewpathing does not affect the locations of output files. All temporary files
will be unaffected and all other output files (such as executables, object files,
etc.) will be created relative to the root node.
If a file located in a directory down the viewpath (for example, in the second
or third node) is to be opened for modification (for example, to add files to
an archive or to edit a text file), then the original file will first be copied into
a location relative to the root node. Then the new copy will be opened for
modification. Hence, your modification will not affect the development group’s
files.
Note When you create a file for output in your root node, the intermediate
directories are not created in the root node, even if the corresponding directory
path exists in the viewpath.
Usage
To enable viewpathing, set the NVPATH environment variable and do not set the
GHS_VP_NONE environment variable.
Environment Variable Meaning
NVPATH Enables viewpathing. Use colons to separate the
pathnames.
GHS_VP_NONE Disables viewpathing.
GHS_VP_DEBUG Enables the diagnostic output.
GHS_VP_SLOW Disables a performance optimization where files that
are opened for creation and not updating are not
copied down the viewpath if they already exist.
Example
This example requires three existing directories (/test/local, /test/group, and
/test/global) and three non-empty files (/test/local/file3.c, /test/group/file2.c,
and /test/global/file1.c):
</test>: pwd
/test
</test>: ls -Agd */*
-rw-rw-r-- 1 green 7 Feb 11 15:56 global/file1.c
-rw-rw-r-- 1 green 15 Feb 11 15:58 group/file2.c
-rw-rw-r-- 1 green 34 Feb 11 15:55 local/file3.c
</test>: cd local
</test/local>: setenv NVPATH "/test/local:/test/group:/test/global"
</test/local>: setenv GHS_VP_DEBUG 1
</test/local>: ax crv archive.a file1.c file2.c file3.c
ax: info: Viewpathing support is ON (FAST).
ax: info: Adding viewpath node 1: /test/local
ax: info: Adding viewpath node 2: /test/group
ax: info: Adding viewpath node 3: /test/global
a - file1.c
ax: info: Located file: /test/global/file1.c
a - file2.c
ax: info: Located file: /test/group/file2.c
a - file3.c
</test>: cd ..
</test>: ls -Agd */*
-rw-rw-r-- 1 green 7 Feb 11 15:56 global/file1.
-rw-rw-r-- 1 green 15 Feb 11 15:58 group/file2.c
-rw-rw-r-- 1 green 246 Feb 11 16:05 local/archive.a
-rw-rw-r-- 1 green 34 Feb 11 15:55 local/file3.c
</test>: cd local
</test/local>: ax tv archive.a
ax: info: Viewpathing support is ON (FAST).
ax: info: Adding viewpath node 1: /test/local
ax: info: Adding viewpath node 2: /test/group
ax: info: Adding viewpath node 3: /test/global
rw-rw-r-- 4025/28 7 Feb 11 15:56 1998 file1.c
rw-rw-r-- 4025/28 15 Feb 11 15:58 1998 file2.c
rw-rw-r-- 4025/28 34 Feb 11 15:55 1998 file3.c
</test/local>: echo "Completely new and larger file 1" > file1.c
</test/local>: ls -Ag
total 6
-rw-rw-r-- 1 green 246 Feb 11 16:05 archive.a
-rw-rw-r-- 1 green 32 Feb 11 16:09 file1.c
-rw-rw-r-- 1 green 34 Feb 11 15:55 file3.c
</test/local>: ax r archive.a file1.c
ax: info: Viewpathing support is ON (FAST).
ax: info: Adding viewpath node 1: /test/local
ax: info: Adding viewpath node 2: /test/group
ax: info: Adding viewpath node 3: /test/global
</test/local>: ax tv archive.a
ax: info: Viewpathing support is ON (FAST).
ax: info: Adding viewpath node 1: /test/local
ax: info: Adding viewpath node 2: /test/group
ax: info: Adding viewpath node 3: /test/global
rw-rw-r-- 4025/28 32 Feb 11 16:09 1998 file1.c
rw-rw-r-- 4025/28 15 Feb 11 15:58 1998 file2.c
rw-rw-r-- 4025/28 34 Feb 11 15:55 1998 file3.c
If your program does not use floating-point operations, you can reduce the size
of your program by building it with special versions of certain library functions,
such as printf, that do not use any floating-point code.
Specifying that your program does not use floating-point operations has two
effects:
• The compiler gives a fatal error for any floating-point constants and for
any use of the reserved words float and double. This prevents any
floating-point value or operation from appearing in the C source code.
• The linker searches a special library that has non-floating-point versions
of library functions before searching the regular libraries. If any of these
functions are used, the non-floating-point versions are loaded in place of
the floating-point versions.
These options control various aspects of the compilation, assembly, and linking
of your project, and are presented in the following format in this chapter:
Builder Option
Description of option.
• Setting (Equivalent Driver Option) — Description of setting.
To set options in the Builder, click Edit → Set Options to open the Options
window (see “Setting Builder Options” on page 50).
To search for options in the Options window, click the Search button ( ) and
enter a text string to search for (see “Searching For Options” on page 58).
To pass options to the compiler driver, add them to your command line or
makefile. For more information about using the driver, see Chapter 3, “The
Compiler Driver”.
Target Options
This is a top-level option category.
Auto-Interrupt Table
Controls whether the compiler will generate an interrupt table. Permitted settings
for this option are:
• On (-auto_interrupt_table) — [default] Enables generation of an interrupt
table.
• Off (-no_auto_interrupt_table) — Disables generation of an interrupt table.
For more information, see “Writing Interrupt Routines” on page 120.
Floating-Point
This option category is contained within Target.
These options control how floating-point operations are performed. The default
setting depends on whether your target has a built-in floating-point unit, or FPU.
Floating-Point Coprocessor
Permitted settings for this option are:
• No Floating-Point (-fnone) — Disallows all floating-point operations (and
directs the C and C++ compilers to give an error for any use of floating-point
variables or constants), thus greatly reducing the size of such library functions
as printf and scanf. Passes -D__NoFloat to allow source code and
header files to hide references to floating-point objects. If your code uses
floating-point operations, then an error will be generated. This option implies
-nofloatio.
Since this setting requires support from the system libraries and header files, it
is not supported for environments using embedded operating systems with
their own C or C++ headers and libraries.
• FPAHardware Coprocessor (-fhard) — Specifies hardware floating-point
(HFP) mode using the FPA coprocessor, in which the compiler uses
floating-point registers to hold floating-point data and to perform floating-point
operations. This setting is only supported for targets with a built-in FPA fpu
and is the default for MicroRAD boards.
• VFPHardware Coprocessor (-fpu=vfp) — Specifies hardware floating-point
(HFP) mode using the VFP coprocessor, in which the compiler uses
floating-point registers to hold floating-point data and to perform floating-point
operations. This setting is only supported for v5 or higher architectures with
an optional VFP fpu.
• Software Emulation (-fsoft) — Specifies software floating-point (SFP)
mode, in which the compiler uses integer registers to hold floating-point data
and generates library subroutine calls to emulate floating-point operations,
regardless of the capabilities of the selected processor. This is the default
for targets without an fpu. If the target has an fpu, then this option selects a
different set of libraries.
Memory Models
This option category is contained within Target.
Far Calls
Controls whether the compiler will generate a far call for every call. Permitted
settings for this option are:
• Make All Calls Far Calls (-farcalls) — Enables generation of a far function
call for every call. This allows for functions to be located at any distance from
the caller.
• Make No Far Calls (-nofarcalls) — [default] Disables generation of far
function calls. Large programs or programs with discontinuous text sections
may not link if the range of the call instruction is exceeded.
For more information, see “Near and Far Function Calls” on page 115.
Linker-Based Far Call Patching
Controls a linker-based optimization which generates far calls only for calls which
are out of range and would otherwise fail. This option will generally produce
smaller code than generating far calls for every call (see above). Permitted
settings for this option are:
• Patch Far Calls When Necessary (-farcallpatch) — [default]
• Do Not Patch Far Calls (-nofarcallpatch)
Placement of Zero-Initialized Data
Controls the allocation of variables and arrays explicitly initialized to zero.
Allocating such objects to an uninitialized section will generally reduce the size of
the executable ROM image. Permitted settings for this option are:
• Place Zero-Initialized Data in .bss (-discard_zero_initializers) — [default]
Allocates variables and arrays explicitly initialized to zero to the .bss section.
• Place Zero-Initialized Data in .data (-no_discard_zero_initializers) —
Allocates variables and arrays explicitly initialized to zero to the .data section.
In certain circumstances, the optimizer may determine that the allocation of
uninitialized variables or arrays to .data will produce more efficient code (see
“Data Definition Movement” on page 646).
Global Registers
Reserves up to 3 registers (r4, r5, and r6 in that order) to hold global variables.
The equivalent driver option is:
• -globalreg=n
For more information, see “Storing Global Variables in Registers” on page 118.
Data Model
Permitted settings for this option are:
• Data addresses are 24 bits (-data_model=small) —
• Data addresses are 32 bits (-data_model=large) —
Data Model
Permitted settings for this option are:
• Code addresses are 24 bits (-code_model=small) —
• Code addresses are 32 bits (-code_model=large) —
Instruction Set
This option category is contained within Target.
Operating System
This option category is contained within Target.
These options are only available when your project specifies an embedded
operating system.
Shared Libraries
Controls whether the application may link in shared libraries. Permitted settings
for this option are:
• No Shared Libraries (-non_shared)
• Link With Shared Libraries (-call_shared) — [default]
OS Directory
Specifies the root of the operating system distribution. The equivalent driver
option is:
• -os_dir directory
Event Logging
This option is available for ThreadX projects only.
Controls event logging, which collects event data for viewing and analysis in the
MULTI EventAnalyzer. Permitted settings for this option are:
• On (-event_logging) — Enables event logging by defining the
TX_EVENT_LOGGING preprocessor symbol.
• Off (-no_event_logging) — [default]
Use ThreadX Demo Library
This option is available for ThreadX projects only.
Controls the ThreadX library to use. Permitted settings for this option are:
• On (-use_demo_library) — Use a demonstration version of ThreadX provided
with MULTI for evaluation purposes.
• Off (-no_use_demo_library) — [default] Use the standard ThreadX library.
ThreadX Demo Library Directory
This option is available for ThreadX projects only.
Specifies the location of the ThreadX demo library. The equivalent driver option is:
• -threadx_demo_dir directory
Kernel Project
This option is available for INTEGRITY projects only.
Controls whether the project is to be linked as a kernel or as a standard application.
Permitted settings for this option are:
• On (Link with the default kernel) (-kernel) — Specifies linking with the
default INTEGRITY kernel library. This kernel library is fully featured and
provides full debug support.
• Off (-no_kernel) — Specifies that no INTEGRITY kernel library be linked in.
• Link with kernel optimized for production use (-kernel=kernel_opt) —
Specifies linking with a production-optimized INTEGRITY kernel library. This
kernel library is fully featured, and has run-mode debug support stripped out.
• Link with kernel optimized for minimal size (no MMU support)
(-kernel=kernel_small) — Specifies linking with an INTEGRITY kernel library
optimized for minimal size. This kernel library provides no virtual memory,
run-mode debug, or console output support, and has some other capabilities
disabled as well.
• Link with kernel optimized for maximum speed (no MMU support)
(-kernel=kernel_fast) — Specifies linking with an INTEGRITY kernel library
optimized for maximum speed. This kernel library provides no virtual memory
or run-mode debug support, and has some other capabilities disabled as well.
• Link with kernel with checked debug output enabled
(-kernel=kernel_checked) — Specifies linking with an INTEGRITY kernel
library that is fully featured, and provides extra debug output and internal
error checking for debug purposes.
• Link with kernel with no MMU support (-kernel=kernel_novirt) — Specifies
linking with an INTEGRITY kernel library that provides no virtual memory
support, and is otherwise fully featured.
• Link with kernel with no MMU or cache support (ARM only)
(-kernel=kernel_nommu) — Specifies linking with an INTEGRITY kernel
library that provides no MMU or cache support, and is otherwise fully featured
(ARM only).
Include libbsp.a
This option is available for INTEGRITY projects only.
Controls whether your INTEGRITY kernel application will link against libbsp.a.
Permitted settings for this option are:
• On (-libbsp) — [default]
• Off (-no_libbsp)
This option has no effect if you are not building an INTEGRITY kernel project.
Relocatable Module
Permitted settings for this option are:
• On (-irel) —
• Off (-no_irel) —
Relocatable Module Base Image
The equivalent driver option is:
• -dyload —
Full POSIX-2001 Compilation Support
Permitted settings for this option are:
• On (--integrity_posix) —
• Off (--no_integrity_posix) —
Dynamic Download Project
This option is available for INTEGRITY projects only.
Controls whether the project will be linked to be suitable for downloading to a
running kernel. Permitted settings for this option are:
• On (-dynamic) — Is ignored if an .int file is specified.
• Off (-no_dynamic) — [default]
Display BootTable
This option is available for INTEGRITY projects only.
Controls the build-time display of the BootTable that the kernel processes at run
time. Permitted settings for this option are:
• On (-display_boot)
• Off (-no_display_boot) — [default]
Delete Unused Kernel Calls
This option is available for INTEGRITY projects only.
Controls the deletion of unused kernel calls from the final image. Permitted
settings for this option are:
• On (-generatemonolithdeletions)
The deletion is based on physical and virtual kernel calls referenced in the
component AddressSpaces. This option may cause unpredictable errors if used
in the compilation of a dynamic download project which could use a deleted kernel
call.
Project Options
This is a top-level option category.
These options allow you to control basic configuration settings for your project,
such as source, output and include directories.
Include Directories
Specifies a directory in which the builder should search for header files. The
equivalent driver option is:
• -Idirectory
When the compiler processes source files that have #include "header_file"
or #include <header_file> directives, it looks for header_file in any
directories specified with this option. You can specify multiple directories, and the
compiler will search them in the order in which they are specified. If the source
file’s #include directive declares a full path to the header file, then the compiler
ignores any directories specified with this option.
For a detailed discussion of how the compiler searches for included files, see
“Instructing the Compiler to Search for Your Headers” on page 96.
Library Directories
Specifies a directory in which the builder should search for libraries. The
equivalent driver option is:
• -Ldirectory
Libraries
Specifies a library for the builder to link against. The equivalent driver option is:
• -llibrary
This option accepts an abbreviated library notation, which is derived by removing
the lib prefix and filename extension from the name of the library file. For example,
my specifies the library libmy.a.
You can specify multiple libraries, and they will be linked against in the order
specified. When using the driver, each library must be specified with it’s own
-l option, for example:
In order to prevent multiply defined symbols, we recommend that you list your
source files on the command line first, and then any -llibrary libraries.
Source Directories Relative to This File
Specifies a directory in which the builder should search for source files. The
syntax for this option is:
• :sourceDir=directory
This is a Builder-only option. There is no equivalent driver option.
Optimization Options
This is a top-level option category.
Green Hills provides a wide range of optimizations to help you produce smaller
and/or faster executables.
For detailed descriptions of all the optimizations, see Chapter 19, “Optimization
Descriptions”. For additional, more specialized options, see “Advanced
Optimization Options” on page 203.
Optimization Strategy
Specifies the high-level optimization strategy. Permitted settings for this option are:
• Optimize for Size (-Ospace) — Enables all the optimizations which improve
both size and performance, and special optimizations which improve code size
at the expense of performance. Any optimization which is expected to increase
code size is disabled. For example, loop unrolling and function inlining are
usually not performed when this setting is selected, and some operations may
be performed by calling library routines rather than generating inline code.
• Optimize for General Use (-O) — Enables all the optimizations which improve
both performance and size, or which improve performance without dramatically
increasing size.
• Optimize for Speed (-Ospeed) — Enables all the optimizations which improve
both size and performance, and which improve performance at the expense of
size. No optimization intended to reduce code size is enabled. This option
is recommended for generating the fastest possible code without the use
of two-pass inlining.
• No Optimizations (-Onone) — [default] Disable all optimizations.
Intermodule Inlining
Enables all the General Use optimizations together with two-pass inlining.
Permitted settings for this option are:
• On (-OI)
• Off (-Onoinline) — [default]
For more information, see “Inlining Optimizations” on page 625.
Linker Optimizations
Controls the linker optimizations listed in “Linker Optimizations” on page 186.
Permitted settings for this option are:
• On (-Olink) — The linker optimizations that are enabled will depend upon
whether you are optimizing for speed or size. Many of these optimizations
make complex changes to your code, and may slow down the link stage,
be harder to debug, or have other drawbacks. To disable individual linker
optimizations, set them to Off in combination with this option.
• Off (-Onolink) — [default]
Optimization Scope
This option category is contained within Optimization.
Individual Functions
This option category is contained within Optimization.
Debugging Options
This is a top-level option category.
Note You can perform run-time error checking without the MULTI Debugger
by rebuilding your application with run-time error checking enabled, and
running a series of validations. You can also hook the run-time error checking
reporting to automatically report any failures that are detected. The following is
an example of how to set up this feature:
Under Project Type, scroll down the list and select Example (Custom
Run-Time Error Checking).
• Custom Run-Time Error Checking is not displayed as an option on
configurations that do not support run-time error checking.
4. Click Finish. After the project is created, a new window appears.
5. Scroll down the list and open user_defined_handler.c. You will find
sample code that will help you set up custom run-time error checking
without the MULTI Debugger.
Preprocessor Options
This is a top-level option category.
These options control the preprocessor. For information about the Green Hills
predefined macros, see “Predefined Macro Names” on page 512.
#undef symbol
These options control various aspects of compilation that relate directly to the
C and C++ languages.
This may behave unexpectedly because an int type may not be used to access
an object of the float type.
.c Files are C++
Controls how the compiler treats files ending with the .c extension. Permitted
settings for this option are:
• On (-dotciscxx) — Interpret .c files as C++.
• Off (-nodotciscxx) — [default] Interpret .c files as C.
MISRA C
This option category is contained within C/C++ Compiler.
The options in this section are only available with the New Generation Compiler.
This section contains options which allow you to control checking of compliance
with the Motor Industry Software Reliability Association (MISRA) rules, a
set of guidelines for the C programming language that is designed to enforce
good practices in the development of embedded automotive systems. Complete
details can be found in the Guidelines For The Use Of The C Language In
Vehicle Based Software, Motor Industry Software Reliability Association, April
1998 book. For more information, see the MISRA (http://www.misra.org.uk/)
web site.
The MISRA rules are organized into 17 groups, each focusing on a particular C
language topic (for example: types, functions, expressions, the C preprocessor,
etc). Each group has an associated option below.
We also provide options to control the severity of messages which alert you
to violations of the rules. Most of the messages are given at compile time,
although some are generated at run-time. Because run-time checking can
adversely affect code performance, an option is provided to disable it.
Note A single driver option allows you to enable any or all of the MISRA
rules. It may be used in any of the following forms (where n is a rule number
from the list below):
Data Types
This option category is contained within C/C++ Compiler.
Signedness of Bitfields
Specifies the signedness of the bitfield type. Permitted settings for this option
are:
• Signed (--signed_fields)
• Unsigned (--unsigned_fields) — [default]
Note that single bit int fields in the Compatibility Mode Compiler are controlled by
this option, but in the New Generation Compiler these fields are always unsigned.
Signedness of Pointers
Specifies the signedness of pointers and addresses. Permitted settings for this
option are:
• Signed (--signed_pointer) — [default]
• Unsigned (--unsigned_pointer)
Signedness of Enum Type
Specifies the signedness of the enum type. Permitted settings for this option are:
• Signed (--signed_enum_fields)
• Unsigned (--unsigned_enum_fields) — [default]
Use Smallest Type Possible for Enum
Controls the allocation of enumerations. Permitted settings for this option are:
• On (--short_enum) — Store enumerations in the smallest possible type.
• Off (--no_short_enum) — [default] Store enumerations as integers.
Long Long Support
Controls support for the long long data type. Permitted settings for this option
are:
• On (--long_long) — [default]
• Off (--no_long_long)
These options control the alignment and packing of various data objects in
memory. See also #pragma pack (n), in “General #pragma Directives”
on page 527.
Minimum Structure Alignment
Controls the minimal alignment of all objects of types struct, class, and union.
Permitted settings for this option are:
• 1-byte (--struct_min_alignment=1) — [default]
• 2-byte (--struct_min_alignment=2)
• 4-byte (--struct_min_alignment=4)
• 8-byte (--struct_min_alignment=8)
Packing (Maximum Structure Alignment)
Controls the default maximum alignment of all objects of types struct and
class. Permitted settings for this option are:
• 1-byte (-pack=1)
• 2-byte (-pack=2)
• 4-byte (-pack=4)
• 8-byte (-pack=8) — [default]
No struct or class or member of a struct or class will have an alignment
greater than the specified value, unless the setting is overridden by the #pragma
pack directive (see “General #pragma Directives” on page 527).
Special Tokens
This option category is contained within C/C++ Compiler.
C++
This option category is contained within C/C++ Compiler.
Namespaces
This option category is contained within C/C++ Compiler→C++.
Keyword Support
This option category is contained within C/C++ Compiler→C++.
Constructors/Destructors
This option category is contained within C/C++ Compiler→C++.
RTTI Support
This option category is contained within C/C++ Compiler→C++.
Virtual Tables
This option category is contained within C/C++ Compiler→C++.
Templates
This option category is contained within C/C++ Compiler→C++.
These options control C++ template instantiation. For a full description of this
feature, see “Template Instantiation” on page 481.
Auto-Instantiation of Templates
Controls automatic instantiation of templates. Permitted settings for this option are:
• On (--auto_instantiation) — [default]
• Off (--no_auto_instantiation) — If you disable automatic instantiation, you
must ensure that the necessary entities are instantiated manually with C/C++
Compiler→C++→Templates→Manual Template Instantiation Mode, or
with #pragma directives in your code.
Manual Template Instantiation Mode
Manually controls instantiation of external template entities. External template
entities are non-inline and non-static template functions and template static data
members. The instantiation mode determines the template entities for which code
should be generated. Permitted settings for this option are:
• All (-tall) — Instantiates all template entities whether or not they are used. For
each fully instantiated template class, all of its member functions and static
data members are instantiated whether or not they are used. Nonmember
template functions are instantiated even if the only reference was a declaration.
• Local Only (-tlocal) — Instantiates only the template entities that are used in
this compilation, and forces those entities to be local to this compilation. This
is intended to provide a very simple mechanism for those new to working
with templates. The compiler will instantiate the functions that are used in
each compilation unit as local functions, and the program will link and run
correctly (barring problems due to multiple copies of local static variables).
However, one may end up with many copies of the instantiated functions,
so this is not suitable for production use. This setting disables C/C++
Compiler→C++→Templates→Auto-Instantiation of Templates.
• Used Only (-tused) — Instantiates only the template entities that are used
in this compilation. This includes all static data members for which there are
template definitions.
• None (-tnone) — [default] Instantiates no template
entities. This is usually the appropriate setting when C/C++
Compiler→C++→Templates→Auto-Instantiation of Templates is enabled.
PCH Messages
Controls the display of the message which reports the creation or use of a
precompiled header file. Permitted settings for this option are:
• On (--pch_messages) — [default]
• Off (--no_pch_messages)
Assembler Options
This is a top-level option category.
or:
For a full list of assembler options which may be passed in this manner, see
Chapter 7, “The asarm Assembler”.
-nogen
-ref
-w
For a full list of assembler options which may be passed in this manner, see
Chapter 7, “The asarm Assembler”.
Linker Options
This is a top-level option category.
Executable Stripping
Controls stripping the executable at the conclusion of linking. Permitted settings
for this option are:
• On (-strip) — Stripping involves removing line number, symbol table, and
debugging information to reduce the file size of the executable.
• Off (-nostrip) — [default]
For information about stripping executables after link-time, see “The gstrip Utility
Program” on page 389.
Start Address Symbol
Specifies the symbol whose address will be used as the program entry point or
start address. Permitted settings for this option are:
• Start Address (-e symbol) —The default symbol is _start.
• No Entry Synbol (-noentry)
Linker Directives Directory
Specifies a directory in which to search for linker directives files. The equivalent
driver option is:
• -directive_dir directory
Preprocess Linker Directives Files
Controls whether linker directives files are preprocessed. Permitted settings for
this option are:
• On (--preprocess_linker_directive)
• Off (--no_preprocess_linker_directive) — [default]
Linker Warnings
Controls the display of linker warnings. Permitted settings for this option are:
• Display (-linker_warnings) — [default]
• Suppress (-no_linker_warnings)
Additional Linker Options (before .ld files)
Passes the specified linker options to the elxr linker command line before any .ld
files. The equivalent driver option is:
• -Wl,option[,option]…
-lnk="-multiple -undefined"
or:
-lnk=-multiple -lnk=-undefined
For a full list of linker options which may be passed in this manner, see Chapter 9,
“The elxr Linker”. The option is passed to the linker in approximately the position
in which it appears on the driver command line.
Linker Command File
Passes the options specified in file directly to the linker. The equivalent driver
option is:
• -lnkcmd=file
The file must contain only one linker option per line. For example:
-nogen
-ref
-w
For a full list of linker options which may be passed in this manner, see “Linker
Options” on page 183.
Linker Optimizations
This option category is contained within Linker.
Symbols
This option category is contained within Linker.
Link-Time Checking
This option category is contained within Linker.
These options control the type, form, and quantity of diagnostic messages you
may receive during building.
Warnings
Controls the display of warnings for most Green Hills tools. Permitted settings
for this option are:
• Display (--warnings) — [default]
• Suppress (-w)
Remarks
Controls the display of remarks for most Green Hills tools. Permitted settings
for this option are:
• Display (--remarks)
• Suppress (--no_remarks) — [default]
Maximum Number of Errors to Display
Limits to n the number of error messages the compiler will print before quitting.
The default is 100 and the minimum is 2.
The equivalent driver option is:
• -errmax=n
Redirect Error Output to File
Specifies a file to which all error output is redirected. The equivalent driver option
is:
• -stderr=file
Quit Building if Warnings are Generated
Controls whether building will cease upon the generation of any warning.
Permitted settings for this option are:
• On (--quit_after_warnings)
• Off (--no_quit_after_warnings) — [default]
Display Version Information
Instructs the compiler and other tools to print its copyright banner and version
number. Permitted settings for this option are:
• On (-V)
• Off (--no_version) — [default]
C/C++ Messages
This option category is contained within Compiler Diagnostics.
These options control various diagnostic messages specific to the C and C++
languages.
These options allow you to increase or decrease the severity of any of the C and
C++ compiler diagnostic messages.
Values for the error number, n, can be obtained by enabling the Compiler
Diagnostics→C/C++ Messages→Varying Message Severity→Display Error
Message Numbers (--display_error_number) option (see below). The
complete set of error numbers is also listed in the online only MULTI: C and
C++ Compiler Error Messages.
Set Message to Error
Sets the specified diagnostics message to the level of error. The equivalent driver
option is:
• --diag_error n[,n2]...
Set Message to Warning
Sets the specified diagnostics message to the level of warning. The equivalent
driver option is:
• --diag_warning n[,n2]...
Set Message to Remark
Sets the specified diagnostics message to the level of remark. The equivalent
driver option is:
• --diag_remark n[,n2]...
Set Message to Silent
Sets the specified diagnostics message to the level of silent. The equivalent driver
option is:
• --diag_suppress n[,n2]...
Advanced Options
This is a top-level option category.
These options control advanced settings that affect compilation for your target.
For more common options, see “Target Options” on page 131.
Target Processor
Specifies code generation for a particular target processor.
If you specify a processor, the driver selects the appropriate instruction set and
a generic .ld file. For more information about these .ld files, see “Working with
Linker Directives Files” on page 43. You can override the default .ld file by
specifying an alternate linker directives file elsewhere on the command line. For a
more detailed discussion on .ld files, see “Linker Directives Files” on page 285.
The equivalent driver option is:
• Generic CPU (-cpu=cpu) — To obtain a list of supported processors from the
command line, enter -cpu=? (or -cpu=\? in many shells).
Initialization of PIC Pointers
Controls extensions in the compiler, linker, and libraries which enable special fixup
operations to be performed at program startup. These operations adjust the initial
values of all pointers to reflect the addresses where the objects were loaded at run
time. Permitted settings for this option are:
• On (--initpipointers) — [default]
• Off (--no_initpipointers)
For more information, see “Customizing the Run-Time Environment Program
Sections” on page 299.
Support For Very Large Switch Statements
Controls the size of switch statement offset entries. Permitted settings for this
option are:
• On (-bigswitch) — Use a 32-bit offset.
• Off (-nobigswitch) — [default] Use a 16-bit offset, which is smaller and faster,
but which will fail if a label is too far away.
Temporary Output
Controls whether temporary files generated during compilation are retained.
Permitted settings for this option are:
• Retain (-keeptempfiles) — Prevents the deletion of temporary files after they
are used. If an assembly language file is created by the compiler, this option
will place it in the current directory instead of the temporary directory.
• Delete (-nokeeptempfiles) — [default]
Non-Standard Output Suffix
Controls the acceptance of non-standard output suffixes. Permitted settings for
this option are:
• Accepted (--any_output_suffix)
• Not Accepted (--no_any_output_suffix) — [default]
Source Directories Relative to Top-Level Project
Specifies a directory in which the builder should search for source files. The
syntax for this option is:
• :sourceDirNonRelative=directory
This is a Builder-only option. There is no equivalent driver option.
Intermediate Output Directory Relative to This File
Specifies the path to where object files (and any custom file types) are written,
relative to the location of the current .gpj project file. The syntax for this option is:
• :outputDirRelative=directory
This is a Builder-only option. There is no equivalent driver option.
Binary Output Directory Relative to Top-Level Project
Specifies the path to where final executable output files are written, relative to the
location of your top-level default.gpj project file. The syntax for this option is:
• :binDir=directory
This is a Builder-only option. There is no equivalent driver option.
Binary Output Directory Relative to This File
Specifies the path to where final executable output files are written, relative to the
location of the current .gpj project file. The syntax for this option is:
• :binDirRelative=directory
This is a Builder-only option. There is no equivalent driver option.
Dependencies Relative to Source Directory
Specifies that the present file must be rebuilt if the specified file, relative to the
location of your source directory, changes. The syntax for this option is:
• :depends=filename
This is a Builder-only option. There is no equivalent driver option.
These options provide very low-level control over various minor optimizations.
These optimizations are generally controlled most effectively by the compiler
when you specify an Optimization→Optimization Strategy, and you should
not use these options unless you have very particular optimization needs. For
more common options, see “Optimization Options” on page 143.
Inline Tiny Functions
Controls the inlining of very small functions. Permitted settings for this option are:
• On (--inline_tiny_functions) — This setting is implied by
Optimization→Optimization Strategy is enabled unless
Debugging→Debugging Level is also enabled.
• Off (--no_inline_tiny_functions) — [default]
For more information, see “Automatic Inlining” on page 625.
Inline C Memory Functions
Controls the inlining of C Memory Functions. Permitted settings for this option are:
• On (-Omemfuncs)
• Off (-Onomemfuncs) — [default]
For more information, see “Inlining of C Memory Functions” on page 632.
Inline C String Functions
Controls the inlining of C String Functions. Permitted settings for this option are:
• On (-Ostrfuncs)
• Off (-Onostrfuncs) — [default]
For more information, see “Inlining of C String Functions” on page 633.
Loop Unrolling
Controls the Loop Unrolling optimization. Permitted settings for this option are:
• On (-Ounroll)
• Off (-Onounroll) — [default]
For more information, see “Loop Unrolling” on page 639.
Conditional Instructions
Controls the use of conditional instructions as an optimization. Permitted settings
for this option are:
• On (-Ocond)
• Off (-Onocond) — [default]
For more information, see “Conditional Instructions” on page 644.
GNU Compatibility Optimizations
Provides compatibility with the general GNU optimization options. Permitted
settings for this option are:
• O1 (-O1) — Turns on all the -O optimizations.
• O2 (-O2) — Turns on all the -O1 optimizations, loop strength reduction, and
loop invariant analysis. For further details, see “Loop Optimizations” on page
636.
• O3 (-O3) — Turns on all the -O2 optimizations and two-pass inlining. For
further details, see “Inlining Optimizations” on page 625.
• O0 (-O0) — [default] No optimizations.
These options provide control over advanced debugging features. For more
common options, see “Debugging Options” on page 147.
Generate Target-Walkable Stack
Creates a frame pointer in register r11. You can use this option to perform
stack traces if you do not have debugging information. The current ARM libraries
are built with this option to support stack traces. Without this option, some
routines do not create a stack frame (in order to reduce code size and improve
performance). Note that this option may produce unexpected complications, such
as disabling good leaf procedure optimization. Using this option without setting
Debugging→Debugging Level to MULTI (-G) may only guarantee a stack trace
and use of the return button in the MULTI Debugger. Permitted settings for this
option are:
• On (-gtws)
• Off (-nogtws) — [default]
These options allow you to vary the amount of debugging information that will
be generated for use with the MULTI Debugger. Note that reducing the amount
of information collected may speed up performance, but it may also reduce the
depth of analysis available through the Debugger.
Cross-Reference Information
This option is only available with the New Generation Compiler.
Controls the amount of debugging cross-referencing information that is generated.
By default, the compiler generates cross-reference data for each user-defined
construct (describing where the construct is declared, defined, read from, written
to, and so on), to allow the Debugger to display cross references. Permitted
settings for this option are:
• Generate for All Objects (--xref=full) — [default] Generates cross-referencing
data for all objects.
• Generate for Object Declarations and Definitions (--xref=declare) —
Generates cross-referencing data only for the declarations and definitions of
the objects.
• Generate for Objects in the Global Scope (--xref=global) — Generates
cross-referencing data for the objects that are declared in the global scope.
• Do Not Generate (--xref=none) — Disables all cross-referencing data.
Debugging Information
Controls the generation of debugging information for types and defines that are
never used in a file. Permitted settings for this option are:
• All (-full_debug_info) — Enables the generation of debugging information
for types and defines that are never used in a file.
• Reduced (-no_full_debug_info) — [default] Disables the generation of
debugging information for types and defines that are never used in a file.
Macro Debugging Information
Controls whether debugging information is generated for all macros, or only for
those that are used. Permitted settings for this option are:
• All (-full_macro_debug_info)
• Reduced (-no_full_macro_debug_info) — [default]
These options control the generation of alternate native debugging formats. Use
them only if you use third-party tools that require native debugging information.
The MULTI Debugger only uses the .dbo format.
Generate MULTI and Native Information
Enables the generation of DWARF, COFF, or BSD debugging information in the
object file (in addition to the Green Hills .dbo format), according to the convention
for your target. Permitted settings for this option are:
• On (-dual_debug)
• Off (-no_dual_debug) — [default]
Requires that the Debugging→Debugging Level be set to Plain or MULTI for the
option to have any affect (see “Debugging Options” on page 147).
Convert DWARF Files to MULTI (.dbo) Format
Controls the conversion of DWARF debugging information to the MULTI .dbo
format. Permitted settings for this option are:
• On (-dwarf_to_dbo)
• Off (-no_dwarf2dbo) — [default]
This option will normally be invoked automatically when necessary by the builder.
Convert Stabs Files to MULTI (.dbo) Format
Controls the conversion of Stabs debugging information to the MULTI .dbo format.
Permitted settings for this option are:
• On (-stabs_to_dbo)
• Off (-no_stabs2dbo) — [default]
This option will normally be invoked automatically when necessary by the builder.
#include "test.h"
#include "sub/../test.h"
(Unix) The compiler detects that both #include directives refer to the same file.
Files to Pre-Include
Includes the source code of the specified filename at the beginning of the
compilation. The equivalent driver option is:
• -include filename
This can be used to establish standard macro definitions, and so on. The filename
is searched for in the directories on the include search list.
Definition of Standard Symbols
Controls the definition of the set of default symbols. Permitted settings for this
option are:
• Define (-stddef) — [default]
• Do Not Define (-nostddef)
By default, the Builder and driver search for header files in various standard
directories provided with your distribution. These options allow you to vary the
location of these standard directories.
Standard Include Directories
Controls whether the standard include directories are searched. Permitted settings
for this option are:
• Search (-stdinc) — [default]
• Do Not Search (-nostdinc)
C Include Directories
Changes the default location in which the compiler searches for C header files.
The equivalent driver option is:
• -c_include_directory directory
C++ Include Directories
Specifies a directory in which the builder should search for C++ header files.
The equivalent driver option is:
• --cxx_include_directory directory
These options control advanced C and C++ compilation settings. For more
common options, see “C/C++ Compiler Options” on page 151.
ANSI C and Standard C++ Extensions
This option is only available with the New Generation Compiler.
Controls the treatment of the “ANSI C Extensions” on page 407 and the “Standard
C++ Extensions” on page 465. Permitted settings for this option are:
• Errors (--discretionary_errors) — [default for Strict ANSI C (-ANSI) and
Standard C++ (Violations Give Errors) (--STD)]
• Warnings (--discretionary_warnings) — [default for Standard C++
(Violations Give Warnings) (--std)]
This option only affects projects where the C/C++ Compiler→C Language
Dialect option is set to Strict ANSI C (-ANSI) or the C/C++ Compiler→C++
Language Dialect option is set to Standard C++ (Violations Give Errors)
(--STD) or Standard C++ (Violations Give Warnings) (--std).
Overloading of enums
Controls support for using operator functions to overload built-in operations on
enum-typed operands. Permitted settings for this option are:
• On (--enum_overloading) — [default]
• Off (--no_enum_overloading)
Support for Friend Injection
Controls whether the name of a class or function that is declared only in friend
declarations is visible when using normal lookup mechanisms. Permitted settings
for this option are:
• On (--friend_injection) — Friend names are visible to such lookups.
• Off (--no_friend_injection) — [default] Function names are visible only when
using argument-dependent lookups, and class names are never visible.
Temporaries’ Lifetime
Specifies the lifetime for temporaries. Permitted settings for this option are:
• Long (--long_lifetime_temps) — Refer to the earliest of end of scope, end of
switch clause, or next label.
• Short (--short_lifetime_temps) — [default] Refer to the end of full
expressions. This is standard C++.
Tiebreaker Processing Time
Specifies the way that tiebreakers apply in overload resolution. Tiebreakers are
decided through the differences of the type qualifiers (const and volatile).
Permitted settings for this option are:
• Early (--early_tiebreaker) — [default] Consider tiebreakers at the same time
as other measures of the quality of the match of an argument value and the
corresponding parameter type.
• Late (--late_tiebreaker) — Ignore tiebreakers during the initial comparison
and consider them only if two functions are otherwise equally good on all
arguments. The tiebreakers can then be used to choose one function over
another.
Distinct C and C++ Functions
Controls whether identical C and C++ functions are treated as distinct. Permitted
settings for this option are:
• On (--c_and_cpp_functions_are_distinct) — Treat function types as distinct
if their only difference is that one has extern "C" linkage and the other
has extern "C++" routine linkage.
• Off (--no_c_and_cpp_functions_are_distinct) — [default] Do not treat such
functions as distinct.
These options control advanced assembler settings. For more common options,
see “C/C++ Compiler Options” on page 151.
Assembler Warnings
Controls the display of assembler warning messages. Permitted settings for this
option are:
• Display (--assembler_warnings) — [default]
• Suppress (--no_assembler_warnings)
Identifier Definition
Passes the arbitrary string string to the output file. The equivalent driver option is:
• -ident=string
This is the same as using the directive #pragma ident “string” in C (see
“General #pragma Directives” on page 527). This option can be used to place the
date of the source file in the object file.
Identifier Support
Controls support for identifier definition and insertion (via the Builder and driver
options above, and through #pragma ident "string"). Permitted settings
for this option are:
• On (-identoutput) — [default]
• Off (-noidentoutput)
These options control advanced linker settings. For more common options, see
“Linker Options” on page 183.
These options allow you to perform old-style linking, without a linker directives
file.
You should use these options only if instructed to do so by Green Hills support
staff.
X-Switches
Specifies one or more internal compiler switches. The equivalent driver option is:
• -Xswitch
EDG Front End Options
Specifies one or more internal EDG front end options. The equivalent driver
option is:
• --option=option
Change Assembler
Specifies the assembler to use. Permitted settings for this option are:
• Use Old Assembler (-old_assembler)
• Use New Assembler (-new_assembler) — [default]
Debug Information (.dbo) Tracing Diagnostics
Controls the collection of diagnostic information pertaining to a search for .dbo
files. Permitted settings for this option are:
• On (-dbo_trace)
This option is useful if you are seeking support for an incident involving missing
.dbo files.
Dbo File Version
Specifies an older version of .dbo debugging information files, for use with an old
MULTI Debugger. Permitted settings for this option are:
• On (--dbo_version n)
Opens the New Project Wizard, which guides you through the process of creating
a new project. For more information, see “Creating a New Project: The New
Project Wizard” on page 24.
Open Project (Ctrl + O)
Opens a project.
Close Project
Closes the current project.
Save Project (Ctrl + S)
New Window
Opens a new Builder window with no open project.
Exit (Ctrl + Q)
Closes the current Builder window, prompting to save any outstanding changes.
Advanced
Displays the Advanced submenu which offers options to:
• Contract All Within selected file — Recursively contracts the selected file
to hide all its children.
• Expand All Within selected file — Recursively expands the selected file to
show all its children.
• Set Imported Environment Variables — Opens a dialog box that allows
you to import variables from your environment to stand in for strings used in
your option settings.
• Set Options in Parent — Opens the Options window to set Builder options
on the immediate parent of the selected file. For source files, this is the normal
behavior provided by Set Options, but for projects this allows options to be
set for a particular occurrence of the project.
• Simplify All Filenames — Attempts to convert any absolute filenames into
filenames relative to the set source directories. Specifically, if the path of
a file is removed and if the file can still be found by searching the source
directories list, then the full pathname is replaced by the filename without a
path. This is a simple means of converting absolute pathnames in projects
to short relative pathnames, which increases portability. This resolving is
done automatically when files are added, so this functionality is usually only
useful after changing source directories.
To subsequently change your Build Target, select Edit → Set Build target
to open the Target Selector window.
Note Advanced users can add customizing target files, which may define
custom file types or control custom tools. To add such a file, click the
Customizations button, and select a custom .bod file with the file chooser.
An example of how to use this functionality is provided in the C: Custom
File Types example.
Invokes the compiler, assembler, and linker as appropriate, to build the currently
selected files and projects.
Preprocess selected file
Preprocesses the selected file.
This item is available for both source files and Program and Library projects.
Rebuild selected file
Builds the currently selected files after first removing the intermediate output files.
Build Ignoring Errors selected file
Builds the current project, ignoring any detected errors. Normally, the build stops
when an error occurs to prevent downstream failures like a link failing because of
missing objects.
Clean selected file
Deletes all of the files that are normally created when building the project. This
includes object files, libraries, and executables. In other words, at each step where
a file would be created in a normal build, the file is deleted instead. The only files
that remain will be the source files necessary for building the project from scratch.
Advanced Build
Opens the Advanced Build dialog box, through which you can execute builds
with less common options. For more information, see “The Advanced Build
Dialog Box” on page 230.
Settings
Opens the Build Settings dialog box, through which you can set common build
options that will be applied to all normal builds. These settings will be saved when
you close the Builder. For more information, see “The Build Settings Dialog
Box” on page 231.
View Build Details
Opens a window displaying Builder feedback from the latest build.
1 connection
2 connection
3 connection
4 connection
Lists the most recently connected debug servers. To connect to one of them,
select it.
Editor
Opens a file chooser to select a file to open in the Editor.
Start Launcher
Opens the Launcher. For more information, see “The MULTI Launcher” on page 4.
Flash selected program
Opens the Write to Flash Memory dialog box, which allows you to write the
selected program to flash chips on the target. The Flash menu item is not
available if MULTI is connected to multiple targets.
CodeBalance selected program
Opens the selected program in the CodeBalance utility, which analyzes profiling
information to optimize an executable. For more information, see Chapter 12,
“The CodeBalance Optimization Wizard”.
Use Utilities
Opens the Utility Program Launcher dialog box. For more information, see “The
Utility Program Launcher Dialog Box” on page 236.
Convert Legacy Project
Opens a file chooser to select a legacy project (*.bld) to be converted to a new
format project (*.gpj).
Options
Opens the Options dialog box for you to change options that affect the way
the Builder and other MULTI tools look and behave. For more information, see
Chapter 9, “Configuration Options” in the MULTI: Editing Files and Configuring
the IDE book.
To use a utility:
For documentation of all the utilities, see Chapter 11, “Utility Programs”.
ccarm -S main.c
where options are assembler options. When running the assembler directly,
do not use the-asm= option.
Assembler Options
The assembler combines each specified ASCII input_file and produces a single
output object module. For information about using these options with the
Builder or driver, see “Running the Assembler from the Builder or Driver”
on page 242.
Assembler Syntax
Character Set
The assembler recognizes the standard ASCII character set, consisting of
uppercase and lowercase letters (A-Z, a-z), digits (0-9), and a group of special
characters listed in the following table. The assembler also recognizes the
ASCII control characters signifying carriage return, newline, form feed, vertical
tab, and horizontal tab.
Character Name Character Name
’ single quotation mark " double quotation mark
( left parenthesis ) right parenthesis
blank (space) % percent
- minus sign + plus sign
: colon ! exclamation mark
, comma \ backslash
. decimal point (period) * asterisk
& ampersand _ underscore
~ tilde | vertical bar
= equal sign ^ carat
< less than > greater than
/ slash $ dollar sign
@ at sign # number sign
Identifiers
Identifiers, or symbols, are composed of letters, digits, and the following special
characters: dollar sign ($), period (.), and underscore (_). The first character
of an identifier must be alphabetic, or one of these three special characters.
Uppercase and lowercase letters are distinct; the identifier abc is not the same
as the identifier ABC. Characters in reserved symbols, such as directives,
machine instructions, and registers, are case-sensitive.
Examples
The following table shows some valid and invalid identifiers:
Identifier Validity
*star Invalid (may not start with *)
123test Invalid (may not start with digit)
f-ptr Invalid (may not use hyphen)
_hello Valid
LABEL Valid
test4 Valid
Reserved Symbols
The following identifiers are built into ARM assembly language.
Identifier Meaning
a1-a4 Aliases for integer registers r0-r3
f0-f7 Floating-point registers
fp Frame pointer (r11)
lr Link register (r14)
pc Program counter (r15)
r0-r15 Integer registers
sb Alias for integer register r9
sl Alias for integer register r10
sp Stack pointer (r13)
v1-v7 Aliases for integer registers r4-r10
In addition, the names of the special purpose registers (SPR’s) such as XER, LR,
and CTR are reserved. Consult the appropriate microprocessor user’s manual
for the list of implemented SPR’s.
Note In addition, the operator names are reserved. For a list of operators, see
“Scalar Expression Operators” on page 251.
Constants
Assembler constants can be numeric, character, or string constants.
Numeric Constants
A sequence of digits defines a numeric constant. Constants can be specified
in hexadecimal, octal, or binary formats, or as floating-point numbers, by
preceding the number with one of the following special prefixes:
Type Prefix Example
hexadecimal 0x 0xb0b
octal 0 0747
binary 0b 0b110011
floating-point 0f 0f6.02e+23
String Constants
Some directives take a string constant as one or more of their arguments. A
string constant consists of a sequence of characters enclosed in double quotation
marks ("). A string constant can contain any ASCII character (including ASCII
null), except newline. The null character is not appended to strings by the
assembler, as it is in C or C++.
Character Constants
A character constant can be used in any location where an integer constant is
needed.
For example, the character constant ’a’ is equivalent to the decimal integer 97,
and the character constant ’\r’ is equivalent to the decimal integer 13.
Escape
Sequence Character ASCII value
\" double quotation mark 34 (0x22)
\\ backslash in a constant or string 92 (0x5C)
Source Statements
An assembler source statement consists of a series of fields delimited by spaces
and/or horizontal tabs, in the following format:
[label:] operator arguments [comments]
Label Field
See “Labels” on page 253.
Operator Field
The operator field starts with the first non-whitespace character after the
optional label field and is terminated by the first whitespace character or line
terminator encountered after the operator. An operator is any symbolic opcode,
directive, or macro call.
Argument Field
The argument field starts with the first non-whitespace character following the
operator field and ends with a line terminator or the beginning of a comment
field. Arguments qualify the opcode, directive, or macro call.
Comment Field
The comment field is optional and begins with “;”, “@”, or the number symbol
("#"). The # symbol must be in the first column of a line or be followed
by a space to be considered a comment character. The assembler ignores all
characters to the right of the comment symbol until the end of the line.
Continuation Lines
The assembler does not support continuation lines.
Whitespace
Whitespace consists of spaces, form feeds, and horizontal tabs.
Line Terminators
Assembly input lines are terminated by a line feed, a form feed, or a carriage
return.
Expressions
Assignment Statements
An expression is assigned to a symbol by an assignment statement in one of the
following forms, where ident is the symbol name:
ident = const-expr
.set ident,const-expr
The expression specifies any addressing mode that is generated when the
symbol becomes an instruction operand. An assignment in the form of = defines
a local constant, while =: specifies that the symbol is also global.
For example:
a = 1 ; set a to be 1
xyz = 123 ; set xyz to be 123
.set sofa, 7 ; set sofa to be 7 (legal)
.set sofa, 8 ; reset sofa to be 8 (legal)
Operator Precedence
The following table lists the operators in decreasing order of precedence. The
binary operators are associative from left to right:
~ and - (unary)
*, /, %
<<, >>, USHR, ROTR, and ROTL
+ and - (binary)
=, .equ, <, >, <=, >=, ULT, UGT, ULE, and UGE
== and !=
&
^
|
Expression Types
The primary expression types are:
Expression type Meaning
absolute A value of an identifier or expression that is computed by the
assembler during assembly. Essentially, any absolute value
is a manifest value with the exception of an absolute
value derived from the difference between two relocatable
values in the same section.
manifest A value of an identifier or expression that is computed by the
assembler when encountered.
quoted string A C-style character string delimited by double quotation
marks is used in conjunction with a number of assembler
directives. All string escape sequences defined in the C
language, such as \n for newline, are allowed. These
sequences are described in “Character Escape Sequences”
on page 248.
relocatable A relocatable expression or identifier assigns a value relative
to the beginning of a particular section. These values are
not determined at assembly time. All label identifiers are
relocatable values.
undefined If an identifier is unassigned, its value cannot be determined
until link time. This is an undefined external.
Type Combinations
The constant types are combined with all operators, except when a relocatable
type was made immediate or absolute. You can combine a constant with a
Examples
4 ; constant
4*(5+6) ; constant
label ; relocatable
Labels
A statement can begin with one or more named labels, which are identifiers
followed by one or two colon characters. Labels defined with one colon are not
referenced outside the source module. A second colon specifies that the label is
made visible external to its source file, instead of local to that file.
To create temporary labels for the assembler, use the .macrolocal directive.
Current Location
The symbol . refers to the current location in the current section, which can
be used as an alternative to creating a label when the current location must
be referenced. For example:
sparse_table:
.word 1,2
The next few lines provide the name of the source file, the current directory,
the date and time the compiler was invoked, and the name and version of the
host operating system in use:
;Source File: file1.c
;Directory: /tmp
;Compile Date: Thu Dec 13 13:45:02 2001
;Host OS: SunOS 5.8 Generic_108528-06
Then the version of the compiler and the exact date of the compiler is shown:
;a %D0 param
;b %D1 param
Assembler Options
When using the assembler directly from the command line, you can pass the
following options to control ARM Ltd. compatibility:
-armuk
Enables ARM Ltd. compatibility mode, which is required to assemble most ARM
Ltd. syntax, including the other assembler command line options in this section.
-pd "variable [SETA|SETL|SETS] expr"
Declares and sets the value of a variable prior to assembly by executing either the
SETA, SETL, or SETS directive.
This option can be passed to the driver in the form
-pd="variable [SETA|SETL|SETS] expr".
-apcs qualifiers
Sets the values of simulated ARM Ltd. internal variables. The qualifiers are
either /none or a concatenation of one or less entries from each of the following
qualifier sets:
• /inter or /nointer (ARM/Thumb interworking)
• /ropi, /pic, /noropi, or /nopic (Position Independent Code)
• /rwpi, /pid, /norwpi, or /nopid (Position Independent Data)
• /swst, /noswt, or /swstna (Software Stack Count Checking)
This option can be passed to the driver in the form -apcs=qualifiers.
For example, when invoking the assembler directly from the command line:
asarm -armuk -pd "Debug SETA 3" -apcs /pic/rwpi test.s
This command translates the assembly file test.s into an object file, having first:
The ARM Ltd. assembler’s two synonyms for !=, <> and /=, are supported.
The unary ? operator used for determining code size is not supported.
where areaname denotes the name of an area to be stored in the object files,
and the attribute list corresponds to attribute bits in the object file. The ARM
Ltd. linker combines all areas with similar attributes into a single section in the
final executable.
The Green Hills assembler recognizes some key attributes passed to the AREA
directive and, rather than generate one area per directive to be recombined
by the linker, puts each area in its appropriate section at assemble-time. The
recognized combinations of attributes and their corresponding sections are as
follows:
Attribute Section
CODE .text
DATA, NOINIT .bss
DATA, READWRITE .data
DATA, READONLY .rodata
The Green Hills assembler also supports the ALIGN=n attribute for aligning
sections. All other attributes are accepted but ignored.
For the most part, AREA directives in ARM Ltd. assembly code may be left as
they are, and will function properly using Green Hills tools. However, some
projects rely on some areas residing in specific places in memory. For this to
work, an AREA directive must be replaced with an appropriate .section
directive and the location can then be specified in a linker directives file. If the
AREA directive is left as it is, the area will be subsumed by a larger section and
its location will not be separately configurable.
Using the ARM Ltd. assembler and linker, all areas would be sorted
by their names in a way that, assuming all other area names begin with
alphabetic characters, would place ___Always_First___ first and
~~~Always_Last~~~ last. However, the Green Hills assembler would
place these areas in the sections .text and .data, respectively, and within
those sections they would be ordered based on the order in which their file
was encountered. In order to guarantee proper ordering of these sections, new
sections must be created for them. The above code should be modified to
read as follows:
.section "Always_First", "ax"
FirstWord
LDR pc, PlaceToJumpTo
.section "Always_Last", "awx"
FinalWord
DCD FirstWord
With this code, separate sections with descriptive names are generated. Then, in
the linker directive file, entries such as the following can be used to properly
order the sections:
-sec {
Always_First:
.text :
.rodata :
.data :
.bss :
Always_Last :
}
Both formats are supported by default in the Green Hills assembler, though
macro parameter substitution, using $parameter rather than just parameter in
the body of the macro, is only supported in ARM Ltd. compatibility mode.
Each assembly file must consistently use one or the other of the macro styles;
both cannot be used within the same file.
The Green Hills .macro and .endm directives support macros in the same
way, but always using the first syntax above.
Assembler Directives
Alignment Directives
.align const-expr
Advances the location counter to the specified addressing boundary, where
const-expr is a number of bytes. The location counter advances to the next
address that is a multiple of the specified addressing boundary. For example,
8, 16, 24, 32, and 40 all have an 8-byte addressing boundary. As the location
counter advances, skipped addresses are filled with zeros for the .data section
and nop instructions for the .text section.
If you place .align const-expr immediately following a section directive such as
.data or .text, the linker ensures that the entire section begins on the specified
addressing boundary. For example, suppose an assembly source file contains
the following:
.data
.align 8
When the source file is linked, the starting address of the .data section is aligned
on an 8-byte boundary. If the addressing boundary is defined in more than one
source file being linked, the linker aligns the final section to the largest boundary
found in the individual sections. For example, suppose two source files, file_1.s
and file_2.s, contain the following:
• file_1.s:
.data
.align 8
• file_2.s:
.data
.align 32
When file_1.s and file_2.s are linked, the .data section is aligned on a 32-byte
boundary.
By default, when the assembler creates a source listing, it always lists .if /
.endif assembly statements, but lists the corresponding object code only if
the block is assembled. That is, the assembler produces and lists object code
only if const-expr evaluates to true.
.if x==2
.ascii "if directive is TRUE"
.elseif x-6
.ascii "elseif directive is TRUE"
.else
.ascii "both if and elseif are FALSE"
.endif
.else
Assembles the subsequent block of assembly statements if previous .if directive
evaluates to false.
.elseif const-expr
Assembles the subsequent block of assembly statements if previous .if directive
evaluates to false and .elseif const-expr evaluates to true. The assembler must
be able to resolve const-expr to a constant without referring to information within
the conditional block of code that follows the .elseif directive.
.endif
Terminates the code block that began with the previous .if directive.
.if const-expr
Starts a conditional block of assembly statements; the assembler generates object
code for these statements only if const-expr evaluates to true. The assembler
must be able to resolve const-expr to a constant without referring to information
within the .if / .endif conditional block of code.
.word const-expr,const-expr,...
Stores the values of constant expressions as successive 32-bit data. The
expressions can be absolute expressions, relocatable expressions, or undefined
external identifiers. The actual values of relocatable and undefined external
identifiers are supplied at link time. The value of each expression must be in
the signed range -2147483648 to 2147483647 or the unsigned range 0 to
4294967295.
A macro might contain another macro. In this case, the assembler processes
the enclosed macro when it expands the enclosing macro. Macros can call
themselves recursively.
To create a a temporary label that changes each time a macro is called, use the
.macrolocal directive. At every macro invocation, all identifiers throughout
the macro body that are listed with .macrolocal are appended with a suffix
unique to that macro expansion. This allows local identifiers to be created and
referenced within the macro without conflicting with the equivalent identifiers
local to a subsequent macro expansion.
Example 1.
Each time the following macro mymac is invoked, label and label2 are
mangled into unique labels.
.macro mymac
.macrolocal label, label2
blt label
mov r0, 1
bgt label2
mov r0, 0
b label2
label:
mvn r0, 0
label2:
.endm
To call a macro, put the name of the macro and its arguments in an assembly
file. The macro must have been previously defined in the assembly file. You
must specify a value for every parameter in the macro.
During macro expansion, the macro’s parameters are replaced by the values
specified after the macro name. The concatenation operator >< can be used
to concatenate two parameters or a parameter with a symbol. The resulting
assembly statement is not scanned for further parameter matches. If one macro
calls another, the parameters of the first invocation are hidden from that of
the inner one.
For example, to call the macros trythis and log_and (defined above)
and place the resulting assembly statements in the .text section, enter the
following:
.text
trythis 16
log_and r1, 0
log_and r1, 2
.endm
Terminates the body of a macro whose definition began with a preceding .macro
directive. The .endm directive must be the first symbol on its line and cannot
have a label.
.exitm
Causes the assembler to exit a macro without further expanding its body of
assembly statements. Use within a .if / .endif block to specify a condition
under which you do not want a macro expanded beyond that point.
.macro name [param1, param2,...]
Begins the definition of a macro, where name is a string representing the name of
the macro and param1 is the first parameter that the macro accepts. Parameters
must be separated by a comma or whitespace. Because the namespace of a
macro is distinct from the other user-defined symbols, the macro’s name and
parameters can duplicate non-macro identifiers.
.macrolabel name
Defines a temporary label.
Repeat blocks can occur within repeat blocks. In this case, the enclosed repeat
block is expanded once for each expansion of the enclosing block. The repeat
count of an inner block is evaluated each time the block is expanded.
You can define a repeat block within a macro definition as long as the repeat
block is completely enclosed within the macro. Likewise, you can define a
macro within a repeat block as long as the macro is completely enclosed within
the repeat block.
.endr
Terminates a repeat block that began with a preceding .rept const-expr directive.
The .endr directive must be the first symbol on its line and cannot have a label.
.rept const-expr
Begins a block of assembly statements that repeats const-expr times, where
const-expr resolves to a constant number.
.rodata
Changes the active section to the .rodata section. Data that follows this directive
is placed in the .rodata section.
.section "string" [, "a" | "b" | |"w" | "x" ]
Directs assembly output into the section named string, which is defined in terms of
the optional attributes as listed below.
• a: the section should have memory allocated for it; that is, it should not be
used solely for debugging or for symbolic information.
• b: the section will have BSS semantics. Although normal data directives
such as .word and .byte, are allowed in a .bss section, all of the values
specified in those directives are discarded by the assembler. In the ELF output
file, the assembler records only the size of the section, and its contents are
omitted. When the section is downloaded to the target, space is allocated for
the section, but no data is downloaded to this section. Instead, the application
is responsible for initializing all bytes in the section to zero.
• w: the section is writable.
• x: the section contains executable code.
If none of these letters are specified, then no attributes are set. This is appropriate
only for sections containing debugging or other information not intended to be part
of the final linked file. Sections that are intended to be part of the final linked
output should have at least the a attribute. After the attributes are set they cannot
be specified again.
The standard sections have predefined attributes as follows:
• .text (Program code): “ax”
• .data (Initialized data): “aw”
• .rodata (Read-only initialized data): “a”
• .bss (Uninitialized data): “ab”
This example creates a section called .mytext with allocation and execute
attributes:
.section ".mytext","ax"
.text
Changes the active section to the .text section. Assembly code and data that
follows this directive is placed in the .text section.
.comm ident,const-expr[,const-expr]
Assigns the specified identifier ident to a common area of const-expr bytes in
length, and causes ident to be visible externally. If ident is not defined by another
relocatable object file, the linker assigns space for the identifier in the .bss
section. The optional const-expr specifies the variable alignment in bytes.
.dsect
Begins a block for defining constants. Within a .dsect / .end block, only labels
and .space directives are permitted. The symbolic names used for labels are
defined to have values equal to the number of bytes from the beginning of the
.dsect block. No space is actually allocated; only the symbolic names in the
label fields are defined.
.end
Terminates a block of constants that began with a preceding .dsect directive.
ident .equ const-expr
Defines the constant value const-expr to the symbol ident. After a symbol is
defined with a .equ directive, it cannot be redefined by another .equ directive.
.export ident
Identical to .import. It is common for .import to cause symbols defined in the
current module to be externally visible, while .export explicitly declares symbols
defined in other modules. The assembler does not require this usage, however.
.global ident
Causes the identifier ident to be visible externally. If the identifier is defined in the
current program, this directive allows the linker to resolve references by other
programs. If the identifier is not defined in the current program, the assembler
resolves it externally.
.import ident
Same as .export.
.lcomm ident,const-expr[,const-expr]
Assigns the specified identifier ident to an area in .bss of const-expr bytes in
length. The optional const-expr specifies the variable alignment in bytes. The
.lcomm directive is similar to .comm, except that ident is not exported.
.lsbss ident,const-expr[,const-expr]
Assigns the specified identifier ident to an area in .sbss of const-expr bytes in
length. The optional const-expr specifies the variable alignment in bytes. The
.lsbss directive is similar to .sbss, except that ident is not exported.
.sbss ident,const-expr[,const-expr]
Assigns the specified identifier ident to a common area of const-expr bytes in
length and causes ident to be visible externally. If ident is not defined by another
relocatable object file, the linker assigns space for the identifier in the .sbss
section. The optional const-expr specifies the variable alignment in bytes.
.set ident,const-expr
Defines the constant value const-expr to the symbol ident. You can use multiple
.set directives to change the value of the same symbol.
.weak ident
Makes the symbol weak. If the ident cannot be located, the linker sets the
symbol’s value to zero.
Miscellaneous Directives
.ident "string"
Adds string to the .comment section within the object file. The .comment section
is not allocatable; it does not occupy memory on the target.
.need ident
Defines a relationship between the function ident and the current function. The
linker will not delete the function ident as long as the current function is used, even
if ident is not used. Suppose a source file contains the following:
myfunc:
.ascii "simple example"
.need otherfunc
The linker will not delete the function otherfunc, even if it is unused, because
it is needed by the function myfunc.
.nothumb
Switches from 16-bit Thumb code (specified by the .thumb directive) back to
32-bit ARM code.
.thumb
Switches to 16-bit Thumb code. To switch back to 32-bit ARM code, use the
.nothumb directive. For more information, see “Thumb Mode” on page 101.
The Green Hills elxr linker combines ELF object files into a single executable
output file. The relocation section of each given file “resolves” its external text
and data references with the files containing the required text and data. Linker
directives files (*.ld) are used to lay out section and memory maps, which
instruct elxr in its placement of sections in memory (see “Linker Directives
Files” on page 285).
To set the program’s entry point to the address of symbol foo when building
the file hello.c and using the linker directives file hello.ld, enter the following:
Note When invoking elxr from the command line, you must preface your
linker directives file with the option -T. To pass multiple linker directives files,
use a -T option for each file.
Linker Options
The following table lists all the elxr options. These options are available to you
whether you invoke elxr with the Builder or driver (see “Running the Linker
from the Builder or Driver” on page 278), or directly from the command line:
@file
Reads additional elxr options from file file. To include a comment in an elxr option
file, place a number sign (#) as the first non-whitespace character of the line you
want treated as a comment.
-A file
Makes symbol names and addresses from a separately linked, fully located file
available during linking (a “fully-located” file is one linked without the use of the
-a or -r options).
The file’s contents are not included in the output; only those symbol addresses
needed by the current link are imported. This option is useful when one linker
image must refer to symbols that are located in another separately linked image.
-a
Causes the output file to be relocatable and executable. Relocation and final
link steps are performed (such as C++ constructor creation, common allocation,
and special symbol creation), but relocation information is retained in the output
file. Implies -r.
Some of the final link steps, including but not limited to C++ constructors and
special symbols, are not guaranteed to have relocations, and thus may not be
valid if the output file is loaded at a different address.
-allabsolute
(For use with the -A option) Imports all absolute symbols, not just those required.
-allow_bad_relocations
Emits only warnings when encountering bad or unknown relocations. The default
behavior is to generate errors.
-append
Suppresses warnings concerning object file sections that do not appear in the
section map.
-C name=value
Sets a constant, name, to the value value, for use in section and memory maps.
If this option is used, it overrides any default value specified in a CONSTANTS
directive in a linker directives file (see “The CONSTANTS Directive” on page 287).
-callgraph[=file]
Generates a call graph, file.graph.
-checksum
-nochecksum
Appends a 4-byte checksum to the end of every program section. The algorithm
used is a standard 32-bit CRC. Sample source code for verifying checksums is
included in libstartup/cksum.c of your installation. The default is -nochecksum.
-cmd=optionfile
Equivalent to -@optionfile.
-codefactor
Enables the code factoring optimization, which reduces code size by removing
redundant sequences of object code at link-time. For more information see “Code
Factoring” on page 307.
-crc
Equivalent to -checksum.
-D symbol=value
Defines symbol, so that references to it resolve to value.
-delete
Removes unused functions from the executable program. For more information,
see “Deleting Unused Functions” on page 305.
-deletedebug
Deletes special debugging symbols associated with deleted functions.
-e address|symbol
Sets the program’s entry point to address, or to the address of symbol. See
“Specifying the Program Entry Point” on page 284.
-earlyabsolute
(For use with the -A option) Imports absolute symbols before searching libraries.
-explicit_padding
(Relevant to Win9x hosts only) Ensures that empty parts of the executable are
filled with 0x00’s, instead of random data.
-extractall
Imports all object members from libraries, instead of only those required.
-extractweak
Treats weak symbols as normal symbols when importing objects from libraries.
-help
Displays a list of the most commonly used linker options.
-Help
Displays a list of all available linker options.
-keep=function
Prevents the deletion of function during function deletion. See -delete.
-keepmap
Prevents the deletion of the map file in the event of a link time error. By default,
the map file is deleted if linking fails.
-L directory
Adds a directory to be searched for libraries specified by -l; may be repeated. All
-L options on the command line are processed before any searches for -l libraries.
Directories are searched in the order in which they appear on the command line.
-lname
Looks for the library libname.a in the directories specified by -L.
-M[a][n][x]
Generates a map file with alphabetical and/or numeric ordering and/or with
cross-referencing.
-many_segments
Prevents multiple sections from being allocated to a single segment. By default,
multiple sections can be allocated to a segment if they are contiguous.
-map[=file]
Generates a map file, file.map, with alphabetic ordering.
-maplines=n
Specifies a page break in the map file every n lines.
-merge_threshold=n
Permits gaps of n bytes when merging program segments. By default, the
permitted size of gaps is 64 bytes.
-multiple
Permits multiply defined symbols. By default, an error is generated.
-no_crom
Disables the use of compressed ROM. Sections that are specified as compressed
ROM copies (through use of the attribute CROM) are treated as if they were
specified as ROM copies using the ROM attribute. For more information about the
CROM attribute, see “Section Attributes” on page 292.
-nocpp
Prevents the creation of C++ constructor/destructor tables.
-no_strict_overlap_check
Gives a warning if sections overlap. An error is given by default. See also
-overlap.
-o file
Specifies the name of the output file as file.
-overlap
Suppresses the default error messages relating to section overlaps. See also
-no_strict_overlap_check.
-prog2
Produces exactly two segments: one to contain sections .text and .rodata,
and the other to contain .data and .bss.
-Q [ y | n ]
Specifies whether or not the linker creates a .comment section containing an
identifying string that records the time at which the executable was linked and
the linker that was used.
-R directory
Specifies a run-time linker library search in directory (Solaris only).
-r
Causes the output file to retain relocation information. The resulting output file can
be used as an elxr input file in further link steps. Implies -undefined. See also -a.
-saferc=rule
Specifies which MISRA SaferC rules to turn on. rule may be specified as all or
as a comma-delimited list of rule numbers.
For more information, see “MISRA C” on page 154.
-saferc_adv=level
Specifies the severity of advisory MISRA rules as none, warn, or error.
-saferc_req=level
Specifies the severity of required MISRA rules as none, warn, or error.
-skip_layout
Leaves all sections at address 0 for run-time loader (for Chorus users only).
-stderr=file
Redirects stderr output to file.
-T file.ld
Reads additional options and memory and section maps from the linker directives
file file.ld. See “Linker Directives Files” on page 285.
-Tsection org
Sets the origin of section (text, data, or bss) to org. This option forces a three
section (.text/.data/.bss.) section map.
-tvec[=nogen]
Links absolute libraries using transfer vectors. If -tvec=nogen is specified then
transfer vectors are not generated for the image (for INTEGRITY users only).
-u symbol
Forces an undefined symbol reference for symbol, as if there had been some use
of the symbol in one of the modules listed on the command line. This might cause
modules to be linked in from libraries that would not otherwise be included.
-unalign_debug_sections
Overrides the section alignment specified in object files and forces .debug
sections to have a 1-byte alignment.
-undefined
Prevents the linker from checking for undefined symbol references. Any undefined
symbols are given an address of 0. See also -a.
-underscore
Adds an underscore to the beginning of all symbols created at link time.
-v
Prints verbose information about the activities of the linker, including the libraries it
searches to resolve undefined symbols.
-V
Displays the version number and copyright information for elxr.
-w
Suppresses linker warnings.
-Y U|L|UL,directory
Changes the default (U), alternative (L), or both (UL) library directories to directory.
program sections, as certain sections are used by the Green Hills run-time
environment (see “Customizing the Run-Time Environment Program Sections”
on page 299).
Note You can specify more than one linker directives file. The files are
processed in the order in which they are specified. If a memory map and a
section map appear in separate files, the file containing the memory map must
appear first.
The following file demonstrates the use of all four linker directives:
OPTION ("-checksum -map")
CONSTANTS {
heap_reserve = 1M
stack_reserve = 512K
}
MEMORY {
dram_rsvd1 : ORIGIN = 0x80000000, LENGTH = 32K
dram_memory : ORIGIN = ., LENGTH = 10M-32K
dram_rsvd2 : ORIGIN = ., LENGTH = 0
SECTIONS {
.text : > dram_memory
.syscall : > .
.secinfo : > .
.fixaddr : > .
.fixtype : > .
.robase ALIGN(8) : > .
.rodata : > .
.data : > .
.profile : > .
.bss : > .
.heap ALIGN(8) PAD(heap_reserve) : > .
.stack ALIGN(8) PAD(stack_reserve) : > .
// These special symbols mark the bounds of RAM and ROM memory.
// They are used by the MULTI debugger.
__ghs_ramstart = MEMADDR(dram_rsvd1);
__ghs_ramend = MEMENDADDR(dram_rsvd2);
__ghs_romstart = MEMADDR(flash_rsvd1);
__ghs_romend = MEMENDADDR(flash_rsvd2);
}
To specify the -checksum and map options in a linker directives file, add the
following line:
OPTION ("-checksum -map")
Note You can also use the OPTION directive to specify files to be linked,
using the following syntax:
OPTION ("file")
For example, to set the constant foo to the value 0x2000 in a linker directives
file, add the following line:
CONSTANTS {foo=0x2000}
Note The CONSTANTS directive can be used in conjunction with the -C linker
option (see “Linker Options” on page 280). If you specify a constant, foo,
using a CONSTANTS directive, you can then vary its value without altering your
linker directives file by passing the -C option at link time.
where:
memname
Specifies the name of a memory region.
origin_expression
Specifies the starting address of the memory region.
length_expression
Specifies the length of the memory region.
All three of these elements must be specified for each region to produce a valid
memory map. Comment lines are prefixed by a number symbol (#).
If a memory map is passed to the linker, only the memory regions named and
defined in it can be referenced in an associated section map.
The linker directives file, memory.ld, contains the following memory map:
MEMORY
{
dram_memory : ORIGIN = 0, LENGTH = 4M
flash_memory : ORIGIN = 0x40000000, LENGTH = 1024K
internal_memory : ORIGIN = 0xffff8000, LENGTH = 0x2000
alt_reset : ORIGIN = 0xfff00100, LENGTH = 256
}
Note You can use “M” (meaning megabyte, or 220 bytes) and “K” (meaning
kilobyte or 210 bytes) in memory maps, as shown in the first two lines of the
example above.
where:
secname
Specifies the name of a section.
start_expression
Specifies the starting address of the section. If omitted, the section starts at the
next available address. Usually, this is the address immediately after the previous
section. However, if a memory map has been specified and there is not enough
space to hold the section in the current memory region, the linker searches for the
next valid area of memory (specified in the memory map) into which the section
fits. The starting address can be further modified to fit alignment constraints of
the subsections included by contents.
If both a start_expression and a memname memory region are specified in a line
in the section map, the start_expression takes precedence.
attributes
Specifies the attributes of the section. Any number of the attributes listed in
“Section Attributes” on page 292 can be included.
{ contents }
Specifies section inclusion commands and assignments. There is no limit to the
number of commands and assignments.
Section inclusion commands take the form filename(secname), which directs that
the section secname from filename must be included. The filename parameter
can be replaced by an asterisk (“*”) to specify sections in all files not otherwise
mentioned. Multiple section inclusion commands are included in the order that
they are specified. If { contents } is omitted, the linker includes sections
named secname from all files, as if { *(secname) } had been entered. For
examples, see Example 5 on page 291.
The special variable dot (“.”), represents the current offset within the section. You
can assign symbols to dot using the syntax “symbol=.;”. You can create holes
in section using dot. For example, “.+=0x100;” would create a 0x100-byte
hole inside a section.
> memname
Allocates the section to memory region memname, which is defined in the
memory map (see “Memory Maps (the MEMORY Directive)” on page 288). If both a
start_expression and a memname memory region are specified in a line in the
section map, then the start_expression takes precedence.
If more than one section is assigned to a memname memory region, the section
that appears first in the section map is written to that region first.
Whether the start address is determined by a start_expression or by the next
available address in the memory region, it can be further modified to fit alignment
constraints of the subsections included by contents.
If you enter a “.” as the memname, the linker returns an error if the section cannot
fit into the same memory region as the preceding section.
All sections in input files that participate in memory layout must be referenced
in the section map.
The linker directives file, sections.ld, contains the following section map, which
references some of the named memory regions defined by the memory map in
memory.ld (see “Memory Maps (the MEMORY Directive)” on page 288):
SECTIONS
{
# RAM SECTIONS
# ROM SECTIONS
The section map lines given in this example demonstrate the syntax of the most
commonly used forms of section inclusion. For the sake of clarity, only the
executable section name and the { contents } argument are given.
.data :{*(.data)}
.data :
The first line above includes the .data sections from all object files in the
.data section of the executable. Because the executable section and the object
file sections have the same name, it is not necessary to specify a { contents }
argument in this case, and the syntax given in the second line is sufficient.
.newdata :{*(.data)}
The line above includes the .data sections from all object files in the
.newdata section of the executable.
.newdata :{foo.o(.data) bar.o(.data)}
The line above includes the .data sections from foo.o and then bar.o in the
.newdata section of the executable. The .data sections from all other
object files are included, by default, in the .data section of the executable.
.newtext :{lib.a(foo.o(.text))}
The line above includes the .text section from the object file foo.o contained
within lib.a in the .newtext section of the executable. The .text sections
from all other object files are included, by default, in the .text section of
the executable.
.newbss :{lib.a(*(.bss))}
The line above includes the .bss section from all object files contained within
lib.a in the .newbss section of the executable. The .bss sections from all
other object files are included, by default, in the .bss section of the executable.
Note Library filenames are case-sensitive. You can give just the library name,
rather than a full path.
To allocate only the COMMON data from the main.o object file to .mybss,
enter the following:
.mybss :{main.o(COMMON)}
Section Attributes
You can use the following attributes to configure section behavior:
ABS
Sets a flag in the output file that indicates that this section has an absolute address
and should not be moved. Program loaders and other utilities that manipulate the
output image should not include this section in any movement related to position
independent code or position independent data.
CLEAR
NOCLEAR
Sets or removes the CLEAR attribute of the section. If CLEAR is present, an
entry is made in the run-time clear table, which is often used by startup code to
initialize memory regions to a particular value (see “Run-Time Clear and Copy
Tables” on page 310).
The CLEAR attribute is set by default for any section that includes a COMMON,
SMALLCOMMON, or ZEROCOMMON section, which are by default included by .bss,
.sbss, and .zbss respectively.
For suggested uses, see Example 6 on page 293.
PAD (value)
Places value bytes of padding at the beginning of the section. This is equivalent
to specifying padding at the beginning of the section contents.
Example:
The following two definitions are equivalent:
.stack pad(0x10000) : {}
.stack : { . += 0x10000; }
ROM (sect_name)
CROM (sect_name)
These attributes allocate the contents of a section, sect_name, to ROM at link
time, while reserving space for the data to be copied to RAM at startup.
CROM compresses its copy by as much as 40% to 50%, and thus can greatly
reduce the amount of ROM required for your application. For more information,
see Example 7 on page 294.
The line above disables the default clearing that results from the inclusion of
COMMONS:
The line above causes the heap, which is normally uninitialized, to be cleared at
startup:
A section created with either of these attributes inherits the attributes and
contents of the original section. The original section is marked uninitialized;
it is modified to reserve address space only, as if it were all padding with no
contents.
To place the .data section in ROM with instructions to have it copied to RAM
at startup, you include, as a minimum, the following lines in your section map:
.data :
...
.ROM.data ROM(.data) :
An entry is automatically made in the ROM copy table to ensure that during
program startup the ROM image of .ROM.data is copied into the space
reserved for .data. See also“Run-Time Clear and Copy Tables” on page 310.
The behavior of a compressed ROM copy is similar to that of a ROM copy, but it
is smaller, and its placement is more restricted than that of a regular ROM copy.
Making the placement of any section other than a ROM copy or compressed
ROM copy dependent on the size of a CROM section can cause a link-time
error. Furthermore, relocations should not reference any symbols, including
__ghsbegin_section or __ghsend_section, whose locations depend on
the size of a CROM section.
For example, the following section map would generate errors because
the placement of .rodata depends on the size of .CROM.data and
.CROM.text:
.data : >RAM
.text :
...
.CROM.data CROM(.data) : >ROM
.CROM.text CROM(.text) :
.rodata :
A correct section map for this layout would have only a CROM section dependent
on the size of .CROM.data:
.data : >RAM
.text :
...
.rodata : >ROM
.CROM.data CROM(.data) :
.CROM.text CROM(.text) :
The effects of the CROM attribute can be disabled by passing the option
-no_crom on the command line (see “Linker Options” on page 280). Sections
marked as CROM are still copied to ROM but are not compressed.
Expressions
Expressions support the standard C operators with their normal precedence.
absolute(expr)
Given a section-relative offset value, absolute returns the absolute address
by adding the address of the containing section to expr. It is an error to use
absolute outside of the parentheses that specify a section contents.
addr(sectname)
Returns the memory address of the section sectname.
align(expr)
Returns the current position (.) aligned to an expr boundary. This is equivalent to:
(. % value)+sizeof(this_section)>value?align(value):.
sizeof(sectname)
Returns the current size of the section sectname.
All assignments to any symbol are section-relative; the numbers involved are
offsets from the start address of the section. Use the absolute() function
to get an address instead of an offset.
Depending on the target and the enabled optimizations, program layout might
occur multiple times. Therefore, you should avoid using expressions that
depend on the number of evaluations. If necessary, you can use the expression
final() to ensure that an expression is evaluated during the final layout only.
Example 8.
In contrast, the following does not properly set the low bit of a symbol because
it may increment multiple times:
# incorrect, will be incremented multiple times
.text : { isdefined(func) ? (func += 1) : 0; }
If you want to use custom code instead of the Green Hills startup code to copy
from ROM to RAM, see “Run-Time Clear and Copy Tables” on page 310.
It is not necessary to copy into RAM any sections that do not change at run
time. Although the .data section must generally be copied to RAM, the Green
Hills ARM compiler can determine whether certain data items do not change
at run time, and so can be retained in ROM. In order to take advantage of this
capability, you should create a section called .rodata . Data items placed into
the .rodata section are user-defined const variables. Declaring a variable
with the keyword const makes the value a constant, and ensures that it is
located to the .rodata section.
The .rodata section should be placed in the link map adjacent to the program
.text section, causing this data to be put into ROM along with the program
text.
These two sections contain read-only data and can be placed in ROM.
Failure to include these sections in the linker directives file may cause them
to be added to the end of the section list by the Green Hills linker, which can
then emit the following warning message:
[elxr] warning: section .fixaddr from libsys.a(ind_crt1.o)
isn’t included by the section map (as .fixaddr);
appending after last section
add to section map or use -append to append without warning
If the program depends on dynamic memory expanding past the end of the
last specified section in a section map, having sections appended to the
section map might be fatal because they can be overwritten. Therefore,
these sections should be included in section maps.
• .heap — This section is created by linker directives, which specifies
the size and location of the run-time heap. This section is required when
using the Green Hills run-time libraries for dynamic memory allocation. A
reference to the predefined linker symbol __ghsbegin_heap , which
denotes the beginning of the .heap section, is located in the ind_heap.c
module of the libsys.a library. If the Green Hills run-time libraries are
not being used at all, then the .heap section can be omitted. Otherwise,
failure to include a .heap section in the linker directives specification for
a program that uses dynamic memory allocation (that is, when the library
modules handling this feature are linked in with the program) causes one or
more linker errors, such as the following:
The Green Hills run-time libraries ensure that the dynamic memory
allocation does not overrun the specified .heap area. The libraries do so by
returning an error code from sbrk,() which, in turn, causes malloc()
and other memory allocation routines to return a NULL pointer. Your code
should always check for erroneous return values when calling dynamic
memory allocation routines. You can customize the Green Hills sbrk()
routine, located in ind_heap.c, to avoid using the .heap section.
• .intercall / .interfunc — These sections may be used
by Thumb-capable processor variants to create correct mixed-mode
applications. Intercall veneers will be inserted into the .intercall
section when they cannot be prepended to the function they are associated
with. The .interfunc section contains helper functions that may be
required by mixed-mode applications.
• .rodata — This section is created by the compiler. Some Green Hills
compilers place read-only data (such as data declared with the C const
specifier and string constants) into a read-only section called .rodata.
The convention used in the default linker directives files is to place
.rodata with other sections that can be placed in ROM. Failure to include
a .rodata section in the section map may cause the linker to append it to
the end of the section map.
• .ROM.data ROM(.data) — When the linker encounters a section
directive that contains ROM(), it creates a read-only copy of the section.
By convention, a section that contains the ROM(.xxx) directive is named
.ROM.xxx, where .xxx is the name of the section that is copied from ROM
into RAM. The Green Hills startup code, ind_crt0.c (see “ind_crt0.c” on
page 583), automatically copies the data from the .ROM.xxx section to the
.xxx section when copying initialized data from ROM to RAM.
If the ROM() directive is used but the Green Hills automatic ROM-RAM
initialization code is not desired (for example, when custom ROM-RAM
copy code is used), ensure that the ROM-RAM copy mechanism in
ind_crt0.c is disabled by modifying or deleting that code.
For example:
.section ".foo", "aw"
.section ".bar", "ax"
• .syscall — Contains the run-time library code for Green Hills emulation
of system calls, and is required when using the Green Hills run-time libraries
for system call emulation. When system call emulation is not being handled
in this way, you can remove use of the .syscall code by customizing the
file ind_dots.arm (see “ind_call.arm, ind_dots.arm” on page 584).
Note Any attempt to explicitly place text or data into these special sections
produces undefined and potentially fatal results. When creating custom-named
sections, you must take care not to use any of the names of these special
sections. For more detailed descriptions of the functions that use these
linker directives and special sections to set up the run-time environment, see
“Customizing the Run-Time Environment Libraries and Object Modules” on
page 580. You can also look at the comments in the customizable source files,
which are located in the libsys and libstartup directories.
Symbol Definitions
The linker can define several symbols that, if referenced but not defined in the
source code, are given particular addresses corresponding to the final image.
Example 1.
SECTIONS
{
.bss1 0x400000:
.bss:
}
void foo() {
memset(__ghsbegin_bss1, 0, (int)__ghssize_bss1);
__ghsbegin_bss[0] = 0xff;
}
if the size of section .bss1 is 0x100, then the linker resolves the following
labels:
__ghsbegin_bss1 to 0x400000
__ghsend_bss1 to 0x400100
__ghssize_bss1 to 0x100
__ghsbegin_bss to 0x400100
Example 2.
if the function foo() is at address 0x100000 and has size 0x20 bytes, then the
linker resolves __ghs_eofn_foo to be 0x100020.
int foo = 5;
void __ghsentry_resetvectors_foo(void)
{
foo = 0;
}
void reset_all()
{
int i = 0;
while (__ghstable_resetvectors[i] != (void (*)(void))0) {
(__ghstable_resetvectors[i])();
i = i + 1;
}
}
The linker supports -delete only for object files produced by the Green Hills
assembler. Other assemblers might produce object files that do not preserve
information required for -delete to function properly.
Tip In cases where a symbol should never be deleted, use the -keep=funcname
compiler driver option or the .need assembler directive.
The linker never deletes symbols preserved by these methods, even if they
appear unused. It is useful to preserve symbols such as interrupt table entry
points, non-standard entry-points, or other portions of code not reached by
normal control transfer within the program.
Symbols specified via the -u linker option are also always considered as needed.
Code Factoring
Code factoring is a link-time optimization, which reduces overall program size,
removing redundant segments of code from object files by using subroutine
calls and tail merges. The standard libraries provided with the Green Hills tools
for ARM are all prepared for code factoring.
Note Linker based farcall patching can also trigger the creation of a .linfix
section. See “Frequently Used Sections” on page 668 for more information.
For example, to factor code from source files foo.c and bar.c, use:
ccarm -codefactor -o hello foo.c bar.c
This command generates two object files, foo.o and bar.o, which are prepared
for code factoring and then passed to elxr, which performs the optimization and
links them into an executable, hello.
Code factoring only factors code within the same output section. For example:
SECTIONS {
.footext : { foo1.o(.text) foo2.o(.text) }
.bartext : { bar1.o(.text) bar2.o(.text) }
}
The code to be linked using the above section map is factored separately as
follows:
This behavior can be useful when you want to prevent code factoring from
creating dependencies between sections that must remain independent.
Code factoring runs during the final stage of linking, in which an executable file
is produced. If you want to incrementally link your files before producing an
executable, you must pass the -codefactor option at each stage to ensure
that the necessary relocation and symbol information is preserved. For example,
to generate a relocatable object file mod.o from object files foo.c and bar.c,
enter the following:
ccarm -codefactor -relobj -o mod.o foo.c bar.c
This command generates the relocatable object file mod.o, and preserves all
symbol and relocation information. To subsequently generate a code factored
executable, enter the following:
ccarm -codefactor mod.o -o hello
It is possible to apply code factoring to only some of the modules that are linked
into the final executable. If foo.c, bar.c, and baz.c are to be linked together to
produce the executable hello, but only bar.c and baz.c are to be code factored,
first generate an object file from foo.c, as follows:
ccarm -c foo.c
This command produces an object file named foo.o, which is excluded from
code factoring in any subsequent link.
Next, generate object files from bar.c and baz.c, using the -codefactor
option, as follows:
ccarm -codefactor -c bar.c baz.c
This command produces the object files bar.o and baz.o, which are prepared
for subsequent code factoring.
• Hand-written assembly code files and mixed assembly and C/C++ source
files (that is, C or C++ source files with #pragma startasm, asm
macros, etc.) cannot be code factored. For optimal results, do not mix both
assembly and C/C++ code within the same source file.
• When using the MULTI Debugger, you cannot set breakpoints on lines of
source code that have been altered or removed by code factoring. These
lines of code display a red breakdot instead of a green breakdot. Switch
to interlaced source and assembly mode, and then set breakpoints at the
assembly level.
• To control code factoring in the linker, the compiler generates a number
of .ghsnote assembler directives (which reside in the non-allocated
.ghs_info SHT_NOTE section, and have no impact on final code size).
You should not modify these directives or the contents of this section.
Compressed ROM
The elxr linker has the capability to compress sections that are placed in ROM.
These sections are then decompressed and copied into RAM during program
startup (see “Run-Time Clear and Copy Tables” on page 310). This compression
makes the executable smaller and reduces the amount of ROM required to store
the program, at the cost of an increase in the time required to link and in the
program startup time. For information about how to use Compressed ROM, see
the CROM attribute in “Section Attributes” on page 292.
These tables each contain zero or more records detailing the action to be taken
at startup.
• If you intend to use Green Hills startup code, the module containing
main() must be compiled with the Green Hills tools.
• You can link in the ADS run-time libraries to fulfill ADS compiler helpers.
This forces any symbol definitions unresolved by the Green Hills libraries
to be resolved against ads_library.l. To do this:
• Any ADS modules must have been compiled using the usual -apcs/interwork
rules. elxr completes intercall stub patching as usual.
• Implementation-defined C constructs (such as va_list) might not be
compatible.
• You should ensure that all modules are compiled for the same target
architecture throughout the compilation process (using the ADS and Green
Hills -cpu cpu options).
• The -r option (which instructs elxr to retain relocation information in the
output file) is not supported when ADS modules are linked in.
• You can use a section map in a linker directives file to rename ADS
sections to their corresponding Green Hills names (see “Section Maps (the
SECTIONS Directive)” on page 289).
• To obtain maximum debugging information, you should pass -dwarf_to_dbo
to translate ADS DWARF2 tables to the Green Hills .dbo format. You might
need to use the MULTI Debugger source command to specify the path to
the ADS source files.
Note The final executable will be a standard Green Hills executable. e_flags
will be dictated by Green Hills modules only.
The ax Librarian
The librarian combines object modules created by the assembler or linker into a
library, which is also referred to as an archive file. By convention, library files
have .a extensions. At link time, the linker can search libraries and extract
object files that are needed to provide definitions for undefined symbols.
When you build the project, the Builder compiles and assembles the source
files, and then runs the librarian to create a library from the resulting object
files. For more information, see “Linking with a Pre-Built Library” on page 37.
where filename1, filename2, filename3, etc. are the source files or object files
that are used to create the library, and libname.a is the name of the library to be
created. The compiler driver compiles and assembles the source files, and then
runs the librarian to create a library from the resulting object files.
Example 1.
To create a library libhello.a from the object files hello.o and world.o, enter:
ccarm hello.o world.o -archive -o libhello.a
Modifying Libraries
You can modify libraries (*.a files) by invoking the librarian (ax) directly, as
follows:
ax -command [options] libraryfile.a [objectfile.o]
where -command is one or more of the librarian commands, and option is one
or more of the librarian command options. The valid commands and options
are listed below.
Librarian Commands
The Librarian commands and any options that can be appended to them must
be entered as one string without spaces. The librarian commands are listed in
the table below (the options in square brackets are explained in the subsequent
table, “Librarian Command Options ” on page 316):
-d [e] [S] [v] libraryfile memberfile...
Deletes the specified memberfile (or files) from the specified libraryfile.
-p [e] libraryfile...
Prints the specified libraryfile (or files) to standard output (if the members are
object files, then the output might not be human-readable).
-q [e] [S] [v] libraryfile memberfile
Appends the specified memberfile (or files) to the end of the specified libraryfile.
The -q command is similar to the -r command except that, with -q, the files will
always be added to the end of the library, rather than replacing any existing
version of the file with the new version.
-r [c] [C] [e] [S] [v] libraryfile memberfile...
Replaces the specified memberfile (or files) in the specified libraryfile. The new
version of memberfile overwrites the existing version.
If memberfile was not previously in libraryfile, it is added.
If libraryfile did not previously exist, it is created.
Note We recommend that you create libraries with the compiler driver and not with
the librarian because only the former method generates the *.dba files necessary
for subsequent debugging.
Examples
To add a new object file foo.o to an existing library lib.a, enter:
ax -r lib.a foo.o
To delete object files foo.o and bar.o from library lib.a, enter:
To extract object file foo.o from library lib.a and rename it to newfoo.o, enter:
ax -tv lib.a
ax -ts lib.a
Utility Programs
The MULTI IDE includes many useful command line utility programs,
including functional replacements for the standard UNIX utilities dump, file,
hide, nm, size, strip, and what. All utility programs work with files generated
by any Green Hills development tools.
-I directory
Specifies an additional directory to search for source files.
The following directories are searched for source files in this order:
• the relative or absolute path specified in the object file
• directories specified using -I directory
• the user’s path
The current directory is not searched unless it is specified in one of these
categories.
--max_header_lines n
Specifies the maximum number n of header source lines to be printed.
The default value for n is 4. Setting n to 0 instructs gasmlist to print all associated
header file lines.
--no_prefix_file
Suppresses the printing of the filename at the beginning of each source line.
--omit_headings
Suppresses the printing of headings to separate files and sections.
--proc_num_on_left
When both file and procedure line numbers are enabled, prints the procedure
numbers on the left. The default is to print them on the right.
--root_remap rt dir
Re-maps the original path rt to the new path dir. For example to map a/b/c to
d/c, pass:
--root_remap a/b d
--show_func_labels
Prints line offsets with the label they are offset from. For instance, +0x4" would
instead be printed label+0x4".
--src_then_asm
Orients the output primarily towards source code. The default is to emphasize
assembly.
Example 1.
In this example, the object file test.o is compiled with the following command
line:
ccarm -G -c test.cc
If the object file has been moved from its original compilation directory, you
might receive an error message similar to the following:
gasmlist: error: aborted without finding file ’/export/samples/test.cc’
You can use one of the following methods to locate missing source files:
• Pass the --root_remap rt dir command to relocate all the paths in the object
to the correct local directories. For instance, if /export/samples/ is available
to you as /home/samples, pass the following command line:
gasmlist --root_remap /export/samples /home/samples test.o
Command line options for gbin2c are divided into three categories. Global
options can be specified anywhere on the command line and apply to all binary
files to be converted. Module inclusion options specify binary files to be
converted. Local options apply only to the binary file specified by the nearest
module inclusion option preceding them on the command line.
Global Options
-compat
Runs gbin2c in gbin2src compatibility mode.
Implies:
• the -list global option
• the -static local option for each binary file.
If an additional options file is not specified on the command line (with -i), this
option also instructs gbin2c to read standard input for additional options in lieu of
an additional options file.
-crc
Outputs a crc value for each converted binary file.
The declaration of the crc variable for the array named name is:
const unsigned int name_crc;
-help
Displays basic usage information.
-i file
Reads file as a list of additional options.
The contents of file are parsed as additional options. Extra whitespace and new
line characters are ignored. Options listed in the file have the same effect as
options on the command line with the following exceptions:
• The options file is not preprocessed by the user’s shell so no special treatment,
such as wildcard substitution, is performed.
• The meaning of the -o option in the additional options file context differs from
its meaning in the command line context. In the options file, -o name means
“refer to the current module as name in the module list, and set the array
name for the current module to name_data". In essence, the -o option is
an alias for the -output option when it occurs on the command line and the
-module_name and -array_name options when it occurs in the options file.
Note that only one additional options file can be specified using the -i option.
-list
Outputs a list of converted modules.
The default definition for the type of each list element is:
struct static_module_info {
const char * const name;
const char * const data;
const struct static_module_info * const next;
};
-size
Outputs the length of each array written.
The declaration of the size variable for the array named name is:
The nature of the array can be controlled via the local options.
Local Options
These options modify settings for the most recently included module:
-array_name name
Sets the array name for the current module to name.
By default the array name for a file is the base name of the file with all periods
replaced with underscores.
-limit n
Outputs a maximum of n bytes of the current module.
-module_name name
Refers to the current module as name in the module list.
-noconst
Removes const from the type of the array for the current module.
-signed
-unsigned
Adds signed or unsigned to the type of the array for the current module.
-skip n
Skips the first n bytes of the current module.
-static
Adds static to the type of the array for the current module.
Example 1.
gbin2c mod.o
/* mod.o: */
Example 2.
gbin2c -crc -size mod.o
In addition to the output from example 1, size and crc information for mod.o
are displayed:
/**
* This file was automatically generated by gbin2c v1.08
* Green Hills Software, Inc. [ http://www.ghs.com ]
* Using command line: gbin2c -crc -size mod.o
* Date generated: Wed Jul 9 16:09:48 2003
* Note: CRC of input file and this array can be found at end of file
**/
/* mod.o: */
Example 3.
gbin2c -crc -size mod.o -static -skip 64 -limit 4
Example 4.
gbin2c -crc mod.o -static foo -signed -size -array_name bar
In this example, both mod.o and foo are converted. Notice that the -crc and
-size global options apply to both files while -static and -signed only apply to
mod.o and foo respectively. This example also demonstrates the use of the
-array_name option and its effect on the size and crc variable names.
/**
* This file was automatically generated by gbin2c v1.08
* Green Hills Software, Inc. [ http://www.ghs.com ]
* Using command line:
* gbin2c -crc mod.o -static foo -signed -size -array_name bar
* Date generated: Wed Jul 9 16:28:19 2003
* Note: CRC of input file and this array can be found at end of file
**/
/* foo: */
/* mod.o: */
Example 5.
gbin2c mod.o foo -module_name bar -list
In this example the module list is output and the module name for foo is
changed to bar.
/**
* This file was automatically generated by gbin2c v1.08
* Green Hills Software, Inc. [ http://www.ghs.com ]
* Using command line: gbin2c mod.o foo -module_name bar -list
* Date generated: Wed Jul 9 16:30:48 2003
**/
struct static_module_info {
const char * const name;
const char * const data;
const struct static_module_info * const next;
};
/* foo: */
/* mod.o: */
Example 6.
gbin2c -i modules -list -crc
In this example, the -i option is used to include an additional options file called
modules, which contains the following text:
mod.o
foo -o bar
The -o option in modules specifies that the module name for foo should be bar
and that its array name should be bar_data.
/**
* This file was automatically generated by gbin2c v1.08
* Green Hills Software, Inc. [ http://www.ghs.com ]
* Using command line: gbin2c -i modules -list -crc
* Additional options from file: mod.o foo -o bar
* Date generated: Wed Jul 9 16:38:51 2003
* Note: CRC of input file and this array can be found at end of file
**/
struct static_module_info {
const char * const name;
const char * const data;
const struct static_module_info * const next;
};
/* foo: */
/* mod.o: */
If the two files are identical, except for time-stamps, gbincmp returns with no
output. If they differ, gbincmp prints the section name and byte offset within
the section of the first difference.
• Contents of sections loaded on the target (target sections) [this is the default]
• Contents of sections not loaded on the target (host sections)
• File headers
• Program headers (ELF headers)
• Section headers
• Relocation tables
• String tables
• Symbol sections
• DWARF debugging sections
• DWARF line number sections
The syntax for this utility is as follows:
gbincmp [options] file1 file2
where file1 and file2 are the names of the two files to be compared.
-help
Displays information about all options.
-host
-nohost
Enables or disables comparison of the contents of host sections.
-line
-noline
Enables or disables comparison of line number information. (ELF only)
-prefixed_msgs
-no_prefixed_msgs
Enables or disables the insertion of the words WARNING and ERROR before every
warning and error message.
-reloc
-noreloc
Enables or disables comparison of relocation information.
-section=sections
-nosection=sections
Enables or disables comparison of the sections named in the comma-separated
sections list. For example, -section=text,data. (ELF only)
-string
-nostring
Enables or disables comparison of string table information.
-symbol
-nosymbol
Enables or disables comparison of symbol table information.
-target
-notarget
Enables or disables comparison of the contents of target sections.
-v
Verbose output. Shows what files and sections are compared.
-commands
Displays commands before they are executed.
-convert=options
Passes options to gbldconvert. This option is only available if you also pass
-autoconvert.
-find filename
Displays the first build path to the file filename. The build path specifies a route
through the build structure to reach filename.
-findall filename
Displays all build paths to the file filename. The build paths specify routes through
the build structure to reach filename.
-help
Displays usage information for basic gbuild options.
-Help
Displays usage information for all gbuild options.
-ignore
Continues building, even if errors are encountered.
-info
Displays status messages but does not perform the actions described in the
messages.
-leave_output
Deletes only intermediate output files. This option is only available with -clean
or -cleanfirst.
-link
Forces linking. The default behavior is to re-link the executable only if any of its
components have changed.
-list
Lists all filenames. This option does not perform any build actions.
-list_depends
Lists known dependencies. You must build your project before passing this option.
This option does not perform any build actions.
-list_options
Lists options specified in the .gpj file. This option does not perform any build
actions.
-lockout
Uses a lock file to prevent simultaneous builds of the same program or library.
-lockoutretry
Waits to obtain a lock file.
-nested_commands
Displays full commands, including internal commands, before they are executed.
-nice
Executes the build with low priority.
-nolink
Generates object files but does not link them.
-noprogress
Suppresses progress messages.
-noreasons
Restricts the information given in progress messages.
For example, the message:
is reduced to:
Compiling hello.c
-parallel[=n]
Specifies the number of processes that gbuild can run in parallel. The default
value for n is 2.
-path list_of_project_files filename
Specifies a build path of project (.gpj) files to follow when building the file filename.
The build path specifies a route through the build structure to reach filename. This
option is helpful when one file is utilized in multiple paths in your build tree, and you
want to specify which path to use for building.
-quiet
Prevents the utility from outputting any warning or error messages.
-skip=target
Skips the specified build target target when building. Here, target is the output
name associated with a build file.
-statistics
Displays comprehensive timing information.
-stderr=filename
Redirects stderr output (status and error messages) to filename.
-strict
Aborts gbuild if gbuild is unable to open a .gpj file in your build tree or if you
specify an unrecognized option on the command line. Without this option, these
problems only generate warning messages.
-time
Displays basic timing information.
-top filename.gpj
Specifies the top-level project file. By default, gbuild uses default.gpj in the
current directory as the top-level project file.
This option allows you to specify a path to a project file in another directory.
-unix
Displays directory slashes as /.
-within intermediate.gpj
Looks for build targets that are children of intermediate.gpj. This option is helpful
when one file is utilized in multiple paths in your build tree, and you want to specify
which path to use for building.
Using gbuild
The following examples take place in a directory, MyProjects/Project1, which
contains a top-level project file called default.gpj, and a number of levels of
subprojects.
To build a particular executable, you must specify either its project file or the
name of the executable itself.
or:
gbuild print_utility
To build individual object files, you must specify either the initial source files
or the object files that they will be compiled into.
For example, to build the source files foo.c, bar.s, and baz.cxx into object
files, enter the following:
gbuild foo.c bar.s baz.cxx
or:
gbuild foo.o bar.o baz.o
As your project grows in size, it might become difficult to find individual files,
particularly if you are using several levels of subprojects. To search for the
project file print_utility.gpj, enter the following:
gbuild -find print_utility.gpj
This command prints the position of print_utility.gpj in the project tree and the
path to it from the current directory. The output resembles the following:
default.gpj utilities.gpj utilities/print_utility/print_utility.gpj
Build options can be set at any level of the project file hierarchy. If you are
building a subproject, it is best to specify the top-level project file, particularly
if it is in a different directory.
By specifying ../../default.gpj as the top-level build file, you will ensure that
any build options set in the upper portions of the project structure are inherited
appropriately.
The gcolor utility reads in a set of rules from a rules file to determine how
the input should be colored. If a line from the input cannot be identified as
conforming to any rule, then no coloring is performed.
There are five types that can be defined using rules that are recognized by
gcolor. Each one can output a specific foreground, background, and attribute.
Rule Default Coloring
info Foreground = Bold, Default
warnings Foreground = Bold, Magenta
errors Foreground = Bold, Red
before Foreground = Normal, Default
after Foreground = Bold, Default
Note The types before and after are used for coloring output from a
diff, for example when comparing changes in a cvs file.
where type and value are drawn from the following tables:
Colors Attributes
Types Background
Value Value Attribute
or Foreground
info -1 Default -1 Default
warnings 0 Black 0 None
errors 1 Red 1 Bold
before 2 Green 4 Underscore
after 3 Yellow 5 Blink
4 Blue 7 Reverse
5 Magenta 8 Concealed
6 Cyan
7 White
Comment lines must be prefixed with a ’#’ character as the first non-whitespace
character.
For example, to make info display in normal white text on a blue background,
you would use the following:
[info]
attribute = 0
foreground = 7
background = 4
Note If you do not specify coloring for a type, that type is colored in the default
manner. If you do not specify values for attribute, foreground, or
background, the default values are used.
Rules Files
The default set of rules is located in defaults/colors/build.rul. These
correspond to the output from the builder and any of the programs that it
invokes (the compiler, assembler, linker, etc.).
A second set of rules is supplied that correspond to standard cvs output. These
are located in defaults/color/cvs.rul. To use these rules, pass the -r cvs.rul
option.
Alternatively, you can specify your own set of rules to use with the -r file option.
You must create a rules file (file.rul) and save it in the following location:
There are two special rule types: none and previous.The none type causes
matching text to be printed without color. This is useful if you want to prevent
the coloring of specific lines that would otherwise match against a later rule.
For example, the rules:
none: ^foobar
info: ^foo
would color lines beginning with foo, except those beginning with foobar.
The previous type causes matching text to be colored the same as the
previous line of text. This is useful to ensure that continuation lines are colored
the same as their parents.
Comment lines must be prefixed with a ’#’ character as the first non-whitespace
character.
Example 1.
To color file foo, using your own set of rules contained within myrules.rul:
gcolor -r myrules.rul foo
To color builder output using the standard rules, enter (for sh shells):
gbuild default.gpj 2>&1 | gcolor
Note that the syntax for csh shells is different. If you are using a csh shell, enter:
gbuild default.gpj |& gcolor
To color CVS output, using the cvs.rul rules, enter (for sh shells):
cvs update 2>&1 | gcolor -r cvs.rul
If either input file is an object file, an object library file, or an executable file,
gcompare automatically runs gfunsize -gcompare -all (or another command
specified by the -x option) to produce an input text file to compare.
You can mix all input file types with no restrictions, including files for different
target CPU’s.
The gcompare utility reads both input text files. For any name that does not
exist in both files, gcompare prints a warning, unless -w is specified. For each
name that exists in both files, gcompare compares the old and new numbers.
If the new number is worse (larger is worse unless -i is specified), gcompare
writes a line to the output report file containing the name, new number, old
number, and percentage by which the new number is worse.
In the following example, the size of the function main has increased by
14% from 28 to 32:
main 32 28 -14%
where oldfile is the base line input file and newfile is the input file for which
deviations (improvements or degradations) are reported.
-z
Does not show cases where files are the same.
If the -r, -1, or -v options are used, all comparisons are shown, regardless of the
result of the comparison. With -r, two reports are shown side by side in two
columns. The left column is sorted from best to worst, and the right column
is sorted from worst to best.
Sample -r output:
linpack.188.O.a vs linpack.188.OS.a vs
linpack.188.OS.a linpack.188.O.a
WORSE by: 4172 3746 11% BETTER by: 3726 4172 10%
linpack.o:_daxpy 152 112 -36% linpack.o:_dscal 34 34 0%
linpack.o:_matgen 342 258 -33% linpack.o:_epslon 20 20 0%
linpack.o:_dgesl 294 240 -23% linpack.o:_idamax 72 72 0%
linpack.o:_dgefa 524 442 -19% linpack.o:_dmxpy 1516 1598 5%
linpack.o:_main 1136 1052 -8% linpack.o:_main 1052 1136 7%
linpack.o:_dmxpy 1598 1516 -5% linpack.o:_dgefa 442 524 16%
linpack.o:_idamax 72 72 0% linpack.o:_dgesl 240 294 18%
linpack.o:_epslon 20 20 0% linpack.o:_matgen 258 342 25%
linpack.o:_dscal 34 34 0% linpack.o:_daxpy 112 152 26%
This output can require many columns. Use the -L option for a 132-column
format. On UNIX, use the lpr -L command to print in landscape mode.
where filename is the name of the input file, and options are drawn from one of
the following tables:
-dinfo
Enables the display of particular information, where info is one of:
• a: raw auxiliary table (not .dnm)
• b: linkage stubs (.dnm only)
• c: static call information (not .dnm)
• d: .dlo file information (for .dnm), or the #define table (for other debugging
files)
• f: filename table
• h: the file header
• k: link labels (.dnm only)
• l: libraries (.dnm only)
• p: the procedure table
• s: sections (for .dnm), or the symbol table (for other debugging files)
• t: the typedef table
• u: .dnm updates (.dnm only)
• x: the section table (not .dnm)
-help
Displays information about all options.
-v
Performs internal consistency checks only. Does not display symbols.
-V
Same as -v, but ignores warnings.
-help
Displays information about all options.
-load
Displays ELF header summary.
-map
Displays section summary.
-N
Only displays information as indicated by the -y options.
-print_checksum
Prints the checksum for each appropriate section. If -verify_checksum is
also specified, checksums are assumed to exist and -print_checksum prints
them for those sections where the checksum is found to be correct. If the
-verify_checksum option is not specified, checksums are assumed not to exist in
the section, so they are calculated using all bytes in the section.
-raw
If the -ysec option is specified, this produces text sections in hexadecimal format
instead of disassembly.
-sx
-nx
Enables or disables attempted shorter C++ demangling.
-sym
Uses symbol names instead of numbers in relocation output.
-v1
-v2
Specifies display of DWARF Version 1 or 2. The DWARF version in use is
detected automatically by gdump, and the appropriate option set automatically.
-verify_checksum
Instructs gdump that all non-empty, allocated sections have a 4-byte checksum
generated by the Green Hills linker. Compares the content of each section against
the existing checksum and, if they do not match, displays both.
-yinfo
-ninfo
Enables or disables the display of particular information, where info is one of:
• d: DWARF debugging information
• dynamic: dynamic linkage information
• f: DWARF call frame information
• g: global offset table
• h: ELF header information
• l: DWARF line number information
• m: DWARF macro information
• r: relocation information
• p: procedure linkage table
• s: symbol table information
• sec: section contents
• sh: section header information
• str: string table information
• text: text section contents
-nx
Does not attempt to demangle C++ names.
-o
Displays optional header.
-r
Displays relocation information.
-raw
Produces section contents in raw form.
-s
Produces section contents.
-sx
Attempts shorter C++ demangling.
-sym
Uses symbol names instead of numbers in relocation output.
-t num[+t num2]
Displays symbol num or symbols from num to num2.
-ysec
-ytext
Enables the display of section contents and/or text section contents.
Example 1.
If the current host system is a SPARC workstation running the Solaris 2.x
operating system (which uses the ELF format for executable files), you will
see the following behavior:
gfile /bin/od
/bin/od: SPARC big endian executable ELF
where filename is the file to examine, and options are drawn from the following
table:
-addr
Displays the address of each function.
-all
Displays the code sizes of all functions. This is the default.
-file
Displays the filename before each function.
-func=name
Displays the code sizes of the specified function or functions.
-gcompare
Displays the output in a format suitable for input to the gcompare utility program.
-help
Displays information about all options.
-hex
Displays function code sizes and addresses in hexadecimal.
-nounderscores
Removes leading underscores from function names.
-sect=name
Displays functions in section name.
-sectnum=n
Displays functions in section number n.
-w
Suppresses warnings.
where filename is the executable to convert, and options are drawn from the
following table:
-auto
Automatically determines byte order and BCS/COFF based on header information.
This is the default.
-B
-L
Specifies that the input object file is big or little endian.
-BCS
-noBCS (default)
Specifies that the input object file is either an 88K BCS variant of COFF or
standard COFF.
-bytes n
Sets the maximum count of unpaired data bytes/data record (minimum 4,
maximum 28). The default is 28.
-e n
Sets the entry point in the hexadecimal file to the specified address n.
-end address
Specifies the end address of the data you want to output to the hexadecimal file.
-fillx n1 n2 v
Fills x-byte value v from addresses n1 to n2 (where x is 1,2, or 4).
-h
Does not produce an end mark of (empty) symbol table.
-help
Lists these ghexfile options.
-hex86 (default)
-hex386
-tekhex
Specifies output of Intel HEX86, HEX386, or extended Tektronix hexadecimal
format.
-interval n[:m]
Restricts output to data bytes at interval n, where n is a value between 2 and 8,
inclusive. The argument m is the number of bytes (the default is 1) included in
each interval. For example, ghexfile -interval 2 outputs every other byte.
-o filename
Sets output filename. The default is stdout.
-padx n1 n2 v
Pads x-byte holes between hexadecimal data records from address n1 to n2 with
value v. x may be 1, 2, or 4.
-romaddr address
Sets starting address in ROM where you want to place data.
-skip sn
Specifies a section (sn) that you do not want to output to the Intel hexadecimal file.
-start address
Specifies the start address of the data you want to output to the Intel hexadecimal
file.
Address Space
The Intel HEX86 hexadecimal format can handle memory addresses only in
the range of 0x00000000 to 0x0010ffef. When this address range is
exceeded, ghexfile displays the message: an address is too big.
The Intel HEX386 format supports the full 32-bit address space. A linear
address record containing the upper 16-bits of the address was added to the
HEX86 format to form the HEX386 format.
The Tektronix extended tekhex format supports the full 32-bit address space.
Data Splitting
In some hardware implementations, the width of the bus differs from the width
of the PROM’s. Depending on how the bus and PROM’s are connected, it
might be necessary to store even bytes in one PROM and odd bytes in another
PROM. The technique of dividing the data into even and odd bytes, or other
ways, is called data splitting.
Data splitting can be done in ghexfile using a few options. The -start option
specifies the starting address of the data in the object input file that you want to
output to the Intel hexadecimal output file. The -end option specifies the last
address of data in the object input file that you want to output. The -interval
option specifies the distance between bytes in the input file that you want to
output. A value of 2 for -interval outputs every other byte. Sometimes it is
necessary to relocate the data to address zero in the Intel hexadecimal output
file for programming PROM. The -romaddr option specifies the start address
of the data bytes in the Intel hexadecimal output file.
The following examples use an executable file named prog1, which has the
following standard sections:
1: .text, address: 0x1000, size: 0x100
2: .data, address: 0x2000, size: 0x200
3: .bss, address: 0x3000, size: 0x200 (No Load Section)
Example 1.
ghexfile -start 0x1000 -end 0x1080 prog1 -o prog1.hex
ghexfile extracts the data in the input file prog1 starting at address 0x1000
and ending at address 0x1080, converts the extracted data to Intel hexadecimal
format, and writes the output to prog1.hex.
Example 2.
ghexfile -start 0x1000 -end 0x1080 -romaddr 0 prog1 -o prog1.hex
Same as the previous example, but the data is relocated to start at address zero.
Example 3.
ghexfile -start 0x1000 -end 0x1080 -romaddr 0 -interval 2 prog1
ghexfile extracts the even data bytes in the input file prog1 starting at address
0x1000 and ending at address 0x1080, relocates the data to start at address
zero, converts the extracted data to Intel hexadecimal format, and writes the
results to the standard output.
Example 4.
ghexfile -start 0x1001 -end 0x1080 -romaddr 0 -interval 2 prog1
Same as the previous example, except the odd data bytes, starting at address
0x1001 and ending at address 0x107F, are extracted.
Example 5.
ghexfile -start 0x1002 -end 0x107F -romaddr 0 -interval 4:2 prog1
ghexfile extracts 2 out of every 4 bytes of data in the input file prog1 starting
at address 0x1002 and ending at address 0x107F, relocates the data to start
at address zero, converts the extracted data to Intel hexadecimal format, and
writes the results to the standard output.
Example 1.
First, the kernel is linked into a single file using the linker’s -r option to retain
relocation information. Then, ghide is run on the kernel using a retain list
of the functions that should remain visible to the application tasks. Finally,
the application tasks are linked with the kernel file, producing a complete
executable file.
The use of ghide ensures that only the desired global symbols in the kernel are
visible to the application tasks. This also prevents duplicate symbol errors in
the linker if any application might have a global symbol with the same name
as an internal kernel-only function.
where executable is the name of the executable from which to generate the
memory image, and options are drawn from the following table:
-byte b [of] n
By default, gmemfile outputs all data bytes to the memory image. This option
looks at data in the input file in chunks the size of the bus width (n) and writes
only the specified data bytes (b) within each data chunk in the input data to the
output file. It can be used to separate odd or even data bytes or words for burning
PROMs when the size of the PROMs differs from the size of the bus. It is also
used to reverse the order of the data bytes for a shared bus environment.
The width, n, represents the width of the data bus. The maximum width allowed is
32 that represents a 256 bit bus. The bytes, b, within the specified bus width n are
numbered 1 through n where 1 is the first byte and n is the last byte.
The bytes, b, can be specified in one of the following ways:
• as a single byte (for example, -byte 1 of 4). In this example, for each 4
byte chunk of input data, only byte 1 is written to the output file.
• as a range of bytes (for example, -byte 1-4 of 8). In this example, for
each 8 byte chuck of data in the input file, bytes 1, 2, 3 and 4 are written
to the output file.
• as a list of bytes (for example, -byte 4,3,2,1 of 4). In this example, for
each 4 byte chunk of data, the bytes are reversed and written to the output file.
-end address
Specifies the highest address of data to be placed in the memory image. If
address is higher than the highest address of the executable, the bytes between
them are padded with zeros unless -fillx is passed. You can specify a section
name instead of an address, and the highest address of that section is used.
-size value
Limits the memory image to the size specified in the value parameter. This is an
alternative to using the -end option. An error is displayed if both -size and -end
appear in the command input.
By default, all data from the executable is written to the memory image.
-skip sname
Excludes data in the specified section sname of the executable from the memory
image.
-start address
Specifies the address in the executable at which to begin copying data to the
memory image. A section name can be specified instead of an address, and then
the start address is the first address in the section. If the start address is lower
than the lowest address in the executable, the bytes between the start address
and the executable are padded with zeros or with a fill value if one was specified
with -fill1, -fill2, or -fill4.
Data Splitting
In some hardware implementations, the width of the data bus differs from the
width of the PROMs. Depending on how the bus and PROMs are connected, it
might be necessary to store low bytes, or words, in one PROM and high bytes,
or words, in another PROM. The gmemfile utility supports such data splitting
through the -byte option (see examples 6 and 7 below).
The following examples use for illustration a program file prog1 that contains
the following sections:
Name Start Address End Address Size
.text 0x1000 0x10ff 0x100
.rodata 0x1100 0x12ff 0x200
.rdata 0x1300 0x15ff 0x300
.data 0x2000 0x22ff 0x300
.bss 0x2300 0x24ff 0x200
The .text section contains all of the code in the program that is executed
from ROM. The .rodata section contains read-only data that is accessed in
ROM. The .rdata section contains initialized data that is stored in ROM
and copied to .data in RAM at program startup. The program references
initialized data at the addresses in section .data in RAM. The .bss section
contains uninitialized data. It is set to zero at program startup.
Example 1.
gmemfile prog1.elf
In this example, because no options have been specified, the output file is
called prog1.bin, the first byte in the memory image is the first byte of section
.text, and its last byte is the last byte of .rdata (which is the last section
that contains initialized data).
Example 2.
gmemfile -start 0 prog1.elf -o prog1.mem
In this example, the option -start 0 sets the starting address at which
gmemfile begins reading the executable to 0. Because the first section of the
executable is .text, which begins at 0x1000, the first 0x1000 bytes of the
memory image are set to zero. The utility continues reading and outputting
the data from sections .text, .rodata, and .rdata. The last byte in
the memory image is the last byte of section .rdata, which is at file offset
0x15ff in the memory image and at address 0x15ff in the executable.
Example 3.
gmemfile prog1.elf -fill2 0 .text 0x3e7f -o prog1.mem
In this example, the -fill2 option specifies that any holes between 0 and the
end of section .text be filled with the value 0x3e7f. The initialized data
in .text is not overwritten by -fill2. The memory image produced in
this example has the same start (0) and end (0x15ff) addresses as that in the
previous example (the -start 0 option is not needed, since -fill2 starts
at zero).
Example 4.
gmemfile prog1.elf -start 0 -end 0x1fff -o prog1.mem
In this example, the PROM is 0x2000 bytes wide and the PROM burner
requires that all bytes in the PROM be filled. The prog1 executable has a
hole in front of its first section (from 0x0 to 0xfff) and after the end of its
initialized data (from 0x1600 to 0x1fff).
The -start option sets the start address of the memory image to zero and
-end sets its end address to 0x1fff. Because no -fill options have been
used, the holes 0x0 to 0xfff and 0x1600 to 0x1fff are filled with zeros.
Example 5.
gmemfile prog1.elf -start 0 -size 0x2000 -o prog1.mem
In this example, the memory image produced is identical to that of the previous
example. Instead of specifying an end address with -end, a size is specified
with -size 0x2000.
Example 6.
gmemfile -byte 1 of 2 prog1.elf -start .text -size 0x100 -o prog1.low.mem
gmemfile -byte 2 of 2 prog1.elf -start .text -size 0x100 -o prog1.high.mem
In this example it is necessary to separate low and high bytes of data into
separate PROMs, each of which is 0x100 bytes wide. The gmemfile utility
is run twice, using the -byte option to select alternate bytes for each of the
output files.
In the first command line, the option -byte 1 of 2 outputs the first byte of
data in each two byte interval. The -start option sets gmemfile to reading
the executable at 0x1000 (the first byte of .text). The -size option sets
the size of the memory image to 0x100 bytes.
The first byte of data in the memory image is the first byte of data in section
.text. The second byte of data in the memory image is the third byte of data
in section .text. The last byte of data in the memory image at file offset
0xff is from the .rodata section in the executable at address 0x11fe
(0x200 bytes above 0x1000).
The following bytes would be output to the first memory image file:
01030507090b0d0f....
The second command line takes the second byte in each 2-byte interval starting
at the address of .text (0x1000). The first byte of data in the memory image
is the second byte of data in section .text. The second byte of data in the
memory image is the fourth byte of data in section .text. The last byte of
data in the memory image is the byte in section .rodata at address 0x11ff.
Example 7.
gmemfile -byte 1,2 of 4 prog1.elf -start .text -size 0x100 -o prog1.low.mem
gmemfile -byte 3,4 of 4 prog1.elf -start .text -size 0x100 -o prog1.high.mem
This example is similar to the previous example, except that the low half and
high half of each 4-byte interval is separated. The first command takes the
low 2-byte half of each 4-byte interval of data in the executable starting at
the address of .text (-x1000) until there are 0x100 bytes of data in the
memory image.
The second command takes the high 2-byte half of each 4-byte interval of data
in the executable starting at the address of .text (-x1000) until there are
0x100 bytes of data in the memory image.
Example 8.
gmemfile prog1.elf -start .rdata -end .rdata -byte 4,3,2,1
of 4 -o reverse.bin
gmemfile -import .text reverse.bin -skip .rdata -o prog1.bin
In this example, it is necessary to change the data in the .rdata section from
big endian to little endian byte ordering. The first command uses the option
-byte 4,3,2,1 of 4 to take data from section .rdata, reverse the byte
order, and write the resultant data to the memory image file reverse.bin.
The second command takes the data from file reverse.bin and loads it after
the .text section. The -import .text reverse.bin option loads
reverse.bin after the end of the .text section (which is the start address of
.rdata). The -skip .rdata option discards any data in section .rdata.
General Options
The general gnm options are as follows:
-help
Displays general options and ELF-specific options.
-helpbsd
Displays BSD-specific options.
-helpcoff
Displays COFF-specific options.
-helpelf
Displays ELF-specific options.
-output file
Writes the output from gnm to file.
-V
Prints the gnm version.
-D
Prints symbols from the dynamic symbol table.
-h
Does not print headers.
-l
Prints an asterisk (*) after symbol type for WEAK symbols. This is for -p mode
only.
-n
Sorts output by symbol name.
-o
Prints value and size of symbols in octal.
-p
Uses 3-column output format.
-prefixed_msgs
-no_prefixed_msgs
Enables or disables the printing of WARNING and ERROR before messages.
-r
Prefixes filename to each line of output.
-u
Prints undefined symbols only.
-v
Sorts output by symbol value.
-x
Prints value and size of symbols in hexadecimal.
-n
Sorts symbols by value.
-o
Prefixes lines with object or archive element name.
-p
Does not sort symbols.
-r
Sorts in reverse order.
-s
Sorts external symbols by size.
-u
Prints only undefined symbols.
Output Formats
By default, gnm produces output similar to the following excerpt (indexes 3
through 11 are omitted for brevity):
[Index] Value Size Type Bind Other Shndx Name
Column Meaning
Index Position of symbol in the symbol table.
Value The value or address of the symbol.
Size Size of the symbol (for example, a 4-byte integer symbol has a size of 4).
Type One of the following:
• NOTY: Symbol without type.
• FILE: Filename symbol.
• SECT: Section name symbol.
• OBJT: Data symbol.
• FUNC: Code symbol.
Column Meaning
Bind One of the following:
• LOCL: Local symbol (for example, C/C++ static).
• GLOB: Global symbol.
• WEAK: Weak global symbol (if undefined, the symbol’s value resolves
to zero).
Other Reserved field, generally zero.
Shndx The name of the section where the symbol is defined. For example:
• .text: Code defined in the .text section.
• .data: Data defined in the .data section.
• ABS: No section (for example, a filename symbol).
• COMMON: Common variable whose section is not yet determined.
Name Symbol name.
The first column is the value or address of the symbol. The second column is its
type (as shown in the following table), and the third is the symbol name. Note
that this format cannot fully describe all sections and storage classes.
Type Meaning
A External absolute
a Local absolute
B External zeroed data
b Local zeroed data
C Common variable (same as B except not yet assigned to a section)
D External initialized data
d Local initialized data
F Filename
I Local thread local storage
L External thread local storage
Type Meaning
N Informational symbol
S Section name
T External text
t Local text
U External undefined
Note You can edit only one file at a time using gpjmodify.
where:
• file.gpj is a top-level project file. This is either the file to be edited or the
ultimate parent of sub.gpj.
• The optional sub.gpj… is an immediate child subproject of file.gpj or a
chain of subprojects (the last of which will be edited). Alternately, you can
specify @path-to-sub.gpj, an absolute path to a subproject at any point in
the project tree.
• options are drawn from the following table:
-f
Forces the edit, even if errors would result.
-help
Displays help information.
-multidir directory
Specifies an alternate MULTI installation directory.
-o output.gpj
Writes the edited file to output.gpj. By default, edits are written to the existing file.
-quiet
Suppresses warning messages.
Note Several of these actions take an optional -filetype type parameter. You
should pass this only if the files you are adding have non-standard extensions
that the Builder is unable to recognize.
Where actions accept a list of files or options, each item in the list must be
separated with a space.
where file.gpj is the name of the file to be created, type is one of program,
subproject, or nobuild, and target_file specifies the project’s target. The
options are drawn from the following table:
-top
Specifies that the new file will be a top-level project file.
-multidir directory
Specifies an alternate MULTI installation directory.
Generating a makefile
The gpjmodify utility can generate a rudimentary makefile from a .gpj file.
This makefile can be used as a guide to help you integrate the Green Hills tools
with an existing makefile structure.
where file.gpj is the .gpj file to be converted, and options are drawn from the
following table:
-multidir directory
Specifies an alternate MULTI installation directory.
-quiet
Suppresses warning messages.
The syntax for this utility is as follows (note the use of the double dash “--”):
grun [options] [dbserv_cmd] -- program_cmd
where:
-pro
Same as the -profile option, but also translates the profiling data.
-profile
Executes the target program with profiling enabled.
-stack address
Sets the initial value for the program’s stack pointer to address.
-subcpu n
Specifies n as the “subcpu” number.
-text address
Sets the starting address of the program’s text (code).
-timeout seconds
Sets the number of seconds to wait before assuming the target has hung. The
default is 600 seconds.
where filename is the name of the input BSD or ELF object file, object file
library, or executable file.
-rom
Displays a sum total of ROM size for the input files. File segments are considered
to be ROM only if they contain initialized data or program code.
This option must be passed alone (or in conjunction with -ram), and must precede
any input files on the command line. For example:
or:
-fillx n1 n2 v
Fills memory from address n1 to address n2 with the x-byte value v (where x
is 1, 2, or 4).
-help
Displays information about all options.
-interval n[:m]
Places only those data bytes from the input file that occur within the specified
interval in the output file. Values for n are 1 through 8. The default is 1, indicating
that every byte will be output. The m value specifies the number of output bytes
for each interval. For example, 4:2 outputs 2 consecutive bytes out of every 4.
This option requires that you set the -start and -romaddr options.
-noS5
Suppresses production of an S5 block count record.
-o filename
Specifies the output filename. By default, output is sent to standard output.
-padx n1 n2 v
Pads x-byte holes between hexadecimal data records from address n1 to n2 with
value v. x may be 1, 2, or 4.
-prefixed_msgs
-no_prefixed_msgs
Enables or disables the printing of WARNING and ERROR before messages.
-romaddr addr
Sets start address in ROM to place data. The default is the same address as in
the input file.
-Stype
Specifies the type of S-Record to be produced, where type is one of the following:
• 1: S1 data records (16-bit addresses)
• 2: S2 data records (24-bit addresses)
• 3 (default): S3 data records (32-bit addresses)
• 5: an S5 record with a count of data records (16-bit addresses)
• 5old: an old format S5 record (16-bit addresses)
• 7: an S7 end record (32-bit entry point)
• 8: an S8 end record (24-bit entry point)
• 9: an S9 end record (16-bit entry point)
The default is to produce S3 data records, an S5 record, and an S7 end record.
-skip s
Does not output data for section s.
-start address
Specifies starting address in object file for output.
By default, the S5 data record contains a 4-byte address. Some old S-Record
readers expect an S5 record to contain a 2-byte address. In this case, use the
-S5old option.
A termination record contains the entry point (the address where program
execution begins). There are three types of termination records, S7, S8, and
S9, as indicated in the previous table.
Some S-Record readers accept data records up to a specified length. Use the
option -bytes size to set the maximum data record length.
If you forget to specify the entry point address when linking, you can use -e
address to set the entry point to the given address.
Data Splitting
In some hardware implementations, the width of the bus differs from the width
of the PROMs. Depending on how the bus and PROM’s are connected, it might
be necessary to store even bytes in one PROM and odd bytes in another PROM.
Data splitting is a technique of dividing the data into even and odd bytes, or in
other ways.
gsrec can perform data splitting. The -start option specifies the starting address
of the data in the object input file to output to the S-Record output file. The -end
option specifies the last address of data in the object input file to output. The
-interval option specifies the distance between bytes in the input file to output.
A value of 2 for -interval outputs every other byte. Sometimes it is necessary
to relocate the data to address zero in the S-Record output file for programming
PROMs. The -romaddr option specifies the start address of the data bytes in
the S-Record output file. The last two succeeding examples separate even and
odd bytes into two different S-Record files.
The following examples use a program file prog1 that contains the following
sections:
1: .text, address: 0x1000, size: 0x100
2: .data, address: 0x2000, size: 0x200
3: .bss, address: 0x3000, size: 0x200 (No Load Section)
4: .data2, address: 0x4000, size: 0x200
Example 1.
gsrec prog1
The gsrec program translates the data in the input file prog1 and writes the
S-Records to the standard output. Because the contents of section .bss are not
loaded, no S-Records are output for its data.
Example 2.
gsrec -S1 -S9 prog1 -o prog1.run
The gsrec program translates the data in the input file prog1 and writes the
S-Records to the specified output file prog1.run. Data are output as S1 records
that have a 16-bit address space. The start address is output as an S9 record
that has a 16-bit address space.
Example 3.
gsrec -start 0x1000 -end 0x1080 prog1 -o prog1.run
The gsrec program translates the data in the input file prog1 starting at address
0x1000 and ending at address 0x1080 to the output file prog1.run.
Example 4.
gsrec -start 0x1000 -end 0x1080 -romaddr 0 prog1 -o prog1.run
The gsrec program translates the data in the input file prog1 starting at address
0x1000 and ending at address 0x1080, relocates the data starting at address
zero, and copies the resulting S-Records to the output file prog1.run.
Example 5.
gsrec -start 0x1000 -end 0x1080 -romaddr 0 -interval 2 prog1
The gsrec program translates the even data bytes in the input file prog1 starting
at address 0x1000 and ending at address 0x1080, relocates the data to start at
address zero, and copies the resulting S-Records to the standard output.
Example 6.
gsrec -start 0x1001 -end 0x107F -romaddr 0 -interval 2 prog1
The gsrec program translates the odd data bytes in the input file prog1 starting
at address 0x1001 and ending at address 0x107F, relocates the data to start at
address zero, and copies the resulting S-Records to the standard output.
Example 7.
gsrec -start 0x1002 -end 0x107F -romaddr 0 -interval 4:2 prog1
The gsrec program translates 2 out of every 4 data bytes in the input file prog1
starting at address 0x1002 and ending at address 0x107F, relocates the data to
start at address zero, and copies the resulting S-Records to the standard output.
To produce the information required for gstack, all files comprising the program
must be compiled with -G.
Caveats
• gstack cannot work if there are potential direct or indirect recursive calls
in the program because it cannot predict how many times the recursion can
occur. gstack prints a warning message if it detects a possible recursion
in the call graph.
• gstack prints a warning message if it detects a call to a function for which
there is no stack frame size information, or for which there is no call
information. Both of these situations might be caused by compiling the
function without using the -G option, or the function might be an assembly
language routine.
• gstack does not understand function calls through pointers. No warning is
printed.
• gstack cannot differentiate between static functions of the same name from
different files.
Example 1.
Run gstack:
$ gstack -s main a.out
Task main, 184 byte stack produced by the call chain of:
Framesize Function
--------- --------
112 main
16 f0
24 f1
32 f2
The gstrip utility processes executable files created by the Green Hills Software
linker as well as those created by some native linkers.
where:
Example 1.
In this example, suppose the executable elxr has only time slot 0 set:
gversion elxr
elxr: Green Hills Software, Version 3.0
elxr: Revision Date Tue Oct 31 09:12:51 2000
gversion 0 elxr
elxr: Green Hills Software, Version 3.0
elxr: [0] Tue Oct 31 09:12:51 2000
If asked to print the value of slot 1, which is not stamped, gversion will display
an error message:
elxr: Green Hills Software, Version 3.0
elxr has not been time stamped
elxr: [m] Tue Oct 31 09:12:51 2000
The following is a sample output for the command gversion -all ax.
ax: Green Hills Software, Version 3.0
ax: [0] Mon Oct 31 01:55:10 2000
ax: [6] Mon Oct 31 17:20:43 2000
ax: License Managed by Elan License Manager
The revision date is the last modification date of the source code. The release
date is the program’s distribution date.
If neither the -c nor -m option is specified, then by default gwhat outputs the
first string in the file. You can set the number of strings to output with the
-all or -s option.
It then displays all subsequent characters up to but not including any of the
following terminator characters (expressed in C) or end-of-file:
Character Character name
" Straight double quotation mark
> Greater than sign
\\ Backslash
\n Newline
\0 Null character
produces:
program.c:
Version 3.0
program.o:
Version 3.0
a.out:
Version 3.0
Under some circumstances, Green Hills may change the Green Hills release
what-string, using the -m option. For example:
The -c option can only be used once on a binary because it looks for the original
[Customer version stamp space] identifier.
You might want to build a custom what-string into your own software to mark
the executables. For example, suppose your executable, acmeprog, contains
a C source file that contains:
char sccsid[] = "@(#)ACME SOFTWARE ";
The following shows the different outputs of gwhat before and after using
the -m and -w options.
gwhat acmeprog
ACME SOFTWARE
gwhat -w "@(#)ACME SOFTWARE " -m "version 12" acmeprog
gwhat acmeprog
ACME SOFTWARE version 12
The CodeBalance
Optimization Wizard
1. Choose either .gpj files or .bld files in the first set of buttons. These file
types may not be mixed in later text fields.
2. Enter the path of the ultimate parent build file of the project in the first
field. You do not need to complete this field if your project build file is the
top-level build file.
3. Enter the path of the build file for your executable in the second field.
CodeBalance only attempts to balance source code under a program’s build
file. External libraries and other source files are not considered.
4. Enter the path to the Green Hills tool chain directory in the third field if
it differs from the default setting.
5. By default, CodeBalance will compare 16- and 32-bit instructions (where
these are supported), along with Size/Space and Loop optimizations. To
disable any of these optimizations, clear the appropriate check box.
6. Check Use MVC if the project build file you are optimizing has been
checked in to MULTI Version Control.
1. Each optimization set generates two executables, one containing code for
profiling, and the other (with a _nopro suffix) used to measure the size
of the final executable. By default, the executables are saved to the same
path as your project build file. To override the defaults, enter new names or
paths in the appropriate fields or use the browse button.
To reset the field to its default value, click the Use Default button. To
change the paths of all the other executables to be built to the path entered
in a field, click its Propagate button.
2. Codebalance uses (or generates) a call graph which, by default, is assumed
to be in the same path as your executable. To override the default, enter a
new name or path in the Call graph path field.
3. To instruct CodeBalance to build new executables, click the Rebuild All
button. Skip this step if you have already built these executables in a
previous invocation of CodeBalance.
1. The top fields show the default names and paths for the profiling data files
for your optimization sets. To override these defaults, enter a new name or
path in the appropriate field, or navigate to it using the browse button. If
you have manually profiled the executables, you must enter the paths to
the profile data files here.
To reset a field to its default value, click the Use Default button. To change
the paths of all the other executables to be built to the path entered in a
field, click its Propagate button.
2. In the next field, enter any command line arguments to be passed to your
executables during simulation.
3. In the next field, enter the command for the appropriate debug server. For
example, to profile using the ARM simulator, enter simarm. Native debug
servers are not compatible with CodeBalance.
4. Click the Generate button to create profile data for the optimized
executables. If the profile data files were generated manually or by a
previous invocation of CodeBalance, you can skip this step.
1. By default, the Optimize tab displays the graph and optimization sets for
an executable optimized for speed. The red arrows on the graph that point
to the size and speed of the recommended executable are in the bottom right
corner of the graph. The chart shows the optimization sets for each function
needed to produce the fastest possible executable, without regard for size.
To change the default setting and to optimize for size instead, select the
Smallest radio button at the top left of the tab.
To obtain the fastest executable within a specified size, select the Fit size
radio button, and enter the required maximum size in bytes in the text field.
Alternatively, you can specify a maximum size by clicking the graph.
The chart shows the optimizations required for each function to produce
the fastest executable that can fit in that size. Because there is not a set of
optimizations for the entire range of executable sizes, CodeBalance might
make recommendations for an executable smaller than the size you specify.
The actual size and speed of the executable generated by the recommended
optimizations is indicated by the red arrows on the chart axes.
2. After you have decided on a suitable balance between size and speed, click
Create buildfile to create an optimizing build file. By default, this build
file overwrites the initial project build file, but you can preserve the original
by choosing a new name and/or path in the Set optimized buildfile field.
If MVC is enabled and the optimizing build file overwrites the original,
this revised build file remains checked out.
3. Choose a path for a wizard file and click Create wizard file. The wizard
file contains optimization options that is set as #pragmas in the source
code. The optimizing build file contains instructions to include this wizard
file when your executable is rebuilt.
4. Click Finish to exit CodeBalance.
5. If you want to build the optimized executable immediately, start the Builder
and build the project in the usual way.
Note The values for the executable size are approximations. CodeBalance is
unable to calculate exact final sizes, and so any size that you specify must be
viewed as a guide, rather than an absolute maximum.
Advanced Options
You can open CodeBalance with many of its fields already completed by
running the program as follows:
codebalance filename -options
Where filename is the build file of the project you want to optimize and -options
can consist of any or all of the following:
-gpj
Turns on the CodeBalance new project mode. This option is necessary if the build
file for your project is in .gpj format.
-help
Displays a help screen.
-parentbld=file
Specifies the name of the top-level build file which contains the project to be
optimized (see “Completing the Setup Tab” on page 397).
-remote="debug_server"
Specifies the debug_server to be used for profiling (see “Completing the Profile
Tab” on page 399).
-simopts="arguments"
Specifies the arguments to be passed to the executable in simulation (see
“Completing the Profile Tab” on page 399). If multiple arguments are specified,
they must be contained in quotation marks.
-tooldir=path
Specifies the path where CodeBalance can find the Green Hills profiling utilities
and compilers (see “Completing the Setup Tab” on page 397).
Language Reference
Chapter 13
Green Hills C
To specify a C dialect:
Set the C/C++ Compiler→C Language Dialect option to one of the
following settings:
• Strict ANSI C (-ANSI) — Accepts the ANSI C language as defined
by X3.159–1989 and does not support extensions.
• ANSI C (-ansi) — [default] Recommended for all new development,
and for the compilation of any existing C code which approximates
to ANSI C. For more information, see “ANSI C” on page 407.
• GNU C (-gcc) — Recommended for porting existing GNU code to
the Green Hills development environment. For more information,
see “GNU C” on page 413.
• K&R C (-k+r) — Recommended for porting existing K&R code to
the Green Hills development environment. For more information,
see “K&R C” on page 420.
ANSI C
The ANSI C dialect is the default. We recommend using this mode for all new
development, as well as for the compilation of any existing C code that comes
close to ANSI C.
The compiler accepts the ANSI C mode as defined by X3.159–1989, with the
addition of support for numerous extensions. These extensions may be useful,
or even necessary, in certain cases. Some cases which are prohibited by the
ANSI standard generate a warning in this mode.
ANSI C Extensions
The extensions provided in this mode are as follows:
• Bitfields may have base types that are enumerated or integral types besides
int and unsigned int. This matches A.6.5.8 in the ANSI Common
Extensions appendix.
• Empty source files.
• Anonymous struct and union types.
• A translation unit (input file) can contain no declarations.
• Comment text can appear at the ends of preprocessing directives.
• __ALIGNOF__ is accepted. It behaves exactly like __alignof__ in
the list of GNU extensions below.
• __INTADDR__(expression) scans the enclosed expression as a constant
expression, and converts it to an integer constant (it is used in the
offsetof macro).
• The last member of a structure may have an incomplete array type. It may
not be the only member of the structure (otherwise, the structure would
have zero size).
• Integer constants suffixed by LL are given the type long long, and those
suffixed by ULL are given the type unsigned long long (any of the
suffix letters may be written in lower case).
• The long long types are accommodated in the usual arithmetic
conversions.
• Benign redeclarations of typedef names are allowed. That is, a typedef
name may be redeclared in the same scope as the same type. A warning is
issued.
• Dollar signs ($) can be accepted in identifiers with all dialects except Strict
ANSI C (-ANSI) and Standard C++ (Violations give Errors) (--STD).
• Numbers are scanned according to the syntax for numbers rather than the
pp-number syntax. Thus, 0x123e+1 is scanned as three tokens instead
of one invalid token.
• Assignment and pointer difference are allowed between pointers to types
that are interchangeable but not identical (e.g., unsigned char * and
char *). This includes pointer to same-sized integral types (e.g., typically,
int * and long *). Assignment of a string constant to a pointer to any
kind of character is allowed without a warning.
• Assignment of pointer types is allowed in cases where the destination type
has added type qualifiers that are not at the top level (e.g., int ** to
const int **). Comparison and pointer difference of such pairs of
pointer types are also allowed. A warning is issued.
• In operations on pointers, a pointer to void is always implicitly converted
to another type if necessary, and a null pointer constant is always implicitly
converted to a null pointer of the right type if necessary. In Strict ANSI
C, some operators allow such things, and others (generally, where it does
not make sense) do not allow them.
• Pointers to different function types may be assigned or compared for equality
(==) or inequality (!=) without an explicit type cast. A warning is issued.
• A pointer to void may be implicitly converted to or from a pointer to
a function type.
• The #assert preprocessing extensions of AT&T System V Release 4 are
allowed. These allow definition and testing of predicate names. Such names
are in a name space distinct from all other names, including macro names. A
predicate name is given a definition by a preprocessing directive of the form:
#assert name
#assert name(token-sequence)
which defines the predicate name. In the first form, the predicate is not
given a value. In the second form, it is given the value token-sequence.
Such a predicate can be tested in a #if expression, as follows:
#name(token-sequence)
The first form removes all definitions of the indicated predicate name; the
second form removes just the indicated definition, leaving any others that
might exist.
• asm statements and declarations are accepted. This feature is disabled in
Strict ANSI C mode because it conflicts with the ANSI C Standard for
statements such as:
asm("xyz");
The following extensions are also supported in this mode and are inspired by
the GNU compiler:
or
#import <filename>
This allows the object declared via the “declarator” to have a set of GNU C
extended attributes. Currently, the construct is parsed but has no effect.
• Keyword __typeof__ is supported. It takes an expression as the
argument, and returns the type of the expression. For instance, the following
code:
int i;
__typeof__(i) j;
GNU C
The GNU C dialect provides close compatibility with code written for the
GNU compiler. It accepts all of the ANSI C dialect features, together with a
number of GNU-specific extensions listed below. We recommend that you
use this dialect only when porting existing GNU-compiled code to the Green
Hills development environment.
A “?” operator can also be treated as an lvalue if its operands have types
that are different but are close enough that an lvalue cast can bridge the gap
(e.g., int and int *). A warning is issued.
• An expression can be cast to a union type containing a field with the type of
that expression. For example:
union X { int i; char c; };
union X f(int i) { return (union X)i; }
• Implicit conversions are allowed between integral and pointer types, and
between incompatible pointer types, with a warning. Implicit conversions
between pointer types can drop cv-qualifiers (e.g., const char * to
char *).
• Pointer arithmetic applies to void pointers and function pointers as if they
were char*.
• Explicit casts to struct and union types are allowed if they are do-nothing
casts, i.e., if the source type is the same as the destination type. (cv-qualifier
differences are allowed but ignored.) The result is an lvalue if the source
is an lvalue.
• Functions with return type void can have return expressions. A warning is
issued if the return expression does not have type void.
• Bitfield lengths that are too large for the associated type are ignored with
a warning (i.e., the field becomes an ordinary field whose address can be
taken). For example:
struct S {
char c: 9; // Oversized bitfield becomes regular field of type char
}; // (assuming a char can hold at most 8 bits)
• “?” operators with mixed void/non-void operands in the second and third
operands are accepted. The result has type void.
• Extraneous short and long specifiers in typedef declarations are ignored
with a warning.
is equivalent to:
"This is \na single string constant."
• The type modifiers signed, unsigned, long, and short can be used
with typedef types if the specifier is valid with the underlying type of the
typedef in ANSI C. For example:
typedef int I;
unsigned I *pui; // OK in GNU C/C++ modes; same as
// "unsigned int *pui"
The following GNU extensions are not currently supported in any GNU mode:
K&R C
K&R is the classic dialect of C in which UNIX was originally written. The first
edition of The C Programming Language by Kernighan and Ritchie describes
the K&R dialect. The most important implementation of this dialect was
the Portable C Compiler (PCC). There are many versions of this compiler,
including the C compilers distributed with System V.3, BSD 4.3 and SunOS
4x. Together these compilers implement hundreds of extensions, without which
it is impossible to compile the UNIX operating system or many existing C
application programs.
Green Hills compilers follow the version of PCC distributed with the Berkeley
4.3 BSD version of UNIX. We have also added many documented and
undocumented extensions from other compilers to simplify the process of
porting existing C programs to the Green Hills compiler.
The following is a list of incompatibilities between the Green Hills K&R Mode
and PCC:
Note that /**/ may be used to concatenate two strings in macro definitions.
• PCC considers the result of a ? : operator to be an lvalue if the first
operand is constant and the second and third operands are compatible
lvalues. The Green Hills compilers do not.
• PCC incorrectly parses the third operand of a ? : operator in a way that
some programs exploit. For example:
i ? j : k += l
is parsed by PCC as
i ? j : (k += l)
are ignored.
• Assignment is allowed between pointers and integers, and between
incompatible pointer types, without an explicit cast. A warning is issued.
• A field selection of the form p->field is allowed if p does not point to a
structure or union that contains field. p must be a pointer or an integer.
Likewise, x.field is allowed even if x is not a structure or union that
That is, function parameters are allowed to have the same names as
typedef identifiers. In the normal ANSI mode, any parameter list that
begins with a typedef identifier is considered prototyped, so the first
example above would give an error.
• The names of functions and of external variables are always entered at the
file scope.
• A function declared static, used, and never defined is treated as if its
storage class were extern.
• Enumerated types are always given type int. In ANSI mode, and depending
on the command line options, smaller integral types will be used if possible.
• No warning is generated for a storage specified appearing in other than the
first position in a list of specifiers (as in int static).
• short, long, and unsigned are treated as “adjectives” in type specifiers,
and they may be used to modify a typedef type.
• A “plain” char is considered to be the same as either signed char or
unsigned char, depending on the target and command line options. In
ANSI C, “plain” char is a third type distinct from both signed char
and unsigned char.
• Free-standing tag declarations are allowed in the parameter declaration list
for a function with old-style parameters.
• float function parameters are promoted to double function parameters.
• float functions are promoted to double functions.
• Declaration specifiers are allowed to be completely omitted in declarations
(ANSI C allows this only for function declarations). Thus,
i;
• Macro invocations having too many arguments are flagged with a warning
rather than an error. The extra arguments are ignored.
• Macro invocations having too few arguments are flagged with a warning
rather than an error. A null string is used as the value of the missing
parameters.
• Extra #else statements (after the first has appeared in an #if block) are
ignored, and a warning is emitted.
• Expressions in a switch statement are cast to int; this differs from the
ANSI C definition in that a long expression is (possibly) truncated.
• The promotion rules for integers are different; unsigned char and
unsigned short are promoted to unsigned int.
• An identifier in a function is allowed to have the same name as a parameter
of the function. A warning is issued.
same size, no data is lost. If the integer is smaller than the pointer, then the data
is reduced from the upper bit.
Japanese Automotive C also makes it legal to declare a bitfield with a type other
than int, signed int, or unsigned int.
For example, compiling the following code with the C/C++ Compiler→C
Language Dialect option set to Strict ANSI C (-ANSI) :
struct {
char b:3;
char c:5;
} s;
Type Qualifiers
There are two type qualifiers in all modes except K&R mode: volatile
and const.
volatile
When your C/C++ Compiler→C Language Dialect is set to ANSI (-ansi)
or Strict ANSI (-ANSI), enabling any of the Optimization→Optimization
Strategy settings (see “Optimization Options” on page 143) will implicitly
enable the Advanced→Advanced Optimization Options→Memory
Optimization option (-OM), which assumes that memory locations only
change under the control of the compiler. This assumption is usually, but
not always, true. Exceptions include memory which is updated by interrupt
routines, and memory-mapped I/O.
This optimization allows the compiler sometimes to avoid and/or delay reads or
writes to memory locations by maintaining a copy of the memory location in a
register. This is generally much faster because reads and writes to registers are
faster than reads and writes to memory.
You can use the volatile qualifier to disable this optimization for particular
variables (indicating that they may change), and retain its use for all other
variables.
const
The compiler gives a compile-time error for any attempt to modify an object
declared const. This qualifier also provides the compiler with additional
information for use in optimizations. Wherever the value of a const variable
is visible, the optimizer makes full use of the fact that this variable is simply
a named constant value, combining it with other constants at compile time,
and performing other simplifications. Even when the value of a const is not
visible, the optimizer can make use of the fact that the variable is invariant to
re-sequence statements and instructions or to move them outside of loops.
When const is used with volatile, the compiler never replaces a use of the
object with its value, even if the value of the object is visible.
Bitfields
Bitfields in C have a base type which determines the field’s alignment,
maximum size, and whether the field is signed or unsigned.
ANSI C Limitations
The ANSI C standard requires that the base type of a bitfield be either int,
signed int, or unsigned int. This restriction is enforced when the
C/C++ Compiler→C Language Dialect option is set to Strict ANSI C
(-ANSI), and is ignored without warning for all other dialects.
Signedness of Bitfields
Bitfields defined without either a signed or unsigned qualifier are
unsigned by default (note that this default varies between target processor
families). To control the signedness of bitfields manually:
The choice of signed versus unsigned bitfields can significantly affect code
efficiency. Unless the processor has special instructions for this purpose, it
may require two or even three instructions to extract the bits of a signed field
whenever that field is evaluated. This is because the bits must be sign-extended
to the size of an int, which may require two arithmetic shifts.
int i;
struct {int x:2; } y;
y.x = 2;
i = y.x;
if (y.x > 0) func();
Second, a bitfield must always fit entirely within a memory location that could
hold its base type. It cannot cross a boundary that a simple variable of that type
cannot cross. Thus, a field of type char can be placed in any memory location,
but cannot cross a byte boundary. For example:
struct {
char a:4;
char b:6;
char c:6;
} w;
Variable w requires three bytes because fields a and b do not fit in a single byte.
Therefore, four bits of padding are inserted before field b. Similarly, the fields
b and c do not fit in a single byte, so two bits of padding are inserted before the
field c. On the other hand, if we had:
struct {
short a:4;
short b:6;
short c:6;
} x;
then, variable x would require only two bytes because the total size of the three
fields is less than the size of a short.
Third, the alignment of a bitfield is determined by its base type. Padding may
be inserted so that the field and the structure containing it are properly aligned.
In the examples above, w has the alignment of a char, which is usually one
byte, and x has the alignment of a short, which is usually either one or two
bytes. Neither w nor x would be any larger due to alignment. However, in the
following example, y and z will have an extra byte of padding added if short
is 2 byte aligned:
struct {
char byte;
short a:4; /* padding inserted before
’a’ for alignment */
short b:6;
short c:6;
} y;
struct {
short a:4;
short b:6;
short c:6;
char byte; /* padding added after
’byte’ for alignment */
} z;
For information about the size and alignment of C and C++ data types, see
“ARM Characteristics” on page 84.
Enumerated Types
The enum type is treated as one of the integral types. By default, the members
of an enum type (enumerators) are treated as integral constants of type int
or greater (in case any of the values of the enumerators are out of int range).
To instruct the compiler to attempt to use the smallest possible predefined type
(including unsigned types) that allows representation of all listed values:
The ANSI standard does not call for strict type checking with respect to enum
types. In fact, a variable of enumerated type is considered equivalent to any
other integral value. Most operations which are allowed on values of integral
is the type of the current argument of the function. The va_arg macro
returns the value of the current argument of the function.
8. The <varargs.h> facility must be terminated by passing the variable of
type va_list to a call of the macro va_end at the end of the function.
Example 1.
#include <varargs.h>
/* Return the sum of a variable number of "int" arguments */
Sum(n, va_alist)
int n;
va_dcl /* steps 3 and 4 */
{
va_list params; /* step 5 */
int ret = 0;
va_start(params); /* step 6 */
while (n-- > 0) {
ret += va_arg(params,int); /* step 7 */
}
va_end(params); /* step 8 */
return(ret);
}
To use the <stdarg.h> facility, you must perform the following steps:
1. The line #include <stdarg.h> must appear before the first function
definition.
2. In the function definition, at least one fixed parameter must appear in the
parameter list before the ellipsis (...).
3. The last parameter in the function’s parameter list must be ellipsis (...).
4. There must be a variable declared in the function of type va_list.
5. The variable argument processing must be initialized by invoking the
macro va_start at the beginning of the function with two parameters:
(1) the variable of type va_list, and (2) the last fixed parameter in the
function parameter list.
Example 2.
#include <stdarg.h>
or
asm ("assembler_string");
The entire contents of the string will be passed through to the assembly
language output file in the same position as it appears in the source file. If the
underlying assembler requires a space or tab before the opcode, this tab or
space must appear in the string.
For example:
asm (" sethi %hi(L16),%o0");
This statement drops the sethi instruction into the assembly code generated by
the compiler, corresponding exactly to where the compiler found it in the source
code. See also Chapter 18, “Enhanced asm Macro Facility for C and C++”.
The Preprocessor
Green Hills C and C++ compilers include a built-in preprocessor. Preprocessing
is normally performed in a single pass. The setting of the C/C++ Compiler→C
Language Dialect option affects the behavior of the preprocessor. If ANSI C
(-ansi) or Strict ANSI C (-ANSI) is specified, then preprocessing follows the
ANSI standard, while K+R C (-k+r) follows the traditional UNIX rules.
When using the Builder, right-click the appropriate file and choose
Preprocess from the context-sensitive menu.
When using the driver, pass the -P option. You can also use the -E
option to direct output to stdout. This latter option includes #line
directives corresponding to the original file.
C Run-Time Library
On UNIX systems, Green Hills C can use the standard C library. The Green
Hills ANSI C Library, libansi.a , is provided for users needing an ANSI C
library and for those on non-UNIX systems which do not already have a C
library.
Extended Characters
English has a small alphabet, which is easily represented in eight bits by the
ASCII character set. However, many languages require more space, and
character sets that need more than 8 bits can be handled in two ways by ISO
C/C++:
The multi-byte string looks just like a traditional string in C, where each element
of the string has type char (or signed char or unsigned char). The
wide character string uses more space because each element of the string has
type wchar_t, which occupies either 16 or 32 bits depending on the target.
However, wide characters take up more space and, more importantly, they
cannot be manipulated by the large number of existing routines that were
written for traditional C character strings, requiring instead special wide
character functions.
Amendment 1 to the ISO C standard, adopted in 1995 and incorporated into both
the ISO C++ standard and the ISO C99 standard, added many new functions to
the standard C library in order to provide support for wide characters. These
new functions include wprintf() and wscanf(), together with most of the
functions in string.h and ctype.h, and have been added to libansi.a.
Note In addition to requiring the new functions, the standard also modifies
the behavior of printf() and scanf() and their derivatives to support
wide character strings and individual wide characters. The Green Hills
implementation does not provide these modifications in order to minimize the
impact of such changes on the size, speed, and stability of existing applications.
The compiler may not need to know everything about an extended character
set in order to parse comments or character and string literals which contain
extended characters. The compiler does need to be able to detect the end of a
string or comment. Therefore, if the extended character set contains no values
which have bytes that match punctuation the compiler is looking for, such as ’
\ ", the compiler will be able to scan the comment or literal without requiring
knowledge of the extended character set.
Parsing of wide character literals, however, is more difficult. The compiler must
know the encoding of the extended character set in order to determine which
bytes make up each element of type wchar_t. For example, L"hello"
will result in a string of type wchar_t[6], because each of the characters is
ASCII (which the compiler understands). If, however, the five bytes in the
string literal were not ASCII, the compiler must decide which bytes compose
the first wchar_t element, and so on.
Applications requiring an extended character set other than these will not
be able to use wide character literals with the Green Hills Software C/C++
compilers. Instead, all literals must be written as multi-byte strings and
converted using functions such as mbstowcs(). Furthermore, if the extended
character set has bytes which match certain ASCII punctuation characters,
multi-byte string literals may not be used either. In either case, it is possible to
place extended character strings in external data files and load them into the
application at run time. The application can still make full use of the Green
Hills C and C++ library routines to manipulate both wide character strings and
multi-byte strings even if the compiler cannot parse string literals containing the
extended character set.
Both Chinese and Kanji use one or more characters to represent a word. In
Chinese, each character is monosyllabic; in Japanese, a Kanji character can
be monosyllabic, polysyllabic, or both, depending on the character. (Almost
all Kanji characters have multiple pronunciations.) There are over 30,000
characters in Chinese, but Kanji routinely uses only a portion of them. For
example, one can read a Japanese newspaper knowing fewer than 2,000 Kanji
characters. The computer representations for Kanji provide between 5,000
and 10,000 Kanji characters.
In Japanese, there is also a phonetic alphabet with fewer than 100 characters.
Just like the English alphabet, this alphabet has cursive and block forms. They
are called Hiragana (cursive) and Katakana (block). Today Katakana characters
are used to spell foreign words and proper names phonetically.
The Green Hills C and C++ compilers provide support for Kanji characters in
comments, character strings, and character constants. Their use in variable
names or other identifiers is not supported because of the conflicts it would
cause with syntactic rules requiring identifiers to begin with a letter or
underscore. For example, the EUC representation of Kanji uses two bytes
for a single character, and neither byte is in the normal ASCII range. Thus a
compiler can scan a C string literal containing EUC Kanji characters without
any knowledge of the multi-byte representation. The Shift-JIS representation
of Kanji, however, allows normal ASCII characters in the second byte. The
compiler must have knowledge of Shift-JIS in order to correctly parse a string
literal containing Shift-JIS characters where the second byte has the value \
or ", for example.
Green Hills run-time libraries also correctly process character data containing
Kanji characters. There are several different ways to represent Kanji characters.
The Kanji representation directly supported by Green Hills compilers uses a
pair of characters to represent a single Kanji character. The first character is
always in the range of 0xa0 to 0xfe and the second character is always in
the range of 0x80 to 0xfe.
The C compiler allows a 2-byte Kanji character with single quotes. This is
easily done, as C allows two ASCII characters between single quotes.
Compiler Limitations
The ANSI standard requires that a conforming compiler implementation accept
programs of a certain complexity and size. These requirements are expressed
in terms of a list of acceptable limits. The Green Hills compiler meets the
requirements. The compiler has a specific upper limit for only one of the limits
(nested #include files). All other features are limited only by available
memory. For completeness, we list below all of the limits addressed by the
ANSI standard, giving, first, the number which the standard requires and,
second in parentheses, the number which the Green Hills compiler supports.
The code (U) indicates the compiler is theoretically unlimited.
The code (U > n) indicates that the compiler is theoretically unlimited, but it is
tested to handle the value n.
Term Meaning
undefined behavior Behavior, upon use of a nonportable or erroneous
program construct, of erroneous data, or of
indeterminately valued objects, for which this
International Standard imposes no requirements.
Permissible undefined behavior ranges from ignoring
the situation completely with unpredictable results, to
behaving during translation or program execution in a
documented manner characteristic of the environment
(with or without the issuance of a diagnostic message),
to terminating a translation or execution (with the
issuance of a diagnostic message).
unspecified behavior Behavior, for a correct program construct and correct
data, for which this International Standard explicitly
imposes no requirements.
Translation F.3.1
Each non-empty sequence of whitespace characters, other than new line, is
replaced by one space character.
There are two classes of messages: warnings and errors. All warning
diagnostics have warning at the beginning of the message field.
The compiler returns one (indicating failure), if any errors were reported, and
zero (indicating success), if there were no errors.
Environment F.3.2
No further processing occurs after program termination in a stand-alone
environment.
The argument argc is the number of valid elements in the argv array.
Identifiers F.3.3
A total of 255 characters are significant in an identifier without external linkage.
Characters F.3.4
The escape sequence values are as follows.
Sequence Value
\a 7
\b 8
\f 12
\n 10
\r 13
Sequence Value
\t 9
\v 11
The source and execution character sets are identical and the mapping is direct.
The basic execution character set includes all possible single-byte characters and
the extended character set includes all possible 4-byte characters. Therefore,
there are no characters or escape sequences represented in these two character
sets.
A wide character constant that contains more than one multi-byte character
has the same integer value as a wide character constant consisting only of the
rightmost multi-byte character.
The character type char is unsigned by default (note that this default
varies between target processor families). To control the signedness of chars
manually:
Integers F.3.5
The table below shows the storage and range of various variable types:
Size
Designation (bits) Range
char 8 0..255
signed char 8 -128..127
unsigned char 8 0..255
short 16 -32768..32767
signed short 16 -32768..32767
unsigned short 16 0..65535
int 32 -2147483648..2147483647
signed int 32 -2147483648..2147483647
unsigned int 32 0..4294967295
long 32 -2147483648..2147483647
signed long 32 -2147483648..2147483647
unsigned long 32 0..4294967295
The sign of the remainder of integer division will have the same sign as the
dividend, if the remainder is not zero.
Floating-Point F.3.6
The amount of storage and the range of various floating-point numbers are
shown below:
Size
Designation (bits) Range in bits
float 32 1.1754943635e-38 to
3.4028235e+38
double 64 2.2250738585072015e-308 to
1.7976931348623158e+308
long double 64 2.2250738585072015e-308 to
1.7976931348623158e+308
The type of the integer required to hold the difference between two pointers to
members of the same array is int. This is the type of diff_t.
Registers F.3.8
The register storage class specifier causes the compiler to give first priority to
the given variable when allocating variables to registers. Therefore, the register
storage class specifier significantly affects allocation of variables. Because the
compiler’s automatic allocation of registers is very good, the register storage
class specifier usually has a negative impact on allocation and should be used
very sparingly.
a_t m;
b_t n;
main()
{
u.a = m;
n = u.b;
}
The members of the union u are declared with two different types. A value is
assigned to u.a and the other member of the union, u.b, is evaluated. Whether
the value of m will equal n depends on the types of a and b. The various cases
are described below:
If a_t and b_t are integral or pointer types and have the same size, then the value
of n will be the same as if m was assigned to n directly, as
n = (b_t) m
If a_t and b_t are integral or pointer types and a_t is larger than b_t, then the
value of n will be as if this assignment were performed:
n = (b_t)((int) m);
If a_t and b_t are integral or pointer types and a_t is smaller than b_t, then the
value of n will be as if this assignment was performed:
n = (b_t)((int) m);
except the high bytes of n would be determined by the contents of memory before
the assignment of m to u.a.
If either a_t or b_t is an integral or pointer type and the other is a floating-point
type, such that both a_t and b_t are the same size in bytes, then the value of n
will depend upon the IEEE-695 signed magnitude representation of floating-point
numbers and the two’s complement or unsigned binary representation of integer
numbers. The bit-pattern of m will be interpreted as a bit-pattern of the alternate
representation. It is possible that illegal values will result if a_t is integral and
b_t is float.
If either a_t or b_t is an integral or pointer type and the other is a floating-point
type, such that a_t is smaller than b_t, then the high bytes of b_t will be taken
from a_t and the low bytes will depend on the contents of memory before the
assignment of m to u.a.
If either a_t or b_t is an integral or pointer type and the other is a floating-point
type, such that a_t is larger than b_t, then the content of b_t will be taken from
the high bytes of a_t and the low bytes of a_t will be discarded.
If a_t and b_t are both arrays of integral or pointer types, where the elements of
each array are of the same size, then the value of n[0] will be the same as if by
direct assignment of m[0] to n[0] and so forth for the first k elements of m and
n, where k is the length of the smaller array. If n is longer than m, the elements
of n beyond the first k will be determined by the contents of memory before the
assignment of m to u.a.
If a_t and b_t are both arrays of integral or pointer types, and the elements of
a_t are larger than the elements of b_t, then the low byte or bytes of m[0] will
be used for the value of n[0], and the higher byte or bytes of m[0] will be used
for the value of n[1], and so on up to n[sizeof(m[0])/sizeof(n[0])-1].
This process continues until the elements of either m or n have been exhausted. If
there are remaining elements in n, they will depend upon the contents of memory
before the assignment of m to u.a.
If a_t and b_t are both arrays of integral or pointer types, and the elements of a_t
are smaller than the elements of b_t, then the contents of m[0] will be used for
the low byte or bytes of n[0] and the contents of m[1] will be used for the higher
byte or bytes of n[0], and so on up to n[sizeof(m[0])/sizeof(n[0])-1].
This process continues until the elements of either m or n have been exhausted. If
there are remaining elements in n, they will depend upon the contents of memory
before the assignment of m to u.a.
to an array type ([]), and so on. Members of structures are padded and aligned
as described in “ARM Characteristics” on page 84. All structure members
except bitfields begin on a byte boundary. A structure is aligned according to
the strictest alignment of any of its members. An array member is aligned
according to the alignment requirement of its elements. Padding is performed
when necessary to ensure that a member or bitfield begins on its required
alignment. There is never any padding before the first member or bitfield, but
there is padding after the last member or bitfield if it is needed to ensure that the
size of the structure is a multiple of its alignment.
Bitfields may be declared with any standard integer base type (including
signed long long and unsigned long long if supported). They
may also be declared with _Bool or enum base types. When a bitfield is
used in an integral context, its value is converted to a standard integer type in
the following way. All standard integer types with rank greater than or equal
to int are ordered from least to greatest rank with signed types preceding
unsigned types of the same rank. The value is then converted to the first type
in this ordering that can represent all of the values of the original bitfield type.
For example, on a target where the long type has the same number of bits as
the int type and the long long type is supported, a bitfield value would
be promoted as follows. If an int can represent all values of the original
type, the value is converted to an int; otherwise, if an unsigned int can
represent all values of the original type, the value is converted to an unsigned
int; otherwise, if a long long can represent all values of the original
type, the value is converted to a long long; otherwise, it is converted to an
unsigned long long.
A bitfield must be wholly contained within a storage unit meeting the size and
alignment requirements of its declared base type. Padding is inserted between
bitfields as required to satisfy this constraint. For example:
struct {
int a:20;
int b:20;
long long c:20;
};
On a target with 32-bit ints with 32-bit alignment, there will be 12 bits of
padding between a and b since b cannot cross a 32-bit aligned boundary.
On a target with 64-bit long longs with 64-bit alignment, there will also
be 12 bits of padding between b and c since c cannot cross a 64-bit aligned
boundary. On a target with 64-bit long longs with 32-bit alignment, there
will be no padding between b and c since a long long can cross one 32-bit
aligned boundary; however, if c were declared to contain more than 44 bits,
there would then be 12 bits of padding between b and c since a 32-bit aligned
long long cannot cross two 32-bit aligned boundaries.
As long as the above constraint is met, multiple bitfields, even those of different
base types, may occupy the same storage unit. Within a particular storage unit,
bitfields are allocated in increasing memory address order. This means on a
big endian target the first bitfield will occupy the most significant bits of the
storage unit, and on a little endian target the first bitfield will occupy the least
significant bits. For example:
struct {
int a:10;
char b:4;
short c:5;
};
Assuming that ints are 32 bits, shorts are 16 bits, chars are 8 bits, and
the alignment of each type matches its size, there will be no padding between a
and b, but there will be 2 bits of padding between b and c. If bytes are 8 bits,
all three fields will occupy one 4-byte storage unit, with a occupying the first
byte, a and b sharing the second byte, and c occupying the third byte.
Qualifiers F.3.10
Any dereference of a pointer, such as *p, constitutes an access to an object, x,
with volatile-qualified type if any address from the value of p up to the value of
p plus sizeof(*p) less one is greater than or equal to the address of x and less
than the sum of the address and size of x.
Declarators F.3.11
There is no specific limit on the number of declarators that may modify an
arithmetic, structure, or union type.
Statements F.3.12
There is no specific limit on the number of case values in a switch.
If the file is included using the form #include file, the directory containing
the file in which the #include directive occurs is searched first. If the
directory does not contain the file, or if the file is using the form #include
<file>, a list of user-specified directories is searched. For information about
specifying include directories, see “Using Your Own Header Files and
Libraries” on page 96.
Quoted names are supported for source files that can be included.
the program would print the following to stderr and then call abort().
Assertion failed: "1==2", file "test.c", line 15
The following table explains the return values of the listed functions for certain
characters:
Function Characters for which non-zero value is returned
isalnum ’A’..’Z’, ’a’..’z’, and ’0’..’9’
isalpha ’A’..’Z’ and ’a’..’z’
iscntrl 0..31 and 127..255
islower ’a’..’z’
isprint 32..126
isupper ’A’..’Z’
The following values are returned by math functions for domain errors:
Function(s) Input values Return value
acos,acosf |x| > 1.0 0.0
acosh x < 1.0 0.0
asin,asinf |x| > 1.0 0.0
asinh x < 1.0 0.0
atan2,atan2f x==0.0,y==0.0 0.0
atanh x==1 or x < -1 0.0
log,logf x <= 0.0 0.0
pow,powf x==0.0 and y<0.0 0.0
sqrt,sqrtf x < 0.0 0.0
Only the functions exp, pow, and tan detect underflow and set errno to
ERANGE.
The function fmod() returns 0.0 when the second argument is zero.
Additional Features
Signals
The equivalent of signal(sig, SIG_DFL) is executed prior to the call of
a signal handler.
Space characters written out to a text stream immediately before a new line
character appear when the stream is read back on UNIX. Other systems vary.
A write on a text stream does cause the associated file to be truncated beyond
that point.
Unbuffered, fully buffered, and line buffered modes are all provided in hosted
environments. Embedded environments provide a limited form of buffering
which is essentially unbuffered, but which provides the benefits of buffering
within operations such as fwrite and printf.
Removing an open file has unpredictable results. In most cases the application
program will only have access to a portion of the file as it was before it was
deleted. Once the application exits, the file will cease to exist entirely even if
the application was writing to the file.
The effect of renaming a file to a name of a file which already exists varies
between systems. On some systems it is undetected and the old file is lost. On
others, the rename fails and all files remain unchanged.
If the - is neither the first character nor the last character in the scan list for [
conversion in the fscanf function, all characters in the range beginning with
the character preceding the - up to and including the character following the -
are added to the scan set. If the character following the - lexically precedes the
character before the -, then the - and the character following it are ignored.
tmpfile
An open temporary file is not removed if the program terminates abnormally.
errno
The functions fgetpos() and ftell() set errno to EBADF on failure.
Memory
The functions calloc, malloc, and realloc return NULL if the size
requested is zero. If the library libkr.a is linked into the application or if
memory checking is enabled, these functions will return a valid pointer.
abort()
When abort() is called, the buffers within the stdio library for open files are
not flushed. The files are closed and will exist. Temporary files will not be
deleted.
exit()
The low-order eight bits of the argument passed to exit are returned as the status.
getenv()
The only limitation on environment names is that they may not contain the
character = which is used to separate the name from its value.
The method to alter the environment list obtained by a call to the getenv
function is to call the function setenv(char *name, char *value).
This will set the environment variable named by the null-terminated string
name to a copy of the null-terminated string pointed to by value.
system()
The format of the string passed to system() may be of any format.
strerror()
The strings returned by strerror for the various values of errno are listed
below:
00: "Error 0 (no error)" 18: "Cross-device link"
01: "Not owner" 19: "No such device"
02: "No such file or directory" 20: "Not a directory"
03: "No such process" 21: "Is a directory"
04: "Interrupted system call" 22: "Invalid argument"
05: "I/O error" 23: "File table overflow"
06: "No such device or address" 24: "Too many open files"
07: "Arg list too long" 25: "Not a typewriter"
08: "Exec format error" 26: "Text file busy"
09: "Bad file number" 27: "File too large"
10: "No children" 28: "No space left on device"
11: "No more processes" 29: "Illegal seek"
12: "Not enough core" 30: "Read-only file system"
13: "Permission denied" 31: "Too many links"
14: "Bad address" 32: "Broken pipe"
15: "Block device required" 33: "Argument too large"
There is little formatting style to the string returned by strerror(). The first
character is always capitalized and the string does not end with a period.
The era for the clock function’s Local Specific Behavior is Midnight, January
1, 1970 (GMT).
68 h 69 i 6A j 6B k 6C l 6D m 6E n 6F o
70 p 71 q 72 r 73 s 74 t 75 u 76 v 77 w
78 x 79 y 7A z 7B { 7C | 7D } 7E ~ 7F del
Amendment 1 Compliance
This release complies with Amendment 1 to the ANSI/ISO standard for C. The
main focus of Amendment 1 was to address the needs of foreign character sets,
primarily wide characters (for more information, see “Extended Characters”
on page 436).
WEOF
• More than sixty new functions to operate on wide characters are declared.
These functions correspond to functions for characters in stdlib.h, stdio.h,
and string.h.
lldiv() takes two long long int arguments and returns both
arg1/arg2 and arg1%arg2 in a single operation.
// Comments
Comments of the form // are supported by default in conformance with ISO
C99. To disable this feature:
Standard C++
This dialect is defined by the International Standard ISO/IEC 14882:1998
(except as noted in this chapter) and includes all the latest features and changes
described in newer C++ books. All of the features of Standard C++ are enabled
by default, except for exception handling (because of the code size and speed
penalty to be paid even if EH features are not used). You can turn off many
individual C++ features by using the appropriate builder or driver options.
Note In order to obtain the exact dialect specified by the standard, you need to
set these additional options as follows:
• If control reaches the end of the main() routine, and main() has an integral
return type, it is treated as if a return 0; statement were executed.
• Pointers to arrays with unknown bounds as parameter types are diagnosed
as errors.
• A functional-notation cast of the form A() can be used even if A is a class
without a (nontrivial) constructor. The temporary created gets the same
default initialization to zero as a static object of the class type.
• A cast can be used to select one out of a set of overloaded functions when
taking the address of a function.
• Template friend declarations and definitions are permitted in class definitions
and class template definitions.
• Type template parameters are permitted to have default arguments.
• Function templates can have non-type template parameters.
• A reference to const volatile cannot be bound to an rvalue.
• Qualification conversions, such as conversion from T ** to T const
* const * are allowed.
• Digraphs are recognized.
• Operator keywords (e.g., and, bitand, etc.) are recognized.
• Static data member declarations can be used to declare member constants.
• wchar_t is recognized as a keyword and a distinct type.
• bool is recognized.
• RTTI (run-time type information), including dynamic_cast and the
typeid operator, is implemented.
• Declarations in tested conditions (in if, switch, for, and while
statements) are supported.
• Array new and delete are implemented.
• New-style casts (static_cast, reinterpret_cast, and
const_cast) are implemented.
• Definition of a nested class outside its enclosing class is allowed.
• mutable is accepted on non-static data member declarations.
• Namespaces are implemented, including using declarations and directives.
Access declarations are broadened to match the corresponding using
declarations.
Accepted Anachronisms
The following anachronisms are accepted when anachronisms are enabled:
• The base class name may be omitted in a base class initializer if there is only
one immediate base class.
• A bound function pointer (a pointer to a member function for a given object)
can be cast to a pointer to a function.
• A nested class name may be used as a non-nested class name provided no
other class of that name has been declared. The anachronism is not applied
to template classes.
• A reference to a non-const type may be initialized from a value of a
different type. A temporary is created, it is initialized from the (converted)
initial value, and the reference is set to the temporary.
• A reference to a non-const class type may be initialized from an rvalue of
the class type or a derived class thereof. No (additional) temporary is used.
• A function with old-style parameter declarations is allowed and may
participate in function overloading as though it were prototyped. Default
argument promotion is not applied to parameter types of such functions
when the check for compatibility is done, so that the following declares the
overloading of two functions foo:
int foo(int);
int foo(x) char x; {return x;}
It will be noted that in C this code is legal but has a different meaning: a
tentative declaration of foo is followed by its definition.
• A reference to a non-const class can be bound to a class rvalue of the
same type or a derived type thereof.
struct A {
A(int);
A operator=(A&);
A operator+(const A&);
};
main() {
A b(1);
b = A(1) + A(2); // Allowed as anachronism
}
GNU C++
This dialect closely emulates the C++ language supported by the GNU compiler.
• When doing name lookup in a base class, the injected class name of a
template class is ignored.
namespace N {
template <class T> struct A {};
}
struct A {
int i;
};
struct B : N::A<int> {
B() { A x; x.i = 1; } // g++ uses ::A, not N::A
};
• The injected class name is found in certain contexts in which the constructor
should be found instead.
struct A {
A(int) {};
};
A::A a(1);
class A {
class B {};
typedef B my_b;
friend class my_b;
};
• An inherited type name can be used in a class definition and later redeclared
as a typedef.
struct A { typedef int I; };
struct B : A {
typedef I J; // Refers to A::I
typedef double I; // Accepted in g++ mode
}; // (introduces B::I)
• In a catch clause, an entity may be declared with the same name as the
handler parameter.
try { }
catch(int e) {
char e;
}
• A constructor need not provide an initializer for every nonstatic const data
member (but a warning is still issued if such an initializer is missing).
struct S {
int const ic;
S() {} // Warning only in GNU C++ mode (error otherwise).
};
EEC++ offers all of the features of Standard C++ except those that adversely
affect code size or speed. Consequently, it excludes:
• Exception handling
• Multiple inheritance and virtual base classes
• Run-time type information
However it does retain the following notable but inexpensive features of C++
which are excluded by Embedded C++ (see “Embedded C++” on page 478):
• Templates
• Namespaces
• The mutable keyword
• Most new-style casts
As with Standard C++, other features can be individually controlled through
Builder and driver options.
Embedded C++
This dialect is intended as a stable, simple, and efficient version of Standard
C++, with the ultimate intention of producing an open standard to be used
worldwide. EC++ is not a new language specification that will compete with
existing Standard C++; rather, it is a pure subset for the practical user of C++. It
is often referred to as EC++ (Embedded C++), and originated in Japan through
the efforts of the following committee members:
EC++ is designed to meet the needs of the embedded industry. The committee
members established the following guidelines for creating EC++. The subset
fulfills the particular requirements of embedded systems designs.
• Many small enhancements and clarifications are retained from ANSI C++.
• Unused keywords are retained from ANSI C++ for upward compatibility.
• A style guide is available, providing guidelines for using EC++ wisely.
New additions to the ANSI C++ language have been made. One such feature
is the mutable keyword. The mutable keyword allows the user to modify
class members even if the object has been declared const. These cannot be
placed in ROM. Previously, the object was placed in ROM, without the ability
to manipulate it.
New-style casts force you to be explicit about the type of cast being performed.
The new-style casts are self documenting, and force you to be aware when
performing a dangerous cast. The EC++ committee felt the learning curve to
use the new-style casts was too steep to justify their benefit.
The following items are language elements which have poor run-time
characteristics and have not been included in EC++:
• iostream operations are supported for cin and cout, using classes
istream, ostream, ios, and streambuf.
• String operations are supported for class string.
• Math facilities are overloaded for both double and float types, in both
real and complex modes.
Note For more information about EC++, please visit the Embedded C++
(http://www.caravan.net/ec2plus/) web site.
Template Instantiation
The C++ language includes the concept of templates. A template is a description
of a class or function that is a model for a family of related classes or functions.
For example, you can write a template for a Stack class, and then use a
stack of integers, a stack of floats, and a stack of some user-defined type. In
the source, these might be written Stack<int>, Stack<float>, and
Stack<X>. From a single source description of the template for a stack, the
compiler can create instantiations of the template for each of the types required.
• You would like to end up with only one copy of each instantiated entity
across all the object files that make up a program. (This of course applies to
entities with external linkage.)
• The language allows you to write a specialization of a template entity,
that is, a specific version to be used in place of a version generated from
the template for a specific data type. (You could, for example, write a
version of Stack<int>, or of just Stack<int>::push, that replaces
the template-generated version; often, such a specialization provides a
more efficient representation for a particular data type.) While compiling a
reference to a template entity, the compiler cannot know if a specialization
for that entity will be provided in another compilation. Thus, it cannot do
the instantiation automatically in any source file that references it.
• The language also dictates that template functions that are not referenced
should not be compiled, and that, in fact, such functions might contain
semantic errors that would prevent them from being compiled. Therefore,
a reference to a template class should not automatically instantiate all the
member functions of that class.
It should be noted that certain template entities are always instantiated when
used (e.g., inline functions).
The Green Hills C++ compiler provides an instantiation mechanism that does
automatic instantiation at link time. For cases where the programmer wants
more explicit control over instantiation, the Green Hills C++ compiler also
provides instantiation modes and instantiation #pragma directives, which can
be used to exert fine-grained control over the instantiation process.
Automatic Instantiation
The goal of an automatic instantiation mode is to provide trouble-free
instantiation so that you can compile source files to object code, link them and
run the resulting program, without having to worry about how the necessary
instantiations get done.
Cfront requires that you follow a particular coding convention: all templates
must be declared in .h files, and for each such file there must be a
Those using Borland’s compiler must make sure that every compilation sees
all the source code it needs to instantiate all the template entities referenced
in that compilation. That is, you cannot refer to a template entity in a source
file if a definition for that entity is not included by that source file. In
practice, this means that either all the definition code is put directly in the .h
files, or that each .h file includes an associated .C (actually, .CPP) file.
The Green Hills C++ approach is a little different. It requires that, for each
instantiation of a non-exported template, there is some (normal, top-level,
explicitly-compiled) source file that contains the definition of the template
entity, a reference that causes the instantiation, and the declarations of any
types required for the particular instantiation. This requirement can be met
in various ways:
Exported templates are also supported by the Green Hills C++ automatic
instantiation method, but they require additional mechanisms explained in
“Exported Templates” on page 490.
1. The first time the source files of a program are compiled, no template
entities are instantiated. However, template information files are generated
and contain information about entities that could have been instantiated in
each compilation. These template information files have a .ti suffix.
2. When the object files are linked together, a program called the prelinker is
run. It examines the object files, looking for references and definitions of
template entities, and for the added information about entities that could
be instantiated.
3. If the prelinker finds a reference to a template entity for which there is
no definition anywhere in the set of object files, it looks for a file that
indicates that it could instantiate that template entity. Upon finding such a
file, the prelinker assigns the instantiation to it. The set of instantiations
assigned to a given file is recorded in an associated instantiation request
file (with a .ii suffix).
4. The prelinker then executes the compiler again to recompile each file for
which the .ii file was changed. The original compilation options (saved in
the .ti file) are used for recompilation.
5. When the compiler compiles a file, it reads the .ii file for that file and
obeys the instantiation requests therein. It produces a new object file
containing the requested template entities (and everything else already in
the object file). The compiler also receives a definition list file, which lists
all the instantiations for which definitions already exist in the set of object
files. If during compilation the compiler has the opportunity to instantiate
a referenced entity that is not on that list, it performs the instantiation. It
passes back to the prelinker (in the definition list file) a list of instantiations
that it has “adopted” in this way, so the prelinker can assign them to a
file. This adoption process allows rapid instantiation and assignment of
instantiations referenced from new instantiations, and reduces the need to
recompile a given file more than once during the prelinking process.
6. The prelinker repeats steps 3-5 until there are no more instantiations to
be adjusted.
7. The object files are linked together.
Once the program has been linked correctly, the .ii files contain a complete set of
instantiation assignments. From then on, whenever source files are recompiled,
the compiler will consult the .ii files and do the indicated instantiations as it
does the normal compilations. That means that, except in cases where the set of
required instantiations changes, the prelink step from then on will find that all
the necessary instantiations are present in the object files and no instantiations
assignment adjustments need be done. This is true even if the entire program is
recompiled.
The .ii files should not, in general, require any manual intervention. There is
one exception. If:
• the first file is being recompiled before the specialization file and is getting
errors,
the .ii file for the file getting the errors must be deleted manually to allow the
prelinker to regenerate it.
Instantiations are normally generated as part of the object file of the translation
unit in which the instantiations are performed. But when one instantiation per
object is used, each instantiation is placed in its own object file. This mode
is useful when building libraries that need to include copies of the instances
referenced from the library. If each instance is not placed in its own object file,
it may be impossible to link the library with another library containing some
of the same instances.
Instantiation Modes
Normally, when a file is compiled, no template entities are instantiated
(except those assigned to the file by automatic instantiation). The
overall instantiation mode can, however, be controlled using the C/C++
Compiler→C++→Templates→Manual Template Instantiation Mode
Builder option and associated driver options (see “Templates” on page 173).
Implicit Inclusion
Implicit inclusion is enabled by default, and permits the compiler to assume
that if it needs a definition to instantiate a template entity declared in a .h file
it can implicitly include the corresponding .C file to get the source code for
the definition. To disable this feature:
To find the template definition file for a given template entity, the compiler
needs to know the full pathname of the file in which the template was declared
and whether the file was included using the system include syntax (e.g.,
#include <file.h>). This information is not available for preprocessed
source code containing #line directives. Consequently, the compiler will not
attempt implicit inclusion for source code containing #line directives.
The following suffixes are searched for: .c, .C, .cpp, .CPP, .cxx, .CXX,
and .cc.
Care should be taken when writing files that may be implicitly included. For
instance, if the file xyz.C is implicitly included since it contains a definition of a
template declared in xyz.h, it is possible that more than one module will include
it. In fact, most likely any module that includes xyz.h will end up implicitly
including xyz.C. In addition, if xyz.C defines a global symbol (a non-template
function or a variable), every module which (implicitly) includes it will get that
symbol definition. This can lead to multiply defined symbol errors from the
linker. This can be averted by having only template definitions in files that can
be implicitly included. An implicitly included header file should be organized
much the same way as any other header file.
Since a file is automatically pulled in when the implicit inclusion is on, the
compiler driver or the builder do not need to separately compile it; just like a
regular header file does not need to be separately compiled.
Implicit inclusion works well alongside automatic instantiation, but the two
are independent. They can be enabled or disabled independently, and implicit
inclusion is still useful when automatic instantiation is not done.
Exported Templates
Exported templates are templates declared with the keyword export, which is
not recognized by default. To enable this feature:
// File 1:
#include <stdio.h>
static void trace() { printf("File 1\n"); }
export template <class T> T const & min(T const &, T const &);
int main() {
trace();
return min(2, 3);
}
// File 2:
#include <stdio.h>
static void trace() { printf("File 2\n"); }
Note that these two files are separate translation units: one is not included in
the other. That allows the two functions trace() to coexist (with internal
linkage).
Automatic Instantiation
The Green Hills C++ compiler performs automatic template instantiation to
build template code by default. During a prelink step, the compiler determines
the necessary template code the program requires and compiles into some of the
object files to make up the program. The compiler tracks how the program uses
template code and records this information in the .ii files in the build directory.
compiles template code into an existing object file, the dependency information
that Clearmake previously recorded for that object file is no longer updated. The
next time that Clearmake is invoked, it will rebuild the object file. After this
rebuild, the dependency information for the object file is correct once again. At
this point, Clearmake no longer executes unnecessary rebuilds of that object file.
This option takes all the template code to which the source module refers and
compiles it into the object module. If multiple source modules refer to the
same template class or function, copies of the compiled template code appear
in multiple object modules.
The Compile-Time Demand Instantiation is easy to use, requiring only that you
specify extra compiler options. It is suitable for most applications, especially
for building archives. Also, this method does not conflict with ClearCase
configuration management. The disadvantage is that the compiler uses extra
time and disk space to perform redundant template instantiation, and the same
instantiation may appear in multiple source files, thereby causing programs
to be larger than necessary.
Explicit Instantiation
The Explicit Instantiation method is an alternate form of compile-time
instantiation. The Green Hills C++ compiler allows you to add directives to the
source code to specify which template classes to instantiate.
When it compiles a source module, the compiler instantiates all the template
classes specified by the directives in the source. The compiler instantiates each
template class completely; that is, it instantiates every member function and
static data member of the class.
Example 1.
class BIG_BASE {
public:
char c[70000];
virtual void foo();
};
class TWO_BASE {
public:
int i;
virtual void bar();
};
Where only single class inheritance is involved, the offset of a base class is
always 0, so this limitation does not apply.
Namespace Support
Namespaces are enabled by default. To disable this feature:
For example:
namespace N {
int g(int);
int x = 0;
template <class T> struct A {
T f(T t) {return g(t);}
T f() {return x;}
};
}
namespace M {
int x =99;
double g(double);
N::A<int> ai;
int i = ai.f(0); // N::A<int>::f(int) calls
// N::g(int)
int i2 = ai.f(); // N::A<int>::f() returns 0 (=
// N::x)
N::A<double> ad;
double d = ad.f(0); // N::A<double>::f(double)
// calls M::g(double)
double d2 = ad.f(); // N::A<double>::f() also
// returns 0 (= N::x)
}
The lookup of names in template instantiations does not conform to the rules in
the working paper in the following respects:
• Although only names from the template definition context are considered for
names that are not functions, the lookup is not limited to those names visible
at the point at which the template was defined.
• Functions from the context in which the template was referenced are
considered for all function calls in the template. Functions from the
referencing context should only be visible for “dependent” functions calls.
The lookup rules for overloaded operators are implemented as specified by the
standard. This means that the operator functions in the global scope overload
with the operator functions declared extern inside a function, instead of
being hidden by them. The old operator function lookup rules are used when
namespaces are turned off. This means a program can have different behavior,
depending on whether it is compiled with namespace support enabled or
disabled, as in the following example:
struct A {};
A operator+(A, double);
void f() {
A a1;
A operator+(A, int);
a1 + 1.0; // calls operator+(A, double) with
// namespaces enabled
} // but otherwise calls operator+(A, int);
The compiler will search for a valid PCH file to read in, and if one is not found
will create one for use on a subsequent compilation.
The PCH file contains a snapshot of all the code preceding the header stop
point. The header stop point is typically the first token in the primary source
file that does not belong to a preprocessing directive, but it can also be specified
directly by #pragma hdrstop (see “Other Ways to Control PCHs” on page
501) if that comes first. For example:
#include "xxx.h"
#include "yyy.h"
int i;
The header stop point is int (the first non-preprocessor token) and the PCH
file will contain a snapshot reflecting the inclusion of xxx.h and yyy.h. If the
first non-preprocessor token or the #pragma hdrstop appears within a #if
block, the header stop point is the outermost enclosing #if. The following
illustrates a more complicated example:
#include "xxx.h"
#ifndef YYY_H
#define YYY_H 1
#include "yyy.h"
#endif
#if TEST
int i;
#endif
Here, the first token that does not belong to a preprocessing directive is again
int, but the header stop point is the start of the #if block containing it. The
PCH file will reflect the inclusion of xxx.h and, conditionally, the definition
of YYY_H and inclusion of yyy.h; it will not contain the state produced by
#if TEST.
A PCH file will be produced only if the header stop point and the preceding
code (mainly, the header files themselves) meet certain requirements:
• The header stop point must appear at file scope; it may not be within an
unclosed scope established by a header file. For example, a PCH file will
not be created in this case.
// xxx.h
class A {
// xxx.C
#include "xxx.h"
int i; };
• The header stop point must not be inside a declaration started within a header
file, nor (in C++) may it be part of a declaration list of a linkage specification.
For example, in the following case the header stop point is int, but since it
is not the start of a new declaration, no PCH file will be created:
// yyy.h
static
// yyy.C
#include "yyy.h"
int i;
• Similarly, the header stop point must not be inside a #if block or a
#define started within a header file.
• The processing preceding the header stop must not have produced any
errors. Note that warnings and other diagnostics will not be reproduced
when the PCH file is reused.
• The compiler version, including the date and time the compiler was built.
• The current directory (i.e., the directory in which the compilation is
occurring).
• The command line options.
• The initial sequence of preprocessing directives from the primary source
file, including #include directives.
• The date and time of the header files specified in #include directives.
This information comprises the PCH “prefix.” The prefix information of a given
source file can be compared to the prefix information of a PCH file to determine
whether the latter is applicable to the current compilation.
line by line, the compiler reads in the rest of a.pch and thereby establishes the
state for the rest of the compilation.
It may be that more than one PCH file is applicable to a given compilation.
If so, the largest (i.e., the one representing the most preprocessing directives
from the primary source file) is used. For instance, consider a primary source
file that begins with:
#include "xxx.h"
#include "yyy.h"
#include "zzz.h"
If there is one PCH file for xxx.h and a second for xxx.h and yyy.h together, the
latter will be selected (assuming both are applicable to the current compilation).
Moreover, after the PCH file for the first two headers is read in and the third is
compiled, a new PCH file for all three headers may be created.
• If the precompiled header file is based on at least one out-of-date header file
but is otherwise applicable for the current compilation.
• If the precompiled header file has the same base name as the source file
being compiled (e.g., xxx.pch and xxx.C) but is not applicable for the
current compilation (e.g., because of different command line options).
This handles some, but not all, common cases. Other PCH file clean-up must be
performed by the programmer.
If the specified PCH file is invalid (i.e., if its prefix does not match the prefix for
the current primary source file), a warning will be issued and it will not be used.
By default, PCH files are created and searched for in the directory containing the
primary source file. To specify an alternate directory for writing and reading:
This option will not affect PCH files specified with an absolute pathname.
Here the precompiled header file will include processing states for xxx.h
and yyy.h but not zzz.h. This is useful if you decide that the information
added by what follows the #pragma hdrstop does not justify the
creation of another PCH file.
• #pragma no_pch may be used to suppress precompiled header
processing for a given source file.
Performance Issues
The relative overhead incurred in writing out and reading back in a precompiled
header file is quite small for reasonably large header files.
In general, the cost of writing out a precompiled header file is relatively low,
even if the file ends up not being used. If it is used, it almost always produces a
significant increase in compilation speed. The problem is that the precompiled
header files can be quite large (from a minimum of about 250K bytes to several
megabytes or more).
Different environments and different projects will have different needs, but in
general you will need to experiment and may need to make some minor changes
to source code in order to make the best use of this feature.
Linkage
C++ accepts the extern "language" directive in order to achieve linkage
between C++ and C. The full syntax is as follows:
extern "language" {
declarations
}
or
extern "language" declaration;
Note that the extern "language" directive only affects the external names of
functions so that the compiler will apply the appropriate function naming rules.
This directive does not modify the type or number of arguments of a function, or
its return type. Normal C++ type checking rules are not altered by this directive.
For more information about using C++ with C, see Chapter 17, “Mixing
Languages and Writing Portable Code”.
Global objects, such as those in libraries (e.g. cin, cout, and cerr) must
be constructed and initialized for the entire program. This means that the
constructor functions must be called as soon as the program begins. The
compiler has no knowledge of external global objects contained in other
modules or libraries except for an extern declaration. This is not enough
information for the compiler to be able to properly insure that these calls are
performed. For targets that use the Green Hills linkers, the linker resolves the
global constructor and destructor information. In other environments, the
cxxmunch utility assumes this responsibility. The VxWorks environment
is unique in that the module load/unload functions invoke the global
constructors/destructors, or else the user executes them manually.
After an executable has been produced, the Green Hills C++ compiler driver
calls an nm utility (such as gnm) to find all global symbols. The output of the
nm utility is sent to the post-link program cxxmunch. cxxmunch searches
for all global constructor and destructor calls and generates a C module that
will execute these calls appropriately at program startup and exit. The driver
then invokes the compiler and assembler to produce another object module.
Following that, the linker is invoked to relink the new constructor/destructor
object with the original object and libraries. This produces the fully processed
C++ executable, which has all of the appropriate constructor and destructor
calls.
The driver makes all of this processing completely transparent. However, those
who choose not to use the driver provided by Green Hills are responsible for
calling the post-link program after producing an executable; otherwise the
program may not run correctly.
This utility is a C++ name “demangler”. It reads the input from stdin and
writes output to stdout. Anything that looks like mangled names in the input
is changed to:
ld: Undefined symbol
f(int, float)
The decode utility takes only a single option: -u. When used, -u specifies
whether external names have an added leading underscore.
up to the first multiple of the size of the base type. Plain bitfields are
unsigned unless C/C++ Compiler→Data Types→Signedness of Bitfields
is set to Signed.
• 12.2: Temporary objects — are generated for f(X(2)), but the result will
be stored directly into ’b’.
• 14: Templates — only C and C++ linkages are supported.
• 14.7.1: Implicit instantiation — Recursive instantiations are limited to 30.
• 15.5.1: The terminate() function — the stack is unwound before
terminate() is called.
• 15.5.2: The unexpected() function — unless reset by user, will call
terminate().
• 16.1: Conditional inclusion — Numeric values for character literals in
#if / #elif controlling expressions is identical to char literals in
regular expressions.
• 16.2: Source file inclusion — (see also “Instructing the Compiler to Search
for Your Headers” on page 96):
All of the preprocessor predefined macros are listed in the following sections.
Macro Formats
The standards for C and C++ require that all macros which are predefined by
the compiler begin with one or two underscore characters. Prior to the ANSI
standard, some C preprocessors defined macros with names (such as ghs or
unix) which could conflict with macro names in the user’s program.
Each Green Hills macro is defined with two leading underscores in all language
modes, unless stated otherwise.
Macros marked with a * are also defined by default without the two leading
underscores in K&R C (and the Compatibility Mode C Compiler’s Transition C
Mode).
Recent preprocessors predefine macros with two leading underscores and two
trailing underscores. Macros marked with a ** are defined by default in all
three possible forms (for instance, ghs, __ghs, and __ghs__) in K&R C
(and the Compatibility Mode C Compiler’s Transition C Mode).
When using other C or C++ modes (except Strict ANSI C), you can instruct
the preprocessor to generate versions of macros marked as * or ** as it
would in K&R mode by enabling the Advanced→Advanced Preprocessor
Options→Definition of Unsafe Symbols (--unsafe_predefines) option.
C Language Macros
__EXTENDED_EMBEDDED_CXX_HEADERS
The Extended Embedded C++ header files and libraries are used (for example,
options --eel or --eele).
__Japanese_Automotive_C
Japanese Automotive C
__PROTOTYPES__
All modes of C except K&R mode. All modes of C++.
__STRICT_ANSI__
Language is Strict ANSI C. Defined only when GNU is selected as your C or
C++ dialect.
__EXTENDED_EMBEDDED_CXX
Language is Extended Embedded C++ (ESTL) (for example option --ee).
__EXTENDED_EMBEDDED_CXX_HEADERS
The Extended Embedded C++ header files and libraries are used (for example,
options --eel or --eele).
__STANDARD_CXX
Language is Standard C++.
__STANDARD_CXX_HEADERS
The Standard C++ header files and libraries are used (for example, options
--stdl or --stdle).
__GHS_VERSION_NUMBER=n
Represents the version, n, of the toolchain.
__gnu_asm
Indicates that the GNU assembler is in use.
__unix_asm
Indicates that the UNIX assembler is in use.
Note For a list of individual processor macros, see “ARM Processor Variants”
on page 90.
Endianness Macros
One of these symbols is always defined to specify the endianness of the target
processor.
__BIG_ENDIAN__
Big Endian byte order.
__LITTLE_ENDIAN__
*
Little Endian byte order.
Sizes
__CHAR_BIT=n
Specifies the size of char in bits.
__FUNCPTR_BIT=n
Specifies the size of a function pointer in bits.
__INT_BIT=n
Specifies the size of int in bits. See also __PTRDIFF_TYPE__,
__SIZE_TYPE__, and __WCHAR_TYPE__ in “GNU Compatibility Macros” on
page 522.
__LONG_BIT=n
Specifies the size of long in bits.
__LLONG_BIT=n
Specifies the size of long long in bits. Defined only if the long long type
is supported.
__NO_LONGLONG
No long long support (equivalent to the --no_long_long driver option).
__PTR_BIT=n
Specifies the size of a pointer in bits.
__REG_BIT=n
Specifies the size of an integer register in bits.
__SHRT_BIT=n
Specifies the size of short in bits.
__WCHAR_BIT=n
Specifies the size of wchar_t in bits.
Signedness
__Enum_Field_Is_Signed__
__Enum_Field_Is_Unsigned__
Bitfield enumerations are signed or unsigned.
__Field_Is_Signed__
__Field_Is_Unsigned__
Bitfields are signed or unsigned
__Ptr_Is_Signed
__Ptr_Is_Unsigned
Pointers are signed or unsigned.
__SIGNED_CHARS__
__CHAR_UNSIGNED__
Type char is signed or unsigned.
__WChar_Is_Signed__
__WChar_Is_Unsigned__
Type wchar_t is signed or unsigned.
Floating-Point Macros
These macros specify the manner in which floating-point operations are
performed.
__DOUBLE_HL
Passed if the high word of a double comes at the lower address in memory. This is
usually the case for big endian targets, although certain targets behave differently.
__IeeeFloat *
IEEE-754 floating-point format. This symbol is always defined.
MISRA Macros
These macros relate to the MISRA C variant.
__MISRA_i=n
MISRA diagnostic levels.
i is either 8 or 118–127, and n is one of the following:
• 0: Silent
• 1: Warn
• 2: Error
For more information about the MISRA rules, see “MISRA C” on page 154.
__ONLY_STANDARD_KEYWORDS_IN_C
MISRA rule No. 1
__BASE__
A string literal representing the name of the current source file, without the
directory path.
__FUNCTION__
A string literal representing the current function name. (The macros
__FUNCTION__ and __PRETTY_FUNCTION__ depend on their context, and
cannot be determined by a preprocessing-only pass. Therefore, the compiler will
not resolve those two macros when options -E or -P are used.)
__PRETTY_FUNCTION__
In C++, a string literal representing the fully qualified function name. In C, behaves
the same as __FUNCTION__.
C++ Macros
These macros relate to various features of C++.
__ARRAY_OPERATORS
Defined when array new and delete are enabled (that is, operator new[] and
operator delete[]).
_BOOL
Defined when bool is recognized as a basic type (for example, as with the option
--bool).
__EDG_IMPLICIT_USING_STD
Defined when the standard namespace std is implicitly used (as with the option
--using_std).
__EDG_RUNTIME_USES_NAMESPACES
Indicates that the C++ Run-time libraries use namespaces.
__EXCEPTION_HANDLING
__EXCEPTIONS
Indicates C++ compiler is running in a mode that allows exception handling.
__NAMESPACES
Indicates C++ namespaces are accepted.
__RTTI
Indicates Run-Time Type Identification code accepted.
_WCHAR_T
Defined if wchar_t is a keyword.
INTEGRITY Macros
__INTEGRITY
INTEGRITY real-time operating system.
ThreadX Macros
__THREADX
ThreadX real-time operating system.
TX_ENABLE_EVENT_LOGGING
ThreadX event logging enabled.
VxWorks Macros
__VXWORKS *
Wind River VxWorks.
__CPU=x
CPU variants for VxWorks.
Deprecated Macros
These macros are deprecated and may not be supported in future versions of
MULTI.
__Char_Is_Signed
Type char is signed char.
__Char_Is_Unsigned
Type char is unsigned char.
__Int_Is_32
Type int is 4 bytes.
__Int_Is_64
Type int is 8 bytes. (The macro __Int_Is_64 is an old style macro, kept for
backward compatibility. The new style macros (like __INT_BIT=n) should be
used when possible.)
__msw *
Any version of Microsoft Windows (deprecated).
__LL_BIT=n
Describes the size of long long in bits.
__LL_Is_64
Type long long is 8 bytes (when long long is an allowed type).
__Long_Is_32
Type long is 4 bytes.
__Long_Is_64
Type long is 8 bytes.
__Ptr_Is_32
Pointers are 4 bytes.
__Ptr_Is_64
Pointers are 8 bytes.
__Reg_Is_32
CPU has 32-bit registers.
__Reg_Is_64
CPU has 64-bit registers.
__WChar_Is_Int__
Type wchar_t are int or unsigned int.
__WChar_Is_Long__
Type wchar_t are long or unsigned long.
__WChar_Is_Short__
Type wchar_t is short or unsigned short.
#pragma Directives
#pragma directives allow individual compiler implementations to add special
features to C programs without changing the C language. Programs that use
#pragma directives stay relatively portable, although they make use of features
unavailable in all ANSI C implementations.
According to the ANSI standard, the #pragma directives that are not
recognized by the compiler should be ignored. This requirement may help
when porting code between compilers because one compiler will recognize and
process a certain #pragma directive, while a different compiler (which does
not need or recognize that #pragma directive) will, by default, generate a
warning and ignore it.
The majority of Green Hills proprietary #pragma directives begin with the
keyword ghs to differentiate them from other implementations. The compiler
considers any #pragma beginning with the ghs keyword to be recognized.
int function(int i)
{
if (i) {
i++;
}
#pragma asm
some assembly
#pragma endasm
return i;
}
In this case, the contents of the #pragma asm will appear in the same block of
code as the i++; statement. An empty statement (such as a lone semicolon on
a line) may be used to force the contents of the pragma #asm into the same
block as the empty statement. This caveat only applies to the Compatibility Mode
compiler.
#pragma hdrstop
Instructs the compiler to write the parse state to disk at this point. Later, when
the file is recompiled, parsing will begin at the point of this #pragma, with the
precompiled header information loaded.
For more information about precompiled header files, see “Precompiled Header
Files” on page 497.
#pragma ident "string"
Inserts string in the output assembly file as a comment.
#pragma inline function-list
This #pragma is deprecated.
Instructs the compiler to consider each function in the comma-separated
function-list as a candidate for inlining.
Note that you cannot force the compiler to inline any function.
#pragma instantiate fn
#pragma can_instantiate fn
#pragma do_not_instantiate fn
These #pragmas can be used to control the instantiation of a template function,
fn. For full documentation, see “Template Instantiation” on page 481.
#pragma intvect intfunc integer_constant
Instructs the compiler to insert a pointer to the function intfunc at the address
specified by integer_constant.
For more information, see “Writing Interrupt Routines” on page 120.
#pragma no_pch
Suppresses precompiled header processing for the current source file.
For more information about precompiled header files, see “Precompiled Header
Files” on page 497.
#pragma once
This #pragma is only available with the New Generation Compiler.
If this #pragma is placed at the beginning of a header file, the compiler will only
include the file once, and will ignore subsequent #include statements that
reference the file.
and foo is not defined in any other file, then the address of foo is set to zero (or,
in the case of projects that use PIC or PID, 0 plus the adjustment for the text
or data segment offset). This will prevent an undefined symbol linker error.
• If foo is defined in filename:
#pragma weak foo
int foo = 1;
and a definition of foo appears in any other file, then that other definition
will have priority, and the definition in filename will be treated as if it were
an external reference.
#pragma weak foo = bar
This #pragma has the same effect as #pragma weak foo, except that (subject
to the same conditions) the address of foo is set to the address of bar. It
requires that foo is not defined in the current module, although it could be an
external reference. bar must be defined at the outermost level of the current
module. bar may not be a common symbol (see the C/C++ Compiler→C/C++
Data Allocation→Allocation of Uninitialized Global Variables option in
“C/C++ Data Allocation” on page 166).This #pragma may be used to provide
a backwards-compatible alias to a symbol which has been renamed in a new
version of a program, as follows:
If any old software depends on the existence of oldname, it will continue to work as
if the function is called oldname. If there are no longer any references to oldname,
then the symbol effectively disappears and can be reused.
These checks can all also be set with Builder or driver options (see the
Debugging→Run-Time Error Checks option in “Debugging Options” on page
147). Note that the driver only accepts the longer form of the check name.
These #pragmas require that the Green Hills library, libind, be linked in. All of
these checks require additional instructions to be inserted into the generated code,
and consequently will increase your code size and degrade its performance.
For information about using these run-time checks, see Chapter 14, “Viewing
Memory Allocation Information” in the MULTI: Debugging book.
Conditional #pragmas
Any of the Green Hills extension #pragmas can be made conditional upon
whether you are generating debugging information or are optimizing your
executable. To make a #pragma conditional, use the syntax:
Intrinsic Functions
The ARM architecture provides a number of intrinsic functions to perform
certain tasks which are difficult or inefficient to write in a high-level language.
The Green Hills C and C++ compilers support these functions.
The name of a C or C++ intrinsic function begins with two underscores (__),
which indicate to the compiler that it is a special function. It usually generates
optimized inline code, often using special instructions that do not correspond to
standard C and C++ operations.
The sticky-overflow bit (Q) set by some DSP instructions can be accessed with
(__GETSR() & (1<<27)).
Multiplication Intrinsics
signed int __SMLAD(signed int Rm, signed int Rs, signed int
Rn);
signed int __SMLADX(signed int Rm, signed int Rs, signed int
Rn);
signed int __SMLSD(signed int Rm, signed int Rs, signed int
Rn);
signed int __SMLSDX(signed int Rm, signed int Rs, signed int
Rn);
These functions multiply the top halfwords of Rm and Rs, and add or subtract the
result from the product of their bottom halfwords. The result of that operation is
then added to Rd.
The X variants swap the top and bottom halfwords of Rs before multiplication.
signed long long __SMLALD(signed long long Rd, signed int Rs,
signed int Rn);
signed long long __SMLALDX(signed long long Rd, signed int
Rs, signed int Rn);
signed long long __SMLSLD(signed long long Rd, signed int Rs,
signed int Rn);
signed long long __SMLSLDX(signed long long Rd, signed int
Rs, signed int Rn);
These functions multiply the top halfwords of Rm and Rs, and add or subtract the
result from the product of their bottom halfwords. The result of that operation is
then added to the 64 bit Rd.
The X variants swap the top and bottom halfwords of Rs before multiplication.
signed int __SMMLA(signed int Rm, signed int Rs, signed int
Rn);
signed int __SMMLAR(signed int Rm, signed int Rs, signed int
Rn);
signed int __SMMLS(signed int Rm, signed int Rs, signed int
Rn);
signed int __SMMLSR(signed int Rm, signed int Rs, signed int
Rn);
These functions perform a signed 32x32->64 bit multiply on Rm and Rs and
add the upper 32 bits to Rn.
The R variants round the intermediate result instead of truncating it.
signed int __SMMUL(signed int Rm, signed int Rs);
signed int __SMMULR(signed int Rm, signed int Rs);
These functions perform a signed 32x32->64 bit multiply on Rm and Rs and
take the upper 32 bits.
The R variant rounds the result instead of truncating it.
signed int __SMUAD(signed int Rm, signed int Rs);
signed int __SMUADX(signed int Rm, signed int Rs);
signed int __SMUSD(signed int Rm, signed int Rs);
signed int __SMUSDX(signed int Rm, signed int Rs);
These functions multiply the top halfwords of Rm and Rs, and add or subtract the
result from the product of their bottom halfwords.
The X variants swap the top and bottom halfwords of Rs before multiplication.
Bitwise Extraction
int __PKHBT(int Rn, int Rm, __ghs_c_int__ lslshift);
Returns a 32 bit value in which the bottom halfword (least significant 16 bits)
are taken from the bottom halfword of Rn, and the top halfword is taken from
the top halfword of Rm logically shifted left by the immediate lslshift. An lslshift
value of 0 specifies no shift.
int __PKHTB(int Rn, int Rm, __ghs_c_int__ asrshift);
Returns a 32 bit value in which the top halfword (most significant 16 bits) are taken
from the top halfword of Rn, and the bottom halfword is taken from the bottom
halfword of Rm arithmetically shifted right by the immediate asrshift. If asrshift is 0,
this operation is equivalent to __PKHBT().
int __SEL8 (int Rn, int Rm);
The 4 bytes of the return value, from least to most significant, are set based on
the condition of the cpsr bits from GE[0] to GE[3]. Each byte is taken from the
corresponding byte of Rn if the GE flag is true, or Rm if it is false.
int __SEL16(int Rn, int Rm);
The top and bottom halfwords of the result are set conditionally based on the value
of the GE[3] and GE[1] bits of the cpsr. If GE[3] is true, the top halfword of
the result is equal to the top halfword of the first parameter, otherwise it is set to
the top halfword of the second parameter. The bottom halfword of the result is
similarly taken from either the first or second parameter, based on the GE[1] bit.
signed int __SSAT(__ghs_c_int__ saturate, signed int Rm,
__ghs_c_int__ lslshift);
unsigned int __USAT(__ghs_c_int__ saturate, unsigned int Rm,
__ghs_c_int__ lslshift);
These functions perform a signed or unsigned saturation at the bit position
specified by the immediate saturate.
An immediate logical shift left, lslshift, may be applied to Rm before saturation.
Synchronization Primitives
int __LDREX(int *Rn);
Generates the ldrex load exclusive synchronization instruction for the address
in Rn, which attempts to mark the address for exclusive access by the current
processor, and return the result.
int __STREX(int Rm, int Rn);
Generates the strex store exclusive synchronization instruction, and attempts to
store the value in Rm to the address Rn. Returns 0 on success or 1 otherwise.
Endianness Intrinsics
int __REV(int Rm);
Reverses the bytes in a 32 bit value, using the REV instruction.
This function is available in Thumb mode.
int __REV16(int Rm);
Reverses the bytes in both the upper and lower 16 bits, using the REV16
instruction.
This function is available in Thumb mode.
void __SETEND_BE(void);
void __SETEND_LE(void);
This chapter describes the standard language libraries provided with the Green
Hills tools for ARM. Libraries are files which contain collections of object files.
Header files provide declarations and macros that may be used while
programming. Many of the functions in the standard libraries are declared in
header files. In C and C++, header files are referenced in the source code by
using a #include directive, which is read by the compiler’s preprocessor.
Note Your Green Hills compiler license permits you to make unlimited
distributions of programs linked with the Green Hills library object code
without charge. However, distribution of any Green Hills library source code or
object code is not permitted.
• include/arm: Contains header files for ARM extensions for C and C++.
• ansi: Contains Standard C library header files.
• scxx: Contains Standard C++ library header files.
• eecxx: Contains Extended Embedded C++ library header files.
• ecxx: Contains Embedded C++ library header files.
Library Directories
Depending upon the target architecture which you specify, the driver searches
one of the following directories (inside install_dir/lib) for libraries to resolve
references in the header files. Each directory contains a library set optimized
for use with a specific type of target CPU in the ARM processor family.
Libraries
Each library directory contains a version of the following set of libraries, built
for the particular target architecture:
• C Library:
libansi.a: Standard ANSI C library. This is the first library the linker
searches by default when you use the C driver, ccarm.
• C++ Libraries (see also “Choosing a C++ Library” on page 553):
By default, the linker searches libraries of the same type as the specified
language variant that do not support exceptions. You can override these defaults
by specifying an alternative library type as follows:
Libraries
C/C++ Compiler→C++ Libraries Setting Standard Run-time
Standard C++ Library without Exceptions libscnoe.a libsedgnoe.a
(--stdl)
Standard C++ Library with Exceptions (--stdle) libsce.a libsedge.a
Extended Embedded C++ Library without libeecnoe.a libedgnoe.a
Exceptions (--eel)
Extended Embedded C++ Library with libeece.a libedge.a
Exceptions (--eele)
Embedded C++ Library without Exceptions libecnoe.a libedgnoe.a
(--el)
Embedded C++ Library with Exceptions (--ele) libece.a libedge.a
Note You can only specify a different library if it is less full-featured than your
chosen language variant (and therefore appears below your default library in
the table). Thus you can write code in C++ while restricting your use of library
modules to those offered in EEC++, but not vice versa. For more information
about the differences between C++, EEC++, and EC++, see Chapter 14, “Green
Hills C++”.
When you specify a particular target to build for, or pass other options, the
compiler may change its search paths, and select additional libraries to link
against. For example:
cxarm --eel -G -fnone -bsp=at91eb01 test.cxx
• Search for header files in the directories include/arm, ansi, and eecxx
(because of the option --eel which specifies extended embedded C++).
• Search for libraries in the arm4 directory (because of the option
-bsp=at91eb01, which specifies the Atmel 91EB01 board, containing a
ARM 7TM processor).
• Open the following libraries for linking against in this order:
libmulti.a (because of the -G option)
libeecnoe.a (because of the --eel option)
libedgnoe.a (because of the --eel option)
libnoflt.a (because of the -fnone option)
libansi.a, libind.a, libstartup.a, libsys.a, and libarch.a (default lower
level libraries).
Note For information about specifying your own libraries and headers to search
for, see “Using Your Own Header Files and Libraries” on page 96.
During a single call, any characters written to one of these functions is buffered.
One function call often requires only one output system call. Once the function
completes, all characters are written to the file. No characters are left in a buffer
after the function call, eliminating both the risk of output loss and the need to
flush buffers when a file is closed or the program exits. No input routines are
buffered by the Less Buffered I/O method. Files are not closed upon program
termination, except as noted below.
You can enable full buffering of any file by calling either setbuf() or
setvbuf(). In this case, characters are only written to a buffered file when
the buffer is full or when fflush() or fclose() is called. Upon normal
termination of the program, if setbuf() or setvbuf() has been called at
any time, all open files will be flushed and then closed.
All files are processed in exactly the same manner, whether they are opened by
default (stdin, stdout, and stderr) or by fopen().
You can disable full buffering in favor of less-buffered I/O (with a possible
decline in performance), by calling pubsetbuf(), setbuf(), or
setvbuf() before calling stdio functions. For example:
cout.rdbuf()->pubsetbuf(0,0);
cout << "Hello" << endl;
printf("Hello\n");
or:
setbuf(stdout, NULL);
cout << "Hello" << endl;
printf("Hello\n");
Division by Zero
Integral divide and modulus operators are implemented in software with Green
Hills library functions. When an illegal division by zero occurs, different
applications will have different requirements for handling it. The division
routines respond to division by zero by calling off to a weak function, int
__division_by_zero(), which is not defined in the libraries. By default,
if this routine is not defined, the division routines will silently ignore division
by zero and return a result of zero. If a program defines this function, it can
specify whatever behavior is desired.
However, when the ’l’ modifier is repeated, an argument of type long long
is indicated. For example:
printf("very large number: %lld", 0x7fffffffffffffffL);
All Green Hills functions can be made thread-safe if a few simple functions
are incorporated into the threading environment. The file libsys/ind_thrd.c
provides stubs for the necessary functions that must be implemented in order to
make the Green Hills libraries thread-safe.
Functions that perform I/O are another concern to thread safety. If multiple
functions are writing data to a file simultaneously, that data may be corrupted.
Similarly, if a function is reading a file while another function is writing to
it, the file may get bad data. You must also implement the file lock/unlock
mechanism to ensure that I/O functions are thread-safe. If desired, the file
locks may be implemented with calls to the general __ghsLock() and
__ghsUnlock() routines.
For applications that have demanding I/O restrictions, you may consider
substituting the quicker, non-thread-safe getc_unlocked for getc, and
putc_unlocked for putc.
In addition, the following functions, which may be used to save and restore
arbitrary state across setjmp() and longjmp() calls, may be implemented:
int __ghs_SaveSignalContext(jmp_buf jmpbuf)
void __ghs_RestoreSignalContext(jmp_buf jmpbuf)
Source code is provided for some low-level routines in the libsys and libstartup
directories, so you can tailor the Green Hills libraries for your particular
environment. When modified, these functions must remain thread-safe so that
functions in the Green Hills libraries that call them also remain thread-safe.
The following code letters identify the level of thread-safety of the library
functions listed in the remainder of this chapter.
Y Completely thread-safe.
P Partially thread-safe. A lock must be implemented for complete thread safety.
I Performs I/O or modifies I/O data structures. This is a special case of a
partially thread-safe function.
T Achieves thread safety by thread local storage, so long as thread
local storage is implemented. See the preceding discussion on
GetThreadLocalStorage().
E Writes to the global variable errno. See above.
N Not thread-safe.
In addition, several libsys.a I/O functions are available as system calls when you
are connected to your target with the MULTI Debugger. For more information,
see “libsys.a Functions Provided through MULTI System Calls” on page 576.
The following tables list the data structures and functions in libansi.a. See
also “libind.a Functions” on page 577.
Variable Declaration
_CTYPE unsigned char _CTYPE[]
sys_errlist char *sys_errlist[]
_tolower_ short _tolower_[]
_toupper_ short _toupper_[]
Thread
Function safe? Arguments/return value
abort() Y void abort(void)
Depends On: raise()
abs() Y int abs(int x)
asctime() T char *asctime(const struct tm *t)
Depends On: __gh_timezone()
asctime_r() Y asctime_r(const struct tm *t, char
*buffer)
Depends On: __gh_timezone()
Thread
Function safe? Arguments/return value
_assert() IE void _assert(const char *problem, const
char *filename, int line)
Depends On: lseek(), raise(), write()
assert() IE void assert(int value)
Depends On: lseek(), raise(), write()
atexit() P int atexit(void (*func)(void))
atof() E double atof(const char *str)
atoi() E int atoi(const char *str)
atol() E long atol(const char *str)
atoll() E long long atoll(const char *str)
bcmp() Y bcmp(char *b1, char *b2, int length)
bcopy() Y bcopy(char *from, char *to, int n)
bsearch() Y void *bsearch(const void *key, const
void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void
*))
bufcpy() Y bufcpy(char *to, char *from, int n)
btowc() Y wint_t btowc(int c)
bzero() Y bzero(char *pt, int n)
calloc() P void *calloc(size_t num, size_t size)
Depends On: sbrk()
cfree() P void cfree(char *item)
Depends On: sbrk()
clearerr() I void clearerr(FILE *file)
clearn() Y void clearn(int n, char *pt)
clock() Y clock_t clock(void)
Depends On: times()
ctime() T char *ctime(const time_t *timer)
Depends On: __gh_timezone(), localtime()
ctime_r() T char *ctime_r(const time_t *timer, char
*buffer)
Depends On: __gh_timezone(), localtime()
Thread
Function safe? Arguments/return value
difftime() Y double difftime(time_t time1, time_t
time0)
div() Y div_t div(int number, int denom)
__docvt() Y internal use only
_doprnt() I int _doprnt(const char *format, va_list
args, FILE *stream)
Depends On: lseek(), write()
_doscan() I _doscan(const char *format, va_list
args, FILE *stream)
Depends On: close(), lseek(), read(),
sbrk(), write()
ecvt() N char *ecvt(double value, int ndig, int
*decpt, int *sign)
eprintf() IE int eprintf(const char *format, ...)
Depends On: lseek(), write()
execl() Y int execl(const char *name, const char
*args, ...)
Depends On: environ(), execve()
execle() Y int execle(const char *name, const char
*args, ...)
Depends On: execve()
execv() Y int execv(const char *name, char *const
*argv)
Depends On: environ(), execve()
exit() P void exit(int val)
Depends On: _exit()
fclose() IE int fclose(FILE *file)
Depends On: close(), lseek(), write()
fcvt() N char *fcvt(double value, int ndig, int
*decpt, int *sign)
fdopen() IE FILE *fdopen(int fno,const char *mode)
Depends On: close(), creat(), lseek(),
open(), write()
feof() Y int feof(FILE *stream)
Thread
Function safe? Arguments/return value
ferror() Y int ferror(FILE *stream)
fflush() IE int fflush(FILE *file)
Depends On: lseek(), write()
ffs() Y int ffs(int i)
fgetc() IE int fgetc(FILE *file)
Depends On: read()
fgetwc() IE wint_t fgetwc(FILE *file)
Depends On: read()
fgetwc_ NE wint_t fgetwc_unlocked(FILE *file)
unlocked()
Depends On: read()
fgetpos() IE int fgetpos(FILE *file,fpos_t *pos)
Depends On: lseek()
fgets() IE char *fgets(char *str, int n, FILE
*file)
Depends On: read()
fgetws() IE wchar_t *fgetws(wchar_t *str, int n,
FILE *file)
Depends On: read()
_filbuf() IE _filbuf(FILE *file)
Depends On: read()
filln() Y void filln(int n, char *pt, int fill)
_flsbuf() IE _flsbuf(int ch, FILE *file)
Depends On: lseek(), write()
fopen() IE FILE *fopen(const char *name, const char
*mode)
Depends On: close(), creat(), lseek(),
open(), write()
fprintf() IE int fprintf(FILE *stream, const char
*format, ...)
Depends On: lseek(), write()
Thread
Function safe? Arguments/return value
fwprintf() IE int fwprintf(FILE *stream, const wchar_t
*format, ...)
Depends On: lseek(), write()
fputc() IE int fputc(int ch,FILE *file)
Depends On: lseek(), write()
fputs() IE int fputs(const char *str,FILE *file)
Depends On: lseek(), write()
fputws() IE int fputws(const wchar_t *str,FILE
*file)
Depends On: lseek(), write()
fputwc() IE wint_t fputwc(wchar_t ch,FILE *file)
Depends On: lseek(), write()
fputwc_ NE wint_t fputwc_unlocked(wchar_t ch,FILE
unlocked() *file)
Depends On: lseek(), write()
fread() IE size_t fread(void *ptr,size_t
size,size_t nitems,FILE *file)
Depends On: read()
free() P void free(void *ptr)
Depends On: sbrk()
freopen() IE FILE *freopen(const char *name, const
char *mode, FILE *file)
Depends On: close(), creat(), lseek(),
open(), write()
frexp() Y double frexp(double value, int *eptr)
frexpf() Y float frexpf(float value, int *eptr)
fscanf() IE int fscanf(FILE *stream, const char
*format, ...)
Depends On: close(), lseek(), read(),
sbrk(), write()
fseek() IE int fseek(FILE *stream, long int offset,
int ptrname)
Depends On: lseek(), write()
Thread
Function safe? Arguments/return value
fsetpos() IE int fsetpos(FILE *file,const fpos_t
*pos)
Depends On: lseek(), write()
ftell() IE long ftell(FILE *stream)
Depends On: lseek()
fwrite() IE size_t fwrite(const void *ptr,size_t
size,size_t nitems, FILE *file)
Depends On: lseek(), write()
fwide() Y int fwide(FILE *stream, int orientation)
fwscanf() IE int fwscanf(FILE *stream, const wchar_t
*format, ...)
gcvt() N char *gcvt(double value, int ndig, char
*buf)
getc() IE int getc(FILE *f)
Depends On: read()
getc_ N int getc_unlocked(FILE *f)
unlocked()
Depends On: read()
getchar() IE int getchar(void)
Depends On: read()
getchar_ I int getchar_unlocked(void)
unlocked()
Depends On: read()
getenv() Y char *getenv(char *np)
Depends On: environ()
getl() IE long getl(FILE *file)
Depends On: read()
gets() IE char *gets(char *str)
Depends On: read()
getw() IE int getw(FILE *file)
Depends On: read()
getwchar() IE wint_t getwchar(FILE *file)
Depends On: read()
Thread
Function safe? Arguments/return value
index() Y char *index(const char *str, const char
ch)
isalnum() Y int isalnum(int c)
isascii() Y int isascii(int c)
isalpha() Y int isalpha(int c)
iscntrl() Y int iscntrl(int c)
isdigit() Y int isdigit(int c)
isgraph() Y int isgraph(int c)
islower() Y int islower(int c)
isprint() Y int isprint(int c)
ispunct() Y int ispunct(int c)
isspace() Y int isspace(int c)
isupper() Y int isupper(int c)
iswalnum() Y int iswalnum(wint_t wc)
iswalpha() Y int iswalpha(wint_t wc)
iswblank() Y int iswblank(wint_t wc)
iswcntr() Y int iswcntrl(wint_t wc)
iswctype() Y int iswctype(wint_t wc, wctype_t index)
iswdigit() Y int iswdigit(wint_t wc)
iswgraph() Y int iswgraph(wint_t wc)
iswlower() Y int iswlower(wint_t wc)
iswprint() Y int iswprint(wint_t wc)
iswpunct() Y int iswpunct(wint_t wc)
iswspace() Y int iswspace(wint_t wc)
iswupper() Y int iswupper(wint_t wc)
iswxdigit() Y int iswxdigit(wint_t wc)
isxdigit() Y int isxdigit(int c)
labs() Y long labs(long x)
ldexp() E double ldexp(double value, int exp)
ldexpf() E float ldexpf(float value, int exp)
ldiv() Y ldiv_t ldiv(long int number, long int
denom)
Thread
Function safe? Arguments/return value
llabs() Y long long llabs(long long x)
lldiv() Y lldiv_t lldiv(long long numer, long long
denom)
localeconv() Y struct lconv *localeconv(void)
longjmp() Y void longjmp (jmp_buf env, int val)
malloc() P void *malloc(size_t size)
Depends On: sbrk()
mblen() Y int mblen(const char *s, size_t n)
mbrlen() Y size_t mbrlen(const char *s, size_t n,
mbstate_t *ps)
mbrtowc() Y size_t mbrtowc(wchar_t *pwc,const char
*s, size_t n, mbstate_t *ps)
mbsinit() Y int mbsinit(const mbstate_t *ps)
mbsrtowcs() Y size_t mbsrtowcs(wchar_t *wcs, const
char **pmbs, size_t n, mbstate_t *ps)
mbstowcs() Y size_t mbstowcs( wchar_t *pwcs, const
char *mbs, size_t n)
mbtowc() Y int mbtowc(wchar_t *pwc, const char *s,
size_t n)
memchr() Y void *memchr(const void *s, int c,
size_t n)
memcmp() Y int memcmp(const void *s1, const void
*s2, size_t length)
memmove() Y void *memmove(void *s1, const void *s2,
size_t n)
mktemp() P char *mktemp(char *str)
Depends On: getpid()
mktime() Y time_t mktime(struct tm *timeptr)
Depends On: __gh_timezone(), localtime(),
localtime_r()
modf() Y double modf(double value, double *iptr)
on_exit() P int on_exit( void (*func)(void), char *
arg)
Thread
Function safe? Arguments/return value
perror() IE void perror(const char *str)
Depends On: lseek(), write()
printf() IE int printf(const char *format, ...)
Depends On: lseek(), write()
putc() IE int putc(int ch, FILE *f)
Depends On: lseek(), write()
putc_ N int putc_unlocked(int ch, FILE *f)
unlocked()
Depends On: lseek(), write()
putchar() IE int putchar(int ch)
Depends On: lseek(), write()
putchar_ N int putchar_unlocked(int ch)
unlocked()
Depends On: lseek(), write()
putl() IE long putl(long l, FILE *file)
Depends On: lseek(), write()
puts() IE int puts(const char *str)
Depends On: lseek(), write()
putw() IE putw(int w, FILE *file)
Depends On: lseek(), write()
putwc() IE wint_t putwc(wchar_t wc, FILE *f)
Depends On: lseek(), write()
putwchar() IE wint_t putwchar(wchar_t wc)
Depends On: lseek(), write()
qsort() Y void qsort(void *base, size_t nmemb,
size_t size, int (*compar)(const void *,
const void *))
rand() P int rand()
rand_r() Y int rand_r(long * seedSent)
realloc() P void *realloc(void *old, size_t
new_size)
Depends On: sbrk()
remove() Y int remove(const char *filename)
Depends On: unlink()
Thread
Function safe? Arguments/return value
rewind() IE void rewind(FILE *stream)
Depends On: lseek(), write()
rindex() Y char *rindex(const char *str, const char
ch)
scanf() IE scanf(const char *format, ...)
Depends On: close(), lseek(), read(),
sbrk(), write()
setbuf() IE void setbuf(FILE *stream, char *buf)
Depends On: close(), lseek(), write()
setjmp() Y int setjmp (jmp_buf env)
setlinebuf() Y int setlinebuf(FILE *stream)
setlocale() Y char *setlocale(int category, const char
*locale)
setvbuf() IE int setvbuf(FILE *stream, char *buf, int
mode, size_t size )
Depends On: close(), lseek(), write()
snprintf() E int snprintf(char *s, size_t size, cosnt
char *format, ...)
sprintf() E int sprintf(char *s, const char *format,
...)
srand() N void srand(int val)
sscanf() Y int sscanf(const char *str, const char
*format, ...)
strcat() Y char *strcat(char *s2, const char *str1)
strchr() Y char *strchr(const char *str, int ch)
strcmp() Y int strcmp(const char *str1, const char
*str2)
strcoll() Y int strcoll(const char *s1, const char
*s2)
strcpy() Y char *strcpy(char *s2, const char *str1)
strcspn() Y size_t strcspn(const char *s1, const
char *s2)
strerror() Y char *strerror(int errnum)
Thread
Function safe? Arguments/return value
strftime() Y size_t strftime(char *start, size_t
maxsize, const char *format, const
struct tm *timeptr)
Depends On: __gh_timezone()
strindex() Y int strindex(char *str, char *sub)
strlen() Y size_t strlen(const char *str)
strncat() Y char *strncat(char *s2, const char
*str1, int n)
strncmp() Y int strncmp(const char *str1, const char
*str2, int n)
strncpy() Y char *strncpy(char *s2, char *str1, int
n)
strpbrk() Y char *strpbrk(const char *s1, const char
*s2)
strrchr() Y char *strrchr(const char *str, int ch)
strrindex() Y int strrindex(char *str, char *sub)
strsave() P char *strsave(char *str)
Depends On: sbrk()
strspn() Y size_t strspn(const char *s1, const char
*s2)
strstr() Y char *strstr(const char *str, const char
*sub)
strtod() E double strtod(const char *str, char
**endptr)
strtok() T char *strtok(char *s1, const char *s2)
strtok_r() Y char *strtok_r(char *s1, const char *s2,
char **ppLast)
strtol() E long strtol(const char *str, char **ptr,
int base)
strtoll() E long long strtoll(const char *str, char
**ptr, int base)
strtoul() E unsigned long strtoul(const char *str,
char **ptr, int base)
strtoull() E unsigned long long strtoull(const char
*str, char **ptr, int base)
Thread
Function safe? Arguments/return value
strxfrm() Y size_t strxfrm(char *s1, const char *s2,
size_t n)
swab() Y swab(char *from, char *to, int nbytes)
swprintf() E int swprintf(wchar_t *s, size_t n, const
wchar_t *format, ...)
swscanf() Y int sscanf(const wchar_t*str, const
wchar_t *format, ...)
tmpfile() IE FILE *tmpfile(void)
Depends On: access(), close(), creat(),
lseek(), open(), unlink(), write()
tmpnam() TPE char *tmpnam(char *s)
Depends On: access()
tmpnam_r() PE char *tmpnam_r(char *s)
Depends On: access()
tolower() Y int tolower(int c)
toupper() Y int toupper(int c)
towctrans() Y wint_t towctrans(wint_t wc, wctrans_t
desc)
towlower() Y wint_t towlower(wint_t wc)
towupper() Y wint_t towupper(wint_t wc)
ungetc() IE int ungetc(int ch,FILE *file)
Depends On: close(), lseek(), sbrk(),
write()
ungetwc() IE wint_t ungetwc(wint_t wc, FILE *f)
Depends On: close(), lseek(), sbrk(),
write()
ungetwc_ NE wint_t ungetwc_unlocked(wint_t wc, FILE
unlocked() *f)
Depends On: close(), lseek(), sbrk(),
write()
vfprintf() IE int vfprintf(FILE *stream, const char
*format, va_list args)
Depends On: lseek(), write()
Thread
Function safe? Arguments/return value
vfscanf() IE vfscanf(FILE *stream, const char
*format, va_list args)
Depends On: close(), lseek(), read(),
sbrk(), write()
vfwscanf() IE vfwscanf(FILE *stream, const wchar_t
*format, va_list args)
Depends On: close(), lseek(), read(),
sbrk(), write()
vfwprintf() IE int vfwprintf(FILE *stream, const
wchar_t *format, va_list args)
Depends On: lseek(), write()
vprintf() IE int vprintf(const char *format, va_list
args )
Depends On: lseek(), write()
vscanf() IE vscanf(const char *format, va_list ap )
Depends On: close(), lseek(), read(),
sbrk(), write()
vsnprintf() Y int vsnprintf(char *s, size_t size,
const char *format, va_list ap)
vsprintf() E int vsprintf(char *s, const char
*format, va_list ap)
vsscanf() Y vsscanf(const char *str, const char
*format, va_list ap)
vswprintf() E int vswprintf(wchar_t *s, const wchar_t
*format, va_list ap)
vswscanf() P int vswscanf(const wchar_t *str, const
wchar_t *format, va_list args)
vwprintf() IE int vwprintf(const wchar_t *format,
va_list args)
Depends On: lseek(), write()
vwscanf() IE int vwscanf(const wchar_t *format,
va_list args)
Depends On: close(), lseek(), read(),
sbrk(), write()
wcrtomb() Y size_t wcrtomb(char *s, wchar_t wc,
mbstate_t *ps)
Thread
Function safe? Arguments/return value
wcscat() Y wchar_t *wcscat(wchar_t *s2, const
wchar_t *str1)
wcschr() Y wchar_t *wcschr(const wchar_t *str,
wchar_t ch)
wcscmp() Y int wcscmp(const wchar_t *str1, const
wchar_t *str2)
wcscoll() Y int wcscoll(const wchar_t *str1, const
wchar_t *str2)
wcscoll() Y int wcscoll(const wchar_t *str1, const
wchar_t *str2)
wcscpy() Y whcar_t *wcscpy(wchar_t *s2, const
wchar_t *str1)
wcscspn() Y size_t wcscspn(const wchar_t *s1, const
wchar_t *s2)
wcscspn() Y size_t wcscspn(const wchar_t *s1, const
wchar_t *s2)
wcsftime() Y size_t wcsftime(wchar_t *start, size_t
maxsize, const wchar_t *format, const
struct tm *timeptr)
Depends On: __gh_timezone()
wcslen() Y size_t wcslen(const wchar_t *str)
wcsncat() Y wchar_t *wcsncat(wchar_t *s2, const
wchar_t *str1, size_t n)
wcsncmp() Y int wcsncmp(const wchar_t *str1, const
wchar_t *str2, size_t n)
wcsncpy() Y wchar_t *wcsncpy(wchar_t *s2, const
wchar_t *str1, size_t n)
wcspbrk() Y wchar_t *wcspbrk(const wchar_t *s1,
const wchar_t *s2)
wcsrchr() Y wchar_t *wcsrchr(const wchar_t *str,
wchar_t wc)
wcsrtombs() Y size_t wcsrtombs(char *mbs, const
wchar_t **pwcs, size_t n, mbstate_t *
ps)
wcsspn() Y size_t wcsspn(const wchar_t *s1, const
wchar_t *s2)
Thread
Function safe? Arguments/return value
wcsstr() Y wchar_t *wcsstr(const wchar_t *str,
const wchar_t *sub)
wcstod() Y double strtod(const wchar_t *str,
wchar_t **endptr)
wcstof() Y float strtof(const wchar_t *str, wchar_t
**endptr)
wcstok() Y wchar_t wcstok(wchar_t *s1, const
wchar_t *s2, wchar_t **ppLast)
wcstol() Y long strtol(const wchar_t *str, wchar_t
**ptr, int base)
wcstoll() Y long long strtol(const wchar_t *str,
wchar_t **ptr, int base)
wcstoul() Y unsigned long strtoul(const wchar_t
*str, wchar_t **ptr, int base)
wcstoull() Y unsigned long long strtoull(const
wchar_t *str, wchar_t **ptr, int base)
wcsxfrm() Y size_t wcsxfrm(wchar_t *s1, const
wchar_t *s2, size_t n)
wctob() Y int wctob(wint_t wc)
wctomb() Y int wctomb(char *s, wchar_t wchar)
wctrans() Y wctrans_t wctrans(const char *name)
wctype() Y wctype_t wctype(const char *name)
wmemchr() Y wchar_t *wmemchr(const wchar_t *s,
wchar_t wc, size_t n)
wmemcmp() Y int wmemcmp(const wchar_t *s1, const
wchar_t *s2, size_t length)
wmemcpy() Y wchar_t *wmemcpy(wchar_t *dest, const
wchar_t *src, size_t n)
wmemmove() Y wchar_t *wmemmove(wchar_t *s1, const
wchar_t *s2, size_t n)
wmemset() Y wchar_t *wmemset(wchar_t *s, wchar_t c,
size_t n)
Thread
Function safe? Arguments/return value
wprintf() EI int wprintf(const wchar_t *format, ...)
wscanf() EI int wscanf(const wchar_t *format, ...)
Depends On: close(), lseek(), read(),
sbrk(), write()
Note If you are working in a stand-alone environment, then you must provide
target-specific edits to these libsys.a functions if you want to use functions
in libansi.a that depend upon them.
libind.a Functions
The libind.a library contains mathematical functions such as sqrt and sin,
which are listed in the following table:
Thread
Function safe? Arguments/return value
acos() E double acos(double x)
acosf() E float acosf(float arg)
acosh() E double acosh(double x)
asin() E double asin(double x)
asinf() E float asinf(float arg)
asinh() E double asinh(double x)
atan() E double atan(double x)
atan2() E double atan2(double y, double x)
atan2f() E float atan2f(float y, float x)
atanf() E float atanf(float x)
atanh() E double atanh(double x)
cabs() E double cabs(struct complex z)
ceil() Y double ceil(double x)
cos() Y double cos(double f0)
cosf() Y float cosf(float f0)
cosh() E double cosh(double x)
coshf() E float coshf(float x)
erf() Y double erf(double x)
erfc() Y double erfc(double x)
exp() E double exp(double x)
expf() E float expf(float x)
fabs() Y double fabs(double x)
floor() Y double floor(double x)
fmod() Y double fmod(double x,double y)
gamma() E double gamma(double x)
_gh_va_arg() Y char *_gh_va_arg(p, align, regtyp, size)
hypot() E double hypot(double x,double y)
Thread
Function safe? Arguments/return value
isinf() Y int isinf(double x)
isnan() Y int isnan(double x)
j0() E double j0(double x)
j1() E double j1(double x)
jn() E double jn(int n,double x)
log() E double log(double x)
log10() E double log10(double x)
log10f() E float log10f(float x)
logf() E float logf(float x)
matherr() Y int matherr(struct exception *ex)
memcpy() Y void *memcpy(void *s1, const void *s2,
size_t n)
memset() Y void *memset(void *s, int c, size_t n)
pow() E double pow(double x, double y)
powf() E float powf(float x, float y)
rmatherr() Y int rmatherr(struct rexception *ex)
__rnerr() P int __rnerr(int num, int linenum, char
*str, void *ptr, void *al, void *a2,
void *a3, void *a4, void *a5, size_t
len)
sin() Y double sin(double f0)
sinf() Y float sinf(float f0)
sinh() E double sinh(double x)
sinhf() E float sinhf(float arg)
sqrt() E double sqrt(double f0)
sqrtf() E float sqrtf(float f0)
tan() E double tan(double x)
tanf() E float tanf(float arg)
tanh() E double tanh(double x)
tanhf() E float tanhf(float x)
y0() E double y0(double x)
Thread
Function safe? Arguments/return value
y1() E double y1(double x)
yn() E double yn(int n, double x)
• crt0.o — the default startup module (see “Startup Module crt0.o” on page
581)
• libstartup.a — the startup library (see “Low-Level Startup Library
libstartup.a” on page 583)
• libsys.a — the system library (see “Low-Level System Library libsys.a”
on page 584)
Many users will be able to use the Green Hills run-time environment without
alteration. However, you may need to customize some of these underlying
routines for your particular environment. The full source files are provided in
the libstartup and libsys directories in install_dir/arm/src. To prepare a project
in which customization can be performed:
1. Click the button to create a new project with the New Project Wizard,
and select settings appropriate to your project until you reach the Link
Options screen.
2. On the Link Options screen, set the Startup Library and/or the System
Library option to “Customize” (see also “Setting Link Options” on page
26).
When you create a project in this way, the New Project Wizard creates a
subproject called startupcode inside your top-level project file, which in
turn contains the subprojects libsys.gpj, libstartup.gpj, and crt0.gpj. These
subprojects contain editable copies of the source to the Green Hills run-time
modules, which you can customize as necessary and rebuild either separately,
or as part of your project.
Note For more information about building and setting build options, see
Chapter 2, “The MULTI Builder”. Options should be changed with care, as
some of them are required for proper operation. For example, the default.gpj
project causes the preprocessor symbol EMBEDDED to be defined when
compiling; this symbol is required for some modules in the libraries.
If you are working with the compiler driver and makefiles, then you should
still create a new project with the New Project Wizard, as described above.
When the files have been created, then edit them as appropriate, and use your
makefile to link to them as usual.
crt0.arm
crt0.arm is the sole source file for the startup module crt0.o. It is a small
target-specific assembly language file and contains only a minimal amount of
code, required to set up a C program environment before calling into a high-level
language C function. This code is located in the function _start(), the
default entry point for programs in the Green Hills environment. On program
startup, an initial system call determines whether a Green Hills debug agent
(or debug server) is controlling execution of the program (as opposed to the
program running stand-alone, without being connected to a debug server). If the
system call is successful, some required register initialization is assumed to have
been accomplished by the debug server; otherwise the code in crt0.arm may do
more initialization. The source code in crt0.arm should be consulted since the
actual register manipulation varies widely across different architectures.
The .stack section is an improved method for specifying the location of the
run-time stack. You can place a .stack section into the linker directives file
to specify the location and size of the run-time stack. The Green Hills startup
code sets up the stack pointer to point to the end of this section if the stack
grows downward, or to the start if the stack grows upward. You can change the
location or size of the stack by changing the linker directives file.
Debug servers automatically detect the existence of the .stack section and
automatically initialize the stack pointer. For example:
.heap align(16) pad(0x100000) :
.stack align (16) pad(0x80000):
This specifies that the stack starts on the first 16-byte aligned address following
the .heap section in memory. The stack is configured to be 0x80000 bytes
in size. The other benefit of using .stack to specify the stack configuration
is that stack checking code is easily built into a program. Such code need
only compare the current value of the stack pointer register with the value
of __ghsbegin_stack or __ghsend_stack (depending on whether
the stack grows down or up) to determine whether the available stack area
is exhausted.
ind_crt0.c
This module contains machine-independent startup code. In particular,
ind_crt0.c clears the uninitialized data sections, such as .bss, and copies
initialized data sections from their locations in ROM to their final locations in
RAM. Whether or not a program requires this ROM to RAM copy depends on
the linker directives file for that program. You do not have to write code to
clear or copy sections at startup; ind_crt0.c does it automatically. If you want
to do this initialization without the aid of the Green Hills library, customize
ind_crt0.c and rebuild libstartup.a.
If your program uses PIC and/or PID, the ind_crt0.c code will relocate
initialized pointers to any position independent object. For example, consider
the following C code:
extern int foo();
int (*ptr)() = &foo;
This declares a global function pointer that is initialized to the address of the
function foo(). Since the location of foo() is not known until run time,
the compiler emits a small amount of data that describes each such relocated
initialization in the program. For example, when compiling for PIC, the
compiler generates data to inform ind_crt0.c that the initializer of the variable
ptr requires a run-time modification specifying the run-time location of the
program’s code, as desired. After ind_crt0.c finishes, all initialized pointers
contain valid run-time addresses.
ind_bcpy.c
This module is implemented for some targets that require special code to
initialize parts of their memory system.
ind_mcpy.c, ind_mset.c
These modules contain the C run-time library functions memcpy() and
memset(), which are used during initialization to copy and clear data sections.
You can modify these routines if desired.
ind_reset.c
These modules contain low-level initialization routines. They may require
modifications to boot up on bare boards that do not have other means for
initialization.
ind_alloc.c
This module returns a piece of memory of the given type and alignment from
the heap. This relies on ind_heap.c to actually get the memory, but since
sbrk() does not give alignment guarantees, this is used as a front end.
ind_call.arm, ind_dots.arm
These modules contain target-specific language and handle lowest-level system
call capability. The routine __ghs_syscall() is called from various
system call routines, such as open(), close(), read(), and write().
The __ghs_syscall() routine transfers control to the start address of the
.syscall section.
Debug servers or monitors can key in this address to accomplish the emulation
of system calls in the Green Hills environment. For example, many debug
servers set a special breakpoint on this address. Then, when the breakpoint
is encountered during execution, the debug server knows that a system call
occurred. The arguments are then retrieved and the system call is emulated on
the host by the debug server.
ind_crt1.c
This module contains the first C function called by the standard libraries after
memory and static and global data have been initialized. It initializes the ANSI
C and other run-time libraries before jumping to the application entry point
(main).
ind_errn.c
This module handles reads and writes to errno in a thread safe manner. See
also ind_thrd.c.
ind_gpid.c
This module returns the current process number. This is used in mktemp() to
add uniqueness to the generated filenames.
ind_targ1.c
This is a hanger for user-customizable target specific functions.
ind_thrd.c
This module implements the locking mechanism needed for thread-safe
libraries. Also see ind_errn.c.
ind_heap.c
This module contains the dynamic memory allocation routines and, in particular,
the system call routine, sbrk(). The .heap section in the linker directives
file specifies the location, size, alignment, and initialization, if any, of the heap.
For example:
.heap align(16) pad(0x100000) :
.stack align (16) pad(0x80000):
This specifies that the heap starts on the first 16-byte aligned address following
the previous section in memory and is 0x100000 bytes in size. The .stack
section then follows the heap area. The pad directive instructs the linker that
the heap is uninitialized on startup. This enables you to place the run-time heap
anywhere in memory; the run-time library automatically allocates memory
where you place this section.
In addition, the ability to hard code a size for the heap assures you that the
program does not use more heap memory than is desired or expected. Any
attempt to allocate memory at an address higher than that specified by the size
in the linker directive will cause sbrk() to fail and return an error value.
ind_io.c
This module contains system routines most likely needed for a UNIX-like
implementation, including:
int open(const char *filename, int mode, . . . );
int creat(const char *filename, int prot);
int close(int fno);
int read(int fno, void *buf, int size);
int write(int fno, const void *buf, int size);
int unlink(char *name);
These system calls enable the program to open, read, write, and close files.
Many of the Green Hills ind_io.c and related system call modules filter down
to calls to the generic system call interface routine __ghs_syscall(),
described in “ind_call.arm, ind_dots.arm” on page 584.
ind_iob.c
This module contains the default file buffer, _iob, used by the C library’s
stdio.h interface. The user may want to modify this to reduce or increase the
number of files that may be opened through this interface. The user may also
modify the default buffering by modifying __gh_iob_init().
ind_exit.c
This module contains the following routines:
Routine Description
_enter() Is called at startup and used as a separate routine to
initialize the I/O system, initialize caching options, etc.
_ghs_at_exit() Registers functions that need to be called upon
_exit() (similar to the ANSI atexit()).
_exit() Calls clean-up routines registered by the program via
__ghs_at_exit() or atexit() and allows the
program to terminate cleanly via an exit system call.
Mixing Languages
Green Hills compilers can combine C and C++ routines within the same
executable files, subject to certain constraints. This section provides some
basic information about using Green Hills compilers to create a mixed language
executable and describes how the compiler driver builds mixed language
executables. Additional language-specific details are provided in the subsequent
sections.
All Green Hills compiler drivers are compatible with each other. This permits a
C driver to compile a FORTRAN module, and a FORTRAN driver to compile
a C++ module. The driver uses the input filename extension to determine the
correct language, rather than assuming that the name of the driver determines
the source code language.
Though compatible during compilation, the various drivers differ during the
link phase. To link an application, the driver must determine all of the languages
in use in order to know which libraries to include. The driver assumes that
every application has modules written in C and assembly language, and that
there is at least one module written in the driver’s default language. If the
command line includes source files written in other languages (as indicated
by the file extension), then the driver recognizes that those languages exist in
the application as well.
Consequently, mixing any one language with C is easy because the driver always
assumes C is in use. To assure the correct linkage when mixing a language with
C, use the driver for the language other than C for linking the application.
Initialization of Libraries
A multiple language application may need to perform input and output in more
than one language. With a little care to avoid conflicts between languages,
this is fully supported. If input and output will always be performed on
different files by each language, then the main program in a single language
application automatically handles the initialization and deinitialization of each
language’s run-time routines. Therefore, if the application will only perform
I/O in one language other than C, then it is easy to write the main program
for the application in that language. For more complex requirements, write
a main program in C to perform the initialization and deinitialization of the
library run-time routines. Examples of main programs in C are given in the
next section.
All languages have full access to these pre-opened files, and input and output
can easily be mixed between the languages on these files. However, for the best
results, a complete input or output operation is done in a single language. In
C, any call to a library function which performs input or output is a complete
operation. If this rule is followed, all data will be output correctly and in the
intended sequence. The C library routine fflush() flushes the buffer of the
pre-opened files in all languages. In addition, to flush one of C++ iostreams,
use the notation file << flush. For example:
cout << flush
Performing input and output on a single file which is not preopened is more
difficult. It is possible to open the file once in each language and perform
input and output independently in each language. In many cases this would be
unacceptable, particularly when working with a device rather than a simple file.
To specify a C declaration:
extern "C" {
int fclose(FILE *);
FILE *fopen(const char *, const char *);
}
Here, all the function declarations that appear in <stdio.h> and <string.h>
are affected in the same manner as the two specific functions declared
individually in the previous example (fclose() and fopen()).
• If code contains both C and C++, then the extern constructs can be placed
within #ifdef __cplusplus statements. This practice is common
within header files. For example,
#ifdef __cplusplus
extern "C" {
#endif
void assert(int );
void _assert(const char *,const int,const char *);
#ifdef __cplusplus
}
#endif
C provides no support for any of the C++ extensions to the language. The C
programmer must manually perform some of the tasks that the C++ compiler
performs automatically. Some knowledge of the internal mechanics and details
of a C++ implementation is necessary, as follows:
• The C++ compiler encodes or mangles function and class member names.
Any C++ function or class members called from a C program must be
referenced by the encoded or mangled names.
• The manner in which a C++ compiler handles member functions must be
known. All member functions (except static member functions) have the
special object member pointer this inserted automatically as the first
argument in the parameter list. A C programmer must manually add the
argument this when calling any member functions from C.
• Handling constructors and destructors for static objects requires special
processing. On most systems, the main() function has special function
call to _main() inserted to insure that all static constructor/destructor
calls are made properly. If main() is not in a C++ module, then the C
programmer must manually include calls to _main() in the C main
module. The _main() code is contained in the C++ library and therefore
must be linked into the final executable.
• Virtual functions are also handled automatically by a C++ compiler, but
involve additional coding to access or use them from a C environment.
Function prototyping requires that the function declaration include the function
return type and the number and type of the arguments. When a prototype is
available for a function, the compiler is able to perform argument checking and
coercion on calls to that function. If a prototype is not available for a function
when it is called, ANSI C will behave like K&R C. The return type of the
function is assumed to be int, and actual arguments will be promoted to int,
long, or double types, or pointers as appropriate. In C++, however, it is an
error to call a function which has not been declared with a prototype.
char *function_name();
has no effect on the number and type of the arguments in ANSI C. In C++ it
is understood as:
char *function_name(void)
which means that the function has no arguments at all. If the function declaration
occurs within the scope of an extern "C" declaration, the function has
non-C++ linkage, and therefore cannot be overloaded. This means that if a
traditional K&R style declaration of a function appears in a header file, and the
#include directive which accesses that header file is enclosed in extern
"C" { }, then it will be impossible to redeclare that function with arguments.
The C/C++ language specifications define programs in such a way that portable
programs will always work with all appropriate language compilers, including
any Green Hills C/C++ compiler. However, difficulties arise when programmers
make non-portable assumptions about the machine or compiler that they are
using. As a result, a program may appear to compile and operate correctly when
compiled with one vendor’s compiler, but not with a Green Hills compiler.
For information about compatibility with Green Hills compilers for other
languages, see “Mixing Languages” on page 590.
Some machines are byte addressable, meaning that their addresses refer to
8-bit bytes. Typically, byte addressable machines operate on 8, 16, 32, 64, and
128-bit quantities. Other machines are word addressable, meaning that their
addresses refer to words of a standard size varying from 16 to 64 bits. Word
addressable machines typically operate on multiples of the word size.
A program that operates on a machine of one word size may not operate on a
machine of a different word size. Thus, word size incompatibility problems
may arise if two different machines have different word sizes, or if one machine
is word addressable and the other is byte addressable. The word size affects the
range of numbers implemented by integer data types, as well as the precision
and range of single and double precision floating-point data types.
The most common word size problems are integer and floating-point
underflows, overflows, and loss of precision. The layout of bit aligned data
structures will vary with the word size, so overlaying structures in memory
makes programs difficult to port to another compiler. Address arithmetic done
in integer variables is often not portable.
Another common non-portable assumption is that pointers are the same size
as int or long. Neither is guaranteed. With all 32-bit Green Hills C/C++
compilers, pointers are 32 bits. But with 64-bit Green Hills C/C++ compilers,
pointers may be either 32 or 64 bits, independent of the size of int or long.
In both languages, all integer constants have type int unless marked with a
type suffix. In certain cases, the use of a plain integer constant instead of a long
integer constant may be non-portable.
Endianness Problems
Programs that overlay characters and integers in memory or that use character
pointers to integer variables and vice versa are often not portable between
machines with different byte ordering.
Programs that declare a single variable with different integer types in different
modules may fail when ported to a machine with a different byte order.
Alignment Requirements
Some systems will not load or store a two byte object unless that object is on an
even address. Other systems have a similar requirement for four or eight byte
objects. Others may allow certain accesses, but require more time to perform
them. Therefore, alignment of data is both a matter of correctness and of time
The alignment requirements on each system are chosen both to satisfy the
restrictions of the hardware and to achieve a reasonable balance between
performance and space. The alignment rules are often not configurable and they
differ for each system. Thus, programs that make assumptions about the relative
position of data objects in memory or elements within classes, structures, or
arrays are not portable—even among the Green Hills C++ compilers.
The C/C++ languages impose the following restrictions on size and alignment:
If a program does not use integer arithmetic for pointer computations and
ensures that all general purpose memory allocation routines return maximally
aligned pointers, then all references to dynamically allocated memory will be
properly aligned.
Unions
A union allows the same memory location to be accessed as more than one type.
This is inherently non-portable. Suppose a union consists of an integer and an
array of four characters. Whether the first element of the array is the most or
least significant part of the integer depends on byte order. It is not even certain
that the integer and the array of characters have the same size.
The exact offset of each field from the base of the structure/class depends on
the size and alignment of the field itself and of those which precede it. The
offset of the first field is always 0 in C, but not necessarily in C++ (for instance
with multiple inheritance). Also, padding is inserted as necessary to satisfy the
alignment requirement of each subsequent field, and may also be added at the
end of the structure/class to make its overall size a multiple of its alignment.
Bitfields
The allocation of bitfields in a structure is dependent upon alignment rules.
Additionally, the exact layout of bits within a bitfield varies between systems
and cannot be assumed by a portable program.
Many modern C/C++ compilers pass some parameters in registers and may not
evaluate parameters from right to left. Integer and floating-point variables, not
to mention structures, may have different rules. One non-portable assumption is
that a double may be passed to a function which expects two integers. Not
only does this assume a relationship between the size of the two types and a
certain ordering of bytes and words, but it assumes that doubles and integers
follow all of the same rules. Both of these assumptions are erroneous.
Even among integral types, a program may assume that int and long are
interchangeable. A C program can invoke printf using the %d operator to
refer to a long parameter; however, this program will fail when ported to a
system where long is larger than int. The correct way is to use %ld for
long parameters.
The same portability problems exist with respect to function return values. A
function which returns an int should never be used to return a pointer or long
or floating-point value, even though it may work reliably on a particular system.
A common mistake is to omit a declaration of a function that returns a pointer,
and then place a cast around the invocation of that function. The cast cannot fix
the error; it only prevents the compiler from reporting it.
Pointer Issues
Nearly all machines supported by Green Hills compilers are byte addressable,
but neither C nor C++ require this. On some machines, a pointer to an int and
a pointer to a char are not interchangeable. ANSI C requires that void pointers
handle all pointer types, but the void pointer must be cast or assigned to its
original type before being used. Similarly, C does not require that function
pointers and data pointers be interchangeable, but some C programs incorrectly
make this assumption.
Pointer arithmetic should always be done directly on the pointers, not by casting
or assigning the pointers to integer types.
NULL Pointer
In all Green Hills C/C++ compilers, and most C compilers in general, the NULL
pointer has the value 0. But there are still two portability issues. One issue is
that some older programs depend upon the contents of memory location 0 being
0. This is now a well recognized programming error and some modern machines
purposely give a memory fault for any attempt to read or write to location 0.
A more subtle problem is the size of NULL. On a machine where pointers are
larger than int, it is incorrect to use the constant 0 as a NULL pointer, because 0
is of type int, which is smaller than a pointer. This matters when passing NULL
to a function that takes variable parameters or is not declared with a prototype.
Green Hills compilers use the ASCII character set and the ASCII collating
sequence. Some language implementations use a different collating sequence,
such as EBCDIC. Programs which manipulate character data, especially string
sorting algorithms, may be dependent on a particular character collating
sequence (the order in which characters are defined by the implementation). If
one character appears before a second character in the collating sequence, then
the first character will be considered smaller than the second character when
they are compared. In the ASCII collating sequence, the lowercase letters ’a’
to ’z’ appear as the contiguous integer values 97 to 122 (decimal). In other
collating sequences, such as EBCDIC, the lowercase letters are not contiguous.
Evaluation Order
None of the language specifications fully describe the order in which the various
components of an expression or statement must be evaluated. Additionally,
the language specifications disallow computations whose results depend upon
which permitted evaluation order is used. Many illegal programs have gone
undetected because they have only been compiled with one compiler. Because
the evaluation order may differ between compilers, some illegal programs may
not operate as expected when compiled with a Green Hills compiler.
Green Hills compilers may execute expressions with side effects (such as
subroutine, procedure, or function calls) in a different order than other
compilers. When a variable is modified as a side effect of an expression, and
its value is also used at another point in the expression, it is not specified
whether the value used at either point in the expression is the value before or
after modification. Different values for the same variable could potentially be
used at different places in the expression, depending on the evaluation order
observed by the compiler.
Green Hills compilers may also execute operators with side effects (such as ++,
--, or +=) in a different order from that of other compilers.
Green Hills compilers may allocate some pointer variables not declared
register to registers. This allows the compiler to generate more efficient
sequences for post-increment operators. These sequences may involve
incrementing at a different position in the statement than that used with other
compilers. In particular, statements of the form:
*p++ = expression involving ’p’
often evaluate differently with a PCC compiler than with a Green Hills compiler.
will usually evaluate differently under PCC than it will under a Green Hills
compiler.
Machine-Specific Arithmetic
Certain arithmetic operators in C/C++ are intended to generate the most
efficient corresponding operation on the target machine. If all input values are
within the expected range, the results are portable. Out of range values may
give different results on different systems.
Shift
The shift operators in C/C++ possess machine-specific arithmetic
characteristics. If the right-hand operand is negative or exceeds the number of
bits in the left-hand operand, the behavior is undefined. In Green Hills C/C++
compilers, the operands will be given to the hardware as if the operands were
legal, and the result depends entirely on the hardware. Some systems accept a
negative shift and reverse the direction of the shift, but many do not. Shifting by
more than the number of bits is the same as shifting by one less than the number
of bits on some systems, but on others it has very different results.
If the left-hand operand of a right shift is signed, C/C++ does not require the
compiler to propagate the sign bit. Thus a correct C/C++ compiler can yield a
positive number when right shifting a negative number by one.
Division
The division operator may round up or down when applied to signed integers
if one or both of them is negative. Division by zero produces different results
on different machines.
For example, C/C++ programs that rely on register variables being allocated
sequentially to pass hidden parameters will not work. Hidden returns (i.e., using
return and expecting to return the value of the last evaluated expression)
will not work either.
This option may cause problems for many parts of operating systems, device
drivers, memory mapped I/O locations, shared memory environments, multiple
process environments, interrupt-driven routines, and when UNIX style signals
are enabled. In C/C++, general optimizations may be used as follows.
If memory optimizations are enabled while compiling this loop, the compiler
may generate code that reads the value pointed to by TSRADDR only once. If the
Advanced→Advanced Optimization Options→Optimize All Appropriate
Loops option (-OL) is also enabled, it is almost certain that this will be the case.
When this happens, the loop executes either once or forever (depending on the
value of the bit when it is first tested) and will be rendered either ineffective
or fatal. Depending on the situation, the compiler may detect such loops
and generate code that operates correctly even with Advanced→Advanced
Optimization Options→Memory Optimization option (-OM) enabled.
However, if the loop body were to test more than one bit at the same address,
the compiler may distort the loop in an attempt to read memory as few times
as possible.
The compiler assumes that the volatile type qualifier is used when it is
available. This means that any Optimization→Optimization Strategy implies
Advanced→Advanced Optimization Options→Memory Optimization
Variable Allocation
Once a variable is allocated to a register it will always reside in that register.
However, because other variables may share the register, it may not always
contain the current value of the variable. This may cause a source level
debugger to give incorrect results. If a variable is looked at outside the range
of its use, the compiler may have temporarily allocated that register for some
other purpose. The best strategy is to check results just after they are assigned,
or when the current value is going to be used later. Near the end of a function,
most of the local variables will no longer be in use, so it is more likely that the
register has been re-allocated.
Advanced Optimizations
In general, it is advantageous to disable some optimizations if source level
debugging is to be performed. The following examples illustrate some specific
types of problems caused when using optimizations in conjunction with source
level debuggers.
Basic blocks also require memory. Every possible branch creates a new block.
Memory usage may increase on machine-generated programs with very large
switch statements or with a very large number of small if statements.
Green Hills compilers read the source program only once. The C++ and the
New Generation C compiler store the entire program into a parse tree before
proceeding with optimization and code generation. The Compatibility Mode
C compiler performs optimization and code generation as it reads in each
function. The optimizer modifies the parse tree and then passes it on to the
code generator. The code generator produces an internal representation of the
machine code to be output for the function. Another optimization phase is then
called to modify this machine code. Finally, the optimized machine code for the
function is output. After the machine code is output, the memory being used
for the parse tree, optimization, and machine code generation is released for
use in processing the next function.
Usually, the size of the largest function in the program determines the maximum
memory usage for parse trees and machine code. If memory size problems
exist, turn off the optimizer and reduce the size of the largest function. A
simple function of less than 100 lines should not cause memory size problems.
However, procedures containing very complex statements, or more than 1000
lines of code, may require several megabytes of memory in order to compile.
Although having the ability to write portable code is an advantage of using the
C language, sometimes it is necessary to introduce machine-specific assembly
language instructions into C code. This need arises most often within operating
system code that must deal with hardware registers that would otherwise be
inaccessible from C. You can use the asm facility to include this assembly code.
In earlier versions of C, the asm facility included a line that looked like a call
on the function asm that took one argument, a string:
asm("assembly instruction here");
The new facility presented here is upward-compatible with old code, since it
retains the old capability. In addition, you can define asm macros that describe
how machine instructions should be generated when their operands take
particular forms that the compiler recognizes, such as register or stack variables.
Although this enhanced asm facility is easier to use than before, the user is
still strongly discouraged from using it for routine applications, because those
applications will not be portable to different machines. The asm facility helps
implement operating systems in a clean way.
The optimizer (ccarm -O) may work incorrectly on C programs that use
the asm macro facility, leading to run-time errors. This is more likely when
the asm macros contain instructions or labels that are unlike those that the C
compiler generates. No compiler warning or error messages will be issued.
Furthermore, the user may need to rewrite asm code in the future, in order
to maximize its benefits as new optimization technology is introduced into
the compilation system.
instructions. Intrinsic functions are also easier to use since the compiler takes
care of loading and storing the operands automatically, as necessary.
Definition of Terms
The following terms are used when describing the asm macro facility.
Term Definition
asm macro The mechanism by which programs use the enhanced
asm facility. An asm macro has a definition and uses. The
definition includes a set of pattern/body pairs. Each pattern
describes the storage modes that the actual arguments must
match for the asm macro body to be expanded. The uses
resemble C function calls.
storage mode The compiler’s idea of where the argument can be found at
run time. Examples are “in a register” or “in memory.”
pattern Specifies the modes for each of the arguments of an asm
macro. When the modes in the pattern all match those of the
use, the corresponding body is expanded.
asm macro body The portion of code that will be expanded by the compiler
when the corresponding pattern matches. The body may
contain references to the formal parameters, in which
case the compiler substitutes the corresponding assembly
language code.
Example
The following is a general example intended to demonstrate how to define
and use an asm macro. For an example specific to ARM, see “ARM asm
Macros” on page 619.
Suppose your machine has an spl instruction for setting machine interrupt
priority levels. spl takes one operand, which must be in a register.
Nevertheless, it would be convenient to have a function that produces inline
code to set priority levels, uses the spl instruction, and works with register
variables or constants.
This example consists of two parts: the definition of the asm macro and its use.
Definition
Define an asm macro, called spl:
asm void SPL(newpri)
{
%reg newpri
spl newpri
%con newpri
movw newpri, %r0
spl %r0
}
The lines that begin with % are patterns. If the arguments at the time the macro
is called match the storage modes in a pattern, the code that follows the pattern
line will expand.
Use
The table below shows the (assembly) code that the compiler will generate with
two different uses of spl. It uses the following introductory code (along with
the above definition):
f() {
register int i;
SPL(i);
SPL(3);
}
The first use of spl has a register variable as its argument (assuming that
i actually gets allocated to a register). This argument has a storage mode
that matches reg, the storage mode in the first pattern. Therefore, the
compiler expands the first code body. newpri, the formal parameter in the
definition, has been replaced in the expanded code by the compiler’s idea of
the assembly-time name for the variable i, namely %r8. Similarly, the second
use of spl has a constant as its argument, which leads to the compiler’s
choosing the second pattern. Here again newpri has been replaced by the
assembly-time form for the constant &3.
The asm macro definition declares a return type for the macro code, specifies
patterns for the formal parameters, and provides bodies of code to expand
when the patterns match. When it encounters an asm macro call, the compiler
replaces uses of the formal parameters with its idea of the assembly language
locations of the actual arguments as it expands the code body. This constitutes
an important difference between C functions and asm macros. An asm macro
can have the effect of changing the value of its arguments, whereas a C function
can only change a copy of its argument values.
Calls to asm macros look exactly like normal C function calls. They may be
used in expressions and they may return values. The arguments to an asm
macro may be arbitrary expressions, except that they may not contain uses
of the same or other asm macros. Return values are passed according to the
target-specific calling convention.
Definition
The syntactic classes type_specifier, identifier, and parameter_list are presented
in the style used in C-language compilers. A syntactic description enclosed in
square brackets ([ ]) is optional, unless the right bracket is followed by +. A +
means “one or more repetitions” of a description. Similarly, * means “zero or
more repetitions.” For example:
asm [type_specifier]identifier ([parameter_list])
{
[storage_mode_specification_line
asm_body] *
}
An asm macro consists of the keyword asm followed by what looks like a C
function declaration. Inside the macro body there are one or more pairs of
storage_mode_specification_lines (patterns) and corresponding asm_bodies.
If the type_specifier is other than void, the asm macro should return a value
of the declared type.
storage_mode_specification_line
% [storage_mode [identifier [, identifier]* ] ]*
Storage Modes
These are the storage modes that the compiler recognizes in asm macros:
Storage Description
mode
con A compile-time constant.
error Generates a compiler error. You can use this mode to flag errors at
compile time if no appropriate pattern exists for a set of actual arguments.
farsprel A location on the stack that is too far away to be accessed in a single
instruction.
lab A compiler-generated unique label. The identifier(s) that are specified
as being of mode lab do not appear as formal parameters in the asm
macro definition, unlike the preceding modes. Such identifiers will be
expanded to be unique.
Example:
mem Matches any allowed machine addressing mode, with the exception
of reg and con.
Storage Description
mode
farmem A location in memory that cannot be accessed with a single-load
instruction. These may need to be broken up into multiple-load
instructions, and the steps for doing this may depend on the compilation
mode.
nearmem A location in memory that can be accessed with a single-load instruction
(such as nearby stack variables or variables in a Small Data Area).
reg A treg or ureg.
treg A compiler-selected temporary register.
ureg A C register variable that the compiler has allocated in a machine
register.
asm Body
The asm body represents the (presumed) assembly code that the compiler will
generate when the modes of all of the formal parameters match the associated
pattern. Syntactically, the asm body consists of the text between two pattern
lines that begin with a percent sign (%) or between the last pattern line and the
right curly brace (}) that ends the asm macro. C-language comment lines are
not recognized as such in the asm body. Instead, they are simply considered
part of the text to be expanded.
Formal parameter names may appear in any context in the asm body, delimited
by non-alphanumeric characters. For each instance of a formal parameter in the
asm body the compiler substitutes the appropriate assembly language operand
syntax that will access the actual argument at run time. As an example, if one
of the actual arguments to an asm macro is x, an automatic variable, a string
like 4(%fp) would be substituted for occurrences of the corresponding formal
parameter. An important consequence of this macro substitution behavior is
that asm macros can change the value of their arguments. This differs from
standard C semantics.
For lab parameters, a unique label is chosen for each new expansion.
An implementation restriction requires that no line in the asm body may start
with a percent sign (%).
%con a %mem b
mov r0,a
ldr r1,b
mul r0,r1,r0
%mem a %con b
ldr r0,a
mov r1,b
mul r0,r1,r0
%mem a %mem b
ldr r0,a
ldr r1,b
mul r0,r1,r0
%error
}
#endif
short x = 30;
short y = 2;
int z=10;
func()
{
int tmp1 = x, tmp2 = y;
int ztmp = z;
return mulword(10,20) + mulword(tmp1,tmp2) + mulword(ztmp,30) +
mulword(ztmp,ztmp) + mulword(10,ztmp);
}
func2()
{
int tmp1 = x, tmp2 = y;
int ztmp = z;
return (10*20) + (tmp1*tmp2) + (ztmp*30) +
(ztmp*ztmp) + (10*ztmp);
}
main()
{
if (func() == func2())
printf("Everything is just peachy.\n");
return 0;
}
Optimization Descriptions
For further details about this and other high-level optimization options, see
“Optimization Options” on page 143.
Inlining Optimizations
The term inlining refers to the process of substituting a call to a function or
subroutine with the actual content of that function or subroutine. This eliminates
the overhead of a subroutine call and results in faster code.
Typically, the best candidate for inlining is a small, frequently executed function
or subroutine that the program calls from only a few locations. Inlining increases
efficiency in high usage areas without significantly increasing program size.
Automatic Inlining
To enable this optimization, set the Optimization→Optimization
Strategy option to Optimize for Speed (-Ospeed).
To disable this optimization, set the Advanced→Advanced
Optimization Options→Inline Tiny Functions option to Off
(--no_inline_tiny_functions).
Manual Inlining
With manual inlining, the user indicates in the source code which functions
should be considered for inlining. The method for doing this differs for each
language:
Functions declared inline are considered to be of static scope; therefore, they are
not exported or available to be inlined in other modules. If all calls to a function
are inlined, and if the address of the function is never taken, the compiler will
not generate any out-of-line code for that function.
Single-pass Inlining
This optimization is enabled by default and cannot be disabled.
Only those functions manually indicated by the user in the source code will be
considered for inlining. In the Compatibility Mode C compiler, only those
functions which are defined before they are called will be inlined.
Example 1.
The following program illustrates the basic principles of inlining. The main
program in this case contains a simple loop that calls the function sub(). The
call itself occurs only once in the program code, but the function is executed
for each iteration of the loop. The call is easily replaced by the routine code
for sub() itself, eliminating both the need for parameter passing and the
overhead of a jump-to-subroutine. The reduced overhead per execution results
in a major increase in program speed.
Inline functions are given the internal linkage (as though they were declared
static). Therefore, it is safe to remove the body unless the address of the
inline function is taken. Note that in the example above, the body of sub()
is eliminated following this strategy.
It is important to note that each module which calls an inline function must
“see” its entire definition (including the body). If only a declaration is available,
all symbols might not get resolved, leading to linker errors. Also, be cautious
when taking an address of an inline function from two different modules—this
will result in two different values (since each module will treat the inline
function as its own local copy). Comparing the two values will not result in
equality (which one might expect for non-inline functions).
In two-pass inlining, compiler warnings are suppressed on the first pass so that
duplicate warnings will not be issued.
Any functions that have been manually specified will also be considered for
inlining.
Any functions that have been manually specified (see “Manual Inlining” on
page 626) will also be considered for inlining.
file_b.c:
extern int a_very_big_function(), b();
__inline int c()
{
return 3;
}
int main()
{
return a_very_big_function() + b() + c();
}
• The function c() will be inlined because it was declared with __inline
in the same module as the caller.
• The functions a_very_big_function() and b() will be generated in
closed form in module a. c() will not be generated in closed form because
it is declared with __inline and it was successfully inlined everywhere.
The compiler will still not consider very large functions for inlining unless
they are specified using the Optimization→Individual Functions→Inline
Specific Functions option (-OI=fn1[,fn2…]). For example, if
Optimization→Intermodule Inlining (-OI) is not inlining sufficiently large
functions for your needs, pass:
ccarm -OI -OB
If you need even larger functions to be inlined, then you must specify them
individually using Optimization→Individual Functions→Inline Specific
Functions option (-OI=fn1[,fn2…]). For example, to enable automatic
two-pass inlining with the higher Optimization→Optimization Scope→Inline
Larger Functions (–OB) threshold, and to additionally inline the function
a_very_big_function(), pass:
ccarm -OI -OB -OI=a_very_big_function
Advantages of Inlining
Inlining is traditionally considered an optimization that improves program
speed at the cost of increasing program size. However, although inlining creates
more code (because the compiler may generate a single function multiple
times within the program), it may actually decrease the overall program size.
When a call is replaced by inlined code, the compiler can usually avoid saving
and restoring several registers before and after the call. Parameters which
normally must be passed on the stack to a called routine can be accessed
directly by the inlined routine in their original location. Furthermore, because
Green Hills compilers perform inlining before most global optimizations, the
process of inlining may significantly enhance the opportunities for additional
optimizations. This results in very efficient code.
For example, if one or more parameter values are constant, large portions of the
inlined routine may be reduced or eliminated at compile time, and loops which
normally execute a variable number of times may become constant.
Pessimistic assumptions made by the compiler when compiling the caller may
not be necessary if no call is made. Normally the compiler must assume that
when a call is performed, global variables may be changed. This prevents the
compiler from optimizing the values of expressions containing global variables
across a call to a function. When the function is inlined, the call is eliminated
and the global variables can be optimized freely.
Limitations of Inlining
Inlining is subject to the following limitations:
the function from within the module will differ from the address taken in other
modules. You should not use memory (or string) inlining when the addresses
of such functions are taken.
You can use these options to control C++ inlining for all modules that make up
an executable, or at a local module-by-module level. You can also use them
together, perhaps enabling maximum inlining for modules that contain only
small functions and disabling all inlining for modules containing large functions.
To control C++ inlining within a module, you should use the #pragma ghs
startnoinline and #pragma ghs endnoinline constructs and/or
the __noinline keyword. These #pragmas bracket off functions which
should not, even if they are member functions defined inside a class, be inlined.
This feature has no effect on template functions or member functions of
template classes.
You can use the __noinline keyword when declaring template member
functions or direct member functions of template classes, by adding it to the
source code in the same place where inline is ordinarily accepted. The
__noinline keyword treats an inline member function as though it were
defined outside of the class body. This has the effect of generating a single
externally visible closed copy for that template instantiation. This is preferable
to disabling all inlining, since it does not generate duplicate copies in different
modules.
Consequently, you can combine the same source code differently without
having to remove the __noinline keyword. To suppress recognition of
the __noinline keyword, set the C/C++ Compiler→C++→Keyword
Support→Support __noinline Keyword option to Off (--disable_noinline).
The Green Hills C++ library header files make use of the __noinline
keyword on member functions which are known to cause large code bloats.
Loop Optimizations
The compiler uses most of its resources to optimize code in the innermost loops
in your source files. Therefore, this optimization is most effective for code
containing many loop structures that are executed frequently.
• strength reduction
• loop invariant analysis
• loop unrolling
For example, the following command line specifies that loop optimizations will
be applied to sub and sub2:
ccarm -OL=sub,sub2 main.c prog1.c prog2.c
Strength Reduction
This optimization is applied to arrays subscripted with the loop index. Most
compilers access the array element by multiplying the size of the element by the
loop index. The Green Hills compilers store the address of the array in a register
and add the size of the array element to the register on each iteration of the loop.
Example 1.
Initial C source code Optimized C source code
subr() subr()
{ {
int i; int i;
int q[4]; int q[4];
for (i=0;i<4;i++) int *_ptr;
q[i]=i; for (i=0, _ptr=q; i<4; i++)
} *_ptr++ = i;
}
Strength reduction also applies to multiplying a loop invariant with the loop
index. The optimizer replaces a multiply instruction or a call to the mul()
library function with add and shift instructions.
Example 2.
Initial C source code Optimized C source code
subr() subr()
{ {
int i,j; int i,j;
int q[4],p[4]; int q[4],p[4];
for (i=3;i>=0;i--) { int *_ptr;
q[i]=i; for (i=3; i>=0; i--) {
for (j=0;j<4;j++) q[i] = i;
p[j]=q[i]; for (j=0, _ptr = &q[i]; j<4; j++)
} p[j] = *_ptr;
} }
}
Loop Unrolling
This optimization duplicates the code in innermost loops up to a maximum of
four times to produce more straightline code. This removes much of the loop
overhead required for testing for stop condition and branching, and allows for
more instruction pipelining and better use of the register allocator . It is most
effective when the innermost loop is relatively short, causing minimal increase
in code size. The following options allow further control over loop unrolling:
To decrease from 8 to 4 the number of times that a loop may be
unrolled:
Set the Optimization→Optimization Scope→Unroll Loops Up To 8
Times option to Off (-Onounroll8).
To increase the maximum size of loops that may be unrolled:
Set the Optimization→Optimization Scope→Unroll Larger Loops
option to On (-Ounrollbig).
To disable loop unrolling (recommended when code size is a priority):
Set the Advanced→Advanced Optimization Options→Loop
Unrolling option to Off (-Onounroll).
Example 3.
This simple example uses a loop with a constant iteration count of 100 and a
maximum loop index of 4. If the number of iterations (n) is large (auxiliary
loop execution time is negligible), then the loop takes n*(4 cycles per iteration)
= 4n cycles to complete. The unrolled loop takes n/ 4 *(10 cycles per iteration)
= 2.5n cycles to complete. If n is large, unrolling makes the loop execute in
only 63% of the original time.
subr(a) subr(a)
int a[]; int a[];
{ {
int i; int i;
for (i=0;i<100;i++) for (i=0;i<100;i+=4) {
a[i]=i; a[i]=i;
} a[i+1]=i+1;
a[i+2]=i+2;
a[i+3]=i+3;
}
}
General Optimizations
To enable all of the optimizations in this section:
Set the Optimization→Optimization Strategy option to one of the
following settings:
• Optimize for Size (-Ospace).
• Optimize for General Use (-O).
• Optimize for Speed (-Ospeed).
Peephole Optimization
This optimization is generally controlled by the setting you specify in the
Optimization→Optimization Strategy option. To control it individually:
Use the Advanced→Advanced Optimization Options→Peephole
Optimization option (-Opeep/-Onopeephole).
When debugging, you may find it helpful to select the Restrict
peephole optimization scope to increase debuggability setting
of the Optimization→Optimization Scope→Pipeline & Peephole
Scope option (-Olimit=peephole).
This optimization identifies common code patterns and replaces them with more
efficient code. This includes optimizations such as flow of control, algebraic
simplifications, and removal of unreachable code. The compiler only performs
this optimization when local code analysis ensures that the results will be
correct without further analysis of the surrounding code.
Example 1.
Initial Assembly code Optimized Assembly code
• branch scheduling
• basic block scheduling
• superscalar scheduling (for certain architecture implementations only)
These are among the most important optimizations for many architectures, and
can increase code speed by 10% or more for the majority of applications.
Branch scheduling consists of two different areas: filling branch delay slots and
filling a delay between a comparison and a branch based on that comparison.
In this example, the branch delay slot is filled when instruction 5 from sequence
(a) is placed in the nop slot after the branch at instruction 6 in sequence (b).
This causes the normally unused cycles after the branch to be used on the
sub instruction.
In this example, this change is made by reversing the order of the two add
instructions at lines 3 and 4 between sequence (a) and sequence (b) to allow
for the load delay in instruction 2. This will prevent a stall after the load and
instead use those cycles on the add instruction.
instructions associated with multiple execution units can execute at the same
time.
For this generic superscalar machine example, assume the same architecture
characteristics as in the previous example and, also, that:
• one integer and one floating-point instruction can be issued in the same cycle
• the floating-point instruction must follow the integer instruction with which
it is paired
This example uses the same instructions as the last example, with the addition
of a floating-point add instruction and a floating-point sub instruction at lines
6 and 7.
(a) Before Scheduling (b) After Scheduling
1 load r0, 0(r5) load r0, 0(r5)
2 load r1, 4(r6) load r1, 4(r6)
3 add r0, r1, r2 add r7, r8, r9
4 add r7, r8, r9 addd f0, f1, f2
5 sub r0, r3, r4 add r0, r1, r2
6 addd f0, f1, f2 subd f3, f2, f4
7 subd f3, f2, f4 branch L2
8 branch L2 sub r0, r3, r4
9 nop
Conditional Instructions
This optimization is generally controlled by the setting you specify in the
Optimization→Optimization Strategy option. To control it individually:
Example 4.
Initial Assembly code Optimized Assembly code
This optimization instructs the compiler to take objects which would otherwise
be allocated to uninitialized sections (such as .bss) and put them into
initialized sections (such as .data) when it determines that this will improve
performance and reduce program size.
Example 5.
Initial C source code Optimized C source code
The optimized code is able to access and load the required data using fewer
instructions.
Example 6.
Initial C source code Optimized C source code
Tail Recursion
This optimization is generally controlled by the setting you specify in the
Optimization→Optimization Strategy option. To control it individually:
Example 7.
Initial C source code Optimized C source code
Constant Propagation
This optimization is generally controlled by the setting you specify in the
Optimization→Optimization Strategy option. To control it individually:
Example 8.
Initial C source code Optimized C source code
main() main()
{ {
int i,a,b; int i,b;
a = 3; b = 0;
b = 0; for (i=0; i<1000; i++)
b+=3;
for (i=0;i<1000;i++) { printf("%d\n", b);
b += a; }
/* a is constant over the
lifetime of the loop */
}
printf("%d\n", b);
}
This optimization generates special code for minimum, maximum, and absolute
value expressions of the form:
(i < j) ? i : j
(i > j) ? i : j
(i < 0) ? -i : i
Memory Optimization
This optimization is generally controlled by the setting you specify in the
Optimization→Optimization Strategy option. To control it individually:
Note This optimization assumes that memory locations only change with
explicit store instructions and thus are not affected by any external sources.
Hence, it is not recommended for applications such as device drivers, and
operating systems, in which memory could be externally affected, or for shared
memory or a non-virtual memory environment when interrupts are enabled.
In the following example, after the expression 0*x is constant folded and the
value 0 is constant propagated into the if conditional, this optimization is able
to determine that the then block is unreachable and removes the call foo()
and the return c. Then, it can determine that the value of variable c is no
longer used, and is able to eliminate the expression c = 3 * x.
Example 9.
Initial C source code Optimized C source code
Example 10.
Initial C source code Optimized C source code
Note This optimization is performed not only for locally defined static
variables, but also for global variables, as shown in the following example.
Example 11.
Initial C source code Optimized C source code
Default Optimizations
The optimizations in this section are very basic and are enabled even if no
Optimization→Optimization Strategy is specified.
In the following example, the variables a and b are both assigned to the same
register because their lifetimes do not overlap (note that the code could be
optimized further, but is not here in order to simplify the example).
Example 1.
Initial C source code Optimized C source code
For small functions, the compiler maintains all local variables in registers.
Scalars are generally considered for register allocation unless their values are
accessed with the address operator (&).
Example 2.
Initial C source code Optimized C source code
Register Coalescing
This optimization is enabled by default and cannot be disabled. It eliminates the
additional register-to-register copies required when using a temporary register.
When evaluating an expression, the compiler uses the destination register as
a work register and organizes the instruction sequence so that the result ends
up in that register.
Example 3.
Initial C source code Optimized C source code
Constant Folding
This optimization is enabled by default, and cannot be disabled. If the compiler
determines that an expression is a constant, it substitutes the constant in place
of any reference to the expression. In the following example, the expression
SHRT_MAX/2 is a constant with a value of 16383.
Example 4.
Initial C source code Optimized C source code
Loop Rotation
This optimization is enabled by default and cannot be disabled. It locates
the termination test and a conditional branch at the bottom of the loop. This
causes the loop to process only one branch instruction on each iteration. Most
compilers place the termination test and an unconditional branch at the top of
the loop and an additional unconditional branch at the bottom.
Example 5.
Initial C source code Optimized C source code
If the compiler determines that the loop is executed at least once, it is entered
at the top. If not, the compiler generates an unconditional branch before the
loop to the termination test.
This chapter explains the formats of ELF (Executable and Linking Format)
files. Sections of this chapter have been reproduced with permission from
UNIX System Laboratories, Inc. For more information about ELF files, see
System V Application Binary Interface, 1993, UNIX System Laboratories, Inc.,
published by Prentice-Hall, Inc.
• a relocatable object file — which contains program code and data and is
suitable for linking with other object files.
• an executable file — which contains a program suitable for execution.
The following diagram shows the differences in format between these kinds
of ELF files:
Both forms of ELF file begin with an ELF Header, which serves as the table of
contents. All other data and tables in the file may appear in any order.
An executable file must have a Program Header Table, which tells the system
how to load the program. This component is optional in a relocatable file.
All data structures that the ELF file format defines follow the usual size and
alignment guidelines for the relevant class. If necessary, data structures contain
explicit padding to ensure 4-byte alignment for 4-byte objects in order to force
structure sizes to a multiple of 4. Data also have suitable alignment from the
beginning of the file. For example, a structure containing Elf32_Addr will
be aligned on a 4-byte boundary within the file.
ELF Headers
Some ELF file control structures can grow because the ELF header contains
their actual sizes. If the ELF file format changes, a program may encounter
control structures that are larger or smaller than expected. An ELF header is set
by the following C structure declaration:
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
e_machine
Specifies the target architecture for an individual file. Permitted values are as
follows:
• 0 (EM_NONE): Invalid machine
• 2 (EM_SPARC): Sun SPARC
• 3 (EM_386): Intel 80386
• 4 (EM_68K): Motorola 68000
• 6 (EM_486): Intel 80486
• 8 (EM_MIPS): MIPS
• 19 (EM_960): Intel i960
• 20 (EM_PPC): PowerPC
• 36 (EM_V800): NEC V800 series
• 37 (EM_FR20): Fujitsu FR
• 40 (EM_ARM): ARM
• 42 (EM_SH): Hitachi SH
• 44 (EM_TRICORE): Infineon TriCore
• 52 (EM_COLDFIRE): Motorola ColdFire
• 54 (EM_MCORE): Motorola MCore
• 58 (EM_STARCORE): Motorola StarCore
• 60 (EM_ST100): STMicroelectronics ST100
• 78 (EM_FIREPATH): Broadcom FirePath
• 79 (EM_ZSP): LSI ZSP
• 88 (EM_M32R): Renesas M32R
• 106 (EM_BLACKFIN): ADI Blackfin
e_version
Identifies the ELF file version. Permitted values are as follows:
• 0 (EV_NONE): Invalid version
• 1 (EV_CURRENT): Current version
The value 1 (one) signifies the original file format; extensions will create new
versions with higher numbers.
e_entry
Specifies the virtual address to which the system first transfers control upon
starting the process. If the file has no associated entry point, this field contains
the value zero.
e_phoff
Specifies the program header table’s file offset in bytes. If the file has no program
header table, this field contains the value zero.
e_shoff
Specifies the section header table’s file offset in bytes. If the file has no section
header table, this field contains the value zero.
e_flags
Specifies processor-specific flags associated with the file. Flag names take the
form EF_machine_flag.
• 0x00080000 (EF_ARM_FHARD): Hardware floating point
• 0x00040000 (EF_ARM_THUMB): Thumb instruction encoding
• 0x00020000 (EF_ARM_V4): Version 4 instruction architecture
• 0x00010000 (EF_ARM_V5): Version 5 instruction architecture
• 0x0000ff000 (EF_ARM_CPU_MASK): Processor variant mask
e_ehsize
Specifies the ELF header size in bytes.
e_phentsize
Specifies the size in bytes of one entry in the file’s program header table; all
entries are the same size.
e_phnum
Specifies the number of entries in the program header table. The product of
e_phentsize and e_phnum specifies the table’s size in bytes. If a file has no
program header table, e_phnum contains the value zero.
e_shentsize
Specifies the section header’s size in bytes. A section header is one entry in the
section header table; all entries are the same size.
e_shnum
Specifies the number of entries in the section header table. The product of
e_shentsize and e_shnum specifies the section header table’s size in bytes. If
a file has no section header table, this field contains the value zero.
e_shstrndx
Specifies the index of the section containing the string table used for section
names. By convention, this is the section .shstrtab. If the file has no section
name string table, this field contains the value SHN_UNDEF.
ELF Identification
ELF provides a file framework to support multiple processors, multiple data
encodings, and multiple classes of machines. To support this file family, the
initial bytes of the file specify how to interpret the file, independent of the
processor on which the inquiry is made and independent of the file’s remaining
contents.
The initial bytes of an ELF header correspond to the e_ident member. The
identification indexes are tabulated below:
Index name Value Meaning
EI_MAG0 to 0 to 3 File identification
EI_MAG3
EI_CLASS 4 File class
EI_DATA 5 Data encoding
EI_VERSION 6 File version
EI_PAD 7 Start of padding bytes
EI_NIDENT 16 Size of e_ident[]
EI_DATA
This byte specifies the data encoding of the processor-specific data in the file.
Permitted values are as follows:
• 0 (ELFDATANONE): Invalid data encoding
• 1 (ELFDATA2LSB): Specifies 2’s complement values, with the least significant
byte occupying the lowest address.
• 2 (ELFDATA2MSB): Specifies 2’s complement values, with the most significant
byte occupying the lowest address.
Other values are reserved and are assigned to new encodings as necessary.
EI_VERSION
This byte specifies the ELF header version number. Currently, this value must be
EV_CURRENT, as explained above for e_version.
EI_PAD
This value marks the beginning of the unused bytes in e_ident. These bytes are
reserved and set to zero; programs that read ELF files should ignore them. The
value of EI_PAD changes if currently unused bytes are given meanings.
EI_NIDENT
This value specifies the size of e_ident[].
ELF Sections
Section Headers
You can use an ELF file’s section header table to locate all the file’s sections.
The section header table is an array of Elf32_Shdr structures. A section
header table index is a subscript into this array. The ELF header e_shoff
specifies the byte offset from the beginning of the file to the section header
table; e_shnum tells how many entries the section header table contains; and
e_shentsize specifies the size in bytes of each entry.
Sections contain all information in a file except the ELF header, the program
header table, and the section header table. Sections satisfy several conditions:
• Every section in an ELF file has exactly one section header describing it.
Section headers may exist that do not have an associated section.
• Each section occupies one contiguous (possibly empty) sequence of bytes
within a file.
• Sections in a file may not overlap. No byte in a file resides in more than
one section.
• An ELF file may have inactive space. The various headers and the sections
might not account for every byte in a file. The contents of the inactive space
are unspecified.
sh_link
Contains a section header table index link, whose interpretation depends on the
section type.
sh_info
Contains extra information, whose interpretation depends on the section type.
sh_addralign
Some sections have address alignment constraints. For example, if a section
contains a doubleword, the system may need to ensure doubleword alignment
for the entire section. That is, the value of sh_addr must be equal to 0 (zero),
modulo the value of sh_addralign. Currently, only 0 (zero) and positive integral
powers of two are allowed. The values 0 (zero) and 1 (one) mean the section
has no alignment constraints.
sh_entsize
Some sections contain a table of fixed-size entries, such as a symbol table. For
such sections, this field specifies the size in bytes of each entry. This structure
contains zero if the section does not contain a table of fixed-sized entries.
Section Types
A section header’s sh_type specifies the section’s semantics as follows:
Name Value Meaning
SHT_NULL 0 Marks the section header as inactive. It does not
have an associated section. Other members of the
section header have undefined values.
SHT_PROGBITS 1 Contains information defined by the program that
created the ELF file, whose format and meaning
are determined solely by the program.
SHT_SYMTAB 2 Contains a symbol table. An object file may have
only one section of this type, but this restriction
may be relaxed in the future. The table provides
symbols for link editing, though it may also be
used for dynamic linking. As a complete symbol
table, it may contain many symbols unnecessary
for dynamic linking.
SHT_STRTAB 3 Contains a string table. A file may have multiple
string table sections.
SHT_RELA 4 Contains relocation entries with explicit addends,
such as type Elf32_Rela for the 32-bit class
of ELF files. A file may have multiple relocation
sections.
SHT_NOTE 7 Contains notes that flag this ELF file indicating
certain properties.
SHT_NOBITS 8 Occupies no space in the file but otherwise
resembles SHT_PROGBITS.
SHT_REL 9 Contains relocation entries without explicit
addends, such as type Elf32_Rel for the
32-bit class of ELF files. A file may have multiple
relocation sections.
Two structures in the section header, sh_link and sh_info, contain special
information, depending on section type as follows:
sh_type sh_link sh_info
SHT_REL The section header index of the The section header index of the
associated symbol table. section to which the relocation
SHT_RELA
applies.
SHT_SYMTAB The section header index of the One greater than the symbol
associated string table. table index of the last local
symbol (binding STB_LOCAL).
other SHN_UNDEF 0
Section Names
Section names beginning with a period (.) are not meant for general use by
application programs, although application programs may use these sections if
their existing meanings are satisfactory. Application programs may use names
without the leading period to avoid conflicts with predefined section names.
.bss
Contains uninitialized data that contributes to the program’s memory image. The
system initializes the data with zeros when the program begins to run.
Type: SHT_NOBITS
Attributes: SHF_ALLOC | SHF_WRITE
.data
Contains initialized data that contributes to the program’s memory image.
Type: SHT_PROGBITS
Attributes: SHF_ALLOC | SHF_WRITE
.linfix
When using Code Factoring or fixing “out of range relocations” inline, the assembly
becomes out of sync with the debugging information. The linker notes the changes
to the program that require updates to the debugging information in the .linfix
section. MULTI merges the information in the .dla file and the .linfix section
when debugging the program.
The .linfix section is not downloaded to the target.
Type: SHT_PROGBITS
Attributes: None
.relname
.relaname
These sections contain relocation information. If the file has a loadable segment
that includes relocation, the attributes of the sections include the SHF_ALLOC bit;
otherwise, that bit will be off. Conventionally, name is supplied by the section
to which the relocations apply. A relocation section for .text has the name
.rel.text or .rela.text.
Types: SHT_REL and SHT_RELA
Attributes: SHF_ALLOC or none
.rodata
Read-only data area. Similar to the .data section, but comprised of constant data.
Type: SHT_PROGBITS
Attributes: SHF_ALLOC
.shstrtab
Contains section names.
Type: SHT_STRTAB
Attributes: None
.strtab
Contains strings, most commonly the strings that represent the names associated
with symbol table entries. If the file has a loadable segment that includes the
symbol string table, the section’s attributes include the SHF_ALLOC bit; otherwise,
that bit will be off.
Type: SHT_STRTAB
Attributes: SHF_ALLOC or none
.symtab
Contains a symbol table. If the file has a loadable segment that includes the
symbol table, the section’s attributes include the SHF_ALLOC bit; otherwise, that
bit will be off.
Type: SHT_SYMTAB
Attributes: SHF_ALLOC or none
.text
Contains the text, or executable instructions, of a program.
Type: SHT_PROGBITS
Attributes: SHF_ALLOC | SHF_EXECINSTR
Some sections are specific to Green Hills ELF; these are listed in the following
table. Target processors may support some or all of these sections.
.syscall
A program code section to support the Green Hills system call mechanism.
Type: SHT_PROGBITS
Attributes: SHF_EXECINSTR | SHF_ALLOC
.secinfo
A table, created by the linker, that describes actions to be taken on sections as
they are loaded for program execution (sections to be cleared, copied from ROM
to RAM, and so on).
Type: SHT_PROGBITS
Attributes: SHF_ALLOC
.fixaddr
.fixtype
Tables created by the compiler for position independent code (PIC) and position
independent data (PID) static pointer adjustments to be made when the program
is loaded for execution.
Type: SHT_PROGBITS
Attributes: SHF_ALLOC
.sdabase
If not in PID mode, the run-time system initializes the Small Data Area (SDA) base
register to be the address of this section (.sdabase).
Type: SHT_NULL
Attributes: SHF_ALLOC
.sdata
.zdata
Initialized Small Data Area and Zero Data Area. Similar to the .data section, but
of limited size and more efficiently addressed.
Type: SHT_PROGBITS
Attributes: SHF_ALLOC | SHF_WRITE
.sbss
.zbss
Uninitialized Small Data Area and Zero Data Area. Similar to the .bss section,
but of limited size and more efficiently addressed.
Type: SHT_PROGBITS
Attributes: SHF_ALLOC | SHF_WRITE
.heap
Section describing the area of memory for dynamic allocations through malloc
and related functions.
Type: SHT_NOBITS
Attributes: SHF_ALLOC | SHF_WRITE
.stack
Section describing the area of memory that the program stack will occupy.
Type: SHT_NOBITS
Attributes: SHF_ALLOC | SHF_WRITE
Relocation Types
Relocation is the process of connecting symbolic references with symbolic
definitions. For example, when a program calls a function, the associated call
instruction must transfer control to the proper destination address at execution.
Relocatable files must have information that describes how to modify their
section contents, thus allowing executable files to contain the right information
for a process’s program image. Relocation entries contain this information. In
the code below, example 2 is preferred:
Example 1.
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
Example 2.
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
r_offset
Specifies the location at which to apply the relocation action. For a relocatable file,
the value is the byte offset from the beginning of the section to the storage unit
affected by the relocation. For an executable file or a shared object, the value of
which is the virtual address of the storage unit affected by the relocation.
r_info
Specifies both the symbol table index with respect to which the relocation must
be made and the type of relocation to apply information for a process’s program
image. For example, a call instruction’s relocation entry contains the symbol table
index of the function being called. You may find the following macros helpful when
reading from or writing to the r_info field:
r_addend
Specifies a constant value used to compute the final value to be stored into the
relocatable field.
A relocation section references two other sections: a symbol table and a section
to modify. The section header’s sh_link and sh_info specify these
sections.
Symbol Tables
The symbol table of an ELF file contains information to locate and relocate
a program’s symbolic definitions and references. A symbol table index is a
subscript into this array. Index 0 (zero) both designates the first entry in the
table and serves as the undefined symbol index. The contents of the initial entry
are specified below. A symbol table entry has the following format:
typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
where:
st_name
Contains an index into the file’s symbol string table. The string table contains the
character representations of the symbol names. If this field is non-zero, then it
represents a string table index that specifies the symbol name. Otherwise, the
symbol table entry has no name.
st_value
Specifies the associated symbol’s value. Depending on the context, this may be
an absolute value, an address, and so on.
st_size
Many symbols have associated sizes. For example, a data object’s size is the
number of bytes contained in the object. This field is zero if the symbol has no
size or an unknown size.
st_info
Specifies the symbol’s binding attributes and type, as explained in the symbol
binding and symbol type sections below. The values and meanings are defined
below:
st_other
The least significant bit is set to indicate thumb mode functions, and clear for
ARM mode.
st_shndx
Every symbol table entry is “defined” in relation to some section; this field contains
the relevant section header table index. Some section indexes indicate special
meanings. For more information, see “Special Section Indexes” on page 666.
Symbol Binding
A symbol’s binding determines the linkage visibility and behavior.
Name Value Attributes
STB_LOCAL 0 Local symbols are not visible outside the object file
containing their definition. Local symbols of the same
name may exist in multiple files without interfering with
each other.
STB_GLOBAL 1 Global symbols are visible to all object files being
combined. One file’s definition of a global symbol will
satisfy another file’s undefined reference to the same
global symbol.
STB_WEAK 2 Weak symbols resemble global symbols, but their
definitions have lower precedence.
STB_LOPROC 13 Values in this inclusive range (from STB_LOPROC to
STB_HIPROC) are reserved for processor-specific
STB_HIPROC 15
semantics. If meanings are specified, the processor
supplement explains them.
Symbol Type
A symbol’s type provides a general classification for the associated entity.
Name Value Attributes
STT_NOTYPE 0 The symbol’s type is not specified.
STT_OBJECT 1 The symbol is associated with a data object, such as a
variable, array, and so on.
STT_FUNC 2 The symbol is associated with a function or other
executable.
STT_SECTION 3 The symbol is associated with a section. Symbol table
entries of this type exist primarily for relocation and
normally have STB_LOCAL binding.
Symbol Values
Symbol table entries for different ELF file types have slightly different
interpretations for the st_value member:
Although the symbol table values have similar meanings for different file types,
the information allows efficient access by the appropriate programs.
String Tables
String table sections contain null-terminated character sequences or strings.
These strings are used to represent symbol and section names. An empty
string table section is permitted; its section header’s sh_size contains zero.
Non-zero indexes are invalid for an empty string table. If the string table is
not empty, you can reference a string as an index into the string table section.
The first byte, which is index 0 (zero), contains a null character. Likewise, a
string table’s last byte contains a null character to ensure null termination for
all strings. A string whose index is 0 (zero) specifies either no name or a null
name, depending on the context.
A section header’s sh_name contains an index into the section header string
table (See the e_shstrndx field in “ELF Headers” on page 660). The
following figures show a string table with 25 bytes and the strings associated
with various indexes:
Index +0 +1 +2 +3 +4 +5 +6 +7 +8 +9
0 \0 n a m e . \0 V a r
10 i a b l e \0 a b l e
20 \0 \0 x x \0
A string table index may refer to any byte in the section. A string may appear
more than once; references to substrings may exist, and a single string may be
referenced multiple times. Strings that are not referenced are also allowed.
Program Headers
An ELF executable file’s program header table is an array of structures, each
describing a segment or other information the system needs to prepare the
program for execution. A file segment contains one or more sections. Program
headers are defined only for executable files. A file specifies its own program
header size with the ELF header’s e_phentsize and e_phnum.
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
p_type
The kind of segment this array element describes and how to interpret the array
element’s information. For more information, see “Program Types” on page 679.
p_offset
Offset from the beginning of the file at which the first byte of the segment resides.
p_vaddr
Address at which the first byte of the segment resides in memory.
p_paddr
This field is currently unused and is set to zero by the linker.
p_filesz
Number of bytes in the file image of the segment; it may be zero.
p_memsz
Number of bytes in the memory image of the segment; it may be zero.
p_flags
Flags relevant to the segment. For more information, see “Program Attribute
Flags” on page 680.
p_align
Loadable process segments must have congruent values for p_vaddr and
p_offset, modulo the page size. This field specifies the value to which the
segments are aligned in memory and in the file. Values 0 and 1 mean no
alignment is required. Otherwise, p_align should be a positive, integral power of
2, and p_vaddr should equal p_offset, modulo p_align.
Program Types
A program header’s p_type specifies the program’s semantics as follows:
Name Value Meaning
PT_NULL 0 The array element is unused; other member values
are undefined. This type lets the program header
table have ignored entries.
PT_LOAD 1 The array element specifies a loadable segment,
described by p_filesz and p_memsz. The bytes
from the file are mapped to the beginning of the
memory segment. If the segment’s memory size
(p_memsz) is larger than the file size (p_filesz),
the “extra” bytes are defined to hold the value 0
and to follow the segment’s initialized area. The
file size may not be larger than the memory size.
Loadable segment entries in the program header
table appear in ascending order, sorted on the
p_vaddr member.
PT_DYNAMIC 2 The array element specifies dynamic linking
information.
PT_INTERP 3 The array element specifies the location and size
of a null-terminated pathname to invoke as an
interpreter. This segment type is meaningful only
for executable files (though it may occur for shared
objects); it may not occur more than once in a file. If
it is present, it must precede any loadable segment
entry.
PT_NOTE 4 The array element specifies the location and size
of auxiliary information.
PT_SHLIB 5 This segment type is reserved but has unspecified
semantics.
For example, typical text segments have read and execute - but not write -
permissions. Data segments normally have read, write, and execute permissions.