Bug 9765 - Scrolling to end of program in asm layout is broken
Summary: Scrolling to end of program in asm layout is broken
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: tui (show other bugs)
Version: 6.50
: P3 minor
Target Milestone: 10.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-01-20 02:07 UTC by Pedro Alves
Modified: 2020-01-31 14:40 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pedro Alves 2009-01-20 02:07:04 UTC
If you switch to TUI's asm window, and then scroll all the way down to the end
of the program, things get broken:

$gdb helloworld
...

(gdb) layout asm
<pretty window shows up>
press page down until the end, then:

(gdb) Cannot access memory at address 0x401000

At this point, page up/down, up/down are broken.  Switching to CLI and back to
TUI seems to half fix "down", but "up" just doesn't work.

Trying to scroll passed the start of the program also throws that same error,
but the scrolling doesn't seem to break in that case.
Comment 1 Pedro Alves 2015-07-02 13:14:50 UTC
Still happens with 7.9.50.20150630-cvs.
Comment 2 Pedro Alves 2016-08-09 20:57:04 UTC
I'm not actually working on this.
Comment 3 anwilli5 2017-09-01 05:11:20 UTC
This happens for me as well (with gdb 8.0) except that gdb aborts with error message "(gdb) terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR'" instead of just getting into a bad state as described by Pedro.
Comment 4 Pedro Alves 2017-09-01 12:13:26 UTC
Sounds like we're letting C++ exceptions cross ncurses (in this case the memory error exception).  We can't, because it's a C library that may have not been built with unwind info.  [we had a similar problem with readline].
Comment 5 Tom Tromey 2018-09-02 23:35:09 UTC
Uncaught exception beneath tui_disassemble:


(top-gdb) bt
#0  0x00007f779fc219fb in raise () at /lib64/libc.so.6
#1  0x00007f779fc23800 in abort () at /lib64/libc.so.6
#2  0x00007f77a0269025 in __gnu_cxx::__verbose_terminate_handler() () at /lib64/libstdc++.so.6
#3  0x00007f77a0266c16 in  () at /lib64/libstdc++.so.6
#4  0x00007f77a0265b19 in  () at /lib64/libstdc++.so.6
#5  0x00007f77a0266508 in __gxx_personality_v0 () at /lib64/libstdc++.so.6
#6  0x00007f779ffcfee3 in  () at /lib64/libgcc_s.so.1
#7  0x00007f779ffd070e in _Unwind_Resume () at /lib64/libgcc_s.so.1
#8  0x000000000062269c in tui_disassemble(gdbarch*, tui_asm_line*, CORE_ADDR, int) (gdbarch=0x3d6a2c0, asm_lines=0x7ffd7590cc68, pc=0x4009d2, count=32) at ../../binutils-gdb/gdb/tui/tui-disasm.c:57
#9  0x0000000000622aee in tui_set_disassem_content(gdbarch*, unsigned long) (gdbarch=0x3d6a2c0, pc=0x4009c5) at ../../binutils-gdb/gdb/tui/tui-disasm.c:200
#10 0x00000000006359f8 in tui_update_source_window_as_is(tui_win_info*, gdbarch*, symtab*, tui_line_or_address, int) (win_info=0x3d90ed0, gdbarch=0x3d6a2c0, s=0x0, line_or_addr=..., noerror=0) at ../../binutils-gdb/gdb/tui/tui-winsource.c:98
#11 0x00000000006232e2 in tui_vertical_disassem_scroll(tui_scroll_direction, int) (scroll_direction=FORWARD_SCROLL, num_to_scroll=35) at ../../binutils-gdb/gdb/tui/tui-disasm.c:396
#12 0x0000000000632d20 in tui_scroll_forward(tui_win_info*, int) (win_to_scroll=0x3d90ed0, num_to_scroll=0) at ../../binutils-gdb/gdb/tui/tui-win.c:598
#13 0x0000000000621207 in tui_dispatch_ctrl_char(unsigned int) (ch=338) at ../../binutils-gdb/gdb/tui/tui-command.c:60
#14 0x000000000062bf5a in tui_getc(FILE*) (fp=0x7f779ffba8a0 <_IO_2_1_stdin_>) at ../../binutils-gdb/gdb/tui/tui-io.c:883
#15 0x0000000000acb234 in rl_read_key () at ../../binutils-gdb/readline/input.c:479
#16 0x0000000000ab766d in readline_internal_char () at ../../binutils-gdb/readline/readline.c:517
#17 0x0000000000acb88d in rl_callback_read_char () at ../../binutils-gdb/readline/callback.c:201
#18 0x0000000000876552 in gdb_rl_callback_read_char_wrapper_noexcept() () at ../../binutils-gdb/gdb/event-top.c:175
#19 0x00000000008765ae in gdb_rl_callback_read_char_wrapper(gdb_client_data) (client_data=0x3231840) at ../../binutils-gdb/gdb/event-top.c:192
#20 0x0000000000876c91 in stdin_event_handler(int, void*) (error=0, client_data=0x3231840) at ../../binutils-gdb/gdb/event-top.c:511
#21 0x0000000000874df9 in handle_file_event(file_handler*, int) (file_ptr=0x3bcad90, ready_mask=1) at ../../binutils-gdb/gdb/event-loop.c:733
#22 0x000000000087539c in gdb_wait_for_event(int) (block=1) at ../../binutils-gdb/gdb/event-loop.c:859
#23 0x0000000000874283 in gdb_do_one_event() () at ../../binutils-gdb/gdb/event-loop.c:347
#24 0x00000000008742bb in start_event_loop() () at ../../binutils-gdb/gdb/event-loop.c:371
#25 0x0000000000907d3e in captured_command_loop() () at ../../binutils-gdb/gdb/main.c:330
#26 0x0000000000909126 in captured_main(void*) (data=0x7ffd7590d4c0) at ../../binutils-gdb/gdb/main.c:1173
#27 0x00000000009091e2 in gdb_main(captured_main_args*) (args=0x7ffd7590d4c0) at ../../binutils-gdb/gdb/main.c:1189
#28 0x0000000000418a6e in main(int, char**) (argc=5, argv=0x7ffd7590d5c8) at ../../binutils-gdb/gdb/gdb.c:32
Comment 6 Tom Tromey 2018-09-02 23:47:39 UTC
A simple fix makes this strange though.
You can scroll off the end and then the window is empty.
And if you try to scroll back, you can't.

tui_find_disassembly_address has logic to deal with this.
It seems like it must be disagreeing with tui_set_disassem_content
somehow.
Comment 7 Tom Tromey 2018-09-03 02:17:37 UTC
(In reply to Tom Tromey from comment #6)

> tui_find_disassembly_address has logic to deal with this.
> It seems like it must be disagreeing with tui_set_disassem_content
> somehow.

I was just misreading this.
When scrolling forward nothing special happens here.
Comment 8 Tom Tromey 2018-09-03 04:28:28 UTC
I have a better patch now but I can also provoke a crash
by scrolling backward.  In this situation the problem is
that it trips across unreadable memory.

Currently I made it "jump" back to memory that is readable;
but then you can't scroll forward again.  Still looking into
it a bit.
Comment 9 Tom Tromey 2018-09-03 04:58:39 UTC
Don't know what to do here.  Also the code is weird.

Is it really that useful to scroll back before the start
of the current function?
Comment 10 Shahab 2020-01-09 08:58:22 UTC
a work-in-progress patch: https://sourceware.org/ml/gdb-patches/2020-01/msg00179.html
Comment 11 Sourceware Commits 2020-01-24 00:11:29 UTC
The master branch has been updated by Andrew Burgess <aburgess@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2f267673f0fdee9287e6d404ecd4f2d29da0d2f2

commit 2f267673f0fdee9287e6d404ecd4f2d29da0d2f2
Author: Pedro Alves <palves@redhat.com>
Date:   Sat Jan 11 01:37:26 2020 +0000

    gdb/tui: Prevent exceptions from trying to cross readline
    
    This is triggered by simply scrolling off the end of the dissasembly
    window.  This commit doesn't fix the actual exception that is being
    thrown, which will still need to be fixed, but makes sure that we
    don't ever throw an exception out to readline.
    
    gdb/ChangeLog:
    yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
    
            PR tui/9765
            * tui/tui-io.c (tui_getc): Rename to ...
            (tui_getc_1): ... this.
            (tui_get): New, reimplent as try/catch wrapper around tui_getc_1.
    
    Change-Id: I2e32a401ab34404b2132ec82a3e1c17b9b723e41
Comment 12 Sourceware Commits 2020-01-24 00:11:37 UTC
The master branch has been updated by Andrew Burgess <aburgess@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=733d0a679536628eb1be4b4b8aa6384de24ff1f1

commit 733d0a679536628eb1be4b4b8aa6384de24ff1f1
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Sat Jan 11 01:38:28 2020 +0000

    gdb/tui: asm window handles invalid memory and scrolls better
    
    This started as a patch to enable the asm window to handle attempts to
    disassemble invalid memory, but it ended up expanding into a
    significant rewrite of how the asm window handles scrolling.  These
    two things ended up being tied together as it was impossible to
    correctly test scrolling into invalid memory when the asm window would
    randomly behave weirdly while scrolling.
    
    Things that should work nicely now; scrolling to the bottom or top of
    the listing with PageUp, PageDown, Up Arrow, Down Arrow and we should
    be able to scroll past small areas of memory that don't have symbols
    associated with them.  It should also be possible to scroll to the
    start of a section even if there's no symbol at the start of the
    section.
    
    Adding tests for this scrolling was a little bit of a problem.  First
    I would have liked to add tests for PageUp / PageDown, but the tuiterm
    library we use doesn't support these commands right now due to only
    emulating a basic ascii terminal.  Changing this to emulate a more
    complex terminal would require adding support for more escape sequence
    control codes, so I've not tried to tackle that in this patch.
    
    Next, I would have liked to test scrolling to the start or end of the
    assembler listing and then trying to scroll even more, however, this
    is a problem because in a well behaving GDB a scroll at the start/end
    has no effect.  What we need to do is:
    
      - Move to start of assembler listing,
      - Send scroll up command,
      - Wait for all curses output,
      - Ensure the assembler listing is unchanged, we're still at the
        start of the listing.
    
    The problem is that there is no curses output, so how long do we wait
    at step 3?  The same problem exists for scrolling to the bottom of the
    assembler listing.  However, when scrolling down you can at least see
    the end coming, so I added a test for this case, however, this feels
    like an area of code that is massively under tested.
    
    gdb/ChangeLog:
    
    	PR tui/9765
    	* minsyms.c (lookup_minimal_symbol_by_pc_section): Update header
    	comment, add extra parameter, and update to store previous symbol
    	when appropriate.
    	* minsyms.h (lookup_minimal_symbol_by_pc_section): Update comment,
    	add extra parameter.
    	* tui/tui-disasm.c (tui_disassemble): Update header comment,
    	remove unneeded parameter, add try/catch around gdb_print_insn,
    	rewrite to add items to asm_lines vector.
    	(tui_find_backward_disassembly_start_address): New function.
    	(tui_find_disassembly_address): Updated throughout.
    	(tui_disasm_window::set_contents): Update for changes to
    	tui_disassemble.
    	(tui_disasm_window::do_scroll_vertical): No need to adjust the
    	number of lines to scroll.
    
    gdb/testsuite/ChangeLog:
    
    	PR tui/9765
    	* gdb.tui/tui-layout-asm.exp: Add scrolling test for asm window.
    
    Change-Id: I323987c8fd316962c937e73c17d952ccd3cfa66c
Comment 13 Shahab 2020-01-24 11:17:35 UTC
still one tiny issue:
https://sourceware.org/ml/gdb-patches/2020-01/msg00780.html
Comment 14 Sourceware Commits 2020-01-31 00:42:36 UTC
The master branch has been updated by Andrew Burgess <aburgess@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=42330a681af23a80d3e1f201d2a65886875e74bd

commit 42330a681af23a80d3e1f201d2a65886875e74bd
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Fri Jan 24 12:46:56 2020 +0000

    gdb/tui: Disassembler scrolling of very small programs
    
    In TUI mode, if the disassembly output for the program is less than
    one screen long, then currently if the user scrolls down until on the
    last assembly instruction is displayed and then tries to scroll up
    using Page-Up, the display doesn't update - they are stuck viewing the
    last line.
    
    If the user tries to scroll up using the Up-Arrow, then the display
    scrolls normally.
    
    What is happening is on the Page-Up we ask GDB to scroll backward the
    same number of lines as the height of the TUI ASM window.  The back
    scanner, which looks for a good place to start disassembling, fails to
    find a starting address which will provide the requested number of new
    lines before we get back to the original starting address (which is
    not surprising, our whole program contains less than a screen height
    of instructions), as a result the back scanner gives up and returns
    the original starting address.
    
    When we scroll with Up-Arrow we only ask the back scanner to find 1
    new instruction, which it manages to do, so this scroll works.
    
    The solution here is, when we fail to find enough instructions, to
    return the lowest address we did manage to find.  This will ensure we
    jump to the lowest possible address in the disassembly output.
    
    gdb/ChangeLog:
    
    	PR tui/9765
    	* tui/tui-disasm.c (tui_find_disassembly_address): If we don't
    	have enough lines to fill the screen, still return the lowest
    	address we found.
    
    gdb/testsuite/ChangeLog:
    
    	PR tui/9765
    	* gdb.tui/tui-layout-asm-short-prog.S: New file.
    	* gdb.tui/tui-layout-asm-short-prog.exp: New file.
    
    Change-Id: I6a6a7972c68a0559e9717fd8d82870b669a40af3
Comment 15 Shahab 2020-01-31 10:11:15 UTC
I can confirm every corner of the issue is resolved with the latest patch. Please confirm and close this bug.
Comment 16 Tom Tromey 2020-01-31 14:40:59 UTC
Fixed!