All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tony Wu <tung7970@gmail.com>
To: ralf@linux-mips.org, linux-mips@linux-mips.org
Subject: [PATCH 1/2] MIPS: detect sibling call in get_frame_info
Date: Thu, 9 May 2013 22:47:53 +0800	[thread overview]
Message-ID: <20130509144753.GC3562@hades> (raw)

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 given 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 info instead.

This patch adds sibling call check by detecting out of range jump.

Signed-off-by: Tony Wu <tung7970@gmail.com>
---
 arch/mips/kernel/process.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index cfc742d..a794eb5 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -223,6 +223,9 @@ struct mips_frame_info {
 	int		pc_offset;
 };
 
+#define J_TARGET(pc,target)	\
+		(((unsigned long)(pc) & 0xf0000000) | ((target) << 2))
+
 static inline int is_ra_save_ins(union mips_instruction *ip)
 {
 	/* sw / sd $ra, offset($sp) */
@@ -250,11 +253,25 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
 	return 0;
 }
 
+static inline int is_sibling_j_ins(union mips_instruction *ip,
+				   unsigned long func_begin, unsigned long func_end)
+{
+	if (ip->j_format.opcode == j_op) {
+		unsigned long addr;
+
+		addr = J_TARGET(ip, ip->j_format.target);
+		if (addr < func_begin || addr > func_end)
+			return 1;
+	}
+	return 0;
+}
+
 static int get_frame_info(struct mips_frame_info *info)
 {
 	union mips_instruction *ip = info->func;
 	unsigned max_insns = info->func_size / sizeof(union mips_instruction);
 	unsigned i;
+	unsigned long func_begin, func_end;
 
 	info->pc_offset = -1;
 	info->frame_size = 0;
@@ -266,10 +283,15 @@ static int get_frame_info(struct mips_frame_info *info)
 		max_insns = 128U;	/* unknown function size */
 	max_insns = min(128U, max_insns);
 
+	func_begin = (unsigned long) info->func;
+	func_end = func_begin + max_insns * sizeof(union mips_instruction);
+
 	for (i = 0; i < max_insns; i++, ip++) {
 
 		if (is_jal_jalr_jr_ins(ip))
 			break;
+		if (is_sibling_j_ins(ip, func_begin, func_end))
+			break;
 		if (!info->frame_size) {
 			if (is_sp_move_ins(ip))
 				info->frame_size = - ip->i_format.simmediate;
-- 
1.7.10.2 (Apple Git-33)

                 reply	other threads:[~2013-05-09 14:48 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130509144753.GC3562@hades \
    --to=tung7970@gmail.com \
    --cc=linux-mips@linux-mips.org \
    --cc=ralf@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.