coff32write.c (9448B)
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 #include <scc/coff32.h> 10 11 #include "../libmach.h" 12 13 struct strtbl { 14 char *s; 15 long siz; 16 }; 17 18 static void 19 pack_hdr(int order, unsigned char *buf, FILHDR *hdr) 20 { 21 int n; 22 23 n = pack(order, 24 buf, 25 "sslllss", 26 hdr->f_magic, 27 hdr->f_nscns, 28 hdr->f_timdat, 29 hdr->f_symptr, 30 hdr->f_nsyms, 31 hdr->f_opthdr, 32 hdr->f_flags); 33 assert(n == FILHSZ); 34 } 35 36 static void 37 pack_scn(int order, unsigned char *buf, SCNHDR *scn) 38 { 39 int n; 40 41 if (scn->s_zeroes == 0) 42 pack(order, buf, "ll", scn->s_zeroes, scn->s_offset); 43 else 44 memcpy(buf, scn->s_name, 8); 45 46 n = pack(order, 47 buf + 8, 48 "llllllssl", 49 scn->s_paddr, 50 scn->s_vaddr, 51 scn->s_size, 52 scn->s_scnptr, 53 scn->s_relptr, 54 scn->s_lnnoptr, 55 scn->s_nrelloc, 56 scn->s_nlnno, 57 scn->s_flags); 58 n += 8; 59 assert(n == SCNHSZ); 60 } 61 62 static void 63 pack_ent(int order, unsigned char *buf, SYMENT *ent) 64 { 65 int n; 66 67 if (ent->n_zeroes == 0) 68 pack(order, buf, "ll", ent->n_zeroes, ent->n_offset); 69 else 70 memcpy(buf, ent->n_name, 8); 71 72 n = pack(order, 73 buf + 8, 74 "lsscc", 75 ent->n_value, 76 ent->n_scnum, 77 ent->n_type, 78 ent->n_sclass, 79 ent->n_numaux); 80 n += 8; 81 82 assert(n == SYMESZ); 83 } 84 85 static void 86 pack_aux_file(int order, unsigned char *buf, AUXENT *aux) 87 { 88 89 if (aux->x_zeroes == 0) { 90 memset(buf, 0, sizeof(AUXESZ)); 91 pack(order, buf, "ll", aux->x_zeroes, aux->x_offset); 92 } else { 93 memcpy(buf, aux->x_fname, E_FILNMLEN); 94 } 95 } 96 97 static void 98 pack_aux_scn(int order, unsigned char *buf, AUXENT *aux) 99 { 100 int n; 101 102 n = pack(order, 103 buf, 104 "lsslsc", 105 aux->x_scnlen, 106 aux->x_nreloc, 107 aux->x_nlinno, 108 aux->x_checksum, 109 aux->x_associated, 110 aux->x_comdat); 111 assert(n == AUXESZ); 112 } 113 114 static void 115 pack_aux_fun(int order, unsigned char *buf, AUXENT *aux) 116 { 117 int n; 118 119 n = pack(order, 120 buf, 121 "lllls", 122 aux->x_tagndx, 123 aux->x_fsize, 124 aux->x_lnnoptr, 125 aux->x_endndx, 126 aux->x_tvndx); 127 assert(n == AUXESZ); 128 } 129 130 static void 131 pack_aux_ary(int order, unsigned char *buf, AUXENT *aux) 132 { 133 int n; 134 135 n = pack(order, 136 buf, 137 "lssssss", 138 aux->x_tagndx, 139 aux->x_lnno, 140 aux->x_size, 141 aux->x_dimen[0], 142 aux->x_dimen[1], 143 aux->x_dimen[2], 144 aux->x_dimen[3], 145 aux->x_tvndx); 146 assert(n == AUXESZ); 147 } 148 149 static void 150 pack_aux_sym(int order, unsigned char *buf, AUXENT *aux) 151 { 152 int n; 153 154 n = pack(order, 155 buf, 156 "lsslls", 157 aux->x_tagndx, 158 aux->x_lnno, 159 aux->x_size, 160 aux->x_lnnoptr, 161 aux->x_endndx, 162 aux->x_tvndx); 163 assert(n == AUXESZ); 164 } 165 166 static void 167 pack_aout(int order, unsigned char *buf, AOUTHDR *aout) 168 { 169 int n; 170 171 n = pack(order, 172 buf, 173 "ssllllll", 174 aout->magic, 175 aout->vstamp, 176 aout->tsize, 177 aout->dsize, 178 aout->bsize, 179 aout->entry, 180 aout->text_start, 181 aout->data_start); 182 assert(n == AOUTSZ); 183 } 184 185 static void 186 pack_reloc(int order, unsigned char *buf, RELOC *rel) 187 { 188 int n; 189 190 n = pack(order, 191 buf, 192 "lls", 193 rel->r_vaddr, 194 rel->r_symndx, 195 rel->r_type); 196 assert(n == RELSZ); 197 } 198 199 static void 200 pack_line(int order, unsigned char *buf, LINENO *lp) 201 { 202 int n; 203 204 n = pack(order, 205 buf, 206 "lls", 207 lp->l_addr.l_symndx, 208 lp->l_lnno); 209 assert(n == LINESZ); 210 } 211 212 static int 213 writehdr(Obj *obj, FILE *fp) 214 { 215 FILHDR *hdr; 216 struct coff32 *coff; 217 unsigned char buf[FILHSZ]; 218 219 coff = obj->data; 220 hdr = &coff->hdr; 221 222 pack_hdr(ORDER(obj->type), buf, hdr); 223 if (fwrite(buf, FILHSZ, 1, fp) != 1) 224 return 0; 225 226 return 1; 227 } 228 229 static int 230 allocstring(struct coff32 *coff, long off, struct strtbl *tbl) 231 { 232 char *s, *name; 233 long len, siz; 234 235 siz = tbl->siz; 236 name = &coff->strtbl[off]; 237 len = strlen(name) + 1; 238 if (len > siz - LONG_MAX) 239 return 0; 240 241 s = realloc(tbl->s, siz + len); 242 if (!s) 243 return 0; 244 memcpy(s + siz, name, len); 245 246 tbl->s = s; 247 tbl->siz += len; 248 249 return 1; 250 } 251 252 static int 253 writescns(Obj *obj, FILE *fp, struct strtbl *tbl) 254 { 255 int i; 256 SCNHDR *scn; 257 FILHDR *hdr; 258 struct coff32 *coff; 259 unsigned char buf[SCNHSZ]; 260 261 coff = obj->data; 262 hdr = &coff->hdr; 263 264 for (i = 0; i < hdr->f_nscns; i++) { 265 scn = &coff->scns[i]; 266 if (scn->s_zeroes == 0) { 267 if (!allocstring(coff, scn->s_offset, tbl)) 268 return 0; 269 } 270 pack_scn(ORDER(obj->type), buf, scn); 271 if (fwrite(buf, SCNHSZ, 1, fp) != 1) 272 return 0; 273 } 274 275 return 1; 276 } 277 278 static int 279 writeents(Obj *obj, FILE *fp, struct strtbl *tbl) 280 { 281 long i; 282 FILHDR *hdr; 283 struct coff32 *coff; 284 unsigned char buf[SYMESZ]; 285 286 coff = obj->data; 287 hdr = &coff->hdr; 288 289 if (!coff->ents) 290 return 1; 291 292 for (i = 0; i < hdr->f_nsyms; i++) { 293 SYMENT *ent; 294 AUXENT *aux; 295 Entry *ep = &coff->ents[i]; 296 297 aux = &ep->u.aux; 298 switch (ep->type) { 299 case SYM_ENT: 300 ent = &ep->u.sym; 301 if (ent->n_zeroes == 0) { 302 if (!allocstring(coff, ent->n_offset, tbl)) 303 return 0; 304 } 305 pack_ent(ORDER(obj->type), buf, ent); 306 break; 307 case SYM_AUX_UNK: 308 memcpy(buf, ep->u.buf, AUXESZ); 309 break; 310 case SYM_AUX_SYM: 311 pack_aux_file(ORDER(obj->type), buf, aux); 312 break; 313 case SYM_AUX_FILE: 314 if (aux->x_zeroes == 0) { 315 if (!allocstring(coff, aux->x_offset, tbl)) 316 return 0; 317 } 318 pack_aux_file(ORDER(obj->type), buf, aux); 319 break; 320 case SYM_AUX_SCN: 321 pack_aux_scn(ORDER(obj->type), buf, aux); 322 break; 323 case SYM_AUX_FUN: 324 pack_aux_fun(ORDER(obj->type), buf, aux); 325 break; 326 case SYM_AUX_ARY: 327 pack_aux_ary(ORDER(obj->type), buf, aux); 328 break; 329 } 330 331 if (fwrite(buf, SYMESZ, 1, fp) != 1) 332 return 0; 333 } 334 335 return 1; 336 } 337 338 static int 339 writestr(Obj *obj, FILE *fp, struct strtbl *tbl) 340 { 341 struct coff32 *coff; 342 unsigned char buf[4]; 343 344 coff = obj->data; 345 346 free(coff->strtbl); 347 coff->strtbl = tbl->s; 348 coff->strsiz = tbl->siz; 349 tbl->s = NULL; 350 tbl->siz = 0; 351 352 if ((coff->strsiz & 0xffff) != coff->strsiz) 353 return 0; 354 355 pack(ORDER(obj->type), buf, "l", coff->strsiz); 356 fwrite(buf, 4, 1, fp); 357 fwrite(coff->strtbl, coff->strsiz, 1, fp); 358 359 return 1; 360 } 361 362 static int 363 writeaout(Obj *obj, FILE *fp) 364 { 365 FILHDR *hdr; 366 struct coff32 *coff; 367 unsigned char buf[AOUTSZ]; 368 369 coff = obj->data; 370 hdr = &coff->hdr; 371 372 if (hdr->f_opthdr == 0) 373 return 1; 374 pack_aout(ORDER(obj->type), buf, &coff->aout); 375 376 return fread(buf, AOUTSZ, 1, fp) != 1; 377 } 378 379 static int 380 writereloc(Obj *obj, FILE *fp) 381 { 382 int i, j; 383 RELOC *rp; 384 SCNHDR *scn; 385 FILHDR *hdr; 386 struct coff32 *coff; 387 unsigned char buf[RELSZ]; 388 389 coff = obj->data; 390 hdr = &coff->hdr; 391 392 if (!coff->rels) 393 return 1; 394 395 for (i = 0; i < hdr->f_nscns; i++) { 396 rp = coff->rels[i]; 397 if (!rp) 398 continue; 399 scn = &coff->scns[i]; 400 401 for (j = 0; j < scn->s_nrelloc; j++) { 402 pack_reloc(ORDER(obj->type), buf, &rp[i]); 403 if (fwrite(buf, RELSZ, 1, fp) != 1) 404 return 0; 405 } 406 } 407 408 return 1; 409 } 410 411 static int 412 writelines(Obj *obj, FILE *fp) 413 { 414 int i; 415 long j; 416 LINENO *lp; 417 SCNHDR *scn; 418 struct coff32 *coff = obj->data; 419 FILHDR *hdr = &coff->hdr; 420 unsigned char buf[LINESZ]; 421 422 if (!coff->lines) 423 return 1; 424 425 for (i = 0; i < hdr->f_nscns; i++) { 426 lp = coff->lines[i]; 427 if (!lp) 428 continue; 429 scn = &coff->scns[i]; 430 for (j = 0; j < scn->s_nlnno; j++) { 431 pack_line(ORDER(obj->type), buf, &lp[j]); 432 if (fwrite(buf, LINESZ, 1, fp) == 1) 433 return 0; 434 } 435 } 436 437 return 1; 438 } 439 440 static int 441 writedata(Obj *obj, Map *map, FILE *fp) 442 { 443 int id; 444 long nsec; 445 unsigned long long n; 446 struct coff32 *coff = obj->data; 447 FILHDR *hdr = &coff->hdr; 448 SCNHDR *scn; 449 Mapsec *sec; 450 451 nsec = hdr->f_nscns; 452 for (scn = coff->scns; nsec--; scn++) { 453 if ((id = findsec(map, scn->s_name)) < 0) 454 continue; 455 sec = &map->sec[id]; 456 if (!sec->fp) 457 continue; 458 459 fseek(sec->fp, sec->offset, SEEK_SET); 460 461 for (n = sec->end - sec->begin; n > 0; n--) 462 putc(getc(sec->fp), fp); 463 464 if (ferror(sec->fp)) 465 return 0; 466 } 467 468 return 1; 469 } 470 471 int 472 coff32write(Obj *obj, Map *map, FILE *fp) 473 { 474 int id; 475 long ptr, n; 476 SCNHDR *scn; 477 Mapsec *sec; 478 struct strtbl tbl; 479 struct coff32 *coff = obj->data; 480 FILHDR *hdr = &coff->hdr; 481 482 ptr = ftell(fp); 483 obj->pos = ptr; 484 tbl.s = NULL; 485 tbl.siz = 0; 486 487 n = hdr->f_nscns; 488 ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ; 489 for (scn = coff->scns; n--; scn++) { 490 scn->s_scnptr = 0; 491 if ((id = findsec(map, scn->s_name)) < 0) 492 continue; 493 sec = &map->sec[id]; 494 if (!sec->fp) 495 continue; 496 497 scn->s_scnptr = ptr; 498 ptr += scn->s_size; 499 } 500 hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0; 501 502 n = hdr->f_nscns; 503 for (scn = coff->scns; n--; scn++) { 504 scn->s_relptr = (scn->s_nrelloc > 0) ? ptr : 0; 505 ptr += scn->s_nrelloc * RELSZ; 506 } 507 508 n = hdr->f_nscns; 509 for (scn = coff->scns; n--; scn++) { 510 scn->s_lnnoptr = (scn->s_nlnno > 0) ? ptr : 0; 511 ptr += scn->s_nlnno * RELSZ; 512 } 513 514 /* and now update symbols */ 515 516 if (!writehdr(obj, fp)) 517 goto err; 518 if (!writeaout(obj, fp)) 519 goto err; 520 if (!writescns(obj, fp, &tbl)) 521 goto err; 522 if (!writedata(obj, map, fp)) 523 goto err; 524 if (!writereloc(obj, fp)) 525 goto err; 526 if (!writelines(obj, fp)) 527 goto err; 528 if (!writeents(obj, fp, &tbl)) 529 goto err; 530 if (!writestr(obj, fp, &tbl)) 531 goto err; 532 if (ferror(fp)) 533 goto err; 534 return 0; 535 536 err: 537 free(tbl.s); 538 return -1; 539 }