Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * emit 32- or 64-bit elf headers for any architecture.
3
 * this is a component of ?l.
4
 */
5
#include "l.h"
6
 
7
enum {
8
	/* offsets into string table */
9
	Stitext		= 1,
10
	Stidata		= 7,
11
	Stistrtab	= 13,
12
};
13
 
14
void
15
elfident(int bo, int class)
16
{
17
	strnput("\177ELF", 4);		/* e_ident */
18
	cput(class);
19
	cput(bo);			/* byte order */
20
	cput(1);			/* version = CURRENT */
21
	if(debug['k']){			/* boot/embedded/standalone */
22
		cput(255);
23
		cput(0);
24
	}
25
	else{
26
		cput(0);		/* osabi = SYSV */
27
		cput(0);		/* abiversion = 3 */
28
	}
29
	strnput("", 7);
30
}
31
 
32
void
33
elfstrtab(void)
34
{
35
	/* string table */
36
	cput(0);
37
	strnput(".text", 5);		/* +1 */
38
	cput(0);
39
	strnput(".data", 5);		/* +7 */
40
	cput(0);
41
	strnput(".strtab", 7);		/* +13 */
42
	cput(0);
43
	cput(0);
44
}
45
 
46
void
47
elf32phdr(void (*putl)(long), ulong type, ulong off, ulong vaddr, ulong paddr,
48
	ulong filesz, ulong memsz, ulong prots, ulong align)
49
{
50
	putl(type);
51
	putl(off);
52
	putl(vaddr);
53
	putl(paddr);
54
	putl(filesz);
55
	putl(memsz);
56
	putl(prots);
57
	putl(align);
58
}
59
 
60
void
61
elf32shdr(void (*putl)(long), ulong name, ulong type, ulong flags, ulong vaddr,
62
	ulong off, ulong sectsz, ulong link, ulong addnl, ulong align,
63
	ulong entsz)
64
{
65
	putl(name);
66
	putl(type);
67
	putl(flags);
68
	putl(vaddr);
69
	putl(off);
70
	putl(sectsz);
71
	putl(link);
72
	putl(addnl);
73
	putl(align);
74
	putl(entsz);
75
}
76
 
77
static void
78
elf32sectab(void (*putl)(long))
79
{
80
	seek(cout, HEADR+textsize+datsize+symsize, 0);
81
	elf32shdr(putl, Stitext, Progbits, Salloc|Sexec, INITTEXT,
82
		HEADR, textsize, 0, 0, 0x10000, 0);
83
	elf32shdr(putl, Stidata, Progbits, Salloc|Swrite, INITDAT,
84
		HEADR+textsize, datsize, 0, 0, 0x10000, 0);
85
	elf32shdr(putl, Stistrtab, Strtab, 1 << 5, 0,
86
		HEADR+textsize+datsize+symsize+3*Shdr32sz, 14, 0, 0, 1, 0);
87
	elfstrtab();
88
}
89
 
90
/* if addpsects > 0, putpsects must emit exactly that many psects. */
91
void
92
elf32(int mach, int bo, int addpsects, void (*putpsects)(Putl))
93
{
94
	ulong phydata;
95
	void (*putw)(long), (*putl)(long);
96
 
97
	if(bo == ELFDATA2MSB){
98
		putw = wput;
99
		putl = lput;
100
	}else if(bo == ELFDATA2LSB){
101
		putw = wputl;
102
		putl = lputl;
103
	}else{
104
		print("elf32 byte order is mixed-endian\n");
105
		errorexit();
106
		return;
107
	}
108
 
109
	elfident(bo, ELFCLASS32);
110
	putw(EXEC);
111
	putw(mach);
112
	putl(1L);			/* version = CURRENT */
113
	putl(entryvalue());		/* entry vaddr */
114
	putl(Ehdr32sz);			/* offset to first phdr */
115
	if(debug['S'])
116
		putl(HEADR+textsize+datsize+symsize); /* offset to first shdr */
117
	else
118
		putl(0);
119
	putl(0L);			/* flags */
120
	putw(Ehdr32sz);
121
	putw(Phdr32sz);
122
	putw(3 + addpsects);		/* # of Phdrs */
123
	putw(Shdr32sz);
124
	if(debug['S']){
125
		putw(3);		/* # of Shdrs */
126
		putw(2);		/* Shdr table index */
127
	}else{
128
		putw(0);
129
		putw(0);
130
	}
131
 
132
	/*
133
	 * could include ELF headers in text -- 8l doesn't,
134
	 * but in theory it aids demand loading.
135
	 */
136
	elf32phdr(putl, PT_LOAD, HEADR, INITTEXT, INITTEXTP,
137
		textsize, textsize, R|X, INITRND);	/* text */
138
	/*
139
	 * we need INITDATP, but it has to be computed.
140
	 * assume distance between INITTEXT & INITTEXTP is also
141
	 * correct for INITDAT and INITDATP.
142
	 */
143
	phydata = INITDAT - (INITTEXT - INITTEXTP);
144
	elf32phdr(putl, PT_LOAD, HEADR+textsize, INITDAT, phydata,
145
		datsize, datsize+bsssize, R|W|X, INITRND); /* data */
146
	elf32phdr(putl, NOPTYPE, HEADR+textsize+datsize, 0, 0,
147
		symsize, lcsize, R, 4);			/* symbol table */
148
	if (addpsects > 0)
149
		putpsects(putl);
150
	cflush();
151
 
152
	if(debug['S'])
153
		elf32sectab(putl);
154
}
155
 
156
/*
157
 * elf64
158
 */
159
 
160
void
161
elf64phdr(void (*putl)(long), void (*putll)(vlong), ulong type, uvlong off,
162
	uvlong vaddr, uvlong paddr, uvlong filesz, uvlong memsz, ulong prots,
163
	uvlong align)
164
{
165
	putl(type);		
166
	putl(prots);		
167
	putll(off);		
168
	putll(vaddr);	
169
	putll(paddr);	
170
	putll(filesz);	
171
	putll(memsz);	
172
	putll(align);		
173
}
174
 
175
void
176
elf64shdr(void (*putl)(long), void (*putll)(vlong), ulong name, ulong type,
177
	uvlong flags, uvlong vaddr, uvlong off, uvlong sectsz, ulong link,
178
	ulong addnl, uvlong align, uvlong entsz)
179
{
180
	putl(name);
181
	putl(type);
182
	putll(flags);
183
	putll(vaddr);
184
	putll(off);
185
	putll(sectsz);
186
	putl(link);
187
	putl(addnl);
188
	putll(align);
189
	putll(entsz);
190
}
191
 
192
static void
193
elf64sectab(void (*putl)(long), void (*putll)(vlong))
194
{
195
	seek(cout, HEADR+textsize+datsize+symsize, 0);
196
	elf64shdr(putl, putll, Stitext, Progbits, Salloc|Sexec, INITTEXT,
197
		HEADR, textsize, 0, 0, 0x10000, 0);
198
	elf64shdr(putl, putll, Stidata, Progbits, Salloc|Swrite, INITDAT,
199
		HEADR+textsize, datsize, 0, 0, 0x10000, 0);
200
	elf64shdr(putl, putll, Stistrtab, Strtab, 1 << 5, 0,
201
		HEADR+textsize+datsize+symsize+3*Shdr64sz, 14, 0, 0, 1, 0);
202
	elfstrtab();
203
}
204
 
205
/* if addpsects > 0, putpsects must emit exactly that many psects. */
206
void
207
elf64(int mach, int bo, int addpsects, void (*putpsects)(Putl))
208
{
209
	uvlong phydata;
210
	void (*putw)(long), (*putl)(long);
211
	void (*putll)(vlong);
212
 
213
	if(bo == ELFDATA2MSB){
214
		putw = wput;
215
		putl = lput;
216
		putll = llput;
217
	}else if(bo == ELFDATA2LSB){
218
		putw = wputl;
219
		putl = lputl;
220
		putll = llputl;
221
	}else{
222
		print("elf64 byte order is mixed-endian\n");
223
		errorexit();
224
		return;
225
	}
226
 
227
	elfident(bo, ELFCLASS64);
228
	putw(EXEC);
229
	putw(mach);
230
	putl(1L);			/* version = CURRENT */
231
	putll(entryvalue());		/* entry vaddr */
232
	putll(Ehdr64sz);		/* offset to first phdr */
233
	if(debug['S'])
234
		putll(HEADR+textsize+datsize+symsize); /* offset to 1st shdr */
235
	else
236
		putll(0);
237
	putl(0L);			/* flags */
238
	putw(Ehdr64sz);
239
	putw(Phdr64sz);
240
	putw(3 + addpsects);		/* # of Phdrs */
241
	putw(Shdr64sz);
242
	if(debug['S']){
243
		putw(3);		/* # of Shdrs */
244
		putw(2);		/* Shdr table index */
245
	}else{
246
		putw(0);
247
		putw(0);
248
	}
249
 
250
	elf64phdr(putl, putll, PT_LOAD, HEADR, INITTEXT, INITTEXTP,
251
		textsize, textsize, R|X, INITRND);	/* text */
252
	/*
253
	 * see 32-bit ELF case for physical data address computation.
254
	 */
255
	phydata = INITDAT - (INITTEXT - INITTEXTP);
256
	elf64phdr(putl, putll, PT_LOAD, HEADR+textsize, INITDAT, phydata,
257
		datsize, datsize+bsssize, R|W, INITRND); /* data */
258
	elf64phdr(putl, putll, NOPTYPE, HEADR+textsize+datsize, 0, 0,
259
		symsize, lcsize, R, 4);			/* symbol table */
260
	if (addpsects > 0)
261
		putpsects(putl);
262
	cflush();
263
 
264
	if(debug['S'])
265
		elf64sectab(putl, putll);
266
}