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

📄 fudge.c.386

📁 cfront是最开始c++语言到C语言的转换工具
💻 386
字号:
/*ident	"@(#)cls4:lib/task/task/fudge.c.386	1.1" *//******************************************************************************* C++ source for the C++ Language System, Release 3.0.  This productis a new release of the original cfront developed in the computerscience research center of AT&T Bell Laboratories.Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc.Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX SystemLaboratories, Inc.  The copyright notice above does not evidenceany actual or intended publication of such source code.*******************************************************************************/#include <task.h>#include "hw_stack.h"// Intel 386 frame fudger/* careful -- stack frame not self-describing */// STACK GROWS DOWN// We define a mask in which FrameLayout can record which regs are saved.// We only care about the non-scratch regs edi, esi, ebx.const short REG_EDI	= 0x1;const short REG_ESI	= 0x2;const short REG_EBX	= 0x4;#define	ALL_REGS_SAVED(m)	((short)(m) == 0x0007)const int		OPCODE_SIZE	= 1;const MACHINE_BYTE	CALL_INSTR	= 0xe8;const int		CALL_SIZE	= 5;const MACHINE_BYTE	JMP_SHORT	= 0xeb;const MACHINE_BYTE	JMP_DISPL	= 0xe9;// assumes we don't need to worry about jump near indirect (0xff)#define IS_JMP_INSTR(instr)					\	((MACHINE_BYTE)(instr) == (MACHINE_BYTE)JMP_SHORT ||	\	 (MACHINE_BYTE)(instr) == (MACHINE_BYTE)JMP_DISPL)const MACHINE_BYTE	PUSH_EBP_INSTR = 0x55;const int		PUSH_SIZE = 1;const MACHINE_BYTE	MOV_INSTR = 0x8b;const int		MOV_SIZE = 2;const MACHINE_BYTE	SUB_INSTR = 0x83;const int		SUB_SIZE = 3;const MACHINE_BYTE	PUSH_EDI_INSTR = 0x57;const MACHINE_BYTE	PUSH_ESI_INSTR = 0x56;const MACHINE_BYTE	PUSH_EBX_INSTR = 0x53;#define	IS_PUSH_REG_INSTR(instp)		\	((*((MACHINE_BYTE*)(instp)) & 0xf0) == 0x50)#define IS_SET_EBP_INSTR(instp)			\	(((*(instp)) == MOV_INSTR) && (*((MACHINE_BYTE*)(instp) + 1) == 0xec))#define	IS_SUB_ESP_INSTR(instp)				\	((*((MACHINE_BYTE*)(instp)) == SUB_INSTR)	\	&& (*((MACHINE_BYTE*)(instp) + 1) == 0xec))int*	Skip_pc_p;	// global to hold fudged return pc.			// See comments in hw_stack.c./* Given a pointer to a call instruction, yield a pointer to * the called function */unsigned intcall_dst_ptr(MACHINE_BYTE* callp){	/*	 * On the Intel 386, the call instruction is: call displ	 * where the displacement is always relative to the pc.	 */	MACHINE_BYTE* dst_op_p = callp + OPCODE_SIZE;	int offset = 0;	// bytes are in reverse order, must flip positions	offset = dst_op_p[0]       |		 dst_op_p[1] <<  8 |		 dst_op_p[2] << 16 |		 dst_op_p[3] << 24;	return (unsigned int)(callp + CALL_SIZE + offset);}FrameLayout::FrameLayout(int* fp){	mask = 0;	unsigned int*	return_pc = (unsigned int*)OLD_PC(fp);	/*	 * find the starting address of the function.  The idea is that the	 * instruction immediately before the return address must be the	 * function call.	 */	MACHINE_BYTE*	callp = (MACHINE_BYTE*)return_pc - CALL_SIZE;	if (*callp != CALL_INSTR)		object::task_error(E_FUNCS, (object*)0);	MACHINE_BYTE* func_addr = (MACHINE_BYTE*) call_dst_ptr(callp);	/* If first instruction is jmp (-O not used), add displacement to pc	 * to get to function prologue.	 * Function prologue should be:	 *	pushl	%ebp	 *	movl	%esp,%ebp	 *	subl	XXX,%esp	/ XXX is the offset we want	 *	pushl	%eXX		/ a push instruction for each saved reg	 *				/ (sometimes first push is of scratch	 *				/ reg, and then that is the offset)	 *	/ stop when no more push instructions, or have saved all regs	 */	if (IS_JMP_INSTR(*func_addr)) {		int displ;		if (*func_addr == JMP_SHORT) {	// 1 byte displacement			displ = func_addr[1];			func_addr += 2;		// next instruction		} else {	// JMP_DISPL, 4 byte displacement				// bytes reversed			displ = func_addr[1]       |				func_addr[2] <<  8 |				func_addr[3] << 16 |				func_addr[4] << 24;			func_addr += 5;		// next instruction		}		func_addr += displ;	// jmp destination	}	if ((*func_addr == PUSH_EBP_INSTR)	    && (IS_SET_EBP_INSTR(func_addr + PUSH_SIZE))) {		func_addr += MOV_SIZE + PUSH_SIZE;		if (IS_SUB_ESP_INSTR(func_addr)) {			offset = func_addr[2] / 4;			func_addr += SUB_SIZE;		} else {	// assume no automatics to be allocated			offset = 0;		}	} else {		object::task_error(E_FUNCS, (object*)0);	}	while (IS_PUSH_REG_INSTR(func_addr) && (! ALL_REGS_SAVED(mask))) {		if (*func_addr == PUSH_EDI_INSTR) {			mask |= REG_EDI;			func_addr += PUSH_SIZE;		} else if (*func_addr == PUSH_ESI_INSTR) {			mask |= REG_ESI;			func_addr += PUSH_SIZE;		} else if (*func_addr == PUSH_EBX_INSTR) {			mask |= REG_EBX;			func_addr += PUSH_SIZE;		} else	{			// Compiler might push a scratch reg before any non-			// scratch regs to reserve space for automatics.			if (mask != 0) {				// if non-scratch regs already saved,				// then this is not an offset				break;			} else {				offset += 1;				func_addr += PUSH_SIZE;			}		}	}	}/* * Fudge frame of function-defined-by-f_fp (called "f" below) * so that that function returns to its grandparent, * in particular, so a parent task returns to the function that * called the derived constructor, skipping the derived constructor; * the child will return to the derived constructor, which is its "main." * To do this we will overwrite the old fp and pc (those saved by * f) with the old-old ones (those saved by f's caller), * and we will overwrite the register save area with registers saved by  * f's caller (referred to as "skip" below). * * There are 2 register-save cases to deal with: *     1. skip_n_saved <= f_n_saved *     3. skip_n_saved >  f_n_saved * * These are handled as follows: *     1. copy the saved skip_regs over the corresponding f_regs, *        leaving any additional saved f_regs intact. *        f's epilogue instructions will be correct. *     2. f's epilogue instructions will restore too few regs, *	  must take special care to see that the extras are restored properly. *	  -Copy saved skip_regs over any corresponding f_regs, *	  -If fudge_return saved more regs than f did, then *	   copy saved extra saved skip_regs over any corresponding fudge_regs, *	  -If more extra skip_regs (not saved by either f or fudge_return, *	   and therefore not used by either) remain, restore them explicitly. *	   They will not be disturbed by the return from fudge_return or f. */voidtask::fudge_return(int* f_fp){	register int*	fp = f_fp;		// fp of frame-to-be-fudged	FrameLayout	lo(fp);			// frame to be fudged	register int*	skip_fp = (int*)OLD_FP(fp); // fp for f's caller (skip)	FrameLayout	skip_lo(skip_fp);	// frame for skip	register int*	fr_fp = FP();		// fp for fudge_return	FrameLayout	fr_lo(fr_fp);		// frame for fudge_return	OLD_PC(fp) = (int)&fudge_sp;	// task::task will return through					// fudge_sp, which will reset the sp					// to point at the return-pc in					// skip's frame	// copy old fp	OLD_FP(fp) = OLD_FP(skip_fp);	// now copy saved registers	// copy any saved skip regs over corresponding f regs; if there isn't	// a corresponding f reg, copy over corresponding fudge_return reg;	// if there isn't a corresponding fr_reg, restore it explicitly.	register int*	to = FIRST_SAVED_REG_P(fp, lo.offset);	register int*	from = FIRST_SAVED_REG_P(skip_fp, skip_lo.offset);	register int*	fr_to = FIRST_SAVED_REG_P(fr_fp, fr_lo.offset);	for (register short m = 1; m != 0x08; m <<=1) {		if (m & lo.mask) {			if (m & skip_lo.mask) {				*to-- = *from--;				if (m & fr_lo.mask) fr_to--;			} else {  // nothing to copy				to--;				if (m & fr_lo.mask) fr_to--;			}		} else if (m & skip_lo.mask) {			// No slot for *from in f's frame			if (m & fr_lo.mask) {  // copy to fudge_return's frame				*fr_to-- = *from--;			} else {				// Not used in f or fudge_return;				// restore explicitly				switch(m)	{				case REG_EDI:					set_edi(from--);					break;				case REG_ESI:					set_esi(from--);					break;				case REG_EBX:					set_ebx(from--);					break;				default:					// Oops--don't expect other regs					// to be saved					from--;					task_error(E_REGMASK, this);					break;				}			}		}	}}

⌨️ 快捷键说明

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