qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [PATCH] target/i386/gdbstub: Fix a bug about order of FPU stack in '


From: 伊藤 太清
Subject: RE: [PATCH] target/i386/gdbstub: Fix a bug about order of FPU stack in 'g' packets.
Date: Thu, 15 Dec 2022 14:29:35 +0000

Supplementary explanation about the patch

 

1. Reproduction of the bug

 

The following 3 files are needed to reproduce the bug.

 

* test_os.s

* test_os.ld

* Makefile

 

And the following 2 tools, too.

 

* build-essential

* gdb

 

The contents of the above files are below.

 

---------- Begin of test_os.s ----------

 

            .code16

            .text

main:

            fninit  # Initialize the FPU

            fld1    # Push 1.0

            fldl2t  # Push log 2 10

            fldl2e # Push log 2 e

            fldpi   # Push pi

            fldlg2 # Push log 10 2

            fldln2 # Push log e 2

            fldz     # Push 0.0

loop:

            hlt

            jmp loop

 

---------- End of test_os.s ----------

 

---------- Begin of test_os.ld ----------

 

OUTPUT_FORMAT("binary");

 

BASE = 0x00007c00;

 

SECTIONS

{

            . = BASE;

            .text :

            {

                       test_os.o(.text)

            }

            . = BASE;

            . += 0x00000200;

            . -= 0x00000002;

            .boot_sector_sign :

            {

                       BYTE(0x55);

                       BYTE(0xaa);

            }

            /DISCARD/ :

            {

                       *(.eh_frame)

                       *(.note.gnu.property)

            }

}

 

---------- End of test_os.ld ----------

 

---------- Begin of Makefile ----------

 

TEST_OS_NAME = test_o

TEST_OS_NAME = test_os

TEST_OS_ASM = $(TEST_OS_NAME).s

TEST_OS_IMG = $(TEST_OS_NAME).img

TEST_OS_LNK = $(TEST_OS_NAME).ld

TEST_OS_MAP = $(TEST_OS_NAME).map

TEST_OS_OBJ = $(TEST_OS_NAME).o

 

all: $(TEST_OS_IMG)

 

test: $(TEST_OS_IMG)

            (qemu-system-i386 -boot order=a \

            -drive file=$<,format=raw,if=floppy \

            -S -gdb tcp::2159 -vnc localhost:0 &) && \

            gdb

 

$(TEST_OS_IMG): $(TEST_OS_OBJ) $(TEST_OS_LNK)

            ld $< -Map $(TEST_OS_MAP) -o $@ -T $(word 2, $^)

 

$(TEST_OS_OBJ): $(TEST_OS_ASM)

            gcc $^ -c -nostdlib -o $@ -Wall -Wextra

 

---------- End of Makefile ----------

 

Put these files on a same directory. "test_os.s" is source code of tiny OS

to run on QEMU. The OS consists only a boot sector. It initialize x87 FPU

and pushes some floating point values onto x87 FPU stack. "test_os.ld" is

its linker script. And you can make "test_os.img", a raw image of the OS.

Now, there are all things to reproduce the bug. You can "make test" to let

QEMU run the OS and wait for GDB, then GDB will start. Then you can execute

some GDB commands to reproduce the bug. Below is "result 1" reproducing the

bug.

 

---------- Begin of result 1 ----------

 

GNU gdb (GDB) 13.0.50.20221204-git

Copyright (C) 2022 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

Type "show copying" and "show warranty" for details.

This GDB was configured as "x86_64-pc-linux-gnu".

Type "show configuration" for configuration details.

For bug reporting instructions, please see:

<https://www.gnu.org/software/gdb/bugs/>.

Find the GDB manual and other documentation resources online at:

    <http://www.gnu.org/software/gdb/documentation/>.

 

For help, type "help".

Type "apropos word" to search for commands related to "word".

(gdb) target remote localhost:2159

Remote debugging using localhost:2159

warning: No executable has been specified and target does not support

determining executable automatically.  Try using the "file" command.

0x0000fff0 in ?? ()

(gdb) break *0x7c00

Breakpoint 1 at 0x7c00

(gdb) continue

Continuing.

 

Breakpoint 1, 0x00007c00 in ?? ()

(gdb) x/10i $eip

=> 0x7c00:      fninit

   0x7c02:      fld1

   0x7c04:      fldl2t

   0x7c06:      fldl2e

   0x7c08:      fldpi

   0x7c0a:      fldlg2

   0x7c0c:      fldln2

   0x7c0e:      fldz

   0x7c10:      hlt

   0x7c11:      jmp    0x7c10

(gdb) stepi

0x00007c02 in ?? ()

(gdb) info float

  R7: Valid   0x00000000000000000000 +0

  R6: Valid   0x00000000000000000000 +0

  R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

=>R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x0000

                       TOP: 0

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c04 in ?? ()

(gdb) info float

=>R7: Valid   0x00000000000000000000 +0

  R6: Valid   0x3fff8000000000000000 +1

  R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x3800

                       TOP: 7

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c06 in ?? ()

(gdb) info float

  R7: Valid   0x00000000000000000000 +0

=>R6: Valid   0x00000000000000000000 +0

  R5: Valid   0x3fff8000000000000000 +1

  R4: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x3000

                       TOP: 6

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c08 in ?? ()

(gdb) info float

  R7: Valid   0x00000000000000000000 +0

  R6: Valid   0x00000000000000000000 +0

=>R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x3fff8000000000000000 +1

  R3: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R2: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x2800

                       TOP: 5

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c0a in ?? ()

(gdb) info float

  R7: Valid   0x00000000000000000000 +0

  R6: Valid   0x00000000000000000000 +0

  R5: Valid   0x00000000000000000000 +0

=>R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x3fff8000000000000000 +1

  R2: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R1: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R0: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

 

Status Word:         0x2000

                       TOP: 4

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c0c in ?? ()

(gdb) info float

  R7: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

  R6: Valid   0x3ffd9a209a84fbcff799 +0.3010299956639811952

  R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x00000000000000000000 +0

=>R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x3fff8000000000000000 +1

  R1: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R0: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

 

Status Word:         0x1800

                       TOP: 3

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c0e in ?? ()

(gdb) info float

  R7: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R6: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

  R5: Valid   0x3ffd9a209a84fbcff799 +0.3010299956639811952

  R4: Valid   0x3ffeb17217f7d1cf79ac +0.6931471805599453094

  R3: Valid   0x00000000000000000000 +0

=>R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x3fff8000000000000000 +1

  R0: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

 

Status Word:         0x1000

                       TOP: 2

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c10 in ?? ()

(gdb) info float

  R7: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R6: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R5: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

  R4: Valid   0x3ffd9a209a84fbcff799 +0.3010299956639811952

  R3: Valid   0x3ffeb17217f7d1cf79ac +0.6931471805599453094

  R2: Valid   0x00000000000000000000 +0

=>R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x3fff8000000000000000 +1

 

Status Word:         0x0800

                       TOP: 1

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

 

---------- End of result 1 ----------

 

As you can see, the FPU stack rotates every pushing.

 

2. Cause

 

There is a cause of the bug in a function "x86_cpu_gdb_read_register" in

"qemu/target/i386/gdbstub.c". GDB receives a command "info float" from stdin

and get values of the all registers containing FPU stack registers from QEMU

to print them. Then, QEMU picks registers in the function to form 'g' packet

to send to GDB. In line 124 of the c source file, absolute indexed FPU stack

registers, namely, R0, ... and R7 , are picked and inserted in 'g' packet.

However, GDB, the packet receiver, extracts FPU stack registers from the

packet and interpret these registers are stack top relative indexed, namely,

ST0, ... and ST7. As a result, GDB can't print FPU stack correctly.

 

3. Modification

 

In added lines of this patch, "n" is a register number of a register to

read. And "IDX_FP_REGS" is register number of the first FPU stack register

"R0". So, "r_index" is absolute index of FPU stack register to read. And

"env->fpstt" is a pointer to top of FPU stack. So, "st_index" is stack top

relative index of FPU stack register to read. By applying this modification,

QEMU inserts FPU stack registers ordered by stack top relative index in 'g'

packet.

 

4. After this patch

 

Below is "result 2" operating as same as "result 1" after applying this

patch.

 

---------- Begin of result 2 ----------

 

GNU gdb (GDB) 13.0.50.20221204-git

Copyright (C) 2022 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

Type "show copying" and "show warranty" for details.

This GDB was configured as "x86_64-pc-linux-gnu".

Type "show configuration" for configuration details.

For bug reporting instructions, please see:

<https://www.gnu.org/software/gdb/bugs/>.

Find the GDB manual and other documentation resources online at:

    <http://www.gnu.org/software/gdb/documentation/>.

 

For help, type "help".

Type "apropos word" to search for commands related to "word".

(gdb) target remote localhost:2159

Remote debugging using localhost:2159

warning: No executable has been specified and target does not support

determining executable automatically.  Try using the "file" command.

0x0000fff0 in ?? ()

(gdb) break *0x7c00

Breakpoint 1 at 0x7c00

(gdb) continue

Continuing.

 

Breakpoint 1, 0x00007c00 in ?? ()

(gdb) x/10i $eip

=> 0x7c00:      fninit

   0x7c02:      fld1

   0x7c04:      fldl2t

   0x7c06:      fldl2e

   0x7c08:      fldpi

   0x7c0a:      fldlg2

   0x7c0c:      fldln2

   0x7c0e:      fldz

   0x7c10:      hlt

   0x7c11:      jmp    0x7c10

(gdb) stepi

0x00007c02 in ?? ()

(gdb) info float

  R7: Valid   0x00000000000000000000 +0

  R6: Valid   0x00000000000000000000 +0

  R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

=>R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x0000

                       TOP: 0

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c04 in ?? ()

(gdb) info float

=>R7: Valid   0x3fff8000000000000000 +1

  R6: Valid   0x00000000000000000000 +0

  R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x3800

                       TOP: 7

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c06 in ?? ()

(gdb) info float

  R7: Valid   0x3fff8000000000000000 +1

=>R6: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R5: Valid   0x00000000000000000000 +0

  R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x3000

                       TOP: 6

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c08 in ?? ()

(gdb) info float

  R7: Valid   0x3fff8000000000000000 +1

  R6: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

=>R5: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R4: Valid   0x00000000000000000000 +0

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x2800

                       TOP: 5

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c0a in ?? ()

(gdb) info float

  R7: Valid   0x3fff8000000000000000 +1

  R6: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R5: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

=>R4: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

  R3: Valid   0x00000000000000000000 +0

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x2000

                       TOP: 4

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c0c in ?? ()

(gdb) info float

  R7: Valid   0x3fff8000000000000000 +1

  R6: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R5: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R4: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

=>R3: Valid   0x3ffd9a209a84fbcff799 +0.3010299956639811952

  R2: Valid   0x00000000000000000000 +0

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x1800

                       TOP: 3

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c0e in ?? ()

(gdb) info float

  R7: Valid   0x3fff8000000000000000 +1

  R6: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R5: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R4: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

  R3: Valid   0x3ffd9a209a84fbcff799 +0.3010299956639811952

=>R2: Valid   0x3ffeb17217f7d1cf79ac +0.6931471805599453094

  R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x1000

                       TOP: 2

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

(gdb) stepi

0x00007c10 in ?? ()

(gdb) info float

  R7: Valid   0x3fff8000000000000000 +1

  R6: Valid   0x4000d49a784bcd1b8afe +3.321928094887362348

  R5: Valid   0x3fffb8aa3b295c17f0bc +1.442695040888963407

  R4: Valid   0x4000c90fdaa22168c235 +3.141592653589793239

  R3: Valid   0x3ffd9a209a84fbcff799 +0.3010299956639811952

  R2: Valid   0x3ffeb17217f7d1cf79ac +0.6931471805599453094

=>R1: Valid   0x00000000000000000000 +0

  R0: Valid   0x00000000000000000000 +0

 

Status Word:         0x0800

                       TOP: 1

Control Word:        0x037f   IM DM ZM OM UM PM

                       PC: Extended Precision (64-bits)

                       RC: Round to nearest

Tag Word:            0x0000

Instruction Pointer: 0x00:0x00000000

Operand Pointer:     0x00:0x00000000

Opcode:              0x0000

 

---------- End of result 2 ----------

 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]