2019-2020-1 20199303 "Linux kernel principle and Analysis" in the eighth week of work

How Linux boot loader and

Understand the process of compiling and linking of ELF executable file format


First step: editing hello.c a
second step: generating a preprocessed file hello.cpp
GCC -E hello.c -o hello.cpp -m32
VI hello.cpp (
Third Step: compiled into assembly code hello.s
the -X-CPP-Output -S GCC -o hello.s hello.cpp -m32
VI hello.s
step Four: compiled into object code, binary files obtained hello.o,
GCC Assembler -C hello.s the -X--o Hello -m32 .o
vi hello.o
step five: link to the executable file the Hello,
gcc -o the Hello hello.o -m32
vi the Hello
step Six: run the
./hello
gcc -o the Hello hello.c
gcc -o the Hello hello.o -m32 -static .static
hello.static file format is ELF
run about hello.static
./hello.static

ELF file three main objectives:

ELF file format is an open standard, various UNIX executable file systems in ELF format are used, it has three different types:
a relocatable object file (Relocatable, or Object File): store the code and data proper, and other create an executable file or share files with Object file.
Executable files (Executable): Save the file to execute a program, the document pointed out how the program exec process image.
Shared libraries (Shared Object, or Shared Library): save the code and data suitable for being connected to the editor for the dynamic linker link.
ELF object files and links involved in the implementation of the program. ELF header file saved the organization of the document, tell the system how to create a memory image of a process.
When creating a new process with parent process by calling fork, the system is actually a copy of the file segment of the parent process and a virtual memory segment. Virtual memory is a virtual memory, it is actually non-existent, but merely from a number of hardware and software management "system." He provides three important capabilities: 1, it will be the main memory as a cache memory address space on disk, save only the active area in the main memory, and back and forth between disk and main memory as needed data (here, the presence of "swap space" and "paging" and so on), in this way, efficient use of main memory; 2, which provides a unified address space (virtual address addressing) for each process, thereby simplifies memory management; 3, the operating system provides separate address space for each process, thereby protecting the address space per process is not destroyed by another process.
Statically linked ELF executable address space of the process:

ELF format is as follows:

Load executable files

LINUX is generally execution environment to launch an executable program through the shell program. Shell itself does not limit the number of command line arguments, it is limited to its own command; Shell calls a system call command exece and environmental parameters passed to the function main executable program.
Save and pass command-line arguments and environment variables:
When the fork a child process, make a copy of the parent process, then call exece, will overwrite the original process environment, user-mode stack is also cleared. When exeve create a new user mode stack; user mode stack to start_stack as a starting point for the main function, to the argv [] command line arguments and envp [] content environment variable passed to a system call exeve (kernel handler) by pointer manner the above command line parameters and environment variables are copied to the new user mode the stack, thereby initializing the context of the new executable. exece loaded executable in kernel mode, and then return to user mode. So it is the first function call parameter passing, then the system call parameters, and finally a function call parameter passing.

Dynamic Link

Dynamic Link is relative to the shared object. The dynamic linker will all shared libraries required for the program is loaded into the address space of a process, and the rollup resolution of all symbols bind to the corresponding dynamic link library (shared library), and relocation work.
Dynamic linking and dynamic linking executable loading operation: There are two forms of Dynamic Link

experiment procedure

Delete menu directory, git clone a new menu directory and use test_exec.c cover test.c file.

makerootfs, boot the kernel

shut down the kernel, re-run qemu, and increase the parameter -s, -S frozen kernel execution, open the gdb, port 1234


started, the exec command execution in the kernel, will be found stuck

to view the EIF hello information

execve process:
Linux / FS / exec.c

SYSCALL_DEFINE3(execve,
             const char __user *, filename,
             const char __user *const __user *, argv,
             const char __user *const __user *, envp)
{
     return do_execve(getname(filename), argv, envp);
}


int do_execve(struct filename *filename,
     const char __user *const __user *__argv,
     const char __user *const __user *__envp)   //__user 用户态指针
{
     struct user_arg_ptr argv = { .ptr.native = __argv };//命令行参数变成结构
     struct user_arg_ptr envp = { .ptr.native = __envp };
     return do_execve_common(filename, argv, envp);
}


static int do_execve_common(struct filename *filename,
                             struct user_arg_ptr argv,
                             struct user_arg_ptr envp)

{

struct linux_binprm *bprm; //保存要执行的文件相关的信息(include/linux/binfmts.h)
...
file = do_open_exec(filename);//打开执行的可执行文件

//填充bprm结构
bprm->file = file;
bprm->filename = bprm->interp = filename->name;
...
retval = copy_strings(bprm->argc, argv, bprm);//命令行参数和环境变量copy到结构体里

retval = exec_binprm(bprm);// 
}


static int exec_binprm(struct linux_binprm *bprm)
{
     pid_t old_pid, old_vpid;
     int ret;

     /* Need to fetch pid before load_binary changes it */
     old_pid = current->pid;
     rcu_read_lock();
     old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
     rcu_read_unlock();

     ret = search_binary_handler(bprm);//寻找可执行文件的处理函数
     if (ret >= 0) {
             audit_bprm(bprm);
             trace_sched_process_exec(current, old_pid, bprm);
             ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
             proc_exec_connector(current);
     }

     return ret;
}


/*
* cycle the list of binary formats handler, until one recognizes the image
*/
int search_binary_handler(struct linux_binprm *bprm)
{
     struct linux_binfmt *fmt;
    ...
    //循环寻找能够解析当前可执行文件的代码
     list_for_each_entry(fmt, &formats, lh) {
             if (!try_module_get(fmt->module))
                     continue;
             read_unlock(&binfmt_lock);
             bprm->recursion_depth++;
             retval = fmt->load_binary(bprm);//加载可执行文件的处理函数,函数指针,实际调用load_elf_binary(linux/fs/binfmt_elf.c)
             read_lock(&binfmt_lock);
             put_binfmt(fmt);
             bprm->recursion_depth--;
             if (retval < 0 && !bprm->mm) {
                     /* we got to flush_old_exec() and failed after it */
                     read_unlock(&binfmt_lock);
                     force_sigsegv(SIGSEGV, current);
                     return retval;
             }
             if (retval != -ENOEXEC || !bprm->file) {
                     read_unlock(&binfmt_lock);
                     return retval;
             }
    }
     read_unlock(&binfmt_lock);

 }

Guess you like

Origin www.cnblogs.com/besti-20199303/p/11829182.html