From: David Daney <ddaney.cavm@gmail.com>
To: Tony Wu <tung7970@gmail.com>
Cc: ralf@linux-mips.org, linux-mips@linux-mips.org
Subject: Re: [PATCH v2 1/2] MIPS: detect sibling call in get_frame_info
Date: Fri, 10 May 2013 09:23:57 -0700 [thread overview]
Message-ID: <518D1F1D.2080504@gmail.com> (raw)
In-Reply-To: <20130510110729.GA7499@hades>
On 05/10/2013 04:07 AM, Tony Wu wrote:
> 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.
I think this is more complex than it needs to be. Also you already
handle the case of a sib call via a function pointer ....
>
> 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;
... here. So why not just add an unconditional J to the list detected,
and get rid of all the rest of the patch?
> + 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;
>
next prev parent reply other threads:[~2013-05-10 16:24 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-10 11:07 [PATCH v2 1/2] MIPS: detect sibling call in get_frame_info Tony Wu
2013-05-10 16:23 ` David Daney [this message]
2013-05-12 16:53 ` Tony Wu
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=518D1F1D.2080504@gmail.com \
--to=ddaney.cavm@gmail.com \
--cc=linux-mips@linux-mips.org \
--cc=ralf@linux-mips.org \
--cc=tung7970@gmail.com \
/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.