Making multiple-segment shared libraries
It's time for another installment of "things you probably should not do".
Today's request is about shared libraries. The current shared library implementation on Palm OS limits you to 64K of code space. What do you do when you want to make a larger shared library?
To figure this out, we need to look at how a shared library is setup. These are Palm resource databases of type 'libr' (defined as sysFileTLibrary in SystemResources.h). They must have a code resource also of type 'libr' with ID 0. This defines the install entry point.
When a library is installed, usually by SysLibLoad, Palm OS opens its resource database read-only, locks down the libr:0 resource, and jumps to the start of that resource block. The entry point is a function at the start of the resource of type
SysLibEntryProcPtr. The install routine gets a reference number and a pointer to a SysLibTblEntryType which will be associated with the library.
The install routine is responsible for setting the dispatchTblP field of the table entry to point to the library's dispatch table. The dispatch table is usually a read-only table stored in the libr:0 code resource. This table contains a list of offsets. The first entry is an offset from the start of the table to the name of the library, while the rest of the entries are offsets to small chunks of code that call other routines in the library. Shared libraries in CodeWarrior actually go through an extra jump due to limitations in the inline assembler. If you look at SampleLib (in the SDK examples) or at the wizard-generated dispatch source file in CW Palm 8, you will see this structure.
For a multi-segment shared library, you can allocate this jump table on the heap using MemPtrNew, follwed by a call to MemPtrSetOwner to change the chunks ownership to the system. Then, you could lock the other code segments into memory and populate the dispatch table with all of the function locations. You will probably need "sub-install" entry points in the other segments to find the function locations, since there is no good way to get linker offsets for other code segments at compile time.
Building a multi-segment library
CodeWarrior's normal build process only supports single segment shared libraries. If you pick the "Palm OS Code Resource" target type, you will only get the one code resource. To bundle additional code resources with that, you need a separate "Palm OS Application" target.
This shell application target will just have a single source file defining a function called __Startup__. This app will never be executed, it just exists to provide a resource container for the linker.
You also will need a Rez file to pull in the separately compiled code resources. You should have named each of the resources something like "libr0001.tmp". Then, you add a .r file with lines like:
include "libr0000.tmp";
include "libr0001.tmp";
include "libr0002.tmp";
These code resources will be pulled into the link. You should setup the Palm Rez PostLinker panel to have type 'libr', and when you build, you will get a shared library PRC file with all of your code resources, plus extra code and data resources that are not used.
This kind of library will be difficult to debug. CodeWarrior supports code segment debugging, but only single segments contained in their own PRC file. We're hoping to improve debugger support for this in the future; we'd also like to setup a standard methodology for implementing these, including a shared library runtime that handles many common tasks.

Send feedback to combee@techwood.org
Copyright © 2004 Benjamin L. Combee
Palm OS is a registered trademark of PalmSource, Inc.
Metrowerks and CodeWarrior are registered trademarks of Metrowerks Inc.
The views expressed on this website/weblog are those of mine alone and do not necessarily reflect the views of PalmSource or Metrowerks.

qwertYAK / frobnovich
|