summaryrefslogtreecommitdiff
path: root/libipt/test/src/ptunit-section-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'libipt/test/src/ptunit-section-file.c')
-rw-r--r--libipt/test/src/ptunit-section-file.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/libipt/test/src/ptunit-section-file.c b/libipt/test/src/ptunit-section-file.c
new file mode 100644
index 0000000000000..753de13a3d211
--- /dev/null
+++ b/libipt/test/src/ptunit-section-file.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2015-2018, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pt_section.h"
+#include "pt_section_file.h"
+
+#include "intel-pt.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+/* This is a variation of ptunit-section.c.
+ *
+ * We provide pt_section_map() et.al. that are normally provided by mmap-based
+ * section implementations. Our implementation falls back to file-based
+ * sections so we're able to test them.
+ *
+ * The actual test is in ptunit-section.c.
+ */
+
+/* The file status used for detecting changes to a file between unmap and map.
+ *
+ * In our case, the changes always affect the size of the file.
+ */
+struct pt_file_status {
+ /* The size in bytes. */
+ long size;
+};
+
+int pt_section_mk_status(void **pstatus, uint64_t *psize, const char *filename)
+{
+ struct pt_file_status *status;
+ FILE *file;
+ long size;
+ int errcode;
+
+ if (!pstatus || !psize)
+ return -pte_internal;
+
+ file = fopen(filename, "rb");
+ if (!file)
+ return -pte_bad_image;
+
+ errcode = fseek(file, 0, SEEK_END);
+ if (errcode) {
+ errcode = -pte_bad_image;
+ goto out_file;
+ }
+
+ size = ftell(file);
+ if (size < 0) {
+ errcode = -pte_bad_image;
+ goto out_file;
+ }
+
+ status = malloc(sizeof(*status));
+ if (!status) {
+ errcode = -pte_nomem;
+ goto out_file;
+ }
+
+ status->size = size;
+
+ *pstatus = status;
+ *psize = (uint64_t) size;
+
+ errcode = 0;
+
+out_file:
+ fclose(file);
+ return errcode;
+}
+
+static int pt_section_map_success(struct pt_section *section)
+{
+ uint16_t mcount;
+ int errcode, status;
+
+ if (!section)
+ return -pte_internal;
+
+ mcount = section->mcount + 1;
+ if (!mcount) {
+ (void) pt_section_unlock(section);
+ return -pte_overflow;
+ }
+
+ section->mcount = mcount;
+
+ errcode = pt_section_unlock(section);
+ if (errcode < 0)
+ return errcode;
+
+ status = pt_section_on_map(section);
+ if (status < 0) {
+ (void) pt_section_unmap(section);
+ return status;
+ }
+
+ return 0;
+}
+
+int pt_section_map(struct pt_section *section)
+{
+ struct pt_file_status *status;
+ const char *filename;
+ uint16_t mcount;
+ FILE *file;
+ long size;
+ int errcode;
+
+ if (!section)
+ return -pte_internal;
+
+ errcode = pt_section_lock(section);
+ if (errcode < 0)
+ return errcode;
+
+ mcount = section->mcount;
+ if (mcount)
+ return pt_section_map_success(section);
+
+ if (section->mapping)
+ goto out_unlock;
+
+ filename = section->filename;
+ if (!filename)
+ goto out_unlock;
+
+ status = section->status;
+ if (!status)
+ goto out_unlock;
+
+ errcode = -pte_bad_image;
+ file = fopen(filename, "rb");
+ if (!file)
+ goto out_unlock;
+
+ errcode = fseek(file, 0, SEEK_END);
+ if (errcode) {
+ errcode = -pte_bad_image;
+ goto out_file;
+ }
+
+ errcode = -pte_bad_image;
+ size = ftell(file);
+ if (size < 0)
+ goto out_file;
+
+ if (size != status->size)
+ goto out_file;
+
+ /* We need to keep the file open on success. It will be closed when
+ * the section is unmapped.
+ */
+ errcode = pt_sec_file_map(section, file);
+ if (!errcode)
+ return pt_section_map_success(section);
+
+out_file:
+ fclose(file);
+
+out_unlock:
+ (void) pt_section_unlock(section);
+ return errcode;
+}