]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/processor-trace/libipt/test/src/ptunit-section-file.c
Import Intel Processor Trace decoder library from
[FreeBSD/FreeBSD.git] / contrib / processor-trace / libipt / test / src / ptunit-section-file.c
1 /*
2  * Copyright (c) 2015-2018, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "pt_section.h"
30 #include "pt_section_file.h"
31
32 #include "intel-pt.h"
33
34 #include <stdlib.h>
35 #include <stdio.h>
36
37
38 /* This is a variation of ptunit-section.c.
39  *
40  * We provide pt_section_map() et.al. that are normally provided by mmap-based
41  * section implementations.  Our implementation falls back to file-based
42  * sections so we're able to test them.
43  *
44  * The actual test is in ptunit-section.c.
45  */
46
47 /* The file status used for detecting changes to a file between unmap and map.
48  *
49  * In our case, the changes always affect the size of the file.
50  */
51 struct pt_file_status {
52         /* The size in bytes. */
53         long size;
54 };
55
56 int pt_section_mk_status(void **pstatus, uint64_t *psize, const char *filename)
57 {
58         struct pt_file_status *status;
59         FILE *file;
60         long size;
61         int errcode;
62
63         if (!pstatus || !psize)
64                 return -pte_internal;
65
66         file = fopen(filename, "rb");
67         if (!file)
68                 return -pte_bad_image;
69
70         errcode = fseek(file, 0, SEEK_END);
71         if (errcode) {
72                 errcode = -pte_bad_image;
73                 goto out_file;
74         }
75
76         size = ftell(file);
77         if (size < 0) {
78                 errcode = -pte_bad_image;
79                 goto out_file;
80         }
81
82         status = malloc(sizeof(*status));
83         if (!status) {
84                 errcode = -pte_nomem;
85                 goto out_file;
86         }
87
88         status->size = size;
89
90         *pstatus = status;
91         *psize = (uint64_t) size;
92
93         errcode = 0;
94
95 out_file:
96         fclose(file);
97         return errcode;
98 }
99
100 static int pt_section_map_success(struct pt_section *section)
101 {
102         uint16_t mcount;
103         int errcode, status;
104
105         if (!section)
106                 return -pte_internal;
107
108         mcount = section->mcount + 1;
109         if (!mcount) {
110                 (void) pt_section_unlock(section);
111                 return -pte_overflow;
112         }
113
114         section->mcount = mcount;
115
116         errcode = pt_section_unlock(section);
117         if (errcode < 0)
118                 return errcode;
119
120         status = pt_section_on_map(section);
121         if (status < 0) {
122                 (void) pt_section_unmap(section);
123                 return status;
124         }
125
126         return 0;
127 }
128
129 int pt_section_map(struct pt_section *section)
130 {
131         struct pt_file_status *status;
132         const char *filename;
133         uint16_t mcount;
134         FILE *file;
135         long size;
136         int errcode;
137
138         if (!section)
139                 return -pte_internal;
140
141         errcode = pt_section_lock(section);
142         if (errcode < 0)
143                 return errcode;
144
145         mcount = section->mcount;
146         if (mcount)
147                 return pt_section_map_success(section);
148
149         if (section->mapping)
150                 goto out_unlock;
151
152         filename = section->filename;
153         if (!filename)
154                 goto out_unlock;
155
156         status = section->status;
157         if (!status)
158                 goto out_unlock;
159
160         errcode = -pte_bad_image;
161         file = fopen(filename, "rb");
162         if (!file)
163                 goto out_unlock;
164
165         errcode = fseek(file, 0, SEEK_END);
166         if (errcode) {
167                 errcode = -pte_bad_image;
168                 goto out_file;
169         }
170
171         errcode = -pte_bad_image;
172         size = ftell(file);
173         if (size < 0)
174                 goto out_file;
175
176         if (size != status->size)
177                 goto out_file;
178
179         /* We need to keep the file open on success.  It will be closed when
180          * the section is unmapped.
181          */
182         errcode = pt_sec_file_map(section, file);
183         if (!errcode)
184                 return pt_section_map_success(section);
185
186 out_file:
187         fclose(file);
188
189 out_unlock:
190         (void) pt_section_unlock(section);
191         return errcode;
192 }