URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 700 to Rev 701
- ↔ Reverse comparison
Rev 700 → Rev 701
/trunk/uclinux/uClinux-2.0.x/fs/binfmt_elf.c
115,6 → 115,17
return p; |
} |
|
static unsigned long stringarraylen(int count, char ** array) |
{ |
int l = 4; |
while(count) { |
l += strlen(array[--count]); |
l++; |
l+=4; |
} |
return l; |
} |
|
int do_relocate(int dst_indx, |
int rel_nb, |
struct elf32_rel *rel_ptr, |
212,15 → 223,15
{ |
struct elfhdr elf_ex; |
struct file *file; |
unsigned char ibcs2_interpreter; |
int i,j; |
int old_fs; |
struct elf32_shdr *elf_spnt, *elf_shdata; |
int elf_exec_fileno; |
unsigned long elf_entry = 0; |
int status; |
unsigned long start_code, end_code, start_data, end_data, start_brk, brk; |
unsigned long elf_stack; |
unsigned long code_start, code_end, code_len = 0; |
unsigned long data_start, data_end, data_len = 0; |
unsigned long bss_start, bss_end, bss_len = 0; |
unsigned long stack_len = 0; |
int rel_indx, symtab_indx = 0, strtab_indx = 0; |
struct elf32_rel *rel_ptr; |
struct elf32_sym *sym_ptr = (struct elf32_sym *)0; |
229,23 → 240,34
|
or32_consth_add = 0; |
or32_consth_rel = 0; |
ibcs2_interpreter = 0; |
status = 0; |
|
current->personality = PER_LINUX; |
|
elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); |
|
if (elf_exec_fileno < 0) |
return elf_exec_fileno; |
|
file = current->files->fd[elf_exec_fileno]; |
|
|
elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ |
|
if (elf_ex.e_ident[0] != 0x7f || |
strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0) { |
return -ENOEXEC; |
} |
|
/* First of all, some simple consistency checks */ |
if (elf_ex.e_type != ET_REL || |
(!elf_check_arch(elf_ex.e_machine)) || |
(!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || |
!bprm->inode->i_op->default_file_ops->mmap)) { |
0 /*!elf_check_arch(elf_ex.e_machine)*/ || |
!bprm->inode->i_op || |
!bprm->inode->i_op->default_file_ops || |
!bprm->inode->i_op->default_file_ops->mmap || |
elf_ex.e_ident[0] != 0x7f || |
strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0) { |
return -ENOEXEC; |
} |
|
if (flush_old_exec(bprm)) { |
return -ENOMEM; |
} |
|
if(elf_ex.e_shnum > ELF_SECTION_NB) |
return -ETOOMANYSECT; |
|
253,39 → 275,20
sec[i].len = 0; |
|
/* Now read in all of the header information */ |
elf_shdata = (struct elf32_shdr *) kmalloc(elf_ex.e_shnum * |
elf_ex.e_shentsize, GFP_KERNEL); |
|
elf_shdata = (struct elf32_shdr *) kmalloc(elf_ex.e_shnum * |
elf_ex.e_shentsize, GFP_KERNEL); |
if (elf_shdata == NULL) { |
if (elf_shdata == NULL) |
return -ENOMEM; |
} |
|
retval = read_exec(bprm->inode, elf_ex.e_shoff, (char *) elf_shdata, |
elf_ex.e_shentsize * elf_ex.e_shnum, 1); |
|
if (retval < 0) { |
kfree(elf_shdata); |
return retval; |
} |
|
elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); |
|
if (elf_exec_fileno < 0) { |
kfree(elf_shdata); |
return elf_exec_fileno; |
} |
file = current->files->fd[elf_exec_fileno]; |
|
elf_stack = ~0UL; |
start_code = ~0UL; |
end_code = 0; |
start_data = ~0UL; |
end_data = 0; |
start_brk = ~0UL; |
brk = 0; |
|
if (flush_old_exec(bprm)) { |
return -ENOMEM; |
} |
|
/* OK, This is the point of no return */ |
|
current->mm->end_data = 0; |
298,72 → 301,96
old_fs = get_fs(); |
set_fs(get_ds()); |
|
/* Calculate the total size of memory needed */ |
for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; i++, elf_spnt++) { |
if((elf_spnt->sh_flags & SHF_ALLOC)) { |
int elf_prot = PROT_READ; |
unsigned long retval; |
if (elf_spnt->sh_flags & SHF_WRITE) |
elf_prot |= PROT_WRITE; |
if (elf_spnt->sh_flags & SHF_EXECINSTR) |
elf_prot |= PROT_EXEC; |
if(elf_spnt->sh_type == SHT_PROGBITS) { |
if(elf_spnt->sh_flags & SHF_EXECINSTR) |
code_len += (elf_spnt->sh_size + 3) & ~(3); |
else if(elf_spnt->sh_flags & SHF_ALLOC) |
data_len += (elf_spnt->sh_size + 3) & ~(3); |
} |
else if(elf_spnt->sh_type == SHT_NOBITS) { |
if(elf_spnt->sh_flags & SHF_ALLOC) |
bss_len += (elf_spnt->sh_size + 3) & ~(3); |
} |
} |
|
if(elf_spnt->sh_size == 0) |
continue; |
/* Allocate space */ |
retval = (unsigned long)do_mmap(NULL, |
0, |
code_len + code_len + bss_len + stack_len, |
PROT_EXEC | PROT_WRITE | PROT_READ, |
0, |
0); |
|
retval = (unsigned long)do_mmap(NULL, |
0, |
elf_spnt->sh_size, |
elf_prot, |
0, |
0); |
if(retval > (unsigned long)-4096) { |
kfree(elf_shdata); |
return retval; |
} |
|
if(retval > (unsigned long)-4096) { |
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
code_start = retval; |
code_end = code_start; |
data_start = code_start + code_len; |
data_end = data_start; |
bss_start = data_start + data_len; |
bss_end = bss_start; |
stack_len = STACK_SIZE; |
|
/* Make room on stack for arguments & environment */ |
stack_len += strlen(bprm->filename) + 1; |
stack_len += stringarraylen(bprm->envc, bprm->envp); |
stack_len += stringarraylen(bprm->argc, bprm->argv); |
|
current->mm->executable = 0; |
|
/* Now copy sections in memory */ |
|
for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; i++, elf_spnt++) { |
|
if(elf_spnt->sh_type == SHT_PROGBITS && elf_spnt->sh_flags & SHF_EXECINSTR) { |
|
retval = read_exec(bprm->inode, elf_spnt->sh_offset, |
(char *)code_end, elf_spnt->sh_size, 1); |
|
if (retval < 0) { |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
return retval; |
} |
|
sec[i].pm_add = code_end; |
sec[i].vm_add = elf_spnt->sh_addr; |
|
sec[i].pm_add = retval; |
code_end = code_end + ((elf_spnt->sh_size + 3) & ~(3)); |
} |
else if (elf_spnt->sh_type == SHT_PROGBITS && elf_spnt->sh_flags & SHF_ALLOC) { |
|
retval = read_exec(bprm->inode, elf_spnt->sh_offset, |
(char *)data_end, elf_spnt->sh_size, 1); |
|
if (retval < 0) { |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
|
sec[i].pm_add = data_end; |
sec[i].vm_add = elf_spnt->sh_addr; |
sec[i].len = elf_spnt->sh_size; |
|
if(elf_spnt->sh_type == SHT_PROGBITS) { |
retval = read_exec(bprm->inode, elf_spnt->sh_offset, |
(char *)retval, elf_spnt->sh_size, 1); |
if (retval < 0) { |
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
kfree(elf_shdata); |
return retval; |
} |
} |
|
if(elf_spnt->sh_type == SHT_PROGBITS) { |
if(elf_spnt->sh_flags & SHF_EXECINSTR) { |
if(sec[i].pm_add < start_code) |
start_code = sec[i].pm_add; |
if((sec[i].pm_add + elf_spnt->sh_size) > end_code) |
end_code = sec[i].pm_add + elf_spnt->sh_size; |
} |
else { |
if(sec[i].pm_add < start_data) |
start_data = sec[i].pm_add; |
if((sec[i].pm_add + elf_spnt->sh_size) > end_data) |
end_data = sec[i].pm_add + elf_spnt->sh_size; |
} |
} |
else if(elf_spnt->sh_type == SHT_NOBITS) { |
if(sec[i].pm_add < start_brk) |
start_brk = sec[i].pm_add; |
if((sec[i].pm_add + elf_spnt->sh_size) > brk) |
brk = sec[i].pm_add + elf_spnt->sh_size; |
} |
data_end = data_end + ((elf_spnt->sh_size + 3) & ~(3)); |
} |
else if (elf_spnt->sh_type == SHT_NOBITS && elf_spnt->sh_flags & SHF_ALLOC) { |
|
sec[i].pm_add = bss_end; |
sec[i].vm_add = elf_spnt->sh_addr; |
|
bss_end = bss_end + ((elf_spnt->sh_size + 3) & ~(3)); |
} |
} |
|
/* Set bss and stack to zero */ |
memset((void*)(bss_start), 0, bss_len + stack_len); |
|
for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; elf_spnt++, i++) { |
if(elf_spnt->sh_type == SHT_SYMTAB && (elf_spnt->sh_size != 0)) { |
struct elf32_shdr *link_shdr; |
381,6 → 408,7
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
396,6 → 424,7
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
414,8 → 443,9
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
kfree(elf_shdata); |
return retval; |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
|
sec[strtab_indx].pm_add = retval; |
428,6 → 458,7
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
456,8 → 487,9
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
kfree(elf_shdata); |
return retval; |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
|
sec[i].pm_add = retval; |
470,12 → 502,12
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
|
rel_indx = i; |
symtab_indx = elf_spnt->sh_link; |
link_shdr = elf_shdata + symtab_indx; |
|
/* Now do relocations for the n-th section. n is read from |
488,6 → 520,7
for(j = 0; j < elf_ex.e_shnum; j++) |
if(sec[j].len) |
do_munmap(sec[j].pm_add, sec[j].len); |
do_munmap(code_start, code_len + code_len + bss_len + stack_len); |
kfree(elf_shdata); |
return retval; |
} |
507,10 → 540,6
set_fs(old_fs); |
kfree(elf_shdata); |
|
sys_close(elf_exec_fileno); |
|
current->personality = PER_LINUX; |
|
if (current->exec_domain && current->exec_domain->use_count) |
(*current->exec_domain->use_count)--; |
if (current->binfmt && current->binfmt->use_count) |
522,7 → 551,7
if (current->binfmt && current->binfmt->use_count) |
(*current->binfmt->use_count)++; |
|
bprm->p = do_mmap(0, 0, STACK_SIZE, PROT_READ|PROT_WRITE, 0, 0) + STACK_SIZE; |
bprm->p = bss_end + stack_len - 4; |
|
bprm->p = putstringarray(bprm->p, 1, &bprm->filename); |
|
535,23 → 564,26
current->flags &= ~PF_FORKNOEXEC; |
bprm->p = (unsigned long)create_elf_tables((char *) bprm->p, bprm->argc, bprm->envc, regs); |
|
current->mm->start_brk = start_brk; |
current->mm->brk = brk; |
current->mm->start_code = start_code; |
current->mm->end_code = end_code; |
current->mm->start_data = start_data; |
current->mm->end_data = end_data; |
current->mm->brk = bss_end; |
current->mm->start_code = code_start; |
current->mm->end_code = code_end; |
current->mm->start_data = data_start; |
current->mm->end_data = data_end; |
current->mm->start_stack = bprm->p; |
|
if(start_brk != ~0UL) { |
int nbyte = brk - start_brk; |
char *fpnt = (char *)brk; |
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__); |
_print(" start_code = %x\n", current->mm->start_code); |
_print(" end_code = %x\n", current->mm->end_code); |
_print(" start_data = %x\n", current->mm->start_data); |
_print(" end_data = %x\n", current->mm->end_data); |
_print(" start_brk = %x\n", current->mm->start_brk); |
_print(" brk = %x\n", current->mm->brk); |
_print(" start_stack = %x\n", current->mm->start_stack); |
_print(" arg_start = %x\n", current->mm->arg_start); |
_print(" env_start = %x\n", current->mm->env_start); |
_print(" env_end = %x\n", current->mm->env_end); |
_print(" elf_entry = %x\n", elf_entry); |
|
do { |
put_user(0, fpnt++); |
} while (--nbyte); |
} |
|
start_thread(regs, elf_entry, bprm->p); |
|
if (current->flags & PF_PTRACED) |