{"id":13921,"url":"https://patchwork.libcamera.org/api/1.1/patches/13921/?format=json","web_url":"https://patchwork.libcamera.org/patch/13921/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20210924102323.26787-3-laurent.pinchart@ideasonboard.com>","date":"2021-09-24T10:23:21","name":"[libcamera-devel,v1,2/4] libcamera: base: backtrace: Use libdw to provide symbolic names","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"e72cdbc749ba9f0dd3fadf0997a7fa910fa819a5","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/1.1/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/13921/mbox/","series":[{"id":2562,"url":"https://patchwork.libcamera.org/api/1.1/series/2562/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=2562","date":"2021-09-24T10:23:19","name":"libcamera: Improve backtraces","version":1,"mbox":"https://patchwork.libcamera.org/series/2562/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/13921/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/13921/checks/","tags":{},"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 6E9B5BDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Sep 2021 10:23:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 165886918A;\n\tFri, 24 Sep 2021 12:23:34 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A8E9D687DD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 12:23:30 +0200 (CEST)","from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4D31345E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 12:23:30 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"Mv0NbmSH\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1632479010;\n\tbh=fGGdyBzvJvEBL0jjFXK/4Fz29pbIasDtOqBedTq5wQI=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=Mv0NbmSHyqtQqaJT3UYMenCEAw8fO5bTA6Pvm2EFhEB86ZLmnGUCOs7gxBrxXHv1s\n\teij4gmagkUKh/sZ68l0PjlQ/VRqIOy1ic35wR5/UejmZ/XDxlrsSqE93SL07UUdmbL\n\tIrWCgJojRRB74BGtUzHVBQEKxYLuqxPR9UTXyYL4=","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Fri, 24 Sep 2021 13:23:21 +0300","Message-Id":"<20210924102323.26787-3-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.32.0","In-Reply-To":"<20210924102323.26787-1-laurent.pinchart@ideasonboard.com>","References":"<20210924102323.26787-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v1 2/4] libcamera: base: backtrace: Use\n\tlibdw to provide 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>"},"content":"libdw provides access to debugging information. This allows creating\nbetter stack trace entries, with file names and line numbers, but also\nwith demangled symbols as the symbol name is available and can be passed\nto abi::__cxa_demangle().\n\nWith libdw, the backtrace previously generated by backtrace_symbols()\n\nsrc/cam/../libcamera/libcamera.so(_ZN9libcamera14VimcCameraData4initEv+0xbd) [0x7f7dbb73222d]\nsrc/cam/../libcamera/libcamera.so(_ZN9libcamera19PipelineHandlerVimc5matchEPNS_16DeviceEnumeratorE+0x3e0) [0x7f7dbb731c40]\nsrc/cam/../libcamera/libcamera.so(_ZN9libcamera13CameraManager7Private22createPipelineHandlersEv+0x1a7) [0x7f7dbb5ea027]\nsrc/cam/../libcamera/libcamera.so(_ZN9libcamera13CameraManager7Private4initEv+0x98) [0x7f7dbb5e9dc8]\nsrc/cam/../libcamera/libcamera.so(_ZN9libcamera13CameraManager7Private3runEv+0x9f) [0x7f7dbb5e9c5f]\nsrc/cam/../libcamera/base/libcamera-base.so(_ZN9libcamera6Thread11startThreadEv+0xee) [0x7f7dbb3e95be]\nsrc/cam/../libcamera/base/libcamera-base.so(+0x4f9d7) [0x7f7dbb3ec9d7]\nsrc/cam/../libcamera/base/libcamera-base.so(+0x4f90e) [0x7f7dbb3ec90e]\nsrc/cam/../libcamera/base/libcamera-base.so(+0x4f2c2) [0x7f7dbb3ec2c2]\n/lib64/libpthread.so.0(+0x7e8e) [0x7f7dbab65e8e]\n/lib64/libc.so.6(clone+0x3f) [0x7f7dbb10b26f]\n\nbecomes\n\nlibcamera::VimcCameraData::init()+0xbd (src/libcamera/libcamera.so [0x00007f9de605b22d])\nlibcamera::PipelineHandlerVimc::match(libcamera::DeviceEnumerator*)+0x3e0 (src/libcamera/libcamera.so [0x00007f9de605ac40])\nlibcamera::CameraManager::Private::createPipelineHandlers()+0x1a7 (src/libcamera/libcamera.so [0x00007f9de5f13027])\nlibcamera::CameraManager::Private::init()+0x98 (src/libcamera/libcamera.so [0x00007f9de5f12dc8])\nlibcamera::CameraManager::Private::run()+0x9f (src/libcamera/libcamera.so [0x00007f9de5f12c5f])\nlibcamera::Thread::startThread()+0xee (src/libcamera/base/libcamera-base.so [0x00007f9de5d125be])\ndecltype(*(std::__1::forward<libcamera::Thread*>(fp0)).*fp()) std::__1::__invoke<void (libcamera::Thread::*)(), libcamera::Thread*, void>(void (libcamera::Thread::*&&)(), libcamera::Thread*&&)+0x77 (src/libcamera/base/libcamera-base.so [0x00007f9de5d159d7])\nvoid 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 (src/libcamera/base/libcamera-base.so [0x00007f9de5d1590e])\nvoid* 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 (src/libcamera/base/libcamera-base.so [0x00007f9de5d152c2])\nstart_thread+0xde (/var/tmp/portage/sys-libs/glibc-2.33-r1/work/glibc-2.33/nptl/pthread_create.c:482)\n__clone+0x3f (../sysdeps/unix/sysv/linux/x86_64/clone.S:97)\n\nThe stack entries related to libcamera are missing source file name and\nline information, which will be investigated separately, but this is\nstill an improvement.\n\nUse libdw when available, falling back to backtrace_symbols() otherwise,\nor if libdw fails for any reason.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/base/backtrace.cpp | 120 +++++++++++++++++++++++++++++++\n src/libcamera/base/meson.build   |   7 ++\n 2 files changed, 127 insertions(+)","diff":"diff --git a/src/libcamera/base/backtrace.cpp b/src/libcamera/base/backtrace.cpp\nindex 913f7ba71b03..011f2e428d5d 100644\n--- a/src/libcamera/base/backtrace.cpp\n+++ b/src/libcamera/base/backtrace.cpp\n@@ -12,9 +12,16 @@\n #include <stdlib.h>\n #endif\n \n+#ifdef HAVE_DW\n+#include <cxxabi.h>\n+#include <elfutils/libdwfl.h>\n+#include <unistd.h>\n+#endif\n+\n #include <sstream>\n \n #include <libcamera/base/span.h>\n+#include <libcamera/base/utils.h>\n \n /**\n  * \\file backtrace.h\n@@ -23,6 +30,101 @@\n \n namespace libcamera {\n \n+namespace {\n+\n+#if HAVE_DW\n+class DwflParser\n+{\n+public:\n+\tDwflParser();\n+\t~DwflParser();\n+\n+\tbool isValid() const { return valid_; }\n+\tstd::string stackEntry(const void *ip);\n+\n+private:\n+\tDwfl_Callbacks callbacks_;\n+\tDwfl *dwfl_;\n+\tbool valid_;\n+};\n+\n+DwflParser::DwflParser()\n+\t: callbacks_({}), dwfl_(nullptr), valid_(false)\n+{\n+\tcallbacks_.find_elf = dwfl_linux_proc_find_elf;\n+\tcallbacks_.find_debuginfo = dwfl_standard_find_debuginfo;\n+\n+\tdwfl_ = dwfl_begin(&callbacks_);\n+\tif (!dwfl_)\n+\t\treturn;\n+\n+\tint ret = dwfl_linux_proc_report(dwfl_, getpid());\n+\tif (ret)\n+\t\treturn;\n+\n+\tret = dwfl_report_end(dwfl_, nullptr, nullptr);\n+\tif (ret)\n+\t\treturn;\n+\n+\tvalid_ = true;\n+}\n+\n+DwflParser::~DwflParser()\n+{\n+\tif (dwfl_)\n+\t\tdwfl_end(dwfl_);\n+}\n+\n+std::string DwflParser::stackEntry(const void *ip)\n+{\n+\tDwarf_Addr addr = reinterpret_cast<Dwarf_Addr>(ip);\n+\n+\tDwfl_Module *module = dwfl_addrmodule(dwfl_, addr);\n+\tif (!module)\n+\t\treturn std::string();\n+\n+\tstd::ostringstream entry;\n+\n+\tGElf_Off offset;\n+\tGElf_Sym sym;\n+\tconst char *symbol = dwfl_module_addrinfo(module, addr, &offset, &sym,\n+\t\t\t\t\t\t  nullptr, nullptr, nullptr);\n+\tif (symbol) {\n+\t\tchar *name = abi::__cxa_demangle(symbol, nullptr, nullptr, nullptr);\n+\t\tentry << (name ? name : symbol) << \"+0x\" << std::hex << offset\n+\t\t      << std::dec;\n+\t\tfree(name);\n+\t} else {\n+\t\tentry << \"??? [\" << utils::hex(addr) << \"]\";\n+\t}\n+\n+\tentry << \" (\";\n+\n+\tDwfl_Line *line = dwfl_module_getsrc(module, addr);\n+\tif (line) {\n+\t\tconst char *filename;\n+\t\tint lineNumber = 0;\n+\n+\t\tfilename = dwfl_lineinfo(line, &addr, &lineNumber, nullptr,\n+\t\t\t\t\t nullptr, nullptr);\n+\n+\t\tentry << (filename ? filename : \"???\") << \":\" << lineNumber;\n+\t} else {\n+\t\tconst char *filename = nullptr;\n+\n+\t\tdwfl_module_info(module, nullptr, nullptr, nullptr, nullptr,\n+\t\t\t\t nullptr, &filename, nullptr);\n+\n+\t\tentry << (filename ? filename : \"???\") << \" [\" << utils::hex(addr) << \"]\";\n+\t}\n+\n+\tentry << \")\";\n+\treturn entry.str();\n+}\n+#endif /* HAVE_DW */\n+\n+} /* namespace */\n+\n /**\n  * \\class Backtrace\n  * \\brief Representation of a call stack backtrace\n@@ -85,6 +187,24 @@ std::string Backtrace::toString(unsigned int skipLevels) const\n \tif (backtrace_.size() <= skipLevels)\n \t\treturn std::string();\n \n+#if HAVE_DW\n+\tDwflParser dwfl;\n+\n+\tif (dwfl.isValid()) {\n+\t\tstd::ostringstream msg;\n+\n+\t\tSpan<void *const> trace{ backtrace_ };\n+\t\tfor (const void *ip : trace.subspan(skipLevels)) {\n+\t\t\tif (ip)\n+\t\t\t\tmsg << dwfl.stackEntry(ip) << std::endl;\n+\t\t\telse\n+\t\t\t\tmsg << \"???\" << std::endl;\n+\t\t}\n+\n+\t\treturn msg.str();\n+\t}\n+#endif\n+\n #if HAVE_BACKTRACE\n \tSpan<void *const> trace{ backtrace_ };\n \ttrace = trace.subspan(skipLevels);\ndiff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\nindex 85af01a19365..1fa894cf1896 100644\n--- a/src/libcamera/base/meson.build\n+++ b/src/libcamera/base/meson.build\n@@ -19,13 +19,20 @@ libcamera_base_sources = files([\n     'utils.cpp',\n ])\n \n+libdw = cc.find_library('libdw', required : false)\n+\n if cc.has_header_symbol('execinfo.h', 'backtrace')\n     config_h.set('HAVE_BACKTRACE', 1)\n endif\n \n+if libdw.found()\n+    config_h.set('HAVE_DW', 1)\n+endif\n+\n libcamera_base_deps = [\n     dependency('threads'),\n     libatomic,\n+    libdw,\n ]\n \n # Internal components must use the libcamera_base_private dependency to enable\n","prefixes":["libcamera-devel","v1","2/4"]}