load_elf_binary 流程:
填充并且检查目标程序ELF头部
load_elf_phdrs加载目标程序的程序头表
如果需要动态链接, 则寻找和处理解释器段
检查并读取解释器的程序表头
装入目标程序的段segment
填写程序的入口地址
create_elf_tables填写目标文件的参数环境变量等必要信息
start_kernel宏准备进入新的程序入口
————————————————
版权声明:本文为CSDN博主「JeanCheng」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gatieme/article/details/51628257
#if defined(CONFIG_MMU)
{
.procname = "randomize_va_space",
.data = &randomize_va_space,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
#endif
* This structure is used to hold the arguments that are used when loading binaries.
struct linux_binprm {
内核解析elf文件,随机化。
static int load_elf_binary(struct linux_binprm *bprm)
load_elf_phdrs load ELF program headers
typedef struct elf64_phdr {------------------------Program Header Table
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset; /* Segment file offset */
Elf64_Addr p_vaddr; /* Segment virtual address */
Elf64_Addr p_paddr; /* Segment physical address */
Elf64_Xword p_filesz; /* Segment size in file */
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment, file & memory */
} Elf64_Phdr;
p_offset : 段偏移,这个段的第一个自己字节到文件开始的距离,也就是该段在文件中的偏移;
p_vaddr : 加载到内存中的虚拟地址;
p_paddr : 加载到内存中的物理地址;
p_filesz : 文件映像中段的大小/字节数,可能是零,比如说GNU_STACK段;
p_memsz : 内存映像中段的大小/字节数,可能是零,比如说GNU_STACK段;
p_flags : flags relevant to the segment. 和这个段有关的标志;
来自 <https://mudongliang.github.io/2015/10/31/linuxelf.html>
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)---- DGL proc variable
current->flags |= PF_RANDOMIZE;
- else if (loc->elf_ex.e_type == ET_DYN) {
if (interpreter) {
load_bias = ELF_ET_DYN_BASE;
if (current->flags & PF_RANDOMIZE)
load_bias += arch_mmap_rnd();
rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
return rnd << PAGE_SHIFT;--------------------------dgl_4k aligned
elf_flags |= elf_fixed;
} else
load_bias = 0;
- if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
current->mm->brk = current->mm->start_brk =
arch_randomize_brk(current->mm);
void setup_new_exec(struct linux_binprm * bprm)
void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
{
unsigned long random_factor = 0UL;
if (current->flags & PF_RANDOMIZE)
random_factor = arch_mmap_rnd();
mm->mmap_base = mmap_base(random_factor, rlim_stack);
create_elf_tables
elf_map
vm_mmap
start_thread
regs->pc = pc;
regs->sp = sp;
It sounds like your GCC is configured to build -pie binaries by default. These binaries really areshared libraries
(of type ET_DYN), except they run just like a normal executable would.
Or you could link your binary with gcc -no-pie ... and that should produce a non-PIE executable of type
ET_EXEC, for which file will say ELF 64-bit LSB executable.