?? binfmt_coff.c
字號:
* THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD
* SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD.
*/
if (status >= 0) {
long text_scnptr = COFF_LONG (text_sect->s_scnptr);
long text_size = COFF_LONG (text_sect->s_size);
long text_vaddr = COFF_LONG (text_sect->s_vaddr);
long data_scnptr;
long data_size;
long data_vaddr;
long bss_size;
long bss_vaddr;
/*
* Generate the proper values for the data fields
*/
if (data_sect != NULL) {
data_scnptr = COFF_LONG (data_sect->s_scnptr);
data_size = COFF_LONG (data_sect->s_size);
data_vaddr = COFF_LONG (data_sect->s_vaddr);
}
else {
data_scnptr = 0;
data_size = 0;
data_vaddr = 0;
}
/*
* Generate the proper values for the bss fields
*/
if (bss_sect != NULL) {
bss_size = COFF_LONG (bss_sect->s_size);
bss_vaddr = COFF_LONG (bss_sect->s_vaddr);
}
else {
bss_size = 0;
bss_vaddr = 0;
}
/*
* Flush the executable from memory. At this point the executable is
* committed to being defined or a segmentation violation will occur.
*/
if (lib_ok) {
#ifdef COFF_DEBUG
printk ("flushing executable\n");
#endif
flush_old_exec (bprm);
/*
* Define the initial locations for the various items in the new process
*/
current->mmap = NULL;
current->rss = 0;
/*
* Construct the parameter and environment string table entries.
*/
bprm->p += change_ldt (0, bprm->page);
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
bprm->p = (unsigned long) create_tables ((char *) bprm->p,
bprm->argc,
bprm->envc,
1);
/*
* Do the end processing once the stack has been constructed
*/
current->start_code = text_vaddr & PAGE_MASK;
current->end_code = text_vaddr + text_size;
current->end_data = data_vaddr + data_size;
current->start_brk =
current->brk = bss_vaddr + bss_size;
current->suid =
current->euid = bprm->e_uid;
current->sgid =
current->egid = bprm->e_gid;
current->executable = bprm->inode; /* Store inode for file */
++bprm->inode->i_count; /* Count the open inode */
regs->eip = start_addr; /* Current EIP register */
regs->esp =
current->start_stack = bprm->p;
}
/*
* Map the text pages
*/
#ifdef COFF_DEBUG
printk (".text: vaddr = %d, size = %d, scnptr = %d\n",
text_vaddr,
text_size,
text_scnptr);
#endif
status = do_mmap (fp,
text_vaddr & PAGE_MASK,
text_size + (text_vaddr & ~PAGE_MASK),
PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_SHARED,
text_scnptr & PAGE_MASK);
status = (status == (text_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
/*
* Map the data pages
*/
if (status >= 0 && data_size != 0) {
#ifdef COFF_DEBUG
printk (".data: vaddr = %d, size = %d, scnptr = %d\n",
data_vaddr,
data_size,
data_scnptr);
#endif
status = do_mmap (fp,
data_vaddr & PAGE_MASK,
data_size + (data_vaddr & ~PAGE_MASK),
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE,
data_scnptr & PAGE_MASK);
status = (status == (data_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
}
/*
* Construct the bss data for the process. The bss ranges from the
* end of the data (which may not be on a page boundry) to the end
* of the bss section. Allocate any necessary pages for the data.
*/
if (status >= 0 && bss_size != 0) {
#ifdef COFF_DEBUG
printk (".bss: vaddr = %d, size = %d\n",
bss_vaddr,
bss_size);
#endif
zeromap_page_range (PAGE_ALIGN (bss_vaddr),
PAGE_ALIGN (bss_size),
PAGE_COPY);
status = clear_memory (bss_vaddr, bss_size);
}
/*
* Load any shared library for the executable.
*/
if (status >= 0 && lib_ok && lib_count != 0) {
int nIndex;
COFF_SCNHDR *sect_ptr = sect_bufr;
/*
* Find the library sections. (There should be atleast one. It was counted
* earlier.) This will evenutally recurse to our code and load the shared
* library with our own procedures.
*/
for (nIndex = 0; nIndex < sections; ++nIndex) {
long int sect_flags = COFF_LONG (sect_ptr->s_flags);
if (sect_flags == COFF_STYP_LIB) {
status = preload_library (bprm, sect_ptr, fp);
if (status != 0)
break;
}
sect_ptr = (COFF_SCNHDR *) &((char *) sect_ptr) [COFF_SCNHSZ];
}
}
/*
* Generate any needed trap for this process. If an error occured then
* generate a segmentation violation. If the process is being debugged
* then generate the load trap. (Note: If this is a library load then
* do not generate the trap here. Pass the error to the caller who
* will do it for the process in the outer lay of this procedure call.)
*/
if (lib_ok) {
if (status < 0)
send_sig (SIGSEGV, current, 0); /* Generate the error trap */
else {
if (current->flags & PF_PTRACED)
send_sig (SIGTRAP, current, 0);
}
status = 0; /* We are committed. It can't fail */
}
}
/*
* Do any cleanup processing
*/
if (fd >= 0)
sys_close (fd); /* Close unused code file */
if (sect_bufr != NULL)
kfree (sect_bufr); /* Release section list buffer */
/*
* Return the completion status.
*/
#ifdef COFF_DEBUG
printk ("binfmt_coff: result = %d\n", status);
#endif
return (status);
}
/*
* This procedure will load the library listed in the file name given
* as the paramter. The result will be non-zero should something fail
* to load.
*/
static int
preload_this_library (struct linux_binprm *exe_bprm, char *lib_name)
{
int status;
int old_fs = get_fs();
/*
* If debugging then print "we have arrived"
*/
#ifdef COFF_DEBUG
printk ("%s loading shared library %s\n",
exe_bprm->filename,
lib_name);
#endif
/*
* Change the FS register to the proper kernel address space and attempt
* to load the library. The library name is allocated from the kernel
* pool.
*/
set_fs (get_ds ());
status = sys_uselib (lib_name);
set_fs (old_fs);
/*
* Return the success/failure to the caller.
*/
return (status);
}
/*
* This procedure is called to load a library section. The various
* libraries are loaded from the list given in the section data.
*/
static int
preload_library (struct linux_binprm *exe_bprm,
COFF_SCNHDR * sect, struct file *fp)
{
int status = 0; /* Completion status */
long nbytes; /* Count of bytes in the header area */
/*
* Fetch the size of the section. There must be enough room for atleast
* one entry.
*/
nbytes = COFF_LONG (sect->s_size);
if (nbytes < COFF_SLIBSZ) {
status = -ENOEXEC;
#ifdef COFF_DEBUG
printk ("library section too small\n");
#endif
}
/*
* Allocate a buffer to hold the section data
*/
else {
COFF_SLIBHD *phdr;
char *buffer = (char *) kmalloc (nbytes, GFP_KERNEL);
if (0 == buffer) {
status = -ENOEXEC;
#ifdef COFF_DEBUG
printk ("kmalloc failed\n");
#endif
}
else {
int old_fs = get_fs ();
/*
* Read the section data from the disk file.
*/
set_fs (get_ds ()); /* Make it point to the proper location */
status = read_exec (exe_bprm->inode, /* INODE for file */
COFF_LONG (sect->s_scnptr), /* Disk location */
buffer, /* Buffer for read */
nbytes); /* Byte count reqd. */
set_fs (old_fs); /* Restore the selector */
/*
* Check the result. The value returned is the byte count actaully read.
*/
if (status >= 0 && status != nbytes) {
#ifdef COFF_DEBUG
printk ("read of lib section was short\n");
#endif
status = -ENOEXEC;
}
}
/*
* At this point, go through the list of libraries in the data area.
*/
phdr = (COFF_SLIBHD *) buffer;
while (status >= 0 && nbytes > COFF_SLIBSZ) {
int entry_size = COFF_LONG (phdr->sl_entsz) * sizeof (long);
int header_size = COFF_LONG (phdr->sl_pathndx) * sizeof (long);
/*
* Validate the sizes of the various items. I don't trust the linker!!
*/
if ((unsigned) header_size >= (unsigned) nbytes ||
entry_size <= 0 ||
(unsigned) entry_size <= (unsigned) header_size) {
status = -ENOEXEC;
#ifdef COFF_DEBUG
printk ("header count is invalid\n");
#endif
}
/*
* Load the library. Stop the load process on the first error.
*/
else {
status = preload_this_library (exe_bprm,
&((char *) phdr)[header_size]);
#ifdef COFF_DEBUG
printk ("preload_this_library result = %d\n", status);
#endif
}
/*
* Point to the next library in the section data.
*/
nbytes -= entry_size;
phdr = (COFF_SLIBHD *) &((char *) phdr)[entry_size];
}
/*
* Release the space for the library list.
*/
if (buffer != NULL)
kfree (buffer);
}
/*
* Return the resulting status to the caller.
*/
return (status);
}
/*
* This procedure is called by the main load sequence. It will load
* the executable and prepare it for execution. It provides the additional
* parameters used by the recursive coff loader and tells the loader that
* this is the main executable. How simple it is . . . .
*/
int
load_coff_binary (struct linux_binprm *bprm, struct pt_regs *regs)
{
return (load_object (bprm, regs, 1));
}
/*
* Load the image for any shared library.
*
* This is called when we need to load a library based upon a file name.
*/
int
load_coff_library (int fd)
{
struct linux_binprm *bprm; /* Parameters for the load operation */
int status; /* Status of the request */
/*
* Read the first portion of the file.
*/
bprm = (struct linux_binprm *) kmalloc (sizeof (struct linux_binprm),
GFP_KERNEL);
if (0 == bprm) {
#ifdef COFF_DEBUG
printk ("kmalloc failed\n");
#endif
status = -ENOEXEC;
}
else {
struct file *file; /* Pointer to the file table */
struct pt_regs regs; /* Register work area */
int old_fs = get_fs (); /* Previous FS register value */
memset (bprm, '\0', sizeof (struct linux_binprm));
file = current->filp[fd];
bprm->inode = file->f_inode; /* The only item _really_ needed */
bprm->filename = ""; /* Make it a legal string */
/*
* Read the section list from the disk file.
*/
set_fs (get_ds ()); /* Make it point to the proper location */
status = read_exec (bprm->inode, /* INODE for file */
0L, /* Offset in the file */
bprm->buf, /* Buffer for read */
sizeof (bprm->buf)); /* Size of the buffer */
set_fs (old_fs); /* Restore the selector */
/*
* Try to load the library.
*/
status = load_object (bprm, ®s, 0);
/*
* Release the work buffer and return the result.
*/
kfree (bprm); /* Release the buffer area */
}
/*
* Return the result of the load operation
*/
return (status);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -