}
+# 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
test_disassembly_bogus_args
test_disassembly_lines_limit
test_disassembly_mixed_lines_limit
+test_disassembly_opcode_format
mi_gdb_exit
return 0
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}
+}