coff32write.c (6354B)
1 #include <assert.h> 2 #include <limits.h> 3 #include <stdint.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <scc/mach.h> 9 10 #include "../libmach.h" 11 #include "coff32.h" 12 13 static void 14 pack_hdr(int order, unsigned char *buf, FILHDR *hdr) 15 { 16 int n; 17 18 n = pack(order, 19 buf, 20 "sslllss", 21 hdr->f_magic, 22 hdr->f_nscns, 23 hdr->f_timdat, 24 hdr->f_symptr, 25 hdr->f_nsyms, 26 hdr->f_opthdr, 27 hdr->f_flags); 28 assert(n == FILHSZ); 29 } 30 31 static void 32 pack_scn(int order, unsigned char *buf, SCNHDR *scn) 33 { 34 int n; 35 36 n = pack(order, 37 buf, 38 "'8llllllssl", 39 scn->s_name, 40 scn->s_paddr, 41 scn->s_vaddr, 42 scn->s_size, 43 scn->s_scnptr, 44 scn->s_relptr, 45 scn->s_lnnoptr, 46 scn->s_nrelloc, 47 scn->s_nlnno, 48 scn->s_flags); 49 assert(n == SCNHSZ); 50 } 51 52 static void 53 pack_ent(int order, unsigned char *buf, SYMENT *ent) 54 { 55 int n; 56 char *s; 57 58 /* TODO: What happens with the union? */ 59 60 n = pack(order, 61 buf, 62 "'8lsscc", 63 ent->n_name, 64 ent->n_value, 65 ent->n_scnum, 66 ent->n_type, 67 ent->n_sclass, 68 ent->n_numaux); 69 assert(n == SYMESZ); 70 } 71 72 static void 73 pack_aout(int order, unsigned char *buf, AOUTHDR *aout) 74 { 75 int n; 76 77 n = pack(order, 78 buf, 79 "ssllllll", 80 aout->magic, 81 aout->vstamp, 82 aout->tsize, 83 aout->dsize, 84 aout->bsize, 85 aout->entry, 86 aout->text_start, 87 aout->data_start); 88 assert(n == AOUTSZ); 89 } 90 91 static void 92 pack_reloc(int order, unsigned char *buf, RELOC *rel) 93 { 94 int n; 95 96 n = pack(order, 97 buf, 98 "lls", 99 rel->r_vaddr, 100 rel->r_symndx, 101 rel->r_type); 102 assert(n == RELSZ); 103 } 104 105 static void 106 pack_line(int order, unsigned char *buf, LINENO *lp) 107 { 108 int n; 109 110 n = pack(order, 111 buf, 112 "lls", 113 lp->l_symndx, 114 lp->l_paddr, 115 lp->l_lnno); 116 assert(n == LINESZ); 117 } 118 119 static int 120 writehdr(Obj *obj, FILE *fp) 121 { 122 FILHDR *hdr; 123 struct coff32 *coff; 124 unsigned char buf[FILHSZ]; 125 126 coff = obj->data; 127 hdr = &coff->hdr; 128 129 pack_hdr(ORDER(obj->type), buf, hdr); 130 if (fwrite(buf, FILHSZ, 1, fp) != 1) 131 return 0; 132 133 return 1; 134 } 135 136 static int 137 writescns(Obj *obj, FILE *fp) 138 { 139 int i; 140 SCNHDR *scn; 141 FILHDR *hdr; 142 struct coff32 *coff; 143 unsigned char buf[SCNHSZ]; 144 145 coff = obj->data; 146 hdr = &coff->hdr; 147 148 for (i = 0; i < hdr->f_nscns; i++) { 149 scn = &coff->scns[i]; 150 pack_scn(ORDER(obj->type), buf, scn); 151 if (fwrite(buf, SCNHSZ, 1, fp) != 1) 152 return 0; 153 } 154 155 return 1; 156 } 157 158 static int 159 writeents(Obj *obj, FILE *fp) 160 { 161 long i, len, strsiz; 162 char *strtbl, *s; 163 FILHDR *hdr; 164 struct coff32 *coff; 165 unsigned char buf[SYMESZ]; 166 167 coff = obj->data; 168 hdr = &coff->hdr; 169 170 if (!coff->ents) 171 return 1; 172 173 strtbl = NULL; 174 strsiz = 0; 175 176 for (i = 0; i < hdr->f_nsyms; i++) { 177 SYMENT *ent = &coff->ents[i]; 178 179 len = strlen(ent->n_name) + 1; 180 if (len > strsiz - LONG_MAX) 181 goto err; 182 s = realloc(strtbl, strsiz + len); 183 if (!s) 184 goto err; 185 memcpy(s + strsiz, ent->n_name, len); 186 strtbl = s; 187 strsiz += len; 188 189 pack_ent(ORDER(obj->type), buf, ent); 190 if (fwrite(buf, SYMESZ, 1, fp) != 1) 191 return 0; 192 } 193 194 free(coff->strtbl); 195 coff->strtbl = strtbl; 196 coff->strsiz = strsiz; 197 198 return 1; 199 200 err: 201 free(strtbl); 202 return 0; 203 } 204 205 static int 206 writestr(Obj *obj, FILE *fp) 207 { 208 struct coff32 *coff; 209 unsigned char buf[4]; 210 211 coff = obj->data; 212 if ((coff->strsiz & 0xffff) != coff->strsiz) 213 return 0; 214 215 pack(ORDER(obj->type), buf, "l", coff->strsiz); 216 fwrite(buf, 4, 1, fp); 217 fwrite(coff->strtbl, coff->strsiz, 1, fp); 218 219 return ferror(fp) == 0; 220 } 221 222 static int 223 writeaout(Obj *obj, FILE *fp) 224 { 225 FILHDR *hdr; 226 struct coff32 *coff; 227 unsigned char buf[AOUTSZ]; 228 229 coff = obj->data; 230 hdr = &coff->hdr; 231 232 if (hdr->f_opthdr == 0) 233 return 1; 234 pack_aout(ORDER(obj->type), buf, &coff->aout); 235 236 return fread(buf, AOUTSZ, 1, fp) != 1; 237 } 238 239 static int 240 writereloc(Obj *obj, FILE *fp) 241 { 242 int i, j; 243 RELOC *rp; 244 SCNHDR *scn; 245 FILHDR *hdr; 246 struct coff32 *coff; 247 unsigned char buf[RELSZ]; 248 249 coff = obj->data; 250 hdr = &coff->hdr; 251 252 if (!coff->rels) 253 return 1; 254 255 for (i = 0; i < hdr->f_nscns; i++) { 256 rp = coff->rels[i]; 257 if (!rp) 258 continue; 259 scn = &coff->scns[i]; 260 261 for (j = 0; j < scn->s_nrelloc; j++) { 262 pack_reloc(ORDER(obj->type), buf, &rp[i]); 263 if (fwrite(buf, RELSZ, 1, fp) != 1) 264 return 0; 265 } 266 } 267 268 return 1; 269 } 270 271 static int 272 writelines(Obj *obj, FILE *fp) 273 { 274 int i; 275 long j; 276 LINENO *lp; 277 SCNHDR *scn; 278 struct coff32 *coff = obj->data; 279 FILHDR *hdr = &coff->hdr; 280 unsigned char buf[LINESZ]; 281 282 if (!coff->lines) 283 return 1; 284 285 for (i = 0; i < hdr->f_nscns; i++) { 286 lp = coff->lines[i]; 287 if (!lp) 288 continue; 289 scn = &coff->scns[i]; 290 for (j = 0; j < scn->s_nlnno; j++) { 291 pack_line(ORDER(obj->type), buf, &lp[j]); 292 if (fwrite(buf, LINESZ, 1, fp) == 1) 293 return 0; 294 } 295 } 296 297 return 1; 298 } 299 300 static int 301 writedata(Obj *obj, Map *map, FILE *fp) 302 { 303 int id; 304 long nsec; 305 unsigned long long n; 306 struct coff32 *coff = obj->data; 307 FILHDR *hdr = &coff->hdr; 308 SCNHDR *scn; 309 Mapsec *sec; 310 311 nsec = hdr->f_nscns; 312 for (scn = coff->scns; nsec--; scn++) { 313 if ((id = findsec(map, scn->s_name)) < 0) 314 return 0; 315 sec = &map->sec[id]; 316 fseek(sec->fp, sec->offset, SEEK_SET); 317 318 for (n = sec->end - sec->begin; n > 0; n--) 319 putc(getc(sec->fp), fp); 320 } 321 322 return !ferror(fp); 323 } 324 325 int 326 coff32write(Obj *obj, Map *map, FILE *fp) 327 { 328 long ptr, n; 329 SCNHDR *scn; 330 struct coff32 *coff = obj->data; 331 FILHDR *hdr = &coff->hdr; 332 333 ptr = ftell(fp); 334 obj->pos = ptr; 335 ptr += FILHSZ + AOUTSZ + n*hdr->f_nscns; 336 337 n = hdr->f_nscns; 338 for (scn = coff->scns; n--; scn++) { 339 scn->s_scnptr = ptr; 340 ptr += scn->s_size; 341 } 342 343 n = hdr->f_nscns; 344 for (scn = coff->scns; n--; scn++) { 345 scn->s_relptr = ptr; 346 ptr += scn->s_nrelloc * RELSZ; 347 } 348 349 n = hdr->f_nscns; 350 for (scn = coff->scns; n--; scn++) { 351 scn->s_lnnoptr = ptr; 352 ptr += scn->s_nlnno * RELSZ; 353 } 354 355 /* and now update symbols */ 356 357 if (!writehdr(obj, fp)) 358 return -1; 359 if (!writeaout(obj, fp)) 360 return -1; 361 if (!writescns(obj, fp)) 362 return -1; 363 if (!writedata(obj, map, fp)) 364 return -1; 365 if (!writereloc(obj, fp)) 366 return -1; 367 if (!writelines(obj, fp)) 368 return -1; 369 if (!writeents(obj, fp)) 370 return -1; 371 if (!writestr(obj, fp)) 372 return -1; 373 374 return 0; 375 }