Sym* datsort(Sym *l) { Sym *l1, *l2, *le; if(l == 0 || l->next == 0) return l; l1 = l; l2 = l; for(;;) { l2 = l2->next; if(l2 == 0) break; l2 = l2->next; if(l2 == 0) break; l1 = l1->next; } l2 = l1->next; l1->next = 0; l1 = datsort(l); l2 = datsort(l2); /* set up lead element */ if(datcmp(l1, l2) < 0) { l = l1; l1 = l1->next; } else { l = l2; l2 = l2->next; } le = l; for(;;) { if(l1 == 0) { while(l2) { le->next = l2; le = l2; l2 = l2->next; } le->next = 0; break; } if(l2 == 0) { while(l1) { le->next = l1; le = l1; l1 = l1->next; } break; } if(datcmp(l1, l2) < 0) { le->next = l1; le = l1; l1 = l1->next; } else { le->next = l2; le = l2; l2 = l2->next; } } le->next = 0; return l; }
void dodata(void) { int32 t, datsize; Section *sect, *noptr; Sym *s, *last, **l; if(debug['v']) Bprint(&bso, "%5.2f dodata\n", cputime()); Bflush(&bso); last = nil; datap = nil; for(s=allsym; s!=S; s=s->allsym) { if(!s->reachable || s->special) continue; if(STEXT < s->type && s->type < SXREF) { if(last == nil) datap = s; else last->next = s; s->next = nil; last = s; } } for(s = datap; s != nil; s = s->next) { if(s->np > s->size) diag("%s: initialize bounds (%lld < %d)", s->name, (vlong)s->size, s->np); } /* * now that we have the datap list, but before we start * to assign addresses, record all the necessary * dynamic relocations. these will grow the relocation * symbol, which is itself data. */ dynreloc(); /* some symbols may no longer belong in datap (Mach-O) */ for(l=&datap; (s=*l) != nil; ) { if(s->type <= STEXT || SXREF <= s->type) *l = s->next; else l = &s->next; } *l = nil; datap = datsort(datap); /* * allocate data sections. list is sorted by type, * so we can just walk it for each piece we want to emit. */ /* read-only data */ sect = addsection(&segtext, ".rodata", 04); sect->vaddr = 0; datsize = 0; s = datap; for(; s != nil && s->type < SSYMTAB; s = s->next) { if(s->align != 0) datsize = rnd(datsize, s->align); s->type = SRODATA; s->value = datsize; datsize += rnd(s->size, PtrSize); } sect->len = datsize - sect->vaddr; /* gosymtab */ sect = addsection(&segtext, ".gosymtab", 04); sect->vaddr = datsize; for(; s != nil && s->type < SPCLNTAB; s = s->next) { s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* gopclntab */ sect = addsection(&segtext, ".gopclntab", 04); sect->vaddr = datsize; for(; s != nil && s->type < SELFROSECT; s = s->next) { s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* read-only ELF sections */ for(; s != nil && s->type < SELFSECT; s = s->next) { sect = addsection(&segtext, s->name, 04); if(s->align != 0) datsize = rnd(datsize, s->align); sect->vaddr = datsize; s->type = SRODATA; s->value = datsize; datsize += rnd(s->size, PtrSize); sect->len = datsize - sect->vaddr; } /* writable ELF sections */ datsize = 0; for(; s != nil && s->type < SNOPTRDATA; s = s->next) { sect = addsection(&segdata, s->name, 06); if(s->align != 0) datsize = rnd(datsize, s->align); sect->vaddr = datsize; s->type = SDATA; s->value = datsize; datsize += rnd(s->size, PtrSize); sect->len = datsize - sect->vaddr; } /* pointer-free data, then data */ sect = addsection(&segdata, ".noptrdata", 06); sect->vaddr = datsize; noptr = sect; for(; ; s = s->next) { if((s == nil || s->type >= SDATA) && sect == noptr) { // finish noptrdata, start data datsize = rnd(datsize, 8); sect->len = datsize - sect->vaddr; sect = addsection(&segdata, ".data", 06); sect->vaddr = datsize; } if(s == nil || s->type >= SBSS) { // finish data sect->len = datsize - sect->vaddr; break; } s->type = SDATA; t = s->size; if(t >= PtrSize) t = rnd(t, PtrSize); else if(t > 2) t = rnd(t, 4); if(s->align != 0) datsize = rnd(datsize, s->align); else if(t & 1) { ; } else if(t & 2) datsize = rnd(datsize, 2); else if(t & 4) datsize = rnd(datsize, 4); else datsize = rnd(datsize, 8); s->value = datsize; datsize += t; } /* bss, then pointer-free bss */ noptr = nil; sect = addsection(&segdata, ".bss", 06); sect->vaddr = datsize; for(; ; s = s->next) { if((s == nil || s->type >= SNOPTRBSS) && noptr == nil) { // finish bss, start noptrbss datsize = rnd(datsize, 8); sect->len = datsize - sect->vaddr; sect = addsection(&segdata, ".noptrbss", 06); sect->vaddr = datsize; noptr = sect; } if(s == nil) { sect->len = datsize - sect->vaddr; break; } if(s->type > SNOPTRBSS) { cursym = s; diag("unexpected symbol type %d", s->type); } t = s->size; if(t >= PtrSize) t = rnd(t, PtrSize); else if(t > 2) t = rnd(t, 4); if(s->align != 0) datsize = rnd(datsize, s->align); else if(t & 1) { ; } else if(t & 2) datsize = rnd(datsize, 2); else if(t & 4) datsize = rnd(datsize, 4); else datsize = rnd(datsize, 8); s->value = datsize; datsize += t; } }
void dodata(void) { int32 t, datsize; Section *sect; Sym *s, *last, **l; Sym *gcdata1, *gcbss1; if(debug['v']) Bprint(&bso, "%5.2f dodata\n", cputime()); Bflush(&bso); // define garbage collection symbols gcdata1 = lookup("gcdata1", 0); gcdata1->type = SGCDATA; gcdata1->reachable = 1; gcbss1 = lookup("gcbss1", 0); gcbss1->type = SGCBSS; gcbss1->reachable = 1; // size of .data and .bss section. the zero value is later replaced by the actual size of the section. adduintxx(gcdata1, 0, PtrSize); adduintxx(gcbss1, 0, PtrSize); last = nil; datap = nil; for(s=allsym; s!=S; s=s->allsym) { if(!s->reachable || s->special) continue; if(STEXT < s->type && s->type < SXREF) { if(last == nil) datap = s; else last->next = s; s->next = nil; last = s; } } for(s = datap; s != nil; s = s->next) { if(s->np > s->size) diag("%s: initialize bounds (%lld < %d)", s->name, (vlong)s->size, s->np); } /* * now that we have the datap list, but before we start * to assign addresses, record all the necessary * dynamic relocations. these will grow the relocation * symbol, which is itself data. */ dynreloc(); /* some symbols may no longer belong in datap (Mach-O) */ for(l=&datap; (s=*l) != nil; ) { if(s->type <= STEXT || SXREF <= s->type) *l = s->next; else l = &s->next; } *l = nil; if(flag_shared) { for(s=datap; s != nil; s = s->next) { if(s->rel_ro) s->type = SDATARELRO; } } datap = datsort(datap); /* * allocate sections. list is sorted by type, * so we can just walk it for each piece we want to emit. * segdata is processed before segtext, because we need * to see all symbols in the .data and .bss sections in order * to generate garbage collection information. */ /* begin segdata */ /* skip symbols belonging to segtext */ s = datap; for(; s != nil && s->type < SELFSECT; s = s->next) ; /* writable ELF sections */ datsize = 0; for(; s != nil && s->type < SNOPTRDATA; s = s->next) { sect = addsection(&segdata, s->name, 06); if(s->align != 0) datsize = rnd(datsize, s->align); sect->vaddr = datsize; s->sect = sect; s->type = SDATA; s->value = datsize; datsize += rnd(s->size, PtrSize); sect->len = datsize - sect->vaddr; } /* pointer-free data */ sect = addsection(&segdata, ".noptrdata", 06); sect->vaddr = datsize; lookup("noptrdata", 0)->sect = sect; lookup("enoptrdata", 0)->sect = sect; for(; s != nil && s->type < SDATARELRO; s = s->next) { s->sect = sect; s->type = SDATA; t = alignsymsize(s->size); datsize = aligndatsize(datsize, s); s->value = datsize; datsize += t; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* dynamic relocated rodata */ if(flag_shared) { sect = addsection(&segdata, ".data.rel.ro", 06); sect->vaddr = datsize; lookup("datarelro", 0)->sect = sect; lookup("edatarelro", 0)->sect = sect; for(; s != nil && s->type == SDATARELRO; s = s->next) { if(s->align != 0) datsize = rnd(datsize, s->align); s->sect = sect; s->type = SDATA; s->value = datsize; datsize += rnd(s->size, PtrSize); } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); } /* data */ sect = addsection(&segdata, ".data", 06); sect->vaddr = datsize; lookup("data", 0)->sect = sect; lookup("edata", 0)->sect = sect; for(; s != nil && s->type < SBSS; s = s->next) { if(s->type == SDATARELRO) { cursym = s; diag("unexpected symbol type %d", s->type); } s->sect = sect; s->type = SDATA; t = alignsymsize(s->size); datsize = aligndatsize(datsize, s); s->value = datsize; gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc datsize += t; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); adduintxx(gcdata1, GC_END, PtrSize); setuintxx(gcdata1, 0, sect->len, PtrSize); /* bss */ sect = addsection(&segdata, ".bss", 06); sect->vaddr = datsize; lookup("bss", 0)->sect = sect; lookup("ebss", 0)->sect = sect; for(; s != nil && s->type < SNOPTRBSS; s = s->next) { s->sect = sect; t = alignsymsize(s->size); datsize = aligndatsize(datsize, s); s->value = datsize; gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc datsize += t; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); adduintxx(gcbss1, GC_END, PtrSize); setuintxx(gcbss1, 0, sect->len, PtrSize); /* pointer-free bss */ sect = addsection(&segdata, ".noptrbss", 06); sect->vaddr = datsize; lookup("noptrbss", 0)->sect = sect; lookup("enoptrbss", 0)->sect = sect; for(; s != nil; s = s->next) { if(s->type > SNOPTRBSS) { cursym = s; diag("unexpected symbol type %d", s->type); } s->sect = sect; t = alignsymsize(s->size); datsize = aligndatsize(datsize, s); s->value = datsize; datsize += t; } sect->len = datsize - sect->vaddr; lookup("end", 0)->sect = sect; /* we finished segdata, begin segtext */ /* read-only data */ sect = addsection(&segtext, ".rodata", 04); sect->vaddr = 0; lookup("rodata", 0)->sect = sect; lookup("erodata", 0)->sect = sect; lookup("reloffset", 0)->sect = sect; datsize = 0; s = datap; for(; s != nil && s->type < STYPELINK; s = s->next) { s->sect = sect; if(s->align != 0) datsize = rnd(datsize, s->align); s->type = SRODATA; s->value = datsize; datsize += rnd(s->size, PtrSize); } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* type */ sect = addsection(&segtext, ".typelink", 04); sect->vaddr = datsize; lookup("typelink", 0)->sect = sect; lookup("etypelink", 0)->sect = sect; for(; s != nil && s->type == STYPELINK; s = s->next) { s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* gcdata */ sect = addsection(&segtext, ".gcdata", 04); sect->vaddr = datsize; lookup("gcdata", 0)->sect = sect; lookup("egcdata", 0)->sect = sect; for(; s != nil && s->type == SGCDATA; s = s->next) { s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* gcbss */ sect = addsection(&segtext, ".gcbss", 04); sect->vaddr = datsize; lookup("gcbss", 0)->sect = sect; lookup("egcbss", 0)->sect = sect; for(; s != nil && s->type == SGCBSS; s = s->next) { s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* gosymtab */ sect = addsection(&segtext, ".gosymtab", 04); sect->vaddr = datsize; lookup("symtab", 0)->sect = sect; lookup("esymtab", 0)->sect = sect; for(; s != nil && s->type < SPCLNTAB; s = s->next) { s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* gopclntab */ sect = addsection(&segtext, ".gopclntab", 04); sect->vaddr = datsize; lookup("pclntab", 0)->sect = sect; lookup("epclntab", 0)->sect = sect; for(; s != nil && s->type < SELFROSECT; s = s->next) { s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; datsize = rnd(datsize, PtrSize); /* read-only ELF sections */ for(; s != nil && s->type < SELFSECT; s = s->next) { sect = addsection(&segtext, s->name, 04); if(s->align != 0) datsize = rnd(datsize, s->align); sect->vaddr = datsize; s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += rnd(s->size, PtrSize); sect->len = datsize - sect->vaddr; } }