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

📄 unwind.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
}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_t(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_t(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_t(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_labeled_state *ls;	for (ls = sr->labeled_states; ls; ls = ls->next) {		if (ls->label == label) {			free_state_stack(&sr->curr);			memcpy(&sr->curr, &ls->saved_state, sizeof(sr->curr));			sr->curr.next = dup_state_stack(ls->saved_state.next);			return;		}	}	printk(KERN_ERR "unwind: failed to find state labeled 0x%lx\n", label);}static inline voiddesc_label_state (unw_word label, struct unw_state_record *sr){	struct unw_labeled_state *ls;	ls = alloc_labeled_state();	if (!ls) {		printk(KERN_ERR "unwind.desc_label_state(): out of memory\n");		return;	}	ls->label = label;	memcpy(&ls->saved_state, &sr->curr, sizeof(ls->saved_state));	ls->saved_state.next = dup_state_stack(sr->curr.next);	/* insert into list of labeled states: */	ls->next = sr->labeled_states;	sr->labeled_states = ls;}/* * 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_t(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 = UNW_WHEN_NEVER;	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_t(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_t(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_t(int, t, sr->region_len - 1);	r->val = 4*spoff;}#define UNW_DEC_BAD_CODE(code)			printk(KERN_ERR "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)#include "unwind_decoder.c"/* Unwind scripts. */static inline unw_hash_index_thash (unsigned long ip){#	define hashmagic	0x9e3779b97f4a7c16UL	/* based on (sqrt(5)/2-1)*2^64 */	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);#undef hashmagic}static inline longcache_match (struct unw_script *script, unsigned long ip, unsigned long pr){	read_lock(&script->lock);	if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0)		/* keep the read lock... */		return 1;	read_unlock(&script->lock);	return 0;}static inline struct unw_script *script_lookup (struct unw_frame_info *info){	struct unw_script *script = unw.cache + info->hint;	unsigned short index;	unsigned long ip, pr;	if (UNW_DEBUG_ON(0))		return NULL;	/* Always regenerate scripts in debug mode */	STAT(++unw.stat.cache.lookups);	ip = info->ip;	pr = info->pr;	if (cache_match(script, ip, pr)) {		STAT(++unw.stat.cache.hinted_hits);		return script;	}	index = unw.hash[hash(ip)];	if (index >= UNW_CACHE_SIZE)		return NULL;	script = unw.cache + index;	while (1) {		if (cache_match(script, ip, pr)) {			/* update hint; no locking required as single-word writes are atomic */			STAT(++unw.stat.cache.normal_hits);			unw.cache[info->prev_script].hint = script - unw.cache;			return script;		}		if (script->coll_chain >= UNW_HASH_SIZE)			return NULL;		script = unw.cache + script->coll_chain;		STAT(++unw.stat.cache.collision_chain_traversals);	}}/* * On returning, a write lock for the SCRIPT is still being held. */static inline struct unw_script *script_new (unsigned long ip){	struct unw_script *script, *prev, *tmp;	unw_hash_index_t index;	unsigned short head;	STAT(++unw.stat.script.news);	/*	 * Can't (easily) use cmpxchg() here because of ABA problem	 * that is intrinsic in cmpxchg()...	 */	head = unw.lru_head;	script = unw.cache + head;	unw.lru_head = script->lru_chain;	/*	 * We'd deadlock here if we interrupted a thread that is holding a read lock on	 * script->lock.  Thus, if the write_trylock() fails, we simply bail out.  The	 * alternative would be to disable interrupts whenever we hold a read-lock, but	 * that seems silly.	 */	if (!write_trylock(&script->lock))		return NULL;	/* re-insert script at the tail of the LRU chain: */	unw.cache[unw.lru_tail].lru_chain = head;	unw.lru_tail = head;	/* remove the old script from the hash table (if it's there): */	if (script->ip) {		index = hash(script->ip);		tmp = unw.cache + unw.hash[index];		prev = NULL;		while (1) {			if (tmp == script) {				if (prev)					prev->coll_chain = tmp->coll_chain;				else					unw.hash[index] = tmp->coll_chain;				break;			} else				prev = tmp;			if (tmp->coll_chain >= UNW_CACHE_SIZE)			/* old script wasn't in the hash-table */				break;			tmp = unw.cache + tmp->coll_chain;		}	}	/* enter new script in the hash table */	index = hash(ip);	script->coll_chain = unw.hash[index];	unw.hash[index] = script - unw.cache;	script->ip = ip;	/* set new IP while we're holding the locks */	STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions);	script->flags = 0;	script->hint = 0;	script->count = 0;	return script;}static voidscript_finalize (struct unw_script *script, struct unw_state_record *sr){	script->pr_mask = sr->pr_mask;	script->pr_val = sr->pr_val;	/*	 * We could down-grade our write-lock on script->lock here but	 * the rwlock API doesn't offer atomic lock downgrading, so	 * we'll just keep the write-lock and release it later when	 * we're done using the script.	 */}static inline voidscript_emit (struct unw_script *script, struct unw_insn insn){	if (script->count >= UNW_MAX_SCRIPT_LEN) {		UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",			__FUNCTION__, UNW_MAX_SCRIPT_LEN);		return;	}	script->insn[script->count++] = insn;}static inline voidemit_nat_info (struct unw_state_record *sr, int i, struct unw_script *script){	struct unw_reg_info *r = sr->curr.reg + i;	enum unw_insn_opcode opc;	struct unw_insn insn;	unsigned long val = 0;	switch (r->where) {	      case UNW_WHERE_GR:		if (r->val >= 32) {			/* register got spilled to a stacked register */			opc = UNW_INSN_SETNAT_TYPE;			val = UNW_NAT_REGSTK;		} else			/* register got spilled to a scratch register */			opc = UNW_INSN_SETNAT_MEMSTK;		break;	      case UNW_WHERE_FR:		opc = UNW_INSN_SETNAT_TYPE;		val = UNW_NAT_VAL;		break;	      case UNW_WHERE_BR:		opc = UNW_INSN_SETNAT_TYPE;		val = UNW_NAT_NONE;		break;	      case UNW_WHERE_PSPREL:	      case UNW_WHERE_SPREL:		opc = UNW_INSN_SETNAT_MEMSTK;		break;	      default:		UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",			   __FUNCTION__, r->where);		return;	}	insn.opc = opc;	insn.dst = unw.preg_index[i];	insn.val = val;	script_emit(script, insn);}static voidcompile_reg (struct unw_state_record *sr, int i, struct unw_script *script){	struct unw_reg_info *r = sr->curr.reg + i;	enum unw_insn_opcode opc;	unsigned long val, rval;	struct unw_insn insn;	long need_nat_info;

⌨️ 快捷键说明

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