void reader(void *v) { int cfd, tfd, forking = 0, pid, newpid; char *ctl, *truss; Msg *s; pid = (int)(uintptr)v; ctl = smprint("/proc/%d/ctl", pid); if ((cfd = open(ctl, OWRITE)) < 0) die(smprint("%s: %r", ctl)); truss = smprint("/proc/%d/syscall", pid); if ((tfd = open(truss, OREAD)) < 0) die(smprint("%s: %r", truss)); cwrite(cfd, ctl, "stop", 4); cwrite(cfd, truss, "startsyscall", 12); s = mallocz(sizeof(Msg) + Bufsize, 1); s->pid = pid; s->buf = (char *)&s[1]; while(pread(tfd, s->buf, Bufsize - 1, 0) > 0){ if (forking && s->buf[1] == '=' && s->buf[3] != '-') { forking = 0; newpid = strtol(&s->buf[3], 0, 0); sendp(forkc, (void*)newpid); procrfork(reader, (void*)newpid, Stacksize, 0); } /* * There are three tests here and they (I hope) guarantee * no false positives. */ if (strstr(s->buf, " Rfork") != nil) { char *a[8]; char *rf; rf = strdup(s->buf); if (tokenize(rf, a, 8) == 5) { ulong flags; flags = strtoul(a[4], 0, 16); if (flags & RFPROC) forking = 1; } free(rf); } sendp(out, s); cwrite(cfd, truss, "startsyscall", 12); s = mallocz(sizeof(Msg) + Bufsize, 1); s->pid = pid; s->buf = (char *)&s[1]; } sendp(quit, nil); threadexitsall(nil); }
void reader(void *v) { char *ctl, *truss; int pid, newpid; int cfd, tfd; Str *s; int forking = 0; pid = (int)v; ctl = smprint("/proc/%d/ctl", pid); if ((cfd = open(ctl, OWRITE)) < 0) die(smprint("%s: %r", ctl)); truss = smprint("/proc/%d/syscall", pid); if ((tfd = open(truss, OREAD)) < 0) die(smprint("%s: %r", truss)); cwrite(cfd, ctl, "stop", 4); cwrite(cfd, truss, "startsyscall", 12); s = mallocz(sizeof(Str) + 8192, 1); s->buf = (char *)&s[1]; /* 8191 is not a typo. It ensures a null-terminated string. The device currently limits to 4096 anyway */ while((s->len = pread(tfd, s->buf, 8191, 0ULL)) > 0){ if (forking && (s->buf[1] == '=') && (s->buf[3] != '-')) { forking = 0; newpid = strtol(&s->buf[3], 0, 0); sendp(forkc, (void*)newpid); procrfork(reader, (void*)newpid, 8192, 0); } /* There are three tests here and they (I hope) guarantee no false positives */ if (strstr(s->buf, " Rfork") != nil) { char *a[8]; char *rf; rf = strdup(s->buf); if (tokenize(rf, a, 8) == 5) { unsigned long flags; flags = strtoul(a[4], 0, 16); if (flags & RFPROC) forking = 1; } free(rf); } sendp(out, s); cwrite(cfd, truss, "startsyscall", 12); s = mallocz(sizeof(Str) + 8192, 1); s->buf = (char *)&s[1]; } sendp(quit, nil); threadexitsall(nil); }
int elfwritebuildinfo(void) { ElfShdr *sh; sh = elfwritenotehdr(".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, buildinfolen, ELF_NOTE_BUILDINFO_TAG); if(sh == nil) return 0; cwrite(ELF_NOTE_BUILDINFO_NAME, ELF_NOTE_BUILDINFO_NAMESZ); cwrite(buildinfo, buildinfolen); cwrite("\0\0\0", rnd(buildinfolen, 4) - buildinfolen); return sh->size; }
int ArduinoCOIL::readRawSensor (seeyou_sensor packet, byte* buffer, int size) { int numread = 0; byte cmd[3]; cmd[0] = packet; cmd[1] = TRAILER; cmd[2] = CARRIAGE_RETURN; if (cwrite (port, cmd, 3) < 0) { Debug::error ("[COIL] Could not request sensor"); return -1; } SleeperThread::msleep(40); // BUG: Why must we sleep? RTFM... numread = cread (port, buffer, size, packet); if (numread < 0) { Debug::error ("[COIL] Could not read sensor"); return -1; } return numread; }
void addpersrc(void) { IMAGE_SECTION_HEADER *h; uchar *p; uint32 val; Reloc *r; if(rsrcsym == nil) return; h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size); h->Characteristics = IMAGE_SCN_MEM_READ| IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; chksectoff(h, cpos()); // relocation for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) { p = rsrcsym->p + r->off; val = h->VirtualAddress + r->add; // 32-bit little-endian p[0] = val; p[1] = val>>8; p[2] = val>>16; p[3] = val>>24; } cwrite(rsrcsym->p, rsrcsym->size); strnput("", h->SizeOfRawData - rsrcsym->size); // update data directory dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress; dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize; }
void* mon_net2tap (void* fd) { uint16_t nread, nwrite; char buffer[BUFSIZE]; unsigned long int net2tap = 0; struct fd *fds = fd; socklen_t sin_size; while (1) { /* data from the network: read it, and write it to the tun/tap interface. * We need to read the length first, and then the packet */ /* Read length */ nread = recvfrom(fds->local_net_fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&fds->local, &sin_size); if(nread == 0) { /* ctrl-c at the other end */ break; } net2tap++; /* read packet */ do_debug("NET2TAP %lu: Read %d bytes from the network\n", net2tap, nread); /* now buffer[] contains a full packet or frame, write it into the tun/tap interface */ nwrite = cwrite(fds->tap_fd, buffer, nread); do_debug("NET2TAP %lu: Written %d bytes to the tap interface\n", net2tap, nwrite); } exit(1); }
int get_ip_from_server(int net_fd, char *devname) { char *buffer; // Get IP Address from server buffer = malloc(100) ; struct ip_header *iphdr = (struct ip_header*)buffer ; memset(buffer,0,100) ; iphdr->vers = 0x45 ; iphdr->ip_header_len = 20 ; iphdr->ttl = 64; if(cwrite(net_fd, buffer, 20) <= 0) { printf("error: write failed while getting IP address from server\n"); exit(1); } cread(net_fd, buffer, 100) ; printf("Got IP response: %08x\n", ntohl(iphdr->dest_ip)) ; set_ip(devname, ntohl(iphdr->dest_ip), 0xffff0000); // Set the interface address. free(buffer) ; return 0; }
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 elfwriteinterp(void) { ElfShdr *sh; sh = elfshname(".interp"); cseek(sh->off); cwrite(interp, sh->size); return sh->size; }
int elfwriteinterp(void) { int n; if(interp == nil) return 0; n = strlen(interp)+1; cseek(ELFRESERVE-n); cwrite(interp, n); return n; }
void revent_handler(int fd, short e, void* args) { char* line = NULL; int len = 0; struct fdev_t* fdev = (struct fdev_t*)args; IOstream* b = &fdev->stream; if (try_read_more(b) == E_ERROR) { if (b->bytes > 0) { cwrite(STDOUT_FILENO, b->cur, b->bytes); } event_del(&fdev->ev); return; } for (; get_line(b, &line, &len) == E_OK; ) { if (cwrite(STDOUT_FILENO, line, len) < 0) { log("STDOUT write error: %s", strerror(errno)); event_del(&fdev->ev); return; } } }
int ArduinoCOIL::setLEDState () { byte cmd[3]; cmd[0] = SENSOR_LED_INDICATOR; cmd[1] = TRAILER; cmd[2] = CARRIAGE_RETURN; if (cwrite (port, cmd, 3) < 0) { Debug::error ("[ArduinoCOIL] Could not set LED status"); return -1; } return 0; }
int write_n(int fd, char *buf, int n) { int nwrite, left = n; while(left > 0) { if ((nwrite = cwrite(fd, buf, left)) == 0){ return 0 ; }else { left -= nwrite; buf += nwrite; } } return n; }
void hang(void) { int me; char *myctl; static char hang[] = "hang"; myctl = smprint("/proc/%d/ctl", getpid()); me = open(myctl, OWRITE); if (me < 0) sysfatal("can't open %s: %r", myctl); cwrite(me, myctl, hang, sizeof hang - 1); close(me); free(myctl); }
int elfwriteopenbsdsig(void) { ElfShdr *sh; // Write Elf_Note header. sh = elfwritenotehdr(".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG); if(sh == nil) return 0; // Followed by OpenBSD string and version. cwrite(ELF_NOTE_OPENBSD_NAME, ELF_NOTE_OPENBSD_NAMESZ); LPUT(ELF_NOTE_OPENBSD_VERSION); return sh->size; }
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; }
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; }
void OpenJournal (void) { DWORD start_seed; #if CREATE_JOURNAL if (create_journal) { if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_WRITE)) { start_seed = SeedRandomNumbers (); cwrite ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); } } else #endif /* CREATE_JOURNAL */ { uio_Stream *fp; if (fp = res_OpenResFile ("starcon.jnl", "rb")) { ReadResFile (journal_buf, 1, sizeof (journal_buf), fp); res_CloseResFile (fp); if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_READ)) { OldArrowInput = ArrowInput; ArrowInput = DemoInput; PlayerInput[0] = PlayerInput[1] = DemoInput; FlushInput (); cread ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); TFB_SeedRandom (start_seed); } } } }
int register_static_ip(int net_fd, int ip, char *devname) { char *buffer; int nread; // Static IP buffer = malloc(100); struct ip_header *iphdr = (struct ip_header*)buffer; memset(buffer,0,100); iphdr->vers = 0x45; iphdr->ip_header_len = 20; iphdr->ttl = 64; iphdr->source_ip = ip; if(cwrite(net_fd, buffer, 20) <= 0) { printf("error: write failed while requesting static IP address from server.\n"); exit(1); } nread = cread(net_fd, buffer, 100) ; if(nread == 0) { // Connection closed while trying to assign a statick IP. This means that someone else already has that address. fprintf(stderr, "ERROR: Requested static IP address already in use.\n"); exit(0); } set_ip(devname, ntohl(iphdr->dest_ip), 0xffff0000); if(add_host_route(devname, (in_addr_t)ntohl(iphdr->dest_ip)) < 0) printf("add_host_route returned\n"); // Set the interface address. free(buffer) ; return 0; }
static void fqd_http_jsend(remote_client *client, const char *status, const char *fmt, ...) { char error[1024] = {0}; char scratch[1024] = {0}; const char *headers = "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n"; va_list argp; va_start(argp, fmt); vsnprintf(error, sizeof(error), fmt, argp); va_end(argp); while(write(client->fd, headers, strlen(headers)) == -1 && errno == EINTR); cwrite(client, "{\n"); cwrite(client, scratch); cwrite(client, " \"status\": \""); cwrite(client, status); cwrite(client, "\",\n"); sprintf(scratch, " \"message\": \"%s\"\n", error); cwrite(client, scratch); cwrite(client, "}\n"); }
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(); }
int main(int argc, char *argv[]) { int tap_fd, option; int flags = IFF_TUN; char if_name[IFNAMSIZ] = ""; int header_len = IP_HDR_LEN; int maxfd; uint16_t nread, nwrite, plength; char buffer[BUFSIZE]; struct sockaddr_in local, remote; char remote_ip[16] = ""; unsigned short int port = PORT; int sock_fd, net_fd, optval = 1; socklen_t remotelen; int cliserv = -1; /* must be specified on cmd line */ unsigned long int tap2net = 0, net2tap = 0; int listen_sd; int sd; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; int err; int yes = 1; struct ip *ip_header; //ip header struct struct VPNDataHdr* vpn_header; int ptc[2]; //pipe from control process to tunnel process progname = argv[0]; /* Check command line options */ while((option = getopt(argc, argv, "i:sc:p:uahd")) > 0){ switch(option) { case 'd': debug = 1; break; case 'h': usage(); break; case 'i': strncpy(if_name,optarg,IFNAMSIZ-1); break; case 's': cliserv = SERVER; break; case 'c': cliserv = CLIENT; strncpy(remote_ip,optarg,15); break; case 'p': port = atoi(optarg); break; case 'u': flags = IFF_TUN; break; case 'a': flags = IFF_TAP; header_len = ETH_HDR_LEN; break; default: my_err("Unknown option %c\n", option); usage(); } } argv += optind; argc -= optind; if(argc > 0){ my_err("Too many options!\n"); usage(); } if(*if_name == '\0'){ my_err("Must specify interface name!\n"); usage(); }else if(cliserv < 0){ my_err("Must specify client or server mode!\n"); usage(); }else if((cliserv == CLIENT)&&(*remote_ip == '\0')){ my_err("Must specify server address!\n"); usage(); } /* initialize tun/tap interface */ if ( (tap_fd = tun_alloc(if_name, flags | IFF_NO_PI)) < 0 ) { my_err("Error connecting to tun/tap interface %s!\n", if_name); exit(1); } do_debug("Successfully connected to interface %s\n", if_name); if ( (sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket()"); exit(1); } ///////////////////////////////////////////////////////// memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_port = htons(port); if (bind(sock_fd, (struct sockaddr*) &local, sizeof(local)) < 0){ perror("bind()"); exit(1); } //init remote memset(&remote, 0, sizeof(remote)); remote.sin_family = AF_INET; //remote.sin_addr.s_addr = inet_addr(remote_ip); remote.sin_port = htons(port); net_fd = sock_fd; do_debug("SERVER: UDP built\n"); ////////////////////////////////////////////////////////////////////// ///////////ssl tcp control connection//////////////// loadcert(); listen_sd = socket (AF_INET, SOCK_STREAM, 0); if(err < 0){ printf("err tcp listening sock!\n"); return 0; } if(setsockopt(listen_sd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1){ perror("Server-socket() error lol!"); exit(1); } memset (&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (TCP_LISTEN_PORT); /* Server Port number */ err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); if(err < 0){ printf("err tcp bind!\n"); return 0; } /* Receive a TCP connection. */ err = listen (listen_sd, 5); do_debug("Server start Listen OK\n"); if(err < 0){ printf("err tcp listening!\n"); return 0; } ///// //////////////////////////////////////////////////// /* use select() to handle two descriptors at once */ maxfd = (tap_fd > net_fd)?tap_fd:net_fd; maxfd = (maxfd > listen_sd)?maxfd:listen_sd; while(1) { int ret; fd_set rd_set; struct Session *cursess; cursess= slisthead; FD_ZERO(&rd_set); FD_SET(tap_fd, &rd_set); FD_SET(net_fd, &rd_set); FD_SET(0, &rd_set); FD_SET(listen_sd,&rd_set); while(cursess != 0){ FD_SET(cursess->sd,&rd_set); maxfd = (maxfd > cursess->sd)?maxfd:cursess->sd; cursess = cursess->next; } cursess = slisthead; ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL); if (ret < 0 && errno == EINTR){ continue; } if (ret < 0) { perror("select()"); exit(1); } if(FD_ISSET(0, &rd_set)){ memset(buffer,0,BUFSIZE); nread = read(0, buffer, BUFSIZE); if(0 == strncmp(buffer,"quit",strlen("quit"))) break; } if(FD_ISSET(listen_sd, &rd_set)){ client_len = sizeof(sa_cli); sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); if(err < 0){ printf("err accept!\n"); return 0; } err = sslinit(sd, &slisthead, &sa_cli, "vpnauth"); if(err) do_debug("Client from %s is connected\n", inet_ntoa(sa_cli.sin_addr)); //continue; } if(FD_ISSET(tap_fd, &rd_set)){ /* data from tun/tap: just read it and write it to the network */ unsigned char outbuffer[VPN_BUFSIZE]; struct VPNDataHdr *pvpnh = (struct VPNDataHdr*) outbuffer; unsigned long curip; cursess = 0; nread = cread(tap_fd, buffer, BUFSIZE); if(nread <= 0) continue; tap2net++; do_debug("TAP2NET %lu: Read %d bytes from the tap interface\n", tap2net, nread); ip_header = (struct ip*) buffer; memcpy(&curip,&(ip_header->ip_dst),sizeof(long)); cursess = findsessByDstIP(slisthead,curip); //memcpy(&tpaddr,&(destsess->ip),sizeof(unsigned long)); if(cursess == 0) continue; remote.sin_addr.s_addr = cursess->ip; /* write length + packet */ if(32 != getHMACSHA256(buffer, pvpnh->hmac, nread,cursess->s_key,KEY_LENGTH)) continue; nwrite = crypt(buffer,nread,outbuffer + sizeof(struct VPNDataHdr),cursess->s_key,cursess->iv,1); if(0 == nwrite) continue; pvpnh->plen = htons(nwrite); sendto(net_fd,outbuffer, nwrite + sizeof(struct VPNDataHdr),0,(struct sockaddr*) &remote, sizeof(remote)); do_debug("TAP2NET %lu: Written %d bytes to the network %s\n", tap2net,nwrite,inet_ntoa(remote.sin_addr)); //continue; } if(FD_ISSET(net_fd, &rd_set)){ /* data from the network: read it, and write it to the tun/tap interface. * We need to read the length first, and then the packet */ unsigned char inbuffer[VPN_BUFSIZE]; unsigned char hmac[32]; int nwrite; struct VPNDataHdr *pvpnh = (struct VPNDataHdr*) inbuffer; struct sockaddr_in sa; socklen_t fromlen; fromlen =sizeof(sa); nread = recvfrom(net_fd,inbuffer,VPN_BUFSIZE,0,(struct sockaddr*)&sa,&fromlen); if(nread <= 0) { continue; } cursess = findsessByVPNHeader(slisthead,pvpnh,sa.sin_addr.s_addr); if(cursess == 0) continue; nwrite = crypt(inbuffer + sizeof(struct VPNDataHdr),htons(pvpnh->plen),buffer,cursess->s_key,cursess->iv,0); if(0 == nwrite) continue; if(32 != getHMACSHA256(buffer, hmac, nwrite,cursess->s_key,KEY_LENGTH) || !isequal(hmac,pvpnh->hmac,HMAC_LENGTH)) continue; net2tap++; /* read packet */ do_debug("NET2TAP %lu: Read %d bytes from the network\n", net2tap, nread); /* now buffer[] contains a full packet or frame, write it into the tun/tap interface */ nwrite = cwrite(tap_fd, buffer, nwrite); do_debug("NET2TAP %lu: Written %d bytes to the tap interface\n", net2tap, nwrite); //continue; } cursess = slisthead; while(cursess != 0){ if(FD_ISSET(cursess->sd, &rd_set)){ struct CliRequest* rst; memset(buffer,0,BUFSIZE); nread = ssl_read(cursess->ssl,buffer,BUFSIZE); rst = (struct CliRequest*)buffer; if(nread != sizeof(struct CliRequest)){ break; } if(nread == 0 || rst->act == QUIT_REQUEST){ struct in_addr temp; temp.s_addr = cursess->ip; do_debug("Client from %s break the connection\n", inet_ntoa(temp)); cleanupSSL(cursess); deletesess(&slisthead,cursess); //slisthead = 0; } if(rst->act == IV_REFRESH_REQUEST){ RefreshIV(cursess); do_debug("IV is refreshed:"); debugSession(cursess); } if(rst->act == IV_REFRESH_SET){ struct ServResponse rsp; rsp.act = ACT_ACK; if(-1 != ssl_write(cursess->ssl,(char*)&rsp, sizeof(struct ServResponse))){ memcpy(cursess->iv, rst->iv,KEY_LENGTH); do_debug("IV is updated:"); debugSession(cursess); } } if(rst->act == KEY_REFRESH_REQUEST){ RefreshKEY(cursess); do_debug("Key is refreshed:"); debugSession(cursess); } if(rst->act == KEY_REFRESH_SET){ struct ServResponse rsp; rsp.act = ACT_ACK; if(-1 != ssl_write(cursess->ssl,(char*)&rsp, sizeof(struct ServResponse))){ memcpy(cursess->s_key, rst->s_key,KEY_LENGTH); do_debug("Key is updated:"); debugSession(cursess); } } } cursess = cursess->next; } } if(slisthead != 0){ struct Session* tsess = slisthead; while(tsess != 0){ cleanupSSL(tsess); tsess = tsess->next; } } freesess(slisthead); close(listen_sd); close(net_fd); close(tap_fd); cleanupCTX(); return(0); }
int main(int argc, char *argv[]) { int tap_fd, option; int flags = IFF_TUN; char if_name[IFNAMSIZ] = ""; int header_len = IP_HDR_LEN; int maxfd; uint16_t nread, nwrite, plength; // uint16_t total_len, ethertype; char buffer[BUFSIZE]; struct sockaddr_in local, remote; char remote_ip[16] = ""; unsigned short int port = PORT; int sock_fd, net_fd, optval = 1; socklen_t remotelen; int cliserv = -1; /* must be specified on cmd line */ unsigned long int tap2net = 0, net2tap = 0; progname = argv[0]; /* Check command line options */ while((option = getopt(argc, argv, "i:sc:p:uahd")) > 0){ switch(option) { case 'd': debug = 1; break; case 'h': usage(); break; case 'i': strncpy(if_name,optarg,IFNAMSIZ-1); break; case 's': cliserv = SERVER; break; case 'c': cliserv = CLIENT; strncpy(remote_ip,optarg,15); break; case 'p': port = atoi(optarg); break; case 'u': flags = IFF_TUN; break; case 'a': flags = IFF_TAP; header_len = ETH_HDR_LEN; break; default: my_err("Unknown option %c\n", option); usage(); } } argv += optind; argc -= optind; if (argc == 2) { strncpy(if_name,argv[0],IFNAMSIZ-1); port = atoi(argv[1]); cliserv = SERVER; flags = IFF_TAP; header_len = ETH_HDR_LEN; } else if(argc > 0){ my_err("Too many options!\n"); usage(); } if(*if_name == '\0'){ my_err("Must specify interface name!\n"); usage(); }else if(cliserv < 0){ my_err("Must specify client or server mode!\n"); usage(); }else if((cliserv == CLIENT)&&(*remote_ip == '\0')){ my_err("Must specify server address!\n"); usage(); } /* initialize tun/tap interface */ if ( (tap_fd = tun_alloc(if_name, flags | IFF_NO_PI)) < 0 ) { my_err("Error connecting to tun/tap interface %s!\n", if_name); exit(1); } do_debug("Successfully connected to interface %s\n", if_name); if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket()"); exit(1); } if(cliserv==CLIENT){ /* Client, try to connect to server */ /* assign the destination address */ memset(&remote, 0, sizeof(remote)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = inet_addr(remote_ip); remote.sin_port = htons(port); /* connection request */ if (connect(sock_fd, (struct sockaddr*) &remote, sizeof(remote)) < 0){ perror("connect()"); exit(1); } net_fd = sock_fd; do_debug("CLIENT: Connected to server %s\n", inet_ntoa(remote.sin_addr)); } else { /* Server, wait for connections */ /* avoid EADDRINUSE error on bind() */ if(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) < 0){ perror("setsockopt()"); exit(1); } memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_port = htons(port); if (bind(sock_fd, (struct sockaddr*) &local, sizeof(local)) < 0){ perror("bind()"); exit(1); } if (listen(sock_fd, 5) < 0){ perror("listen()"); exit(1); } /* wait for connection request */ remotelen = sizeof(remote); memset(&remote, 0, remotelen); if ((net_fd = accept(sock_fd, (struct sockaddr*)&remote, &remotelen)) < 0){ perror("accept()"); exit(1); } do_debug("SERVER: Client connected from %s\n", inet_ntoa(remote.sin_addr)); } /* use select() to handle two descriptors at once */ maxfd = (tap_fd > net_fd)?tap_fd:net_fd; while(1) { int ret; fd_set rd_set; FD_ZERO(&rd_set); FD_SET(tap_fd, &rd_set); FD_SET(net_fd, &rd_set); ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL); if (ret < 0 && errno == EINTR){ continue; } if (ret < 0) { perror("select()"); exit(1); } if(FD_ISSET(tap_fd, &rd_set)){ /* data from tun/tap: just read it and write it to the network */ nread = cread(tap_fd, buffer, BUFSIZE); tap2net++; do_debug("TAP2NET %lu: Read %d bytes from the tap interface\n", tap2net, nread); /* write length + packet */ plength = htons(nread); nwrite = cwrite(net_fd, (char *)&plength, sizeof(plength)); nwrite = cwrite(net_fd, buffer, nread); do_debug("TAP2NET %lu: Written %d bytes to the network\n", tap2net, nwrite); } if(FD_ISSET(net_fd, &rd_set)){ /* data from the network: read it, and write it to the tun/tap interface. * We need to read the length first, and then the packet */ /* Read length */ nread = read_n(net_fd, (char *)&plength, sizeof(plength)); if(nread == 0) { /* ctrl-c at the other end */ break; } net2tap++; /* read packet */ nread = read_n(net_fd, buffer, ntohs(plength)); do_debug("NET2TAP %lu: Read %d bytes from the network\n", net2tap, nread); /* now buffer[] contains a full packet or frame, write it into the tun/tap interface */ nwrite = cwrite(tap_fd, buffer, nread); do_debug("NET2TAP %lu: Written %d bytes to the tap interface\n", net2tap, nwrite); } } return(0); }
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 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 event_handler(int fd, short e, void* args) { char* line = NULL; int len = 0; int size = 0; int st = wet->st; IOstream* stream = &(wet->stream); WEVENT_T* ev = (WEVENT_T*)args; if (!isempty_buffer(&ev->buffer)) { size = cwrite(fd, ev->buffer.cur, ev->buffer.size); if (size < 0) { log("write error, %s\n", strerror(errno)); update_stat(STAT_CLOSE_PIPE); } else { seek_buffer(&ev->buffer, size); return; } } switch (st) { case STAT_READ_MORE: if (try_read_more(stream) == E_ERROR) { update_stat(STAT_LAST_BUF); } else { update_stat(STAT_WRITE_LINE); } break; case STAT_WRITE_LINE: if (get_line(stream, &line, &len) == E_NEED_MORE || len == 0) { update_stat(STAT_READ_MORE); break; } size = cwrite(fd, line, len); if (size < 0) { log("write error, %s\n", strerror(errno)); update_stat(STAT_CLOSE_PIPE); break; } if (size < len) { expand_buffer(&ev->buffer, line + size, len - size); break; } break; case STAT_LAST_BUF: if (stream->bytes <= 0) { update_stat(STAT_CLOSE_PIPE); break; } size = cwrite(fd, stream->cur, stream->bytes); if (size < 0) { log("write error, %s\n", strerror(errno)); update_stat(STAT_CLOSE_PIPE); break; } if (size == stream->bytes) { stream->bytes = 0; update_stat(STAT_CLOSE_PIPE); break; } if (size < stream->bytes) { expand_buffer(&ev->buffer, stream->cur+size, stream->bytes-size); stream->bytes = 0; break; } break; case STAT_CLOSE_PIPE: close(fd); event_del(&ev->e); break; } }
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 reader(void *v) { int cfd, tfd, exiting, pid; uintptr_t newpid; char *ctl, *truss; Str *s; static char waitstop[] = "waitstop"; pid = (int)(uintptr)v; if (debug) fprint(outf, "DEBUG: -------------> reader starts with pid %d\n", pid); ctl = smprint("/proc/%d/ctl", pid); if ((cfd = open(ctl, OWRITE)) < 0) die(smprint("%s: %r", ctl)); truss = smprint("/proc/%d/syscall", pid); if ((tfd = open(truss, OREAD)) < 0) die(smprint("%s: %r", truss)); if (debug) fprint(outf, "DEBUG: Send %s to pid %d ...", waitstop, pid); /* child was stopped by hang msg earlier */ cwrite(cfd, ctl, waitstop, sizeof waitstop - 1); if (debug) fprint(outf, "DEBUG: back for %d\n", pid); if (debug) fprint(outf, "DEBUG: Send %s to pid %d\n", "startsyscall", pid); cwrite(cfd, ctl, "startsyscall", 12); if (debug) fprint(outf, "DEBUG: back for %d\n", pid); s = newstr(); exiting = 0; while((s->len = pread(tfd, s->buf, Bufsize - 1, 0)) >= 0){ if (s->buf[0] == 'F') { char *val = strstr(s->buf, "= "); if (val) { newpid = strtol(&val[2], 0, 0); sendp(forkc, (void*)newpid); procrfork(reader, (void*)newpid, Stacksize, 0); } } if (strstr(s->buf, " Exits") != nil) exiting = 1; sendp(out, s); /* print line from /proc/$child/syscall */ if (exiting) { s = newstr(); strcpy(s->buf, "\n"); sendp(out, s); break; } /* flush syscall trace buffer */ if (debug) fprint(outf, "DEBUG: Send %s to pid %d\n", "startsyscall", pid); cwrite(cfd, ctl, "startsyscall", 12); if (debug) fprint(outf, "DEBUG: back for %d\n", pid); s = newstr(); } sendp(quit, nil); threadexitsall(nil); }
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(); }