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

📄 coredump.c

📁 linux 内核源代码
💻 C
字号:
/* * SPU core dump code * * (C) Copyright 2006 IBM Corp. * * Author: Dwayne Grant McConnell <decimal@us.ibm.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/elf.h>#include <linux/file.h>#include <linux/fs.h>#include <linux/list.h>#include <linux/module.h>#include <linux/syscalls.h>#include <asm/uaccess.h>#include "spufs.h"static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,				size_t size, loff_t *off){	u64 data;	int ret;	if (spufs_coredump_read[num].read)		return spufs_coredump_read[num].read(ctx, buffer, size, off);	data = spufs_coredump_read[num].get(ctx);	ret = snprintf(buffer, size, "0x%.16lx", data);	if (ret >= size)		return size;	return ++ret; /* count trailing NULL */}/* * 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 spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset){	unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;	ssize_t written;	if (*foffset + nr > limit)		return -EIO;	written = file->f_op->write(file, addr, nr, &file->f_pos);	*foffset += written;	if (written != nr)		return -EIO;	return 0;}static int spufs_dump_align(struct file *file, char *buf, loff_t new_off,			    loff_t *foffset){	int rc, size;	size = min((loff_t)PAGE_SIZE, new_off - *foffset);	memset(buf, 0, size);	rc = 0;	while (rc == 0 && new_off > *foffset) {		size = min((loff_t)PAGE_SIZE, new_off - *foffset);		rc = spufs_dump_write(file, buf, size, foffset);	}	return rc;}static int spufs_ctx_note_size(struct spu_context *ctx, int dfd){	int i, sz, total = 0;	char *name;	char fullname[80];	for (i = 0; spufs_coredump_read[i].name != NULL; i++) {		name = spufs_coredump_read[i].name;		sz = spufs_coredump_read[i].size;		sprintf(fullname, "SPU/%d/%s", dfd, name);		total += sizeof(struct elf_note);		total += roundup(strlen(fullname) + 1, 4);		total += roundup(sz, 4);	}	return total;}/* * The additional architecture-specific notes for Cell are various * context files in the spu context. * * This function iterates over all open file descriptors and sees * if they are a directory in spufs.  In that case we use spufs * internal functionality to dump them without needing to actually * open the files. */static struct spu_context *coredump_next_context(int *fd){	struct fdtable *fdt = files_fdtable(current->files);	struct file *file;	struct spu_context *ctx = NULL;	for (; *fd < fdt->max_fds; (*fd)++) {		if (!FD_ISSET(*fd, fdt->open_fds))			continue;		file = fcheck(*fd);		if (!file || file->f_op != &spufs_context_fops)			continue;		ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;		if (ctx->flags & SPU_CREATE_NOSCHED)			continue;		/* start searching the next fd next time we're called */		(*fd)++;		break;	}	return ctx;}int spufs_coredump_extra_notes_size(void){	struct spu_context *ctx;	int size = 0, rc, fd;	fd = 0;	while ((ctx = coredump_next_context(&fd)) != NULL) {		spu_acquire_saved(ctx);		rc = spufs_ctx_note_size(ctx, fd);		spu_release_saved(ctx);		if (rc < 0)			break;		size += rc;	}	return size;}static int spufs_arch_write_note(struct spu_context *ctx, int i,				  struct file *file, int dfd, loff_t *foffset){	loff_t pos = 0;	int sz, rc, nread, total = 0;	const int bufsz = PAGE_SIZE;	char *name;	char fullname[80], *buf;	struct elf_note en;	buf = (void *)get_zeroed_page(GFP_KERNEL);	if (!buf)		return -ENOMEM;	name = spufs_coredump_read[i].name;	sz = spufs_coredump_read[i].size;	sprintf(fullname, "SPU/%d/%s", dfd, name);	en.n_namesz = strlen(fullname) + 1;	en.n_descsz = sz;	en.n_type = NT_SPU;	rc = spufs_dump_write(file, &en, sizeof(en), foffset);	if (rc)		goto out;	rc = spufs_dump_write(file, fullname, en.n_namesz, foffset);	if (rc)		goto out;	rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset);	if (rc)		goto out;	do {		nread = do_coredump_read(i, ctx, buf, bufsz, &pos);		if (nread > 0) {			rc = spufs_dump_write(file, buf, nread, foffset);			if (rc)				goto out;			total += nread;		}	} while (nread == bufsz && total < sz);	if (nread < 0) {		rc = nread;		goto out;	}	rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4),			      foffset);out:	free_page((unsigned long)buf);	return rc;}int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset){	struct spu_context *ctx;	int fd, j, rc;	fd = 0;	while ((ctx = coredump_next_context(&fd)) != NULL) {		spu_acquire_saved(ctx);		for (j = 0; spufs_coredump_read[j].name != NULL; j++) {			rc = spufs_arch_write_note(ctx, j, file, fd, foffset);			if (rc) {				spu_release_saved(ctx);				return rc;			}		}		spu_release_saved(ctx);	}	return 0;}

⌨️ 快捷键说明

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