|
Packit |
b1f7ae |
/*
|
|
Packit |
b1f7ae |
* Copyright (c) 2013-2017, Intel Corporation
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
b1f7ae |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
b1f7ae |
* this list of conditions and the following disclaimer.
|
|
Packit |
b1f7ae |
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
b1f7ae |
* this list of conditions and the following disclaimer in the documentation
|
|
Packit |
b1f7ae |
* and/or other materials provided with the distribution.
|
|
Packit |
b1f7ae |
* * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
b1f7ae |
* may be used to endorse or promote products derived from this software
|
|
Packit |
b1f7ae |
* without specific prior written permission.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
b1f7ae |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
b1f7ae |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
b1f7ae |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
b1f7ae |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
b1f7ae |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
b1f7ae |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
b1f7ae |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
b1f7ae |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
b1f7ae |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
b1f7ae |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include "pt_section.h"
|
|
Packit |
b1f7ae |
#include "pt_section_file.h"
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include "intel-pt.h"
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include <stdlib.h>
|
|
Packit |
b1f7ae |
#include <string.h>
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int fmap_init(struct pt_sec_file_mapping *mapping)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!mapping)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
memset(mapping, 0, sizeof(*mapping));
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#if defined(FEATURE_THREADS)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = mtx_init(&mapping->lock, mtx_plain);
|
|
Packit |
b1f7ae |
if (errcode != thrd_success)
|
|
Packit |
b1f7ae |
return -pte_bad_lock;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
#endif /* defined(FEATURE_THREADS) */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static void fmap_fini(struct pt_sec_file_mapping *mapping)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!mapping)
|
|
Packit |
b1f7ae |
return;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
fclose(mapping->file);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#if defined(FEATURE_THREADS)
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
mtx_destroy(&mapping->lock);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#endif /* defined(FEATURE_THREADS) */
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int fmap_lock(struct pt_sec_file_mapping *mapping)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!mapping)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#if defined(FEATURE_THREADS)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = mtx_lock(&mapping->lock);
|
|
Packit |
b1f7ae |
if (errcode != thrd_success)
|
|
Packit |
b1f7ae |
return -pte_bad_lock;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
#endif /* defined(FEATURE_THREADS) */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int fmap_unlock(struct pt_sec_file_mapping *mapping)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!mapping)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#if defined(FEATURE_THREADS)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = mtx_unlock(&mapping->lock);
|
|
Packit |
b1f7ae |
if (errcode != thrd_success)
|
|
Packit |
b1f7ae |
return -pte_bad_lock;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
#endif /* defined(FEATURE_THREADS) */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int pt_sec_file_map(struct pt_section *section, FILE *file)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
struct pt_sec_file_mapping *mapping;
|
|
Packit |
b1f7ae |
uint64_t offset, size;
|
|
Packit |
b1f7ae |
long begin, end, fsize;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!section)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
mapping = section->mapping;
|
|
Packit |
b1f7ae |
if (mapping)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
offset = section->offset;
|
|
Packit |
b1f7ae |
size = section->size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
begin = (long) offset;
|
|
Packit |
b1f7ae |
end = begin + (long) size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Check for overflows. */
|
|
Packit |
b1f7ae |
if ((uint64_t) begin != offset)
|
|
Packit |
b1f7ae |
return -pte_bad_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if ((uint64_t) end != (offset + size))
|
|
Packit |
b1f7ae |
return -pte_bad_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (end < begin)
|
|
Packit |
b1f7ae |
return -pte_bad_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Validate that the section lies within the file. */
|
|
Packit |
b1f7ae |
errcode = fseek(file, 0, SEEK_END);
|
|
Packit |
b1f7ae |
if (errcode)
|
|
Packit |
b1f7ae |
return -pte_bad_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
fsize = ftell(file);
|
|
Packit |
b1f7ae |
if (fsize < 0)
|
|
Packit |
b1f7ae |
return -pte_bad_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (fsize < end)
|
|
Packit |
b1f7ae |
return -pte_bad_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
mapping = malloc(sizeof(*mapping));
|
|
Packit |
b1f7ae |
if (!mapping)
|
|
Packit |
b1f7ae |
return -pte_nomem;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = fmap_init(mapping);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
free(mapping);
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
mapping->file = file;
|
|
Packit |
b1f7ae |
mapping->begin = begin;
|
|
Packit |
b1f7ae |
mapping->end = end;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
section->mapping = mapping;
|
|
Packit |
b1f7ae |
section->unmap = pt_sec_file_unmap;
|
|
Packit |
b1f7ae |
section->read = pt_sec_file_read;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return pt_section_add_bcache(section);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int pt_sec_file_unmap(struct pt_section *section)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
struct pt_sec_file_mapping *mapping;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!section)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
mapping = section->mapping;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!mapping || !section->unmap || !section->read)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
section->mapping = NULL;
|
|
Packit |
b1f7ae |
section->unmap = NULL;
|
|
Packit |
b1f7ae |
section->read = NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
fmap_fini(mapping);
|
|
Packit |
b1f7ae |
free(mapping);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int pt_sec_file_read(const struct pt_section *section, uint8_t *buffer,
|
|
Packit |
b1f7ae |
uint16_t size, uint64_t offset)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
struct pt_sec_file_mapping *mapping;
|
|
Packit |
b1f7ae |
FILE *file;
|
|
Packit |
b1f7ae |
long begin;
|
|
Packit |
b1f7ae |
size_t read;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!buffer || !section)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
mapping = section->mapping;
|
|
Packit |
b1f7ae |
if (!mapping)
|
|
Packit |
b1f7ae |
return -pte_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
file = mapping->file;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* We already checked in pt_section_read() that the requested memory
|
|
Packit |
b1f7ae |
* lies within the section's boundaries.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* And we checked that the file covers the entire section in
|
|
Packit |
b1f7ae |
* pt_sec_file_map(). There's no need to check for overflows, again.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
begin = mapping->begin + (long) offset;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = fmap_lock(mapping);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = fseek(file, begin, SEEK_SET);
|
|
Packit |
b1f7ae |
if (errcode)
|
|
Packit |
b1f7ae |
goto out_unlock;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
read = fread(buffer, 1, size, file);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = fmap_unlock(mapping);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return (int) read;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
out_unlock:
|
|
Packit |
b1f7ae |
(void) fmap_unlock(mapping);
|
|
Packit |
b1f7ae |
return -pte_nomap;
|
|
Packit |
b1f7ae |
}
|