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, 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
elf32(int mach,int bo,int addpsects,void (* putpsects)(Putl))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
elf64phdr(void (* putl)(long),void (* putll)(vlong),ulong type,uvlong off,uvlong vaddr,uvlong paddr,uvlong filesz,uvlong memsz,ulong prots,uvlong align)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
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)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
elf64sectab(void (* putl)(long),void (* putll)(vlong))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
elf64(int mach,int bo,int addpsects,void (* putpsects)(Putl))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 }
267