| Zeile 57: | Zeile 57: | ||
Zuerst ein paar Definitionen: | Zuerst ein paar Definitionen: | ||
| + | <freebasic> | ||
type Elf32_Addr as UINTEGER | type Elf32_Addr as UINTEGER | ||
type Elf32_Half as USHORT | type Elf32_Half as USHORT | ||
| Zeile 63: | Zeile 64: | ||
type Elf32_Word as UINTEGER | type Elf32_Word as UINTEGER | ||
type Elf32_Uchar as UBYTE | type Elf32_Uchar as UBYTE | ||
| + | </freebasic> | ||
Beginnen wir nun mal mit dem ELF-Header. | Beginnen wir nun mal mit dem ELF-Header. | ||
| + | <freebasic> | ||
type ELF_IDENT_HEADER | type ELF_IDENT_HEADER | ||
EI_MAGIC as UINTEGER '// ELF-Magic Number | EI_MAGIC as UINTEGER '// ELF-Magic Number | ||
| Zeile 92: | Zeile 95: | ||
e_shstrndex as Elf32_Half '// tells us which entry of the section-header is linked to the String-Table | e_shstrndex as Elf32_Half '// tells us which entry of the section-header is linked to the String-Table | ||
end type | end type | ||
| + | </freebasic> | ||
So. Wofür ist jetzt "ELF_IDENT_HEADER" gut? Ganz einfach, er gibt uns erst mal ein paar grundlegende Infos, z.B. ob die Datei Little oder Big Endian ist. Das ist wichtig, da der Rest der Datei diesen Regeln folgt! (Eigentlich ist dieser Header etwas anders eingeteilt, aber der Einfachheit halber habe ich das mal so gelöst. Wie es wirklich richtig ist kann man in den ELF-Spezifikationen nachlesen) | So. Wofür ist jetzt "ELF_IDENT_HEADER" gut? Ganz einfach, er gibt uns erst mal ein paar grundlegende Infos, z.B. ob die Datei Little oder Big Endian ist. Das ist wichtig, da der Rest der Datei diesen Regeln folgt! (Eigentlich ist dieser Header etwas anders eingeteilt, aber der Einfachheit halber habe ich das mal so gelöst. Wie es wirklich richtig ist kann man in den ELF-Spezifikationen nachlesen) | ||
| Zeile 98: | Zeile 102: | ||
Nun schmeiße ich euch wieder ein paar Konstanten an den Kopf: | Nun schmeiße ich euch wieder ein paar Konstanten an den Kopf: | ||
| + | <freebasic> | ||
const ELF_MAG0 as UBYTE = &h7f | const ELF_MAG0 as UBYTE = &h7f | ||
const ELF_MAG1 as UBYTE = &h45 | const ELF_MAG1 as UBYTE = &h45 | ||
| Zeile 111: | Zeile 116: | ||
const ELF_DATA_2LSB as UBYTE = &h01 | const ELF_DATA_2LSB as UBYTE = &h01 | ||
const ELF_DATA_2MSB as UBYTE = &h02 | const ELF_DATA_2MSB as UBYTE = &h02 | ||
| + | </freebasic> | ||
Die sind alle für den Ident-Header. Zuerst die Magic-Number, dann die Klasse (gibt nur an ob wir eine 32bit oder eine 64bit ELF-Datei vor uns haben) und dann die Angabe ob wir Little oder Big Endian haben. Die werden später wieder verwendet. | Die sind alle für den Ident-Header. Zuerst die Magic-Number, dann die Klasse (gibt nur an ob wir eine 32bit oder eine 64bit ELF-Datei vor uns haben) und dann die Angabe ob wir Little oder Big Endian haben. Die werden später wieder verwendet. | ||
| + | <freebasic> | ||
const ELF_ET_NONE as USHORT = &h0000 '// no type | const ELF_ET_NONE as USHORT = &h0000 '// no type | ||
const ELF_ET_REL as USHORT = &h0001 '// relocatable | const ELF_ET_REL as USHORT = &h0001 '// relocatable | ||
| Zeile 133: | Zeile 140: | ||
const ELF_EV_NONE as UINTEGER = &h00 '// invalid version | const ELF_EV_NONE as UINTEGER = &h00 '// invalid version | ||
const ELF_EV_CURRENT as UINTEGER = &h01 '// current version | const ELF_EV_CURRENT as UINTEGER = &h01 '// current version | ||
| + | </freebasic> | ||
So, die sind für den ELF-Header. Zuerst die Konstanten für den Dateityp, dann für die Architektur. Und schließlich die Konstanten, damit wir erkennen das es eine aktuelle Version des ELF-Formats ist. | So, die sind für den ELF-Header. Zuerst die Konstanten für den Dateityp, dann für die Architektur. Und schließlich die Konstanten, damit wir erkennen das es eine aktuelle Version des ELF-Formats ist. | ||
So, was fehlt noch? Achja, richtig, der Program-Header. Los gehts. | So, was fehlt noch? Achja, richtig, der Program-Header. Los gehts. | ||
| + | <freebasic> | ||
type ELF_PROGRAM_HEADER_ENTRY | type ELF_PROGRAM_HEADER_ENTRY | ||
p_type as Elf32_Word '// type of the segment (see constants above) | p_type as Elf32_Word '// type of the segment (see constants above) | ||
| Zeile 147: | Zeile 156: | ||
p_align as Elf32_Word '// alignment. if zero or one, then no alignment is needed, otherwise the alignment has to be a power of two | p_align as Elf32_Word '// alignment. if zero or one, then no alignment is needed, otherwise the alignment has to be a power of two | ||
end type | end type | ||
| + | </freebasic> | ||
Das wird später alles noch klarer. Und damit dieser Header nicht so alleine ist, bekommt er auch ein paar Konstanten: | Das wird später alles noch klarer. Und damit dieser Header nicht so alleine ist, bekommt er auch ein paar Konstanten: | ||
| + | <freebasic> | ||
const ELF_PT_NULL as UINTEGER = &h00 '// invalid segment | const ELF_PT_NULL as UINTEGER = &h00 '// invalid segment | ||
const ELF_PT_LOAD as UINTEGER = &h01 '// loadable segment | const ELF_PT_LOAD as UINTEGER = &h01 '// loadable segment | ||
| Zeile 162: | Zeile 173: | ||
const ELF_PF_W as UINTEGER = &h02 '// writeable segment | const ELF_PF_W as UINTEGER = &h02 '// writeable segment | ||
const ELF_PF_R as UINTEGER = &h04 '// readable segment | const ELF_PF_R as UINTEGER = &h04 '// readable segment | ||
| + | </freebasic> | ||
Zuerst die Konstanten für den Segment-Typ. Uns interessieren momentan nur die PT_LOAD-Segmente, die anderen brauchen wir (noch) nicht. Die anderen Konstanten können wir momentan getrost ignorieren. Die geben nur ein paar Flags an ;). | Zuerst die Konstanten für den Segment-Typ. Uns interessieren momentan nur die PT_LOAD-Segmente, die anderen brauchen wir (noch) nicht. Die anderen Konstanten können wir momentan getrost ignorieren. Die geben nur ein paar Flags an ;). | ||
| Zeile 169: | Zeile 181: | ||
Jetzt gehts richtig los. | Jetzt gehts richtig los. | ||
| + | <freebasic> | ||
function ELF_check (ELFheader as ELF_HEADER) as BYTE | function ELF_check (ELFheader as ELF_HEADER) as BYTE | ||
'// first, we check the MAGIC-string | '// first, we check the MAGIC-string | ||
| Zeile 185: | Zeile 198: | ||
return -1 | return -1 | ||
end function | end function | ||
| + | </freebasic> | ||
Eigentlich müsste man hier nicht wirklich erklären, oder? Ich tus trotzdem. Also, wir geben dieser Funktion einen ELF-Header. Zuerst überprüfen wir den MAGIC-String (0x7f, 'E', 'L', 'F'). Dann stellen wir sicher, das die Datei auch zum ausführen gedacht ist, anschließend prüfen wir, ob es auch die richtige Architektur ist. Dann sehen wir nach, das wir ein 32bit ELF-File haben, sehen nach dem richtigen Datenformat (ihr wisst schon, Endian...) und zum Schluss überprüfen wir die Dateiversion. | Eigentlich müsste man hier nicht wirklich erklären, oder? Ich tus trotzdem. Also, wir geben dieser Funktion einen ELF-Header. Zuerst überprüfen wir den MAGIC-String (0x7f, 'E', 'L', 'F'). Dann stellen wir sicher, das die Datei auch zum ausführen gedacht ist, anschließend prüfen wir, ob es auch die richtige Architektur ist. Dann sehen wir nach, das wir ein 32bit ELF-File haben, sehen nach dem richtigen Datenformat (ihr wisst schon, Endian...) und zum Schluss überprüfen wir die Dateiversion. | ||
| Zeile 191: | Zeile 205: | ||
Und nun zum wichtigsten, aber auch gemeinsten Code: | Und nun zum wichtigsten, aber auch gemeinsten Code: | ||
| + | <freebasic> | ||
sub ELF_Create_Task (ID as USHORT, priority as UBYTE, address as any ptr) | sub ELF_Create_Task (ID as USHORT, priority as UBYTE, address as any ptr) | ||
dim ELFheader as ELF_HEADER ptr = cast(ELF_HEADER ptr, address) | dim ELFheader as ELF_HEADER ptr = cast(ELF_HEADER ptr, address) | ||
| Zeile 220: | Zeile 235: | ||
Task_Create (ID, priority, cast(any ptr, ELFheader->e_entry)) | Task_Create (ID, priority, cast(any ptr, ELFheader->e_entry)) | ||
end sub | end sub | ||
| + | </freebasic> | ||
Die Funktion kümmert sich um die Erstellung eines Tasks. Dazu geben wir ihm die gewünschte Task-ID und die Priorität (kann man natürlich auch weglassen), und natürlich einen Pointer auf die ELF-Datei (kriegt ihr von GRUB in der Multiboot-Info-Struktur). | Die Funktion kümmert sich um die Erstellung eines Tasks. Dazu geben wir ihm die gewünschte Task-ID und die Priorität (kann man natürlich auch weglassen), und natürlich einen Pointer auf die ELF-Datei (kriegt ihr von GRUB in der Multiboot-Info-Struktur). | ||
| Zeile 252: | Zeile 268: | ||
* [http://www.acm.uiuc.edu/sigops/rsrc/pfmt11.pdf Tool Interface Standard (TIS) Executable and Linking Format (ELF) Specification Version 1.2 (PDF)] | * [http://www.acm.uiuc.edu/sigops/rsrc/pfmt11.pdf Tool Interface Standard (TIS) Executable and Linking Format (ELF) Specification Version 1.2 (PDF)] | ||
| − | [[ | + | [[Kategorie:Tutorials]] |