/* fix the program header that represetns the text segment. * make it large enough to contain the extra bits we are going * to put in - fix both the memory and file size */ int adj_phdr(Elf32_Ehdr *eh32) { Elf32_Phdr *phdr; int phdr_num; int i; int new_text_size; int text_mem_size; phdr = (Elf32_Phdr *)(kern_file+eh32->e_phoff); phdr_num = eh32->e_phnum; if (debug_level == 2) { printf("Dumping phdr information\n"); } /* look for text segment and data segment info */ for (i=0; i<phdr_num; i++,phdr++) { if (debug_level == 2) { dump_phdr(phdr); } if (phdr->p_vaddr == TEXT_VADDR) { text_file_size = phdr->p_filesz; text_mem_size = phdr->p_memsz; text_file_offset = phdr->p_offset; } if (phdr->p_vaddr == DATA_VADDR) { old_data_file_offset = phdr->p_offset; } } if (old_data_file_offset < text_file_offset) { fprintf(stderr, "error data segment before text segment\n"); exit(-1); } /* now go through and adjust text sizes and data offset */ phdr = (Elf32_Phdr *)(kern_file+eh32->e_phoff); for (i=0; i<phdr_num; i++,phdr++) { if (phdr->p_vaddr == TEXT_VADDR) { new_text_size = PAGE_ROUND_UP((BITS_VADDR - TEXT_VADDR) + bits_info.st_size); phdr->p_filesz = new_text_size; phdr->p_memsz = new_text_size; } if (phdr->p_vaddr == DATA_VADDR) { data_file_offset = text_file_offset + new_text_size; amount_push_back = data_file_offset - old_data_file_offset; phdr->p_offset = data_file_offset; } } if (debug_level == 2) { printf("\n\n"); } return 0; }
/* Main program. */ int main(int argc, char **argv) { struct nucs_exec ahdr; // minix aout header struct nucs_exec_elf32 input_exec_elf32; struct stat st_input; elf32_ehdr_t ehdr; elf32_phdr_t* phdrs = 0; elf32_shdr_t* shdrs = 0; int fd_in; int fd_out; int fd_aout; char* input = 0; char* output = 0; char* faout = 0; char strnum[MAX_DIGITS]; char* strflags[MAX_TOKENS]; unsigned int flags = A_EXEC; unsigned char cpu = A_I80386; int stackheap = -1; int hdrlen = HDRLEN; int opt; int i=0; int n=0; memset(strflags, 0, sizeof(strflags)); memset(strnum, 0, sizeof(strnum)); while ((opt = getopt(argc, argv,"c:d:f:hi:l:o:s:")) != -1) { switch (opt) { case 'c': /* cpu type */ if(!strncmp(optarg,"i386",4)) cpu = A_I80386; if(!strncmp(optarg,"i8086",5)) cpu = A_I8086; break; case 'd': /* dump aout header */ faout = optarg; break; case 'f': /* flags */ memset(strflags,0,MAX_TOKENS); flags = 0x00; /* get the first token */ strflags[0] = strtok(optarg," ,"); /* parse the rest of string */ while ((++i <= MAX_TOKENS) && ((strflags[i] = strtok (0," ,")) != 0)); n=i; unsigned int flag = 0x00; for(i=0; i<n; i++) { if(strlen(strflags[i]) > 2 && strflags[i][0] == '0' && strflags[i][1] == 'x') sscanf(strflags[i],"%x",&flag); else flag = atoi(strflags[i]); flags |= flag; } break; case 'h': usage(); exit(0); case 'i': /* input */ input = optarg; break; case 'l': /* header length (default 0x20) */ memset(strnum,0,MAX_DIGITS); if(strlen(optarg) > 2 && optarg[0] == '0' && optarg[1] == 'x') sscanf(optarg,"%x",&hdrlen); else hdrlen = atoi(optarg); break; case 'o': /* output */ output = optarg; break; case 's': /* stack + heap size */ { char * mulstr; stackheap = strtoul(optarg, &mulstr, 0); if (mulstr[0] != 0) { switch (mulstr[0]) { case 'k': stackheap <<= 10; break; case 'M': stackheap <<= 20; break; default: goto wrong_size; } if (mulstr[1] != 0) { switch(mulstr[1]) { case 'w': stackheap *= 4; /* assuming 32bits */ break; case 'b': break; default: goto wrong_size; } } } break; wrong_size: fprintf(stderr, "Unrecognized size modifier\n"); usage(); exit(1); } break; default: /* '?' */ usage(); exit(1); } } if(faout) { if((fd_aout = open(faout, O_RDONLY))<0) { perror("open"); exit(1); } if ((n = read(fd_aout, &ahdr, sizeof(ahdr))) < 0) { perror("read"); } close(fd_aout); if (n != sizeof(ahdr)) { fprintf(stderr,"Wrong header size (want %d got %d\n",sizeof(ahdr),n); } dump_aout(&ahdr); return 0; } if(!input || !output || stackheap<0) { usage(); exit(1); } if (stat(input, &st_input) != 0) { perror("stat"); exit(1); } if((fd_in = open(input, O_RDONLY))<0) { report(input,"Couldn't open input file"); exit(1); } if((fd_out = open(output, O_CREAT|O_RDWR|O_TRUNC, S_IFREG|S_IRUSR|S_IWUSR|S_IWUSR))<0) { report(output,"Couldn't open output file"); exit(1); } read_elf32_ehdr(input, &ehdr); #if DO_TRACE == 1 printf("---[ELF header]---\n"); dump_ehdr(&ehdr); #endif phdrs = read_elf32_phdrs(input, &ehdr, phdrs); #if DO_TRACE == 1 for(i=0; i<ehdr.e_phnum; i++) { printf("---[%d. program header]---\n",i); dump_phdr(&phdrs[i]); } #endif shdrs = read_elf32_shdrs(input, &ehdr, shdrs); #if DO_TRACE == 1 for(i=0; i<ehdr.e_shnum; i++) { printf("---[%d. section header]---\n",i); dump_shdr(&shdrs[i]); } #endif create_exec_elf32(&ehdr, phdrs, shdrs, &input_exec_elf32); #if DO_TRACE == 1 dump_exec_elf32(&input_exec_elf32); #endif /* Build a.out header and write to output */ memset(&ahdr, 0, sizeof(ahdr)); ahdr.a_magic[0] = A_MAGIC0; ahdr.a_magic[1] = A_MAGIC1; ahdr.a_flags = flags; ahdr.a_cpu = cpu; ahdr.a_hdrlen = hdrlen; ahdr.a_text = input_exec_elf32.text_size; ahdr.a_data = input_exec_elf32.data_size; ahdr.a_bss = input_exec_elf32.bss_size; ahdr.a_total = ahdr.a_text + ahdr.a_data + ahdr.a_bss + stackheap; ahdr.a_entry = input_exec_elf32.initial_ip; if (flags & A_NSYM) { ahdr.a_syms = input_exec_elf32.symtab_size; } else { ahdr.a_syms = 0; } write(fd_out, &ahdr, hdrlen); close(fd_in); close(fd_out); return 0; }