jt_pqueue* jt_pqueue_new(void) { jt_pqueue* pq = jt_new(jt_pqueue); pq->item = jt_newarray(jt_pqueueitem*, 4); pq->length = 0; pq->size = 4; return pq; }
jt_pqueueitem* jt_pqueue_newitem(uint5 priority) { jt_pqueueitem* pqi = jt_new(jt_pqueueitem); pqi->priority = priority; pqi->data = 0; return pqi; }
/* add symbols in object file to local symbol map */ void readsymbols(section* symtab, section* strtab, jt_map** symbolmap) { int i; Elf32_Sym* thissym; for (i=1; i<symtab->content->length/sizeof(Elf32_Sym); i++) { mapentry* mentry = jt_new(mapentry); thissym = buffer_IDX(symtab->content, Elf32_Sym, i); mentry->name = symbolname(thissym, strtab); mentry->binding = ELF32_ST_BIND(thissym->st_info); mentry->symtabentry = i; mentry->backpatches = 0; #ifdef DEBUG /* fprintf(stderr, "Read symbol %s\n", mentry->name);*/ #endif jt_map_insert(symbolmap, mentry->name, mentry); } }
/* Must match write_elf in asm/elfutil.c */ image* loadimage(FILE* f, int inlibrary) { image* img = jt_new(image); uint5 total = 0; section* sections[SHN_COUNT]; const uint5 numsections = sizeof(sections)/sizeof(section*); uint5 i; /* yucky innit. */ sections[0] = &img->null; sections[1] = &img->shstrtab; sections[2] = &img->text; sections[3] = &img->data; sections[4] = &img->rodata; sections[5] = &img->bss; sections[6] = &img->symtab; sections[7] = &img->strtab; sections[8] = &img->reltext; sections[9] = &img->reldata; sections[10] = &img->relrodata; sections[11] = &img->relbss; img->symbolmap = 0; total += fread(&img->ehdr, sizeof(Elf32_Ehdr), 1, f) * sizeof(Elf32_Ehdr); if (img->ehdr.e_ident[EI_MAG0] != ELFMAG0 || img->ehdr.e_ident[EI_MAG1] != ELFMAG1 || img->ehdr.e_ident[EI_MAG2] != ELFMAG2 || img->ehdr.e_ident[EI_MAG3] != ELFMAG3) { fprintf(stderr, "Unrecognized file format\n"); exit(1); } // read section headers for (i=0; i<numsections; i++) { total += fread(§ions[i]->header, sizeof(Elf32_Shdr), 1, f) * sizeof(Elf32_Shdr); fixshdr(§ions[i]->header); } // read section data for (i=0; i<numsections; i++) { total += loadsection(sections[i], f); } #ifdef DEBUG fprintf(stderr, "Read %d bytes total\n", total); #endif /* fiddle symtab to make it host byte order */ fixsymtab(img->symtab.content->buffer, img->symtab.content->length / sizeof(Elf32_Sym)); img->used = IMAGE_UNUSED; img->library = inlibrary; return img; }
/* find global symbols defined in an object file, add to global symbol map. Overrides weak symbols with global symbols. */ void findglobals(image* in, jt_map** global) { uint5 i; for (i=1; i<in->symtab.content->length/sizeof(Elf32_Sym); i++) { Elf32_Sym* sym = buffer_IDX(in->symtab.content, Elf32_Sym, i); char* name = symbolname(sym, &in->strtab); mapentry* oldmsym = jt_map_find(*global, name); uint5 newbinding = ELF32_ST_BIND(sym->st_info); if ((newbinding!=STB_GLOBAL && newbinding!=STB_WEAK) || sym->st_shndx==SHN_UNDEF) continue; if (oldmsym) { if (!in->library) { /* We have a symbol with this name already */ switch (oldmsym->binding) { case STB_GLOBAL: if (newbinding==STB_GLOBAL) { fprintf(stderr, "Multiply-defined global symbol %s\n", name); exit(1); } /* Else new symbol is weak, we can ignore it */ break; case STB_WEAK: if (newbinding==STB_WEAK) { #ifdef DEBUG2 fprintf(stderr, "Warning: multiply-defined weak symbol %s\n", name); #endif } else { /* Override old weak symbol */ oldmsym->binding = STB_GLOBAL; oldmsym->symtabentry = i; oldmsym->in_image = in; } break; default: fprintf(stderr, "Non-global symbol in global symbol map? (%s)\n", name); exit(1); } } } else { /* Generate a new global map entry */ mapentry* msym = jt_new(mapentry); msym->name = name; msym->binding = newbinding; msym->symtabentry = i; msym->in_image = in; msym->index = -1u; msym->backpatches = 0; jt_map_insert(global, name, msym); } } }
void loadarchive(FILE* ar, program* prog, jt_clist* objects) { char armagic[SARMAG]; struct ar_hdr arheader; int entry = 0; int havesymtab = 0; fread(armagic, 1, SARMAG, ar); if (strncmp(armagic, ARMAG, SARMAG) != 0) { fprintf(stderr, "This does not look like an archive file\n"); exit(1); } #ifdef DEBUG fprintf(stderr, "Got archive file!\n"); #endif while (!feof(ar)) { long posn = ftell(ar); int size; if ((posn & 1) == 1) { /* odd byte boundary, we must read another character, a newline */ int c = fgetc(ar); if (c != '\n') { fprintf(stderr, "Was expecting newline padding for header\n"); exit(1); } } /* first thing we try to read from the file this iteration: if it * fails, we've hit the end of the file (feof() didn't seem to work) */ if (fread(&arheader, 1, sizeof(arheader), ar) != sizeof(arheader)) break; if (strncmp(arheader.ar_fmag, ARFMAG, sizeof(ARFMAG)-1) != 0) { fprintf(stderr, "Bad archive header\n"); exit(1); } sscanf(arheader.ar_size, "%d", &size); posn = ftell(ar); #ifdef DEBUG fprintf(stderr, "Good archive header, length=%d\n", size); #endif if (entry==0 && !havesymtab && arheader.ar_name[0] == '/' && arheader.ar_name[1] == ' ') { archive_symtab* symtab = jt_new(archive_symtab); /* unnamed first entry is probably a symtab */ if (readsymtab(ar, &arheader, symtab)) { fprintf(stderr, "Error reading symbol table\n"); exit(1); } havesymtab = 1; /* don't really want one of those, was just being polite */ free(symtab->loc); free(symtab->name); free(symtab->nameidx); free(symtab); } else if (arheader.ar_name[0] == '/' && arheader.ar_name[1] == '/') { int posn = ftell(ar), size; #ifdef DEBUG fprintf(stderr, "Detected long filename section\n"); #endif sscanf(arheader.ar_size, "%d", &size); fseek(ar, posn+size, SEEK_SET); #ifdef DEBUG fprintf(stderr, "Skipped %d bytes\n", size); #endif } else { jt_clist* newobj = jt_clist_append(objects); image* img; #ifdef DEBUG uint5 i; #endif /* read a file from the archive */ #ifdef DEBUG fprintf(stderr, "Original filename: "); if (arheader.ar_name[0]=='/') { fprintf(stderr, "(long)\n"); } else { for (i=0; i<16; i++) { if (arheader.ar_name[i]=='/') break; fputc(arheader.ar_name[i], stderr); } fputc('\n', stderr); } #endif newobj->data = img = loadimage(ar, 1); readsymbols(&img->symtab, &img->strtab, &img->symbolmap); findglobals(img, &prog->globalsymbolmap); } /* position over file */ fseek(ar, posn+size, SEEK_SET); entry++; } #ifdef DEBUG fprintf(stderr, "Read library, returning...\n"); #endif }