All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] Emulating MIPS self-examining code
@ 2010-02-08 14:26 Dmitry Antipov
  2010-02-08 15:13 ` Aurelien Jarno
  0 siblings, 1 reply; 2+ messages in thread
From: Dmitry Antipov @ 2010-02-08 14:26 UTC (permalink / raw)
  To: qemu-devel

Hello,

I'm trying to emulate the following MIPS code (taken from the bootloader of my system):

         /* Initialize GOT pointer.
         ** Global symbols can't be resolved before this is done, and as such we can't
         ** use any global symbols in this code.  We use the bal/ move xxx,ra combination to access
         ** data in a PC relative manner to avoid this.  This code will correctly set the
         ** gp regardless of whether the code has already been relocated or not.
         ** This code determines the current gp by computing the link time (gp - pc)
         ** and adding this to the current pc.
         ** runtime_gp = runtime_pc + (linktime_gp - linktime_pc)
         ** U-boot is running from the address it is linked at at this time, so this
         ** general case code is not strictly necessary here.
         */

         /* Branch and link to get current PC in ra */
         bal     1f
         nop
         .extern _GLOBAL_OFFSET_TABLE_
         .word   _GLOBAL_OFFSET_TABLE_  /* This contains the linked address of the GOT */
         /* The ra register now contains the runtime address of the above memory location */

         .word   . - 4                  /* This contains the link time address of the previous word,
                                         which is also what the link time expected PC value is */
1:
         move    gp, ra    /* Move current PC into gp register */
         lw      t1, 0(ra) /* Load linked address of the GOT into t1 */
         lw      t2, 4(ra) /* Load the link time address of the GOT storage location into t2 */
         sub     t1, t2    /* Subtract t2 from t1. */
         /* t1 now contains the difference between the link-time GOT table address and the link time expected PC */

         /* Add this difference to the current PC (copied into gp above) so that gp now has the current runtime
         ** GOT table address */
         add     gp, t1  # calculate current location of offset table

Corresponding objdump output is:

...[skipped]
bfc306c4:       04110003        bal     bfc306d4 <func+0x28>
bfc306c8:       00000000        nop
bfc306cc:       bfc79d10        cache   0x7,-25328(s8)
bfc306d0:       bfc306cc        cache   0x3,1740(s8)
bfc306d4:       03e0e02d        move    gp,ra
bfc306d8:       8fe90000        lw      a5,0(ra)
bfc306dc:       8fea0004        lw      a6,4(ra)
bfc306e0:       012a4822        sub     a5,a5,a6
bfc306e4:       0389e020        add     gp,gp,a5
...[skipped]
bfc79d10 <_GLOBAL_OFFSET_TABLE_>:
bfc79d10:       00000000        nop
...[skipped]

This is a kind of self-examining code (bfc306cc..bfc306d0 is treated as data). The problem
is that QEMU translates this (master?)piece into two translation blocks bfc306c4..bfc306c8
and bfc306d4..bfc306e4, silently ignoring bfc306cc..bfc306d0 because there is no way
to execute in that area. Due to this, 0(ra) at bfc306d8 can't be evaluated correctly.

Is there any ideas on how to get such code emulated?

Dmitry

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] Emulating MIPS self-examining code
  2010-02-08 14:26 [Qemu-devel] Emulating MIPS self-examining code Dmitry Antipov
@ 2010-02-08 15:13 ` Aurelien Jarno
  0 siblings, 0 replies; 2+ messages in thread
From: Aurelien Jarno @ 2010-02-08 15:13 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: qemu-devel

On Mon, Feb 08, 2010 at 05:26:33PM +0300, Dmitry Antipov wrote:
> Hello,
> 
> I'm trying to emulate the following MIPS code (taken from the bootloader of my system):
> 
>         /* Initialize GOT pointer.
>         ** Global symbols can't be resolved before this is done, and as such we can't
>         ** use any global symbols in this code.  We use the bal/ move xxx,ra combination to access
>         ** data in a PC relative manner to avoid this.  This code will correctly set the
>         ** gp regardless of whether the code has already been relocated or not.
>         ** This code determines the current gp by computing the link time (gp - pc)
>         ** and adding this to the current pc.
>         ** runtime_gp = runtime_pc + (linktime_gp - linktime_pc)
>         ** U-boot is running from the address it is linked at at this time, so this
>         ** general case code is not strictly necessary here.
>         */
> 
>         /* Branch and link to get current PC in ra */
>         bal     1f
>         nop
>         .extern _GLOBAL_OFFSET_TABLE_
>         .word   _GLOBAL_OFFSET_TABLE_  /* This contains the linked address of the GOT */
>         /* The ra register now contains the runtime address of the above memory location */
> 
>         .word   . - 4                  /* This contains the link time address of the previous word,
>                                         which is also what the link time expected PC value is */
> 1:
>         move    gp, ra    /* Move current PC into gp register */
>         lw      t1, 0(ra) /* Load linked address of the GOT into t1 */
>         lw      t2, 4(ra) /* Load the link time address of the GOT storage location into t2 */
>         sub     t1, t2    /* Subtract t2 from t1. */
>         /* t1 now contains the difference between the link-time GOT table address and the link time expected PC */
> 
>         /* Add this difference to the current PC (copied into gp above) so that gp now has the current runtime
>         ** GOT table address */
>         add     gp, t1  # calculate current location of offset table
> 
> Corresponding objdump output is:
> 
> ...[skipped]
> bfc306c4:       04110003        bal     bfc306d4 <func+0x28>
> bfc306c8:       00000000        nop
> bfc306cc:       bfc79d10        cache   0x7,-25328(s8)
> bfc306d0:       bfc306cc        cache   0x3,1740(s8)
> bfc306d4:       03e0e02d        move    gp,ra
> bfc306d8:       8fe90000        lw      a5,0(ra)
> bfc306dc:       8fea0004        lw      a6,4(ra)
> bfc306e0:       012a4822        sub     a5,a5,a6
> bfc306e4:       0389e020        add     gp,gp,a5
> ...[skipped]
> bfc79d10 <_GLOBAL_OFFSET_TABLE_>:
> bfc79d10:       00000000        nop
> ...[skipped]
> 
> This is a kind of self-examining code (bfc306cc..bfc306d0 is treated as data). The problem
> is that QEMU translates this (master?)piece into two translation blocks bfc306c4..bfc306c8
> and bfc306d4..bfc306e4, silently ignoring bfc306cc..bfc306d0 because there is no way

It does not ignore it, it skips it because of the jump in 0xbfc306c4
which instructs the CPU to jump into bfc306d4. That's why the second 
block starts at this address.

> to execute in that area. Due to this, 0(ra) at bfc306d8 can't be evaluated correctly.

Why? Do you mean this instruction is not executed? What is important
here is the value of gp.

> Is there any ideas on how to get such code emulated?

I personally don't see the problem. Please also post the input asm code
and the output tcg code from qemu (-d in_asm,op).

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-02-08 15:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-08 14:26 [Qemu-devel] Emulating MIPS self-examining code Dmitry Antipov
2010-02-08 15:13 ` Aurelien Jarno

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.