diff options
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-disassemble.exp | 83 | ||||
-rw-r--r-- | gdb/testsuite/lib/mi-support.exp | 27 |
2 files changed, 110 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.mi/mi-disassemble.exp b/gdb/testsuite/gdb.mi/mi-disassemble.exp index 2d3e8e2..b7c5247 100644 --- a/gdb/testsuite/gdb.mi/mi-disassemble.exp +++ b/gdb/testsuite/gdb.mi/mi-disassemble.exp @@ -239,6 +239,88 @@ proc test_disassembly_bogus_args {} { } +# Check the format of the opcode bytes. +proc test_disassembly_opcode_format {} { + # First, we need to find a multi-byte instruction that we can + # then disassemble using the MI command. + set longest_insn_bytes "" + set longest_insn_addr "" + gdb_test_multiple "disassemble /r main" "" { + -re "^disassemble /r main\r\n" { + exp_continue + } + + -re "^&\"disassemble /r main.n\"\r\n" { + exp_continue + } + + -re "^~\"Dump of assembler code for function \[^\r\n\]+\r\n" { + exp_continue + } + + -re "^~\".. ($::hex) <\[^>\]+>:\\\\t(\[^\\\\\]+)\\\\t\[^\r\n\]+\r\n" { + set addr $expect_out(1,string) + set bytes $expect_out(2,string) + if { [string length $bytes] > [string length $longest_insn_bytes] } { + set longest_insn_addr $addr + set longest_insn_bytes $bytes + } + exp_continue + } + + -re "^~\"End of assembler dump\[^\r\n\]+\r\n" { + exp_continue + } + + -re "^\\^done\r\n$::mi_gdb_prompt$" { + gdb_assert { ![string equal $longest_insn_bytes ""] } \ + "found the bytes string for a longest instruction" + gdb_assert { ![string equal $longest_insn_addr ""] } \ + "found the address for a longest instruction" + } + } + + verbose -log "Longest instruction at ${longest_insn_addr} with bytes '${longest_insn_bytes}'" + + # Check that the instruction bytes that we found above consists of + # a series of individual bytes separated by a whitespace. Also, + # we check that the bytes reported match what can be found in the + # inferior memory. + set split_bytes [split $longest_insn_bytes " "] + set is_bad false + set addr $longest_insn_addr + set idx 0 + foreach b $split_bytes { + if { [string length $b] != 2 } { + set is_bad true + } + + # Load the actual byte value from memory, and check it matches + # the opcode byte reported in the disassembler output. + set addr 0x[format %x [expr $longest_insn_addr + $idx]] + set actual [format %02x [mi_get_valueof "/x" "*((unsigned char *) $addr)" "XX"]] + gdb_assert [string equal $actual "$b"] \ + "byte at $addr matches" + + incr idx + } + gdb_assert { !$is_bad } "check length of each byte" + set check_bytes [join $split_bytes " "] + gdb_assert { [string equal $check_bytes $longest_insn_bytes] } \ + "bytes are separated by a single space" + + # Figure out an end address at which to stop the disassembly. + set byte_count [llength $split_bytes] + set end_addr 0x[format %x [expr $longest_insn_addr + $byte_count]] + set start_addr $longest_insn_addr + + verbose -log "Instruction is ${byte_count} bytes, end address ${end_addr}" + + mi_gdb_test "321-data-disassemble -s $start_addr -e $end_addr -- 2" \ + "321\\^done,asm_insns=\\\[\{address=\"$start_addr\",func-name=\"main\",offset=\"$::decimal\",opcodes=\"$longest_insn_bytes\",inst=\".*\"\}\]" \ + "data-disassemble checking the opcodes bytes format" +} + mi_clean_restart $binfile mi_runto_main test_disassembly_only @@ -248,6 +330,7 @@ test_disassembly_mixed_with_opcodes test_disassembly_bogus_args test_disassembly_lines_limit test_disassembly_mixed_lines_limit +test_disassembly_opcode_format mi_gdb_exit return 0 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index e821c0f..2b534f5 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -2833,3 +2833,30 @@ proc mi_is_target_remote {} { return [gdb_is_target_remote_prompt "$mi_gdb_prompt"] } + +# Retrieve the value of EXP in the inferior, represented in format +# specified in FMT (using "printFMT"). DEFAULT is used as fallback if +# print fails. TEST is the test message to use. It can be omitted, +# in which case a test message is built from EXP. +# +# This is an MI version of gdb_valueof. + +proc mi_get_valueof { fmt exp default {test ""} } { + global mi_gdb_prompt + + if {$test == "" } { + set test "get valueof \"${exp}\"" + } + + set val ${default} + gdb_test_multiple "print${fmt} ${exp}" "$test" { + -re "~\"\\$\[0-9\]* = (\[^\r\n\]*)\\\\n\"\r\n\\^done\r\n$mi_gdb_prompt$" { + set val $expect_out(1,string) + pass "$test" + } + timeout { + fail "$test (timeout)" + } + } + return ${val} +} |