Странная обратная трассировка после инструкций по вызову - PullRequest
1 голос
/ 23 февраля 2020

Я пытался отследить evince-3.28.4 выполнение, используя GDB. В некоторой точке в libdl есть инструкция callq, которая показана ниже (т. Е. В _dl_lookup_symbol_x+840):

 │0x7ffff7de03f5 <_dl_lookup_symbol_x+837>        mov    %rbx,%rsi                              │
>│0x7ffff7de03f8 <_dl_lookup_symbol_x+840>        callq  0x7ffff7df0b00 <_dl_signal_cexception> │
 │0x7ffff7de03fd <_dl_lookup_symbol_x+845>        mov    %rbx,%rdi                              │

Когда выполнение достигает здесь, обратная трассировка выглядит следующим образом:

#0  0x00007ffff7de03f8 in _dl_lookup_symbol_x (undef_name=0x7ffff744fa23 "gtk_progress_get_type", undef_map=0x7ffff7ffe170, ref=0x7fffffffd8d8, symbol_scope=0x7ffff7ffe4f8, version=0x0, type_class=0, flags=2, skip_map=<optimized out>) at dl-lookup.c:857
#1  0x00007ffff4bd6da6 in do_sym (flags=2, vers=0x0, who=0x7ffff486d48e <g_module_symbol+126>, name=0x7ffff744fa23 "gtk_progress_get_type", handle=0x7ffff7ffe170)
at dl-sym.c:151
#2  0x00007ffff4bd6da6 in _dl_sym (handle=0x7ffff7ffe170, name=0x7ffff744fa23 "gtk_progress_get_type", who=0x7ffff486d48e <g_module_symbol+126>) at dl-sym.c:254
#3  0x00007fffefcdf0e4 in dlsym_doit (a=a@entry=0x7fffffffdb20) at dlsym.c:50
#4  0x00007ffff4bd72df in __GI__dl_catch_exception (exception=exception@entry=0x7fffffffdab0, operate=0x7fffefcdf0d0 <dlsym_doit>, args=0x7fffffffdb20)
at dl-error-skeleton.c:196
#5  0x00007ffff4bd736f in __GI__dl_catch_error (objname=0x5555557d44a0, errstring=0x5555557d44a8, mallocedp=0x5555557d4498, operate=<optimized out>, args=<optimized out>) at dl-error-skeleton.c:215
#6  0x00007fffefcdf735 in _dlerror_run (operate=operate@entry=0x7fffefcdf0d0 <dlsym_doit>, args=args@entry=0x7fffffffdb20) at dlerror.c:162
#7  0x00007fffefcdf166 in __dlsym (handle=handle@entry=0x7ffff7ffe170, name=name@entry=0x7ffff744fa23 "gtk_progress_get_type") at dlsym.c:70
#8  0x00007ffff486d48e in _g_module_symbol (symbol_name=0x7ffff744fa23 "gtk_progress_get_type", handle=0x7ffff7ffe170) at ../../../../gmodule/gmodule-dl.c:163
#9  0x00007ffff486d48e in g_module_symbol (module=module@entry=0x5555557d44c0, symbol_name=symbol_name@entry=0x7ffff744fa23 "gtk_progress_get_type", symbol=symbol@entry=0x7fffffffdba0) at ../../../../gmodule/gmodule.c:800
#10 0x00007ffff728f55e in _gtk_module_has_mixed_deps (module_to_check=module_to_check@entry=0x0) at ../../../../gtk/gtkmodules.c:594
#11 0x00007ffff728f703 in find_module (name=0x5555557db040 "gail") at ../../../../gtk/gtkmodules.c:227
#12 0x00007ffff728f703 in load_module (name=0x5555557db040 "gail", module_list=0x0) at ../../../../gtk/gtkmodules.c:292
#13 0x00007ffff728f703 in load_modules (module_str=module_str@entry=0x5555557d44f0 "gail:atk-bridge") at ../../../../gtk/gtkmodules.c:423
#14 0x00007ffff728fb64 in _gtk_modules_init (argc=0x0, argv=<optimized out>, gtk_modules_args=0x5555557d44f0 "gail:atk-bridge") at ../../../../gtk/gtkmodules.c:544
#15 0x00007ffff726786b in do_post_parse_initialization (argc=0x0, argv=0x0) at ../../../../gtk/gtkmain.c:755
#16 0x00007ffff726786b in post_parse_hook (context=<optimized out>, group=<optimized out>, data=0x5555557d0cd0, error=0x7fffffffdd98) at ../../../../gtk/gtkmain.c:798
#17 0x00007ffff54768a8 in g_option_context_parse (context=<optimized out>, argc=<optimized out>, argv=<optimized out>, error=<optimized out>)
at ../../../../glib/goption.c:2165
#18 0x0000555555573386 in main (argc=<optimized out>, argv=<optimized out>) at main.c:275

Но когда я ввожу ni (чтобы перейти к следующей инструкции по сборке), это превращается в следующее:

#0  0x00007ffff4bd72cd in __GI__dl_catch_exception (exception=exception@entry=0x7fffffffdab0, operate=0x7fffefcdf0d0 <dlsym_doit>, args=0x7fffffffdb20)
at dl-error-skeleton.c:194
#1  0x00007ffff4bd736f in __GI__dl_catch_error (objname=0x5555557d44a0, errstring=0x5555557d44a8, mallocedp=0x5555557d4498, operate=<optimized out>, args=<optimized out>) at dl-error-skeleton.c:215
#2  0x00007fffefcdf735 in _dlerror_run (operate=operate@entry=0x7fffefcdf0d0 <dlsym_doit>, args=args@entry=0x7fffffffdb20) at dlerror.c:162
#3  0x00007fffefcdf166 in __dlsym (handle=handle@entry=0x7ffff7ffe170, name=name@entry=0x7ffff744fa23 "gtk_progress_get_type") at dlsym.c:70
#4  0x00007ffff486d48e in _g_module_symbol (symbol_name=0x7ffff744fa23 "gtk_progress_get_type", handle=0x7ffff7ffe170) at ../../../../gmodule/gmodule-dl.c:163
#5  0x00007ffff486d48e in g_module_symbol (module=module@entry=0x5555557d44c0, symbol_name=symbol_name@entry=0x7ffff744fa23 "gtk_progress_get_type", symbol=symbol@entry=0x7fffffffdba0) at ../../../../gmodule/gmodule.c:800
#6  0x00007ffff728f55e in _gtk_module_has_mixed_deps (module_to_check=module_to_check@entry=0x0) at ../../../../gtk/gtkmodules.c:594
#7  0x00007ffff728f703 in find_module (name=0x5555557db040 "gail") at ../../../../gtk/gtkmodules.c:227
#8  0x00007ffff728f703 in load_module (name=0x5555557db040 "gail", module_list=0x0) at ../../../../gtk/gtkmodules.c:292
#9  0x00007ffff728f703 in load_modules (module_str=module_str@entry=0x5555557d44f0 "gail:atk-bridge") at ../../../../gtk/gtkmodules.c:423
#10 0x00007ffff728fb64 in _gtk_modules_init (argc=0x0, argv=<optimized out>, gtk_modules_args=0x5555557d44f0 "gail:atk-bridge") at ../../../../gtk/gtkmodules.c:544
#11 0x00007ffff726786b in do_post_parse_initialization (argc=0x0, argv=0x0) at ../../../../gtk/gtkmain.c:755
#12 0x00007ffff726786b in post_parse_hook (context=<optimized out>, group=<optimized out>, data=0x5555557d0cd0, error=0x7fffffffdd98) at ../../../../gtk/gtkmain.c:798
#13 0x00007ffff54768a8 in g_option_context_parse (context=<optimized out>, argc=<optimized out>, argv=<optimized out>, error=<optimized out>)
at ../../../../glib/goption.c:2165
#14 0x0000555555573386 in main (argc=<optimized out>, argv=<optimized out>) at main.c:275

Как видно, после простого вызова и возврата , 4 элемента выталкиваются из стека. Возможно, в паре <<code>_dl_signal_cexception(), __GI__dl_catch_exception()> есть что-то особенное. Стек изменяется другими способами, кроме call или return. Кажется, что _dl_signal_cexception() в конечном итоге приводит к функции __longjmp() в ../sysdeps/x86_64/__longjmp.S, которая изменяет обратную трассировку. Может кто-нибудь описать процесс?

1 Ответ

1 голос
/ 23 февраля 2020

Как видно, после простого вызова и возврата 4 элемента выталкиваются из стека. Возможно, в паре _dl_signal_cexception() __GI__dl_catch_exception() есть что-то особенное. Стек изменяется другими способами, кроме вызова или возврата.

Правильно: _dl_signal_exception не return, он использует longjmp для передачи управления не своему вызывающему, а его вызывающие абоненты ... вызывающие абоненты.

Кажется, что _dl_signal_cexception(), наконец, приводит к __longjmp()

Правильно.

Может кто-нибудь описать процесс?

Вы, кажется, не понимаете, что делает longjmp. Чтение справочной страницы и / или этого примера должно помочь.

Обновление:

этот подход для переход в потоке управления каким-то безумным даже по сравнению с простыми gotos ... какие-либо другие случаи, которые я должен рассмотреть?

Другие "интересные" передачи управления через makecontext, setcontext и swapcontext семейство функций, и (в C ++) throw и catch в значительной степени эквивалентны setjmp и longjmp.

...