190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2013-2019, Intel Corporation 390792Sgshapiro * 490792Sgshapiro * Redistribution and use in source and binary forms, with or without 590792Sgshapiro * modification, are permitted provided that the following conditions are met: 690792Sgshapiro * 790792Sgshapiro * * Redistributions of source code must retain the above copyright notice, 890792Sgshapiro * this list of conditions and the following disclaimer. 990792Sgshapiro * * Redistributions in binary form must reproduce the above copyright notice, 1090792Sgshapiro * this list of conditions and the following disclaimer in the documentation 11266692Sgshapiro * and/or other materials provided with the distribution. 1290792Sgshapiro * * Neither the name of Intel Corporation nor the names of its contributors 1390792Sgshapiro * may be used to endorse or promote products derived from this software 1490792Sgshapiro * without specific prior written permission. 1590792Sgshapiro * 1690792Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1790792Sgshapiro * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1890792Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1990792Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2090792Sgshapiro * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2190792Sgshapiro * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2290792Sgshapiro * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2390792Sgshapiro * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2490792Sgshapiro * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2590792Sgshapiro * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2690792Sgshapiro * POSSIBILITY OF SUCH DAMAGE. 2790792Sgshapiro */ 2890792Sgshapiro 2990792Sgshapiro#include "pt_section.h" 3090792Sgshapiro#include "pt_section_file.h" 3190792Sgshapiro 3290792Sgshapiro#include "intel-pt.h" 3390792Sgshapiro 3490792Sgshapiro#include <stdlib.h> 3590792Sgshapiro#include <string.h> 3690792Sgshapiro 3790792Sgshapiro 3890792Sgshapirostatic int fmap_init(struct pt_sec_file_mapping *mapping) 3990792Sgshapiro{ 4090792Sgshapiro if (!mapping) 4190792Sgshapiro return -pte_internal; 4290792Sgshapiro 4390792Sgshapiro memset(mapping, 0, sizeof(*mapping)); 4490792Sgshapiro 4590792Sgshapiro#if defined(FEATURE_THREADS) 4690792Sgshapiro { 4790792Sgshapiro int errcode; 4890792Sgshapiro 4990792Sgshapiro errcode = mtx_init(&mapping->lock, mtx_plain); 5090792Sgshapiro if (errcode != thrd_success) 5190792Sgshapiro return -pte_bad_lock; 5290792Sgshapiro } 5390792Sgshapiro#endif /* defined(FEATURE_THREADS) */ 5490792Sgshapiro 5590792Sgshapiro return 0; 5690792Sgshapiro} 5790792Sgshapiro 5890792Sgshapirostatic void fmap_fini(struct pt_sec_file_mapping *mapping) 5990792Sgshapiro{ 6090792Sgshapiro if (!mapping) 6190792Sgshapiro return; 6290792Sgshapiro 6390792Sgshapiro fclose(mapping->file); 6490792Sgshapiro 6590792Sgshapiro#if defined(FEATURE_THREADS) 6690792Sgshapiro 6790792Sgshapiro mtx_destroy(&mapping->lock); 6890792Sgshapiro 6990792Sgshapiro#endif /* defined(FEATURE_THREADS) */ 7090792Sgshapiro} 7190792Sgshapiro 7290792Sgshapirostatic int fmap_lock(struct pt_sec_file_mapping *mapping) 7390792Sgshapiro{ 7490792Sgshapiro if (!mapping) 7590792Sgshapiro return -pte_internal; 7690792Sgshapiro 7790792Sgshapiro#if defined(FEATURE_THREADS) 7890792Sgshapiro { 7990792Sgshapiro int errcode; 8090792Sgshapiro 8190792Sgshapiro errcode = mtx_lock(&mapping->lock); 8290792Sgshapiro if (errcode != thrd_success) 8390792Sgshapiro return -pte_bad_lock; 8490792Sgshapiro } 8590792Sgshapiro#endif /* defined(FEATURE_THREADS) */ 8690792Sgshapiro 8790792Sgshapiro return 0; 8890792Sgshapiro} 8990792Sgshapiro 9090792Sgshapirostatic int fmap_unlock(struct pt_sec_file_mapping *mapping) 9190792Sgshapiro{ 9290792Sgshapiro if (!mapping) 9390792Sgshapiro return -pte_internal; 9490792Sgshapiro 9590792Sgshapiro#if defined(FEATURE_THREADS) 9690792Sgshapiro { 9790792Sgshapiro int errcode; 9890792Sgshapiro 9990792Sgshapiro errcode = mtx_unlock(&mapping->lock); 10090792Sgshapiro if (errcode != thrd_success) 10190792Sgshapiro return -pte_bad_lock; 10290792Sgshapiro } 10390792Sgshapiro#endif /* defined(FEATURE_THREADS) */ 10490792Sgshapiro 10590792Sgshapiro return 0; 10690792Sgshapiro} 10790792Sgshapiro 10890792Sgshapiroint pt_sec_file_map(struct pt_section *section, FILE *file) 10990792Sgshapiro{ 110 struct pt_sec_file_mapping *mapping; 111 uint64_t offset, size; 112 long begin, end, fsize; 113 int errcode; 114 115 if (!section) 116 return -pte_internal; 117 118 mapping = section->mapping; 119 if (mapping) 120 return -pte_internal; 121 122 offset = section->offset; 123 size = section->size; 124 125 begin = (long) offset; 126 end = begin + (long) size; 127 128 /* Check for overflows. */ 129 if ((uint64_t) begin != offset) 130 return -pte_bad_image; 131 132 if ((uint64_t) end != (offset + size)) 133 return -pte_bad_image; 134 135 if (end < begin) 136 return -pte_bad_image; 137 138 /* Validate that the section lies within the file. */ 139 errcode = fseek(file, 0, SEEK_END); 140 if (errcode) 141 return -pte_bad_image; 142 143 fsize = ftell(file); 144 if (fsize < 0) 145 return -pte_bad_image; 146 147 if (fsize < end) 148 return -pte_bad_image; 149 150 mapping = malloc(sizeof(*mapping)); 151 if (!mapping) 152 return -pte_nomem; 153 154 errcode = fmap_init(mapping); 155 if (errcode < 0) 156 goto out_mem; 157 158 mapping->file = file; 159 mapping->begin = begin; 160 mapping->end = end; 161 162 section->mapping = mapping; 163 section->unmap = pt_sec_file_unmap; 164 section->read = pt_sec_file_read; 165 section->memsize = pt_sec_file_memsize; 166 167 return 0; 168 169out_mem: 170 free(mapping); 171 return errcode; 172} 173 174int pt_sec_file_unmap(struct pt_section *section) 175{ 176 struct pt_sec_file_mapping *mapping; 177 178 if (!section) 179 return -pte_internal; 180 181 mapping = section->mapping; 182 183 if (!mapping || !section->unmap || !section->read || !section->memsize) 184 return -pte_internal; 185 186 section->mapping = NULL; 187 section->unmap = NULL; 188 section->read = NULL; 189 section->memsize = NULL; 190 191 fmap_fini(mapping); 192 free(mapping); 193 194 return 0; 195} 196 197int pt_sec_file_read(const struct pt_section *section, uint8_t *buffer, 198 uint16_t size, uint64_t offset) 199{ 200 struct pt_sec_file_mapping *mapping; 201 FILE *file; 202 long begin; 203 size_t read; 204 int errcode; 205 206 if (!buffer || !section) 207 return -pte_internal; 208 209 mapping = section->mapping; 210 if (!mapping) 211 return -pte_internal; 212 213 file = mapping->file; 214 215 /* We already checked in pt_section_read() that the requested memory 216 * lies within the section's boundaries. 217 * 218 * And we checked that the file covers the entire section in 219 * pt_sec_file_map(). There's no need to check for overflows, again. 220 */ 221 begin = mapping->begin + (long) offset; 222 223 errcode = fmap_lock(mapping); 224 if (errcode < 0) 225 return errcode; 226 227 errcode = fseek(file, begin, SEEK_SET); 228 if (errcode) 229 goto out_unlock; 230 231 read = fread(buffer, 1, size, file); 232 233 errcode = fmap_unlock(mapping); 234 if (errcode < 0) 235 return errcode; 236 237 return (int) read; 238 239out_unlock: 240 (void) fmap_unlock(mapping); 241 return -pte_nomap; 242} 243 244int pt_sec_file_memsize(const struct pt_section *section, uint64_t *size) 245{ 246 if (!section || !size) 247 return -pte_internal; 248 249 if (!section->mapping) 250 return -pte_internal; 251 252 *size = 0ull; 253 254 return 0; 255} 256