gdb/python: fix invalid use disassemble_info::stream
After this commit:
commit 81384924cd
Date: Tue Apr 5 11:06:16 2022 +0100
gdb: have gdb_disassemble_info carry 'this' in its stream pointer
The disassemble_info::stream field will no longer be a ui_file*. That
commit failed to update one location in py-disasm.c though.
While running some tests using the Python disassembler API, I
triggered a call to gdbpy_disassembler::print_address_func, and, as I
had compiled GDB with the undefined behaviour sanitizer, GDB crashed
as the code currently (incorrectly) casts the stream field to be a
ui_file*.
In this commit I fix this error.
In order to test this case I had to tweak the existing test case a
little. I also spotted some debug printf statements in py-disasm.py,
which I have removed.
This commit is contained in:
parent
554128418b
commit
23aa2befce
4 changed files with 22 additions and 13 deletions
|
@ -626,7 +626,7 @@ gdbpy_disassembler::print_address_func (bfd_vma addr,
|
||||||
{
|
{
|
||||||
gdbpy_disassembler *dis
|
gdbpy_disassembler *dis
|
||||||
= static_cast<gdbpy_disassembler *> (info->application_data);
|
= static_cast<gdbpy_disassembler *> (info->application_data);
|
||||||
print_address (dis->arch (), addr, (struct ui_file *) info->stream);
|
print_address (dis->arch (), addr, dis->stream ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* constructor. */
|
/* constructor. */
|
||||||
|
|
|
@ -16,10 +16,16 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
test ()
|
||||||
{
|
{
|
||||||
asm ("nop");
|
asm ("nop");
|
||||||
asm ("nop"); /* Break here. */
|
asm ("nop"); /* Break here. */
|
||||||
asm ("nop");
|
asm ("nop");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return test ();
|
||||||
|
}
|
||||||
|
|
|
@ -110,8 +110,8 @@ foreach plan $test_plans {
|
||||||
gdb_test_no_output "python add_global_disassembler($global_disassembler_name)"
|
gdb_test_no_output "python add_global_disassembler($global_disassembler_name)"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Disassemble main, and check the disassembler output.
|
# Disassemble test, and check the disassembler output.
|
||||||
gdb_test "disassemble main" $expected_pattern
|
gdb_test "disassemble test" $expected_pattern
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,21 +138,21 @@ with_test_prefix "DisassemblerResult errors" {
|
||||||
with_test_prefix "GLOBAL tagging disassembler" {
|
with_test_prefix "GLOBAL tagging disassembler" {
|
||||||
py_remove_all_disassemblers
|
py_remove_all_disassemblers
|
||||||
gdb_test_no_output "python gdb.disassembler.register_disassembler(TaggingDisassembler(\"GLOBAL\"), None)"
|
gdb_test_no_output "python gdb.disassembler.register_disassembler(TaggingDisassembler(\"GLOBAL\"), None)"
|
||||||
gdb_test "disassemble main" "${base_pattern}\\s+## tag = GLOBAL\r\n.*"
|
gdb_test "disassemble test" "${base_pattern}\\s+## tag = GLOBAL\r\n.*"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Now register an architecture specific disassembler, and check it
|
# Now register an architecture specific disassembler, and check it
|
||||||
# overrides the global disassembler.
|
# overrides the global disassembler.
|
||||||
with_test_prefix "LOCAL tagging disassembler" {
|
with_test_prefix "LOCAL tagging disassembler" {
|
||||||
gdb_test_no_output "python gdb.disassembler.register_disassembler(TaggingDisassembler(\"LOCAL\"), \"${curr_arch}\")"
|
gdb_test_no_output "python gdb.disassembler.register_disassembler(TaggingDisassembler(\"LOCAL\"), \"${curr_arch}\")"
|
||||||
gdb_test "disassemble main" "${base_pattern}\\s+## tag = LOCAL\r\n.*"
|
gdb_test "disassemble test" "${base_pattern}\\s+## tag = LOCAL\r\n.*"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Now remove the architecture specific disassembler, and check that
|
# Now remove the architecture specific disassembler, and check that
|
||||||
# the global disassembler kicks back in.
|
# the global disassembler kicks back in.
|
||||||
with_test_prefix "GLOBAL tagging disassembler again" {
|
with_test_prefix "GLOBAL tagging disassembler again" {
|
||||||
gdb_test_no_output "python gdb.disassembler.register_disassembler(None, \"${curr_arch}\")"
|
gdb_test_no_output "python gdb.disassembler.register_disassembler(None, \"${curr_arch}\")"
|
||||||
gdb_test "disassemble main" "${base_pattern}\\s+## tag = GLOBAL\r\n.*"
|
gdb_test "disassemble test" "${base_pattern}\\s+## tag = GLOBAL\r\n.*"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check that a DisassembleInfo becomes invalid after the call into the
|
# Check that a DisassembleInfo becomes invalid after the call into the
|
||||||
|
@ -160,7 +160,7 @@ with_test_prefix "GLOBAL tagging disassembler again" {
|
||||||
with_test_prefix "DisassembleInfo becomes invalid" {
|
with_test_prefix "DisassembleInfo becomes invalid" {
|
||||||
py_remove_all_disassemblers
|
py_remove_all_disassemblers
|
||||||
gdb_test_no_output "python add_global_disassembler(GlobalCachingDisassembler)"
|
gdb_test_no_output "python add_global_disassembler(GlobalCachingDisassembler)"
|
||||||
gdb_test "disassemble main" "${base_pattern}\\s+## CACHED\r\n.*"
|
gdb_test "disassemble test" "${base_pattern}\\s+## CACHED\r\n.*"
|
||||||
gdb_test "python GlobalCachingDisassembler.check()" "PASS"
|
gdb_test "python GlobalCachingDisassembler.check()" "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,10 +168,10 @@ with_test_prefix "DisassembleInfo becomes invalid" {
|
||||||
with_test_prefix "memory source api" {
|
with_test_prefix "memory source api" {
|
||||||
py_remove_all_disassemblers
|
py_remove_all_disassemblers
|
||||||
gdb_test_no_output "python analyzing_disassembler = add_global_disassembler(AnalyzingDisassembler)"
|
gdb_test_no_output "python analyzing_disassembler = add_global_disassembler(AnalyzingDisassembler)"
|
||||||
gdb_test "disassemble main" "${base_pattern}\r\n.*"
|
gdb_test "disassemble test" "${base_pattern}\r\n.*"
|
||||||
gdb_test "python analyzing_disassembler.find_replacement_candidate()" \
|
gdb_test "python analyzing_disassembler.find_replacement_candidate()" \
|
||||||
"Replace from $hex to $hex with NOP"
|
"Replace from $hex to $hex with NOP"
|
||||||
gdb_test "disassemble main" "${base_pattern}\r\n.*" \
|
gdb_test "disassemble test" "${base_pattern}\r\n.*" \
|
||||||
"second disassembler pass"
|
"second disassembler pass"
|
||||||
gdb_test "python analyzing_disassembler.check()" \
|
gdb_test "python analyzing_disassembler.check()" \
|
||||||
"PASS"
|
"PASS"
|
||||||
|
@ -196,6 +196,12 @@ with_test_prefix "maint info python-disassemblers" {
|
||||||
"\[^\r\n\]+BuiltinDisassembler\\s+\\(Matches current architecture\\)" \
|
"\[^\r\n\]+BuiltinDisassembler\\s+\\(Matches current architecture\\)" \
|
||||||
"GLOBAL\\s+BuiltinDisassembler"] \
|
"GLOBAL\\s+BuiltinDisassembler"] \
|
||||||
"list disassemblers, multiple disassemblers registered"
|
"list disassemblers, multiple disassemblers registered"
|
||||||
|
|
||||||
|
# Check that disassembling main (with the BuiltinDisassembler in
|
||||||
|
# place) doesn't cause GDB to crash. The hope is that
|
||||||
|
# disassembling main will result in a call to print_address, which
|
||||||
|
# is where the problem was.
|
||||||
|
gdb_test "disassemble main" ".*"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check the attempt to create a "new" DisassembleInfo object fails.
|
# Check the attempt to create a "new" DisassembleInfo object fails.
|
||||||
|
|
|
@ -584,7 +584,6 @@ class AnalyzingDisassembler(Disassembler):
|
||||||
if self._nop_index is None and result.string == "nop":
|
if self._nop_index is None and result.string == "nop":
|
||||||
self._nop_index = len(self._pass_1_length)
|
self._nop_index = len(self._pass_1_length)
|
||||||
# The offset in the following read_memory call defaults to 0.
|
# The offset in the following read_memory call defaults to 0.
|
||||||
print("APB: Reading nop bytes")
|
|
||||||
self._nop_bytes = info.read_memory(result.length)
|
self._nop_bytes = info.read_memory(result.length)
|
||||||
|
|
||||||
# Record information about each instruction that is disassembled.
|
# Record information about each instruction that is disassembled.
|
||||||
|
@ -661,8 +660,6 @@ class AnalyzingDisassembler(Disassembler):
|
||||||
def check(self):
|
def check(self):
|
||||||
"""Call this after the second disassembler pass to validate the output."""
|
"""Call this after the second disassembler pass to validate the output."""
|
||||||
if self._check != self._pass_2_insn:
|
if self._check != self._pass_2_insn:
|
||||||
print("APB, Check : %s" % self._check)
|
|
||||||
print("APB, Result: %s" % self._pass_2_insn)
|
|
||||||
raise gdb.GdbError("mismatch")
|
raise gdb.GdbError("mismatch")
|
||||||
print("PASS")
|
print("PASS")
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue