int exec(char *path, char **argv) { char *s, *last; char newPath[2*INPUT_BUF]={0}; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) { for( i=0;i<place_to_add_path;i++) { if((ip = namei(newstrcat(newPath,pathVariable[i],path))) != 0){ break; } } if(i>=place_to_add_path) return -1; } ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int main(int argc, char **argv) { char *outname = "aout.rdf"; int moduleloaded = 0; char *respstrings[128] = { 0, }; options.verbose = 0; options.align = 16; options.dynalink = 0; options.strip = 0; error_file = stderr; argc--, argv++; if (argc == 0) usage(); while (argc && *argv && **argv == '-' && argv[0][1] != 'l') { switch (argv[0][1]) { case 'r': printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n"); printf("RDOFF2 revision %s\n", RDOFF2_REVISION); exit(0); case 'v': if (argv[0][2] == '=') { options.verbose = argv[0][3] - '0'; if (options.verbose < 0 || options.verbose > 9) { fprintf(stderr, "ldrdf: verbosity level must be a number" " between 0 and 9\n"); exit(1); } } else options.verbose++; break; case 'a': options.align = atoi(argv[1]); if (options.align <= 0) { fprintf(stderr, "ldrdf: -a expects a positive number argument\n"); exit(1); } argv++, argc--; break; case 's': options.strip = 1; break; case 'd': if (argv[0][2] == 'y') options.dynalink = 1; break; case 'o': outname = argv[1]; argv++, argc--; break; case 'j': if (!objpath) { options.objpath = 1; objpath = argv[1]; argv++, argc--; break; } else { fprintf(stderr, "ldrdf: more than one objects search path specified\n"); exit(1); } case 'L': if (!libpath) { options.libpath = 1; libpath = argv[1]; argv++, argc--; break; } else { fprintf(stderr, "ldrdf: more than one libraries search path specified\n"); exit(1); } case '@':{ int i = 0; char buf[256]; FILE *f; options.respfile = 1; if (argv[1] != NULL) f = fopen(argv[1], "r"); else { fprintf(stderr, "ldrdf: no response file name specified\n"); exit(1); } if (f == NULL) { fprintf(stderr, "ldrdf: unable to open response file\n"); exit(1); } argv++, argc--; while (fgets(buf, sizeof(buf), f) != NULL) { char *p; if (buf[0] == '\n') continue; if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; if (i >= 128) { fprintf(stderr, "ldrdf: too many input files\n"); exit(1); } *(respstrings + i) = newstr(buf); argc++, i++; } break; } case '2': options.stderr_redir = 1; error_file = stdout; break; case 'g': generic_rec_file = argv[1]; argv++, argc--; break; default: usage(); } argv++, argc--; } if (options.verbose > 4) { printf("ldrdf invoked with options:\n"); printf(" section alignment: %d bytes\n", options.align); printf(" output name: `%s'\n", outname); if (options.strip) printf(" strip symbols\n"); if (options.dynalink) printf(" Unix-style dynamic linking\n"); if (options.objpath) printf(" objects search path: %s\n", objpath); if (options.libpath) printf(" libraries search path: %s\n", libpath); printf("\n"); } symtab = symtabNew(); initsegments(); if (!symtab) { fprintf(stderr, "ldrdf: out of memory\n"); exit(1); } while (argc) { if (!*argv) argv = respstrings; if (!*argv) break; if (!strncmp(*argv, "-l", 2)) { if (libpath && (argv[0][2] != '/')) add_library(newstrcat(libpath, *argv + 2)); else add_library(*argv + 2); } else { if (objpath && (argv[0][0] != '/')) loadmodule(newstrcat(objpath, *argv)); else loadmodule(*argv); moduleloaded = 1; } argv++, argc--; } if (!moduleloaded) { printf("ldrdf: nothing to do. ldrdf -h for usage\n"); return 0; } search_libraries(); if (options.verbose > 2) { printf("symbol table:\n"); symtabDump(symtab, stdout); } write_output(outname); if (errorcount > 0) exit(1); return 0; }