I tried to trace evince-3.28.4
execution using GDB
. There is a callq
instruction at some point in libdl
, which is shown below (i.e., at _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 │
When the execution reaches here, the backtrace is as follows:
#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
But when I enter ni
(to jump to the next assembly instruction), it turns into this:
#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
As can be seen, after a simple call and return, 4 elements are popped off the stack. Perhaps there is something special about the <_dl_signal_cexception()
, __GI__dl_catch_exception()
> pair. The stack is changed by some means other than call
or return
. It seems that _dl_signal_cexception()
finally leads to a __longjmp()
function at ../sysdeps/x86_64/__longjmp.S
which modifies the backtrace. Can someone describe the process?
Advertisement
Answer
As can be seen, after a simple call and return, 4 elements are popped off the stack. Perhaps there is something special about the
_dl_signal_cexception()
__GI__dl_catch_exception()
pair. The stack is changed by some means other than call or return.
Correct: the _dl_signal_exception
doesn’t return
, it uses longjmp
to transfer control not to its caller, but to its callers callers … caller.
It seems that
_dl_signal_cexception()
finally leads to a__longjmp()
Correct.
Can someone describe the process?
You appear to not understand what longjmp
does. Reading its man page and/or this example should help.
Update:
this approach for transition in control flow is somehow insane even compared to simple gotos … any other cases that I should consider?
Other “interesting” control transfers are via makecontext
, setcontext
and swapcontext
family of functions, and (in C++) throw
and catch
are pretty much equivalent to setjmp
and longjmp
.