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