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