summaryrefslogtreecommitdiff
path: root/elf.myr
blob: 1e25536f71226e241620cb4d2d2d7c1cae53099b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use std
use bio

use "types"

pkg =
	const emitelf	: (lnk : lnk# -> void)
;;


/* identification entries */
const Elfclass64	= 2
const Elfdata2lsb	= 1
const Elfabifreebsd	= 9
const Elfversion	= 1
const Elfabiversion	= 0

/* header values */
const Typeexec	: uint16 = 2
const Machx64	: uint16 = 62
const Phoff	: uint64 = 64
const Shoff	: uint64 = 0
const Flags	: uint32 = 0

const Hdrsz	: uint32 = 64
const Nphdr	: uint32 = 4
const Nshdr	: uint32 = 0

/* program header values */
const Phdrsz	: uint32 = 56
const Ptload	: uint32 = 1
const Pfx	: uint32 = 1
const Pfw	: uint32 = 2
const Pfr	: uint32 = 4
const Pfrw	: uint32 = 6
const Pfrx	: uint32 = 5
const Pflags 	: uint32 = 0

const Nsegment	= 4
const Nsection	= 0
const Align	= 4096

const emitelf = {lnk
	match bio.create(lnk.outf, bio.Wr, 0o755)
	| `std.Err e:
		std.fatal("could not open output: {}\n", e)
	| `std.Ok f:
		header(f, lnk)
		//ident(f, lnk)
		//strtab(f, lnk)
		sdata(f, lnk, lnk.text, Align)
		sdata(f, lnk, lnk.data, Align)
		sdata(f, lnk, lnk.rodata, Align)
		bio.close(f)
	;;
}

const header = {f, lnk
	wstr(f, "\x7fELF") // 3
	w8(f, Elfclass64)  // 4
	w8(f, Elfdata2lsb) // 5
	w8(f, Elfversion)  // 6
	w8(f, Elfabifreebsd)  // 7
	w8(f, Elfabiversion)
	pad(f, 7)

	w16(f, Typeexec)
	w16(f, Machx64)
	w32(f, (Elfversion : uint32))
	w64(f, lnk.entry)		/* entry point */
	w64(f, (Hdrsz : uint64))	/* program header offset */
	w64(f, 0/*FIXME*/)		/* section header offset */
	w32(f, Flags)			/* no flags */
	w16(f, (Hdrsz : uint16))
	w16(f, (Phdrsz : uint16))
	w16(f, Nsegment)
	w16(f, 0)
	w16(f, Nsection)
	w16(f, 0)

	phdrs(f, lnk)
	//shdr(f, lnk)
}

const phdrs = {f, lnk
	phdr(f, lnk, lnk.text, lnk.text.len, Pfrx)
	phdr(f, lnk, lnk.data, lnk.data.len, Pfrw)
	phdr(f, lnk, lnk.rodata, lnk.rodata.len, Pfr)
	phdr(f, lnk, "", lnk.bss, Pfrw)
}

const phdr = {f, lnk, buf, sz, prot
	w32(f, Ptload)
	w32(f, prot)

	w64(f, lnk.foff)
	w64(f, lnk.voff)
	w64(f, lnk.voff)

	w64(f, buf.len)	/* size on disk */
	w64(f, sz)	/* size in memory */
	w64(f, 4096)	/* align to page size */
	lnk.foff += buf.len
	lnk.voff += sz
}

const sdata = {f, lnk, buf, align
	//pad(f, 4096 - f.voff % 4096)
	wstr(f, buf)
}

//const sectionheader = {f, lnk
//	/* text section */
//	/* data section */
//	/* rodata section */
//	/* bss section */
//	/* strtab */
//}

const wstr	= {f, s; check(bio.write(f, s))}
const w8	= {f, v; check(bio.putb(f, v))}
const w16	= {f, v; check(bio.putle16(f, v))}
const w32	= {f, v : uint32; check(bio.putle32(f, v))}
const w64	= {f, v; check(bio.putle64(f, v))}
const pad = {f, n
	for var i = 0; i < n; i++
		check(bio.putb(f, 0))
	;;
}

generic check = {st : bio.status(@a)
	match st
	| `bio.Ok _:	/* nothing */
	| `bio.Err e:	std.fatal("i/o error: {}\n", e)
	| `bio.Eof:	std.fatal("i/o error: eof\n")
	;;
}