From patchwork Mon Jul 9 21:55:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 28285 Received: (qmail 106162 invoked by alias); 9 Jul 2018 21:56:20 -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 106006 invoked by uid 89); 9 Jul 2018 21:56:19 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT autolearn=ham version=3.3.2 spammy=Hello! X-HELO: sessmg23.ericsson.net Received: from sessmg23.ericsson.net (HELO sessmg23.ericsson.net) (193.180.251.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Jul 2018 21:56:17 +0000 DKIM-Signature: v=1; a=rsa-sha256; d=ericsson.com; s=mailgw201801; c=relaxed/simple; q=dns/txt; i=@ericsson.com; t=1531173375; h=From:Sender:Reply-To:Subject:Date:Message-Id:To:CC:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=CG+NXnBbL+yl8AN3HG1aUIknRViPXWZ+POnbqoA3rus=; b=Xzb82+nJn1IaBpMl0nWWN0Bvg+EYqTTyZByhTfzXw0jiOzLz6kKXZYw8MqKReOct cCpGuYbMxj1XyYyznoeko7viEzIYEvIo9j2PEUAfQ4nW+hrQsdxNEWrnQM0pBmU+ fqy3G1bQVkr1mysRN8n0iEU8xcWoZMRW5M/gLkYK+Lg=; Received: from ESESBMB501.ericsson.se (Unknown_Domain [153.88.183.114]) by sessmg23.ericsson.net (Symantec Mail Security) with SMTP id ED.57.22015.FF9D34B5; Mon, 9 Jul 2018 23:56:15 +0200 (CEST) Received: from ESESBMB503.ericsson.se (153.88.183.170) by ESESBMB501.ericsson.se (153.88.183.168) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3; Mon, 9 Jul 2018 23:56:14 +0200 Received: from NAM03-CO1-obe.outbound.protection.outlook.com (153.88.183.157) by ESESBMB503.ericsson.se (153.88.183.170) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3 via Frontend Transport; Mon, 9 Jul 2018 23:56:14 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kd/Sd1BkqlmWUdGjFuJTQUIbx/SeifkQU76yQqAflu4=; b=P1zyf0IOeTfxfMiWjRFanwvapwMDQQOWZm6WBm8qpmUOsDLSWKwpL/eMHi/coAIajVAV7VBeE0oP79OOqtJPResZPzI3oTuCRPfSISrc5OVEFN4+dm492jGR5tlOLebOtsjFdLfraQN7YsSGA0CQsWrO2F8OkU1uETn6PA/XgPU= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=simon.marchi@ericsson.com; Received: from elxacz23q12.ca.am.ericsson.se (192.75.88.130) by DM6PR15MB2393.namprd15.prod.outlook.com (2603:10b6:5:8d::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.930.18; Mon, 9 Jul 2018 21:56:11 +0000 From: Simon Marchi To: CC: Simon Marchi Subject: [PATCH 2/3] Introduce scoped_mmapped_file Date: Mon, 9 Jul 2018 17:55:50 -0400 Message-Id: <1531173351-6351-3-git-send-email-simon.marchi@ericsson.com> In-Reply-To: <1531173351-6351-1-git-send-email-simon.marchi@ericsson.com> References: <1531173351-6351-1-git-send-email-simon.marchi@ericsson.com> MIME-Version: 1.0 Return-Path: simon.marchi@ericsson.com Received-SPF: None (protection.outlook.com: ericsson.com does not designate permitted sender hosts) X-IsSubscribed: yes We already have scoped_mmap, which can is a thin RAII layer over mmap. If one simply wants to mmap an entire file for reading, it takes a bit of boilerplate. This patch introduces the scoped_mmapped_file class to make this easier. gdb/ChangeLog: * common/scoped_mmapped_file.h: New file. * common/scoped_fd.h (class scoped_fd) : New method. : New method. <~scoped_fd>: Use destroy. * unittests/scoped_mmapped_file-selftests.c: New file. * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add unittests/scoped_mmapped_file-selftests.c. --- gdb/Makefile.in | 1 + gdb/common/scoped_fd.h | 17 ++++- gdb/common/scoped_mmapped_file.h | 70 +++++++++++++++++++ gdb/unittests/scoped_mmapped_file-selftests.c | 96 +++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 gdb/common/scoped_mmapped_file.h create mode 100644 gdb/unittests/scoped_mmapped_file-selftests.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 13627e0..ff3bfbf 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -434,6 +434,7 @@ SUBDIR_UNITTESTS_SRCS = \ unittests/rsp-low-selftests.c \ unittests/scoped_fd-selftests.c \ unittests/scoped_mmap-selftests.c \ + unittests/scoped_mmapped_file-selftests.c \ unittests/scoped_restore-selftests.c \ unittests/string_view-selftests.c \ unittests/tracepoint-selftests.c \ diff --git a/gdb/common/scoped_fd.h b/gdb/common/scoped_fd.h index a6a8ab9..574c26e 100644 --- a/gdb/common/scoped_fd.h +++ b/gdb/common/scoped_fd.h @@ -34,8 +34,7 @@ public: explicit scoped_fd (int fd = -1) noexcept : m_fd (fd) {} ~scoped_fd () { - if (m_fd >= 0) - close (m_fd); + destroy (); } DISABLE_COPY_AND_ASSIGN (scoped_fd); @@ -52,7 +51,21 @@ public: return m_fd; } + void reset (int new_fd) + { + destroy (); + + m_fd = new_fd; + } + private: + + void destroy () + { + if (m_fd >= 0) + close (m_fd); + } + int m_fd; }; diff --git a/gdb/common/scoped_mmapped_file.h b/gdb/common/scoped_mmapped_file.h new file mode 100644 index 0000000..bd6de31 --- /dev/null +++ b/gdb/common/scoped_mmapped_file.h @@ -0,0 +1,70 @@ +/* scoped_mmapped_file, automatically map/unmap entire files. + + Copyright (C) 2018 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef SCOPED_MMAPPED_FILE_H +#define SCOPED_MMAPPED_FILE_H + +#if defined(HAVE_SYS_MMAN_H) + +#include "scoped_mmap.h" +#include "scoped_fd.h" + +#include +#include +#include + +/* A smart-pointer-like class to automatically mmap an entire file. */ + +class scoped_mmapped_file +{ +public: + + scoped_mmapped_file () = default; + + /* Map FILENAME in memory. Throw an error if anything goes wrong. */ + scoped_mmapped_file (const char *filename) + { + m_fd.reset (open (filename, O_RDONLY)); + if (m_fd.get () < 0) + perror_with_name ("open"); + + off_t size = lseek (m_fd.get (), 0, SEEK_END); + if (size < 0) + perror_with_name ("lseek"); + + /* We can't map an empty file. */ + if (size == 0) + error (_("file to mmap is empty")); + + m_mmap.reset (nullptr, size, PROT_READ, MAP_PRIVATE, m_fd.get (), 0); + if (m_mmap.get () == MAP_FAILED) + perror_with_name ("mmap"); + } + + size_t size () const noexcept { return m_mmap.size (); } + void *get () const noexcept { return m_mmap.get (); } + +private: + scoped_mmap m_mmap; + scoped_fd m_fd; +}; + +#endif /* defined(HAVE_SYS_MMAN_H) */ + +#endif /* SCOPED_MMAPPED_FILE_H */ diff --git a/gdb/unittests/scoped_mmapped_file-selftests.c b/gdb/unittests/scoped_mmapped_file-selftests.c new file mode 100644 index 0000000..ee41dc2 --- /dev/null +++ b/gdb/unittests/scoped_mmapped_file-selftests.c @@ -0,0 +1,96 @@ +/* Self tests for scoped_mmapped_file for GDB, the GNU debugger. + + Copyright (C) 2018 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "selftest.h" +#include "common/scoped_mmapped_file.h" +#include "common/gdb_unlinker.h" + +#if defined (HAVE_SYS_MMAN_H) + +namespace selftests { +namespace scoped_mmapped_file { + +static void +test_destroy () +{ + char filename[] = "scoped_mmapped_file-selftest-XXXXXX"; + int fd = mkstemp (filename); + SELF_CHECK (fd >= 0); + + write (fd, "Hello!", 7); + close (fd); + + gdb::unlinker unlink_test_file (filename); + + { + ::scoped_mmapped_file f (filename); + + SELF_CHECK (f.get () != MAP_FAILED); + SELF_CHECK (f.size () == 7); + SELF_CHECK (0 == strcmp ((char *) f.get (), "Hello!")); + } +} + +static void +test_default_constructor () +{ + ::scoped_mmapped_file f; + + SELF_CHECK (f.get () == MAP_FAILED); + SELF_CHECK (f.size () == 0); +} + +static void +test_invalid_filename () +{ + bool threw = false; + + try { + ::scoped_mmapped_file f ("/this/file/should/not/exist"); + } catch (gdb_exception &e) { + threw = true; + } + + SELF_CHECK (threw); +} + +static void +run_tests () +{ + test_destroy (); + test_default_constructor (); + test_invalid_filename (); +} + +} /* namespace scoped_mmapped_file */ +} /* namespace selftests */ + +#endif /* defined (HAVE_SYS_MMAN_H) */ + +void +_initialize_scoped_mmapped_file_selftests () +{ +#if defined (HAVE_SYS_MMAN_H) + selftests::register_test ("scoped_mmapped_file", + selftests::scoped_mmapped_file::run_tests); +#endif /* defined (HAVE_SYS_MMAN_H) */ +} + +