ElfShdr * elfwritenotehdr(char *str, uint32 namesz, uint32 descsz, uint32 tag) { ElfShdr *sh; sh = elfshname(str); // Write Elf_Note header. cseek(sh->off); LPUT(namesz); LPUT(descsz); LPUT(tag); return sh; }
int elfwriteinterp(vlong stridx) { ElfShdr *sh = nil; int i; for(i = 0; i < hdr.shnum; i++) if(shdr[i]->name == stridx) sh = shdr[i]; if(sh == nil || interp == nil) return 0; cseek(sh->off); cwrite(interp, sh->size); return sh->size; }
static void pewrite(void) { cseek(0); cwrite(dosstub, sizeof dosstub); strnput("PE", 4); // TODO: This code should not assume that the // memory representation is little-endian or // that the structs are packed identically to // their file representation. cwrite(&fh, sizeof fh); if(pe64) cwrite(&oh64, sizeof oh64); else cwrite(&oh, sizeof oh); cwrite(sh, nsect * sizeof sh[0]); }
int elfwritenetbsdsig(vlong stridx) { ElfShdr *sh = nil; int i; for(i = 0; i < hdr.shnum; i++) if(shdr[i]->name == stridx) sh = shdr[i]; if(sh == nil) return 0; // Write Elf_Note header followed by NetBSD string. cseek(sh->off); LPUT(ELF_NOTE_NETBSD_NAMESZ); LPUT(ELF_NOTE_NETBSD_DESCSZ); LPUT(ELF_NOTE_TYPE_NETBSD_TAG); cwrite(ELF_NOTE_NETBSD_NAME, 8); LPUT(ELF_NOTE_NETBSD_VERSION); return sh->size; }
unsigned int check_xdelta1_magic(cfile *patchf) { unsigned char buff[XDELTA_MAGIC_LEN]; cseek(patchf, 0, CSEEK_FSTART); if(XDELTA_MAGIC_LEN != cread(patchf, buff, XDELTA_MAGIC_LEN)) { return 0; } if(memcmp(buff, XDELTA_110_MAGIC, XDELTA_MAGIC_LEN)==0) { return 2; } else if (memcmp(buff, XDELTA_104_MAGIC, XDELTA_MAGIC_LEN)==0) { return 1; } else if (memcmp(buff, XDELTA_100_MAGIC, XDELTA_MAGIC_LEN)==0) { return 1; } else if (memcmp(buff, XDELTA_020_MAGIC, XDELTA_MAGIC_LEN)==0) { return 1; } else if (memcmp(buff, XDELTA_018_MAGIC, XDELTA_MAGIC_LEN)==0) { return 1; } else if (memcmp(buff, XDELTA_014_MAGIC, XDELTA_MAGIC_LEN)==0) { return 1; } return 0; }
// load into memory and return a pointer to the section of type 'type', // or NULL if the file doesn't have a section of that type. uint8_t *SIFLoader::FindSection(int type, int *length_out) { // try and find the section in the index for(int i=0;;i++) { SIFIndexEntry *entry = (SIFIndexEntry *)fIndex.ItemAt(i); if (!entry) break; if (entry->type == type) { // got it! // haven't loaded it yet? need to fetch it from file? if (!entry->data) { if (!fFP) { NX_ERR("SIFLoader::FindSection: entry found and need to load it, but file handle closed\n"); if (length_out) *length_out = 0; return NULL; } NX_LOG("Loading SIF section %d from address %04x\n", type, entry->foffset); entry->data = (uint8_t *)malloc(entry->length); cseek(fFP, entry->foffset, SEEK_SET); cread(entry->data, entry->length, 1, fFP); } if (length_out) *length_out = entry->length; return entry->data; } } if (length_out) *length_out = 0; return NULL; }
void asmbelf(vlong symo) { int a, o; vlong startva, resoff; ElfEhdr *eh; ElfPhdr *ph, *pph, *pnote; ElfShdr *sh; Section *sect; eh = getElfEhdr(); switch(thechar) { default: diag("unknown architecture in asmbelf"); errorexit(); case '5': eh->machine = EM_ARM; break; case '6': eh->machine = EM_X86_64; break; case '8': eh->machine = EM_386; break; } startva = INITTEXT - HEADR; resoff = ELFRESERVE; pph = nil; if(isobj) { /* skip program headers */ eh->phoff = 0; eh->phentsize = 0; goto elfobj; } /* program header info */ pph = newElfPhdr(); pph->type = PT_PHDR; pph->flags = PF_R + PF_X; pph->off = eh->ehsize; pph->vaddr = INITTEXT - HEADR + pph->off; pph->paddr = INITTEXT - HEADR + pph->off; pph->align = INITRND; /* * PHDR must be in a loaded segment. Adjust the text * segment boundaries downwards to include it. */ o = segtext.vaddr - pph->vaddr; segtext.vaddr -= o; segtext.len += o; o = segtext.fileoff - pph->off; segtext.fileoff -= o; segtext.filelen += o; if(!debug['d']) { /* interpreter */ sh = elfshname(".interp"); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC; sh->addralign = 1; if(interpreter == nil) { switch(HEADTYPE) { case Hlinux: interpreter = linuxdynld; break; case Hfreebsd: interpreter = freebsddynld; break; case Hnetbsd: interpreter = netbsddynld; break; case Hopenbsd: interpreter = openbsddynld; break; } } resoff -= elfinterp(sh, startva, resoff, interpreter); ph = newElfPhdr(); ph->type = PT_INTERP; ph->flags = PF_R; phsh(ph, sh); } pnote = nil; if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) { sh = nil; switch(HEADTYPE) { case Hnetbsd: sh = elfshname(".note.netbsd.ident"); resoff -= elfnetbsdsig(sh, startva, resoff); break; case Hopenbsd: sh = elfshname(".note.openbsd.ident"); resoff -= elfopenbsdsig(sh, startva, resoff); break; } pnote = newElfPhdr(); pnote->type = PT_NOTE; pnote->flags = PF_R; phsh(pnote, sh); } if(buildinfolen > 0) { sh = elfshname(".note.gnu.build-id"); resoff -= elfbuildinfo(sh, startva, resoff); if(pnote == nil) { pnote = newElfPhdr(); pnote->type = PT_NOTE; pnote->flags = PF_R; } phsh(pnote, sh); } // Additions to the reserved area must be above this line. USED(resoff); elfphload(&segtext); elfphload(&segdata); /* Dynamic linking sections */ if(!debug['d']) { /* -d suppresses dynamic loader format */ sh = elfshname(".dynsym"); sh->type = SHT_DYNSYM; sh->flags = SHF_ALLOC; if(PtrSize == 8) sh->entsize = ELF64SYMSIZE; else sh->entsize = ELF32SYMSIZE; sh->addralign = PtrSize; sh->link = elfshname(".dynstr")->shnum; // sh->info = index of first non-local symbol (number of local symbols) shsym(sh, lookup(".dynsym", 0)); sh = elfshname(".dynstr"); sh->type = SHT_STRTAB; sh->flags = SHF_ALLOC; sh->addralign = 1; shsym(sh, lookup(".dynstr", 0)); if(elfverneed) { sh = elfshname(".gnu.version"); sh->type = SHT_GNU_VERSYM; sh->flags = SHF_ALLOC; sh->addralign = 2; sh->link = elfshname(".dynsym")->shnum; sh->entsize = 2; shsym(sh, lookup(".gnu.version", 0)); sh = elfshname(".gnu.version_r"); sh->type = SHT_GNU_VERNEED; sh->flags = SHF_ALLOC; sh->addralign = PtrSize; sh->info = elfverneed; sh->link = elfshname(".dynstr")->shnum; shsym(sh, lookup(".gnu.version_r", 0)); } switch(eh->machine) { case EM_X86_64: sh = elfshname(".rela.plt"); sh->type = SHT_RELA; sh->flags = SHF_ALLOC; sh->entsize = ELF64RELASIZE; sh->addralign = PtrSize; sh->link = elfshname(".dynsym")->shnum; sh->info = elfshname(".plt")->shnum; shsym(sh, lookup(".rela.plt", 0)); sh = elfshname(".rela"); sh->type = SHT_RELA; sh->flags = SHF_ALLOC; sh->entsize = ELF64RELASIZE; sh->addralign = 8; sh->link = elfshname(".dynsym")->shnum; shsym(sh, lookup(".rela", 0)); break; default: sh = elfshname(".rel.plt"); sh->type = SHT_REL; sh->flags = SHF_ALLOC; sh->entsize = ELF32RELSIZE; sh->link = elfshname(".dynsym")->shnum; shsym(sh, lookup(".rel.plt", 0)); sh = elfshname(".rel"); sh->type = SHT_REL; sh->flags = SHF_ALLOC; sh->entsize = ELF32RELSIZE; sh->addralign = 4; sh->link = elfshname(".dynsym")->shnum; shsym(sh, lookup(".rel", 0)); break; } sh = elfshname(".plt"); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_EXECINSTR; if(eh->machine == EM_X86_64) sh->entsize = 16; else sh->entsize = 4; sh->addralign = 4; shsym(sh, lookup(".plt", 0)); sh = elfshname(".got"); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = PtrSize; sh->addralign = PtrSize; shsym(sh, lookup(".got", 0)); sh = elfshname(".got.plt"); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = PtrSize; sh->addralign = PtrSize; shsym(sh, lookup(".got.plt", 0)); sh = elfshname(".hash"); sh->type = SHT_HASH; sh->flags = SHF_ALLOC; sh->entsize = 4; sh->addralign = PtrSize; sh->link = elfshname(".dynsym")->shnum; shsym(sh, lookup(".hash", 0)); /* sh and PT_DYNAMIC for .dynamic section */ sh = elfshname(".dynamic"); sh->type = SHT_DYNAMIC; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 2*PtrSize; sh->addralign = PtrSize; sh->link = elfshname(".dynstr")->shnum; shsym(sh, lookup(".dynamic", 0)); ph = newElfPhdr(); ph->type = PT_DYNAMIC; ph->flags = PF_R + PF_W; phsh(ph, sh); /* * Thread-local storage segment (really just size). */ // Do not emit PT_TLS for OpenBSD since ld.so(1) does // not currently support it. This is handled // appropriately in runtime/cgo. if(tlsoffset != 0 && HEADTYPE != Hopenbsd) { ph = newElfPhdr(); ph->type = PT_TLS; ph->flags = PF_R; ph->memsz = -tlsoffset; ph->align = PtrSize; } } if(HEADTYPE == Hlinux) { ph = newElfPhdr(); ph->type = PT_GNU_STACK; ph->flags = PF_W+PF_R; ph->align = PtrSize; ph = newElfPhdr(); ph->type = PT_PAX_FLAGS; ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled ph->align = PtrSize; } elfobj: sh = elfshname(".shstrtab"); sh->type = SHT_STRTAB; sh->addralign = 1; shsym(sh, lookup(".shstrtab", 0)); eh->shstrndx = sh->shnum; // put these sections early in the list if(!debug['s']) { elfshname(".symtab"); elfshname(".strtab"); } for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshbits(sect); if(isobj) { for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshreloc(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshreloc(sect); } if(!debug['s']) { sh = elfshname(".symtab"); sh->type = SHT_SYMTAB; sh->off = symo; sh->size = symsize; sh->addralign = PtrSize; sh->entsize = 8+2*PtrSize; sh->link = elfshname(".strtab")->shnum; sh->info = elfglobalsymndx; sh = elfshname(".strtab"); sh->type = SHT_STRTAB; sh->off = symo+symsize; sh->size = elfstrsize; sh->addralign = 1; // TODO(rsc): Enable for isobj too, once we know it works. if(!isobj) dwarfaddelfheaders(); } /* Main header */ eh->ident[EI_MAG0] = '\177'; eh->ident[EI_MAG1] = 'E'; eh->ident[EI_MAG2] = 'L'; eh->ident[EI_MAG3] = 'F'; if(HEADTYPE == Hfreebsd) eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; else if(HEADTYPE == Hnetbsd) eh->ident[EI_OSABI] = ELFOSABI_NETBSD; else if(HEADTYPE == Hopenbsd) eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; if(PtrSize == 8) eh->ident[EI_CLASS] = ELFCLASS64; else eh->ident[EI_CLASS] = ELFCLASS32; eh->ident[EI_DATA] = ELFDATA2LSB; eh->ident[EI_VERSION] = EV_CURRENT; if(flag_shared) eh->type = ET_DYN; else if(isobj) eh->type = ET_REL; else eh->type = ET_EXEC; if(!isobj) eh->entry = entryvalue(); eh->version = EV_CURRENT; if(pph != nil) { pph->filesz = eh->phnum * eh->phentsize; pph->memsz = pph->filesz; } cseek(0); a = 0; a += elfwritehdr(); a += elfwritephdrs(); a += elfwriteshdrs(); if(!debug['d']) a += elfwriteinterp(); if(!isobj) { if(HEADTYPE == Hnetbsd) a += elfwritenetbsdsig(); if(HEADTYPE == Hopenbsd) a += elfwriteopenbsdsig(); if(buildinfolen > 0) a += elfwritebuildinfo(); } if(a > ELFRESERVE) diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); }
void asmb(void) { int32 v, magic; int a, dynsym; uint32 symo, startva, dwarfoff, machlink, resoff; ElfEhdr *eh; ElfPhdr *ph, *pph, *pnote; ElfShdr *sh; Section *sect; Sym *sym; int o; int i; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); machlink = 0; if(HEADTYPE == Hdarwin) { if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); cseek(dwarfoff); segdwarf.fileoff = cpos(); dwarfemitdebugsections(); segdwarf.filelen = cpos() - segdwarf.fileoff; machlink = domacholink(); } if(iself) { /* index of elf text section; needed by asmelfsym, double-checked below */ /* !debug['d'] causes extra sections before the .text section */ elftextsh = 2; if(!debug['d']) { elftextsh += 10; if(elfverneed) elftextsh += 2; } if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) elftextsh += 1; if(buildinfolen > 0) elftextsh += 1; } symsize = 0; spsize = 0; lcsize = 0; symo = 0; if(!debug['s']) { // TODO: rationalize if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { default: if(iself) goto Elfsym; case Hgarbunix: symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen; break; case Hunixcoff: symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; break; case Hplan9x32: symo = HEADR+segtext.filelen+segdata.filelen; break; case Hmsdoscom: case Hmsdosexe: debug['s'] = 1; symo = HEADR+segtext.filelen+segdata.filelen; break; case Hdarwin: symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink; break; Elfsym: symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; case Hwindows: symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; symo = rnd(symo, PEFILEALIGN); break; } cseek(symo); switch(HEADTYPE) { default: if(iself) { if(debug['v']) Bprint(&bso, "%5.2f elfsym\n", cputime()); asmelfsym(); cflush(); cwrite(elfstrdat, elfstrsize); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); } break; case Hplan9x32: asmplan9sym(); cflush(); sym = lookup("pclntab", 0); if(sym != nil) { lcsize = sym->np; for(i=0; i < lcsize; i++) cput(sym->p[i]); cflush(); } break; case Hwindows: if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); break; } } if(debug['v']) Bprint(&bso, "%5.2f headr\n", cputime()); Bflush(&bso); cseek(0L); switch(HEADTYPE) { default: if(iself) goto Elfput; case Hgarbunix: /* garbage */ lputb(0x160L<<16); /* magic and sections */ lputb(0L); /* time and date */ lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); lputb(symsize); /* nsyms */ lputb((0x38L<<16)|7L); /* size of optional hdr and flags */ lputb((0413<<16)|0437L); /* magic and version */ lputb(rnd(HEADR+segtext.filelen, 4096)); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(entryvalue()); /* va of entry */ lputb(INITTEXT-HEADR); /* va of base of text */ lputb(segdata.vaddr); /* va of base of data */ lputb(segdata.vaddr+segdata.filelen); /* va of base of bss */ lputb(~0L); /* gp reg mask */ lputb(0L); lputb(0L); lputb(0L); lputb(0L); lputb(~0L); /* gp value ?? */ break; case Hunixcoff: /* unix coff */ /* * file header */ lputl(0x0004014c); /* 4 sections, magic */ lputl(0); /* unix time stamp */ lputl(0); /* symbol table */ lputl(0); /* nsyms */ lputl(0x0003001c); /* flags, sizeof a.out header */ /* * a.out header */ lputl(0x10b); /* magic, version stamp */ lputl(rnd(segtext.filelen, INITRND)); /* text sizes */ lputl(segdata.filelen); /* data sizes */ lputl(segdata.len - segdata.filelen); /* bss sizes */ lputb(entryvalue()); /* va of entry */ lputl(INITTEXT); /* text start */ lputl(segdata.vaddr); /* data start */ /* * text section header */ s8put(".text"); lputl(HEADR); /* pa */ lputl(HEADR); /* va */ lputl(segtext.filelen); /* text size */ lputl(HEADR); /* file offset */ lputl(0); /* relocation */ lputl(0); /* line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x20); /* flags text only */ /* * data section header */ s8put(".data"); lputl(segdata.vaddr); /* pa */ lputl(segdata.vaddr); /* va */ lputl(segdata.filelen); /* data size */ lputl(HEADR+segtext.filelen); /* file offset */ lputl(0); /* relocation */ lputl(0); /* line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x40); /* flags data only */ /* * bss section header */ s8put(".bss"); lputl(segdata.vaddr+segdata.filelen); /* pa */ lputl(segdata.vaddr+segdata.filelen); /* va */ lputl(segdata.len - segdata.filelen); /* bss size */ lputl(0); /* file offset */ lputl(0); /* relocation */ lputl(0); /* line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x80); /* flags bss only */ /* * comment section header */ s8put(".comment"); lputl(0); /* pa */ lputl(0); /* va */ lputl(symsize+lcsize); /* comment size */ lputl(HEADR+segtext.filelen+segdata.filelen); /* file offset */ lputl(HEADR+segtext.filelen+segdata.filelen); /* offset of syms */ lputl(HEADR+segtext.filelen+segdata.filelen+symsize);/* offset of line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x200); /* flags comment only */ break; case Hplan9x32: /* plan9 */ magic = 4*11*11+7; lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ lputb(entryvalue()); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ break; case Hmsdoscom: /* MS-DOS .COM */ break; case Hmsdosexe: /* fake MS-DOS .EXE */ v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; wputl(0x5A4D); /* 'MZ' */ wputl(v % 512); /* bytes in last page */ wputl(rnd(v, 512)/512); /* total number of pages */ wputl(0x0000); /* number of reloc items */ v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); wputl(v/16); /* size of header */ wputl(0x0000); /* minimum allocation */ wputl(0xFFFF); /* maximum allocation */ wputl(0x0000); /* initial ss value */ wputl(0x0100); /* initial sp value */ wputl(0x0000); /* complemented checksum */ v = entryvalue(); wputl(v); /* initial ip value (!) */ wputl(0x0000); /* initial cs value */ wputl(0x0000); wputl(0x0000); wputl(0x003E); /* reloc table offset */ wputl(0x0000); /* overlay number */ break; case Hdarwin: asmbmacho(); break; Elfput: eh = getElfEhdr(); startva = INITTEXT - HEADR; resoff = ELFRESERVE; /* This null SHdr must appear before all others */ newElfShdr(elfstr[ElfStrEmpty]); /* program header info */ pph = newElfPhdr(); pph->type = PT_PHDR; pph->flags = PF_R + PF_X; pph->off = eh->ehsize; pph->vaddr = INITTEXT - HEADR + pph->off; pph->paddr = INITTEXT - HEADR + pph->off; pph->align = INITRND; /* * PHDR must be in a loaded segment. Adjust the text * segment boundaries downwards to include it. */ o = segtext.vaddr - pph->vaddr; segtext.vaddr -= o; segtext.len += o; o = segtext.fileoff - pph->off; segtext.fileoff -= o; segtext.filelen += o; if(!debug['d']) { /* interpreter */ sh = newElfShdr(elfstr[ElfStrInterp]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC; sh->addralign = 1; if(interpreter == nil) { switch(HEADTYPE) { case Hlinux: interpreter = linuxdynld; break; case Hfreebsd: interpreter = freebsddynld; break; case Hnetbsd: interpreter = netbsddynld; break; case Hopenbsd: interpreter = openbsddynld; break; } } resoff -= elfinterp(sh, startva, resoff, interpreter); ph = newElfPhdr(); ph->type = PT_INTERP; ph->flags = PF_R; phsh(ph, sh); } pnote = nil; if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) { sh = nil; switch(HEADTYPE) { case Hnetbsd: sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); resoff -= elfnetbsdsig(sh, startva, resoff); break; case Hopenbsd: sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]); resoff -= elfopenbsdsig(sh, startva, resoff); break; } pnote = newElfPhdr(); pnote->type = PT_NOTE; pnote->flags = PF_R; phsh(pnote, sh); } if(buildinfolen > 0) { sh = newElfShdr(elfstr[ElfStrNoteBuildInfo]); resoff -= elfbuildinfo(sh, startva, resoff); if(pnote == nil) { pnote = newElfPhdr(); pnote->type = PT_NOTE; pnote->flags = PF_R; } phsh(pnote, sh); } // Additions to the reserved area must be above this line. USED(resoff); elfphload(&segtext); elfphload(&segdata); /* Dynamic linking sections */ if(!debug['d']) { /* -d suppresses dynamic loader format */ /* S headers for dynamic linking */ sh = newElfShdr(elfstr[ElfStrGot]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 4; sh->addralign = 4; shsym(sh, lookup(".got", 0)); sh = newElfShdr(elfstr[ElfStrGotPlt]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 4; sh->addralign = 4; shsym(sh, lookup(".got.plt", 0)); dynsym = eh->shnum; sh = newElfShdr(elfstr[ElfStrDynsym]); sh->type = SHT_DYNSYM; sh->flags = SHF_ALLOC; sh->entsize = ELF32SYMSIZE; sh->addralign = 4; sh->link = dynsym+1; // dynstr // sh->info = index of first non-local symbol (number of local symbols) shsym(sh, lookup(".dynsym", 0)); sh = newElfShdr(elfstr[ElfStrDynstr]); sh->type = SHT_STRTAB; sh->flags = SHF_ALLOC; sh->addralign = 1; shsym(sh, lookup(".dynstr", 0)); if(elfverneed) { sh = newElfShdr(elfstr[ElfStrGnuVersion]); sh->type = SHT_GNU_VERSYM; sh->flags = SHF_ALLOC; sh->addralign = 2; sh->link = dynsym; sh->entsize = 2; shsym(sh, lookup(".gnu.version", 0)); sh = newElfShdr(elfstr[ElfStrGnuVersionR]); sh->type = SHT_GNU_VERNEED; sh->flags = SHF_ALLOC; sh->addralign = 4; sh->info = elfverneed; sh->link = dynsym+1; // dynstr shsym(sh, lookup(".gnu.version_r", 0)); } sh = newElfShdr(elfstr[ElfStrRelPlt]); sh->type = SHT_REL; sh->flags = SHF_ALLOC; sh->entsize = ELF32RELSIZE; sh->addralign = 4; sh->link = dynsym; sh->info = eh->shnum; // .plt shsym(sh, lookup(".rel.plt", 0)); sh = newElfShdr(elfstr[ElfStrPlt]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_EXECINSTR; sh->entsize = 4; sh->addralign = 4; shsym(sh, lookup(".plt", 0)); sh = newElfShdr(elfstr[ElfStrHash]); sh->type = SHT_HASH; sh->flags = SHF_ALLOC; sh->entsize = 4; sh->addralign = 4; sh->link = dynsym; shsym(sh, lookup(".hash", 0)); sh = newElfShdr(elfstr[ElfStrRel]); sh->type = SHT_REL; sh->flags = SHF_ALLOC; sh->entsize = ELF32RELSIZE; sh->addralign = 4; sh->link = dynsym; shsym(sh, lookup(".rel", 0)); /* sh and PT_DYNAMIC for .dynamic section */ sh = newElfShdr(elfstr[ElfStrDynamic]); sh->type = SHT_DYNAMIC; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 8; sh->addralign = 4; sh->link = dynsym+1; // dynstr shsym(sh, lookup(".dynamic", 0)); ph = newElfPhdr(); ph->type = PT_DYNAMIC; ph->flags = PF_R + PF_W; phsh(ph, sh); /* * Thread-local storage segment (really just size). */ // Do not emit PT_TLS for OpenBSD since ld.so(1) does // not currently support it. This is handled // appropriately in runtime/cgo. if(tlsoffset != 0 && HEADTYPE != Hopenbsd) { ph = newElfPhdr(); ph->type = PT_TLS; ph->flags = PF_R; ph->memsz = -tlsoffset; ph->align = 4; } } ph = newElfPhdr(); ph->type = PT_GNU_STACK; ph->flags = PF_W+PF_R; ph->align = 4; ph = newElfPhdr(); ph->type = PT_PAX_FLAGS; ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled ph->align = 4; sh = newElfShstrtab(elfstr[ElfStrShstrtab]); sh->type = SHT_STRTAB; sh->addralign = 1; shsym(sh, lookup(".shstrtab", 0)); if(elftextsh != eh->shnum) diag("elftextsh = %d, want %d", elftextsh, eh->shnum); for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshbits(sect); if(!debug['s']) { sh = newElfShdr(elfstr[ElfStrSymtab]); sh->type = SHT_SYMTAB; sh->off = symo; sh->size = symsize; sh->addralign = 4; sh->entsize = 16; sh->link = eh->shnum; // link to strtab sh = newElfShdr(elfstr[ElfStrStrtab]); sh->type = SHT_STRTAB; sh->off = symo+symsize; sh->size = elfstrsize; sh->addralign = 1; dwarfaddelfheaders(); } /* Main header */ eh->ident[EI_MAG0] = '\177'; eh->ident[EI_MAG1] = 'E'; eh->ident[EI_MAG2] = 'L'; eh->ident[EI_MAG3] = 'F'; eh->ident[EI_CLASS] = ELFCLASS32; eh->ident[EI_DATA] = ELFDATA2LSB; eh->ident[EI_VERSION] = EV_CURRENT; switch(HEADTYPE) { case Hfreebsd: eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; break; case Hnetbsd: eh->ident[EI_OSABI] = ELFOSABI_NETBSD; break; case Hopenbsd: eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; break; } eh->type = ET_EXEC; eh->machine = EM_386; eh->version = EV_CURRENT; eh->entry = entryvalue(); if(pph != nil) { pph->filesz = eh->phnum * eh->phentsize; pph->memsz = pph->filesz; } cseek(0); a = 0; a += elfwritehdr(); a += elfwritephdrs(); a += elfwriteshdrs(); a += elfwriteinterp(elfstr[ElfStrInterp]); if(HEADTYPE == Hnetbsd) a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]); if(HEADTYPE == Hopenbsd) a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]); if(buildinfolen > 0) a += elfwritebuildinfo(elfstr[ElfStrNoteBuildInfo]); if(a > ELFRESERVE) diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); break; case Hwindows: asmbpe(); break; } cflush(); }
int read_seq_write_rand(command_list *cl, DCB_registered_src *r_src, unsigned char is_overlay, cfile *out_cfh, unsigned long buf_size) { unsigned char *buf; unsigned char *p; unsigned long x, start=0, end=0, len=0; unsigned long max_pos = 0, pos = 0; unsigned long offset; signed long tmp_len; dcb_src_read_func read_func; cfile_window *cfw; u_dcb_src u_src; #define END_POS(x) ((x).src_pos + (x).len) pos = 0; max_pos = 0; if(is_overlay) { read_func = r_src->mask_read_func; } else { read_func = r_src->read_func; } assert(read_func != NULL); u_src = r_src->src_ptr; if(0 != cseek(u_src.cfh, 0, CSEEK_FSTART)) { ap_printf("cseeked failed: bailing, io_error 0\n"); return IO_ERROR; } if((buf = (unsigned char *)malloc(buf_size)) == NULL) { return MEM_ERROR; } // we should *never* go backwards u_src.cfh->state_flags |= CFILE_FLAG_BACKWARD_SEEKS; while(start < cl->com_count) { if(pos < cl->full_command[start].src_pos) { pos = cl->full_command[start].src_pos; max_pos = END_POS(cl->full_command[start]); } else { while(start < cl->com_count && pos > cl->full_command[start].src_pos) { start++; } if(start == cl->com_count) continue; pos = cl->full_command[start].src_pos; max_pos = MAX(max_pos, END_POS(cl->full_command[start])); } if(end < start) { end = start; } while(end < cl->com_count && cl->full_command[end].src_pos < max_pos) { max_pos = MAX(max_pos, END_POS(cl->full_command[end])); end++; } if(pos == max_pos) { continue; } while(pos < max_pos) { len = MIN(max_pos - pos, buf_size); x = read_func(u_src, pos, buf, len); // if(len < max_pos - pos) // v0printf("buffered %lu, max was %lu\n", len, max_pos - pos); if(len != x){ ap_printf("x=%lu, pos=%lu, len=%lu\n", x, pos, len); ap_printf("bailing, io_error 2\n"); free(buf); return IO_ERROR; } for(x=start; x < end; x++) { offset = MAX(cl->full_command[x].src_pos, pos); tmp_len = MIN(END_POS(cl->full_command[x]), pos + len) - offset; if(tmp_len > 0) { if(cl->full_command[x].ver_pos + (offset - cl->full_command[x].src_pos) != cseek(out_cfh, cl->full_command[x].ver_pos + (offset - cl->full_command[x].src_pos), CSEEK_FSTART)) { ap_printf("bailing, io_error 3\n"); free(buf); return IO_ERROR; } if(is_overlay) { p = buf + offset - pos; cfw = expose_page(out_cfh); if(cfw->write_end == 0) { cfw->write_start = cfw->pos; } while(buf + offset - pos + tmp_len > p) { if(cfw->pos == cfw->end) { cfw->write_end = cfw->end; cfw = next_page(out_cfh); if(cfw->end == 0) { ap_printf("bailing from applying overlay mask in read_seq_writ_rand\n"); free(buf); return IO_ERROR; } } cfw->buff[cfw->pos] += *p; p++; cfw->pos++; } cfw->write_end = cfw->pos; } else { if(tmp_len != cwrite(out_cfh, buf + offset - pos, tmp_len)) { ap_printf("bailing, io_error 4\n"); free(buf); return IO_ERROR; } } } } pos += len; } } u_src.cfh->state_flags &= ~CFILE_FLAG_BACKWARD_SEEKS; free(buf); return 0; }
void asmb(void) { int32 magic; int i; vlong vl, symo, dwarfoff, machlink; Section *sect; Sym *sym; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); if(debug['v']) Bprint(&bso, "%5.2f codeblk\n", cputime()); Bflush(&bso); if(iself) asmbelfsetup(); sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); machlink = 0; if(HEADTYPE == Hdarwin) { if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); cseek(dwarfoff); segdwarf.fileoff = cpos(); dwarfemitdebugsections(); segdwarf.filelen = cpos() - segdwarf.fileoff; machlink = domacholink(); } switch(HEADTYPE) { default: diag("unknown header type %d", HEADTYPE); case Hplan9x32: case Hplan9x64: case Helf: break; case Hdarwin: debug['8'] = 1; /* 64-bit addresses */ break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: debug['8'] = 1; /* 64-bit addresses */ break; case Hwindows: break; } symsize = 0; spsize = 0; lcsize = 0; symo = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { default: case Hplan9x64: case Helf: debug['s'] = 1; symo = HEADR+segtext.len+segdata.filelen; break; case Hdarwin: symo = rnd(HEADR+segtext.len, INITRND)+rnd(segdata.filelen, INITRND)+machlink; break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; case Hwindows: symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; symo = rnd(symo, PEFILEALIGN); break; } cseek(symo); switch(HEADTYPE) { default: if(iself) { cseek(symo); asmelfsym(); cflush(); cwrite(elfstrdat, elfstrsize); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); if(isobj) elfemitreloc(); } break; case Hplan9x64: asmplan9sym(); cflush(); sym = lookup("pclntab", 0); if(sym != nil) { lcsize = sym->np; for(i=0; i < lcsize; i++) cput(sym->p[i]); cflush(); } break; case Hwindows: if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); break; } } if(debug['v']) Bprint(&bso, "%5.2f headr\n", cputime()); Bflush(&bso); cseek(0L); switch(HEADTYPE) { default: case Hplan9x64: /* plan9 */ magic = 4*26*26+7; magic |= 0x00008000; /* fat header */ lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ vl = entryvalue(); lputb(PADDR(vl)); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ vputb(vl); /* va of entry */ break; case Hplan9x32: /* plan9 */ magic = 4*26*26+7; lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ lputb(entryvalue()); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ break; case Hdarwin: asmbmacho(); break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: asmbelf(symo); break; case Hwindows: asmbpe(); break; } cflush(); }
void asmb(void) { int32 magic; int a, dynsym; vlong vl, startva, symo, dwarfoff, machlink, resoff; ElfEhdr *eh; ElfPhdr *ph, *pph; ElfShdr *sh; Section *sect; Sym *sym; int i, o; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); elftextsh = 0; if(debug['v']) Bprint(&bso, "%5.2f codeblk\n", cputime()); Bflush(&bso); sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); /* output read-only data in text segment (rodata, gosymtab and pclntab) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); machlink = 0; if(HEADTYPE == Hdarwin) { if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); cseek(dwarfoff); segdwarf.fileoff = cpos(); dwarfemitdebugsections(); segdwarf.filelen = cpos() - segdwarf.fileoff; machlink = domacholink(); } switch(HEADTYPE) { default: diag("unknown header type %d", HEADTYPE); case Hplan9x32: case Hplan9x64: case Helf: break; case Hdarwin: debug['8'] = 1; /* 64-bit addresses */ break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: debug['8'] = 1; /* 64-bit addresses */ /* index of elf text section; needed by asmelfsym, double-checked below */ /* !debug['d'] causes extra sections before the .text section */ elftextsh = 2; if(!debug['d']) { elftextsh += 10; if(elfverneed) elftextsh += 2; } if(HEADTYPE == Hnetbsd) elftextsh += 1; break; case Hwindows: break; } symsize = 0; spsize = 0; lcsize = 0; symo = 0; if(!debug['s']) { if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { default: case Hplan9x64: case Helf: debug['s'] = 1; symo = HEADR+segtext.len+segdata.filelen; break; case Hdarwin: symo = rnd(HEADR+segtext.len, INITRND)+rnd(segdata.filelen, INITRND)+machlink; break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; case Hwindows: symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; symo = rnd(symo, PEFILEALIGN); break; } cseek(symo); switch(HEADTYPE) { default: if(iself) { cseek(symo); asmelfsym(); cflush(); cwrite(elfstrdat, elfstrsize); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); } break; case Hplan9x64: asmplan9sym(); cflush(); sym = lookup("pclntab", 0); if(sym != nil) { lcsize = sym->np; for(i=0; i < lcsize; i++) cput(sym->p[i]); cflush(); } break; case Hwindows: if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); break; } } if(debug['v']) Bprint(&bso, "%5.2f headr\n", cputime()); Bflush(&bso); cseek(0L); switch(HEADTYPE) { default: case Hplan9x64: /* plan9 */ magic = 4*26*26+7; magic |= 0x00008000; /* fat header */ lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ vl = entryvalue(); lputb(PADDR(vl)); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ vputb(vl); /* va of entry */ break; case Hplan9x32: /* plan9 */ magic = 4*26*26+7; lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ lputb(entryvalue()); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ break; case Hdarwin: asmbmacho(); break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: /* elf amd-64 */ eh = getElfEhdr(); startva = INITTEXT - HEADR; resoff = ELFRESERVE; /* This null SHdr must appear before all others */ newElfShdr(elfstr[ElfStrEmpty]); /* program header info */ pph = newElfPhdr(); pph->type = PT_PHDR; pph->flags = PF_R + PF_X; pph->off = eh->ehsize; pph->vaddr = INITTEXT - HEADR + pph->off; pph->paddr = INITTEXT - HEADR + pph->off; pph->align = INITRND; /* * PHDR must be in a loaded segment. Adjust the text * segment boundaries downwards to include it. */ o = segtext.vaddr - pph->vaddr; segtext.vaddr -= o; segtext.len += o; o = segtext.fileoff - pph->off; segtext.fileoff -= o; segtext.filelen += o; if(!debug['d']) { /* interpreter */ sh = newElfShdr(elfstr[ElfStrInterp]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC; sh->addralign = 1; if(interpreter == nil) { switch(HEADTYPE) { case Hlinux: interpreter = linuxdynld; break; case Hfreebsd: interpreter = freebsddynld; break; case Hnetbsd: interpreter = netbsddynld; break; case Hopenbsd: interpreter = openbsddynld; break; } } resoff -= elfinterp(sh, startva, resoff, interpreter); ph = newElfPhdr(); ph->type = PT_INTERP; ph->flags = PF_R; phsh(ph, sh); } if(HEADTYPE == Hnetbsd) { sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); sh->type = SHT_NOTE; sh->flags = SHF_ALLOC; sh->addralign = 4; resoff -= elfnetbsdsig(sh, startva, resoff); ph = newElfPhdr(); ph->type = PT_NOTE; ph->flags = PF_R; phsh(ph, sh); } elfphload(&segtext); elfphload(&segdata); /* Dynamic linking sections */ if(!debug['d']) { /* -d suppresses dynamic loader format */ /* S headers for dynamic linking */ sh = newElfShdr(elfstr[ElfStrGot]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 8; sh->addralign = 8; shsym(sh, lookup(".got", 0)); sh = newElfShdr(elfstr[ElfStrGotPlt]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 8; sh->addralign = 8; shsym(sh, lookup(".got.plt", 0)); dynsym = eh->shnum; sh = newElfShdr(elfstr[ElfStrDynsym]); sh->type = SHT_DYNSYM; sh->flags = SHF_ALLOC; sh->entsize = ELF64SYMSIZE; sh->addralign = 8; sh->link = dynsym+1; // dynstr // sh->info = index of first non-local symbol (number of local symbols) shsym(sh, lookup(".dynsym", 0)); sh = newElfShdr(elfstr[ElfStrDynstr]); sh->type = SHT_STRTAB; sh->flags = SHF_ALLOC; sh->addralign = 1; shsym(sh, lookup(".dynstr", 0)); if(elfverneed) { sh = newElfShdr(elfstr[ElfStrGnuVersion]); sh->type = SHT_GNU_VERSYM; sh->flags = SHF_ALLOC; sh->addralign = 2; sh->link = dynsym; sh->entsize = 2; shsym(sh, lookup(".gnu.version", 0)); sh = newElfShdr(elfstr[ElfStrGnuVersionR]); sh->type = SHT_GNU_VERNEED; sh->flags = SHF_ALLOC; sh->addralign = 8; sh->info = elfverneed; sh->link = dynsym+1; // dynstr shsym(sh, lookup(".gnu.version_r", 0)); } sh = newElfShdr(elfstr[ElfStrRelaPlt]); sh->type = SHT_RELA; sh->flags = SHF_ALLOC; sh->entsize = ELF64RELASIZE; sh->addralign = 8; sh->link = dynsym; sh->info = eh->shnum; // .plt shsym(sh, lookup(".rela.plt", 0)); sh = newElfShdr(elfstr[ElfStrPlt]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_EXECINSTR; sh->entsize = 16; sh->addralign = 4; shsym(sh, lookup(".plt", 0)); sh = newElfShdr(elfstr[ElfStrHash]); sh->type = SHT_HASH; sh->flags = SHF_ALLOC; sh->entsize = 4; sh->addralign = 8; sh->link = dynsym; shsym(sh, lookup(".hash", 0)); sh = newElfShdr(elfstr[ElfStrRela]); sh->type = SHT_RELA; sh->flags = SHF_ALLOC; sh->entsize = ELF64RELASIZE; sh->addralign = 8; sh->link = dynsym; shsym(sh, lookup(".rela", 0)); /* sh and PT_DYNAMIC for .dynamic section */ sh = newElfShdr(elfstr[ElfStrDynamic]); sh->type = SHT_DYNAMIC; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 16; sh->addralign = 8; sh->link = dynsym+1; // dynstr shsym(sh, lookup(".dynamic", 0)); ph = newElfPhdr(); ph->type = PT_DYNAMIC; ph->flags = PF_R + PF_W; phsh(ph, sh); /* * Thread-local storage segment (really just size). */ if(tlsoffset != 0) { ph = newElfPhdr(); ph->type = PT_TLS; ph->flags = PF_R; ph->memsz = -tlsoffset; ph->align = 8; } } ph = newElfPhdr(); ph->type = PT_GNU_STACK; ph->flags = PF_W+PF_R; ph->align = 8; ph = newElfPhdr(); ph->type = PT_PAX_FLAGS; ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled ph->align = 8; sh = newElfShstrtab(elfstr[ElfStrShstrtab]); sh->type = SHT_STRTAB; sh->addralign = 1; shsym(sh, lookup(".shstrtab", 0)); if(elftextsh != eh->shnum) diag("elftextsh = %d, want %d", elftextsh, eh->shnum); for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshbits(sect); if(!debug['s']) { sh = newElfShdr(elfstr[ElfStrSymtab]); sh->type = SHT_SYMTAB; sh->off = symo; sh->size = symsize; sh->addralign = 8; sh->entsize = 24; sh->link = eh->shnum; // link to strtab sh = newElfShdr(elfstr[ElfStrStrtab]); sh->type = SHT_STRTAB; sh->off = symo+symsize; sh->size = elfstrsize; sh->addralign = 1; dwarfaddelfheaders(); } /* Main header */ eh->ident[EI_MAG0] = '\177'; eh->ident[EI_MAG1] = 'E'; eh->ident[EI_MAG2] = 'L'; eh->ident[EI_MAG3] = 'F'; if(HEADTYPE == Hfreebsd) eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; else if(HEADTYPE == Hnetbsd) eh->ident[EI_OSABI] = ELFOSABI_NETBSD; else if(HEADTYPE == Hopenbsd) eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; eh->ident[EI_CLASS] = ELFCLASS64; eh->ident[EI_DATA] = ELFDATA2LSB; eh->ident[EI_VERSION] = EV_CURRENT; eh->type = ET_EXEC; eh->machine = EM_X86_64; eh->version = EV_CURRENT; eh->entry = entryvalue(); pph->filesz = eh->phnum * eh->phentsize; pph->memsz = pph->filesz; cseek(0); a = 0; a += elfwritehdr(); a += elfwritephdrs(); a += elfwriteshdrs(); a += elfwriteinterp(elfstr[ElfStrInterp]); if(HEADTYPE == Hnetbsd) a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]); if(a > ELFRESERVE) diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); break; case Hwindows: asmbpe(); break; } cflush(); }
void asmbpe(void) { IMAGE_SECTION_HEADER *t, *d; switch(thechar) { default: diag("unknown PE architecture"); errorexit(); case '6': fh.Machine = IMAGE_FILE_MACHINE_AMD64; break; case '8': fh.Machine = IMAGE_FILE_MACHINE_I386; break; } t = addpesection(".text", segtext.len, segtext.len); t->Characteristics = IMAGE_SCN_CNT_CODE| IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ; chksectseg(t, &segtext); textsect = nsect; d = addpesection(".data", segdata.len, segdata.filelen); d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; chksectseg(d, &segdata); if(!debug['s']) dwarfaddpeheaders(); cseek(nextfileoff); addimports(d); addexports(); addsymtable(); addpersrc(); fh.NumberOfSections = nsect; fh.TimeDateStamp = time(0); fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED| IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED; if (pe64) { fh.SizeOfOptionalHeader = sizeof(oh64); fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; set(Magic, 0x20b); // PE32+ } else { fh.SizeOfOptionalHeader = sizeof(oh); fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE; set(Magic, 0x10b); // PE32 oh.BaseOfData = d->VirtualAddress; } set(MajorLinkerVersion, 3); set(MinorLinkerVersion, 0); set(SizeOfCode, t->SizeOfRawData); set(SizeOfInitializedData, d->SizeOfRawData); set(SizeOfUninitializedData, 0); set(AddressOfEntryPoint, entryvalue()-PEBASE); set(BaseOfCode, t->VirtualAddress); set(ImageBase, PEBASE); set(SectionAlignment, PESECTALIGN); set(FileAlignment, PEFILEALIGN); set(MajorOperatingSystemVersion, 4); set(MinorOperatingSystemVersion, 0); set(MajorImageVersion, 1); set(MinorImageVersion, 0); set(MajorSubsystemVersion, 4); set(MinorSubsystemVersion, 0); set(SizeOfImage, nextsectoff); set(SizeOfHeaders, PEFILEHEADR); if(strcmp(headstring, "windowsgui") == 0) set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_GUI); else set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_CUI); // Disable stack growth as we don't want Windows to // fiddle with the thread stack limits, which we set // ourselves to circumvent the stack checks in the // Windows exception dispatcher. // Commit size must be strictly less than reserve // size otherwise reserve will be rounded up to a // larger size, as verified with VMMap. // Go code would be OK with 64k stacks, but we need larger stacks for cgo. // That default stack reserve size affects only the main thread, // for other threads we specify stack size in runtime explicitly // (runtime knows whether cgo is enabled or not). // If you change stack reserve sizes here, // change STACKSIZE in runtime/cgo/gcc_windows_{386,amd64}.c as well. if(!iscgo) { set(SizeOfStackReserve, 0x00010000); set(SizeOfStackCommit, 0x0000ffff); } else { set(SizeOfStackReserve, pe64 ? 0x00200000 : 0x00100000); // account for 2 guard pages set(SizeOfStackCommit, (pe64 ? 0x00200000 : 0x00100000) - 0x2000); } set(SizeOfHeapReserve, 0x00100000); set(SizeOfHeapCommit, 0x00001000); set(NumberOfRvaAndSizes, 16); pewrite(); }
void asmb(void) { int32 magic; uint32 symo, dwarfoff, machlink; Section *sect; LSym *sym; int i; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); if(iself) asmbelfsetup(); sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } if(segrodata.filelen > 0) { if(debug['v']) Bprint(&bso, "%5.2f rodatblk\n", cputime()); Bflush(&bso); cseek(segrodata.fileoff); datblk(segrodata.vaddr, segrodata.filelen); } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); machlink = 0; if(HEADTYPE == Hdarwin) { if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); cseek(dwarfoff); segdwarf.fileoff = cpos(); dwarfemitdebugsections(); segdwarf.filelen = cpos() - segdwarf.fileoff; machlink = domacholink(); } symsize = 0; spsize = 0; lcsize = 0; symo = 0; if(!debug['s']) { // TODO: rationalize if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { default: if(iself) goto Elfsym; case Hplan9: symo = HEADR+segtext.filelen+segdata.filelen; break; case Hdarwin: symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink; break; Elfsym: symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; case Hwindows: symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; symo = rnd(symo, PEFILEALIGN); break; } cseek(symo); switch(HEADTYPE) { default: if(iself) { if(debug['v']) Bprint(&bso, "%5.2f elfsym\n", cputime()); asmelfsym(); cflush(); cwrite(elfstrdat, elfstrsize); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); if(linkmode == LinkExternal) elfemitreloc(); } break; case Hplan9: asmplan9sym(); cflush(); sym = linklookup(ctxt, "pclntab", 0); if(sym != nil) { lcsize = sym->np; for(i=0; i < lcsize; i++) cput(sym->p[i]); cflush(); } break; case Hwindows: if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); break; case Hdarwin: if(linkmode == LinkExternal) machoemitreloc(); break; } } if(debug['v']) Bprint(&bso, "%5.2f headr\n", cputime()); Bflush(&bso); cseek(0L); switch(HEADTYPE) { default: case Hplan9: /* plan9 */ magic = 4*11*11+7; lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ lputb(entryvalue()); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ break; case Hdarwin: asmbmacho(); break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: case Hdragonfly: case Hnacl: asmbelf(symo); break; case Hwindows: asmbpe(); break; } cflush(); }
void asmb(void) { int32 t; int a, dynsym; uint32 fo, symo, startva, resoff; ElfEhdr *eh; ElfPhdr *ph, *pph; ElfShdr *sh; Section *sect; int o; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); /* output read-only data in text segment (rodata, gosymtab and pclntab) */ for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); if(iself) { /* index of elf text section; needed by asmelfsym, double-checked below */ /* !debug['d'] causes extra sections before the .text section */ elftextsh = 2; if(!debug['d']) { elftextsh += 10; if(elfverneed) elftextsh += 2; } if(HEADTYPE == Hnetbsd) elftextsh += 1; } /* output symbol table */ symsize = 0; lcsize = 0; symo = 0; if(!debug['s']) { // TODO: rationalize if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { default: if(iself) goto ElfSym; case Hnoheader: case Hrisc: case Hixp1200: case Hipaq: debug['s'] = 1; break; case Hplan9x32: symo = HEADR+segtext.len+segdata.filelen; break; case Hnetbsd: symo = rnd(segdata.filelen, 4096); break; ElfSym: symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; } cseek(symo); if(iself) { if(debug['v']) Bprint(&bso, "%5.2f elfsym\n", cputime()); asmelfsym(); cflush(); cwrite(elfstrdat, elfstrsize); // if(debug['v']) // Bprint(&bso, "%5.2f dwarf\n", cputime()); // dwarfemitdebugsections(); } cflush(); } cursym = nil; if(debug['v']) Bprint(&bso, "%5.2f header\n", cputime()); Bflush(&bso); cseek(0L); switch(HEADTYPE) { case Hnoheader: /* no header */ break; case Hrisc: /* aif for risc os */ lputl(0xe1a00000); /* NOP - decompress code */ lputl(0xe1a00000); /* NOP - relocation code */ lputl(0xeb000000 + 12); /* BL - zero init code */ lputl(0xeb000000 + (entryvalue() - INITTEXT + HEADR - 12 - 8) / 4); /* BL - entry code */ lputl(0xef000011); /* SWI - exit code */ lputl(textsize+HEADR); /* text size */ lputl(segdata.filelen); /* data size */ lputl(0); /* sym size */ lputl(segdata.len - segdata.filelen); /* bss size */ lputl(0); /* sym type */ lputl(INITTEXT-HEADR); /* text addr */ lputl(0); /* workspace - ignored */ lputl(32); /* addr mode / data addr flag */ lputl(0); /* data addr */ for(t=0; t<2; t++) lputl(0); /* reserved */ for(t=0; t<15; t++) lputl(0xe1a00000); /* NOP - zero init code */ lputl(0xe1a0f00e); /* B (R14) - zero init return */ break; case Hplan9x32: /* plan 9 */ lput(0x647); /* magic */ lput(textsize); /* sizes */ lput(segdata.filelen); lput(segdata.len - segdata.filelen); lput(symsize); /* nsyms */ lput(entryvalue()); /* va of entry */ lput(0L); lput(lcsize); break; case Hnetbsd: /* boot for NetBSD */ lput((143<<16)|0413); /* magic */ lputl(rnd(HEADR+textsize, 4096)); lputl(rnd(segdata.filelen, 4096)); lputl(segdata.len - segdata.filelen); lputl(symsize); /* nsyms */ lputl(entryvalue()); /* va of entry */ lputl(0L); lputl(0L); break; case Hixp1200: /* boot for IXP1200 */ break; case Hipaq: /* boot for ipaq */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ lputl(0xe3300000); /* nop */ break; case Hlinux: /* elf arm */ eh = getElfEhdr(); fo = HEADR; startva = INITTEXT - fo; /* va of byte 0 of file */ resoff = ELFRESERVE; /* This null SHdr must appear before all others */ newElfShdr(elfstr[ElfStrEmpty]); /* program header info */ pph = newElfPhdr(); pph->type = PT_PHDR; pph->flags = PF_R + PF_X; pph->off = eh->ehsize; pph->vaddr = INITTEXT - HEADR + pph->off; pph->paddr = INITTEXT - HEADR + pph->off; pph->align = INITRND; /* * PHDR must be in a loaded segment. Adjust the text * segment boundaries downwards to include it. */ o = segtext.vaddr - pph->vaddr; segtext.vaddr -= o; segtext.len += o; o = segtext.fileoff - pph->off; segtext.fileoff -= o; segtext.filelen += o; if(!debug['d']) { /* interpreter for dynamic linking */ sh = newElfShdr(elfstr[ElfStrInterp]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC; sh->addralign = 1; if(interpreter == nil) interpreter = linuxdynld; resoff -= elfinterp(sh, startva, resoff, interpreter); ph = newElfPhdr(); ph->type = PT_INTERP; ph->flags = PF_R; phsh(ph, sh); } if(HEADTYPE == Hnetbsd) { sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); sh->type = SHT_NOTE; sh->flags = SHF_ALLOC; sh->addralign = 4; resoff -= elfnetbsdsig(sh, startva, resoff); ph = newElfPhdr(); ph->type = PT_NOTE; ph->flags = PF_R; phsh(ph, sh); } elfphload(&segtext); elfphload(&segdata); /* Dynamic linking sections */ if(!debug['d']) { /* -d suppresses dynamic loader format */ /* S headers for dynamic linking */ sh = newElfShdr(elfstr[ElfStrGot]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 4; sh->addralign = 4; shsym(sh, lookup(".got", 0)); sh = newElfShdr(elfstr[ElfStrGotPlt]); sh->type = SHT_PROGBITS; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 4; sh->addralign = 4; shsym(sh, lookup(".got.plt", 0)); dynsym = eh->shnum; sh = newElfShdr(elfstr[ElfStrDynsym]); sh->type = SHT_DYNSYM; sh->flags = SHF_ALLOC; sh->entsize = ELF32SYMSIZE; sh->addralign = 4; sh->link = dynsym+1; // dynstr // sh->info = index of first non-local symbol (number of local symbols) shsym(sh, lookup(".dynsym", 0)); sh = newElfShdr(elfstr[ElfStrDynstr]); sh->type = SHT_STRTAB; sh->flags = SHF_ALLOC; sh->addralign = 1; shsym(sh, lookup(".dynstr", 0)); sh = newElfShdr(elfstr[ElfStrHash]); sh->type = SHT_HASH; sh->flags = SHF_ALLOC; sh->entsize = 4; sh->addralign = 4; sh->link = dynsym; shsym(sh, lookup(".hash", 0)); sh = newElfShdr(elfstr[ElfStrRel]); sh->type = SHT_REL; sh->flags = SHF_ALLOC; sh->entsize = ELF32RELSIZE; sh->addralign = 4; sh->link = dynsym; shsym(sh, lookup(".rel", 0)); /* sh and PT_DYNAMIC for .dynamic section */ sh = newElfShdr(elfstr[ElfStrDynamic]); sh->type = SHT_DYNAMIC; sh->flags = SHF_ALLOC+SHF_WRITE; sh->entsize = 8; sh->addralign = 4; sh->link = dynsym+1; // dynstr shsym(sh, lookup(".dynamic", 0)); ph = newElfPhdr(); ph->type = PT_DYNAMIC; ph->flags = PF_R + PF_W; phsh(ph, sh); /* * Thread-local storage segment (really just size). if(tlsoffset != 0) { ph = newElfPhdr(); ph->type = PT_TLS; ph->flags = PF_R; ph->memsz = -tlsoffset; ph->align = 4; } */ } ph = newElfPhdr(); ph->type = PT_GNU_STACK; ph->flags = PF_W+PF_R; ph->align = 4; sh = newElfShstrtab(elfstr[ElfStrShstrtab]); sh->type = SHT_STRTAB; sh->addralign = 1; shsym(sh, lookup(".shstrtab", 0)); if(elftextsh != eh->shnum) diag("elftextsh = %d, want %d", elftextsh, eh->shnum); for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshbits(sect); if(!debug['s']) { sh = newElfShdr(elfstr[ElfStrSymtab]); sh->type = SHT_SYMTAB; sh->off = symo; sh->size = symsize; sh->addralign = 4; sh->entsize = 16; sh->link = eh->shnum; // link to strtab sh = newElfShdr(elfstr[ElfStrStrtab]); sh->type = SHT_STRTAB; sh->off = symo+symsize; sh->size = elfstrsize; sh->addralign = 1; // dwarfaddelfheaders(); } /* Main header */ eh->ident[EI_MAG0] = '\177'; eh->ident[EI_MAG1] = 'E'; eh->ident[EI_MAG2] = 'L'; eh->ident[EI_MAG3] = 'F'; eh->ident[EI_CLASS] = ELFCLASS32; eh->ident[EI_DATA] = ELFDATA2LSB; eh->ident[EI_VERSION] = EV_CURRENT; eh->type = ET_EXEC; eh->machine = EM_ARM; eh->version = EV_CURRENT; eh->entry = entryvalue(); if(pph != nil) { pph->filesz = eh->phnum * eh->phentsize; pph->memsz = pph->filesz; } cseek(0); a = 0; a += elfwritehdr(); a += elfwritephdrs(); a += elfwriteshdrs(); a += elfwriteinterp(elfstr[ElfStrInterp]); if(HEADTYPE == Hnetbsd) a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]); if(a > ELFRESERVE) diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); break; } cflush(); if(debug['c']){ print("textsize=%d\n", textsize); print("datsize=%ulld\n", segdata.filelen); print("bsssize=%ulld\n", segdata.len - segdata.filelen); print("symsize=%d\n", symsize); print("lcsize=%d\n", lcsize); print("total=%lld\n", textsize+segdata.len+symsize+lcsize); } }
signed int xdelta1ReconstructDCBuff(DCB_SRC_ID src_id, cfile *patchf, CommandBuffer *dcbuff, unsigned int version) { cfile *add_cfh, *ctrl_cfh; unsigned long control_offset, control_end, flags; unsigned long len, offset, x, count, proc_count; unsigned long add_start, add_pos; unsigned char buff[32]; EDCB_SRC_ID ref_id, add_id; unsigned char add_is_sequential, copy_is_sequential; cseek(patchf, XDELTA_MAGIC_LEN, CSEEK_FSTART); cread(patchf, buff, 4); flags = readUBytesBE(buff, 4); cread(patchf, buff, 4); dcbuff->ver_size = 0; // the header is 32 bytes, then 2 word's, each the length of the // src/trg file name. add_start = 32 + readUBytesBE(buff, 2) + readUBytesBE(buff + 2, 2); cseek(patchf, -12, CSEEK_END); control_end = ctell(patchf, CSEEK_FSTART); cread(patchf, buff, 4); control_offset = readUBytesBE(buff,4); cseek(patchf, control_offset, CSEEK_FSTART); if(flags & XD_COMPRESSED_FLAG) { v2printf("compressed segments detected\n"); if((ctrl_cfh = (cfile *)malloc(sizeof(cfile)))==NULL) { return MEM_ERROR; } copen_child_cfh(ctrl_cfh, patchf, control_offset, control_end, GZIP_COMPRESSOR, CFILE_RONLY); } else { ctrl_cfh = patchf; } /* kludge. skipping 8 byte unknown, and to_file md5.*/ cseek(ctrl_cfh, 24, CSEEK_CUR); /* read the frigging to length, since it's variable */ x = readXDInt(ctrl_cfh, buff); v2printf("to_len(%lu)\n", x); /* two bytes here I don't know about... */ cseek(ctrl_cfh, 2, CSEEK_CUR); /* get and skip the segment name's len and md5 */ x = readXDInt(ctrl_cfh, buff); cseek(ctrl_cfh, x + 16, CSEEK_CUR); /* read the damned segment patch len. */ x = readXDInt(ctrl_cfh, buff); /* skip the seq/has data bytes */ /* handle sequential/has_data info */ cread(ctrl_cfh, buff, 2); add_is_sequential = buff[1]; v2printf("patch sequential? (%u)\n", add_is_sequential); /* get and skip the next segment name len and md5. */ x = readXDInt(ctrl_cfh, buff); cseek(ctrl_cfh, x + 16, CSEEK_CUR); /* read the damned segment patch len. */ x = readXDInt(ctrl_cfh, buff); v2printf("seg2_len(%lu)\n", x); /* handle sequential/has_data */ cread(ctrl_cfh, buff, 2); copy_is_sequential = buff[1]; v2printf("copy is sequential? (%u)\n", copy_is_sequential); /* next get the number of instructions (eg copy | adds) */ count = readXDInt(ctrl_cfh, buff); proc_count=0; /* so starts the commands... */ v2printf("supposedly %lu commands...\nstarting command processing at %zi\n", count, ctell(ctrl_cfh, CSEEK_FSTART)); if(flags & XD_COMPRESSED_FLAG) { add_pos = 0; if((add_cfh = (cfile *)malloc(sizeof(cfile)))==NULL) { return MEM_ERROR; } copen_child_cfh(add_cfh, patchf, add_start, control_offset, GZIP_COMPRESSOR, CFILE_RONLY); add_id = DCB_REGISTER_ADD_SRC(dcbuff, add_cfh, NULL, 1); } else { add_pos = add_start; add_id = DCB_REGISTER_VOLATILE_ADD_SRC(dcbuff, patchf, NULL, 0); } ref_id = src_id; while(proc_count++ != count) { x = readXDInt(ctrl_cfh, buff); offset = readXDInt(ctrl_cfh, buff); len = readXDInt(ctrl_cfh, buff); if(x==XD_INDEX_COPY) { DCB_add_copy(dcbuff, offset, 0, len, ref_id); } else { if(add_is_sequential != 0) { offset += add_pos; add_pos += len; } else { offset += add_pos; } DCB_add_add(dcbuff, offset, len, add_id); } } v2printf("finishing position was %zi\n", ctell(ctrl_cfh, CSEEK_FSTART)); v2printf("processed %lu of %lu commands\n", proc_count, count); dcbuff->ver_size = dcbuff->reconstruct_pos; if(flags & XD_COMPRESSED_FLAG) { cclose(ctrl_cfh); free(ctrl_cfh); } return 0; }
void asmb(void) { int32 v, magic; uint32 symo, dwarfoff, machlink; Section *sect; Sym *sym; int i; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); if(iself) asmbelfsetup(); sect = segtext.sect; cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); codeblk(sect->vaddr, sect->len); for(sect = sect->next; sect != nil; sect = sect->next) { cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); datblk(sect->vaddr, sect->len); } if(segrodata.filelen > 0) { if(debug['v']) Bprint(&bso, "%5.2f rodatblk\n", cputime()); Bflush(&bso); cseek(segrodata.fileoff); datblk(segrodata.vaddr, segrodata.filelen); } if(debug['v']) Bprint(&bso, "%5.2f datblk\n", cputime()); Bflush(&bso); cseek(segdata.fileoff); datblk(segdata.vaddr, segdata.filelen); machlink = 0; if(HEADTYPE == Hdarwin) { if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); cseek(dwarfoff); segdwarf.fileoff = cpos(); dwarfemitdebugsections(); segdwarf.filelen = cpos() - segdwarf.fileoff; machlink = domacholink(); } symsize = 0; spsize = 0; lcsize = 0; symo = 0; if(!debug['s']) { // TODO: rationalize if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { default: if(iself) goto Elfsym; case Hgarbunix: symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen; break; case Hunixcoff: symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; break; case Hplan9x32: symo = HEADR+segtext.filelen+segdata.filelen; break; case Hmsdoscom: case Hmsdosexe: debug['s'] = 1; symo = HEADR+segtext.filelen+segdata.filelen; break; case Hdarwin: symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink; break; Elfsym: symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; case Hwindows: symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; symo = rnd(symo, PEFILEALIGN); break; } cseek(symo); switch(HEADTYPE) { default: if(iself) { if(debug['v']) Bprint(&bso, "%5.2f elfsym\n", cputime()); asmelfsym(); cflush(); cwrite(elfstrdat, elfstrsize); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); if(linkmode == LinkExternal) elfemitreloc(); } break; case Hplan9x32: asmplan9sym(); cflush(); sym = lookup("pclntab", 0); if(sym != nil) { lcsize = sym->np; for(i=0; i < lcsize; i++) cput(sym->p[i]); cflush(); } break; case Hwindows: if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); break; case Hdarwin: if(linkmode == LinkExternal) machoemitreloc(); break; } } if(debug['v']) Bprint(&bso, "%5.2f headr\n", cputime()); Bflush(&bso); cseek(0L); switch(HEADTYPE) { default: case Hgarbunix: /* garbage */ lputb(0x160L<<16); /* magic and sections */ lputb(0L); /* time and date */ lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); lputb(symsize); /* nsyms */ lputb((0x38L<<16)|7L); /* size of optional hdr and flags */ lputb((0413<<16)|0437L); /* magic and version */ lputb(rnd(HEADR+segtext.filelen, 4096)); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(entryvalue()); /* va of entry */ lputb(INITTEXT-HEADR); /* va of base of text */ lputb(segdata.vaddr); /* va of base of data */ lputb(segdata.vaddr+segdata.filelen); /* va of base of bss */ lputb(~0L); /* gp reg mask */ lputb(0L); lputb(0L); lputb(0L); lputb(0L); lputb(~0L); /* gp value ?? */ break; case Hunixcoff: /* unix coff */ /* * file header */ lputl(0x0004014c); /* 4 sections, magic */ lputl(0); /* unix time stamp */ lputl(0); /* symbol table */ lputl(0); /* nsyms */ lputl(0x0003001c); /* flags, sizeof a.out header */ /* * a.out header */ lputl(0x10b); /* magic, version stamp */ lputl(rnd(segtext.filelen, INITRND)); /* text sizes */ lputl(segdata.filelen); /* data sizes */ lputl(segdata.len - segdata.filelen); /* bss sizes */ lputb(entryvalue()); /* va of entry */ lputl(INITTEXT); /* text start */ lputl(segdata.vaddr); /* data start */ /* * text section header */ s8put(".text"); lputl(HEADR); /* pa */ lputl(HEADR); /* va */ lputl(segtext.filelen); /* text size */ lputl(HEADR); /* file offset */ lputl(0); /* relocation */ lputl(0); /* line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x20); /* flags text only */ /* * data section header */ s8put(".data"); lputl(segdata.vaddr); /* pa */ lputl(segdata.vaddr); /* va */ lputl(segdata.filelen); /* data size */ lputl(HEADR+segtext.filelen); /* file offset */ lputl(0); /* relocation */ lputl(0); /* line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x40); /* flags data only */ /* * bss section header */ s8put(".bss"); lputl(segdata.vaddr+segdata.filelen); /* pa */ lputl(segdata.vaddr+segdata.filelen); /* va */ lputl(segdata.len - segdata.filelen); /* bss size */ lputl(0); /* file offset */ lputl(0); /* relocation */ lputl(0); /* line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x80); /* flags bss only */ /* * comment section header */ s8put(".comment"); lputl(0); /* pa */ lputl(0); /* va */ lputl(symsize+lcsize); /* comment size */ lputl(HEADR+segtext.filelen+segdata.filelen); /* file offset */ lputl(HEADR+segtext.filelen+segdata.filelen); /* offset of syms */ lputl(HEADR+segtext.filelen+segdata.filelen+symsize);/* offset of line numbers */ lputl(0); /* relocation, line numbers */ lputl(0x200); /* flags comment only */ break; case Hplan9x32: /* plan9 */ magic = 4*11*11+7; lputb(magic); /* magic */ lputb(segtext.filelen); /* sizes */ lputb(segdata.filelen); lputb(segdata.len - segdata.filelen); lputb(symsize); /* nsyms */ lputb(entryvalue()); /* va of entry */ lputb(spsize); /* sp offsets */ lputb(lcsize); /* line offsets */ break; case Hmsdoscom: /* MS-DOS .COM */ break; case Hmsdosexe: /* fake MS-DOS .EXE */ v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; wputl(0x5A4D); /* 'MZ' */ wputl(v % 512); /* bytes in last page */ wputl(rnd(v, 512)/512); /* total number of pages */ wputl(0x0000); /* number of reloc items */ v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); wputl(v/16); /* size of header */ wputl(0x0000); /* minimum allocation */ wputl(0xFFFF); /* maximum allocation */ wputl(0x0000); /* initial ss value */ wputl(0x0100); /* initial sp value */ wputl(0x0000); /* complemented checksum */ v = entryvalue(); wputl(v); /* initial ip value (!) */ wputl(0x0000); /* initial cs value */ wputl(0x0000); wputl(0x0000); wputl(0x003E); /* reloc table offset */ wputl(0x0000); /* overlay number */ break; case Hdarwin: asmbmacho(); break; case Hlinux: case Hfreebsd: case Hnetbsd: case Hopenbsd: case Hdragonfly: case Hhaiku: asmbelf(symo); break; case Hwindows: asmbpe(); break; } cflush(); }
static void addimports(IMAGE_SECTION_HEADER *datsect) { IMAGE_SECTION_HEADER *isect; uvlong n, oftbase, ftbase; vlong startoff, endoff; Imp *m; Dll *d; LSym* dynamic; startoff = cpos(); dynamic = linklookup(ctxt, ".windynamic", 0); // skip import descriptor table (will write it later) n = 0; for(d = dr; d != nil; d = d->next) n++; cseek(startoff + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (n + 1)); // write dll names for(d = dr; d != nil; d = d->next) { d->nameoff = cpos() - startoff; strput(d->name); } // write function names for(d = dr; d != nil; d = d->next) { for(m = d->ms; m != nil; m = m->next) { m->off = nextsectoff + cpos() - startoff; wputl(0); // hint strput(m->s->extname); } } // write OriginalFirstThunks oftbase = cpos() - startoff; n = cpos(); for(d = dr; d != nil; d = d->next) { d->thunkoff = cpos() - n; for(m = d->ms; m != nil; m = m->next) put(m->off); put(0); } // add pe section and pad it at the end n = cpos() - startoff; isect = addpesection(".idata", n, n); isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; chksectoff(isect, startoff); strnput("", isect->SizeOfRawData - n); endoff = cpos(); // write FirstThunks (allocated in .data section) ftbase = dynamic->value - datsect->VirtualAddress - PEBASE; cseek(datsect->PointerToRawData + ftbase); for(d = dr; d != nil; d = d->next) { for(m = d->ms; m != nil; m = m->next) put(m->off); put(0); } // finally write import descriptor table cseek(startoff); for(d = dr; d != nil; d = d->next) { lputl(isect->VirtualAddress + oftbase + d->thunkoff); lputl(0); lputl(0); lputl(isect->VirtualAddress + d->nameoff); lputl(datsect->VirtualAddress + ftbase + d->thunkoff); } lputl(0); //end lputl(0); lputl(0); lputl(0); lputl(0); // update data directory dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE; dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size; cseek(endoff); }
int read_entry(cfile *src_cfh, off_u64 start, tar_entry *entry) { unsigned char block[512]; unsigned int read_bytes; unsigned int name_len, prefix_len; if(start != cseek(src_cfh, start, CSEEK_FSTART)) { return IO_ERROR; } if((read_bytes=cread(src_cfh, block, 512))!=512) { return IO_ERROR; } entry->start = start; entry->end = 512 + start; if(strnlen((const char *)block, 512)==0) { return TAR_EMPTY_ENTRY; } if (! check_str_chksum(block)) { v0printf("checksum failed on a tarfile, bailing\n"); return IO_ERROR; } if('L'==block[TAR_TYPEFLAG_LOC]) { v2printf("handling longlink at %llu eg(%llu)\n", (act_off_u64)start, (act_off_u64)(start * 512)); name_len = octal_str2long(block + TAR_SIZE_LOC, TAR_SIZE_LEN); if((read_bytes=cread(src_cfh, block, 512))!=512) { v0printf("unexpected EOF on tarfile, bailing\n"); return EOF_ERROR; } if((entry->fullname = (unsigned char *)malloc(name_len + 1))==NULL){ v0printf("unable to allocate memory for name_len, bailing\n"); return EOF_ERROR; } memcpy(entry->fullname, block, name_len); if((read_bytes=cread(src_cfh, block, 512))!=512){ v0printf("unable to allocate memory for fullname, bailing\n"); return EOF_ERROR; } if(! check_str_chksum(block)) { v0printf("tar checksum failed for tar entry at %llu, bailing\n", (act_off_u64)start); // IO_ERROR? please. add data_error. return IO_ERROR; } entry->fullname[name_len] = '\0'; entry->end += octal_str2long(block + TAR_SIZE_LOC, TAR_SIZE_LEN) + 1024; } else { name_len = strnlen((char *)block + TAR_NAME_LOC, TAR_NAME_LEN); prefix_len = strnlen((char *)block + TAR_PREFIX_LOC, TAR_PREFIX_LEN); // check if space will be needed for the slash prefix_len += (prefix_len==0 ? 0 : 1); if((entry->fullname = (unsigned char *)malloc(name_len + prefix_len + 1))==NULL){ v0printf("unable to allocate needed memory, bailing\n"); return MEM_ERROR; } if(prefix_len) { memcpy(entry->fullname, block + TAR_PREFIX_LOC, prefix_len -1); entry->fullname[prefix_len] = '/'; memcpy(entry->fullname + prefix_len, block + TAR_NAME_LOC, name_len); entry->fullname[prefix_len + name_len ] = '\0'; } else { memcpy(entry->fullname, block + TAR_NAME_LOC, name_len); entry->fullname[name_len] = '\0'; } entry->end += octal_str2long(block + TAR_SIZE_LOC, TAR_SIZE_LEN); } if(entry->end % 512) entry->end += 512 - (entry->end % 512); return 0; }