[Top] [All Lists]

[PATCH v3 1/2] MIPS: fix sibling call handling in get_frame_info

Subject: [PATCH v3 1/2] MIPS: fix sibling call handling in get_frame_info
From: Tony Wu <>
Date: Mon, 13 May 2013 00:04:29 +0800
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=x-received:date:from:to:subject:message-id:mime-version :content-type:content-disposition:user-agent; bh=On+WnFxDgn79/IeTgSNcAjmHiQXN1R99VixZuV9dNKY=; b=Ua2OJ/u4oFmnDo4fk1L6igy5xdmCrr1TKWq9mqG8DYpx6D86XxWbBcvxeqB54Ve65L OOFFzoKOio/bQRgILqmgb7Oyr6jQMp77dy/rE3CIA3TVQd9HyTQCU+7XzBIJib978xma uEkbZ00D9E2cpe62iwHv0STD2vSZTShHrCmdEP/vfDQcA2iY/ZaCB685+FRs3L6dD0su kxS4/02wj+EicLXB94Die9huGydhSii6BWPzjMLQaaWibQ5WiCHlm0tUm+GvhnOSFG2o O2oNBeKDbAfmXe+TXvfzS6OCmKaBtY/GL5S1cCiWmXqJaGl/heGPXyfkr05C685lN8zq +MxA==
List-archive: <>
List-help: <>
List-id: linux-mips <>
List-owner: <>
List-post: <>
List-software: Ecartis version 1.0.0
List-subscribe: <>
List-unsubscribe: <>
Original-recipient: rfc822;
User-agent: Mutt/1.5.21 (2010-09-15)
Given a function, get_frame_info() analyzes its instructions
to figure out frame size and return address. get_frame_info()
works as follows:

1. analyze up to 128 instructions if the function size is unknown
2. search for 'addiu/daddiu sp,sp,-immed' for frame size
3. search for 'sw ra,offset(sp)' for return address
4. end search when it sees jr/jal/jalr

This leads to an issue when the given function is a sibling
call, example shown as follows.

801ca110 <schedule>:
801ca110:       8f820000        lw      v0,0(gp)
801ca114:       8c420000        lw      v0,0(v0)
801ca118:       080726f0        j       801c9bc0 <__schedule>
801ca11c:       00000000        nop

801ca120 <io_schedule>:
801ca120:       27bdffe8        addiu   sp,sp,-24
801ca124:       3c028022        lui     v0,0x8022
801ca128:       afbf0014        sw      ra,20(sp)

In this case, get_frame_info() cannot properly detect schedule's
frame info, and eventually returns io_schedule's instead.

This patch adds 'j' to the end search condition to workaround
sibling call cases.

Signed-off-by: Tony Wu <>
 arch/mips/kernel/process.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index cfc742d..d66b04d 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -231,8 +231,10 @@ static inline int is_ra_save_ins(union mips_instruction 
                ip->i_format.rt == 31;
-static inline int is_jal_jalr_jr_ins(union mips_instruction *ip)
+static inline int is_jump_ins(union mips_instruction *ip)
+       if (ip->j_format.opcode == j_op)
+               return 1;
        if (ip->j_format.opcode == jal_op)
                return 1;
        if (ip->r_format.opcode != spec_op)
@@ -268,7 +270,7 @@ static int get_frame_info(struct mips_frame_info *info)
        for (i = 0; i < max_insns; i++, ip++) {
-               if (is_jal_jalr_jr_ins(ip))
+               if (is_jump_ins(ip))
                if (!info->frame_size) {
                        if (is_sp_move_ins(ip))
-- (Apple Git-33)

<Prev in Thread] Current Thread [Next in Thread>