1. 程式人生 > >基於PPC64架構 Linux 核心訊號處理過程棧處理分析

基於PPC64架構 Linux 核心訊號處理過程棧處理分析

handle_rt_signal64主要負責訊號處理棧處理分析,如下圖所示

int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
	struct rt_sigframe __user *frame;
	unsigned long newsp = 0;
    unsigned long oldsp = 0;
	long err = 0;

    /* 從regs->gpr[1]讀取當前棧指標,往下增長sizeof(*frame),0x960Byte */
	frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 0);
	if (unlikely(frame == NULL))
		goto badframe;

	err |= __put_user(&frame->info, &frame->pinfo);
	err |= __put_user(&frame->uc, &frame->puc);
	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
	if (err)
		goto badframe;
    /* 個人增加的除錯程式碼,純粹列印 */
    oldsp = regs->gpr[1];

	/* Create the ucontext.  */
	err |= __put_user(0, &frame->uc.uc_flags);
    /* 儲存當前sp到使用者棧,後續需要從這裡恢復原來的內容 */
	err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
	if (MSR_TM_ACTIVE(regs->msr)) {
		/* The ucontext_t passed to userland points to the second
		 * ucontext_t (for transactional state) with its uc_link ptr.
		 */
		err |= __put_user(&frame->uc_transact, &frame->uc.uc_link);
		err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
					    &frame->uc_transact.uc_mcontext,
					    regs, ksig->sig,
					    NULL,
					    (unsigned long)ksig->ka.sa.sa_handler);
	} else
#endif
	{
		err |= __put_user(0, &frame->uc.uc_link);
        /* 儲存當前訊號上下文到使用者棧空間,後續需要從這裡恢復原來的內容 */
		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, ksig->sig,
					NULL, (unsigned long)ksig->ka.sa.sa_handler,
					1);
	}
	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
	if (err)
		goto badframe;

	/* Make sure signal handler doesn't get spurious FP exceptions */
	current->thread.fp_state.fpscr = 0;

	/* Set up to return from userspace. */
	if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
        /* link是函式返回地址LR,訊號處理handle執行return後地址,此處使用VDSO */
		regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
	} else {
		err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
		if (err)
			goto badframe;
		regs->link = (unsigned long) &frame->tramp[0];
	}

	/* Allocate a dummy caller frame for the signal handler. */
    /* 在frame再往下構建一個128B的虛擬棧,個人認為是作為安全空隙,避免被踩?*/
	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
	err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);

	/* Set up "regs" so we "return" to the signal handler. */
	if (is_elf2_task()) {
		regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
		regs->gpr[12] = regs->nip;
	} else {
		/* Handler is *really* a pointer to the function descriptor for
		 * the signal routine.  The first entry in the function
		 * descriptor is the entry address of signal and the second
		 * entry is the TOC value we need to use.
		 */
		func_descr_t __user *funct_desc_ptr =
			(func_descr_t __user *) ksig->ka.sa.sa_handler;
        /* 設定regs->nip為使用者訊號處理函式地址,一旦從核心返回,直接執行 */
		err |= get_user(regs->nip, &funct_desc_ptr->entry);
		err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
	}

	/* enter the signal handler in native-endian mode */
	regs->msr &= ~MSR_LE;
	regs->msr |= (MSR_KERNEL & MSR_LE);
    /* 設定使用者訊號處理函式的棧地址 */
	regs->gpr[1] = newsp;
    /* 訊號處理函式的第一個入參,訊號值 */
	regs->gpr[3] = ksig->sig;
	regs->result = 0;
	if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
         /* 如果指定SA_SIGINFO,訊號處理函式的第二個入參 */
		err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo);
         /* 如果指定SA_SIGINFO,訊號處理函式的第三個入參 */
		err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc);
		regs->gpr[6] = (unsigned long) frame;
	} else {
		regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext;
	}
	if (err)
		goto badframe;
    /* 除錯列印原來的oldsp,frame,newsp, 新的link,新的nip */
    pr_info("oldsp=%#lx, oldsp=%#lx, frame=%#lx, newsp=%#lx, regs->link=%#lx,regs->nip=%#lx",  oldsp, frame, newsp, regs->link,regs->nip);
	return 0;

badframe:
	if (show_unhandled_signals)
		printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
				   current->comm, current->pid, "setup_rt_frame",
				   (long)frame, regs->nip, regs->link);

	return 1;
}

在handle_rt_signal64增加了列印後,測試用例註冊一個訊號,訊號處理函式使用嵌入彙編方式讀取R1暫存器(當前SP),

從當前SP開始列印一堆資料,如下所示。當前SP地址是0x3ffffe75d1c0與newsp又相差144B,為什麼呢?請繼續往下看。

oldsp=0x3ffffe75dc30, frame=0x3ffffe75d2d0, newsp=0x3ffffe75d250, regs->link=0x3fff8a740478, regs->nip=0x10000964

add=0x3ffffe75d1c0, val=0x3ffffe75d250
add=0x3ffffe75d1c8, val=0x3d8
add=0x3ffffe75d1d0, val=0x100009e4
add=0x3ffffe75d1d8, val=0x400000010
add=0x3ffffe75d1e0, val=0x1474e5500
add=0x3ffffe75d1e8, val=0x100192d8
add=0x3ffffe75d1f0, val=0x600000020
add=0x3ffffe75d1f8, val=0x3ffffe75d1f0
add=0x3ffffe75d200, val=0x3ffffe75d1f0
add=0x3ffffe75d208, val=0x27
add=0x3ffffe75d210, val=0
add=0x3ffffe75d218, val=0x3ffffe75d210
add=0x3ffffe75d220, val=0x3ffffe75d210
add=0x3ffffe75d228, val=0x3ffffe75d1c0
add=0x3ffffe75d230, val=0xe01040200
add=0x3ffffe75d238, val=0x3ffffe75d1c0
add=0x3ffffe75d240, val=0x67406c2d820a1180
add=0x3ffffe75d248, val=0xffffffff
add=0x3ffffe75d250, val=0x3ffffe75dc30
add=0x3ffffe75d258, val=0x2200c081290a042
add=0x3ffffe75d260, val=0x3fff8a740478
add=0x3ffffe75d268, val=0xcc28013980000a0a
add=0x3ffffe75d270, val=0xc28081240818440
add=0x3ffffe75d278, val=0x8008518000000044
add=0x3ffffe75d280, val=0xcd042041d
add=0x3ffffe75d288, val=0x80003018b5000001
add=0x3ffffe75d290, val=0x1041090022100260
add=0x3ffffe75d298, val=0x4712a92850000501
add=0x3ffffe75d2a0, val=0x440980482000028
add=0x3ffffe75d2a8, val=0x240020054e01000
add=0x3ffffe75d2b0, val=0x80164430c11002
add=0x3ffffe75d2b8, val=0x1c00021004240000
add=0x3ffffe75d2c0, val=0x80018000f90a380
add=0x3ffffe75d2c8, val=0x4406280080012010
add=0x3ffffe75d2d0, val=0
add=0x3ffffe75d2d8, val=0
add=0x3ffffe75d2e0, val=0
add=0x3ffffe75d2e8, val=0x2fe75d9e8
add=0x3ffffe75d2f0, val=0
add=0x3ffffe75d2f8, val=0
add=0x3ffffe75d300, val=0
add=0x3ffffe75d308, val=0x3fff8a77ea10
add=0x3ffffe75d310, val=0x3ffffe75d7e0
add=0x3ffffe75d318, val=0x3fff8a534ec8
add=0x3ffffe75d320, val=0x5
add=0x3ffffe75d328, val=0x3ffffe75d7b0
add=0x3ffffe75d330, val=0x3ffffe75d9f8
add=0x3ffffe75d338, val=0x3fff8a77b4d8
add=0x3ffffe75d340, val=0x3ffffe75d810
add=0x3ffffe75d348, val=0x3fff8a55fe10
add=0x3ffffe75d350, val=0x1
add=0x3ffffe75d358, val=0x3fff8a5361fb
add=0x3ffffe75d360, val=0x10
add=0x3ffffe75d368, val=0x3ffffe75d9c0
add=0x3ffffe75d370, val=0x3ffffe75d3f0
add=0x3ffffe75d378, val=0x420042228a70de10
add=0x3ffffe75d380, val=0x3fff8a7592e0
add=0x3ffffe75d388, val=0x3fff8a57eae4
add=0x3ffffe75d390, val=0x18
add=0x3ffffe75d398, val=0xcfe75d9c0
add=0x3ffffe75d3a0, val=0x10011260
add=0x3ffffe75d3a8, val=0x480042228a73de00
add=0x3ffffe75d3b0, val=0x3ffffe75d3b8
add=0x3ffffe75d3b8, val=0xa2
add=0x3ffffe75d3c0, val=0x3ffffe75dc30
add=0x3ffffe75d3c8, val=0x3fff8a727c10
add=0x3ffffe75d3d0, val=0x4
add=0x3ffffe75d3d8, val=0x3ffffe75de38
add=0x3ffffe75d3e0, val=0x88000248
add=0x3ffffe75d3e8, val=0x4000
add=0x3ffffe75d3f0, val=0x3fff8a5c3ef8
add=0x3ffffe75d3f8, val=0x8202f000
add=0x3ffffe75d400, val=0
add=0x3ffffe75d408, val=0
add=0x3ffffe75d410, val=0
add=0x3ffffe75d418, val=0
add=0x3ffffe75d420, val=0x3fff8a780750
add=0x3ffffe75d428, val=0
add=0x3ffffe75d430, val=0
add=0x3ffffe75d438, val=0
add=0x3ffffe75d440, val=0
add=0x3ffffe75d448, val=0
add=0x3ffffe75d450, val=0
add=0x3ffffe75d458, val=0
add=0x3ffffe75d460, val=0
add=0x3ffffe75d468, val=0
add=0x3ffffe75d470, val=0
add=0x3ffffe75d478, val=0
add=0x3ffffe75d480, val=0
add=0x3ffffe75d488, val=0
add=0x3ffffe75d490, val=0x3fff8a77ee20
add=0x3ffffe75d498, val=0x3ffffe75dd38
add=0x3ffffe75d4a0, val=0x10000
add=0x3ffffe75d4a8, val=0x3ffffe75ddb8
add=0x3ffffe75d4b0, val=0xffffffff
add=0x3ffffe75d4b8, val=0x3fff8a648754
add=0x3ffffe75d4c0, val=0x8202d000
add=0x3ffffe75d4c8, val=0x3ffffe75de38
add=0x3ffffe75d4d0, val=0
add=0x3ffffe75d4d8, val=0x3fff8a64854c
add=0x3ffffe75d4e0, val=0
add=0x3ffffe75d4e8, val=0x98000248
add=0x3ffffe75d4f0, val=0x1
add=0x3ffffe75d4f8, val=0xc00
add=0x3ffffe75d500, val=0x3fff8a648440
add=0x3ffffe75d508, val=0
add=0x3ffffe75d510, val=0xfffffffffffffffc
add=0x3ffffe75d518, val=0x3fff8a781b10
add=0x3ffffe75d520, val=0
add=0x3ffffe75d528, val=0x3fff8a781ae8
add=0x3ffffe75d530, val=0x3ffffe75d6a0
add=0x3ffffe75d538, val=0
add=0x3ffffe75d540, val=0
add=0x3ffffe75d548, val=0
add=0x3ffffe75d550, val=0
add=0x3ffffe75d558, val=0
add=0x3ffffe75d560, val=0
add=0x3ffffe75d568, val=0
add=0x3ffffe75d570, val=0
add=0x3ffffe75d578, val=0
add=0x3ffffe75d580, val=0
add=0x3ffffe75d588, val=0
add=0x3ffffe75d590, val=0
add=0x3ffffe75d598, val=0
add=0x3ffffe75d5a0, val=0
add=0x3ffffe75d5a8, val=0
add=0x3ffffe75d5b0, val=0
add=0x3ffffe75d5b8, val=0
add=0x3ffffe75d5c0, val=0
add=0x3ffffe75d5c8, val=0
add=0x3ffffe75d5d0, val=0
add=0x3ffffe75d5d8, val=0
add=0x3ffffe75d5e0, val=0
add=0x3ffffe75d5e8, val=0
add=0x3ffffe75d5f0, val=0
add=0x3ffffe75d5f8, val=0
add=0x3ffffe75d600, val=0
add=0x3ffffe75d608, val=0
add=0x3ffffe75d610, val=0
add=0x3ffffe75d618, val=0
add=0x3ffffe75d620, val=0
add=0x3ffffe75d628, val=0
add=0x3ffffe75d630, val=0
add=0x3ffffe75d638, val=0xfff8000000000000
add=0x3ffffe75d640, val=0x3ffffe75d650
add=0x3ffffe75d648, val=0x3fff8a77b000
add=0x3ffffe75d650, val=0
add=0x3ffffe75d658, val=0
add=0x3ffffe75d660, val=0
add=0x3ffffe75d668, val=0
add=0x3ffffe75d670, val=0
add=0x3ffffe75d678, val=0
add=0x3ffffe75d680, val=0
add=0x3ffffe75d688, val=0
add=0x3ffffe75d690, val=0
add=0x3ffffe75d698, val=0
add=0x3ffffe75d6a0, val=0
add=0x3ffffe75d6a8, val=0
add=0x3ffffe75d6b0, val=0
add=0x3ffffe75d6b8, val=0
add=0x3ffffe75d6c0, val=0
add=0x3ffffe75d6c8, val=0
add=0x3ffffe75d6d0, val=0
add=0x3ffffe75d6d8, val=0
add=0x3ffffe75d6e0, val=0
add=0x3ffffe75d6e8, val=0
add=0x3ffffe75d6f0, val=0
add=0x3ffffe75d6f8, val=0
add=0x3ffffe75d700, val=0
add=0x3ffffe75d708, val=0
add=0x3ffffe75d710, val=0
add=0x3ffffe75d718, val=0
add=0x3ffffe75d720, val=0
add=0x3ffffe75d728, val=0
add=0x3ffffe75d730, val=0
add=0x3ffffe75d738, val=0
add=0x3ffffe75d740, val=0x404040404040404
add=0x3ffffe75d748, val=0x404040404040404
add=0x3ffffe75d750, val=0x1020304050607
add=0x3ffffe75d758, val=0x8090a0b0c0d0e0f
add=0x3ffffe75d760, val=0
add=0x3ffffe75d768, val=0x3fff8a77eea0
add=0x3ffffe75d770, val=0
add=0x3ffffe75d778, val=0
add=0x3ffffe75d780, val=0
add=0x3ffffe75d788, val=0
add=0x3ffffe75d790, val=0
add=0x3ffffe75d798, val=0
add=0x3ffffe75d7a0, val=0
add=0x3ffffe75d7a8, val=0
add=0x3ffffe75d7b0, val=0
add=0x3ffffe75d7b8, val=0
add=0x3ffffe75d7c0, val=0
add=0x3ffffe75d7c8, val=0
add=0x3ffffe75d7d0, val=0
add=0x3ffffe75d7d8, val=0
add=0x3ffffe75d7e0, val=0
add=0x3ffffe75d7e8, val=0
add=0x3ffffe75d7f0, val=0
add=0x3ffffe75d7f8, val=0
add=0x3ffffe75d800, val=0
add=0x3ffffe75d808, val=0
add=0x3ffffe75d810, val=0
add=0x3ffffe75d818, val=0
add=0x3ffffe75d820, val=0
add=0x3ffffe75d828, val=0
add=0x3ffffe75d830, val=0
add=0x3ffffe75d838, val=0
add=0x3ffffe75d840, val=0
add=0x3ffffe75d848, val=0
add=0x3ffffe75d850, val=0
add=0x3ffffe75d858, val=0x10000
add=0x3ffffe75d860, val=0xffffffff00000000
add=0x3ffffe75d868, val=0x3fff8a779000
add=0x3ffffe75d870, val=0x3fff8a779750
add=0x3ffffe75d878, val=0xf
add=0x3ffffe75d880, val=0x3ffffe75d920
add=0x3ffffe75d888, val=0x3ffffe75d940
add=0x3ffffe75d890, val=0x3fff8a747448
add=0x3ffffe75d898, val=0x3fff8a780d60
add=0x3ffffe75d8a0, val=0x3ffffe75d920
add=0x3ffffe75d8a8, val=0xffffffff
add=0x3ffffe75d8b0, val=0
add=0x3ffffe75d8b8, val=0
add=0x3ffffe75d8c0, val=0
add=0x3ffffe75d8c8, val=0
add=0x3ffffe75d8d0, val=0
add=0x3ffffe75d8d8, val=0
add=0x3ffffe75d8e0, val=0
add=0x3ffffe75d8e8, val=0
add=0x3ffffe75d8f0, val=0
add=0x3ffffe75d8f8, val=0
add=0x3ffffe75d900, val=0
add=0x3ffffe75d908, val=0
add=0x3ffffe75d910, val=0x3fff8a5a9e08
add=0x3ffffe75d918, val=0x1b9708
add=0x3ffffe75d920, val=0x3fff8a567000
add=0x3ffffe75d928, val=0x3fff8a720708
add=0x3ffffe75d930, val=0x3ffffe75dee8
add=0x3ffffe75d938, val=0x3fff8a77b000
add=0x3ffffe75d940, val=0x3ffffe75d9f0
add=0x3ffffe75d948, val=0x22000482fe75d950
add=0x3ffffe75d950, val=0x3fff8a75af4c
add=0x3ffffe75d958, val=0x420222448a77d718
add=0x3ffffe75d960, val=0x3fff8a756ffc
add=0x3ffffe75d968, val=0
add=0x3ffffe75d970, val=0x3ffffe75da10
add=0x3ffffe75d978, val=0x3fff8a788278
add=0x3ffffe75d980, val=0x3fff8a7803c8
add=0x3ffffe75d988, val=0x3fff8a788278
add=0x3ffffe75d990, val=0x3ffffe75da10
add=0x3ffffe75d998, val=0x3ffffe75d9a8
add=0x3ffffe75d9a0, val=0x3ffffe75d2d0
add=0x3ffffe75d9a8, val=0xc00000000
add=0x3ffffe75d9b0, val=0xfffffffe8a747448
add=0x3ffffe75d9b8, val=0
add=0x3ffffe75d9c0, val=0
add=0x3ffffe75d9c8, val=0x3ffffe75dbd0
add=0x3ffffe75d9d0, val=0x3fff8a780cd0
add=0x3ffffe75d9d8, val=0x3fff8a7803c8
add=0x3ffffe75d9e0, val=0x3ffffe75dee8
add=0x3ffffe75d9e8, val=0x105cf61e
add=0x3ffffe75d9f0, val=0x7aa
add=0x3ffffe75d9f8, val=0x3fff8a77ba70
add=0x3ffffe75da00, val=0x2
add=0x3ffffe75da08, val=0x3fff8a77b000
add=0x3ffffe75da10, val=0x3ffffe75db80
add=0x3ffffe75da18, val=0x10033000
add=0x3ffffe75da20, val=0x3fff8a754530
add=0x3ffffe75da28, val=0x3ffffe75db70
add=0x3ffffe75da30, val=0x3fff8a77da90
add=0x3ffffe75da38, val=0x1
add=0x3ffffe75da40, val=0x3ffffe75db88
add=0x3ffffe75da48, val=0x3fff8a77d718
add=0x3ffffe75da50, val=0x1
add=0x3ffffe75da58, val=0x3fff8a77bbf0
add=0x3ffffe75da60, val=0x3fff8a714900
add=0x3ffffe75da68, val=0x3ffffe75dbd0
add=0x3ffffe75da70, val=0x3ffffe75dbf0
add=0x3ffffe75da78, val=0x3ffffe75dbd0
add=0x3ffffe75da80, val=0x3ffffe75dc30
add=0x3ffffe75da88, val=0x3ffffe75daa0
add=0x3ffffe75da90, val=0x3ffffe75daa8
add=0x3ffffe75da98, val=0x3fff8a721728
add=0x3ffffe75daa0, val=0
add=0x3ffffe75daa8, val=0
add=0x3ffffe75dab0, val=0
add=0x3ffffe75dab8, val=0
add=0x3ffffe75dac0, val=0
add=0x3ffffe75dac8, val=0
add=0x3ffffe75dad0, val=0x3fff8a77ee20
add=0x3ffffe75dad8, val=0x3fff8a76a5d0
add=0x3ffffe75dae0, val=0x3fff8a56a8b4
add=0x3ffffe75dae8, val=0
add=0x3ffffe75daf0, val=0
add=0x3ffffe75daf8, val=0
add=0x3ffffe75db00, val=0
add=0x3ffffe75db08, val=0
add=0x3ffffe75db10, val=0x3fff8a7803c8
add=0x3ffffe75db18, val=0x3ffffe75dc60
add=0x3ffffe75db20, val=0x3fff8a7818c0
add=0x3ffffe75db28, val=0x1
add=0x3ffffe75db30, val=0x3ffffe75dc78
add=0x3ffffe75db38, val=0x3fff8a781548
add=0x3ffffe75db40, val=0x1
add=0x3ffffe75db48, val=0x3fff8a77bab8
add=0x3ffffe75db50, val=0x3ffffe75dd80
add=0x3ffffe75db58, val=0x10000447
add=0x3ffffe75db60, val=0
add=0x3ffffe75db68, val=0x3fff8a7818c0
add=0x3ffffe75db70, val=0x105cf61e
add=0x3ffffe75db78, val=0x3ffffe75db80
add=0x3ffffe75db80, val=0x3ffffe75dd10
add=0x3ffffe75db88, val=0x22042444ffffffff
add=0x3ffffe75db90, val=0x3fff8a754d7c
add=0x3ffffe75db98, val=0
add=0x3ffffe75dba0, val=0x30
add=0x3ffffe75dba8, val=0x5b
add=0x3ffffe75dbb0, val=0x6e
add=0x3ffffe75dbb8, val=0x77
add=0x3ffffe75dbc0, val=0x3ffffe75dc78
add=0x3ffffe75dbc8, val=0
add=0x3ffffe75dbd0, val=0x3ffffe75dc60
add=0x3ffffe75dbd8, val=0
add=0x3ffffe75dbe0, val=0
add=0x3ffffe75dbe8, val=0
add=0x3ffffe75dbf0, val=0
add=0x3ffffe75dbf8, val=0
add=0x3ffffe75dc00, val=0
add=0x3ffffe75dc08, val=0x3fff8a77ee20
add=0x3ffffe75dc10, val=0x3ffffe75dd38
add=0x3ffffe75dc18, val=0x10000
add=0x3ffffe75dc20, val=0x3ffffe75ddb8
add=0x3ffffe75dc28, val=0xffffffff
add=0x3ffffe75dc30, val=0x3ffffe75de70
add=0x3ffffe75dc38, val=0x3fff8a77ee20
add=0x3ffffe75dc40, val=0x3ffffe75dee0
add=0x3ffffe75dc48, val=0x8
add=0x3ffffe75dc50, val=0x3ffffe75dee8
add=0x3ffffe75dc58, val=0x3fff8a70e9c8
add=0x3ffffe75dc60, val=0x3fff8a576750
add=0x3ffffe75dc68, val=0x3fff8a77b000
add=0x3ffffe75dc70, val=0x3fff8a616b9c
add=0x3ffffe75dc78, val=0xffffffff

其中:oldspp與frame相差0x960B, frame與newsp=128B, regs->link=0x3fff8a740478, regs->nip=0x10000964,NIP指向訊號處理函式地址(如下反彙編所示地址0x10000964)

回答上面的問題,當前SP地址是0x3ffffe75d1c0與newsp又相差144B,為什麼呢?

看反彙編程式碼10000970:    f8 21 ff 71     stdu    r1,-144(r1),可以看到r1又往下增長了144B了(我們的列印在此行之後)。

0000000010000964 <.sig_handler>:
    10000964:	7c 08 02 a6 	mflr    r0
    10000968:	f8 01 00 10 	std     r0,16(r1)
    1000096c:	fb e1 ff f8 	std     r31,-8(r1)
    10000970:	f8 21 ff 71 	stdu    r1,-144(r1)
    10000974:	7c 3f 0b 78 	mr      r31,r1
    10000978:	7c 69 1b 78 	mr      r9,r3
    1000097c:	91 3f 00 c0 	stw     r9,192(r31)
    10000980:	39 20 00 00 	li      r9,0
    10000984:	91 3f 00 70 	stw     r9,112(r31)
    10000988:	39 20 00 00 	li      r9,0
    1000098c:	f9 3f 00 78 	std     r9,120(r31)
    10000990:	7c 29 0b 78 	mr      r9,r1
    10000994:	f9 3f 00 78 	std     r9,120(r31)

其中:regs->link=0x3fff8a740478用於使用VDSO機制,從本程序maps可以看出VDSO可以看出vdso64_rt_sigtramp的地址是0x0478;regs->nip=0x10000964指向TEXT段的訊號處理函式。

[email protected]:/proc/2033# cat maps 
10000000-10001000 r-xp 00000000 00:16 2291                               /var/volatile/timer
10011000-10012000 rw-p 00001000 00:16 2291                               /var/volatile/timer
10012000-10033000 rw-p 00000000 00:00 0                                  [heap]
3fff8a532000-3fff8a550000 r-xp 00000000 01:00 9891                       /lib64/libpthread-2.20.so
3fff8a550000-3fff8a55f000 ---p 0001e000 01:00 9891                       /lib64/libpthread-2.20.so
3fff8a55f000-3fff8a560000 r--p 0001d000 01:00 9891                       /lib64/libpthread-2.20.so
3fff8a560000-3fff8a562000 rw-p 0001e000 01:00 9891                       /lib64/libpthread-2.20.so
3fff8a562000-3fff8a567000 rw-p 00000000 00:00 0 
3fff8a567000-3fff8a6fb000 r-xp 00000000 01:00 9909                       /lib64/libc-2.20.so
3fff8a6fb000-3fff8a70a000 ---p 00194000 01:00 9909                       /lib64/libc-2.20.so
3fff8a70a000-3fff8a70e000 r--p 00193000 01:00 9909                       /lib64/libc-2.20.so
3fff8a70e000-3fff8a721000 rw-p 00197000 01:00 9909                       /lib64/libc-2.20.so
3fff8a721000-3fff8a725000 rw-p 00000000 00:00 0 
3fff8a725000-3fff8a72e000 r-xp 00000000 01:00 9906                       /lib64/librt-2.20.so
3fff8a72e000-3fff8a73d000 ---p 00009000 01:00 9906                       /lib64/librt-2.20.so
3fff8a73d000-3fff8a73e000 r--p 00008000 01:00 9906                       /lib64/librt-2.20.so
3fff8a73e000-3fff8a73f000 rw-p 00009000 01:00 9906                       /lib64/librt-2.20.so
3fff8a73f000-3fff8a740000 rw-p 00000000 00:00 0 
3fff8a740000-3fff8a743000 r-xp 00000000 00:00 0                          [vdso]
3fff8a747000-3fff8a76f000 r-xp 00000000 01:00 9930                       /lib64/ld-2.20.so
3fff8a779000-3fff8a77d000 rw-p 00000000 00:00 0 
3fff8a77d000-3fff8a77e000 rw-p 00000000 00:00 0 
3fff8a77e000-3fff8a77f000 r--p 00027000 01:00 9930                       /lib64/ld-2.20.so
3fff8a77f000-3fff8a782000 rw-p 00028000 01:00 9930                       /lib64/ld-2.20.so
3ffffe73e000-3ffffe75f000 rw-p 00000000 00:00 0                          [stack]
[email protected]:/proc/2033# 

regs->link=0x3fff8a740478用於使用VDSO機制,究竟是執行什麼程式碼呢?

原來是以下程式碼,從以下程式碼看出,addi    r1, r1, __SIGNAL_FRAMESIZE又把newsp改為到frame。注意當前r1是由於訊號處理函式結束blr返回後自動已經改為newsp(r1+144B)了。

V_FUNCTION_BEGIN(__kernel_sigtramp_rt64)
.Lsigrt_start = . - 4
	addi	r1, r1, __SIGNAL_FRAMESIZE
	li	r0,__NR_rt_sigreturn
	sc
.Lsigrt_end:
V_FUNCTION_END(__kernel_sigtramp_rt64)

通過sc系統呼叫,執行以下程式碼

int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
		     unsigned long r6, unsigned long r7, unsigned long r8,
		     struct pt_regs *regs)
{
    /* 當前gpr[1]就是上次frame,frame結構體第一個元素就是uc,因此強轉換沒有問題 */
	struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1];
	sigset_t set;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
	unsigned long msr;
#endif

	/* Always make any pending restarted system calls return -EINTR */
	current->restart_block.fn = do_no_restart_syscall;

	if (!access_ok(VERIFY_READ, uc, sizeof(*uc)))
		goto badframe;

	if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
		goto badframe;
	set_current_blocked(&set);
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
	if (__get_user(msr, &uc->uc_mcontext.gp_regs[PT_MSR]))
		goto badframe;
	if (MSR_TM_ACTIVE(msr)) {
		/* We recheckpoint on return. */
		struct ucontext __user *uc_transact;
		if (__get_user(uc_transact, &uc->uc_link))
			goto badframe;
		if (restore_tm_sigcontexts(regs, &uc->uc_mcontext,
					   &uc_transact->uc_mcontext))
			goto badframe;
	}
	else
	/* Fall through, for non-TM restore */
#endif
    /* 恢復訊號上下文 */
	if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext))
		goto badframe;
    /* 恢復棧指標內容 */
	if (restore_altstack(&uc->uc_stack))
		goto badframe;

	set_thread_flag(TIF_RESTOREALL);
	return 0;

badframe:
	if (show_unhandled_signals)
		printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
				   current->comm, current->pid, "rt_sigreturn",
				   (long)uc, regs->nip, regs->link);

	force_sig(SIGSEGV, current);
	return 0;
}

總結:核心的訊號處理機制效率並不高,因為__kernel_sigtramp_rt64返回再次進入核心時,核心從使用者態棧空間還原出原始的pt_regs,準備返回使用者態時,又重新檢測有沒有pending訊號,一旦有,又得執行訊號處理函式又需要構建frame,不停地迴圈,因此效率堪憂。

有空再補充一個棧變化圖。