diff --git a/source/CONSTANTS.ob07 b/source/CONSTANTS.ob07 index d2cb23f..ea11a3f 100644 --- a/source/CONSTANTS.ob07 +++ b/source/CONSTANTS.ob07 @@ -25,6 +25,7 @@ CONST Target_iConsole64* = 6; Target_iGUI64* = 7; Target_iDLL64* = 8; + Target_iELF32* = 9; Target_sConsole* = "console"; Target_sGUI* = "gui"; @@ -34,6 +35,7 @@ CONST Target_sConsole64* = "console64"; Target_sGUI64* = "gui64"; Target_sDLL64* = "dll64"; + Target_sELF32* = "elfexe"; END CONSTANTS. \ No newline at end of file diff --git a/source/Compiler.ob07 b/source/Compiler.ob07 index f59cca4..56814cc 100644 --- a/source/Compiler.ob07 +++ b/source/Compiler.ob07 @@ -31,6 +31,8 @@ BEGIN res := mConst.Target_iGUI64 ELSIF s = mConst.Target_sDLL64 THEN res := mConst.Target_iDLL64 + ELSIF s = mConst.Target_sELF32 THEN + res := mConst.Target_iELF32 ELSE res := 0 END @@ -160,7 +162,7 @@ VAR checking: SET; bits64: BOOLEAN; - bit32only: ARRAY 15 OF CHAR; + //bit32only: ARRAY 15 OF CHAR; BEGIN StackSize := 2; @@ -178,19 +180,17 @@ BEGIN C.String("Akron Oberon-07/16 Compiler v"); C.Int(mConst.vMajor); C.String("."); C.Int2(mConst.vMinor); C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit)"); C.Ln; C.StringLn("Usage: Compiler
[optional settings]"); C.Ln; - IF UTILS.bit_depth = 64 THEN - bit32only := " (32-bit only)"; - C.StringLn('target = console | gui | dll | console64 | gui64 | dll64 | kos | obj'); C.Ln; + IF UTILS.bit_depth = 64 THEN + C.StringLn('target = console | gui | dll | console64 | gui64 | dll64 | kos | obj | elfexe'); C.Ln; ELSIF UTILS.bit_depth = 32 THEN - bit32only := ""; - C.StringLn('target = console | gui | dll | kos | obj'); C.Ln; + C.StringLn('target = console | gui | dll | kos | obj | elfexe'); C.Ln; END; C.StringLn("optional settings:"); C.Ln; C.StringLn(" -stk set size of stack in megabytes"); C.Ln; C.StringLn(" -base
set base address of image in kilobytes"); C.Ln; - C.String( " -pic generate position-independent code"); C.StringLn(bit32only); C.Ln; - C.String( " -reloc make relocation table"); C.StringLn(bit32only); C.Ln; - C.StringLn(' -ver set version of program ("obj" only)'); C.Ln; + C.StringLn(" -pic generate position-independent code"); C.Ln; + C.StringLn(" -reloc make relocation table"); C.Ln; + C.StringLn(' -ver set version of program'); C.Ln; C.StringLn(' -nochk <"ptibcwra"> disable runtime checking (pointers, types, indexes,'); C.StringLn(' BYTE, CHR, WCHR)'); C.Ln; UTILS.Exit(0) @@ -253,6 +253,9 @@ BEGIN ELSIF target IN {mConst.Target_iKolibri, mConst.Target_iObject} THEN STRINGS.append(lib_path, "KolibriOS") + ELSIF target = mConst.Target_iELF32 THEN + STRINGS.append(lib_path, "Linux32") + ELSIF target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN STRINGS.append(lib_path, "Windows64") diff --git a/source/ELF.ob07 b/source/ELF.ob07 new file mode 100644 index 0000000..7792144 --- /dev/null +++ b/source/ELF.ob07 @@ -0,0 +1,301 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE ELF; + +IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, PE32; + + +CONST + + EI_NIDENT = 16; + ET_EXEC = 2; + ET_DYN = 3; + + EM_386 = 3; + + ELFCLASS32 = 1; + ELFCLASS64 = 2; + + ELFDATA2LSB = 1; + ELFDATA2MSB = 2; + + PF_X = 1; + PF_W = 2; + PF_R = 4; + + +TYPE + + Elf32_Ehdr = RECORD + + e_ident: ARRAY EI_NIDENT OF BYTE; + + e_type, + e_machine: WCHAR; + + e_version, + e_entry, + e_phoff, + e_shoff, + e_flags: INTEGER; + + e_ehsize, + e_phentsize, + e_phnum, + e_shentsize, + e_shnum, + e_shstrndx: WCHAR + + END; + + + Elf32_Phdr = RECORD + + p_type, + p_offset, + p_vaddr, + p_paddr, + p_filesz, + p_memsz, + p_flags, + p_align: INTEGER + + END; + + FILE = WR.FILE; + + +PROCEDURE align (n, _align: INTEGER): INTEGER; +BEGIN + IF n MOD _align # 0 THEN + n := n + _align - (n MOD _align) + END + + RETURN n +END align; + + +PROCEDURE Write16 (file: FILE; w: WCHAR); +BEGIN + WR.Write16LE(file, ORD(w)) +END Write16; + + +PROCEDURE WritePH (file: FILE; ph: Elf32_Phdr); +BEGIN + WR.Write32LE(file, ph.p_type); + WR.Write32LE(file, ph.p_offset); + WR.Write32LE(file, ph.p_vaddr); + WR.Write32LE(file, ph.p_paddr); + WR.Write32LE(file, ph.p_filesz); + WR.Write32LE(file, ph.p_memsz); + WR.Write32LE(file, ph.p_flags); + WR.Write32LE(file, ph.p_align) +END WritePH; + + +PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER); +VAR + reloc: BIN.RELOC; + L, delta: INTEGER; + +BEGIN + reloc := program.rel_list.first(BIN.RELOC); + WHILE reloc # NIL DO + + L := BIN.get32le(program.code, reloc.offset); + delta := 3 - reloc.offset - text; + + CASE reloc.opcode OF + |BIN.PICDATA: BIN.put32le(program.code, reloc.offset, L + data + delta) + |BIN.PICCODE: BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta) + |BIN.PICBSS: BIN.put32le(program.code, reloc.offset, L + bss + delta) + END; + + reloc := reloc.next(BIN.RELOC) + END; +END fixup; + + +PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR); +CONST + interp = 0; + dyn = 1; + header = 2; + text = 3; + data = 4; + bss = 5; + +VAR + ehdr: Elf32_Ehdr; + phdr: ARRAY 16 OF Elf32_Phdr; + + i, LoadAdr, offset: INTEGER; + + SizeOf: RECORD header, code, data, bss: INTEGER END; + + File: FILE; + + str: ARRAY 40 OF CHAR; lstr: INTEGER; + Dyn: ARRAY 201 OF BYTE; + +BEGIN + str := "/lib/ld-linux.so.2"; + lstr := LENGTH(str); + + LoadAdr := 08048000H; + + SizeOf.code := CHL.Length(program.code); + SizeOf.data := CHL.Length(program.data); + SizeOf.bss := program.bss; + + ehdr.e_ident[0] := 7FH; + ehdr.e_ident[1] := ORD("E"); + ehdr.e_ident[2] := ORD("L"); + ehdr.e_ident[3] := ORD("F"); + ehdr.e_ident[4] := ELFCLASS32; + ehdr.e_ident[5] := ELFDATA2LSB; + ehdr.e_ident[6] := 1; + ehdr.e_ident[7] := 3; + FOR i := 8 TO EI_NIDENT - 1 DO + ehdr.e_ident[i] := 0 + END; + + ehdr.e_type := WCHR(ET_EXEC); + ehdr.e_machine := WCHR(EM_386); + ehdr.e_version := 1; + ehdr.e_phoff := 34H; + ehdr.e_shoff := 0; + ehdr.e_flags := 0; + ehdr.e_ehsize := WCHR(34H); + ehdr.e_phentsize := WCHR(20H); + ehdr.e_phnum := WCHR(6);//!!! + ehdr.e_shentsize := WCHR(28H); + ehdr.e_shnum := WCHR(0); + ehdr.e_shstrndx := WCHR(0); + + SizeOf.header := 34H + 20H * ORD(ehdr.e_phnum); + + phdr[interp].p_type := 3; + phdr[interp].p_offset := SizeOf.header; + phdr[interp].p_vaddr := LoadAdr + phdr[interp].p_offset; + phdr[interp].p_paddr := LoadAdr + phdr[interp].p_offset; + phdr[interp].p_filesz := lstr + 1; + phdr[interp].p_memsz := lstr + 1; + phdr[interp].p_flags := PF_R; + phdr[interp].p_align := 1; + + phdr[dyn].p_type := 2; + phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz; + phdr[dyn].p_vaddr := LoadAdr + phdr[dyn].p_offset; + phdr[dyn].p_paddr := LoadAdr + phdr[dyn].p_offset; + phdr[dyn].p_filesz := 50H;//!!! + phdr[dyn].p_memsz := 50H;//!!! + phdr[dyn].p_flags := PF_R; + phdr[dyn].p_align := 1; + + offset := 0; + + phdr[header].p_type := 1; + phdr[header].p_offset := offset; + phdr[header].p_vaddr := LoadAdr; + phdr[header].p_paddr := LoadAdr; + phdr[header].p_filesz := 1D0H;//!!! + phdr[header].p_memsz := 1D0H;//!!! + phdr[header].p_flags := PF_R + PF_W; + phdr[header].p_align := 1000H; + + offset := offset + phdr[header].p_filesz; + + phdr[text].p_type := 1; + phdr[text].p_offset := offset; + phdr[text].p_vaddr := LoadAdr + offset + 1000H; + phdr[text].p_paddr := LoadAdr + offset + 1000H; + phdr[text].p_filesz := SizeOf.code; + phdr[text].p_memsz := SizeOf.code; + phdr[text].p_flags := PF_X + PF_R; + phdr[text].p_align := 1000H; + + ehdr.e_entry := phdr[text].p_vaddr; + + offset := offset + phdr[text].p_filesz; + + phdr[data].p_type := 1; + phdr[data].p_offset := offset; + phdr[data].p_vaddr := LoadAdr + offset + 2000H; + phdr[data].p_paddr := LoadAdr + offset + 2000H; + phdr[data].p_filesz := SizeOf.data; + phdr[data].p_memsz := SizeOf.data; + phdr[data].p_flags := PF_R + PF_W; + phdr[data].p_align := 1000H; + + offset := offset + phdr[data].p_filesz; + + phdr[bss].p_type := 1; + phdr[bss].p_offset := offset; + phdr[bss].p_vaddr := LoadAdr + offset + 3000H; + phdr[bss].p_paddr := LoadAdr + offset + 3000H; + phdr[bss].p_filesz := 0; + phdr[bss].p_memsz := SizeOf.bss; + phdr[bss].p_flags := PF_R + PF_W; + phdr[bss].p_align := 1000H; + + fixup(program, phdr[text].p_vaddr, phdr[data].p_vaddr, phdr[bss].p_vaddr); + + File := WR.Create(FileName); + + FOR i := 0 TO EI_NIDENT - 1 DO + WR.WriteByte(File, ehdr.e_ident[i]) + END; + + Write16(File, ehdr.e_type); + Write16(File, ehdr.e_machine); + + WR.Write32LE(File, ehdr.e_version); + WR.Write32LE(File, ehdr.e_entry); + WR.Write32LE(File, ehdr.e_phoff); + WR.Write32LE(File, ehdr.e_shoff); + WR.Write32LE(File, ehdr.e_flags); + + Write16(File, ehdr.e_ehsize); + Write16(File, ehdr.e_phentsize); + Write16(File, ehdr.e_phnum); + Write16(File, ehdr.e_shentsize); + Write16(File, ehdr.e_shnum); + Write16(File, ehdr.e_shstrndx); + + WritePH(File, phdr[interp]); + WritePH(File, phdr[dyn]); + WritePH(File, phdr[header]); + WritePH(File, phdr[text]); + WritePH(File, phdr[data]); + WritePH(File, phdr[bss]); + + FOR i := 0 TO lstr DO + WR.WriteByte(File, ORD(str[i])) + END; + + i := 0; + PE32.InitArray(Dyn, i, "010000000E00000005000000AF8104080A000000190000000600000057810408"); + PE32.InitArray(Dyn, i, "0B00000010000000110000008781040812000000100000001300000008000000"); + PE32.InitArray(Dyn, i, "0400000097810408000000000000000000000000000000000000000000000000"); + PE32.InitArray(Dyn, i, "0100000000000000000000001200000008000000000000000000000012000000"); + PE32.InitArray(Dyn, i, "C881040801010000CC8104080102000001000000030000000000000001000000"); + PE32.InitArray(Dyn, i, "020000000000000000646C6F70656E00646C73796D006C6962646C2E736F2E32"); + PE32.InitArray(Dyn, i, "000000000000000000"); + + WR.Write(File, Dyn, LEN(Dyn)); + + CHL.WriteToFile(File, program.code); + CHL.WriteToFile(File, program.data); + + WR.Close(File) +END write; + + +END ELF. \ No newline at end of file diff --git a/source/PE32.ob07 b/source/PE32.ob07 index 7b729fd..7e7d7c2 100644 --- a/source/PE32.ob07 +++ b/source/PE32.ob07 @@ -356,7 +356,7 @@ BEGIN END fixup; -PROCEDURE InitArray (VAR array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); +PROCEDURE InitArray* (VAR array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); VAR i, k: INTEGER; diff --git a/source/UTILS.ob07 b/source/UTILS.ob07 index 7b01174..aeae93d 100644 --- a/source/UTILS.ob07 +++ b/source/UTILS.ob07 @@ -13,6 +13,7 @@ IMPORT HOST, UNIXTIME; CONST slash* = HOST.slash; + OS* = HOST.OS; bit_depth* = HOST.bit_depth; maxint* = HOST.maxint; @@ -24,7 +25,7 @@ VAR time*: INTEGER; eol*: ARRAY 3 OF CHAR; - + maxreal*: REAL; @@ -96,10 +97,17 @@ END GetCurrentDirectory; PROCEDURE UnixTime* (): INTEGER; VAR year, month, day, hour, min, sec: INTEGER; + res: INTEGER; BEGIN - HOST.now(year, month, day, hour, min, sec) - RETURN UNIXTIME.time(year, month, day, hour, min, sec) + IF OS = "LINUX32" THEN + res := HOST.UnixTime() + ELSE + HOST.now(year, month, day, hour, min, sec); + res := UNIXTIME.time(year, month, day, hour, min, sec) + END + + RETURN res END UnixTime; diff --git a/source/X86.ob07 b/source/X86.ob07 index 2ecf203..c3d950c 100644 --- a/source/X86.ob07 +++ b/source/X86.ob07 @@ -7,7 +7,7 @@ MODULE X86; -IMPORT CODE, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, mConst := CONSTANTS, MACHINE, CHL := CHUNKLISTS, PATHS; +IMPORT CODE, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, mConst := CONSTANTS, MACHINE, CHL := CHUNKLISTS, PATHS; CONST @@ -568,7 +568,7 @@ PROCEDURE NewLabel (): INTEGER; BEGIN BIN.NewLabel(program) RETURN CODE.NewLabel() -END NewLabel; +END NewLabel; PROCEDURE GetRegA; @@ -2206,11 +2206,13 @@ BEGIN IF target = mConst.Target_iKolibri THEN reg1 := REG.GetAnyReg(R); Pic(reg1, BIN.IMPTAB, 0); - push(reg1); // push IMPORT + push(reg1); // push IMPORT drop ELSIF target = mConst.Target_iObject THEN OutByte(68H); // push IMPORT Reloc(BIN.IMPTAB, 0) + ELSIF target = mConst.Target_iELF32 THEN + OutByte(54H) // push esp ELSE pushc(0) END; @@ -2218,7 +2220,7 @@ BEGIN IF pic THEN reg1 := REG.GetAnyReg(R); Pic(reg1, BIN.PICDATA, 0); - push(reg1); // push _data + push(reg1); // push _data drop ELSE OutByte(68H); // push _data @@ -2233,7 +2235,7 @@ BEGIN IF pic THEN reg1 := REG.GetAnyReg(R); Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); - push(reg1); // push _data + tcount * 4 + dcount + push(reg1); // push _data + tcount * 4 + dcount drop ELSE OutByte(68H); // push _data @@ -2276,7 +2278,7 @@ VAR BEGIN - IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri} THEN + IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN pushc(0); CallRTL(pic, CODE._exit); ELSIF target = mConst.Target_iDLL THEN @@ -2348,6 +2350,10 @@ BEGIN pic := FALSE END; + IF target = mConst.Target_iELF32 THEN + pic := TRUE + END; + R := REG.Create(push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); prolog(code, pic, target, stack, dllinit, dllret); @@ -2365,6 +2371,8 @@ BEGIN KOS.write(program, outname) ELSIF target = mConst.Target_iObject THEN MSCOFF.write(program, outname, ver) + ELSIF target = mConst.Target_iELF32 THEN + ELF.write(program, outname) END END CodeGen;