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

📄 unwind.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		return;	}	memcpy(rs, &sr->curr, sizeof(*rs));	rs->next = sr->stack;	sr->stack = rs;}static voidpop (struct unw_state_record *sr){	struct unw_reg_state *rs;	if (!sr->stack) {		printk ("unwind: stack underflow!\n");		return;	}	rs = sr->stack;	sr->stack = rs->next;	free_reg_state(rs);}static enum unw_register_index __attribute__((const))decode_abreg (unsigned char abreg, int memory){	switch (abreg) {	      case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);	      case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);	      case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);	      case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);	      case 0x60: return UNW_REG_PR;	      case 0x61: return UNW_REG_PSP;	      case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;	      case 0x63: return UNW_REG_RP;	      case 0x64: return UNW_REG_BSP;	      case 0x65: return UNW_REG_BSPSTORE;	      case 0x66: return UNW_REG_RNAT;	      case 0x67: return UNW_REG_UNAT;	      case 0x68: return UNW_REG_FPSR;	      case 0x69: return UNW_REG_PFS;	      case 0x6a: return UNW_REG_LC;	      default:		break;	}	dprintk("unwind: bad abreg=0x%x\n", abreg);	return UNW_REG_LC;}static voidset_reg (struct unw_reg_info *reg, enum unw_where where, int when, unsigned long val){	reg->val = val;	reg->where = where;	if (reg->when == UNW_WHEN_NEVER)		reg->when = when;}static voidalloc_spill_area (unsigned long *offp, unsigned long regsize,		  struct unw_reg_info *lo, struct unw_reg_info *hi){	struct unw_reg_info *reg;	for (reg = hi; reg >= lo; --reg) {		if (reg->where == UNW_WHERE_SPILL_HOME) {			reg->where = UNW_WHERE_PSPREL;			reg->val = 0x10 - *offp;			*offp += regsize;		}	}}static inline voidspill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word t){	struct unw_reg_info *reg;	for (reg = *regp; reg <= lim; ++reg) {		if (reg->where == UNW_WHERE_SPILL_HOME) {			reg->when = t;			*regp = reg + 1;			return;		}	}	dprintk("unwind: excess spill!\n");}static inline voidfinish_prologue (struct unw_state_record *sr){	struct unw_reg_info *reg;	unsigned long off;	int i;	/*	 * First, resolve implicit register save locations (see Section "11.4.2.3 Rules	 * for Using Unwind Descriptors", rule 3):	 */	for (i = 0; i < (int) sizeof(unw.save_order)/sizeof(unw.save_order[0]); ++i) {		reg = sr->curr.reg + unw.save_order[i];		if (reg->where == UNW_WHERE_GR_SAVE) {			reg->where = UNW_WHERE_GR;			reg->val = sr->gr_save_loc++;		}	}	/*	 * Next, compute when the fp, general, and branch registers get	 * saved.  This must come before alloc_spill_area() because	 * we need to know which registers are spilled to their home	 * locations.	 */	if (sr->imask) {		unsigned char kind, mask = 0, *cp = sr->imask;		unsigned long t;		static const unsigned char limit[3] = {			UNW_REG_F31, UNW_REG_R7, UNW_REG_B5		};		struct unw_reg_info *(regs[3]);		regs[0] = sr->curr.reg + UNW_REG_F2;		regs[1] = sr->curr.reg + UNW_REG_R4;		regs[2] = sr->curr.reg + UNW_REG_B1;		for (t = 0; t < sr->region_len; ++t) {			if ((t & 3) == 0)				mask = *cp++;			kind = (mask >> 2*(3-(t & 3))) & 3;			if (kind > 0)				spill_next_when(&regs[kind - 1], sr->curr.reg + limit[kind - 1],						sr->region_start + t);		}	}	/*	 * Next, lay out the memory stack spill area:	 */	if (sr->any_spills) {		off = sr->spill_offset;		alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31); 		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5);		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7);	}}/* * Region header descriptors. */static voiddesc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,	       struct unw_state_record *sr){	int i;	if (!(sr->in_body || sr->first_region))		finish_prologue(sr);	sr->first_region = 0;	/* check if we're done: */	if (body && sr->when_target < sr->region_start + sr->region_len) {		sr->done = 1;		return;	}	for (i = 0; i < sr->epilogue_count; ++i)		pop(sr);	sr->epilogue_count = 0;	sr->epilogue_start = UNW_WHEN_NEVER;	if (!body)		push(sr);	sr->region_start += sr->region_len;	sr->region_len = rlen;	sr->in_body = body;	if (!body) {		for (i = 0; i < 4; ++i) {			if (mask & 0x8)				set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,					sr->region_start + sr->region_len - 1, grsave++);			mask <<= 1;		}		sr->gr_save_loc = grsave;		sr->any_spills = 0;		sr->imask = 0;		sr->spill_offset = 0x10;	/* default to psp+16 */	}}/* * Prologue descriptors. */static inline voiddesc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr){	if (abi == 0 && context == 'i')		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;	else		dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context);}static inline voiddesc_br_gr (unsigned char brmask, unsigned char gr, struct unw_state_record *sr){	int i;	for (i = 0; i < 5; ++i) {		if (brmask & 1)			set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,				sr->region_start + sr->region_len - 1, gr++);		brmask >>= 1;	}}static inline voiddesc_br_mem (unsigned char brmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 5; ++i) {		if (brmask & 1) {			set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		brmask >>= 1;	}}static inline voiddesc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 4; ++i) {		if ((grmask & 1) != 0) {			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		grmask >>= 1;	}	for (i = 0; i < 20; ++i) {		if ((frmask & 1) != 0) {			set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		frmask >>= 1;	}}static inline voiddesc_fr_mem (unsigned char frmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 4; ++i) {		if ((frmask & 1) != 0) {			set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		frmask >>= 1;	}}static inline voiddesc_gr_gr (unsigned char grmask, unsigned char gr, struct unw_state_record *sr){	int i;	for (i = 0; i < 4; ++i) {		if ((grmask & 1) != 0)			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,				sr->region_start + sr->region_len - 1, gr++);		grmask >>= 1;	}}static inline voiddesc_gr_mem (unsigned char grmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 4; ++i) {		if ((grmask & 1) != 0) {			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		grmask >>= 1;	}}static inline voiddesc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr){	set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,		sr->region_start + MIN((int)t, sr->region_len - 1), 16*size);}static inline voiddesc_mem_stack_v (unw_word t, struct unw_state_record *sr){	sr->curr.reg[UNW_REG_PSP].when = sr->region_start + MIN((int)t, sr->region_len - 1);}static inline voiddesc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr){	set_reg(sr->curr.reg + reg, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, dst);}static inline voiddesc_reg_psprel (unsigned char reg, unw_word pspoff, struct unw_state_record *sr){	set_reg(sr->curr.reg + reg, UNW_WHERE_PSPREL, sr->region_start + sr->region_len - 1,		0x10 - 4*pspoff);}static inline voiddesc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr){	set_reg(sr->curr.reg + reg, UNW_WHERE_SPREL, sr->region_start + sr->region_len - 1,		4*spoff);}static inline voiddesc_rp_br (unsigned char dst, struct unw_state_record *sr){	sr->return_link_reg = dst;}static inline voiddesc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr){	struct unw_reg_info *reg = sr->curr.reg + regnum;	if (reg->where == UNW_WHERE_NONE)		reg->where = UNW_WHERE_GR_SAVE;	reg->when = sr->region_start + MIN((int)t, sr->region_len - 1);}static inline voiddesc_spill_base (unw_word pspoff, struct unw_state_record *sr){	sr->spill_offset = 0x10 - 4*pspoff;}static inline unsigned char *desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr){	sr->imask = imaskp;	return imaskp + (2*sr->region_len + 7)/8;}/* * Body descriptors. */static inline voiddesc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr){	sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;	sr->epilogue_count = ecount + 1;}static inline voiddesc_copy_state (unw_word label, struct unw_state_record *sr){	struct unw_reg_state *rs;	for (rs = sr->reg_state_list; rs; rs = rs->next) {		if (rs->label == label) {			memcpy (&sr->curr, rs, sizeof(sr->curr));			return;		}	}	printk("unwind: failed to find state labelled 0x%lx\n", label);}static inline voiddesc_label_state (unw_word label, struct unw_state_record *sr){	struct unw_reg_state *rs;	rs = alloc_reg_state();	memcpy(rs, &sr->curr, sizeof(*rs));	rs->label = label;	rs->next = sr->reg_state_list;	sr->reg_state_list = rs;}/* * General descriptors. */static inline intdesc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr){	if (sr->when_target <= sr->region_start + MIN((int)t, sr->region_len - 1))		return 0;	if (qp > 0) {		if ((sr->pr_val & (1UL << qp)) == 0) 			return 0;		sr->pr_mask |= (1UL << qp);	}	return 1;}static inline voiddesc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, struct unw_state_record *sr){	struct unw_reg_info *r;	if (!desc_is_active(qp, t, sr))		return;	r = sr->curr.reg + decode_abreg(abreg, 0);	r->where = UNW_WHERE_NONE;	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);	r->val = 0;}static inline voiddesc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned char x,		     unsigned char ytreg, struct unw_state_record *sr){	enum unw_where where = UNW_WHERE_GR;	struct unw_reg_info *r;	if (!desc_is_active(qp, t, sr))		return;	if (x)		where = UNW_WHERE_BR;	else if (ytreg & 0x80)		where = UNW_WHERE_FR;	r = sr->curr.reg + decode_abreg(abreg, 0);	r->where = where;	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);	r->val = (ytreg & 0x7f);}static inline voiddesc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word pspoff,		     struct unw_state_record *sr){	struct unw_reg_info *r;	if (!desc_is_active(qp, t, sr))		return;	r = sr->curr.reg + decode_abreg(abreg, 1);	r->where = UNW_WHERE_PSPREL;	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);	r->val = 0x10 - 4*pspoff;}static inline voiddesc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word spoff,		       struct unw_state_record *sr){	struct unw_reg_info *r;	if (!desc_is_active(qp, t, sr))		return;	r = sr->curr.reg + decode_abreg(abreg, 1);	r->where = UNW_WHERE_SPREL;	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);	r->val = 4*spoff;}#define UNW_DEC_BAD_CODE(code)			printk("unwind: unknown code 0x%02x\n", code);/* * region headers: */#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg)	desc_prologue(0,r,m,gr,arg)#define UNW_DEC_PROLOGUE(fmt,b,r,arg)		desc_prologue(b,r,0,32,arg)/* * prologue descriptors: */#define UNW_DEC_ABI(fmt,a,c,arg)		desc_abi(a,c,arg)#define UNW_DEC_BR_GR(fmt,b,g,arg)		desc_br_gr(b,g,arg)#define UNW_DEC_BR_MEM(fmt,b,arg)		desc_br_mem(b,arg)#define UNW_DEC_FRGR_MEM(fmt,g,f,arg)		desc_frgr_mem(g,f,arg)#define UNW_DEC_FR_MEM(fmt,f,arg)		desc_fr_mem(f,arg)#define UNW_DEC_GR_GR(fmt,m,g,arg)		desc_gr_gr(m,g,arg)#define UNW_DEC_GR_MEM(fmt,m,arg)		desc_gr_mem(m,arg)#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg)	desc_mem_stack_f(t,s,arg)#define UNW_DEC_MEM_STACK_V(fmt,t,arg)		desc_mem_stack_v(t,arg)#define UNW_DEC_REG_GR(fmt,r,d,arg)		desc_reg_gr(r,d,arg)#define UNW_DEC_REG_PSPREL(fmt,r,o,arg)		desc_reg_psprel(r,o,arg)#define UNW_DEC_REG_SPREL(fmt,r,o,arg)		desc_reg_sprel(r,o,arg)#define UNW_DEC_REG_WHEN(fmt,r,t,arg)		desc_reg_when(r,t,arg)#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)	desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)	desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)#define UNW_DEC_PRIUNAT_GR(fmt,r,arg)		desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg)	desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg)	desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)#define UNW_DEC_RP_BR(fmt,d,arg)		desc_rp_br(d,arg)#define UNW_DEC_SPILL_BASE(fmt,o,arg)		desc_spill_base(o,arg)#define UNW_DEC_SPILL_MASK(fmt,m,arg)		(m = desc_spill_mask(m,arg))/* * body descriptors: */#define UNW_DEC_EPILOGUE(fmt,t,c,arg)		desc_epilogue(t,c,arg)#define UNW_DEC_COPY_STATE(fmt,l,arg)		desc_copy_state(l,arg)#define UNW_DEC_LABEL_STATE(fmt,l,arg)		desc_label_state(l,arg)/* * general unwind descriptors: */#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg)	desc_spill_reg_p(p,t,a,x,y,arg)#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg)	desc_spill_reg_p(0,t,a,x,y,arg)#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg)	desc_spill_psprel_p(p,t,a,o,arg)#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg)	desc_spill_psprel_p(0,t,a,o,arg)#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg)	desc_spill_sprel_p(p,t,a,o,arg)#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg)	desc_spill_sprel_p(0,t,a,o,arg)#define UNW_DEC_RESTORE_P(f,p,t,a,arg)		desc_restore_p(p,t,a,arg)#define UNW_DEC_RESTORE(f,t,a,arg)		desc_restore_p(0,t,a,arg)

⌨️ 快捷键说明

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