mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
1179 lines
45 KiB
Plaintext
1179 lines
45 KiB
Plaintext
<!doctype linuxdoc system> <!-- -*- text-mode -*- -->
|
|
|
|
<article>
|
|
<title>ld65 Users Guide
|
|
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
|
|
|
<abstract>
|
|
The ld65 linker combines object files into an executable file. ld65 is highly
|
|
configurable and uses configuration files for high flexibility.
|
|
</abstract>
|
|
|
|
<!-- Table of contents -->
|
|
<toc>
|
|
|
|
<!-- Begin the document -->
|
|
|
|
<sect>Overview<p>
|
|
|
|
The ld65 linker combines several object modules created by the ca65
|
|
assembler, producing an executable file. The object modules may be read
|
|
from a library created by the ar65 archiver (this is somewhat faster and
|
|
more convenient). The linker was designed to be as flexible as possible.
|
|
It complements the features that are built into the ca65 macroassembler:
|
|
|
|
<itemize>
|
|
|
|
<item> Accept any number of segments to form an executable module.
|
|
|
|
<item> Resolve arbitrary expressions stored in the object files.
|
|
|
|
<item> In case of errors, use the meta information stored in the object files
|
|
to produce helpful error messages. In case of undefined symbols,
|
|
expression range errors, or symbol type mismatches, ld65 is able to
|
|
tell you the exact location in the original assembler source, where
|
|
the symbol was referenced.
|
|
|
|
<item> Flexible output. The output of ld65 is highly configurable by a config
|
|
file. Some more-common platforms are supported by default configurations
|
|
that may be activated by naming the target system. The output
|
|
generation was designed with different output formats in mind, so
|
|
adding other formats shouldn't be a great problem.
|
|
|
|
</itemize>
|
|
|
|
|
|
<sect>Usage<p>
|
|
|
|
|
|
<sect1>Command-line option overview<p>
|
|
|
|
The linker is called as follows:
|
|
|
|
<tscreen><verb>
|
|
---------------------------------------------------------------------------
|
|
Usage: ld65 [options] module ...
|
|
Short options:
|
|
-( Start a library group
|
|
-) End a library group
|
|
-C name Use linker config file
|
|
-D sym=val Define a symbol
|
|
-L path Specify a library search path
|
|
-Ln name Create a VICE label file
|
|
-S addr Set the default start address
|
|
-V Print the linker version
|
|
-h Help (this text)
|
|
-m name Create a map file
|
|
-o name Name the default output file
|
|
-t sys Set the target system
|
|
-u sym Force an import of symbol 'sym'
|
|
-v Verbose mode
|
|
-vm Verbose map file
|
|
|
|
Long options:
|
|
--cfg-path path Specify a config file search path
|
|
--config name Use linker config file
|
|
--dbgfile name Generate debug information
|
|
--define sym=val Define a symbol
|
|
--end-group End a library group
|
|
--force-import sym Force an import of symbol 'sym'
|
|
--help Help (this text)
|
|
--lib file Link this library
|
|
--lib-path path Specify a library search path
|
|
--mapfile name Create a map file
|
|
--module-id id Specify a module id
|
|
--obj file Link this object file
|
|
--obj-path path Specify an object file search path
|
|
--start-addr addr Set the default start address
|
|
--start-group Start a library group
|
|
--target sys Set the target system
|
|
--version Print the linker version
|
|
---------------------------------------------------------------------------
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>Command-line options in detail<p>
|
|
|
|
Here is a description of all of the command-line options:
|
|
|
|
<descrip>
|
|
|
|
<label id="option--start-group">
|
|
<tag><tt>-(, --start-group</tt></tag>
|
|
|
|
Start a library group. The libraries specified within a group are searched
|
|
multiple times to resolve crossreferences within the libraries. Normally,
|
|
crossreferences are resolved only within a library, that is the library is
|
|
searched multiple times. Libraries specified later on the command line
|
|
cannot reference otherwise unreferenced symbols in libraries specified
|
|
earlier, because the linker has already handled them. Library groups are
|
|
a solution for this problem, because the linker will search repeatedly
|
|
through all libraries specified in the group, until all possible open
|
|
symbol references have been satisfied.
|
|
|
|
|
|
<tag><tt>-), --end-group</tt></tag>
|
|
|
|
End a library group. See the explanation of the <tt><ref
|
|
id="option--start-group" name="--start-group"></tt> option.
|
|
|
|
|
|
<tag><tt>-h, --help</tt></tag>
|
|
|
|
Print the short option summary shown above.
|
|
|
|
|
|
<label id="option-m">
|
|
<tag><tt>-m name, --mapfile name</tt></tag>
|
|
|
|
This option (which needs an argument that will used as a filename for
|
|
the generated map file) will cause the linker to generate a map file.
|
|
The map file does contain a detailed overview over the modules used, the
|
|
sizes for the different segments, and a table containing exported
|
|
symbols.
|
|
|
|
|
|
<label id="option-o">
|
|
<tag><tt>-o name</tt></tag>
|
|
|
|
The -o switch is used to give the name of the default output file.
|
|
Depending on your output configuration, this name <em/might not/ be used as the
|
|
name for the output file. However, for the default configurations, this
|
|
name is used for the output file name.
|
|
|
|
|
|
<label id="option-t">
|
|
<tag><tt>-t sys, --target sys</tt></tag>
|
|
|
|
The argument for the -t switch is the name of the target system. Since this
|
|
switch will activate a default configuration, it may not be used together
|
|
with the <tt><ref id="option-C" name="-C"></tt> option. The following target
|
|
systems are currently supported:
|
|
|
|
<itemize>
|
|
<item>none
|
|
<item>module
|
|
<item>apple2
|
|
<item>apple2enh
|
|
<item>atari2600
|
|
<item>atari
|
|
<item>atarixl
|
|
<item>atmos
|
|
<item>c16 (works also for the c116 with memory up to 32K)
|
|
<item>c64
|
|
<item>c128
|
|
<item>cbm510 (CBM-II series with 40-column video)
|
|
<item>cbm610 (all CBM series-II computers with 80-column video)
|
|
<item>geos-apple
|
|
<item>geos-cbm
|
|
<item>lunix
|
|
<item>lynx
|
|
<item>nes
|
|
<item>pet (all CBM PET systems except the 2001)
|
|
<item>plus4
|
|
<item>sim6502
|
|
<item>sim65c02
|
|
<item>supervision
|
|
<item>telestrat
|
|
<item>vic20
|
|
</itemize>
|
|
|
|
There are a few more targets defined but neither of them is actually
|
|
supported.
|
|
|
|
|
|
<tag><tt>-u sym[:addrsize], --force-import sym[:addrsize]</tt></tag>
|
|
|
|
Force an import of a symbol. While object files are always linked to the
|
|
output file, regardless if there are any references, object modules from
|
|
libraries get only linked in if an import can be satisfied by this module.
|
|
The <tt/--force-import/ option may be used to add a reference to a symbol and
|
|
as a result force linkage of the module that exports the identifier.
|
|
|
|
The name of the symbol may optionally be followed by a colon and an address-size
|
|
specifier. If no address size is specified, the default address size
|
|
for the target machine is used.
|
|
|
|
Please note that the symbol name needs to have the internal representation,
|
|
meaning you have to prepend an underscore for C identifiers.
|
|
|
|
|
|
<label id="option-v">
|
|
<tag><tt>-v, --verbose</tt></tag>
|
|
|
|
Using the -v option, you may enable more output that may help you to
|
|
locate problems. If an undefined symbol is encountered, -v causes the
|
|
linker to print a detailed list of the references (that is, source file
|
|
and line) for this symbol.
|
|
|
|
|
|
<tag><tt>-vm</tt></tag>
|
|
|
|
Must be used in conjunction with <tt><ref id="option-m" name="-m"></tt>
|
|
(generate map file). Normally the map file will not include empty segments
|
|
and sections, or unreferenced symbols. Using this option, you can force the
|
|
linker to include all that information into the map file. Also, it will
|
|
include a second <tt/Exports/ list. The first list is sorted by name;
|
|
the second one is sorted by value.
|
|
|
|
|
|
<label id="option-C">
|
|
<tag><tt>-C</tt></tag>
|
|
|
|
This gives the name of an output config file to use. See section 4 for more
|
|
information about config files. -C may not be used together with <tt><ref
|
|
id="option-t" name="-t"></tt>.
|
|
|
|
|
|
<label id="option-D">
|
|
<tag><tt>-D sym=value, --define sym=value</tt></tag>
|
|
|
|
This option allows to define an external symbol on the command line. Value
|
|
may start with a '$' sign or with <tt/0x/ for hexadecimal values,
|
|
otherwise a leading zero denotes octal values. See also <ref
|
|
id="SYMBOLS" name="the SYMBOLS section"> in the configuration file.
|
|
|
|
|
|
<label id="option--lib-path">
|
|
<tag><tt>-L path, --lib-path path</tt></tag>
|
|
|
|
Specify a library search path. This option may be used more than once. It
|
|
adds a directory to the search path for library files. Libraries specified
|
|
without a path are searched in the current directory, in the list of
|
|
directories specified using <tt/--lib-path/, in directories given by
|
|
environment variables, and in a built-in default directory.
|
|
|
|
|
|
<tag><tt>-Ln</tt></tag>
|
|
|
|
This option allows you to create a file that contains all global labels and
|
|
may be loaded into the VICE emulator using the <tt/ll/ (load label) command
|
|
or into the Oricutron emulator using the <tt/sl/ (symbols load) command. You
|
|
may use this to debug your code with VICE. Note: Older versions had some
|
|
bugs in the label code. If you have problems, please get the latest <url
|
|
url="http://vice-emu.sourceforge.net" name="VICE"> version.
|
|
|
|
|
|
<label id="option-S">
|
|
<tag><tt>-S addr, --start-addr addr</tt></tag>
|
|
|
|
Using -S you may define the default starting address. If and how this
|
|
address is used depends on the config file in use. For the default
|
|
configurations, only the "none", "apple2" and "apple2enh" systems honor an
|
|
explicit start address, all other default configs provide their own.
|
|
|
|
|
|
<tag><tt>-V, --version</tt></tag>
|
|
|
|
This option prints the version number of the linker. If you send any
|
|
suggestions or bugfixes, please include this number.
|
|
|
|
|
|
<label id="option--cfg-path">
|
|
<tag><tt>--cfg-path path</tt></tag>
|
|
|
|
Specify a config file search path. This option may be used more than once.
|
|
It adds a directory to the search path for config files. A config file given
|
|
with the <tt><ref id="option-C" name="-C"></tt> option that has no path in
|
|
its name is searched in the current directory, in the list of directories
|
|
specified using <tt/--cfg-path/, in directories given by environment variables,
|
|
and in a built-in default directory.
|
|
|
|
|
|
<label id="option--dbgfile">
|
|
<tag><tt>--dbgfile name</tt></tag>
|
|
|
|
Specify an output file for debug information. Available information will be
|
|
written to this file. Using the <tt/-g/ option for the compiler and assembler
|
|
will increase the amount of information available. Please note that debug
|
|
information generation is currently being developed, so the format of the
|
|
file and its contents are subject to change without further notice.
|
|
|
|
|
|
<tag><tt>--lib file</tt></tag>
|
|
|
|
Links a library to the output. Use this command-line option instead of just
|
|
naming the library file, if the linker is not able to determine the file
|
|
type because of an unusual extension.
|
|
|
|
|
|
<tag><tt>--obj file</tt></tag>
|
|
|
|
Links an object file to the output. Use this command-line option instead
|
|
of just naming the object file, if the linker is not able to determine the
|
|
file type because of an unusual extension.
|
|
|
|
|
|
<label id="option--obj-path">
|
|
<tag><tt>--obj-path path</tt></tag>
|
|
|
|
Specify an object file search path. This option may be used more than once.
|
|
It adds a directory to the search path for object files. An object file
|
|
passed to the linker that has no path in its name is searched in the current
|
|
directory, in the list of directories specified using <tt/--obj-path/, in
|
|
directories given by environment variables, and in a built-in default directory.
|
|
|
|
</descrip>
|
|
|
|
|
|
|
|
<sect>Search paths<p>
|
|
|
|
Starting with version 2.10, there are now several search-path lists for files needed
|
|
by the linker: one for libraries, one for object files, and one for config
|
|
files.
|
|
|
|
|
|
<sect1>Library search path<p>
|
|
|
|
The library search-path list contains in this order:
|
|
|
|
<enum>
|
|
<item>The current directory.
|
|
<item>Any directory added with the <tt><ref id="option--lib-path"
|
|
name="--lib-path"></tt> option on the command line.
|
|
<item>The value of the environment variable <tt/LD65_LIB/ if it is defined.
|
|
<item>A subdirectory named <tt/lib/ of the directory defined in the environment
|
|
variable <tt/CC65_HOME/, if it is defined.
|
|
<item>An optionally compiled-in library path.
|
|
</enum>
|
|
|
|
|
|
<sect1>Object file search path<p>
|
|
|
|
The object file search-path list contains in this order:
|
|
|
|
<enum>
|
|
<item>The current directory.
|
|
<item>Any directory added with the <tt><ref id="option--obj-path"
|
|
name="--obj-path"></tt> option on the command line.
|
|
<item>The value of the environment variable <tt/LD65_OBJ/ if it is defined.
|
|
<item>A subdirectory named <tt/obj/ of the directory defined in the environment
|
|
variable <tt/CC65_HOME/, if it is defined.
|
|
<item>An optionally compiled-in directory.
|
|
</enum>
|
|
|
|
|
|
<sect1>Config file search path<p>
|
|
|
|
The config file search-path list contains in this order:
|
|
|
|
<enum>
|
|
<item>The current directory.
|
|
<item>Any directory added with the <tt><ref id="option--cfg-path"
|
|
name="--cfg-path"></tt> option on the command line.
|
|
<item>The value of the environment variable <tt/LD65_CFG/ if it is defined.
|
|
<item>A subdirectory named <tt/cfg/ of the directory defined in the environment
|
|
variable <tt/CC65_HOME/, if it is defined.
|
|
<item>An optionally compiled-in directory.
|
|
</enum>
|
|
|
|
|
|
|
|
<sect>Detailed workings<p>
|
|
|
|
The linker does several things when combining object modules:
|
|
|
|
First, the command line is parsed from left to right. For each object file
|
|
encountered (object files are recognized by a magic word in the header, so
|
|
the linker does not care about the name), imported and exported
|
|
identifiers are read from the file and inserted in a table. If a library
|
|
name is given (libraries are also recognized by a magic word, there are no
|
|
special naming conventions), all modules in the library are checked if an
|
|
export from this module would satisfy an import from other modules. All
|
|
modules where this is the case are marked. If duplicate identifiers are
|
|
found, the linker issues warnings.
|
|
|
|
That procedure (parsing and reading from left to right) does mean that a
|
|
library may only satisfy references for object modules (given directly or from
|
|
a library) named <em/before/ that library. With the command line
|
|
|
|
<tscreen><verb>
|
|
ld65 crt0.o clib.lib test.o
|
|
</verb></tscreen>
|
|
|
|
the module <tt/test.o/ must not contain references to modules in the library
|
|
<tt/clib.lib/. But, if it does, you have to change the order of the modules
|
|
on the command line:
|
|
|
|
<tscreen><verb>
|
|
ld65 crt0.o test.o clib.lib
|
|
</verb></tscreen>
|
|
|
|
Step two is, to read the configuration file, and assign start addresses
|
|
for the segments and define any linker symbols (see <ref id="config-files"
|
|
name="Configuration files">).
|
|
|
|
After that, the linker is ready to produce an output file. Before doing that,
|
|
it checks its data for consistency. That is, it checks for unresolved
|
|
externals (if the output format is not relocatable) and for symbol type
|
|
mismatches (for example a zero-page symbol is imported by a module as an absolute
|
|
symbol).
|
|
|
|
Step four is, to write the actual target files. In this step, the linker will
|
|
resolve any expressions contained in the segment data. Circular references are
|
|
also detected in this step (a symbol may have a circular reference that goes
|
|
unnoticed if the symbol is not used).
|
|
|
|
Step five is to output a map file with a detailed list of all modules,
|
|
segments and symbols encountered.
|
|
|
|
And, last step, if you give the <tt><ref id="option-v" name="-v"></tt> switch
|
|
twice, you get a dump of the segment data. However, this may be quite
|
|
unreadable if you're not a developer. :-)
|
|
|
|
|
|
|
|
<sect>Configuration files<label id="config-files"><p>
|
|
|
|
Configuration files are used to describe the layout of the output file(s). Two
|
|
major topics are covered in a config file: The memory layout of the target
|
|
architecture, and the assignment of segments to memory areas. In addition,
|
|
several other attributes may be specified.
|
|
|
|
Case is ignored for keywords, that is, section or attribute names, but it is
|
|
<em/not/ ignored for names and strings.
|
|
|
|
|
|
|
|
<sect1>Memory areas<p>
|
|
|
|
Memory areas are specified in a <tt/MEMORY/ section. Let's have a look at an
|
|
example (this one describes the usable memory layout of the C64):
|
|
|
|
<tscreen><verb>
|
|
MEMORY {
|
|
RAM1: start = $0800, size = $9800;
|
|
ROM1: start = $A000, size = $2000;
|
|
RAM2: start = $C000, size = $1000;
|
|
ROM2: start = $E000, size = $2000;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
As you can see, there are two RAM areas and two ROM areas. The names
|
|
(before the colon) are arbitrary names that must start with a letter, with
|
|
the remaining characters being letters or digits. The names of the memory
|
|
areas are used when assigning segments. As mentioned above, case is
|
|
significant for those names.
|
|
|
|
The syntax above is used in all sections of the config file. The name
|
|
(<tt/ROM1/ etc.) is said to be an identifier, the remaining tokens up to the
|
|
semicolon specify attributes for this identifier. You may use the equal sign
|
|
to assign values to attributes, and you may use a comma to separate
|
|
attributes, you may also leave both out. But you <em/must/ use a semicolon to
|
|
mark the end of the attributes for one identifier. The section above may also
|
|
have looked like this:
|
|
|
|
<tscreen><verb>
|
|
# Start of memory section
|
|
MEMORY
|
|
{
|
|
RAM1:
|
|
start $0800
|
|
size $9800;
|
|
ROM1:
|
|
start $A000
|
|
size $2000;
|
|
RAM2:
|
|
start $C000
|
|
size $1000;
|
|
ROM2:
|
|
start $E000
|
|
size $2000;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
There are of course more attributes for a memory section than just start and
|
|
size. Start and size are mandatory attributes, that means, each memory area
|
|
defined <em/must/ have these attributes given (the linker will check that). I
|
|
will cover other attributes later. As you may have noticed, I've used a
|
|
comment in the example above. Comments start with a hash mark ('#'), the
|
|
remainder of the line is ignored if this character is found.
|
|
|
|
|
|
<sect1>Segments<p>
|
|
|
|
Let's assume you have written a program for your trusty old C64, and you would
|
|
like to run it. For testing purposes, it should run in the <tt/RAM/ area. So
|
|
we will start to assign segments to memory sections in the <tt/SEGMENTS/
|
|
section:
|
|
|
|
<tscreen><verb>
|
|
SEGMENTS {
|
|
CODE: load = RAM1, type = ro;
|
|
RODATA: load = RAM1, type = ro;
|
|
DATA: load = RAM1, type = rw;
|
|
BSS: load = RAM1, type = bss, define = yes;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
What we are doing here is telling the linker, that all segments go into the
|
|
<tt/RAM1/ memory area in the order specified in the <tt/SEGMENTS/ section. So
|
|
the linker will first write the <tt/CODE/ segment, then the <tt/RODATA/
|
|
segment, then the <tt/DATA/ segment - but it will not write the <tt/BSS/
|
|
segment. Why? Here enters the segment type: For each segment specified, you may also
|
|
specify a segment attribute. There are five possible segment attributes:
|
|
|
|
<tscreen><verb>
|
|
ro means readonly
|
|
rw means read/write
|
|
bss means that this is an uninitialized segment
|
|
zp a zeropage segment
|
|
overwrite a segment that overwrites (parts of) another one
|
|
|
|
</verb></tscreen>
|
|
|
|
So, because we specified that the segment with the name BSS is of type bss,
|
|
the linker knows that this is uninitialized data, and will not write it to an
|
|
output file. This is an important point: For the assembler, the <tt/BSS/
|
|
segment has no special meaning. You specify, which segments have the bss
|
|
attribute when linking. This approach is much more flexible than having one
|
|
fixed bss segment, and is a result of the design decision to supporting an
|
|
arbitrary segment count.
|
|
|
|
If you specify "<tt/type = bss/" for a segment, the linker will make sure that
|
|
this segment does only contain uninitialized data (that is, zeroes), and issue
|
|
a warning if this is not the case.
|
|
|
|
For a <tt/bss/ type segment to be useful, it must be cleared somehow by your
|
|
program (this happens usually in the startup code - for example the startup
|
|
code for cc65-generated programs takes care about that). But how does your
|
|
code know, where the segment starts, and how big it is? The linker is able to
|
|
give that information, but you must request it. This is, what we're doing with
|
|
the "<tt/define = yes/" attribute in the <tt/BSS/ definitions. For each
|
|
segment, where this attribute is true, the linker will export three symbols.
|
|
|
|
<tscreen><verb>
|
|
__NAME_LOAD__ This is set to the address where the
|
|
segment is loaded.
|
|
__NAME_RUN__ This is set to the run address of the
|
|
segment. We will cover run addresses
|
|
later.
|
|
__NAME_SIZE__ This is set to the segment size.
|
|
</verb></tscreen>
|
|
|
|
Replace <tt/NAME/ by the name of the segment, in the example above, this would
|
|
be <tt/BSS/. These symbols may be accessed by your code.
|
|
|
|
Now, as we've configured the linker to write the first three segments and
|
|
create symbols for the last one, there's only one question left: Where does
|
|
the linker put the data? It would be very convenient to have the data in a
|
|
file, wouldn't it?
|
|
|
|
<sect1>Output files<p>
|
|
|
|
We don't have any files specified above, and indeed, this is not needed in a
|
|
simple configuration like the one above. There is an additional attribute
|
|
"file" that may be specified for a memory area, that gives a file name to
|
|
write the area data into. If there is no file name given, the linker will
|
|
assign the default file name. This is "a.out" or the one given with the
|
|
<tt><ref id="option-o" name="-o"></tt> option on the command line. Since the
|
|
default behaviour is OK for our purposes, I did not use the attribute in the
|
|
example above. Let's have a look at it now.
|
|
|
|
The "file" attribute (the keyword may also be written as "FILE" if you like
|
|
that better) takes a string enclosed in double quotes ('&dquot;') that specifies the
|
|
file, where the data is written. You may specify the same file several times,
|
|
in that case the data for all memory areas having this file name is written
|
|
into this file, in the order of the memory areas defined in the <tt/MEMORY/
|
|
section. Let's specify some file names in the <tt/MEMORY/ section used above:
|
|
|
|
<tscreen><verb>
|
|
MEMORY {
|
|
RAM1: start = $0800, size = $9800, file = %O;
|
|
ROM1: start = $A000, size = $2000, file = "rom1.bin";
|
|
RAM2: start = $C000, size = $1000, file = %O;
|
|
ROM2: start = $E000, size = $2000, file = "rom2.bin";
|
|
}
|
|
</verb></tscreen>
|
|
|
|
The <tt/%O/ used here is a way to specify the default behaviour explicitly:
|
|
<tt/%O/ is replaced by a string (including the quotes) that contains the
|
|
default output name, that is, "a.out" or the name specified with the <tt><ref
|
|
id="option-o" name="-o"></tt> option on the command line. Into this file, the
|
|
linker will first write any segments that go into <tt/RAM1/, and will append
|
|
then the segments for <tt/RAM2/, because the memory areas are given in this
|
|
order. So, for the RAM areas, nothing has really changed.
|
|
|
|
We've not used the ROM areas, but we will do that below, so we give the file
|
|
names here. Segments that go into <tt/ROM1/ will be written to a file named
|
|
"rom1.bin", and segments that go into <tt/ROM2/ will be written to a file
|
|
named "rom2.bin". The name given on the command line is ignored in both cases.
|
|
|
|
Assigning an empty file name for a memory area will discard the data written
|
|
to it. This is useful, if the memory area has segments assigned that are empty
|
|
(for example because they are of type bss). In that case, the linker will
|
|
create an empty output file. This may be suppressed by assigning an empty file
|
|
name to that memory area.
|
|
|
|
The <tt/%O/ sequence is also allowed inside a string. So using
|
|
|
|
<tscreen><verb>
|
|
MEMORY {
|
|
ROM1: start = $A000, size = $2000, file = "%O-1.bin";
|
|
ROM2: start = $E000, size = $2000, file = "%O-2.bin";
|
|
}
|
|
</verb></tscreen>
|
|
|
|
would write two files that start with the name of the output file specified on
|
|
the command line, with "-1.bin" and "-2.bin" appended respectively. Because
|
|
'%' is used as an escape char, the sequence "%%" has to be used if a single
|
|
percent sign is required.
|
|
|
|
<sect1>OVERWRITE segments<p>
|
|
|
|
There are situations when you may wish to overwrite some part (or parts) of a
|
|
segment with another one. Perhaps you are modifying an OS ROM that has its
|
|
public subroutines at fixed, well-known addresses, and you want to prevent them
|
|
from shifting to other locations in memory if your changed code takes less
|
|
space. Or you are updating a block of code available in binary-only form with
|
|
fixes that are scattered in various places. Generally, whenever you want to
|
|
minimize disturbance to an existing code brought on by your updates, OVERWRITE
|
|
segments are worth considering.
|
|
|
|
Here is an example:
|
|
|
|
<tscreen><verb>
|
|
MEMORY {
|
|
RAM: file = "", start = $6000, size = $2000, type=rw;
|
|
ROM: file = %O, start = $8000, size = $8000, type=ro;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
Nothing unusual so far, just two memory blocks - one RAM, one ROM. Now let's
|
|
look at the segment configuration:
|
|
|
|
<tscreen><verb>
|
|
SEGMENTS {
|
|
RAM: load = RAM, type = bss;
|
|
ORIGINAL: load = ROM, type = ro;
|
|
FASTCOPY: load = ROM, start=$9000, type = overwrite;
|
|
JMPPATCH1: load = ROM, start=$f7e8, type = overwrite;
|
|
DEBUG: load = ROM, start=$8000, type = overwrite;
|
|
VERSION: load = ROM, start=$e5b7, type = overwrite;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
Segment named ORIGINAL contains the original code, disassembled or provided in
|
|
a binary form (i.e. using <tt/.INCBIN/ directive; see the <tt/ca65/ assembler
|
|
document). Subsequent four segments will be relocated to addresses specified
|
|
by their "start" attributes ("offset" can also be used) and then will overwrite
|
|
whatever was at these locations in the ORIGINAL segment. In the end, resulting
|
|
binary output file will thus contain original data with the exception of four
|
|
sequences starting at $9000, $f7e8, $8000 and $e5b7, which will sport code from
|
|
their respective segments. How long these sequences will be depends on the
|
|
lengths of corresponding segments - they can even overlap, so think what you're
|
|
doing.
|
|
|
|
Finally, note that OVERWRITE segments should be the final segments loaded to a
|
|
particular memory area, and that they need at least one of "start" or "offset"
|
|
attributes specified.
|
|
|
|
<sect1>LOAD and RUN addresses (ROMable code)<p>
|
|
|
|
Let us look now at a more complex example. Say, you've successfully tested
|
|
your new "Super Operating System" (SOS for short) for the C64, and you
|
|
will now go and replace the ROMs by your own code. When doing that, you
|
|
face a new problem: If the code runs in RAM, we need not to care about
|
|
read/write data. But now, if the code is in ROM, we must care about it.
|
|
Remember the default segments (you may of course specify your own):
|
|
|
|
<tscreen><verb>
|
|
CODE read-only code
|
|
RODATA read-only data
|
|
DATA read/write data
|
|
BSS uninitialized data, read/write
|
|
</verb></tscreen>
|
|
|
|
Since <tt/BSS/ is not initialized, we must not care about it now, but what
|
|
about <tt/DATA/? <tt/DATA/ contains initialized data, that is, data that was
|
|
explicitly assigned a value. And your program will rely on these values on
|
|
startup. Since there's no way to remember the contents of the data segment,
|
|
other than storing it into one of the ROMs, we have to put it there. But
|
|
unfortunately, ROM is not writable, so we have to copy it into RAM before
|
|
running the actual code.
|
|
|
|
The linker won't copy the data from ROM into RAM for you (this must be done by
|
|
the startup code of your program), but it has some features that will help you
|
|
in this process.
|
|
|
|
First, you may not only specify a "<tt/load/" attribute for a segment, but
|
|
also a "<tt/run/" attribute. The "<tt/load/" attribute is mandatory, and, if
|
|
you don't specify a "<tt/run/" attribute, the linker assumes that load area
|
|
and run area are the same. We will use this feature for our data area:
|
|
|
|
<tscreen><verb>
|
|
SEGMENTS {
|
|
CODE: load = ROM1, type = ro;
|
|
RODATA: load = ROM2, type = ro;
|
|
DATA: load = ROM2, run = RAM2, type = rw, define = yes;
|
|
BSS: load = RAM2, type = bss, define = yes;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
Let's have a closer look at this <tt/SEGMENTS/ section. We specify that the
|
|
<tt/CODE/ segment goes into <tt/ROM1/ (the one at $A000). The readonly data
|
|
goes into <tt/ROM2/. Read/write data will be loaded into <tt/ROM2/ but is run
|
|
in <tt/RAM2/. That means that all references to labels in the <tt/DATA/
|
|
segment are relocated to be in <tt/RAM2/, but the segment is written to
|
|
<tt/ROM2/. All your startup code has to do is, to copy the data from its
|
|
location in <tt/ROM2/ to the final location in <tt/RAM2/.
|
|
|
|
So, how do you know, where the data is located? This is the second point,
|
|
where you get help from the linker. Remember the "<tt/define/" attribute?
|
|
Since we have set this attribute to true, the linker will define three
|
|
external symbols for the data segment that may be accessed from your code:
|
|
|
|
<tscreen><verb>
|
|
__DATA_LOAD__ This is set to the address where the segment
|
|
is loaded, in this case, it is an address in
|
|
ROM2.
|
|
__DATA_RUN__ This is set to the run address of the segment,
|
|
in this case, it is an address in RAM2.
|
|
__DATA_SIZE__ This is set to the segment size.
|
|
</verb></tscreen>
|
|
|
|
So, what your startup code must do, is to copy <tt/__DATA_SIZE__/ bytes from
|
|
<tt/__DATA_LOAD__/ to <tt/__DATA_RUN__/ before any other routines are called.
|
|
All references to labels in the <tt/DATA/ segment are relocated to <tt/RAM2/
|
|
by the linker, so things will work properly.
|
|
|
|
There's a library subroutine called <tt/copydata/ (in a module named
|
|
<tt/copydata.s/) that might be used to do actual copying. Be sure to have a
|
|
look at it's inner workings before using it!
|
|
|
|
|
|
<sect1>Other MEMORY area attributes<p>
|
|
|
|
There are some other attributes not covered above. Before starting the
|
|
reference section, I will discuss the remaining things here.
|
|
|
|
You may request symbols definitions also for memory areas. This may be
|
|
useful for things like a software stack, or an I/O area.
|
|
|
|
<tscreen><verb>
|
|
MEMORY {
|
|
STACK: start = $C000, size = $1000, define = yes;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
This will define some external symbols that may be used in your code:
|
|
|
|
<tscreen><verb>
|
|
__STACK_START__ This is set to the start of the memory
|
|
area, $C000 in this example.
|
|
__STACK_SIZE__ The size of the area, here $1000.
|
|
__STACK_LAST__ This is NOT the same as START+SIZE.
|
|
Instead, it is defined as the first
|
|
address that is not used by data. If we
|
|
don't define any segments for this area,
|
|
the value will be the same as START.
|
|
__STACK_FILEOFFS__ The binary offset in the output file. This
|
|
is not defined for relocatable output file
|
|
formats (o65).
|
|
</verb></tscreen>
|
|
|
|
A memory section may also have a type. Valid types are
|
|
|
|
<tscreen><verb>
|
|
ro for readonly memory
|
|
rw for read/write memory.
|
|
</verb></tscreen>
|
|
|
|
The linker will assure, that no segment marked as read/write or bss is put
|
|
into a memory area that is marked as readonly.
|
|
|
|
Unused memory in a memory area may be filled. Use the "<tt/fill = yes/"
|
|
attribute to request this. The default value to fill unused space is zero. If
|
|
you don't like this, you may specify a byte value that is used to fill these
|
|
areas with the "<tt/fillval/" attribute. If there is no "<tt/fillval/"
|
|
attribute for the segment, the "<tt/fillval/" attribute of the memory area (or
|
|
its default) is used instead. This means that the value may also be used to
|
|
fill unfilled areas generated by the assembler's <tt/.ALIGN/ and <tt/.RES/
|
|
directives.
|
|
|
|
The symbol <tt/%S/ may be used to access the default start address (that is,
|
|
the one defined in <ref id="FEATURES" name="the FEATURES section">, or the
|
|
value given on the command line with the <tt><ref id="option-S" name="-S"></tt>
|
|
option).
|
|
|
|
To support systems with banked memory, a special attribute named <tt/bank/ is
|
|
available. The attribute value is an arbitrary 32-bit integer. The assembler
|
|
has a builtin function named <tt/.BANK/ which may be used with an argument
|
|
that has a segment reference (for example a symbol). The result of this
|
|
function is the value of the bank attribute for the run memory area of the
|
|
segment.
|
|
|
|
|
|
<sect1>Other SEGMENT attributes<p>
|
|
|
|
Segments may be aligned to some memory boundary. Specify "<tt/align = num/" to
|
|
request this feature. Num must be a power of two. To align all segments on a
|
|
page boundary, use
|
|
|
|
<tscreen><verb>
|
|
SEGMENTS {
|
|
CODE: load = ROM1, type = ro, align = $100;
|
|
RODATA: load = ROM2, type = ro, align = $100;
|
|
DATA: load = ROM2, run = RAM2, type = rw, define = yes,
|
|
align = $100;
|
|
BSS: load = RAM2, type = bss, define = yes, align = $100;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
If an alignment is requested, the linker will add enough space to the output
|
|
file, so that the new segment starts at an address that is dividable by the
|
|
given number without a remainder. All addresses are adjusted accordingly. To
|
|
fill the unused space, bytes of zero are used, or, if the memory area has a
|
|
"<tt/fillval/" attribute, that value. Alignment is always needed, if you have
|
|
used the <tt/.ALIGN/ command in the assembler. The alignment of a segment
|
|
must be equal or greater than the alignment used in the <tt/.ALIGN/ command.
|
|
The linker will check that, and issue a warning, if the alignment of a segment
|
|
is lower than the alignment requested in an <tt/.ALIGN/ command of one of the
|
|
modules making up this segment.
|
|
|
|
For a given segment you may also specify a fixed offset into a memory area or
|
|
a fixed start address. Use this if you want the code to run at a specific
|
|
address (a prominent case is the interrupt vector table which must go at
|
|
address $FFFA). Only one of <tt/ALIGN/ or <tt/OFFSET/ or <tt/START/ may be
|
|
specified. If the directive creates empty space, it will be filled with zero,
|
|
of with the value specified with the "<tt/fillval/" attribute if one is given.
|
|
The linker will warn you if it is not possible to put the code at the
|
|
specified offset (this may happen if other segments in this area are too
|
|
large). Here's an example:
|
|
|
|
<tscreen><verb>
|
|
SEGMENTS {
|
|
VECTORS: load = ROM2, type = ro, start = $FFFA;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
or (for the segment definitions from above)
|
|
|
|
<tscreen><verb>
|
|
SEGMENTS {
|
|
VECTORS: load = ROM2, type = ro, offset = $1FFA;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
The "<tt/align/", "<tt/start/" and "<tt/offset/" attributes change placement
|
|
of the segment in the run memory area, because this is what is usually
|
|
desired. If load and run memory areas are equal (which is the case if only the
|
|
load memory area has been specified), the attributes will also work. There is
|
|
also an "<tt/align_load/" attribute that may be used to align the start of the
|
|
segment in the load memory area, in case different load and run areas have
|
|
been specified. There are no special attributes to set start or offset for
|
|
just the load memory area.
|
|
|
|
A "<tt/fillval/" attribute may not only be specified for a memory area, but
|
|
also for a segment. The value must be an integer between 0 and 255. It is used
|
|
as the fill value for space reserved by the assembler's <tt/.ALIGN/ and <tt/.RES/
|
|
commands. It is also used as the fill value for space between sections (part of a
|
|
segment that comes from one object file) caused by alignment, but not for
|
|
space that preceeds the first section.
|
|
|
|
To suppress the warning, the linker issues if it encounters a segment that is
|
|
not found in any of the input files, use "<tt/optional=yes/" as an additional
|
|
segment attribute. Be careful when using this attribute, because a missing
|
|
segment may be a sign of a problem, and if you're suppressing the warning,
|
|
there is no one left to tell you about it.
|
|
|
|
<sect1>The FILES section<p>
|
|
|
|
The <tt/FILES/ section is used to support other formats than straight binary
|
|
(which is the default, so binary output files do not need an explicit entry
|
|
in the <tt/FILES/ section).
|
|
|
|
The <tt/FILES/ section lists output files and as only attribute the format of
|
|
each output file. Assigning binary format to the default output file would
|
|
look like this:
|
|
|
|
<tscreen><verb>
|
|
FILES {
|
|
%O: format = bin;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
There are two other available formats, one is the o65 format specified by Andre
|
|
Fachat (see the <url url="http://www.6502.org/users/andre/o65/fileformat.html"
|
|
name="6502 binary relocation format specification">). It is defined like this:
|
|
|
|
<tscreen><verb>
|
|
FILES {
|
|
%O: format = o65;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
The other format available is the Atari (xex) segmented file format, this is
|
|
the standard format used by Atari DOS 2.0 and upward file managers in the Atari
|
|
8-bit computers, and it is defined like this:
|
|
|
|
<tscreen><verb>
|
|
FILES {
|
|
%O: format = atari;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
In the Atari segmented file format, the linker will write each <tt/MEMORY/ area
|
|
as a new segment, including a header with the start and end address.
|
|
|
|
The necessary o65 or Atari attributes are defined in a special section labeled
|
|
<ref id="FORMAT" name="FORMAT">.
|
|
|
|
|
|
|
|
<sect1>The FORMAT section<label id="FORMAT"><p>
|
|
|
|
The <tt/FORMAT/ section is used to describe file formats. The default (binary)
|
|
format has currently no attributes, so, while it may be listed in this
|
|
section, the attribute list is empty. The second supported format,
|
|
<url url="http://www.6502.org/users/andre/o65/fileformat.html" name="o65">,
|
|
has several attributes that may be defined here.
|
|
|
|
<tscreen><verb>
|
|
FORMATS {
|
|
o65: os = lunix, version = 0, type = small,
|
|
import = LUNIXKERNEL,
|
|
export = _main;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
The Atari file format has two attributes:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt>RUNAD = symbol</tt></tag>
|
|
|
|
Specify a symbol as the run address of the binary, the loader will call this
|
|
address after all the file is loaded in memory. If the attribute is omitted,
|
|
no run address is included in the file.
|
|
|
|
<tag><tt>INITAD = memory_area : symbol</tt></tag>
|
|
|
|
Specify a symbol as the initialization address for the given memory area.
|
|
The binary loader will call this address just after the memory area is loaded
|
|
into memory, before continuing loading the rest of the file.
|
|
|
|
</descrip>
|
|
|
|
|
|
<tscreen><verb>
|
|
FORMATS {
|
|
atari: runad = _start;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
|
|
<sect1>The FEATURES section<label id="FEATURES"><p>
|
|
|
|
In addition to the <tt/MEMORY/ and <tt/SEGMENTS/ sections described above, the
|
|
linker has features that may be enabled by an additional section labeled
|
|
<tt/FEATURES/.
|
|
|
|
|
|
<sect2>The CONDES feature<p>
|
|
|
|
<tt/CONDES/ is used to tell the linker to emit module constructor/destructor
|
|
tables.
|
|
|
|
<tscreen><verb>
|
|
FEATURES {
|
|
CONDES: segment = RODATA,
|
|
type = constructor,
|
|
label = __CONSTRUCTOR_TABLE__,
|
|
count = __CONSTRUCTOR_COUNT__;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
The <tt/CONDES/ feature has several attributes:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt>segment</tt></tag>
|
|
|
|
This attribute tells the linker into which segment the table should be
|
|
placed. If the segment does not exist, it is created.
|
|
|
|
|
|
<tag><tt>type</tt></tag>
|
|
|
|
Describes the type of the routines to place in the table. Type may be one of
|
|
the predefined types <tt/constructor/, <tt/destructor/, <tt/interruptor/, or
|
|
a numeric value between 0 and 6.
|
|
|
|
|
|
<tag><tt>label</tt></tag>
|
|
|
|
This specifies the label to use for the table. The label points to the start
|
|
of the table in memory and may be used from within user-written code.
|
|
|
|
|
|
<tag><tt>count</tt></tag>
|
|
|
|
This is an optional attribute. If specified, an additional symbol is defined
|
|
by the linker using the given name. The value of this symbol is the number
|
|
of entries (<em/not/ bytes) in the table. While this attribute is optional,
|
|
it is often useful to define it.
|
|
|
|
|
|
<tag><tt>order</tt></tag>
|
|
|
|
An optional attribute that takes one of the keywords <tt/increasing/ or
|
|
<tt/decreasing/ as an argument. Specifies the sorting order of the entries
|
|
within the table. The default is <tt/increasing/, which means that the
|
|
entries are sorted with increasing priority (the first entry has the lowest
|
|
priority). "Priority" is the priority specified when declaring a symbol as
|
|
<tt/.CONDES/ with the assembler, higher values mean higher priority. You may
|
|
change this behaviour by specifying <tt/decreasing/ as the argument, the
|
|
order of entries is reversed in this case.
|
|
|
|
Please note that the order of entries with equal priority is undefined.
|
|
|
|
<tag><tt>import</tt></tag>
|
|
|
|
This attribute defines a valid symbol name, that is added as an import
|
|
to the modules defining a constructor/destructor of the given type.
|
|
This can be used to force linkage of a module if this module exports the
|
|
requested symbol.
|
|
|
|
</descrip>
|
|
|
|
Without specifying the <tt/CONDES/ feature, the linker will not create any
|
|
tables, even if there are <tt/condes/ entries in the object files.
|
|
|
|
For more information see the <tt/.CONDES/ command in the <url
|
|
url="ca65.html" name="ca65 manual">.
|
|
|
|
|
|
<sect2>The STARTADDRESS feature<p>
|
|
|
|
<tt/STARTADDRESS/ is used to set the default value for the start address,
|
|
which can be referenced by the <tt/%S/ symbol. The builtin default for the
|
|
linker is $200.
|
|
|
|
<tscreen><verb>
|
|
FEATURES {
|
|
# Default start address is $1000
|
|
STARTADDRESS: default = $1000;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
Please note that order is important: The default start address must be defined
|
|
<em/before/ the <tt/%S/ symbol is used in the config file. This does usually
|
|
mean, that the <tt/FEATURES/ section has to go to the top of the config file.
|
|
|
|
|
|
|
|
<sect1>The SYMBOLS section<label id="SYMBOLS"><p>
|
|
|
|
The configuration file may also be used to define symbols used in the link
|
|
stage or to force symbols imports. This is done in the SYMBOLS section. The
|
|
symbol name is followed by a colon and symbol attributes.
|
|
|
|
The following symbol attributes are supported:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt>addrsize</tt></tag>
|
|
|
|
The <tt/addrsize/ attribute specifies the address size of the symbol and
|
|
may be one of
|
|
<itemize>
|
|
<item><tt/zp/, <tt/zeropage/ or <tt/direct/
|
|
<item><tt/abs/, <tt/absolute/ or <tt/near/
|
|
<item><tt/far/
|
|
<item><tt/long/ or <tt/dword/.
|
|
</itemize>
|
|
|
|
Without this attribute, the default address size is <tt/abs/.
|
|
|
|
<tag><tt>type</tt></tag>
|
|
|
|
This attribute is mandatory. Its value is one of <tt/export/, <tt/import/ or
|
|
<tt/weak/. <tt/export/ means that the symbol is defined and exported from
|
|
the linker config. <tt/import/ means that an import is generated for this
|
|
symbol, eventually forcing a module that exports this symbol to be included
|
|
in the output. <tt/weak/ is similar as <tt/export/. However, the symbol is
|
|
only defined if it is not defined elsewhere.
|
|
|
|
<tag><tt>value</tt></tag>
|
|
|
|
This must only be given for symbols of type <tt/export/ or <tt/weak/. It
|
|
defines the value of the symbol and may be an expression.
|
|
|
|
</descrip>
|
|
|
|
The following example defines the stack size for an application, but allows
|
|
the programmer to override the value by specifying <tt/--define
|
|
__STACKSIZE__=xxx/ on the command line.
|
|
|
|
<tscreen><verb>
|
|
SYMBOLS {
|
|
# Define the stack size for the application
|
|
__STACKSIZE__: type = weak, value = $800;
|
|
}
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
<sect>Special segments<p>
|
|
|
|
The builtin config files do contain segments that have a special meaning for
|
|
the compiler and the libraries that come with it. If you replace the builtin
|
|
config files, you will need the following information.
|
|
|
|
<sect1>ONCE<p>
|
|
|
|
The ONCE segment is used for initialization code run only once before
|
|
execution reaches main() - provided that the program runs in RAM. You
|
|
may for example add the ONCE segment to the heap in really memory
|
|
constrained systems.
|
|
|
|
<sect1>LOWCODE<p>
|
|
|
|
For the LOWCODE segment, it is guaranteed that it won't be banked out, so it
|
|
is reachable at any time by interrupt handlers or similar.
|
|
|
|
<sect1>STARTUP<p>
|
|
|
|
This segment contains the startup code which initializes the C software stack
|
|
and the libraries. It is placed in its own segment because it needs to be
|
|
loaded at the lowest possible program address on several platforms.
|
|
|
|
<sect1>ZPSAVE<p>
|
|
|
|
The ZPSAVE segment contains the original values of the zeropage locations used
|
|
by the ZEROPAGE segment. It is placed in its own segment because it must not be
|
|
initialized.
|
|
|
|
|
|
|
|
<sect>Copyright<p>
|
|
|
|
ld65 (and all cc65 binutils) are (C) Copyright 1998-2005 Ullrich von
|
|
Bassewitz. For usage of the binaries and/or sources the following
|
|
conditions do apply:
|
|
|
|
This software is provided 'as-is', without any expressed or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
<enum>
|
|
<item> The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
<item> Altered source versions must be plainly marked as such, and must not
|
|
be misrepresented as being the original software.
|
|
<item> This notice may not be removed or altered from any source
|
|
distribution.
|
|
</enum>
|
|
|
|
|
|
|
|
</article>
|