⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 binfmt_elf.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,			(elf_phdata->p_offset -			 ELF_PAGEOFFSET(elf_phdata->p_vaddr)));	up_write(&current->mm->mmap_sem);	if (error != ELF_PAGESTART(elf_phdata->p_vaddr))		goto out_free_ph;	elf_bss = elf_phdata->p_vaddr + elf_phdata->p_filesz;	padzero(elf_bss);	len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1);	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;	if (bss > len)		do_brk(len, bss - len);	error = 0;out_free_ph:	kfree(elf_phdata);out:	return error;}/* * Note that some platforms still use traditional core dumps and not * the ELF core dump.  Each platform can select it as appropriate. */#ifdef USE_ELF_CORE_DUMP/* * ELF core dumper * * Modelled on fs/exec.c:aout_core_dump() * Jeremy Fitzhardinge <jeremy@sw.oz.au> *//* * These are the only things you should do on a core-file: use only these * functions to write out all the necessary info. */static int dump_write(struct file *file, const void *addr, int nr){	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;}static int dump_seek(struct file *file, off_t off){	if (file->f_op->llseek) {		if (file->f_op->llseek(file, off, 0) != off)			return 0;	} else		file->f_pos = off;	return 1;}/* * Decide whether a segment is worth dumping; default is yes to be * sure (missing info is worse than too much; etc). * Personally I'd include everything, and use the coredump limit... * * I think we should skip something. But I am not sure how. H.J. */static inline int maydump(struct vm_area_struct *vma){	/*	 * If we may not read the contents, don't allow us to dump	 * them either. "dump_write()" can't handle it anyway.	 */	if (!(vma->vm_flags & VM_READ))		return 0;	/* Do not dump I/O mapped devices! -DaveM */	if (vma->vm_flags & VM_IO)		return 0;#if 1	if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))		return 1;	if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))		return 0;#endif	return 1;}#define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))/* An ELF note in memory */struct memelfnote{	const char *name;	int type;	unsigned int datasz;	void *data;};static int notesize(struct memelfnote *en){	int sz;	sz = sizeof(struct elf_note);	sz += roundup(strlen(en->name), 4);	sz += roundup(en->datasz, 4);	return sz;}/* #define DEBUG */#ifdef DEBUGstatic void dump_regs(const char *str, elf_greg_t *r){	int i;	static const char *regs[] = { "ebx", "ecx", "edx", "esi", "edi", "ebp",					      "eax", "ds", "es", "fs", "gs",					      "orig_eax", "eip", "cs",					      "efl", "uesp", "ss"};	printk("Registers: %s\n", str);	for(i = 0; i < ELF_NGREG; i++)	{		unsigned long val = r[i];		printk("   %-2d %-5s=%08lx %lu\n", i, regs[i], val, val);	}}#endif#define DUMP_WRITE(addr, nr)	\	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)#define DUMP_SEEK(off)	\	do { if (!dump_seek(file, (off))) return 0; } while(0)static int writenote(struct memelfnote *men, struct file *file){	struct elf_note en;	en.n_namesz = strlen(men->name);	en.n_descsz = men->datasz;	en.n_type = men->type;	DUMP_WRITE(&en, sizeof(en));	DUMP_WRITE(men->name, en.n_namesz);	/* XXX - cast from long long to long to avoid need for libgcc.a */	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */	DUMP_WRITE(men->data, men->datasz);	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */	return 1;}#undef DUMP_WRITE#undef DUMP_SEEK#define DUMP_WRITE(addr, nr)	\	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \		goto end_coredump;#define DUMP_SEEK(off)	\	if (!dump_seek(file, (off))) \		goto end_coredump;/* * Actual dumper * * This is a two-pass process; first we find the offsets of the bits, * and then they are actually written out.  If we run out of core limit * we just truncate. */static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file){	int has_dumped = 0;	mm_segment_t fs;	int segs;	size_t size = 0;	int i;	struct vm_area_struct *vma;	struct elfhdr elf;	off_t offset = 0, dataoff;	unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;	int numnote = 4;	struct memelfnote notes[4];	struct elf_prstatus prstatus;	/* NT_PRSTATUS */	elf_fpregset_t fpu;		/* NT_PRFPREG */	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */	/* first copy the parameters from user space */	memset(&psinfo, 0, sizeof(psinfo));	{		int i, len;		len = current->mm->arg_end - current->mm->arg_start;		if (len >= ELF_PRARGSZ)			len = ELF_PRARGSZ-1;		copy_from_user(&psinfo.pr_psargs,			      (const char *)current->mm->arg_start, len);		for(i = 0; i < len; i++)			if (psinfo.pr_psargs[i] == 0)				psinfo.pr_psargs[i] = ' ';		psinfo.pr_psargs[len] = 0;	}	memset(&prstatus, 0, sizeof(prstatus));	/*	 * This transfers the registers from regs into the standard	 * coredump arrangement, whatever that is.	 */#ifdef ELF_CORE_COPY_REGS	ELF_CORE_COPY_REGS(prstatus.pr_reg, regs)#else	if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))	{		printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",			(long)sizeof(elf_gregset_t), (long)sizeof(struct pt_regs));	}	else		*(struct pt_regs *)&prstatus.pr_reg = *regs;#endif	/* now stop all vm operations */	down_write(&current->mm->mmap_sem);	segs = current->mm->map_count;#ifdef DEBUG	printk("elf_core_dump: %d segs %lu limit\n", segs, limit);#endif	/* Set up header */	memcpy(elf.e_ident, ELFMAG, SELFMAG);	elf.e_ident[EI_CLASS] = ELF_CLASS;	elf.e_ident[EI_DATA] = ELF_DATA;	elf.e_ident[EI_VERSION] = EV_CURRENT;	memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);	elf.e_type = ET_CORE;	elf.e_machine = ELF_ARCH;	elf.e_version = EV_CURRENT;	elf.e_entry = 0;	elf.e_phoff = sizeof(elf);	elf.e_shoff = 0;	elf.e_flags = 0;	elf.e_ehsize = sizeof(elf);	elf.e_phentsize = sizeof(struct elf_phdr);	elf.e_phnum = segs+1;		/* Include notes */	elf.e_shentsize = 0;	elf.e_shnum = 0;	elf.e_shstrndx = 0;	fs = get_fs();	set_fs(KERNEL_DS);	has_dumped = 1;	current->flags |= PF_DUMPCORE;	DUMP_WRITE(&elf, sizeof(elf));	offset += sizeof(elf);				/* Elf header */	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */	/*	 * Set up the notes in similar form to SVR4 core dumps made	 * with info from their /proc.	 */	notes[0].name = "CORE";	notes[0].type = NT_PRSTATUS;	notes[0].datasz = sizeof(prstatus);	notes[0].data = &prstatus;	prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;	prstatus.pr_sigpend = current->pending.signal.sig[0];	prstatus.pr_sighold = current->blocked.sig[0];	psinfo.pr_pid = prstatus.pr_pid = current->pid;	psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;	psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;	psinfo.pr_sid = prstatus.pr_sid = current->session;	prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime);	prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime);	prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime);	prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime);	prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime);	prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime);	prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime);	prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime);#ifdef DEBUG	dump_regs("Passed in regs", (elf_greg_t *)regs);	dump_regs("prstatus regs", (elf_greg_t *)&prstatus.pr_reg);#endif	notes[1].name = "CORE";	notes[1].type = NT_PRPSINFO;	notes[1].datasz = sizeof(psinfo);	notes[1].data = &psinfo;	i = current->state ? ffz(~current->state) + 1 : 0;	psinfo.pr_state = i;	psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];	psinfo.pr_zomb = psinfo.pr_sname == 'Z';	psinfo.pr_nice = current->nice;	psinfo.pr_flag = current->flags;	psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);	psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);	strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));	notes[2].name = "CORE";	notes[2].type = NT_TASKSTRUCT;	notes[2].datasz = sizeof(*current);	notes[2].data = current;	/* Try to dump the FPU. */	prstatus.pr_fpvalid = dump_fpu (regs, &fpu);	if (!prstatus.pr_fpvalid)	{		numnote--;	}	else	{		notes[3].name = "CORE";		notes[3].type = NT_PRFPREG;		notes[3].datasz = sizeof(fpu);		notes[3].data = &fpu;	}		/* Write notes phdr entry */	{		struct elf_phdr phdr;		int sz = 0;		for(i = 0; i < numnote; i++)			sz += notesize(&notes[i]);		phdr.p_type = PT_NOTE;		phdr.p_offset = offset;		phdr.p_vaddr = 0;		phdr.p_paddr = 0;		phdr.p_filesz = sz;		phdr.p_memsz = 0;		phdr.p_flags = 0;		phdr.p_align = 0;		offset += phdr.p_filesz;		DUMP_WRITE(&phdr, sizeof(phdr));	}	/* Page-align dumped data */	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);	/* Write program headers for segments dump */	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {		struct elf_phdr phdr;		size_t sz;		sz = vma->vm_end - vma->vm_start;		phdr.p_type = PT_LOAD;		phdr.p_offset = offset;		phdr.p_vaddr = vma->vm_start;		phdr.p_paddr = 0;		phdr.p_filesz = maydump(vma) ? sz : 0;		phdr.p_memsz = sz;		offset += phdr.p_filesz;		phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;		if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;		if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;		phdr.p_align = ELF_EXEC_PAGESIZE;		DUMP_WRITE(&phdr, sizeof(phdr));	}	for(i = 0; i < numnote; i++)		if (!writenote(&notes[i], file))			goto end_coredump;	DUMP_SEEK(dataoff);	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {		unsigned long addr;		if (!maydump(vma))			continue;#ifdef DEBUG		printk("elf_core_dump: writing %08lx-%08lx\n", vma->vm_start, vma->vm_end);#endif		for (addr = vma->vm_start;		     addr < vma->vm_end;		     addr += PAGE_SIZE) {			struct page* page;			struct vm_area_struct *vma;			if (get_user_pages(current, current->mm, addr, 1, 0, 1,						&page, &vma) <= 0) {				DUMP_SEEK (file->f_pos + PAGE_SIZE);			} else {				if (page == ZERO_PAGE(addr)) {					DUMP_SEEK (file->f_pos + PAGE_SIZE);				} else {					void *kaddr;					flush_cache_page(vma, addr);					kaddr = kmap(page);					DUMP_WRITE(kaddr, PAGE_SIZE);					flush_page_to_ram(page);					kunmap(page);				}				put_page(page);			}		}	}	if ((off_t) file->f_pos != offset) {		/* Sanity check */		printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",		       (off_t) file->f_pos, offset);	} end_coredump:	set_fs(fs);	up_write(&current->mm->mmap_sem);	return has_dumped;}#endif		/* USE_ELF_CORE_DUMP */static int __init init_elf_binfmt(void){	return register_binfmt(&elf_format);}static void __exit exit_elf_binfmt(void){	/* Remove the COFF and ELF loaders. */	unregister_binfmt(&elf_format);}module_init(init_elf_binfmt)module_exit(exit_elf_binfmt)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -