/*
 * Copyright (c) 2013-2016, 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.
 */

#define _POSIX_C_SOURCE 1
#define _DARWIN_C_SOURCE 1

#include "pt_section.h"
#include "pt_section_posix.h"
#include "pt_section_file.h"

#include "intel-pt.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>


int pt_section_mk_status(void **pstatus, uint64_t *psize, const char *filename)
{
	struct pt_sec_posix_status *status;
	struct stat buffer;
	int errcode;

	if (!pstatus || !psize)
		return -pte_internal;

	errcode = stat(filename, &buffer);
	if (errcode < 0)
		return errcode;

	if (buffer.st_size < 0)
		return -pte_bad_image;

	status = malloc(sizeof(*status));
	if (!status)
		return -pte_nomem;

	status->stat = buffer;

	*pstatus = status;
	*psize = buffer.st_size;

	return 0;
}

static int check_file_status(struct pt_section *section, int fd)
{
	struct pt_sec_posix_status *status;
	struct stat stat;
	int errcode;

	if (!section)
		return -pte_internal;

	errcode = fstat(fd, &stat);
	if (errcode)
		return -pte_bad_image;

	status = section->status;
	if (!status)
		return -pte_internal;

	if (stat.st_size != status->stat.st_size)
		return -pte_bad_image;

	if (stat.st_mtime != status->stat.st_mtime)
		return -pte_bad_image;

	return 0;
}

int pt_sec_posix_map(struct pt_section *section, int fd)
{
	struct pt_sec_posix_mapping *mapping;
	uint64_t offset, size, adjustment;
	uint8_t *base;

	if (!section)
		return -pte_internal;

	offset = section->offset;
	size = section->size;

	adjustment = offset % PAGE_SIZE;

	offset -= adjustment;
	size += adjustment;

	/* The section is supposed to fit into the file so we shouldn't
	 * see any overflows, here.
	 */
	if (size < section->size)
		return -pte_internal;

	base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, offset);
	if (base == MAP_FAILED)
		return -pte_nomem;

	mapping = malloc(sizeof(*mapping));
	if (!mapping)
		goto out_map;

	mapping->base = base;
	mapping->size = size;
	mapping->begin = base + adjustment;
	mapping->end = base + size;

	section->mapping = mapping;
	section->unmap = pt_sec_posix_unmap;
	section->read = pt_sec_posix_read;

	return 0;

out_map:
	munmap(base, size);
	return -pte_nomem;
}

int pt_section_map(struct pt_section *section)
{
	const char *filename;
	uint16_t mcount;
	FILE *file;
	int fd, errcode;

	if (!section)
		return -pte_internal;

	errcode = pt_section_lock(section);
	if (errcode < 0)
		return errcode;

	mcount = section->mcount + 1;
	if (mcount > 1) {
		section->mcount = mcount;
		return pt_section_unlock(section);
	}

	errcode = -pte_internal;
	if (!mcount)
		goto out_unlock;

	if (section->mapping)
		goto out_unlock;

	filename = section->filename;
	if (!filename)
		goto out_unlock;

	errcode = -pte_bad_image;
	fd = open(filename, O_RDONLY);
	if (fd == -1)
		goto out_unlock;

	errcode = check_file_status(section, fd);
	if (errcode < 0)
		goto out_fd;

	/* We close the file on success.  This does not unmap the section. */
	errcode = pt_sec_posix_map(section, fd);
	if (!errcode) {
		section->mcount = 1;
		close(fd);
		return pt_section_unlock(section);
	}

	/* Fall back to file based sections - report the original error
	 * if we fail to convert the file descriptor.
	 */
	file = fdopen(fd, "rb");
	if (!file)
		goto out_fd;

	/* 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) {
		section->mcount = 1;
		return pt_section_unlock(section);
	}

	fclose(file);
	goto out_unlock;

out_fd:
	close(fd);

out_unlock:
	(void) pt_section_unlock(section);
	return errcode;
}

int pt_sec_posix_unmap(struct pt_section *section)
{
	struct pt_sec_posix_mapping *mapping;

	if (!section)
		return -pte_internal;

	mapping = section->mapping;
	if (!mapping || !section->unmap || !section->read)
		return -pte_internal;

	section->mapping = NULL;
	section->unmap = NULL;
	section->read = NULL;

	munmap(mapping->base, mapping->size);
	free(mapping);

	return 0;
}

int pt_sec_posix_read(const struct pt_section *section, uint8_t *buffer,
		      uint16_t size, uint64_t offset)
{
	struct pt_sec_posix_mapping *mapping;
	const uint8_t *begin;

	if (!buffer || !section)
		return -pte_invalid;

	mapping = section->mapping;
	if (!mapping)
		return -pte_internal;

	/* We already checked in pt_section_read() that the requested memory
	 * lies within the section's boundaries.
	 *
	 * And we checked that the entire section was mapped.  There's no need
	 * to check for overflows, again.
	 */
	begin = mapping->begin + offset;

	memcpy(buffer, begin, size);
	return (int) size;
}
