LIST *listsort(LIST * head, cmpfunc cmp) { LIST *high = NULL, *low = NULL, *item, *next; if (!head || !head->next) return head; for (item = head; item;) { next = item->next; if ((*cmp) (item, head) < 0) { item->next = low; low = item; } else { item->next = high; high = item; } item = next; } high = listsort(high, cmp); low = listsort(low, cmp); head = listjoin(high, low); return head; }
/*------------------------------------------------------------------*/ void s_string_list_sort_master_pin_list() { int i = 0; STRING_LIST *local_list, *p; /* Here's where we do the sort. The sort is done using a fcn found on the web. */ local_list = sheet_head->master_pin_list_head; for (p=local_list; p; p=p->next) p->pos = 0; local_list = listsort(local_list, 0, 1); /* Do this after sorting is done. This resets the order of the individual items * in the list. */ while (local_list != NULL) { /* make sure item is not null */ local_list->pos = i; if (local_list->next != NULL) { i++; local_list = local_list->next; } else { break; /* leave loop *before* iterating to NULL EOL marker */ } } /* Now go to first item in local list and reassign list head to new first element */ while (local_list->prev != NULL) { local_list = local_list->prev; } sheet_head->master_pin_list_head = local_list; return; }
int main(void) { #define n 13 element k[n], *head, *p; int order[][n] = { { 0,1,2,3,4,5,6,7,8,9,10,11,12 }, { 6,2,8,4,11,1,12,7,3,9,5,0,10 }, { 12,11,10,9,8,7,6,5,4,3,2,1,0 }, }; unsigned int i, j; for (j = 0; j < n; j++) k[j].i = j; listsort(NULL, cmp, 0, 0); for (i = 0; i < sizeof(order)/sizeof(*order); i++) { int *ord = order[i]; head = &k[ord[0]]; for (j = 0; j < n; j++) { if (j == n-1) k[ord[j]].next = NULL; else k[ord[j]].next = &k[ord[j+1]]; } printf("before:"); p = head; do { printf(" %d", p->i); p = p->next; } while (p != NULL); printf("\t"); head = listsort(head, cmp); printf(" after:"); p = head; do { printf(" %d", p->i); p = p->next; } while (p != NULL); printf("\n"); } printf("\n"); return 0; }
/** * Ordena uma lista * Depende da função bubble * Retorna o primeiro nó da lista * * Node* first : primeiro nó da lista */ Node* listsort(Node* first){ if(first == NULL) return NULL; else{ first->nextNode = listsort(first->nextNode); first = bubble(first); return first; } }
void rstats_print(bool unsure) { size_t robn = stats_head->robn; /* sort by ascending spamicity */ stats_head->list = (rstats_t *)listsort((element *)stats_head->list, (fcn_compare *)&compare_rstats_t); if (Rtable || verbose>=3) rstats_print_rtable(stats_head->list); else if (verbose==2 || (unsure && verbose)) rstats_print_histogram(robn, stats_head->list); }
static void complete_command(ostream &out, istream &in) { FrObject *prefixsym ; out << "Find all frames with prefix: " << flush ; in >> prefixsym ; if (!prefixsym || !prefixsym->symbolp()) { out << "You must enter a symbol for the prefix. To match with" << endl << "lowercase, use vertical bars like |this|." << endl ; return ; } const char *prefix = ((FrSymbol*)prefixsym)->symbolName() ; char longest_prefix[FrMAX_SYMBOLNAME_LEN] ; FrList *matches = collect_prefix_matching_frames(prefix,longest_prefix, sizeof(longest_prefix)) ; matches = listsort(matches,compare_symbol_names) ; out << "The matching frames are " << matches << endl ; out << "The longest common prefix is " << longest_prefix << endl ; free_object(matches) ; }
static void treeprint(struct tnode *p) { struct linkwords *temp1; struct linklist *temp2; int pos; if (p != NULL) { // Traverse left side of tree treeprint(p->left); // Sort the unstemmed words on the current node listsort(p->words, p->wordcount); // Print out the words for (temp1 = p->words; temp1 != NULL; temp1 = temp1->next) { printf("%s", temp1->word); if (temp1->next != NULL) printf(", "); } (void)putchar('\n'); // Print out the line numbers adjusting for rough right margin pos = printf("\t"); for (temp2 = p->lines; temp2 != NULL; temp2 = temp2->next) { pos += printf("%d", temp2->linenum); if (temp2->next != NULL) pos += printf(", "); if (pos > RIGHTMARGIN && temp2->next != NULL) { (void)putchar('\n'); pos = printf("\t"); } } (void)putchar('\n'); treeprint(p->right); } }
/*! \brief Sort the master component attribute list * * Take the master comp attrib list * sheet_head->master_comp_attrib_list_head * and sort it in this order: * <all refdeses in alphabetical order> * Right now it does nothing other than fill in the "position" * and "length" variables. */ void s_string_list_sort_master_comp_attrib_list() { int i = 0; STRING_LIST *local_list, *p; /* Here's where we do the sort */ local_list = sheet_head->master_comp_attrib_list_head; /* * Note that this sort is TBD -- it is more than just an alphabetic sort 'cause we want * certain attribs to go first. */ for (p=local_list; p; p=p->next) { int i; p->pos = DEFAULT_ATTRIB_POS; for (i=0; i<NUM_CERTAINS; i++) if (p->data != NULL) { if (strcmp (certain_attribs[i].attrib, p->data) == 0) { p->pos = certain_attribs[i].pos; break; } } } local_list = listsort(local_list, 0, 1); sheet_head->master_comp_attrib_list_head = local_list; /* Do this after sorting is done. This resets the order of the individual items * in the list. */ while (local_list != NULL) { local_list->pos = i; i++; local_list = local_list->next; } return; }
Sym* listsort(Sym *l, int (*cmp)(Sym*, Sym*), int off) { Sym *l1, *l2, *le; #define NEXT(l) (*(Sym**)((char*)(l)+off)) if(l == 0 || NEXT(l) == 0) return l; l1 = l; l2 = l; for(;;) { l2 = NEXT(l2); if(l2 == 0) break; l2 = NEXT(l2); if(l2 == 0) break; l1 = NEXT(l1); } l2 = NEXT(l1); NEXT(l1) = 0; l1 = listsort(l, cmp, off); l2 = listsort(l2, cmp, off); /* set up lead element */ if(cmp(l1, l2) < 0) { l = l1; l1 = NEXT(l1); } else { l = l2; l2 = NEXT(l2); } le = l; for(;;) { if(l1 == 0) { while(l2) { NEXT(le) = l2; le = l2; l2 = NEXT(l2); } NEXT(le) = 0; break; } if(l2 == 0) { while(l1) { NEXT(le) = l1; le = l1; l1 = NEXT(l1); } break; } if(cmp(l1, l2) < 0) { NEXT(le) = l1; le = l1; l1 = NEXT(l1); } else { NEXT(le) = l2; le = l2; l2 = NEXT(l2); } } NEXT(le) = 0; return l; #undef NEXT }
void dodata(void) { int32 n, 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("gcdata", 0); gcdata1->type = STYPE; gcdata1->reachable = 1; gcbss1 = lookup("gcbss", 0); gcbss1->type = STYPE; 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. * * on darwin, we need the symbol table numbers for dynreloc. */ if(HEADTYPE == Hdarwin) machosymorder(); 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 = listsort(datap, datcmp, offsetof(Sym, next)); /* * 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); sect->align = symalign(s); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; s->sect = sect; s->type = SDATA; s->value = datsize; datsize += s->size; sect->len = datsize - sect->vaddr; } /* pointer-free data */ sect = addsection(&segdata, ".noptrdata", 06); sect->align = maxalign(s, SDATARELRO-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; lookup("noptrdata", 0)->sect = sect; lookup("enoptrdata", 0)->sect = sect; for(; s != nil && s->type < SDATARELRO; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SDATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; /* dynamic relocated rodata */ if(flag_shared) { sect = addsection(&segdata, ".data.rel.ro", 06); sect->align = maxalign(s, SDATARELRO); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; lookup("datarelro", 0)->sect = sect; lookup("edatarelro", 0)->sect = sect; for(; s != nil && s->type == SDATARELRO; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SDATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; } /* data */ sect = addsection(&segdata, ".data", 06); sect->align = maxalign(s, SBSS-1); datsize = rnd(datsize, sect->align); 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; datsize = aligndatsize(datsize, s); s->value = datsize; gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc datsize += s->size; } sect->len = datsize - sect->vaddr; adduintxx(gcdata1, GC_END, PtrSize); setuintxx(gcdata1, 0, sect->len, PtrSize); /* bss */ sect = addsection(&segdata, ".bss", 06); sect->align = maxalign(s, SNOPTRBSS-1); datsize = rnd(datsize, sect->align); 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; datsize = aligndatsize(datsize, s); s->value = datsize; gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc datsize += s->size; } sect->len = datsize - sect->vaddr; adduintxx(gcbss1, GC_END, PtrSize); setuintxx(gcbss1, 0, sect->len, PtrSize); /* pointer-free bss */ sect = addsection(&segdata, ".noptrbss", 06); sect->align = maxalign(s, SNOPTRBSS); datsize = rnd(datsize, sect->align); 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); } datsize = aligndatsize(datsize, s); s->sect = sect; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; lookup("end", 0)->sect = sect; /* we finished segdata, begin segtext */ s = datap; datsize = 0; /* read-only data */ sect = addsection(&segtext, ".rodata", 04); sect->align = maxalign(s, STYPELINK-1); sect->vaddr = 0; lookup("rodata", 0)->sect = sect; lookup("erodata", 0)->sect = sect; datsize = 0; for(; s != nil && s->type < STYPELINK; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; /* typelink */ sect = addsection(&segtext, ".typelink", 04); sect->align = maxalign(s, STYPELINK); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; lookup("typelink", 0)->sect = sect; lookup("etypelink", 0)->sect = sect; for(; s != nil && s->type == STYPELINK; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; /* gosymtab */ sect = addsection(&segtext, ".gosymtab", 04); sect->align = maxalign(s, SPCLNTAB-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; lookup("symtab", 0)->sect = sect; lookup("esymtab", 0)->sect = sect; for(; s != nil && s->type < SPCLNTAB; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; /* gopclntab */ sect = addsection(&segtext, ".gopclntab", 04); sect->align = maxalign(s, SELFROSECT-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; lookup("pclntab", 0)->sect = sect; lookup("epclntab", 0)->sect = sect; for(; s != nil && s->type < SELFROSECT; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; } sect->len = datsize - sect->vaddr; /* read-only ELF, Mach-O sections */ for(; s != nil && s->type < SELFSECT; s = s->next) { sect = addsection(&segtext, s->name, 04); sect->align = symalign(s); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; s->sect = sect; s->type = SRODATA; s->value = datsize; datsize += s->size; sect->len = datsize - sect->vaddr; } /* number the sections */ n = 1; for(sect = segtext.sect; sect != nil; sect = sect->next) sect->extnum = n++; for(sect = segdata.sect; sect != nil; sect = sect->next) sect->extnum = n++; }
void ldelf(Biobuf *f, char *pkg, int64 len, char *pn) { int32 base; uint64 add, info; char *name; int i, j, rela, is64, n; uchar hdrbuf[64]; uchar *p; ElfHdrBytes *hdr; ElfObj *obj; ElfSect *sect, *rsect; ElfSym sym; Endian *e; Reloc *r, *rp; LSym *s; LSym **symbols; symbols = nil; if(debug['v']) Bprint(&bso, "%5.2f ldelf %s\n", cputime(), pn); ctxt->version++; base = Boffset(f); if(Bread(f, hdrbuf, sizeof hdrbuf) != sizeof hdrbuf) goto bad; hdr = (ElfHdrBytes*)hdrbuf; if(memcmp(hdr->ident, ElfMagic, 4) != 0) goto bad; switch(hdr->ident[5]) { case ElfDataLsb: e = ≤ break; case ElfDataMsb: e = &be; break; default: goto bad; } // read header obj = mal(sizeof *obj); obj->e = e; obj->f = f; obj->base = base; obj->len = len; obj->name = pn; is64 = 0; if(hdr->ident[4] == ElfClass64) { ElfHdrBytes64* hdr; is64 = 1; hdr = (ElfHdrBytes64*)hdrbuf; obj->type = e->e16(hdr->type); obj->machine = e->e16(hdr->machine); obj->version = e->e32(hdr->version); obj->phoff = e->e64(hdr->phoff); obj->shoff = e->e64(hdr->shoff); obj->flags = e->e32(hdr->flags); obj->ehsize = e->e16(hdr->ehsize); obj->phentsize = e->e16(hdr->phentsize); obj->phnum = e->e16(hdr->phnum); obj->shentsize = e->e16(hdr->shentsize); obj->shnum = e->e16(hdr->shnum); obj->shstrndx = e->e16(hdr->shstrndx); } else { obj->type = e->e16(hdr->type); obj->machine = e->e16(hdr->machine); obj->version = e->e32(hdr->version); obj->entry = e->e32(hdr->entry); obj->phoff = e->e32(hdr->phoff); obj->shoff = e->e32(hdr->shoff); obj->flags = e->e32(hdr->flags); obj->ehsize = e->e16(hdr->ehsize); obj->phentsize = e->e16(hdr->phentsize); obj->phnum = e->e16(hdr->phnum); obj->shentsize = e->e16(hdr->shentsize); obj->shnum = e->e16(hdr->shnum); obj->shstrndx = e->e16(hdr->shstrndx); } obj->is64 = is64; if(hdr->ident[6] != obj->version) goto bad; if(e->e16(hdr->type) != ElfTypeRelocatable) { diag("%s: elf but not elf relocatable object", pn); return; } switch(thechar) { default: diag("%s: elf %s unimplemented", pn, thestring); return; case '5': if(e != &le || obj->machine != ElfMachArm || hdr->ident[4] != ElfClass32) { diag("%s: elf object but not arm", pn); return; } break; case '6': if(e != &le || obj->machine != ElfMachAmd64 || hdr->ident[4] != ElfClass64) { diag("%s: elf object but not amd64", pn); return; } break; case '8': if(e != &le || obj->machine != ElfMach386 || hdr->ident[4] != ElfClass32) { diag("%s: elf object but not 386", pn); return; } break; } // load section list into memory. obj->sect = mal(obj->shnum*sizeof obj->sect[0]); obj->nsect = obj->shnum; for(i=0; i<obj->nsect; i++) { if(Bseek(f, base+obj->shoff+i*obj->shentsize, 0) < 0) goto bad; sect = &obj->sect[i]; if(is64) { ElfSectBytes64 b; werrstr("short read"); if(Bread(f, &b, sizeof b) != sizeof b) goto bad; sect->name = (char*)(uintptr)e->e32(b.name); sect->type = e->e32(b.type); sect->flags = e->e64(b.flags); sect->addr = e->e64(b.addr); sect->off = e->e64(b.off); sect->size = e->e64(b.size); sect->link = e->e32(b.link); sect->info = e->e32(b.info); sect->align = e->e64(b.align); sect->entsize = e->e64(b.entsize); } else { ElfSectBytes b; werrstr("short read"); if(Bread(f, &b, sizeof b) != sizeof b) goto bad; sect->name = (char*)(uintptr)e->e32(b.name); sect->type = e->e32(b.type); sect->flags = e->e32(b.flags); sect->addr = e->e32(b.addr); sect->off = e->e32(b.off); sect->size = e->e32(b.size); sect->link = e->e32(b.link); sect->info = e->e32(b.info); sect->align = e->e32(b.align); sect->entsize = e->e32(b.entsize); } } // read section string table and translate names if(obj->shstrndx >= obj->nsect) { werrstr("shstrndx out of range %d >= %d", obj->shstrndx, obj->nsect); goto bad; } sect = &obj->sect[obj->shstrndx]; if(map(obj, sect) < 0) goto bad; for(i=0; i<obj->nsect; i++) if(obj->sect[i].name != nil) obj->sect[i].name = (char*)sect->base + (uintptr)obj->sect[i].name; // load string table for symbols into memory. obj->symtab = section(obj, ".symtab"); if(obj->symtab == nil) { // our work is done here - no symbols means nothing can refer to this file return; } if(obj->symtab->link <= 0 || obj->symtab->link >= obj->nsect) { diag("%s: elf object has symbol table with invalid string table link", pn); return; } obj->symstr = &obj->sect[obj->symtab->link]; if(is64) obj->nsymtab = obj->symtab->size / sizeof(ElfSymBytes64); else obj->nsymtab = obj->symtab->size / sizeof(ElfSymBytes); if(map(obj, obj->symtab) < 0) goto bad; if(map(obj, obj->symstr) < 0) goto bad; // load text and data segments into memory. // they are not as small as the section lists, but we'll need // the memory anyway for the symbol images, so we might // as well use one large chunk. // create symbols for mapped sections for(i=0; i<obj->nsect; i++) { sect = &obj->sect[i]; if((sect->type != ElfSectProgbits && sect->type != ElfSectNobits) || !(sect->flags&ElfSectFlagAlloc)) continue; if(sect->type != ElfSectNobits && map(obj, sect) < 0) goto bad; name = smprint("%s(%s)", pkg, sect->name); s = linklookup(ctxt, name, ctxt->version); free(name); switch((int)sect->flags&(ElfSectFlagAlloc|ElfSectFlagWrite|ElfSectFlagExec)) { default: werrstr("unexpected flags for ELF section %s", sect->name); goto bad; case ElfSectFlagAlloc: s->type = SRODATA; break; case ElfSectFlagAlloc + ElfSectFlagWrite: s->type = SNOPTRDATA; break; case ElfSectFlagAlloc + ElfSectFlagExec: s->type = STEXT; break; } if(sect->type == ElfSectProgbits) { s->p = sect->base; s->np = sect->size; } s->size = sect->size; s->align = sect->align; sect->sym = s; } // enter sub-symbols into symbol table. // symbol 0 is the null symbol. symbols = malloc(obj->nsymtab * sizeof(symbols[0])); if(symbols == nil) { diag("out of memory"); errorexit(); } for(i=1; i<obj->nsymtab; i++) { if(readsym(obj, i, &sym, 1) < 0) goto bad; symbols[i] = sym.sym; if(sym.type != ElfSymTypeFunc && sym.type != ElfSymTypeObject && sym.type != ElfSymTypeNone) continue; if(sym.shndx == ElfSymShnCommon) { s = sym.sym; if(s->size < sym.size) s->size = sym.size; if(s->type == 0 || s->type == SXREF) s->type = SNOPTRBSS; continue; } if(sym.shndx >= obj->nsect || sym.shndx == 0) continue; // even when we pass needSym == 1 to readsym, it might still return nil to skip some unwanted symbols if(sym.sym == S) continue; sect = obj->sect+sym.shndx; if(sect->sym == nil) { if(strncmp(sym.name, ".Linfo_string", 13) == 0) // clang does this continue; diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type); continue; } s = sym.sym; if(s->outer != S) { if(s->dupok) continue; diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name); errorexit(); } s->sub = sect->sym->sub; sect->sym->sub = s; s->type = sect->sym->type | (s->type&~SMASK) | SSUB; if(!(s->cgoexport & CgoExportDynamic)) s->dynimplib = nil; // satisfy dynimport s->value = sym.value; s->size = sym.size; s->outer = sect->sym; if(sect->sym->type == STEXT) { if(s->external && !s->dupok) diag("%s: duplicate definition of %s", pn, s->name); s->external = 1; } } // Sort outer lists by address, adding to textp. // This keeps textp in increasing address order. for(i=0; i<obj->nsect; i++) { s = obj->sect[i].sym; if(s == S) continue; if(s->sub) s->sub = listsort(s->sub, valuecmp, offsetof(LSym, sub)); if(s->type == STEXT) { if(s->onlist) sysfatal("symbol %s listed multiple times", s->name); s->onlist = 1; if(ctxt->etextp) ctxt->etextp->next = s; else ctxt->textp = s; ctxt->etextp = s; for(s = s->sub; s != S; s = s->sub) { if(s->onlist) sysfatal("symbol %s listed multiple times", s->name); s->onlist = 1; ctxt->etextp->next = s; ctxt->etextp = s; } } } // load relocations for(i=0; i<obj->nsect; i++) { rsect = &obj->sect[i]; if(rsect->type != ElfSectRela && rsect->type != ElfSectRel) continue; if(rsect->info >= obj->nsect || obj->sect[rsect->info].base == nil) continue; sect = &obj->sect[rsect->info]; if(map(obj, rsect) < 0) goto bad; rela = rsect->type == ElfSectRela; n = rsect->size/(4+4*is64)/(2+rela); r = mal(n*sizeof r[0]); p = rsect->base; for(j=0; j<n; j++) { add = 0; rp = &r[j]; if(is64) { // 64-bit rel/rela rp->off = e->e64(p); p += 8; info = e->e64(p); p += 8; if(rela) { add = e->e64(p); p += 8; } } else { // 32-bit rel/rela rp->off = e->e32(p); p += 4; info = e->e32(p); info = info>>8<<32 | (info&0xff); // convert to 64-bit info p += 4; if(rela) { add = e->e32(p); p += 4; } } if((info & 0xffffffff) == 0) { // skip R_*_NONE relocation j--; n--; continue; } if((info >> 32) == 0) { // absolute relocation, don't bother reading the null symbol rp->sym = S; } else { if(readsym(obj, info>>32, &sym, 0) < 0) goto bad; sym.sym = symbols[info>>32]; if(sym.sym == nil) { werrstr("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect->sym->name, j, (int)(info>>32), sym.name, sym.shndx, sym.type); goto bad; } rp->sym = sym.sym; } rp->type = reltype(pn, (uint32)info, &rp->siz); if(rela) rp->add = add; else { // load addend from image if(rp->siz == 4) rp->add = e->e32(sect->base+rp->off); else if(rp->siz == 8) rp->add = e->e64(sect->base+rp->off); else diag("invalid rela size %d", rp->siz); } if(rp->siz == 4) rp->add = (int32)rp->add; //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); }
void ldpe(Biobuf *f, char *pkg, int64 len, char *pn) { char *name; int32 base; uint32 l; int i, j, numaux; PeObj *obj; PeSect *sect, *rsect; IMAGE_SECTION_HEADER sh; uchar symbuf[18]; Sym *s; Reloc *r, *rp; PeSym *sym; USED(len); if(debug['v']) Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn); sect = nil; version++; base = Boffset(f); obj = mal(sizeof *obj); obj->f = f; obj->base = base; obj->name = pn; // read header if(Bread(f, &obj->fh, sizeof obj->fh) != sizeof obj->fh) goto bad; // load section list obj->sect = mal(obj->fh.NumberOfSections*sizeof obj->sect[0]); obj->nsect = obj->fh.NumberOfSections; for(i=0; i < obj->fh.NumberOfSections; i++) { if(Bread(f, &obj->sect[i].sh, sizeof sh) != sizeof sh) goto bad; obj->sect[i].size = obj->sect[i].sh.SizeOfRawData; obj->sect[i].name = (char*)obj->sect[i].sh.Name; // TODO return error if found .cormeta } // load string table Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0); if(Bread(f, symbuf, 4) != 4) goto bad; l = le32(symbuf); obj->snames = mal(l); Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0); if(Bread(f, obj->snames, l) != l) goto bad; // read symbols obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]); obj->npesym = obj->fh.NumberOfSymbols; Bseek(f, base+obj->fh.PointerToSymbolTable, 0); for(i=0; i<obj->fh.NumberOfSymbols; i+=numaux+1) { Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*i, 0); if(Bread(f, symbuf, sizeof symbuf) != sizeof symbuf) goto bad; if((symbuf[0] == 0) && (symbuf[1] == 0) && (symbuf[2] == 0) && (symbuf[3] == 0)) { l = le32(&symbuf[4]); obj->pesym[i].name = (char*)&obj->snames[l]; } else { // sym name length <= 8 obj->pesym[i].name = mal(9); strncpy(obj->pesym[i].name, (char*)symbuf, 8); obj->pesym[i].name[8] = 0; } obj->pesym[i].value = le32(&symbuf[8]); obj->pesym[i].sectnum = le16(&symbuf[12]); obj->pesym[i].sclass = symbuf[16]; obj->pesym[i].aux = symbuf[17]; obj->pesym[i].type = le16(&symbuf[14]); numaux = obj->pesym[i].aux; if (numaux < 0) numaux = 0; } // create symbols for mapped sections for(i=0; i<obj->nsect; i++) { sect = &obj->sect[i]; if(sect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE) continue; if(map(obj, sect) < 0) goto bad; name = smprint("%s(%s)", pkg, sect->name); s = lookup(name, version); free(name); switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE)) { case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ: //.rdata s->type = SRODATA; break; case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss s->type = SBSS; break; case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data s->type = SDATA; break; case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text s->type = STEXT; break; default: werrstr("unexpected flags for PE section %s", sect->name); goto bad; } s->p = sect->base; s->np = sect->size; s->size = sect->size; sect->sym = s; if(strcmp(sect->name, ".rsrc") == 0) setpersrc(sect->sym); } // load relocations for(i=0; i<obj->nsect; i++) { rsect = &obj->sect[i]; if(rsect->sym == 0 || rsect->sh.NumberOfRelocations == 0) continue; if(rsect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE) continue; r = mal(rsect->sh.NumberOfRelocations*sizeof r[0]); Bseek(f, obj->base+rsect->sh.PointerToRelocations, 0); for(j=0; j<rsect->sh.NumberOfRelocations; j++) { rp = &r[j]; if(Bread(f, symbuf, 10) != 10) goto bad; uint32 rva, symindex; uint16 type; rva = le32(&symbuf[0]); symindex = le32(&symbuf[4]); type = le16(&symbuf[8]); if(readsym(obj, symindex, &sym) < 0) goto bad; if(sym->sym == nil) { werrstr("reloc of invalid sym %s idx=%d type=%d", sym->name, symindex, sym->type); goto bad; } rp->sym = sym->sym; rp->siz = 4; rp->off = rva; switch(type) { default: diag("%s: unknown relocation type %d;", pn, type); case IMAGE_REL_I386_REL32: case IMAGE_REL_AMD64_REL32: case IMAGE_REL_AMD64_ADDR32: // R_X86_64_PC32 case IMAGE_REL_AMD64_ADDR32NB: rp->type = D_PCREL; rp->add = le32(rsect->base+rp->off); break; case IMAGE_REL_I386_DIR32NB: case IMAGE_REL_I386_DIR32: rp->type = D_ADDR; // load addend from image rp->add = le32(rsect->base+rp->off); break; case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64 rp->siz = 8; rp->type = D_ADDR; // load addend from image rp->add = le64(rsect->base+rp->off); break; } // ld -r could generate multiple section symbols for the // same section but with different values, we have to take // that into account if (obj->pesym[symindex].name[0] == '.') rp->add += obj->pesym[symindex].value; } qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff); s = rsect->sym; s->r = r; s->nr = rsect->sh.NumberOfRelocations; } // enter sub-symbols into symbol table. for(i=0; i<obj->npesym; i++) { if(obj->pesym[i].name == 0) continue; if(obj->pesym[i].name[0] == '.') //skip section continue; if(obj->pesym[i].sectnum > 0) { sect = &obj->sect[obj->pesym[i].sectnum-1]; if(sect->sym == 0) continue; } if(readsym(obj, i, &sym) < 0) goto bad; s = sym->sym; if(sym->sectnum == 0) {// extern if(s->type == SDYNIMPORT) s->plt = -2; // flag for dynimport in PE object files. if (s->type == SXREF && sym->value > 0) {// global data s->type = SDATA; s->size = sym->value; } continue; } else if (sym->sectnum > 0) { sect = &obj->sect[sym->sectnum-1]; if(sect->sym == 0) diag("%s: %s sym == 0!", pn, s->name); } else { diag("%s: %s sectnum < 0!", pn, s->name); } if(sect == nil) return; if(s->outer != S) { if(s->dupok) continue; diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name); errorexit(); } s->sub = sect->sym->sub; sect->sym->sub = s; s->type = sect->sym->type | SSUB; s->value = sym->value; s->size = 4; s->outer = sect->sym; if(sect->sym->type == STEXT) { Prog *p; if(s->text != P) diag("%s: duplicate definition of %s", pn, s->name); // build a TEXT instruction with a unique pc // just to make the rest of the linker happy. p = prg(); p->as = ATEXT; p->from.type = D_EXTERN; p->from.sym = s; p->textflag = 7; p->to.type = D_CONST; p->link = nil; p->pc = pc++; s->text = p; } } // Sort outer lists by address, adding to textp. // This keeps textp in increasing address order. for(i=0; i<obj->nsect; i++) { s = obj->sect[i].sym; if(s == S) continue; if(s->sub) s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub)); if(s->type == STEXT) { if(etextp) etextp->next = s; else textp = s; etextp = s; for(s = s->sub; s != S; s = s->sub) { etextp->next = s; etextp = s; } } } return; bad: diag("%s: malformed pe file: %r", pn); }
void dodata(void) { int32 n; vlong datsize; Section *sect; Segment *segro; LSym *s, *last, **l; LSym *gcdata, *gcbss; ProgGen gen; if(debug['v']) Bprint(&bso, "%5.2f dodata\n", cputime()); Bflush(&bso); last = nil; datap = nil; for(s=ctxt->allsym; s!=S; s=s->allsym) { if(!s->reachable || s->special) continue; if(STEXT < s->type && s->type < SXREF) { if(s->onlist) sysfatal("symbol %s listed multiple times", s->name); s->onlist = 1; 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. * * on darwin, we need the symbol table numbers for dynreloc. */ if(HEADTYPE == Hdarwin) machosymorder(); 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 = listsort(datap, datcmp, offsetof(LSym, next)); /* * 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); sect->align = symalign(s); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; s->sect = sect; s->type = SDATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); sect->len = datsize - sect->vaddr; } /* pointer-free data */ sect = addsection(&segdata, ".noptrdata", 06); sect->align = maxalign(s, SINITARR-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.noptrdata", 0)->sect = sect; linklookup(ctxt, "runtime.enoptrdata", 0)->sect = sect; for(; s != nil && s->type < SINITARR; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SDATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; /* shared library initializer */ if(flag_shared) { sect = addsection(&segdata, ".init_array", 06); sect->align = maxalign(s, SINITARR); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; for(; s != nil && s->type == SINITARR; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; } /* data */ sect = addsection(&segdata, ".data", 06); sect->align = maxalign(s, SBSS-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.data", 0)->sect = sect; linklookup(ctxt, "runtime.edata", 0)->sect = sect; gcdata = linklookup(ctxt, "runtime.gcdata", 0); proggeninit(&gen, gcdata); for(; s != nil && s->type < SBSS; s = s->next) { if(s->type == SINITARR) { ctxt->cursym = s; diag("unexpected symbol type %d", s->type); } s->sect = sect; s->type = SDATA; datsize = aligndatsize(datsize, s); s->value = datsize - sect->vaddr; proggenaddsym(&gen, s); // gc growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; proggenfini(&gen, sect->len); // gc /* bss */ sect = addsection(&segdata, ".bss", 06); sect->align = maxalign(s, SNOPTRBSS-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.bss", 0)->sect = sect; linklookup(ctxt, "runtime.ebss", 0)->sect = sect; gcbss = linklookup(ctxt, "runtime.gcbss", 0); proggeninit(&gen, gcbss); for(; s != nil && s->type < SNOPTRBSS; s = s->next) { s->sect = sect; datsize = aligndatsize(datsize, s); s->value = datsize - sect->vaddr; proggenaddsym(&gen, s); // gc growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; proggenfini(&gen, sect->len); // gc /* pointer-free bss */ sect = addsection(&segdata, ".noptrbss", 06); sect->align = maxalign(s, SNOPTRBSS); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.noptrbss", 0)->sect = sect; linklookup(ctxt, "runtime.enoptrbss", 0)->sect = sect; for(; s != nil && s->type == SNOPTRBSS; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; linklookup(ctxt, "runtime.end", 0)->sect = sect; // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. if(datsize != (uint32)datsize) { diag("data or bss segment too large"); } if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) { sect = addsection(&segdata, ".tbss", 06); sect->align = PtrSize; sect->vaddr = 0; datsize = 0; for(; s != nil && s->type == STLSBSS; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize; } else { // Might be internal linking but still using cgo. // In that case, the only possible STLSBSS symbol is runtime.tlsg. // Give it offset 0, because it's the only thing here. if(s != nil && s->type == STLSBSS && strcmp(s->name, "runtime.tlsg") == 0) { s->value = 0; s = s->next; } } if(s != nil) { ctxt->cursym = nil; diag("unexpected symbol type %d for %s", s->type, s->name); } /* * We finished data, begin read-only data. * Not all systems support a separate read-only non-executable data section. * ELF systems do. * OS X and Plan 9 do not. * Windows PE may, but if so we have not implemented it. * And if we're using external linking mode, the point is moot, * since it's not our decision; that code expects the sections in * segtext. */ if(iself && linkmode == LinkInternal) segro = &segrodata; else segro = &segtext; s = datap; datsize = 0; /* read-only executable ELF, Mach-O sections */ for(; s != nil && s->type < STYPE; s = s->next) { sect = addsection(&segtext, s->name, 04); sect->align = symalign(s); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; s->sect = sect; s->type = SRODATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); sect->len = datsize - sect->vaddr; } /* read-only data */ sect = addsection(segro, ".rodata", 04); sect->align = maxalign(s, STYPELINK-1); datsize = rnd(datsize, sect->align); sect->vaddr = 0; linklookup(ctxt, "runtime.rodata", 0)->sect = sect; linklookup(ctxt, "runtime.erodata", 0)->sect = sect; for(; s != nil && s->type < STYPELINK; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; /* typelink */ sect = addsection(segro, ".typelink", 04); sect->align = maxalign(s, STYPELINK); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.typelink", 0)->sect = sect; linklookup(ctxt, "runtime.etypelink", 0)->sect = sect; for(; s != nil && s->type == STYPELINK; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; /* gosymtab */ sect = addsection(segro, ".gosymtab", 04); sect->align = maxalign(s, SPCLNTAB-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.symtab", 0)->sect = sect; linklookup(ctxt, "runtime.esymtab", 0)->sect = sect; for(; s != nil && s->type < SPCLNTAB; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; /* gopclntab */ sect = addsection(segro, ".gopclntab", 04); sect->align = maxalign(s, SELFROSECT-1); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; linklookup(ctxt, "runtime.pclntab", 0)->sect = sect; linklookup(ctxt, "runtime.epclntab", 0)->sect = sect; for(; s != nil && s->type < SELFROSECT; s = s->next) { datsize = aligndatsize(datsize, s); s->sect = sect; s->type = SRODATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); } sect->len = datsize - sect->vaddr; /* read-only ELF, Mach-O sections */ for(; s != nil && s->type < SELFSECT; s = s->next) { sect = addsection(segro, s->name, 04); sect->align = symalign(s); datsize = rnd(datsize, sect->align); sect->vaddr = datsize; s->sect = sect; s->type = SRODATA; s->value = datsize - sect->vaddr; growdatsize(&datsize, s); sect->len = datsize - sect->vaddr; } // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits. if(datsize != (uint32)datsize) { diag("read-only data segment too large"); } /* number the sections */ n = 1; for(sect = segtext.sect; sect != nil; sect = sect->next) sect->extnum = n++; for(sect = segrodata.sect; sect != nil; sect = sect->next) sect->extnum = n++; for(sect = segdata.sect; sect != nil; sect = sect->next) sect->extnum = n++; }