{"id":570,"date":"2021-04-13T11:49:51","date_gmt":"2021-04-13T10:49:51","guid":{"rendered":"https:\/\/eocanha.org\/blog\/?p=570"},"modified":"2021-04-13T11:49:51","modified_gmt":"2021-04-13T10:49:51","slug":"gstreamer-webkit-debugging-tricks-using-gdb-1-2","status":"publish","type":"post","link":"https:\/\/eocanha.org\/blog\/2021\/04\/13\/gstreamer-webkit-debugging-tricks-using-gdb-1-2\/","title":{"rendered":"GStreamer WebKit debugging tricks using GDB (1\/2)"},"content":{"rendered":"\n<p>I&#8217;ve been developing and debugging desktop and mobile applications on embedded devices over the last decade or so. The main part of this period I&#8217;ve been focused on the multimedia side of the WebKit ports using GStreamer, an area that is a mix of C (glib, GObject and GStreamer) and C++ (WebKit).<\/p>\n\n\n\n<p>Over these years I&#8217;ve had to work on ARM embedded devices (mobile phones, set-top-boxes, Raspberry Pi using buildroot) where most of the environment aids and tools we take for granted on a regular x86 Linux desktop just aren&#8217;t available. In these situations you have to be imaginative and find your own way to get the work done and debug the issues you find in along the way.<\/p>\n\n\n\n<p>I&#8217;ve been writing down the most interesting tricks I&#8217;ve found in this journey and I&#8217;m sharing them with you in a series of 7 blog posts, one per week. Most of them aren&#8217;t mine, and the ones I learnt in the begining of my career can even seem a bit naive, but I find them worth to share anyway. I hope you find them as useful as I do.<\/p>\n\n\n\n<h2 id=\"breakpoints-with-command\">Breakpoints with command<\/h2>\n\n\n\n<p>You can break on a place, run some command and continue execution. Useful to get logs:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">break getenv\ncommand\n # This disables scroll continue messages\n # and supresses output\n silent\n set pagination off\n p (char*)$r0\ncontinue\nend\n\nbreak grl-xml-factory.c:2720 if (data != 0)\ncommand\n call grl_source_get_id(data->source)\n # $ is the last value in the history, the result of\n # the previous call\n call grl_media_set_source (send_item->media, $)\n call grl_media_serialize_extended (send_item->media, \n  GRL_MEDIA_SERIALIZE_FULL)\n continue\nend<\/pre>\n\n\n\n<p>This idea can be combined with watchpoints and <a href=\"https:\/\/www.collabora.com\/about-us\/blog\/2015\/04\/13\/tracking-the-reference-count-of-a-gstminiobject-using-gdb\/\">applied to trace reference counting in GObjects and know from which places the refcount is increased and decreased<\/a>.<\/p>\n\n\n\n<h2>Force execution of an if branch<\/h2>\n\n\n\n<p>Just wait until the if chooses a branch and then jump to the other one:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">6 if (i > 3) {\n(gdb) next\n7 printf(\"%d > 3\\n\", i);\n(gdb) break 9\n(gdb) jump 9\n9 printf(\"%d &lt;= 3\\n\", i);\n(gdb) next\n5 &lt;= 3<\/pre>\n\n\n\n<h2>Debug glib warnings<\/h2>\n\n\n\n<p>If you get a warning message like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">W\/GLib-GObject(18414): g_object_unref: assertion `G_IS_OBJECT (object)' failed<\/pre>\n\n\n\n<p>the functions involved are: <code>g_return_if_fail_warning()<\/code>, which calls to <code>g_log()<\/code>. It&#8217;s good to set a breakpoint in any of the two:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">break g_log<\/pre>\n\n\n\n<p>Another method is to <code>export G_DEBUG=fatal_criticals<\/code>, which will convert all the criticals in crashes, which will stop the debugger.<\/p>\n\n\n\n<h2>Debug GObjects<\/h2>\n\n\n\n<p>If you want to inspect the contents of a GObjects that you have in a reference\u2026<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">(gdb) print web_settings \n$1 = (WebKitWebSettings *) 0x7fffffffd020<\/pre>\n\n\n\n<p>you can dereference it\u2026<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">(gdb) print *web_settings\n$2 = {parent_instance = {g_type_instance = {g_class = 0x18}, ref_count = 0, qdata = 0x0}, priv = 0x0}<\/pre>\n\n\n\n<p>even if it&#8217;s an untyped gpointer\u2026<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">(gdb) print user_data\n(void *) 0x7fffffffd020\n(gdb) print *((WebKitWebSettings *)(user_data))\n{parent_instance = {g_type_instance = {g_class = 0x18}, ref_count = 0, qdata = 0x0}, priv = 0x0}<\/pre>\n\n\n\n<p>To find the type, you can use GType:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">(gdb) call (char*)g_type_name( ((GTypeInstance*)0x70d1b038)->g_class->g_type )\n$86 = 0x2d7e14 \"GstOMXH264Dec-omxh264dec\"<\/pre>\n\n\n\n<h2>Instantiate C++ object from gdb<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">(gdb) call malloc(sizeof(std::string))\n$1 = (void *) 0x91a6a0\n(gdb) call ((std::string*)0x91a6a0)->basic_string()\n(gdb) call ((std::string*)0x91a6a0)->assign(\"Hello, World\")\n$2 = (std::basic_string&lt;char, std::char_traits&lt;char>, std::allocator&lt;char> > &amp;) @0x91a6a0: {static npos = &lt;optimized out>, _M_dataplus = {&lt;std::allocator&lt;char>> = {&lt;__gnu_cxx::new_allocator&lt;char>> = {&lt;No data fields>}, &lt;No data fields>}, _M_p = 0x91a6f8 \"Hello, World\"}}\n(gdb) call SomeFunctionThatTakesAConstStringRef(*(const std::string*)0x91a6a0)<\/pre>\n\n\n\n<p>See: <a href=\"http:\/\/stackoverflow.com\/questions\/7060099\/how-to-call-constructor-in-gdb-for-pretty-printers\">1<\/a> and <a href=\"http:\/\/stackoverflow.com\/a\/11311786\/752445\">2<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been developing and debugging desktop and mobile applications on embedded devices over the last decade or so. The main part of this period I&#8217;ve been focused on the multimedia side of the WebKit ports using GStreamer, an area that is a mix of C (glib, GObject and GStreamer) and C++ (WebKit). Over these years &hellip; <a href=\"https:\/\/eocanha.org\/blog\/2021\/04\/13\/gstreamer-webkit-debugging-tricks-using-gdb-1-2\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">GStreamer WebKit debugging tricks using GDB (1\/2)<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[11,13,2,1,7,12],"tags":[20],"_links":{"self":[{"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/posts\/570"}],"collection":[{"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/comments?post=570"}],"version-history":[{"count":7,"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/posts\/570\/revisions"}],"predecessor-version":[{"id":594,"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/posts\/570\/revisions\/594"}],"wp:attachment":[{"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/media?parent=570"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/categories?post=570"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eocanha.org\/blog\/wp-json\/wp\/v2\/tags?post=570"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}