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