weirdNox / emacs-gdb

GDB graphical interface for GNU Emacs
GNU General Public License v3.0
177 stars 10 forks source link

Segmentation fault #5

Closed kevinboulain closed 3 years ago

kevinboulain commented 5 years ago

Happens when I debug a program that asserts in a thread. I simply wanted to r (run) until it crashes then up until I get in user code to peek around. When I reach user code, a crash follows. A dummy program with a pthread_create & assert doesn't trigger the crash so sorry for the lack of example program.

Emacs' trace (truncated for brevity):

Fatal error 11: Segmentation fault
Backtrace:
emacs[0x4abee7]
emacs[0x492ec7]
emacs[0x4aa74e]
emacs[0x4aa948]
emacs[0x4aa9c9]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x128e0)[0x7f8c517dc8e0]
.../emacs/straight/build/gdb-mi/gdb-module.so(+0x997b)[0x7f8c4da6397b]
emacs[0x530978]
...

And the culprit is:

addr2line -e .../emacs/straight/build/gdb-mi/gdb-module.so +0x997b
.../emacs/straight/build/gdb-mi/gdb-module.c:1011

In my copy of gdb-module.c, line 1011 is the switch on Output->kind (I patched it to display Output's address so on master it should be line 1010):

diff --git i/gdb-module.c w/gdb-module.c
index 2c66ffc..a202ac3 100644
--- i/gdb-module.c
+++ w/gdb-module.c
@@ -1007,6 +1007,7 @@ static emacs_value handleGdbMiOutput(emacs_env *Env, ptrdiff_t NumberOfArgs,

     char *PrintString = 0;
     for(mi_output *Output = ParserOutput; Output; Output = Output->next) {
+        dprintf(2, ">>> Output:%p\n", Output);
         switch(Output->kind) {
             case GDBWIRE_MI_OUTPUT_OOB: {
                 handleMiOobRecord(Env, Output->variant.oob_record, &PrintString);

Right before crashing Emacs I get:

...
>>> Output:0x4052fe0
>>> Output:0x2ff8530
>>> Output:0x30

So there is probably a NULL pointer used somewhere.

By the way, why not compile gdb-module.so with debug symbols? It could help bug reports by giving you the line of crash (I had to modify the Makefile and recompile).

I hope it's enough, if is isn't feel free to request more.

martin5233 commented 5 years ago

I had a similar problem, which went away, when I switched to compiling the module with debug flags instead of release flags. As it works this way, I haven't investigated further.

weirdNox commented 5 years ago

By the way, why not compile gdb-module.so with debug symbols?

I don't know if debug symbols are any good using optimizations, but I could try it.

Thanks for the report, going to investigate this week!

kevinboulain commented 5 years ago

I don't know if debug symbols are any good using optimizations, but I could try it.

I think it's fairly common to enable both.

Regarding the segfault, ParserOutput is NULL.

weirdNox commented 5 years ago

Weird, I've tried to reproduce the problem locally and wasn't able to. Could you provide a minimal example?

Also, I think ParserOutput being 0 shouldn't be a problem, it is used in the loop (which verifies if it is non 0) and it is used in gdbwire_mi_output_free which also verifies.

kevinboulain commented 5 years ago

Unfortunately, I can't provide an example (but I can reproduce locally).

Hope this helps (I can't quite see how this is possible yet, the control flow seems a bit weird):

=================================================================
==17697==ERROR: AddressSanitizer: heap-use-after-free on address 0x6040001c3df0 at pc 0x7fd5f7fe0d2b bp 0x7ffc751ab0f0 sp 0x7ffc751ab0e8
READ of size 8 at 0x6040001c3df0 thread T0
    #0 0x7fd5f7fe0d2a in handleGdbMiOutput .../straight/build/gdb-mi/gdb-module.c:1009
    #1 0x530977 in funcall_module .../emacs/src/emacs-module.c:778
    #2 0x5065fc in Ffuncall .../emacs/src/eval.c:2783
    #3 0x53ef9f in exec_byte_code .../emacs/src/bytecode.c:629
    #4 0x5065fc in Ffuncall .../emacs/src/eval.c:2783
    #5 0x53ef9f in exec_byte_code .../emacs/src/bytecode.c:629
    #6 0x5065fc in Ffuncall .../emacs/src/eval.c:2783
    #7 0x507fa7 in Fapply .../emacs/src/eval.c:2389
    #8 0x508295 in apply1 .../emacs/src/eval.c:2605
    #9 0x5058d5 in internal_condition_case_1 .../emacs/src/eval.c:1356
    #10 0x541ed0 in read_and_dispose_of_process_output .../emacs/src/process.c:6004
    #11 0x541ed0 in read_process_output .../emacs/src/process.c:5915
    #12 0x5499ad in wait_reading_process_output .../emacs/src/process.c:5614
    #13 0x412351 in sit_for .../emacs/src/dispnew.c:5793
    #14 0x49e48d in read_char .../emacs/src/keyboard.c:2717
    #15 0x49f97a in read_key_sequence .../emacs/src/keyboard.c:9147
    #16 0x4a101b in command_loop_1 .../emacs/src/keyboard.c:1368
    #17 0x50583d in internal_condition_case .../emacs/src/eval.c:1332
    #18 0x493243 in command_loop_2 .../emacs/src/keyboard.c:1110
    #19 0x5057ac in internal_catch .../emacs/src/eval.c:1097
    #20 0x4931da in command_loop .../emacs/src/keyboard.c:1089
    #21 0x49764d in recursive_edit_1 .../emacs/src/keyboard.c:695
    #22 0x4979a7 in Frecursive_edit .../emacs/src/keyboard.c:766
    #23 0x4092d4 in main .../emacs/src/emacs.c:1713
    #24 0x7fd5fe081b16 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x22b16)
    #25 0x409ec9 in _start (.../emacs/bin/emacs-26.1+0x409ec9)

0x6040001c3df0 is located 32 bytes inside of 40-byte region [0x6040001c3dd0,0x6040001c3df8)
freed by thread T0 here:
    #0 0x7fd5ff0c8b50 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xe8b50)
    #1 0x7fd5f7fbdc05 in gdbwire_mi_output_free gdbwire.c:2065
    #2 0x7fd5f7fbdbc5 in gdbwire_mi_output_free gdbwire.c:2062
    #3 0x7fd5f7fbdbc5 in gdbwire_mi_output_free gdbwire.c:2062
    #4 0x7fd5f7fe0d49 in handleGdbMiOutput .../straight/build/gdb-mi/gdb-module.c:1031
    #5 0x530977 in funcall_module .../emacs/src/emacs-module.c:778
    #6 0x5065fc in Ffuncall .../emacs/src/eval.c:2783

previously allocated by thread T0 here:
    #0 0x7fd5ff0c90b8 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xe90b8)
    #1 0x7fd5f7fbd942 in gdbwire_mi_output_alloc gdbwire.c:2035
    #2 0x7fd5f7fd671a in gdbwire_mi_push_parse gdbwire.c:7105
    #3 0x7fd5f7fbd671 in gdbwire_mi_parser_parse_line gdbwire.c:1814
    #4 0x7fd5f7fbcc41 in gdbwire_mi_parser_push_data gdbwire.c:1967
    #5 0x7fd5f7fbc7cb in gdbwire_mi_parser_push gdbwire.c:1929
    #6 0x7fd5f7fe0899 in handleGdbMiOutput .../straight/build/gdb-mi/gdb-module.c:1005
    #7 0x530977 in funcall_module .../emacs/src/emacs-module.c:778
    #8 0x5065fc in Ffuncall .../emacs/src/eval.c:2783

SUMMARY: AddressSanitizer: heap-use-after-free .../straight/build/gdb-mi/gdb-module.c:1009 in handleGdbMiOutput
Shadow bytes around the buggy address:
  0x0c0880030760: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x0c0880030770: fa fa 00 00 00 00 00 00 fa fa fd fd fd fd fd fd
  0x0c0880030780: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x0c0880030790: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x0c08800307a0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
=>0x0c08800307b0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd[fd]fa
  0x0c08800307c0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x0c08800307d0: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x0c08800307e0: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x0c08800307f0: fa fa 00 00 00 00 00 00 fa fa fd fd fd fd fd fd
  0x0c0880030800: fa fa fd fd fd fd fd fd fa fa 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==17697==ABORTING
dvzubarev commented 3 years ago

Hi, I had the same crash, when stepping in std library function. I could reproduce this crash on my work machine, but couldn't on my notebook. I used the following code:

#include <iostream>
#include <memory>

struct temp_t{
    void fun(int k){
        std::cout<<"fun "<<k<<std::endl;
    }
};

int main(){
    std::unique_ptr<temp_t> pt (new temp_t);
    pt->fun(3);
}

Set break on pt->fun(3); and step into, Emacs will find unique_ptr.h and crash immediately. It turned out that the main culprit is lsp-mode and its prompt when you entering files outside of your project. Since I use nix for dependency management, stdlib files are located in non-standard location: /nix/store/... and this folder is not blacklisted by default for c++. There was standard lsp-mode prompt:

%s is not part of any project. Select action:
%s==>Import project root %s. 
....

Actually I didn't see this prompt unless i started debug this crash under gdb. So It is possible that this prompt somehow interfere with parsing output from gdb?? When I added /nix/store to blacklisted folders (to disable prompt) this crash has gone.

geza-herman commented 3 years ago

This happens for me as well, immediately after starting emacs-gdb. Here's some additional information what happens:

weirdNox commented 3 years ago

@geza-herman, thanks for the detailed report! Does this commit fix your problem? The handling of GDB's output may happen at different times, and maybe it depends on Emacs version, build configuration, environment, etc, so I tried to prevent going into the C module when we are already processing previous output. I had never encountered that issue, so please tell me if it works for you!

geza-herman commented 3 years ago

Thanks for the quick response! It fixes the issue for me. Thank you (and thank you for developing this package, it's very useful)!.

weirdNox commented 3 years ago

Awesome! Happy to help :) As I had been using and fixing some things in the package this week, I had the codebase in my head so the fix was pretty clear to me, after your description.

I'll close the issue, assuming this fixes the rest of the segmentation faults, reopen or create another issue if necessary.