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 } 267