[{"id":19888,"web_url":"https://patchwork.libcamera.org/comment/19888/","msgid":"<3935117f244d6554ddbcbf756f6c9a8b76017335.camel@ndufresne.ca>","date":"2021-09-27T14:06:40","subject":"Re: [libcamera-devel] [PATCH v1 4/4] libcamera: base: backtrace:\n\tFallback to libunwind for symbolic names","submitter":{"id":30,"url":"https://patchwork.libcamera.org/api/people/30/","name":"Nicolas Dufresne","email":"nicolas@ndufresne.ca"},"content":"Le vendredi 24 septembre 2021 à 13:23 +0300, Laurent Pinchart a écrit :\n> libunwind has an API to provide symbolic names for functions. It's less\n> optimal than using backtrace_symbols() or libdw, as it doesn't allow\n> deferring the symbolic names lookup, but it can be usefull as a fallback\n> if no other option is available.\n> \n> A sample backtrace when falling back to libunwind looks like\n> \n> libcamera::VimcCameraData::init()+0xbd\n> libcamera::PipelineHandlerVimc::match(libcamera::DeviceEnumerator*)+0x3e0\n> libcamera::CameraManager::Private::createPipelineHandlers()+0x1a7\n> libcamera::CameraManager::Private::init()+0x98\n> libcamera::CameraManager::Private::run()+0x9f\n> libcamera::Thread::startThread()+0xee\n> decltype(*(std::__1::forward<libcamera::Thread*>(fp0)).*fp()) std::__1::__invoke<void (libcamera::Thread::*)(), libcamera::Thread*, void>(void (libcamera::Thread::*&&)(), libcamera::Thread*&&)+0x77\n> void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (libcamera::Thread::*)(), libcamera::Thread*, 2ul>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (libcamera::Thread::*)(), libcamera::Thread*>&, std::__1::__tuple_indices<2ul>)+0x3e\n> void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (libcamera::Thread::*)(), libcamera::Thread*> >(void*)+0x62\n> start_thread+0xde\n> ???\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  include/libcamera/base/backtrace.h |  1 +\n>  src/libcamera/base/backtrace.cpp   | 37 +++++++++++++++++++++++++++++-\n>  2 files changed, 37 insertions(+), 1 deletion(-)\n> \n> diff --git a/include/libcamera/base/backtrace.h b/include/libcamera/base/backtrace.h\n> index 58ccc14c8f81..bb77c73b67e3 100644\n> --- a/include/libcamera/base/backtrace.h\n> +++ b/include/libcamera/base/backtrace.h\n> @@ -30,6 +30,7 @@ private:\n>  \tbool unwindTrace();\n>  \n>  \tstd::vector<void *> backtrace_;\n> +\tstd::vector<std::string> backtraceText_;\n>  };\n>  \n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/base/backtrace.cpp b/src/libcamera/base/backtrace.cpp\n> index 40fa60d0f9bf..bbb0cc0e17da 100644\n> --- a/src/libcamera/base/backtrace.cpp\n> +++ b/src/libcamera/base/backtrace.cpp\n> @@ -196,6 +196,12 @@ bool Backtrace::unwindTrace()\n>  \t\treturn false;\n>  \n>  \tdo {\n> +#if HAVE_BACKTRACE || HAVE_DW\n> +\t\t/*\n> +\t\t * If backtrace() or libdw is available, they will be used in\n> +\t\t * toString() to provide symbol information for the stack\n> +\t\t * frames using the IP register value.\n> +\t\t */\n>  \t\tunw_word_t ip;\n>  \t\tret = unw_get_reg(&cursor, UNW_REG_IP, &ip);\n>  \t\tif (ret) {\n> @@ -204,6 +210,29 @@ bool Backtrace::unwindTrace()\n>  \t\t}\n>  \n>  \t\tbacktrace_.push_back(reinterpret_cast<void *>(ip));\n> +#else\n> +\t\t/*\n> +\t\t * Otherwise, use libunwind to get the symbol information. As\n> +\t\t * the libunwind API uses cursors, we can't store the IP values\n> +\t\t * and delay symbol lookup to toString().\n> +\t\t */\n> +\t\tchar symbol[256];\n> +\t\tunw_word_t offset = 0;\n> +\t\tret = unw_get_proc_name(&cursor, symbol, sizeof(symbol), &offset);\n> +\t\tif (ret) {\n> +\t\t\tbacktraceText_.emplace_back(\"???\\n\");\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tstd::ostringstream entry;\n> +\n> +\t\tchar *name = abi::__cxa_demangle(symbol, nullptr, nullptr, nullptr);\n> +\t\tentry << (name ? name : symbol);\n> +\t\tfree(name);\n\nPerhaps a smart pointer.\n\n> +\n> +\t\tentry << \"+0x\" << std::hex << offset << \"\\n\";\n> +\t\tbacktraceText_.emplace_back(entry.str());\n> +#endif\n>  \t} while (unw_step(&cursor) > 0);\n>  \n>  \treturn true;\n> @@ -239,9 +268,15 @@ std::string Backtrace::toString(unsigned int skipLevels) const\n>  \t */\n>  \tskipLevels += 2;\n>  \n> -\tif (backtrace_.size() <= skipLevels)\n> +\tif (backtrace_.size() <= skipLevels &&\n> +\t    backtraceText_.size() <= skipLevels)\n>  \t\treturn std::string();\n>  \n> +\tif (!backtraceText_.empty()) {\n> +\t\tSpan<const std::string> trace{ backtraceText_ };\n> +\t\treturn utils::join(trace.subspan(skipLevels), \"\");\n> +\t}\n> +\n>  #if HAVE_DW\n>  \tDwflParser dwfl;\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 6A40FC3243\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 27 Sep 2021 14:06:44 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D69416918B;\n\tMon, 27 Sep 2021 16:06:43 +0200 (CEST)","from mail-qk1-x72a.google.com (mail-qk1-x72a.google.com\n\t[IPv6:2607:f8b0:4864:20::72a])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C1D566012C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 27 Sep 2021 16:06:42 +0200 (CEST)","by mail-qk1-x72a.google.com with SMTP id 72so36697109qkk.7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 27 Sep 2021 07:06:42 -0700 (PDT)","from nicolas-tpx395.localdomain (173-246-12-168.qc.cable.ebox.net.\n\t[173.246.12.168]) by smtp.gmail.com with ESMTPSA id\n\tbk20sm6498787qkb.13.2021.09.27.07.06.40\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 27 Sep 2021 07:06:41 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=ndufresne-ca.20210112.gappssmtp.com\n\theader.i=@ndufresne-ca.20210112.gappssmtp.com\n\theader.b=\"zTI3KHfZ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ndufresne-ca.20210112.gappssmtp.com; s=20210112;\n\th=message-id:subject:from:to:date:in-reply-to:references:user-agent\n\t:mime-version:content-transfer-encoding;\n\tbh=3heC4q49zYNludAybHYRWo2T88qB6oyvWELwpXTtt+U=;\n\tb=zTI3KHfZ2XNxTV9W+1ja4tTX666K928rTTm3gnLBeul2b1eGqB20PZLoTOn8pgxVyu\n\tlmIrDofveBB1JIF8IHfD1TOQxb8vFPERT0qKB4D59zX2UI7W7JyZvBKm1CRSwZH5tTn5\n\tYNg7x9De33OLS8oaJT6EmJCudoE5+rLeXMAGQJ2psJ7sgKESZp02ltAMpEq+eR8lNvQ4\n\t6nhy+AYSyGMgwYLT8yfqRT5ITxCTGlc0mcJygw5FC0RaAnmBHj/0h9Oibw+IUBt5BtIT\n\tUPIG+m2O1CTVF87Neq3Z56CWc+UHhwzlg63spZLen0MYuYs7BI5Crf5u7pp9KmozBDTj\n\tdr9Q==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:message-id:subject:from:to:date:in-reply-to\n\t:references:user-agent:mime-version:content-transfer-encoding;\n\tbh=3heC4q49zYNludAybHYRWo2T88qB6oyvWELwpXTtt+U=;\n\tb=QpBkTdMBFZd8P/WrpV1oZpTXJ57OmivQ90ZCMsGdeKdzhzxf0SpD1R6r7up2e0Ue7E\n\tUynTV0FsHMs2JDm1wALlqHOzZ6bLWmZb2P2Zw0QPUPbU6U2OGq5zgtodkVA5a/eiHv9f\n\tibl4M1EgPM2xls6JVoAIBX+2otjEklU6Ned2PTn/kM1nCg9c+HvWNbrXF/jcSEleCkp0\n\t/xqm3cPeeQNckmNry6sPTCS7DKjRtsGg+jePABGA41xbqivjPYXIfUqa61IMGegg7TPP\n\tMlhbQwj6viZQPZV1wqRpZEp0zyrnxK7mLAX9CCQq9mBxvtZOVIqgfD8JkseKtMYe9JUh\n\tGNCA==","X-Gm-Message-State":"AOAM530ESNQT+DT/yUiPxi+Sd3tPCkdnngIpRzogJqqIZrmUYsXE38Jc\n\tUAJwM6+i9UH5AfvRbZfSEwsPmgncFVuFEA==","X-Google-Smtp-Source":"ABdhPJxptOcNkBwbLyY8kTj8c6/hKwJWJ4ahS/SaigqzCzUNrqbxKTLBOnN0T+t7lQkn/inQ2J02Rw==","X-Received":"by 2002:a05:620a:430c:: with SMTP id\n\tu12mr66514qko.439.1632751601452; \n\tMon, 27 Sep 2021 07:06:41 -0700 (PDT)","Message-ID":"<3935117f244d6554ddbcbf756f6c9a8b76017335.camel@ndufresne.ca>","From":"Nicolas Dufresne <nicolas@ndufresne.ca>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 27 Sep 2021 10:06:40 -0400","In-Reply-To":"<20210924102323.26787-5-laurent.pinchart@ideasonboard.com>","References":"<20210924102323.26787-1-laurent.pinchart@ideasonboard.com>\n\t<20210924102323.26787-5-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","User-Agent":"Evolution 3.40.4 (3.40.4-1.fc34) ","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH v1 4/4] libcamera: base: backtrace:\n\tFallback to libunwind for symbolic names","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":19912,"web_url":"https://patchwork.libcamera.org/comment/19912/","msgid":"<YVJ/tirXFzXcs/WD@pendragon.ideasonboard.com>","date":"2021-09-28T02:36:38","subject":"Re: [libcamera-devel] [PATCH v1 4/4] libcamera: base: backtrace:\n\tFallback to libunwind for symbolic names","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Nicolas,\n\nOn Mon, Sep 27, 2021 at 10:06:40AM -0400, Nicolas Dufresne wrote:\n> Le vendredi 24 septembre 2021 à 13:23 +0300, Laurent Pinchart a écrit :\n> > libunwind has an API to provide symbolic names for functions. It's less\n> > optimal than using backtrace_symbols() or libdw, as it doesn't allow\n> > deferring the symbolic names lookup, but it can be usefull as a fallback\n> > if no other option is available.\n> > \n> > A sample backtrace when falling back to libunwind looks like\n> > \n> > libcamera::VimcCameraData::init()+0xbd\n> > libcamera::PipelineHandlerVimc::match(libcamera::DeviceEnumerator*)+0x3e0\n> > libcamera::CameraManager::Private::createPipelineHandlers()+0x1a7\n> > libcamera::CameraManager::Private::init()+0x98\n> > libcamera::CameraManager::Private::run()+0x9f\n> > libcamera::Thread::startThread()+0xee\n> > decltype(*(std::__1::forward<libcamera::Thread*>(fp0)).*fp()) std::__1::__invoke<void (libcamera::Thread::*)(), libcamera::Thread*, void>(void (libcamera::Thread::*&&)(), libcamera::Thread*&&)+0x77\n> > void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (libcamera::Thread::*)(), libcamera::Thread*, 2ul>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (libcamera::Thread::*)(), libcamera::Thread*>&, std::__1::__tuple_indices<2ul>)+0x3e\n> > void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (libcamera::Thread::*)(), libcamera::Thread*> >(void*)+0x62\n> > start_thread+0xde\n> > ???\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  include/libcamera/base/backtrace.h |  1 +\n> >  src/libcamera/base/backtrace.cpp   | 37 +++++++++++++++++++++++++++++-\n> >  2 files changed, 37 insertions(+), 1 deletion(-)\n> > \n> > diff --git a/include/libcamera/base/backtrace.h b/include/libcamera/base/backtrace.h\n> > index 58ccc14c8f81..bb77c73b67e3 100644\n> > --- a/include/libcamera/base/backtrace.h\n> > +++ b/include/libcamera/base/backtrace.h\n> > @@ -30,6 +30,7 @@ private:\n> >  \tbool unwindTrace();\n> >  \n> >  \tstd::vector<void *> backtrace_;\n> > +\tstd::vector<std::string> backtraceText_;\n> >  };\n> >  \n> >  } /* namespace libcamera */\n> > diff --git a/src/libcamera/base/backtrace.cpp b/src/libcamera/base/backtrace.cpp\n> > index 40fa60d0f9bf..bbb0cc0e17da 100644\n> > --- a/src/libcamera/base/backtrace.cpp\n> > +++ b/src/libcamera/base/backtrace.cpp\n> > @@ -196,6 +196,12 @@ bool Backtrace::unwindTrace()\n> >  \t\treturn false;\n> >  \n> >  \tdo {\n> > +#if HAVE_BACKTRACE || HAVE_DW\n> > +\t\t/*\n> > +\t\t * If backtrace() or libdw is available, they will be used in\n> > +\t\t * toString() to provide symbol information for the stack\n> > +\t\t * frames using the IP register value.\n> > +\t\t */\n> >  \t\tunw_word_t ip;\n> >  \t\tret = unw_get_reg(&cursor, UNW_REG_IP, &ip);\n> >  \t\tif (ret) {\n> > @@ -204,6 +210,29 @@ bool Backtrace::unwindTrace()\n> >  \t\t}\n> >  \n> >  \t\tbacktrace_.push_back(reinterpret_cast<void *>(ip));\n> > +#else\n> > +\t\t/*\n> > +\t\t * Otherwise, use libunwind to get the symbol information. As\n> > +\t\t * the libunwind API uses cursors, we can't store the IP values\n> > +\t\t * and delay symbol lookup to toString().\n> > +\t\t */\n> > +\t\tchar symbol[256];\n> > +\t\tunw_word_t offset = 0;\n> > +\t\tret = unw_get_proc_name(&cursor, symbol, sizeof(symbol), &offset);\n> > +\t\tif (ret) {\n> > +\t\t\tbacktraceText_.emplace_back(\"???\\n\");\n> > +\t\t\tcontinue;\n> > +\t\t}\n> > +\n> > +\t\tstd::ostringstream entry;\n> > +\n> > +\t\tchar *name = abi::__cxa_demangle(symbol, nullptr, nullptr, nullptr);\n> > +\t\tentry << (name ? name : symbol);\n> > +\t\tfree(name);\n> \n> Perhaps a smart pointer.\n\nAs mentioned in the reply to 2/4, I don't mind. Let's discuss it there,\nand I'll update this location accordingly.\n\n> > +\n> > +\t\tentry << \"+0x\" << std::hex << offset << \"\\n\";\n> > +\t\tbacktraceText_.emplace_back(entry.str());\n> > +#endif\n> >  \t} while (unw_step(&cursor) > 0);\n> >  \n> >  \treturn true;\n> > @@ -239,9 +268,15 @@ std::string Backtrace::toString(unsigned int skipLevels) const\n> >  \t */\n> >  \tskipLevels += 2;\n> >  \n> > -\tif (backtrace_.size() <= skipLevels)\n> > +\tif (backtrace_.size() <= skipLevels &&\n> > +\t    backtraceText_.size() <= skipLevels)\n> >  \t\treturn std::string();\n> >  \n> > +\tif (!backtraceText_.empty()) {\n> > +\t\tSpan<const std::string> trace{ backtraceText_ };\n> > +\t\treturn utils::join(trace.subspan(skipLevels), \"\");\n> > +\t}\n> > +\n> >  #if HAVE_DW\n> >  \tDwflParser dwfl;\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E6A80C3243\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 28 Sep 2021 02:36:47 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9B09E69189;\n\tTue, 28 Sep 2021 04:36:47 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0AFBB684C7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 28 Sep 2021 04:36:46 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A50123F1;\n\tTue, 28 Sep 2021 04:36:45 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"X3g4E0vt\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1632796605;\n\tbh=gw8S4IhoZBLHRnQQnq+zqVSYlYGtdHTNztdo9CPn3tM=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=X3g4E0vtHP5KhOVTz3Qr0m/eW2JFyJl75eGXV27qIgFCY8AW6PN7fSgeCtpqfiR4P\n\t3XlfUTKKoYSq3VF6f1PAHphD6uz4lcX1tnckq3NqzrtYoxH8CsNgMvWKcMY5K8jiKs\n\tU5DiaLCvJxgmaFjB93uJxktM1iUs4nk3vJjDNabs=","Date":"Tue, 28 Sep 2021 05:36:38 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Nicolas Dufresne <nicolas@ndufresne.ca>","Message-ID":"<YVJ/tirXFzXcs/WD@pendragon.ideasonboard.com>","References":"<20210924102323.26787-1-laurent.pinchart@ideasonboard.com>\n\t<20210924102323.26787-5-laurent.pinchart@ideasonboard.com>\n\t<3935117f244d6554ddbcbf756f6c9a8b76017335.camel@ndufresne.ca>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<3935117f244d6554ddbcbf756f6c9a8b76017335.camel@ndufresne.ca>","Subject":"Re: [libcamera-devel] [PATCH v1 4/4] libcamera: base: backtrace:\n\tFallback to libunwind for symbolic names","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]