Show a patch.

GET /api/1.1/patches/14030/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 14030,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/14030/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/14030/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20211003223606.20016-3-laurent.pinchart@ideasonboard.com>",
    "date": "2021-10-03T22:36:04",
    "name": "[libcamera-devel,v2,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=api",
        "name": "Laurent Pinchart",
        "email": "laurent.pinchart@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/14030/mbox/",
    "series": [
        {
            "id": 2593,
            "url": "https://patchwork.libcamera.org/api/1.1/series/2593/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2593",
            "date": "2021-10-03T22:36:03",
            "name": "libcamera: Improve backtraces",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/2593/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/14030/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/14030/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 9847FC3243\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun,  3 Oct 2021 22:36:19 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7348F691C7;\n\tMon,  4 Oct 2021 00:36:18 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5EBD8691B7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  4 Oct 2021 00:36:15 +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 0087BD4C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  4 Oct 2021 00:36:14 +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=\"UrHi4tKC\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1633300575;\n\tbh=SF9crXhGs8tjbaI9tNhDKbJWGJGwCDdfJhZvgB67+Uw=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=UrHi4tKCjJeeDwgTsJ5Vj95oooOHxMvbYlRu7f4Ev2B3mjCN6gdOhiV/4AvxAC+KV\n\tyLwRaqfjoepabaH65CH4P1X39ps4uAtvrrlFWzUBr9eT/I+mDKVn3baUIPwjgULN/K\n\taziiPrjIK4453u19aYnBhL7LasT6hXVPUMJPk2Dc=",
        "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon,  4 Oct 2021 01:36:04 +0300",
        "Message-Id": "<20211003223606.20016-3-laurent.pinchart@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.32.0",
        "In-Reply-To": "<20211003223606.20016-1-laurent.pinchart@ideasonboard.com>",
        "References": "<20211003223606.20016-1-laurent.pinchart@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v2 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 c010a7e42e4d..79e4a31f3d21 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 fc00296dfa8a..4c44b9f55011 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",
        "v2",
        "2/4"
    ]
}