coff32write.c (6703B)
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, *name; 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 if (ent->n_zeroes == 0) { 180 name = &coff->strtbl[ent->n_offset]; 181 len = strlen(name) + 1; 182 if (len > strsiz - LONG_MAX) 183 goto err; 184 s = realloc(strtbl, strsiz + len); 185 if (!s) 186 goto err; 187 memcpy(s + strsiz, name, len); 188 strtbl = s; 189 strsiz += len; 190 } 191 192 pack_ent(ORDER(obj->type), buf, ent); 193 if (fwrite(buf, SYMESZ, 1, fp) != 1) 194 return 0; 195 } 196 197 free(coff->strtbl); 198 coff->strtbl = strtbl; 199 coff->strsiz = strsiz; 200 201 return 1; 202 203 err: 204 free(strtbl); 205 return 0; 206 } 207 208 static int 209 writestr(Obj *obj, FILE *fp) 210 { 211 struct coff32 *coff; 212 unsigned char buf[4]; 213 214 coff = obj->data; 215 if ((coff->strsiz & 0xffff) != coff->strsiz) 216 return 0; 217 218 pack(ORDER(obj->type), buf, "l", coff->strsiz); 219 fwrite(buf, 4, 1, fp); 220 fwrite(coff->strtbl, coff->strsiz, 1, fp); 221 222 return 1; 223 } 224 225 static int 226 writeaout(Obj *obj, FILE *fp) 227 { 228 FILHDR *hdr; 229 struct coff32 *coff; 230 unsigned char buf[AOUTSZ]; 231 232 coff = obj->data; 233 hdr = &coff->hdr; 234 235 if (hdr->f_opthdr == 0) 236 return 1; 237 pack_aout(ORDER(obj->type), buf, &coff->aout); 238 239 return fread(buf, AOUTSZ, 1, fp) != 1; 240 } 241 242 static int 243 writereloc(Obj *obj, FILE *fp) 244 { 245 int i, j; 246 RELOC *rp; 247 SCNHDR *scn; 248 FILHDR *hdr; 249 struct coff32 *coff; 250 unsigned char buf[RELSZ]; 251 252 coff = obj->data; 253 hdr = &coff->hdr; 254 255 if (!coff->rels) 256 return 1; 257 258 for (i = 0; i < hdr->f_nscns; i++) { 259 rp = coff->rels[i]; 260 if (!rp) 261 continue; 262 scn = &coff->scns[i]; 263 264 for (j = 0; j < scn->s_nrelloc; j++) { 265 pack_reloc(ORDER(obj->type), buf, &rp[i]); 266 if (fwrite(buf, RELSZ, 1, fp) != 1) 267 return 0; 268 } 269 } 270 271 return 1; 272 } 273 274 static int 275 writelines(Obj *obj, FILE *fp) 276 { 277 int i; 278 long j; 279 LINENO *lp; 280 SCNHDR *scn; 281 struct coff32 *coff = obj->data; 282 FILHDR *hdr = &coff->hdr; 283 unsigned char buf[LINESZ]; 284 285 if (!coff->lines) 286 return 1; 287 288 for (i = 0; i < hdr->f_nscns; i++) { 289 lp = coff->lines[i]; 290 if (!lp) 291 continue; 292 scn = &coff->scns[i]; 293 for (j = 0; j < scn->s_nlnno; j++) { 294 pack_line(ORDER(obj->type), buf, &lp[j]); 295 if (fwrite(buf, LINESZ, 1, fp) == 1) 296 return 0; 297 } 298 } 299 300 return 1; 301 } 302 303 static int 304 writedata(Obj *obj, Map *map, FILE *fp) 305 { 306 int id; 307 long nsec; 308 unsigned long long n; 309 struct coff32 *coff = obj->data; 310 FILHDR *hdr = &coff->hdr; 311 SCNHDR *scn; 312 Mapsec *sec; 313 314 nsec = hdr->f_nscns; 315 for (scn = coff->scns; nsec--; scn++) { 316 if ((id = findsec(map, scn->s_name)) < 0) 317 continue; 318 sec = &map->sec[id]; 319 if (!sec->fp) 320 continue; 321 322 fseek(sec->fp, sec->offset, SEEK_SET); 323 324 for (n = sec->end - sec->begin; n > 0; n--) 325 putc(getc(sec->fp), fp); 326 327 if (ferror(sec->fp)) 328 return 0; 329 } 330 331 return 1; 332 } 333 334 int 335 coff32write(Obj *obj, Map *map, FILE *fp) 336 { 337 int id; 338 long ptr, n; 339 SCNHDR *scn; 340 Mapsec *sec; 341 struct coff32 *coff = obj->data; 342 FILHDR *hdr = &coff->hdr; 343 344 ptr = ftell(fp); 345 obj->pos = ptr; 346 347 n = hdr->f_nscns; 348 ptr += FILHSZ + hdr->f_opthdr + n*SCNHSZ; 349 for (scn = coff->scns; n--; scn++) { 350 scn->s_scnptr = 0; 351 if ((id = findsec(map, scn->s_name)) < 0) 352 continue; 353 sec = &map->sec[id]; 354 if (!sec->fp) 355 continue; 356 357 scn->s_scnptr = ptr; 358 ptr += scn->s_size; 359 } 360 hdr->f_symptr = (hdr->f_nsyms > 0) ? ptr : 0; 361 362 n = hdr->f_nscns; 363 for (scn = coff->scns; n--; scn++) { 364 scn->s_relptr = ptr; 365 ptr += scn->s_nrelloc * RELSZ; 366 } 367 368 n = hdr->f_nscns; 369 for (scn = coff->scns; n--; scn++) { 370 scn->s_lnnoptr = ptr; 371 ptr += scn->s_nlnno * RELSZ; 372 } 373 374 /* and now update symbols */ 375 376 if (!writehdr(obj, fp)) 377 return -1; 378 if (!writeaout(obj, fp)) 379 return -1; 380 if (!writescns(obj, fp)) 381 return -1; 382 if (!writedata(obj, map, fp)) 383 return -1; 384 if (!writereloc(obj, fp)) 385 return -1; 386 if (!writelines(obj, fp)) 387 return -1; 388 if (!writeents(obj, fp)) 389 return -1; 390 if (!writestr(obj, fp)) 391 return -1; 392 if (ferror(fp)) 393 return -1; 394 395 return 0; 396 }