Lutz Vieweg's

CLLD

The linker for gcc-compiled programs on the HP48

1.	Purpose

clld links object-files and libraries created by itself or class, and creates executable binaries or 
shared libraries. This is what linkers on any architecture usually do :^)

2.	Design goals

The HP48 is a handheld computer, that is, in comparison to most non-handheld-computers, both 
slow and limited in terms of maximum memory-size. So the main goals for me when I wrote clld 
were to make the resulting executables

	as fast as possible

	as small as possible

The consequences of theese design-goals are

	executables use absolute addresses, so they need relocation whenever they have been 
moved somewhere else in memory.

	executables can be linked to shared libraries at runtime.
While this needs some cycles on each startup of an executable, the speed penalty is negli-
gable in comparison to the amount of memory that is saved this way.

	shared libraries do not have to be position-independent (as on most other architectures), 
they are relocated as well as the executables.

The three points above make it necessary to have some code that performs all the necessary run-time 
actions on the HP48. It's all done by the dynamic linker GCCLDD, that comes along with clld. This 
program has to be available for every executable binary created by clld on your HP48.

3.	Usage / Syntax

To link one or more object files or shared libraries into an executable, invoke clld with the names 
of the files as parameters. The order of the files doesn't matter, except for the very first one, which is 
jumped into on startup, and it is the only object-file that is linked in any case - all other object files 
are linked only if they export any symbols that are imported by another object file.



You can use the following options to change the behaviour of clld:

-o <filename>	allows you to specify the name of the file that will be 
written by clld. By default, the name ,a.out" is used.



-v	enables verbose output (including some statistics).

-shared	tells clld not to create an executable binary, but a 
shared library. clld will then write two files, one end-
ing in ,.sl", which is the binary image of the shared 
library code, and can be downloaded into your HP48, 
and one file ending in ,.slo", which is an ordinary 
object-file, with the exception that it is marked as corre-
sponding to a shared library.

-static <filename>	Allows you to link an object file that corresponds to a 
shared library (a *.slo file) as an ordinary object file. 
This may be helpful for debugging sessions - there's lit-
tle use this option otherwise.

4.	Using shared libraries

Shared libraries are just collections of code that may be used by more than one program, allowing for 
great amounts of memory to be saved. The code that is used inside shared libraries is not different 
from any ordinary code, except for one minor restriction: shared libraries cannot import numerical 
symbols. This shouldn't be a problem, as code that is produced by compilers usually does not use 
numerical symbols (such symbols that do not reference any location in memory, but have just a con-
stant value) at all.



There's one big difference between shared libraries for the HP48 and such on most other architec-
tures: On most systems, shared libraries contain symbols which are matched against symbols that are 
stored within an executable to resolve all references between the main code and the libraries. But 
storing symbol names and such inside binaries for the HP48 is generally not a good idea as they take 
up a lot of memory that is short on the HP48. To overcome this problem, clld uses two files for any 
shared library: One that contains all symbols, debugging info and such along with the code, which is 
used for the link-process on the host computer. And another one, that holds only the code and the 
minimal binary information that is needed to resolve the references at run-time, only this file needs to 
reside in the memory of the HP48.



This has one important disadvantage: If a shared library changes, any program that uses this library 
has to be re-linked against the new version on the host computer.

I think this disadvantage is justified by the amount of memory that is saved by keeping the symbol-
names and such out of the HP48's memory.



Hint: Whenever you change a shared library, change its name, so you may have both the new and the 
old version of the library in your HP48, allowing programs that use the older ones still to work. Just 
put a version-number inside the library name, such as ,libc.1.0.sl".

4.1.	(Ab-)using shared libraries as static object-files

The host-side representation of shared libraries that holds all of the symbol-names and such are in 
fact of the same format as ordinary object files, except that they are marked to correspond to a shared 
library. This allows you to link a ,.slo"-file statically, but this is discouraged unless there are very 
good reasons to do so - one may be that you want to include the debugging-info from the shared 
library routines.

5.	Binary file structure

This chapter describes the structure of the executable- and shared-library binaries that are created by 
,clld" for the HP48 computer. 

5.1.	Executables

DOCOL

	DOIDNT `name of		 n. shared-library'

	DOIDNT `name of		 n-1. shared-library'

	...

	DOIDNT `name of		 1. shared-library'

	DOEXT0 {

		dcr.	5	MAGIC_WORD

		dcr.5		5+sizeof{

			dcr.5		Base-address of last relocation



			dcr.5		Offset where 1. relocation has to be applied

			dcr.5		Offset where 2. relocation has to be applied

			...

			dcr.5		Offset where k. relocation has to be applied

			dcr.5		0

			

			dcr.5		Start-address of <Executable Code>

			dcr.5		Start-address of 1. shared-library's <Executable Code>

			dcr.5		Start-address of 2. shared-library's <Executable Code>

			...

			dcr.5		Start-address of n. shared-library's <Executable Code>

			dcr.5		0



			dcr.2		x

			dcr.5		Offset into <Executable Code> Nr. i which satisfies...

			dcr.5		... import Nr. 1 into the main-code at the offset stored here

			dcr.2		x

			dcr.5		Offset into <Executable Code> Nr. i which satisfies...

			dcr.5		... import Nr. 2 into the main-code at the offset stored here

			...

			dcr.5		Offset into <Executable Code> Nr. i which satisfies...

			dcr.5		... import Nr. n into the main-code at the offset stored here

			dcr.2		0



			for (s=1, s < n; s++) {

				dcr.2		x		

				dcr.5		Offset into <Executable Code> Nr. i which satisfies the 1. 
import-address of shared-library Nr. s

				dcr.2		x

				dcr.5		Offset into <Executable Code> Nr. i which satisfies the 2. 
import-address of shared-library Nr. s

				...

				dcr.2		x

				dcr.5		Offset into <Executable Code> Nr. i which satisfies the m. 
import-address of shared-library Nr. s

				dcr.2		0

			}

		}

		<Executable Code>

	}

	DOIDNT `GCCLDD'

SEMI

5.2.	Shared Libraries

DOCOL

	DOEXT0 {

		dcr.	5	MAGIC_WORD

		dcr.5		5+sizeof{

			dcr.5		Base-address of last relocation



			dcr.5		Offset where 1. relocation has to be applied

			dcr.5		Offset where 2. relocation has to be applied

			...

			dcr.5		Offset where k. relocation has to be applied

			dcr.5		0

			

			dcr.5		Offset where the n. import has to be applied

			dcr.5		Offset where the n-1. import has to be applied

			...

			dcr.5		Offset where the 1. import has to be applied

		}

		<Executable Code>

	}

SEMI
