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
elfident(int bo,int class)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
elfstrtab(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
elf32phdr(void (* putl)(long),ulong type,ulong off,ulong vaddr,ulong paddr,ulong filesz,ulong memsz,ulong prots,ulong align)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
elf32shdr(void (* putl)(long),ulong name,ulong type,ulong flags,ulong vaddr,ulong off,ulong sectsz,ulong link,ulong addnl,ulong align,ulong entsz)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
elf32sectab(void (* putl)(long))78 elf32sectab(void (*putl)(long))
79 {
80 seek(cout, HEADR+textsize+datsize+symsize, 0);
81 elf32shdr(putl, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0);
83 elf32shdr(putl, Stitext, Progbits, Salloc|Sexec, INITTEXT,
84 HEADR, textsize, 0, 0, INITRND, 0);
85 elf32shdr(putl, Stidata, Progbits, Salloc|Swrite, INITDAT,
86 HEADR+textsize, datsize, 0, 0, INITRND, 0);
87 elf32shdr(putl, Stistrtab, Strtab, 1 << 5, 0,
88 HEADR+textsize+datsize+symsize+4*Shdr32sz, 22, 0, 0, 1, 0);
89 elfstrtab();
90 }
91
92 /* if addpsects > 0, putpsects must emit exactly that many psects. */
93 void
elf32(int mach,int bo,int addpsects,void (* putpsects)(Putl))94 elf32(int mach, int bo, int addpsects, void (*putpsects)(Putl))
95 {
96 ulong phydata;
97 void (*putw)(long), (*putl)(long);
98
99 if(bo == ELFDATA2MSB){
100 putw = wput;
101 putl = lput;
102 }else if(bo == ELFDATA2LSB){
103 putw = wputl;
104 putl = lputl;
105 }else{
106 print("elf32 byte order is mixed-endian\n");
107 errorexit();
108 return;
109 }
110
111 elfident(bo, ELFCLASS32);
112 putw(EXEC);
113 putw(mach);
114 putl(1L); /* version = CURRENT */
115 putl(entryvalue()); /* entry vaddr */
116 putl(Ehdr32sz); /* offset to first phdr */
117 if(debug['S'])
118 putl(HEADR+textsize+datsize+symsize); /* offset to first shdr */
119 else
120 putl(0);
121 putl(0L); /* flags */
122 putw(Ehdr32sz);
123 putw(Phdr32sz);
124 putw(3 + addpsects); /* # of Phdrs */
125 putw(Shdr32sz);
126 if(debug['S']){
127 putw(4); /* # of Shdrs */
128 putw(3); /* Shdr table index */
129 }else{
130 putw(0);
131 putw(0);
132 }
133
134 /*
135 * could include ELF headers in text -- 8l doesn't,
136 * but in theory it aids demand loading.
137 */
138 elf32phdr(putl, PT_LOAD, HEADR, INITTEXT, INITTEXTP,
139 textsize, textsize, R|X, INITRND); /* text */
140 /*
141 * we need INITDATP, but it has to be computed.
142 * assume distance between INITTEXT & INITTEXTP is also
143 * correct for INITDAT and INITDATP.
144 */
145 phydata = INITDAT - (INITTEXT - INITTEXTP);
146 elf32phdr(putl, PT_LOAD, HEADR+textsize, INITDAT, phydata,
147 datsize, datsize+bsssize, R|W|X, INITRND); /* data */
148 elf32phdr(putl, NOPTYPE, HEADR+textsize+datsize, 0, 0,
149 symsize, lcsize, R, 4); /* symbol table */
150 if (addpsects > 0)
151 putpsects(putl);
152 cflush();
153
154 if(debug['S'])
155 elf32sectab(putl);
156 }
157
158 /*
159 * elf64
160 */
161
162 void
elf64phdr(void (* putl)(long),void (* putll)(vlong),ulong type,uvlong off,uvlong vaddr,uvlong paddr,uvlong filesz,uvlong memsz,ulong prots,uvlong align)163 elf64phdr(void (*putl)(long), void (*putll)(vlong), ulong type, uvlong off,
164 uvlong vaddr, uvlong paddr, uvlong filesz, uvlong memsz, ulong prots,
165 uvlong align)
166 {
167 putl(type);
168 putl(prots);
169 putll(off);
170 putll(vaddr);
171 putll(paddr);
172 putll(filesz);
173 putll(memsz);
174 putll(align);
175 }
176
177 void
elf64shdr(void (* putl)(long),void (* putll)(vlong),ulong name,ulong type,uvlong flags,uvlong vaddr,uvlong off,uvlong sectsz,ulong link,ulong addnl,uvlong align,uvlong entsz)178 elf64shdr(void (*putl)(long), void (*putll)(vlong), ulong name, ulong type,
179 uvlong flags, uvlong vaddr, uvlong off, uvlong sectsz, ulong link,
180 ulong addnl, uvlong align, uvlong entsz)
181 {
182 putl(name);
183 putl(type);
184 putll(flags);
185 putll(vaddr);
186 putll(off);
187 putll(sectsz);
188 putl(link);
189 putl(addnl);
190 putll(align);
191 putll(entsz);
192 }
193
194 static void
elf64sectab(void (* putl)(long),void (* putll)(vlong))195 elf64sectab(void (*putl)(long), void (*putll)(vlong))
196 {
197 seek(cout, HEADR+textsize+datsize+symsize, 0);
198 elf64shdr(putl, putll, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0);
200 elf64shdr(putl, putll, Stitext, Progbits, Salloc|Sexec, INITTEXT,
201 HEADR, textsize, 0, 0, INITRND, 0);
202 elf64shdr(putl, putll, Stidata, Progbits, Salloc|Swrite, INITDAT,
203 HEADR+textsize, datsize, 0, 0, INITRND, 0);
204 elf64shdr(putl, putll, Stistrtab, Strtab, 1 << 5, 0,
205 HEADR+textsize+datsize+symsize+4*Shdr64sz, 22, 0, 0, 1, 0);
206 elfstrtab();
207 }
208
209 /* if addpsects > 0, putpsects must emit exactly that many psects. */
210 void
elf64(int mach,int bo,int addpsects,void (* putpsects)(Putl))211 elf64(int mach, int bo, int addpsects, void (*putpsects)(Putl))
212 {
213 uvlong phydata;
214 void (*putw)(long), (*putl)(long);
215 void (*putll)(vlong);
216
217 if(bo == ELFDATA2MSB){
218 putw = wput;
219 putl = lput;
220 putll = llput;
221 }else if(bo == ELFDATA2LSB){
222 putw = wputl;
223 putl = lputl;
224 putll = llputl;
225 }else{
226 print("elf64 byte order is mixed-endian\n");
227 errorexit();
228 return;
229 }
230
231 elfident(bo, ELFCLASS64);
232 putw(EXEC);
233 putw(mach);
234 putl(1L); /* version = CURRENT */
235 putll(entryvalue()); /* entry vaddr */
236 putll(Ehdr64sz); /* offset to first phdr */
237 if(debug['S'])
238 putll(HEADR+textsize+datsize+symsize); /* offset to 1st shdr */
239 else
240 putll(0);
241 putl(0L); /* flags */
242 putw(Ehdr64sz);
243 putw(Phdr64sz);
244 putw(3 + addpsects); /* # of Phdrs */
245 putw(Shdr64sz);
246 if(debug['S']){
247 putw(4); /* # of Shdrs */
248 putw(3); /* Shdr table index */
249 }else{
250 putw(0);
251 putw(0);
252 }
253
254 elf64phdr(putl, putll, PT_LOAD, HEADR, INITTEXT, INITTEXTP,
255 textsize, textsize, R|X, INITRND); /* text */
256 /*
257 * see 32-bit ELF case for physical data address computation.
258 */
259 phydata = INITDAT - (INITTEXT - INITTEXTP);
260 elf64phdr(putl, putll, PT_LOAD, HEADR+textsize, INITDAT, phydata,
261 datsize, datsize+bsssize, R|W, INITRND); /* data */
262 elf64phdr(putl, putll, NOPTYPE, HEADR+textsize+datsize, 0, 0,
263 symsize, lcsize, R, 4); /* symbol table */
264 if (addpsects > 0)
265 putpsects(putl);
266 cflush();
267
268 if(debug['S'])
269 elf64sectab(putl, putll);
270 }
271