coff32setsec.c (2354B)
1 #include <limits.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include <scc/mach.h> 7 #include <scc/coff32.h> 8 9 #include "../libmach.h" 10 #include "fun.h" 11 12 static char * 13 secname(Coff32 *coff, SCNHDR *scn, Section *sec) 14 { 15 char *p; 16 unsigned long siz = strlen(sec->name); 17 18 if (siz < SCNNMLEN) 19 return strncpy(scn->s_name, sec->name, SCNNMLEN); 20 21 if (coff->strsiz > ULONG_MAX - siz - 1) 22 return NULL; 23 24 siz += coff->strsiz + 1; 25 if ((p = realloc(coff->strtbl, siz)) == NULL) 26 return NULL; 27 coff->strtbl = p; 28 29 scn->s_zeroes = 0; 30 scn->s_offset = coff->strsiz; 31 coff->strsiz += siz; 32 return strcpy(&coff->strtbl[scn->s_offset], sec->name); 33 } 34 35 Section * 36 coff32setsec(Obj *obj, int *idx, Section *sec) 37 { 38 long flags, n = *idx; 39 SCNHDR *scn; 40 Coff32 *coff = obj->data; 41 FILHDR *hdr = &coff->hdr; 42 43 /* TODO: what happens with SABS? */ 44 switch (sec->type) { 45 case 'D': 46 switch (sec->flags) { 47 case SALLOC | SRELOC | SLOAD | SWRITE | SREAD: 48 if (strcmp(sec->name ,".data") == 0) 49 flags = STYP_DATA; 50 else 51 flags = STYP_REG; 52 break; 53 case SALLOC | SREAD | SWRITE: 54 flags = STYP_NOLOAD; 55 break; 56 case SALLOC | SRELOC | SLOAD | SREAD: 57 flags = STYP_RDATA; 58 break; 59 case SEXEC | SALLOC | SRELOC | SLOAD | SREAD: 60 flags = STYP_TEXT | STYP_DATA; 61 break; 62 default: 63 goto invalid; 64 } 65 break; 66 case 'T': 67 flags = STYP_TEXT; 68 break; 69 case 'B': 70 flags = STYP_BSS; 71 break; 72 case 'N': 73 case '?': 74 default: 75 invalid: 76 /* TODO */ 77 return NULL; 78 } 79 80 if (strlen(sec->name) >= SCNNMLEN) 81 return NULL; 82 83 if (n >= hdr->f_nscns) { 84 if (n > SHRT_MAX - 1) 85 return NULL; 86 scn = realloc(coff->scns, (n+1) * sizeof(SCNHDR)); 87 if (!scn) 88 return NULL; 89 coff->scns = scn; 90 hdr->f_nscns = n + 1; 91 } 92 93 scn = &coff->scns[n]; 94 if (!secname(coff, scn, sec)) 95 return NULL; 96 97 /* 98 * sec->offset is ignored because it is very unlikely 99 * that the vaule is meaningful here. The field offset 100 * was added only to allow getsec to retrive the information 101 * in a generic way, but it was never expected to be a 2 way 102 * relation. That pointer is updated when the object file 103 * is written using a mapping. 104 */ 105 scn->s_paddr = sec->load; 106 scn->s_vaddr = sec->base; 107 scn->s_size = sec->size; 108 scn->s_scnptr = 0; 109 scn->s_relptr = 0; 110 scn->s_lnnoptr = 0; 111 scn->s_nrelloc = 0; 112 scn->s_nlnno = 0; 113 scn->s_flags = flags; 114 115 return sec; 116 }