*参照元 [#g685cf4a] #backlinks *説明 [#va855e73] -パス: [[linux-2.6.33/fs/binfmt_elf.c]] -FIXME: これは何? --説明 **引数 [#i963e8b1] - -- **返り値 [#qf442fb6] - -- **参考 [#edf5e669] *実装 [#qc5e91f9] /* * 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(struct coredump_params *cprm) { int has_dumped = 0; mm_segment_t fs; int segs; size_t size = 0; struct vm_area_struct *vma, *gate_vma; struct elfhdr *elf = NULL; loff_t offset = 0, dataoff, foffset; unsigned long mm_flags; struct elf_note_info info; /* * We no longer stop all VM operations. * * This is because those proceses that could possibly change map_count * or the mmap / vma pages are now blocked in do_exit on current * finishing this core dump. * * Only ptrace can touch these memory addresses, but it doesn't change * the map_count or the pages allocated. So no possibility of crashing * exists while dumping the mm->vm_next areas to the core file. */ /* alloc memory for large data structures: too large to be on stack */ elf = kmalloc(sizeof(*elf), GFP_KERNEL); if (!elf) goto out; /* * The number of segs are recored into ELF header as 16bit value. * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here. */ segs = current->mm->map_count; #ifdef ELF_CORE_EXTRA_PHDRS segs += ELF_CORE_EXTRA_PHDRS; #endif gate_vma = get_gate_vma(current); if (gate_vma != NULL) segs++; /* * Collect all the non-memory information about the process for the * notes. This also sets up the file header. */ if (!fill_note_info(elf, segs + 1, /* including notes section */ &info, cprm->signr, cprm->regs)) goto cleanup; has_dumped = 1; current->flags |= PF_DUMPCORE; fs = get_fs(); set_fs(KERNEL_DS); DUMP_WRITE(elf, sizeof(*elf)); offset += sizeof(*elf); /* Elf header */ offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */ foffset = offset; /* Write notes phdr entry */ { struct elf_phdr phdr; size_t sz = get_note_info_size(&info); sz += elf_coredump_extra_notes_size(); fill_elf_note_phdr(&phdr, sz, offset); offset += sz; DUMP_WRITE(&phdr, sizeof(phdr)); } dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); /* * We must use the same mm->flags while dumping core to avoid * inconsistency between the program headers and bodies, otherwise an * unusable core file can be generated. */ mm_flags = current->mm->flags; /* Write program headers for segments dump */ for (vma = first_vma(current, gate_vma); vma != NULL; vma = next_vma(vma, gate_vma)) { struct elf_phdr phdr; phdr.p_type = PT_LOAD; phdr.p_offset = offset; phdr.p_vaddr = vma->vm_start; phdr.p_paddr = 0; phdr.p_filesz = vma_dump_size(vma, mm_flags); phdr.p_memsz = vma->vm_end - vma->vm_start; 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)); } #ifdef ELF_CORE_WRITE_EXTRA_PHDRS ELF_CORE_WRITE_EXTRA_PHDRS; #endif /* write out the notes section */ if (!write_note_info(&info, cprm->file, &foffset)) goto end_coredump; if (elf_coredump_extra_notes_write(cprm->file, &foffset)) goto end_coredump; /* Align to page */ if (!dump_seek(cprm->file, dataoff - foffset)) goto end_coredump; for (vma = first_vma(current, gate_vma); vma != NULL; vma = next_vma(vma, gate_vma)) { unsigned long addr; unsigned long end; end = vma->vm_start + vma_dump_size(vma, mm_flags); for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { struct page *page; int stop; page = get_dump_page(addr); if (page) { void *kaddr = kmap(page); stop = ((size += PAGE_SIZE) > cprm->limit) || !dump_write(cprm->file, kaddr, PAGE_SIZE); kunmap(page); page_cache_release(page); } else stop = !dump_seek(cprm->file, PAGE_SIZE); if (stop) goto end_coredump; } } #ifdef ELF_CORE_WRITE_EXTRA_DATA ELF_CORE_WRITE_EXTRA_DATA; #endif end_coredump: set_fs(fs); cleanup: free_note_info(&info); kfree(elf); out: return has_dumped; } *コメント [#d5ac3096]