Nächste Überarbeitung | Vorhergehende ÜberarbeitungNächste ÜberarbeitungBeide Seiten der Revision |
software:deep:dev:crosscompiler:linker32 [2014-01-11 08:51] – Externe Bearbeitung 127.0.0.1 | software:deep:dev:crosscompiler:linker32 [2014-02-10 12:57] – graf |
---|
* Checksum | * Checksum |
[{{ .:constblock.png?450&direct | Structure of the constant pool for a class }}]\\ | [{{ .:constblock.png?450&direct | Structure of the constant pool for a class }}]\\ |
The //const pool// contains values of type //float// and //double// which are not placed directly into the code. After all elements are added the //constBlockSize// can be determined and the indices (''Item.index'') of all elements will be fixed. It's important to note that all elements, which are addresses (''AddressItem'', ''ConstantBlockItem'', ...), simply contain a reference to the according item. Only later after address fixing can the real addresses be inserted! | The //const pool// contains values of type //float// and //double// which are not placed directly into the code. After all elements are added the //constBlockSize// can be determined and the indices (''Item.index'') of all elements will be fixed. It's important to note that all elements, which are addresses (''AddressItem'', ''ConstantBlockItem'', ...), simply contain a reference to the according item. Only later, after address fixing, can the real addresses be inserted!\\ |
Diese Methode muss vom //Launcher// für jede Klasse aufgerufen werden.\\ | When the system ist starting up, the [[..:rts:start|Runtime System]] reads the start addresses of the constant block for all classes from the //System Table// (see below). With the predefined offset //cblkClinitAddrOffset// the address of the class constructor can be fetched in order to load a class. With another offset the heap manager can read the global references of this class. This information is used by the garbage collection. //codeBase// holds the start address of code of a class whereas //codeSize// is the size of the code. Methods, which are defined in the configuration as system methods and which are assigned a fixed offset are excluded from //codeSize// (Exception Handlers). |
Das //Laufzeitsystem// holt sich aus der //Systemtabelle// für alle Klassen die Startadresse des Konstantenblockes und kann dann daraus die Startadresse des Klassenkonstruktors (benötigt der Kernel für das Booten) oder auch die globalen Pointer dieser Klasse (benötigt der Heap für die Garbage Collection) holen. //codeBase// gibt die Startadresse der ersten Methode einer Klasse an, //codeSize// ist die Grösse aller Methoden einer Klasse summiert. Davon ausgenommen sind Systemmethoden, die in der Konfiguration definiert sind, und die einen dort fixierten Offset haben (Exception Handlers). | |
| |
Der Konstantenblock ist als Liste aufgebaut (Item). Die Basisklasse für die Listeneinträge ist ''ch.ntb.inf.dee.linker.ConstBlkEntry''. Je nach Art des Eintrages wird eine der folgenden Klassen verwendet: | In the compiler the constant block is modeled as linked list of ''ch.ntb.inf.deep.linker.ConstBlkEntry''. Depending on the type of entry one of the following classes is used. |
* **''AddressEntry''**: Für Einträge, die eine Adresse repräsentieren. | * **''AddressEntry''**: For entries representing an address. |
* **''ConstantEntry''**: Für Einträge, die eine Konstante repräsentieren (StdConstant). | * **''ConstantEntry''**: For entries representing a constant (StdConstant). |
* **''FixedValueEntry''**: Für Einträge, die einen festen Wert repräsentieren (z.B. eine Grössenangabe). | * **''FixedValueEntry''**: For entries representing a fixed value (e.g. a size). |
* **''InterfaceEntry''**: Für Einträge, die einen Interface-Eintrag repräsentieren (Interface-ID und Offset). | * **''InterfaceEntry''**: For entries representing an interface entry (id and offset). |
* **''StringEntry''**: Für Einträge, die einen konstanten String repräsentieren (StringLiteral). | * **''StringEntry''**: For entries representing a constant string (StringLiteral). |
* **''OffsetEntry''**: Für Einträge in die Tabelle allen Instanzpointern. | * **''OffsetEntry''**: For entries representing an offset to the table with all instance references. |
| |
=== Typedescriptor === | ==== Type Descriptor ==== |
Der Typdeskriptor wird benötigt um Instanzmethoden zu finden und um Typenprüfungen durchführen zu können. Der Aufbau und die Funktionsweise ist auf einer eigenen Seite beschrieben: [[Type Descriptor]]. | The structure and purpose of the [[Type Descriptor]] is described separately. |
| |
=== String pool === | ==== String pool ==== |
Der Stringpool beinhaltet die konstanten Strings einer Klasse. Dabei werden die Strings folgendermassen abgelegt (siehe auch unter [[strings|Strings]]: | The string pool holds the constant strings of a class. They are stored as follows (also see [[strings|Strings]]: |
[ tag ] | [ tag ] |
[ stringClassAddress ] | [ stringClassAddress ] |
[ chars ] | [ chars ] |
[ ⋮ ] | [ ⋮ ] |
Dabe werden die einzelnen Zeichen jeweils in 2-Byte-Unicode-Kodierung abgelegt. | The characters of the string are stored in 2-Byte-Unicode. |
| |
=== Constant pool === | ==== Constant Pool ==== |
Der Konstantenpool beinhaltet die Konstanten einer Klasse. Zur Zeit werden nur Gleitkomma-Zahlen (Float & Double) im Konstantenblock abgelegt. Ganzzahlen werden direkt in den Code integriert. Die Gleitkommazahlen werden wie in Java an IEEE 754 angelehnt abgelegt. Dabei wird bei einer 64bit Zahl das Highword an der niedrigeren Adresse abgelegt. | The constant pool holds the constants of a class. Currently we only store there floating point numbers (//float// and //double//). Integer numbers are packed into the instructions directly (even //long//). Floating point numbers are stored in IEEE 754 format, the high word of a 64 bit //double// is at the lower address (bid endian). |
| |
**Beispiel:** | **Example:** |
[40490FDB] 3.1415927 (float) | [40490FDB] 3.1415927 (float) |
[401921FB] 6.283185307179586 (double) | [401921FB] 6.283185307179586 (double) |
| |
| |
===== Grösse und Offsets berechnen ===== | ===== Calculate Size and Offsets ===== |
[{{ .:linker_code_methods.png?300px&direct|Maschinencode: Grösse und Offsets}}] | [{{ .:linker_code_methods.png?350px&direct|Machine Code: Size and Offsets}}] |
Bevor die Memory Map fixiert werden kann, müssen noch ein paar Grössen und Offsets pro Standard-Klasse berechnet werden: | Before the memory map can be fixed, a couple sizes and offsets must be calculated for each class: |
* ''void calculateCodeSizeAndOffsets(Class)'': Diese Methode berechnet die Grösse des Maschinencodes für die gesamte Klasse und setzt das Feld ''offset'' jeder Methode dieser Klasse. Dieses beschreibt den Byte-Offset des Maschinencodes einer Methode im Speicher ausgehend von der Startaddresse des Codes der Klasse. Wenn der Offset einer Methode direkt von der Konfiguration vorgegeben ist (für Exception-Handler-Code) wird diese Methode nicht in die Berechnung der Codegrösse miteinbezogen. Der durch die Konfiguration vorgegebene Offset bezieht sich nicht auf die Basis einer Klasse, sondern auf die Basis des zugehörigen Segmentes. | * ''void calculateCodeSizeAndOffsets(Class)'': This methods determines the size of the machine code of the whole class and sets the field //offset// of each method of this class. //offset// is the byte offset of the machine code of a method in the memory starting from the start address of the code of this class. If a method offset is given by the configuration (e.g. exception handlers), then this method is not included in the culculation of the code size. The offset given by the configuration is not relative to the base of a class but to the base of the appropriate segment. |
* ''void calculateGlobalConstantTableSize()'': Berechnet die Grösse der globalen Konstanten-Tabelle. | * ''void calculateGlobalConstantTableSize()'': This method calculates the size of the global constant table. |
| |
===== Systemtabelle erstellen ===== | ===== Create System Table ===== |
Der Linker stellt für das gesamte System eine Systemtabelle zusammen. Diese muss an eine fixe Adresse geladen werden und enthält wichtige Informationen für das Laufzeitsystem. Grundsätzlich muss dabei zwischen drei Fällen unterschieden werden: | The linker assembles a system table for the whole system. This table must be loaded to a prefixed address in the target system and holds information for the [[..:rts:start|Runtime System]]. Various settings must be handled: |
- Das gesamte System befindet sich im Flash. | - The system runs from the flash |
- Das gesamte System befindet sich im Ram. | - The system runs from the RAM. |
- Das Basissystem befinden sich im Flash. Weitere Klassen werden nachträglich ins Ram geladen. Für diesen Fall werden zwei Systemtabellen benötigt. Im Flash befindet sich eine Systemtabelle, welche nur die Klassen im Flash abdeckt. Im RAM hingegen befindet sich eine Systemtabelle, die sowohl die Klassen im RAM als auch die im Flash abdeckt. -> IMPORTANT Dies ist zur Zeit noch nicht implementiert IMPORTANT | - The base system is in the flash. Further classes are later loaded into the RAM. This case needs two system tables. The flash holds a system table which contains only classes which are present in the flash. The system table in the RAM must hold all classes. IMPORTANT This feature is not implemented yet IMPORTANT |
\\ | |
Die Methode ''void createSystemtable()'' erstellt die Systemtabelle. Diese ist als doppelt verkettete Liste realisiert und verwendet die selben von ''BlockEntry'' abgeleiteten Listenelemente wie die Konstantenblöcke der Klassen, zusätzlich noch die Klasse ''SysTabEntry''. Diese referenziert den Konstantenblock einer Klasse. | |
| |
Die Systemtabelle hat den folgenden Aufbau: | In the compiler the system table is modeled as list. as elements it uses the same blocks as for the constant block. Additionally ''SysTabEntry'' is used to reference the constant block of a class. |
[{{ .:systemtable.png?450&direct |//Aufbau der Systemtabelle// }}] | |
| |
Bevor die Systemtabelle zusammengestellt werden kann, muss der Klassenkonstruktor der Kernel-Klasse gefunden werden. Dazu wird der Klassennamen aus der Konfiguration geladen und anschliessend die Methode ''<clinit>'' gesucht. | The structure of the system table is: |
| [{{ .:systemtable.png?450&direct |//Structure of the system table// }}] |
| |
Nun kann die Systemtabelle aufgebaut werden. Dazu wird als erstes der Offset zum Beginn der Klassenliste (Liste mit der Basisadresse des Konstantenblocks jeder Klasse) eingefügt. Anschliessend werden die Informationen zu Heap und Stack eingefügt. Anschliessend die Anzahl vorhandener Klassen und die bereits erwähnte Liste mit den Basisadressen der Konstantenblöcke. Die Systemtabelle wird mit dem Wert 0x0 abgeschlossen. | First, the class constructor of the class kernel must be found. For this, the class name of the kernel is fetched from the configuration and the method //<clinit>// is searched. Then, the table can be built. The offset to the addresses with the constant blocks is placed at the beginning. Heap and stack information is added. For each class the address of the constant block must be entered. The table ends with the value 0. |
| |
Der letzte Teil mit den Referenzen auf den Konstantenblock der einzelnen Klassen ist wie folgt zusammengestellt. Zuerst kommen alle Klassen mit einem Klassenkonstruktor. Diese Klassen sind bereits in der korrekten Reihenfolge gemäss [[class_initialization]] sortiert. Anschliessend kommen alle nicht-initialisierten Klassen. Arrays und Interfaces haben keinen Konstantenblock und kommen nicht in die Liste mit Ausnahme von Interfaces, die einen Klassenkonstruktor haben, siehe //Interfacemethoden// in [[type_descriptor]]. | The references to the constant blocks are assembled as follows. First come the classes with class constructors. These classes are already sorted in correct order as described in [[class_initialization]]. Classes without initialization follow afterwards. Arrays and interfaces have no constant block and are not listed. The exception to this rule are interfaces with class constructor, see [[.:interfaces|Interfaces]]. |
\\ | |
Beim MPC555 wird die Systemtabelle in der Dual-Mapped-Section direkt nach dem Exceptioncode positioniert (Addresse 0x2000 -> siehe Memory Map). | |
| |
===== Memory Map fixieren ===== | ===== Fix Memory Map ===== |
[{{ .:linker_code.png?300px&direct|Maschinencode: Grösse und Offsets}}] | [{{ .:linker_code.png?350px&direct|Fixing the memory map}}] |
Das Platzieren des Codes, der statischen Variablen und der Konstanten im Speicher geschieht wie folgt. Als erstes wird jeder Klasse ein Memory-Segment für den Code (''Class.codeSegment''), die statischen Variablen (''Class.varSegment'') und die Konstanten (''Class.constSegment'') zugeteilt. Welche Segmente das sind, wird der Konfiguration entnommen. Dabei läuft der Linker rekursiv durch die möglichen Segmente und wählt das erste passende aus. Während dieser Zuteilung wird der im Segment benutzte Platz gespeichert (''Segment.usedSize'') und der entsprechende Offset (''Class.codeOffset'', ''Class.varOffset'' und ''Class.constOffset'') zugeteilt. Auch für jedes Array und für jedes benötigte Interface wird ein Segment (''Class.constSegment'') für den Typedescriptor gesucht und der Offset (Array.offset, Class.offset) gesetzt. | In this step the code is placed in the memory, as well as the class variables and the constants. First, each class is assigned a memory segment for the code (''Class.codeSegment''), class variables (''Class.varSegment'') and constants (''Class.constSegment''). Which segments to use can be read from the configuration. The linker traverses the possible segments and choses a suitable one. While doing this, the used space of each segment is stored (''Segment.usedSize'') and the appropriate offsets are set (''Class.codeOffset'', ''Class.varOffset'' and ''Class.constOffset''). Arrays and interfaces must be handled as well. Further, the size of the segment for the system table has to be set and also the size of the segment for the global constant table. |
Anschliessend wird die verwendete Grösse auch noch für das Systemtabellen-Segment gesetzt und das Speichersegment für die globale Konstantentabelle festgelegt. | Now, the base address of each used segment can be determined. |
In einem weiteren Schritt wird die Grösse für jedes verwendete Segment festgelegt (sofern nicht bereits in der Konfiguration vorgegeben). Nun kann für jedes verwendete Segment die Basisadresse berechnet werden. | IMPORTANT System methods with offsets given by the configuration must be placed in their appropriate segments. This leads to holes. Such holes could be eliminated by a more efficient allocation, which is currently not done. |
\\ Achtung: Ganz zu Beginn müssen Systemmethoden, die einen in von Konfiguration gegebenen Offset haben (Exception-Handlers), bereits im passenden Segment platziert werden. Das führt zu "Löchern" in diesem Segment. Diese Löcher können durch eine effizientere Allokation eliminiert werden, was aber zur Zeit nicht gemacht ist. | |
| |
===== Absolute Adressen berechnen ===== | ===== Calculate Absolute Addresses ===== |
Nachdem der Code, die statischen Variablen und der Konstantenblock jeder Klasse und auch die Systemtabelle und die globale Konstantentabelle platziert sind, werden nun die absoluten Adressen berechnet. Dazu steht die Methode ''void calculateAbsoluteAddresses(Class)'' bereit. | Nachdem der Code, die statischen Variablen und der Konstantenblock jeder Klasse und auch die Systemtabelle und die globale Konstantentabelle platziert sind, werden nun die absoluten Adressen berechnet. Dazu steht die Methode ''void calculateAbsoluteAddresses(Class)'' bereit. |
In einem ersten Schritt werden die Adressen für die statischen Felder bestimmt. Dazu läuft der Linker durch die entsprechende Liste (''Class.classFields'') durch und berechnet die absolute Adresse (''Item.address''). Die Adresse wird nur bei nicht konstanten Feldern gesetzt. | In einem ersten Schritt werden die Adressen für die statischen Felder bestimmt. Dazu läuft der Linker durch die entsprechende Liste (''Class.classFields'') durch und berechnet die absolute Adresse (''Item.address''). Die Adresse wird nur bei nicht konstanten Feldern gesetzt. |