[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you compile and link using the default options, the size of your application's code is limited to 32K. The 68000 DragonBall processor can only make a relative jump if it is of a distance of 32K or less, and you will get errors from the assembler and/or linker if your code attempts to jump further than that. The default size limit, enforced at link time, is such that it is possible to jump arbitrarily within a maximally sized code resource without risking attempting an impossibly long jump.
While the default is limited, it is certainly possible to create larger applications; the choices and issues involved are discussed in this chapter.
Also discussed are other types of projects: shared libraries and various flavours of stand-alone code resources, particularly HackMaster Hacks and Palm OS 5 armlets.
3.1 Size limitations for a single code resource 3.2 Multiple code resources ...and how to escape them. 3.3 Shared libraries Creating and using shared libraries. 3.4 Stand-alone code resources Hacks, armlets, etc.
Even though the processor is unable to make a relative jump directly between the extremities of a code section larger than 32K, it is still possible to use such a code section if you are willing to indulge in manual heroics to help the compiler avoid needing to make such an extreme function call.
Note that a code section corresponds to a code
resource in your
project's final Palm OS database, and the maximum size for any kind of
resource is still limited to approximately 64K by the Palm OS memory manager
and the HotSync protocol.
Some of the heroic techniques are:
foo_aux()
that just call the real function foo()
with the same arguments and which can be placed anywhere, thus effectively
giving each such foo()
two entry points and loosening the constraints
on the arrangement problem. Or use the assembly language equivalent of a
proxy function, which can avoid remarshalling the arguments and really be
a jump.
The maximum size of the main code section is specified in the linker
script and enforced during linking (see section `Linker Scripts' in Using ld). You can override the default script's
32K size by using a -T script
linker option in your link command.
Two suitable linker scripts, which can be used as is or copied and modified,
are already provided, both allowing a .text
section of up to
approximately 64K:
-T text_64k
-T text_64k_palmos3
There is, of course, some risk in going right up to the maximum resource
size limits. In practice, the limit has typically been increasing with
each new version of Palm OS, and has never decreased. Nonetheless, it may
be wise to use text_64k
even if you plan to target only Palm OS 3.0
and higher devices.
Theoretically, the heroics required to make functions calls over a distance of more than 32K are applicable for an arbitrarily large code resource. Unfortunately each resource is still limited to only 64K by the HotSync protocol, at least on Palm OS versions up to and including Palm OS 4.1. Thus the gain compared to a hassle-free 32K code resource is not great, and the best way to allow an application to increase beyond 32K of code is to allow it to have multiple separate code resources.
One simple technique for producing multiple code resources is to map
distinct GCC code sections into distinct Palm OS code resources. This
version of prc-tools implements a limited form of that: functions may
be marked as being in particular sections via the standard GCC
section
attribute (see section `Declaring Attributes of Functions' in Using and Porting GCC).
(These markings are used quite early in the compiler, so other ways of putting
functions into different sections, such as -ffunction-sections
and rearrangements at link time, don't work.)
A project definition file (see section 4. Definition files) must be used, with
a multiple code clause to inform build-prc
of the new sections.
You also need to define the pointer variables mentioned above in an
assembly language stub file linked into your executable, and should use
a linker script to place the new sections at appropriate addresses.
The easiest way to do these things is to use multigen
to generate
them from the same definition file clause (see section 6.2 multigen).
3.2.1 Multiple code resources and global data But especially without globals 3.2.2 Breaking up an existing application
The current implementation puts pointers to the code resources into the application's global data, and uses those pointers in the code emitted for each call in which the calling function and the called function are in different sections. This means that you must not attempt to call between different sections when globals are not available.
In particular, all functions in your application called while processing a
launch code that doesn't give you globals must be in the main code section.
This always includes PilotMain
, which is always called by the startup
code for all launch codes.
Read-only data, such as string literals and other constant data, are put into code sections rather than the global data section. This saves global data space, which is in short supply, and is valid since the data, just like the code resources that contain them, are read-only.
When an item of read-only data has file or global scope, it will be placed in the main code section. When it is local to a function, it will mostly, but not always, be placed in the same code section as that function.
GCC's optimizer will usually notice when a string literal (or other constant) is identical to one which has been previously emitted, and will reuse the storage previously emitted rather than reserving more space for a duplicate.
Thus, in the following example, when optimisation is on, the string literal
referenced from bar
may well be in the foosec
section, while
bar
itself is in the main code section:
const char *foo () __attribute__ ((section ("foosec"))); const char *foo () { return "hello world"; } const char *bar () { return "hello world"; } |
The code emitted for such a reference is similar to that emitted for an inter-section function call: when there is a data reference in which the referring function and the referenced item of read-only data are in different sections, the code emitted uses the item's code resource's pointer, which is located in the application's global data.
This means that you must ensure that this sort of reference doesn't occur when globals are not available. Because this compiler optimisation (of course) occurs only within a single translation unit, a sufficient (but not necessary) way to ensure this is by placing functions which are in different sections in different translation units (e.g., in separate `.c' files).
In particular, all read-only data referenced while processing a launch code
that doesn't give you globals must be in the main code section. (Thus, in
the example above, bar
is likely to crash if it is called during a
no-globals launch.)
This can be arranged in the following ways, amongst others:
const char greeting[] = "hello world"; const char *bar () { return greeting; } |
(When an item of read-only data is reused, it will have been placed in the same section as the function from which it was first referenced. Thus, if the functions are ordered as described, all read-only data referenced from the functions in the main code section will themselves be in the main code section. Any inter-section references to read-only data must then be from functions in other named code sections. But in order for such a function to have been called, globals must be available; hence the inter-section reference will be safe too.)
To use multiple code resources in an existing application, you need to do the following:
obj-res
, change it to use
build-prc
directly on your bfd executable. For example,
from an original
myapp.prc: code0000.myapp.grc ... build-prc ... *.myapp.grc ... code0000.myapp.grc: myapp m68k-palmos-obj-res myapp |
remove references to .grc files, and delete the obj-res rule altogether:
myapp.prc: myapp ... build-prc ... myapp ... |
#define EDIT_SECTION __attribute__ ((section ("editfns"))) void EditFormHandler (...) EDIT_SECTION; void DrawEditForm () EDIT_SECTION; |
Make very sure that the relevant annotated declaration is visible when you define such a function, and especially everywhere you call it. If there is a call to a non-default sectioned function from which the annotated declaration is not visible, the call will be generated as a call to the default code section. When such a call is executed, it jumps to effectively a random location in the wrong code section and almost certainly crashes. (Warning options which can detect these mistakes at compile time are noted in the discussion of required visibilities in 1.2 Function attributes.)
Note that COFF only stores eight character of a section name: if your section names are any longer than this, they will be truncated, leading to trouble.
multiple code { "editfns" } |
Or, if you're not already using a definition file, write one including such a clause and use it in your build-prc command:
myapp.prc: myapp.def myapp ... build-prc ... myapp.def myapp ... |
myapp-sections.o: myapp-sections.s m68k-palmos-gcc -c myapp-sections.s myapp-sections.s myapp-sections.ld: myapp.def m68k-palmos-multigen myapp.def |
OBJS = ...list of object files... myapp-sections.o myapp: $(OBJS) myapp-sections.ld m68k-palmos-gcc -o myapp $(OBJS) myapp-sections.ld |
(This section has not yet been written; see 6.3 stubgen, and also the library projects in the sample code collection.)
Normally build-prc processes a bfd executable as a full-blown executable,
converting its .data
, .bss
, and .text
and any other
code sections into the corresponding Palm OS resources, as appropriate.
However if the bfd executable contains certain sections that are special
to build-prc, its .text
section will be converted into a stand-alone
code resource instead, and the other sections listed above will be
discarded (producing warnings) if present.
These "special sections" are .disposn
(which is an abbreviation of
disposition) and .trap
. They are interpreted as follows:
.disposn
section, if present, specify the
generated resource's ID, while (if the section is at least six bytes in
length) the next four bytes specify its type. If the .disposn
section
is only two bytes in length, the generated resource's type will be a suitable
default dependent on the architecture of the bfd executable: code
for
68000 or armc
for ARM.
.trap
section, if present, are converted
into a TRAP
resource. If a .disposn
section is also present,
the TRAP
resource will have the ID specified by that section;
otherwise (when the project definition file specifies the Hack project kind),
TRAP
and code
resources converted from successive bfd executables
are numbered consecutively from 1000.
Note that these two-byte integer fields are interpreted according to the native endianness of the bfd executable in which they occur.
There is nothing special about compiling code that is to become stand-alone, other than that you must not use global data or any extra code resources, because stand-alone code, by definition, cannot have such things.
There are considerations at link time, related to the lack of startup code:
-nostartfiles
option (see section `Options for Linking' in Using and Porting GCC).
.text
section, build-prc will insert an appropriate jump instruction
at the start of the generated code resource. Thus a stand-alone code resource
can always be jumped to by jumping to its beginning.
You specify the entry point at link time: in short, it is a function named
start()
by default, or you can set it with the -e
option
(see section `Setting the entry point' in Using ld).
You can easily set up the special sections marking your code as stand-alone by using the following macros, provided in `Standalone.h':
STANDALONE_CODE_RESOURCE_ID (id)
STANDALONE_CODE_RESOURCE_TYPE_ID (type, id)
STANDALONE_CODE_RESOURCE_TYPESTR_ID (type, id)
...TYPE...
macro; if you use a string (`"TYPE"'),
use the ...TYPESTR...
version.
HACKMASTER_TRAP (vector)
TRAP
resource containing vector, which may be any C constant expression,
for example, a numeric constant or even a sysTrapfoo
constant
as defined in a Palm OS SDK's `CoreTraps.h'.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |