From patchwork Thu Jan 25 09:12:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Metzger, Markus T" X-Patchwork-Id: 25531 Received: (qmail 26353 invoked by alias); 25 Jan 2018 09:12:35 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 25563 invoked by uid 89); 25 Jan 2018 09:12:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-23.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=9057, destruction X-HELO: mga03.intel.com Received: from mga03.intel.com (HELO mga03.intel.com) (134.134.136.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 25 Jan 2018 09:12:10 +0000 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Jan 2018 01:12:09 -0800 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga002.fm.intel.com with ESMTP; 25 Jan 2018 01:12:08 -0800 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id w0P9C7Ec026703; Thu, 25 Jan 2018 09:12:07 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id w0P9C7Ag032417; Thu, 25 Jan 2018 10:12:07 +0100 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with LOCAL id w0P9C68d032413; Thu, 25 Jan 2018 10:12:07 +0100 From: Markus Metzger To: gdb-patches@sourceware.org Subject: [PATCH 1/5] btrace: prepare for throwing exceptions when enabling btrace Date: Thu, 25 Jan 2018 10:12:02 +0100 Message-Id: <1516871526-32129-2-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1516871526-32129-1-git-send-email-markus.t.metzger@intel.com> References: <1516871526-32129-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes We indicate success or failure for enabling branch tracing via the pointer return value. Depending on the type of error, errno may provide additional information. Prepare for using exceptions with more descriptive error messages by using smart pointers and objects with automatic destruction to hold intermediate results. 2018-01-25 Markus Metzger gdb/ * nat/linux-btrace.c (perf_event_pt_event_type): Use gdb_file_up. (scoped_close_fd, scoped_mmap): New. (linux_enable_bts, linux_enable_pt): Use gdb::unique_xmalloc_ptr, scoped_close_fd, and scoped_mmap. --- gdb/nat/linux-btrace.c | 183 +++++++++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 66 deletions(-) diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c index bbd0fe6..280d9f1 100644 --- a/gdb/nat/linux-btrace.c +++ b/gdb/nat/linux-btrace.c @@ -179,17 +179,12 @@ perf_event_read_all (struct perf_event_buffer *pev, gdb_byte **data, static int perf_event_pt_event_type (int *type) { - FILE *file; - int found; - - file = fopen ("/sys/bus/event_source/devices/intel_pt/type", "r"); - if (file == NULL) + gdb_file_up file = + gdb_fopen_cloexec ("/sys/bus/event_source/devices/intel_pt/type", "r"); + if (file.get () == nullptr) return -1; - found = fscanf (file, "%d", type); - - fclose (file); - + int found = fscanf (file.get (), "%d", type); if (found == 1) return 0; return -1; @@ -657,19 +652,95 @@ linux_supports_btrace (struct target_ops *ops, enum btrace_format format) internal_error (__FILE__, __LINE__, _("Unknown branch trace format")); } +class scoped_close_fd +{ + int m_fd; + +public: + scoped_close_fd (int fd = -1) noexcept : m_fd (fd) {} + ~scoped_close_fd () noexcept + { + if (m_fd >= 0) + close (m_fd); + } + + scoped_close_fd (const scoped_close_fd &) = delete; + scoped_close_fd &operator = (const scoped_close_fd &) = delete; + + int release () noexcept + { + int fd = m_fd; + m_fd = -1; + return fd; + } + + operator int () const noexcept + { + return m_fd; + } +}; + +template +class scoped_mmap +{ + void *m_mem; + size_t m_length; + +public: + scoped_mmap () noexcept : m_mem (nullptr), m_length (0) {} + scoped_mmap (void *addr, size_t length, int prot, int flags, int fd, + off_t offset) noexcept : m_mem (nullptr), m_length (length) + { + m_mem = mmap (addr, m_length, prot, flags, fd, offset); + } + ~scoped_mmap () noexcept + { + if (m_mem != nullptr) + munmap (m_mem, m_length); + } + + scoped_mmap (const scoped_mmap &) = delete; + scoped_mmap &operator = (const scoped_mmap &) = delete; + + object_type *release () noexcept + { + void *mem = m_mem; + m_mem = nullptr; + return static_cast (mem); + } + + void reset (void *addr, size_t length, int prot, int flags, int fd, + off_t offset) noexcept + { + if (m_mem != nullptr) + munmap (m_mem, m_length); + + m_length = length; + m_mem = mmap (addr, m_length, prot, flags, fd, offset); + } + + size_t size () const noexcept { return m_length; } + uint8_t *raw () const noexcept { return static_cast (m_mem); } + + operator void * () const noexcept { return m_mem; } + object_type *operator -> () const noexcept + { + return static_cast (m_mem); + } +}; + /* Enable branch tracing in BTS format. */ static struct btrace_target_info * linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf) { - struct perf_event_mmap_page *header; - struct btrace_target_info *tinfo; struct btrace_tinfo_bts *bts; size_t size, pages; __u64 data_offset; int pid, pg; - tinfo = XCNEW (struct btrace_target_info); + gdb::unique_xmalloc_ptr tinfo + (XCNEW (btrace_target_info)); tinfo->ptid = ptid; tinfo->conf.format = BTRACE_FORMAT_BTS; @@ -692,9 +763,10 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf) pid = ptid_get_pid (ptid); errno = 0; - bts->file = syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0); - if (bts->file < 0) - goto err_out; + scoped_close_fd fd (syscall (SYS_perf_event_open, &bts->attr, pid, + -1, -1, 0)); + if (fd < 0) + return nullptr; /* Convert the requested size in bytes to pages (rounding up). */ pages = ((size_t) conf->size / PAGE_SIZE @@ -711,6 +783,7 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf) /* We try to allocate the requested size. If that fails, try to get as much as we can. */ + scoped_mmap header; for (; pages > 0; pages >>= 1) { size_t length; @@ -730,14 +803,13 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf) continue; /* The number of pages we request needs to be a power of two. */ - header = ((struct perf_event_mmap_page *) - mmap (NULL, length, PROT_READ, MAP_SHARED, bts->file, 0)); + header.reset (NULL, length, PROT_READ, MAP_SHARED, fd, 0); if (header != MAP_FAILED) break; } if (pages == 0) - goto err_file; + return nullptr; data_offset = PAGE_SIZE; @@ -753,29 +825,19 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf) /* Check for overflows. */ if ((__u64) size != data_size) - { - munmap ((void *) header, size + PAGE_SIZE); - goto err_file; - } + return nullptr; } #endif /* defined (PERF_ATTR_SIZE_VER5) */ - bts->header = header; - bts->bts.mem = ((const uint8_t *) header) + data_offset; bts->bts.size = size; bts->bts.data_head = &header->data_head; + bts->bts.mem = header.raw () + data_offset; bts->bts.last_head = 0ull; + bts->header = header.release (); + bts->file = fd.release (); tinfo->conf.bts.size = (unsigned int) size; - return tinfo; - - err_file: - /* We were not able to allocate any buffer. */ - close (bts->file); - - err_out: - xfree (tinfo); - return NULL; + return tinfo.release (); } #if defined (PERF_ATTR_SIZE_VER5) @@ -785,10 +847,8 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf) static struct btrace_target_info * linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf) { - struct perf_event_mmap_page *header; - struct btrace_target_info *tinfo; struct btrace_tinfo_pt *pt; - size_t pages, size; + size_t pages; int pid, pg, errcode, type; if (conf->size == 0) @@ -802,7 +862,8 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf) if (pid == 0) pid = ptid_get_pid (ptid); - tinfo = XCNEW (struct btrace_target_info); + gdb::unique_xmalloc_ptr tinfo + (XCNEW (btrace_target_info)); tinfo->ptid = ptid; tinfo->conf.format = BTRACE_FORMAT_PT; @@ -816,16 +877,16 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf) pt->attr.exclude_idle = 1; errno = 0; - pt->file = syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0); - if (pt->file < 0) - goto err; + scoped_close_fd fd (syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0)); + if (fd < 0) + return nullptr; /* Allocate the configuration page. */ - header = ((struct perf_event_mmap_page *) - mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, - pt->file, 0)); + scoped_mmap header (NULL, PAGE_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0); if (header == MAP_FAILED) - goto err_file; + return nullptr; header->aux_offset = header->data_offset + header->data_size; @@ -844,6 +905,7 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf) /* We try to allocate the requested size. If that fails, try to get as much as we can. */ + scoped_mmap aux; for (; pages > 0; pages >>= 1) { size_t length; @@ -855,41 +917,30 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf) if ((__u64) UINT_MAX < data_size) continue; - size = (size_t) data_size; + length = (size_t) data_size; /* Check for overflows. */ - if ((__u64) size != data_size) + if ((__u64) length != data_size) continue; header->aux_size = data_size; - length = size; - pt->pt.mem = ((const uint8_t *) - mmap (NULL, length, PROT_READ, MAP_SHARED, pt->file, - header->aux_offset)); - if (pt->pt.mem != MAP_FAILED) + aux.reset (NULL, length, PROT_READ, MAP_SHARED, fd, header->aux_offset); + if (aux != MAP_FAILED) break; } if (pages == 0) - goto err_conf; + return nullptr; - pt->header = header; - pt->pt.size = size; + pt->pt.size = aux.size (); + pt->pt.mem = aux.release (); pt->pt.data_head = &header->aux_head; + pt->header = header.release (); + pt->file = fd.release (); - tinfo->conf.pt.size = (unsigned int) size; - return tinfo; - - err_conf: - munmap((void *) header, PAGE_SIZE); - - err_file: - close (pt->file); - - err: - xfree (tinfo); - return NULL; + tinfo->conf.pt.size = (unsigned int) pt->pt.size; + return tinfo.release (); } #else /* !defined (PERF_ATTR_SIZE_VER5) */