Import Intel Processor Trace decoder library from

vendor/processor-trace/24982c1a6fce48f1e416461d42899805f74fbb26

Sponsored by:	DARPA, AFRL
This commit is contained in:
br 2018-03-19 18:59:15 +00:00
commit c27a7c453c
95 changed files with 45831 additions and 0 deletions

View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 2014-2018, 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.
*
*
* It looks like there is still no support for C11's threads.h.
*
* We implement the few features we actually need hoping that this file will
* soon go away.
*/
#ifndef THREADS_H
#define THREADS_H
#include <pthread.h>
#ifndef PTHREAD_MUTEX_NORMAL
# define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP
#endif
#include <stdint.h>
#include <stdlib.h>
enum {
thrd_success = 1,
thrd_error
};
struct pt_thread {
pthread_t thread;
};
typedef struct pt_thread thrd_t;
typedef int (*thrd_start_t)(void *);
struct thrd_args {
thrd_start_t fun;
void *arg;
};
static void *thrd_routine(void *arg)
{
struct thrd_args *args;
int result;
args = arg;
if (!args)
return (void *) (intptr_t) -1;
result = -1;
if (args->fun)
result = args->fun(args->arg);
free(args);
return (void *) (intptr_t) result;
}
static inline int thrd_create(thrd_t *thrd, thrd_start_t fun, void *arg)
{
struct thrd_args *args;
int errcode;
if (!thrd || !fun)
return thrd_error;
args = malloc(sizeof(*args));
if (!args)
return thrd_error;
args->fun = fun;
args->arg = arg;
errcode = pthread_create(&thrd->thread, NULL, thrd_routine, args);
if (errcode) {
free(args);
return thrd_error;
}
return thrd_success;
}
static inline int thrd_join(thrd_t *thrd, int *res)
{
void *result;
int errcode;
if (!thrd)
return thrd_error;
errcode = pthread_join(thrd->thread, &result);
if (errcode)
return thrd_error;
if (res)
*res = (int) (intptr_t) result;
return thrd_success;
}
struct pt_mutex {
pthread_mutex_t mutex;
};
typedef struct pt_mutex mtx_t;
enum {
mtx_plain = PTHREAD_MUTEX_NORMAL
};
static inline int mtx_init(mtx_t *mtx, int type)
{
int errcode;
if (!mtx || type != mtx_plain)
return thrd_error;
errcode = pthread_mutex_init(&mtx->mutex, NULL);
if (errcode)
return thrd_error;
return thrd_success;
}
static inline void mtx_destroy(mtx_t *mtx)
{
if (mtx)
(void) pthread_mutex_destroy(&mtx->mutex);
}
static inline int mtx_lock(mtx_t *mtx)
{
int errcode;
if (!mtx)
return thrd_error;
errcode = pthread_mutex_lock(&mtx->mutex);
if (errcode)
return thrd_error;
return thrd_success;
}
static inline int mtx_unlock(mtx_t *mtx)
{
int errcode;
if (!mtx)
return thrd_error;
errcode = pthread_mutex_unlock(&mtx->mutex);
if (errcode)
return thrd_error;
return thrd_success;
}
struct pt_cond {
pthread_cond_t cond;
};
typedef struct pt_cond cnd_t;
static inline int cnd_init(cnd_t *cnd)
{
int errcode;
if (!cnd)
return thrd_error;
errcode = pthread_cond_init(&cnd->cond, NULL);
if (errcode)
return thrd_error;
return thrd_success;
}
static inline int cnd_destroy(cnd_t *cnd)
{
int errcode;
if (!cnd)
return thrd_error;
errcode = pthread_cond_destroy(&cnd->cond);
if (errcode)
return thrd_error;
return thrd_success;
}
static inline int cnd_signal(cnd_t *cnd)
{
int errcode;
if (!cnd)
return thrd_error;
errcode = pthread_cond_signal(&cnd->cond);
if (errcode)
return thrd_error;
return thrd_success;
}
static inline int cnd_broadcast(cnd_t *cnd)
{
int errcode;
if (!cnd)
return thrd_error;
errcode = pthread_cond_broadcast(&cnd->cond);
if (errcode)
return thrd_error;
return thrd_success;
}
static inline int cnd_wait(cnd_t *cnd, mtx_t *mtx)
{
int errcode;
if (!cnd || !mtx)
return thrd_error;
errcode = pthread_cond_wait(&cnd->cond, &mtx->mutex);
if (errcode)
return thrd_error;
return thrd_success;
}
#endif /* THREADS_H */

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017-2018, 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.
*/
#ifndef PT_COMPILER_H
#define PT_COMPILER_H
/* Both the relevant Clang and GCC versions support this. */
#if !defined(__has_attribute)
# define __has_attribute(attr) 0
#endif
#if !defined(fallthrough)
# if (__has_attribute(fallthrough))
# define fallthrough __attribute__((fallthrough))
# else
# define fallthrough /* Fall through. */
# endif
#endif /* !defined(fallthrough) */
#endif /* PT_COMPILER_H */

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include <stddef.h>
#include <stdint.h>
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
#ifndef PRIx64
# define PRIx64 "llx"
#endif
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRIu32
# define PRIu32 "u"
#endif
#ifndef PRIx32
# define PRIx32 "x"
#endif
#ifndef PRIu16
# define PRIu16 "u"
#endif
#ifndef PRIu8
# define PRIu8 "u"
#endif
#ifndef PRIx8
# define PRIx8 "x"
#endif
#ifndef SCNx64
# define SCNx64 "llx"
#endif

View File

@ -0,0 +1,239 @@
/*
* Copyright (c) 2014-2018, 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.
*
*
* It looks like there is still no support for C11's threads.h.
*
* We implement the few features we actually need hoping that this file will
* soon go away.
*/
#ifndef THREADS_H
#define THREADS_H
#include "windows.h"
enum {
thrd_success = 1,
thrd_error
};
struct pt_thread {
HANDLE handle;
};
typedef struct pt_thread thrd_t;
typedef int (*thrd_start_t)(void *);
struct thrd_args {
thrd_start_t fun;
void *arg;
};
static DWORD WINAPI thrd_routine(void *arg)
{
struct thrd_args *args;
int result;
args = (struct thrd_args *) arg;
if (!args)
return (DWORD) -1;
result = -1;
if (args->fun)
result = args->fun(args->arg);
free(args);
return (DWORD) result;
}
static inline int thrd_create(thrd_t *thrd, thrd_start_t fun, void *arg)
{
struct thrd_args *args;
HANDLE handle;
if (!thrd || !fun)
return thrd_error;
args = malloc(sizeof(*args));
if (!args)
return thrd_error;
args->fun = fun;
args->arg = arg;
handle = CreateThread(NULL, 0, thrd_routine, args, 0, NULL);
if (!handle) {
free(args);
return thrd_error;
}
thrd->handle = handle;
return thrd_success;
}
static inline int thrd_join(thrd_t *thrd, int *res)
{
DWORD status;
BOOL success;
if (!thrd)
return thrd_error;
status = WaitForSingleObject(thrd->handle, INFINITE);
if (status)
return thrd_error;
if (res) {
DWORD result;
success = GetExitCodeThread(thrd->handle, &result);
if (!success) {
(void) CloseHandle(thrd->handle);
return thrd_error;
}
*res = (int) result;
}
success = CloseHandle(thrd->handle);
if (!success)
return thrd_error;
return thrd_success;
}
struct pt_mutex {
CRITICAL_SECTION cs;
};
typedef struct pt_mutex mtx_t;
enum {
mtx_plain
};
static inline int mtx_init(mtx_t *mtx, int type)
{
if (!mtx || type != mtx_plain)
return thrd_error;
InitializeCriticalSection(&mtx->cs);
return thrd_success;
}
static inline void mtx_destroy(mtx_t *mtx)
{
if (mtx)
DeleteCriticalSection(&mtx->cs);
}
static inline int mtx_lock(mtx_t *mtx)
{
if (!mtx)
return thrd_error;
EnterCriticalSection(&mtx->cs);
return thrd_success;
}
static inline int mtx_unlock(mtx_t *mtx)
{
if (!mtx)
return thrd_error;
LeaveCriticalSection(&mtx->cs);
return thrd_success;
}
struct pt_cond {
CONDITION_VARIABLE cond;
};
typedef struct pt_cond cnd_t;
static inline int cnd_init(cnd_t *cnd)
{
if (!cnd)
return thrd_error;
InitializeConditionVariable(&cnd->cond);
return thrd_success;
}
static inline int cnd_destroy(cnd_t *cnd)
{
if (!cnd)
return thrd_error;
/* Nothing to do. */
return thrd_success;
}
static inline int cnd_signal(cnd_t *cnd)
{
if (!cnd)
return thrd_error;
WakeConditionVariable(&cnd->cond);
return thrd_success;
}
static inline int cnd_broadcast(cnd_t *cnd)
{
if (!cnd)
return thrd_error;
WakeAllConditionVariable(&cnd->cond);
return thrd_success;
}
static inline int cnd_wait(cnd_t *cnd, mtx_t *mtx)
{
BOOL success;
if (!cnd || !mtx)
return thrd_error;
success = SleepConditionVariableCS(&cnd->cond, &mtx->cs, INFINITE);
if (!success)
return thrd_error;
return thrd_success;
}
#endif /* THREADS_H */

View File

@ -0,0 +1,172 @@
# Copyright (c) 2013-2018, 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.
include_directories(
internal/include
)
set(LIBIPT_SECTION_FILES
src/pt_section.c
src/pt_section_file.c
)
set(LIBIPT_FILES
src/pt_error.c
src/pt_packet_decoder.c
src/pt_query_decoder.c
src/pt_encoder.c
src/pt_sync.c
src/pt_version.c
src/pt_last_ip.c
src/pt_tnt_cache.c
src/pt_ild.c
src/pt_image.c
src/pt_image_section_cache.c
src/pt_retstack.c
src/pt_insn_decoder.c
src/pt_time.c
src/pt_asid.c
src/pt_event_queue.c
src/pt_packet.c
src/pt_decoder_function.c
src/pt_config.c
src/pt_insn.c
src/pt_block_decoder.c
src/pt_block_cache.c
src/pt_msec_cache.c
)
if (CMAKE_HOST_UNIX)
include_directories(
internal/include/posix
)
set(LIBIPT_FILES ${LIBIPT_FILES} src/posix/init.c)
set(LIBIPT_SECTION_FILES ${LIBIPT_SECTION_FILES} src/posix/pt_section_posix.c)
endif (CMAKE_HOST_UNIX)
if (CMAKE_HOST_WIN32)
add_definitions(
# export libipt symbols
#
/Dpt_export=__declspec\(dllexport\)
)
include_directories(
internal/include/windows
)
set(LIBIPT_FILES ${LIBIPT_FILES} src/windows/init.c)
set(LIBIPT_SECTION_FILES ${LIBIPT_SECTION_FILES} src/windows/pt_section_windows.c)
endif (CMAKE_HOST_WIN32)
set(LIBIPT_FILES ${LIBIPT_FILES} ${LIBIPT_SECTION_FILES})
add_library(libipt SHARED
${LIBIPT_FILES}
)
# put the version into the intel-pt header
#
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/intel-pt.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/intel-pt.h
)
set_target_properties(libipt PROPERTIES
PREFIX ""
PUBLIC_HEADER ${CMAKE_CURRENT_BINARY_DIR}/include/intel-pt.h
VERSION ${PT_VERSION}
SOVERSION ${PT_VERSION_MAJOR}
)
install(TARGETS libipt
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
function(add_ptunit_std_test name)
add_ptunit_c_test(${name} src/pt_${name}.c ${ARGN})
endfunction(add_ptunit_std_test)
add_ptunit_std_test(last_ip)
add_ptunit_std_test(tnt_cache)
add_ptunit_std_test(retstack)
add_ptunit_std_test(ild)
add_ptunit_std_test(cpu)
add_ptunit_std_test(time)
add_ptunit_std_test(asid)
add_ptunit_std_test(event_queue)
add_ptunit_std_test(image src/pt_asid.c)
add_ptunit_std_test(sync src/pt_packet.c)
add_ptunit_std_test(config)
add_ptunit_std_test(image_section_cache)
add_ptunit_std_test(block_cache)
add_ptunit_std_test(msec_cache)
add_ptunit_c_test(mapped_section src/pt_asid.c)
add_ptunit_c_test(query
src/pt_encoder.c
src/pt_last_ip.c
src/pt_packet_decoder.c
src/pt_sync.c
src/pt_tnt_cache.c
src/pt_time.c
src/pt_event_queue.c
src/pt_query_decoder.c
src/pt_packet.c
src/pt_decoder_function.c
src/pt_packet_decoder.c
src/pt_config.c
src/pt_time.c
src/pt_block_cache.c
)
add_ptunit_c_test(section ${LIBIPT_SECTION_FILES})
add_ptunit_c_test(section-file
test/src/ptunit-section.c
src/pt_section.c
src/pt_section_file.c
)
add_ptunit_c_test(packet
src/pt_encoder.c
src/pt_packet_decoder.c
src/pt_sync.c
src/pt_packet.c
src/pt_decoder_function.c
src/pt_config.c
)
add_ptunit_c_test(fetch
src/pt_decoder_function.c
src/pt_encoder.c
src/pt_config.c
)
add_ptunit_cpp_test(cpp)
add_ptunit_libraries(cpp libipt)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2015-2018, 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.
*/
#ifndef PT_SECTION_POSIX_H
#define PT_SECTION_POSIX_H
#include <stdint.h>
#include <sys/stat.h>
struct pt_section;
/* Fstat-based file status. */
struct pt_sec_posix_status {
/* The file status. */
struct stat stat;
};
/* MMAP-based section mapping information. */
struct pt_sec_posix_mapping {
/* The mmap base address. */
uint8_t *base;
/* The mapped memory size. */
uint64_t size;
/* The begin and end of the mapped memory. */
const uint8_t *begin, *end;
};
/* Map a section.
*
* On success, sets @section's mapping, unmap, and read pointers.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @file are NULL.
* Returns -pte_invalid if @section can't be mapped.
*/
extern int pt_sec_posix_map(struct pt_section *section, int fd);
/* Unmap a section.
*
* On success, clears @section's mapping, unmap, and read pointers.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_sec_posix_unmap(struct pt_section *section);
/* Read memory from an mmaped section.
*
* Reads at most @size bytes from @section at @offset into @buffer.
*
* Returns the number of bytes read on success, a negative error code otherwise.
* Returns -pte_invalid if @section or @buffer are NULL.
* Returns -pte_nomap if @offset is beyond the end of the section.
*/
extern int pt_sec_posix_read(const struct pt_section *section, uint8_t *buffer,
uint16_t size, uint64_t offset);
/* Compute the memory size of a section.
*
* On success, provides the amount of memory used for mapping @section in bytes
* in @size.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @size is NULL.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_sec_posix_memsize(const struct pt_section *section,
uint64_t *size);
#endif /* PT_SECTION_POSIX_H */

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_ASID_H
#define PT_ASID_H
#include <stddef.h>
struct pt_asid;
/* Read an asid provided by our user.
*
* Translate a user-provided asid in @user into @asid. This uses default values
* for fields that are not provided by the user and for all fields, if @user is
* NULL.
*
* Fields set in @user that are not known (i.e. from a newer version of this
* library) will be ignored.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal, if @asid is NULL.
*/
extern int pt_asid_from_user(struct pt_asid *asid, const struct pt_asid *user);
/* Provide an asid to the user.
*
* Translate @asid into a potentially older or newer version in @user.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal, if @user or @asid is NULL.
* Returns -pte_invalid, if @size is too small.
*/
extern int pt_asid_to_user(struct pt_asid *user, const struct pt_asid *asid,
size_t size);
/* Match two asids.
*
* Asids match if all fields provide either default values or are identical.
*
* Returns a positive number if @lhs matches @rhs.
* Returns zero if @lhs does not match @rhs.
* Returns a negative error code otherwise.
*
* Returns -pte_internal if @lhs or @rhs are NULL.
*/
extern int pt_asid_match(const struct pt_asid *lhs, const struct pt_asid *rhs);
#endif /* PT_ASID_H */

View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#ifndef PT_BLOCK_CACHE_H
#define PT_BLOCK_CACHE_H
#include "intel-pt.h"
#include <stdint.h>
/* A block cache entry qualifier.
*
* This describes what to do at the decision point determined by a block cache
* entry.
*/
enum pt_bcache_qualifier {
/* This is not a decision point.
*
* The next decision point is too far away and one or more fields
* threatened to overflow so we had to stop somewhere on our way.
*
* Apply the displacement and number of instructions and continue from
* the resulting IP.
*/
ptbq_again,
/* The decision point is a conditional branch.
*
* This requires a conditional branch query.
*
* The isize field should provide the size of the branch instruction so
* only taken branches require the instruction to be decoded.
*/
ptbq_cond,
/* The decision point is a near indirect call.
*
* This requires a return-address stack update and an indirect branch
* query.
*
* The isize field should provide the size of the call instruction so
* the return address can be computed by adding it to the displacement
* that brings us to the call instruction.
*
* No instruction decode is required.
*/
ptbq_ind_call,
/* The decision point is a near return.
*
* The return may be compressed so this requires a conditional branch
* query to determine the compression state and either a return-address
* stack lookup or an indirect branch query.
*
* No instruction decode is required.
*/
ptbq_return,
/* The decision point is an indirect jump or far branch.
*
* This requires an indirect branch query.
*
* No instruction decode is required.
*/
ptbq_indirect,
/* The decision point requires the instruction at the decision point IP
* to be decoded to determine the next step.
*
* This is used for
*
* - near direct calls that need to maintain the return-address stack.
*
* - near direct jumps that are too far away to be handled with a
* block cache entry as they would overflow the displacement field.
*/
ptbq_decode
};
/* A block cache entry.
*
* There will be one such entry per byte of decoded memory image. Each entry
* corresponds to an IP in the traced memory image. The cache is initialized
* with invalid entries for all IPs.
*
* Only entries for the first byte of each instruction will be used; other
* entries are ignored and will remain invalid.
*
* Each valid entry gives the distance from the entry's IP to the next decision
* point both in bytes and in the number of instructions.
*/
struct pt_bcache_entry {
/* The displacement to the next decision point in bytes.
*
* This is zero if we are at a decision point except for ptbq_again
* where it gives the displacement to the next block cache entry to be
* used.
*/
int32_t displacement:16;
/* The number of instructions to the next decision point.
*
* This is typically one at a decision point since we are already
* accounting for the instruction at the decision point.
*
* Note that this field must be smaller than the respective struct
* pt_block field so we can fit one block cache entry into an empty
* block.
*/
uint32_t ninsn:8;
/* The execution mode for all instruction between here and the next
* decision point.
*
* This is enum pt_exec_mode.
*
* This is ptem_unknown if the entry is not valid.
*/
uint32_t mode:2;
/* The decision point qualifier.
*
* This is enum pt_bcache_qualifier.
*/
uint32_t qualifier:3;
/* The size of the instruction at the decision point.
*
* This is zero if the size is too big to fit into the field. In this
* case, the instruction needs to be decoded to determine its size.
*/
uint32_t isize:3;
};
/* Get the execution mode of a block cache entry. */
static inline enum pt_exec_mode pt_bce_exec_mode(struct pt_bcache_entry bce)
{
return (enum pt_exec_mode) bce.mode;
}
/* Get the block cache qualifier of a block cache entry. */
static inline enum pt_bcache_qualifier
pt_bce_qualifier(struct pt_bcache_entry bce)
{
return (enum pt_bcache_qualifier) bce.qualifier;
}
/* Check if a block cache entry is valid. */
static inline int pt_bce_is_valid(struct pt_bcache_entry bce)
{
return pt_bce_exec_mode(bce) != ptem_unknown;
}
/* A block cache. */
struct pt_block_cache {
/* The number of cache entries. */
uint32_t nentries;
/* A variable-length array of @nentries entries. */
struct pt_bcache_entry entry[];
};
/* Create a block cache.
*
* @nentries is the number of entries in the cache and should match the size of
* the to-be-cached section in bytes.
*/
extern struct pt_block_cache *pt_bcache_alloc(uint64_t nentries);
/* Destroy a block cache. */
extern void pt_bcache_free(struct pt_block_cache *bcache);
/* Cache a block.
*
* It is expected that all calls for the same @index write the same @bce.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @bcache is NULL.
* Returns -pte_internal if @index is outside of @bcache.
*/
extern int pt_bcache_add(struct pt_block_cache *bcache, uint64_t index,
struct pt_bcache_entry bce);
/* Lookup a cached block.
*
* The returned cache entry need not be valid. The caller is expected to check
* for validity using pt_bce_is_valid(*@bce).
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @bcache or @bce is NULL.
* Returns -pte_internal if @index is outside of @bcache.
*/
extern int pt_bcache_lookup(struct pt_bcache_entry *bce,
const struct pt_block_cache *bcache,
uint64_t index);
#endif /* PT_BLOCK_CACHE_H */

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#ifndef PT_BLOCK_DECODER_H
#define PT_BLOCK_DECODER_H
#include "pt_query_decoder.h"
#include "pt_image.h"
#include "pt_retstack.h"
#include "pt_ild.h"
#include "pt_msec_cache.h"
/* A block decoder.
*
* It decodes Intel(R) Processor Trace into a sequence of instruction blocks
* such that the instructions in each block can be decoded without further need
* of trace.
*/
struct pt_block_decoder {
/* The Intel(R) Processor Trace query decoder. */
struct pt_query_decoder query;
/* The configuration flags.
*
* Those are our flags set by the user. In @query.config.flags, we set
* the flags we need for the query decoder.
*/
struct pt_conf_flags flags;
/* The default image. */
struct pt_image default_image;
/* The image. */
struct pt_image *image;
/* The current cached section. */
struct pt_msec_cache scache;
/* The current address space. */
struct pt_asid asid;
/* The current Intel(R) Processor Trace event. */
struct pt_event event;
/* The call/return stack for ret compression. */
struct pt_retstack retstack;
/* The current instruction.
*
* This is only valid if @process_insn is set.
*/
struct pt_insn insn;
struct pt_insn_ext iext;
/* The start IP of the next block.
*
* If tracing is disabled, this is the IP at which we assume tracing to
* be resumed.
*/
uint64_t ip;
/* The current execution mode. */
enum pt_exec_mode mode;
/* The status of the last successful decoder query.
*
* Errors are reported directly; the status is always a non-negative
* pt_status_flag bit-vector.
*/
int status;
/* A collection of flags defining how to proceed flow reconstruction:
*
* - tracing is enabled.
*/
uint32_t enabled:1;
/* - process @event. */
uint32_t process_event:1;
/* - instructions are executed speculatively. */
uint32_t speculative:1;
/* - process @insn/@iext.
*
* We have started processing events binding to @insn/@iext. The
* instruction has been accounted for in the previous block, but we
* have not yet proceeded past it.
*
* We will do so in pt_blk_event() after processing all events that
* bind to it.
*/
uint32_t process_insn:1;
/* - a paging event has already been bound to @insn/@iext. */
uint32_t bound_paging:1;
/* - a vmcs event has already been bound to @insn/@iext. */
uint32_t bound_vmcs:1;
/* - a ptwrite event has already been bound to @insn/@iext. */
uint32_t bound_ptwrite:1;
};
/* Initialize a block decoder.
*
* Returns zero on success; a negative error code otherwise.
* Returns -pte_internal, if @decoder or @config is NULL.
*/
extern int pt_blk_decoder_init(struct pt_block_decoder *decoder,
const struct pt_config *config);
/* Finalize a block decoder. */
extern void pt_blk_decoder_fini(struct pt_block_decoder *decoder);
#endif /* PT_BLOCK_DECODER_H */

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2015-2018, 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.
*/
#include "intel-pt.h"
/* Read the configuration provided by a library user and zero-initialize
* missing fields.
*
* We keep the user's size value if it is smaller than sizeof(*@config) to
* allow decoders to detect missing configuration bits.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @config is NULL.
* Returns -pte_invalid if @uconfig is NULL.
* Returns -pte_bad_config if @config is too small to be useful.
*/
extern int pt_config_from_user(struct pt_config *config,
const struct pt_config *uconfig);
/* Get the configuration for the n'th address filter.
*
* Returns zero if @filter is NULL or @n is out of bounds.
*
* This corresponds to IA32_RTIT_CTL.ADDRn_CFG.
*/
extern uint32_t pt_filter_addr_cfg(const struct pt_conf_addr_filter *filter,
uint8_t n);
/* Get the lower bound (inclusive) of the n'th address filter.
*
* Returns zero if @filter is NULL or @n is out of bounds.
*
* This corresponds to IA32_RTIT_ADDRn_A.
*/
extern uint64_t pt_filter_addr_a(const struct pt_conf_addr_filter *filter,
uint8_t n);
/* Get the upper bound (inclusive) of the n'th address filter.
*
* Returns zero if @filter is NULL or @n is out of bounds.
*
* This corresponds to IA32_RTIT_ADDRn_B.
*/
extern uint64_t pt_filter_addr_b(const struct pt_conf_addr_filter *filter,
uint8_t n);
/* Check address filters.
*
* Checks @addr against @filter.
*
* Returns a positive number if @addr lies in a tracing-enabled region.
* Returns zero if @addr lies in a tracing-disabled region.
* Returns a negative pt_error_code otherwise.
*/
extern int pt_filter_addr_check(const struct pt_conf_addr_filter *filter,
uint64_t addr);

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_CPU_H
#define PT_CPU_H
struct pt_cpu;
/* Parses @s which should be of format family/model[/stepping] and
* stores the value in @cpu on success.
* The optional stepping defaults to 0 if omitted.
*
* Returns 0 on success.
* Returns -pte_invalid if @cpu or @s is NULL.
* Returns -pte_invalid if @s could not be parsed.
*/
extern int pt_cpu_parse(struct pt_cpu *cpu, const char *s);
/* Get the cpu we're running on.
*
* Reads the family/model/stepping of the processor on which this function
* is executed and stores the value in @cpu.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_invalid if @cpu is NULL.
*/
extern int pt_cpu_read(struct pt_cpu *cpu);
#endif /* PT_CPU_H */

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_CPUID_H
#define PT_CPUID_H
#include <inttypes.h>
/* Execute cpuid with @leaf set in the eax register.
* The result is stored in @eax, @ebx, @ecx and @edx.
*/
extern void pt_cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx);
#endif /* PT_CPUID_H */

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_DECODER_FUNCTION_H
#define PT_DECODER_FUNCTION_H
#include <stdint.h>
struct pt_query_decoder;
struct pt_packet_decoder;
struct pt_packet;
struct pt_config;
/* Intel(R) Processor Trace decoder function flags. */
enum pt_decoder_function_flag {
/* The decoded packet contains an unconditional branch destination. */
pdff_tip = 1 << 0,
/* The decode packet contains unconditional branch destinations. */
pdff_tnt = 1 << 1,
/* The decoded packet contains an event. */
pdff_event = 1 << 2,
/* The decoded packet marks the end of a PSB header. */
pdff_psbend = 1 << 3,
/* The decoded packet contains a non-branch IP update. */
pdff_fup = 1 << 4,
/* The decoded packet is unknown to the decoder. */
pdff_unknown = 1 << 5,
/* The decoded packet contains timing information. */
pdff_timing = 1 << 6,
/* The decoded packet contains padding. */
pdff_pad = 1 << 7
};
/* An Intel(R) Processor Trace decoder function. */
struct pt_decoder_function {
/* The function to analyze the next packet. */
int (*packet)(struct pt_packet_decoder *, struct pt_packet *);
/* The function to decode the next packet. */
int (*decode)(struct pt_query_decoder *);
/* The function to decode the next packet in segment header
* context, i.e. between PSB and ENDPSB.
*/
int (*header)(struct pt_query_decoder *);
/* Decoder function flags. */
int flags;
};
/* Fetch the decoder function.
*
* Sets @dfun to the decoder function for decoding the packet at @pos.
*
* Returns 0 on success.
* Returns -pte_internal if @dfun or @config is NULL.
* Returns -pte_nosync if @pos is NULL or outside @config's trace buffer.
* Returns -pte_eos if the opcode is incomplete or missing.
*/
extern int pt_df_fetch(const struct pt_decoder_function **dfun,
const uint8_t *pos, const struct pt_config *config);
/* Decoder functions for the various packet types.
*
* Do not call those functions directly!
*/
extern const struct pt_decoder_function pt_decode_unknown;
extern const struct pt_decoder_function pt_decode_pad;
extern const struct pt_decoder_function pt_decode_psb;
extern const struct pt_decoder_function pt_decode_tip;
extern const struct pt_decoder_function pt_decode_tnt_8;
extern const struct pt_decoder_function pt_decode_tnt_64;
extern const struct pt_decoder_function pt_decode_tip_pge;
extern const struct pt_decoder_function pt_decode_tip_pgd;
extern const struct pt_decoder_function pt_decode_fup;
extern const struct pt_decoder_function pt_decode_pip;
extern const struct pt_decoder_function pt_decode_ovf;
extern const struct pt_decoder_function pt_decode_mode;
extern const struct pt_decoder_function pt_decode_psbend;
extern const struct pt_decoder_function pt_decode_tsc;
extern const struct pt_decoder_function pt_decode_cbr;
extern const struct pt_decoder_function pt_decode_tma;
extern const struct pt_decoder_function pt_decode_mtc;
extern const struct pt_decoder_function pt_decode_cyc;
extern const struct pt_decoder_function pt_decode_stop;
extern const struct pt_decoder_function pt_decode_vmcs;
extern const struct pt_decoder_function pt_decode_mnt;
extern const struct pt_decoder_function pt_decode_exstop;
extern const struct pt_decoder_function pt_decode_mwait;
extern const struct pt_decoder_function pt_decode_pwre;
extern const struct pt_decoder_function pt_decode_pwrx;
extern const struct pt_decoder_function pt_decode_ptw;
#endif /* PT_DECODER_FUNCTION_H */

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_ENCODER_H
#define PT_ENCODER_H
#include "intel-pt.h"
/* An Intel PT packet encoder. */
struct pt_encoder {
/* The encoder configuration. */
struct pt_config config;
/** The current position in the trace buffer. */
uint8_t *pos;
};
/* Initialize the packet encoder.
*
* Returns zero on success, a negative error code otherwise.
*/
extern int pt_encoder_init(struct pt_encoder *, const struct pt_config *);
/* Finalize the packet encoder. */
extern void pt_encoder_fini(struct pt_encoder *);
/* The below functions are convenience wrappers around pt_enc_next(). */
/* Encode a Padding (pad) packet. */
extern int pt_encode_pad(struct pt_encoder *);
/* Encode a Packet Stream Boundary (psb) packet. */
extern int pt_encode_psb(struct pt_encoder *);
/* Encode an End PSB (psbend) packet. */
extern int pt_encode_psbend(struct pt_encoder *);
/* Encode a Target Instruction Pointer (tip) packet. */
extern int pt_encode_tip(struct pt_encoder *, uint64_t ip,
enum pt_ip_compression ipc);
/* Encode a Taken Not Taken (tnt) packet - 8-bit version. */
extern int pt_encode_tnt_8(struct pt_encoder *, uint8_t tnt, int size);
/* Encode a Taken Not Taken (tnt) packet - 64-bit version. */
extern int pt_encode_tnt_64(struct pt_encoder *, uint64_t tnt, int size);
/* Encode a Packet Generation Enable (tip.pge) packet. */
extern int pt_encode_tip_pge(struct pt_encoder *, uint64_t ip,
enum pt_ip_compression ipc);
/* Encode a Packet Generation Disable (tip.pgd) packet. */
extern int pt_encode_tip_pgd(struct pt_encoder *, uint64_t ip,
enum pt_ip_compression ipc);
/* Encode a Flow Update Packet (fup). */
extern int pt_encode_fup(struct pt_encoder *, uint64_t ip,
enum pt_ip_compression ipc);
/* Encode a Paging Information Packet (pip). */
extern int pt_encode_pip(struct pt_encoder *, uint64_t cr3, uint8_t flags);
/* Encode a Overflow Packet (ovf). */
extern int pt_encode_ovf(struct pt_encoder *);
/* Encode a Mode Exec Packet (mode.exec). */
extern int pt_encode_mode_exec(struct pt_encoder *, enum pt_exec_mode);
/* Encode a Mode Tsx Packet (mode.tsx). */
extern int pt_encode_mode_tsx(struct pt_encoder *, uint8_t);
/* Encode a Time Stamp Counter (tsc) packet. */
extern int pt_encode_tsc(struct pt_encoder *, uint64_t);
/* Encode a Core Bus Ratio (cbr) packet. */
extern int pt_encode_cbr(struct pt_encoder *, uint8_t);
/* Encode a TSC/MTC Alignment (tma) packet. */
extern int pt_encode_tma(struct pt_encoder *, uint16_t ctc,
uint16_t fc);
/* Encode a Mini Time Counter (mtc) packet. */
extern int pt_encode_mtc(struct pt_encoder *, uint8_t ctc);
/* Encode a Cycle Count (cyc) packet. */
extern int pt_encode_cyc(struct pt_encoder *, uint32_t cyc);
/* Encode a TraceStop Packet (stop). */
extern int pt_encode_stop(struct pt_encoder *);
/* Encode a VMCS packet. */
extern int pt_encode_vmcs(struct pt_encoder *, uint64_t);
/* Encode a Maintenance (mnt) packet. */
extern int pt_encode_mnt(struct pt_encoder *, uint64_t);
#endif /* PT_ENCODER_H */

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_EVENT_QUEUE_H
#define PT_EVENT_QUEUE_H
#include "intel-pt.h"
#include <stdint.h>
/* Events are grouped by the packet the event binds to. */
enum pt_event_binding {
evb_psbend,
evb_tip,
evb_fup,
evb_max
};
enum {
/* The maximal number of pending events - should be a power of two. */
evq_max = 8
};
/* A queue of events. */
struct pt_event_queue {
/* A collection of event queues, one per binding. */
struct pt_event queue[evb_max][evq_max];
/* The begin and end indices for the above event queues. */
uint8_t begin[evb_max];
uint8_t end[evb_max];
/* A standalone event to be published immediately. */
struct pt_event standalone;
};
/* Initialize (or reset) an event queue. */
extern void pt_evq_init(struct pt_event_queue *);
/* Get a standalone event.
*
* Returns a pointer to the standalone event on success.
* Returns NULL if @evq is NULL.
*/
extern struct pt_event *pt_evq_standalone(struct pt_event_queue *evq);
/* Enqueue an event.
*
* Adds a new event to @evq for binding @evb.
*
* Returns a pointer to the new event on success.
* Returns NULL if @evq is NULL or @evb is invalid.
* Returns NULL if @evq is full.
*/
extern struct pt_event *pt_evq_enqueue(struct pt_event_queue *evq,
enum pt_event_binding evb);
/* Dequeue an event.
*
* Removes the first event for binding @evb from @evq.
*
* Returns a pointer to the dequeued event on success.
* Returns NULL if @evq is NULL or @evb is invalid.
* Returns NULL if @evq is empty.
*/
extern struct pt_event *pt_evq_dequeue(struct pt_event_queue *evq,
enum pt_event_binding evb);
/* Clear a queue and discard events.
*
* Removes all events for binding @evb from @evq.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @evq is NULL or @evb is invalid.
*/
extern int pt_evq_clear(struct pt_event_queue *evq,
enum pt_event_binding evb);
/* Check for emptiness.
*
* Check if @evq for binding @evb is empty.
*
* Returns a positive number if @evq is empty.
* Returns zero if @evq is not empty.
* Returns -pte_internal if @evq is NULL or @evb is invalid.
*/
extern int pt_evq_empty(const struct pt_event_queue *evq,
enum pt_event_binding evb);
/* Check for non-emptiness.
*
* Check if @evq for binding @evb contains pending events.
*
* Returns a positive number if @evq is not empty.
* Returns zero if @evq is empty.
* Returns -pte_internal if @evq is NULL or @evb is invalid.
*/
extern int pt_evq_pending(const struct pt_event_queue *evq,
enum pt_event_binding evb);
/* Find an event by type.
*
* Searches @evq for binding @evb for an event of type @evt.
*
* Returns a pointer to the first matching event on success.
* Returns NULL if there is no such event.
* Returns NULL if @evq is NULL.
* Returns NULL if @evb or @evt is invalid.
*/
extern struct pt_event *pt_evq_find(struct pt_event_queue *evq,
enum pt_event_binding evb,
enum pt_event_type evt);
#endif /* PT_EVENT_QUEUE_H */

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#if !defined(PT_ILD_H)
#define PT_ILD_H
#include "pt_insn.h"
#include "intel-pt.h"
typedef enum {
PTI_MAP_0, /* 1-byte opcodes. may have modrm */
PTI_MAP_1, /* 2-byte opcodes (0x0f). may have modrm */
PTI_MAP_2, /* 3-byte opcodes (0x0f38). has modrm */
PTI_MAP_3, /* 3-byte opcodes (0x0f3a). has modrm */
PTI_MAP_AMD3DNOW, /* 3d-now opcodes (0x0f0f). has modrm */
PTI_MAP_INVALID
} pti_map_enum_t;
struct pt_ild {
/* inputs */
uint8_t const *itext;
uint8_t max_bytes; /*1..15 bytes */
enum pt_exec_mode mode;
union {
struct {
uint32_t osz:1;
uint32_t asz:1;
uint32_t lock:1;
uint32_t f3:1;
uint32_t f2:1;
uint32_t last_f2f3:2; /* 2 or 3 */
/* The vex bit is set for c4/c5 VEX and EVEX. */
uint32_t vex:1;
/* The REX.R and REX.W bits in REX, VEX, or EVEX. */
uint32_t rex_r:1;
uint32_t rex_w:1;
} s;
uint32_t i;
} u;
uint8_t imm1_bytes; /* # of bytes in 1st immediate */
uint8_t imm2_bytes; /* # of bytes in 2nd immediate */
uint8_t disp_bytes; /* # of displacement bytes */
uint8_t modrm_byte;
/* 5b but valid values= 0,1,2,3 could be in bit union */
uint8_t map;
uint8_t rex; /* 0b0100wrxb */
uint8_t nominal_opcode;
uint8_t disp_pos;
/* imm_pos can be derived from disp_pos + disp_bytes. */
};
static inline pti_map_enum_t pti_get_map(const struct pt_ild *ild)
{
return (pti_map_enum_t) ild->map;
}
static inline uint8_t pti_get_modrm_mod(const struct pt_ild *ild)
{
return ild->modrm_byte >> 6;
}
static inline uint8_t pti_get_modrm_reg(const struct pt_ild *ild)
{
return (ild->modrm_byte >> 3) & 7;
}
static inline uint8_t pti_get_modrm_rm(const struct pt_ild *ild)
{
return ild->modrm_byte & 7;
}
/* MAIN ENTRANCE POINTS */
/* one time call. not thread safe init. call when single threaded. */
extern void pt_ild_init(void);
/* all decoding is multithread safe. */
/* Decode one instruction.
*
* Input:
*
* @insn->ip: the virtual address of the instruction
* @insn->raw: the memory at that virtual address
* @insn->size: the maximal size of the instruction
* @insn->mode: the execution mode
*
* Output:
*
* @insn->size: the actual size of the instruction
* @insn->iclass: a coarse classification
*
* @iext->iclass: a finer grain classification
* @iext->variant: instruction class dependent information
*
* Returns zero on success, a negative error code otherwise.
*/
extern int pt_ild_decode(struct pt_insn *insn, struct pt_insn_ext *iext);
#endif /* PT_ILD_H */

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_IMAGE_H
#define PT_IMAGE_H
#include "pt_mapped_section.h"
#include "intel-pt.h"
#include <stdint.h>
/* A list of sections. */
struct pt_section_list {
/* The next list element. */
struct pt_section_list *next;
/* The mapped section. */
struct pt_mapped_section section;
/* The image section identifier. */
int isid;
};
/* A traced image consisting of a collection of sections. */
struct pt_image {
/* The optional image name. */
char *name;
/* The list of sections. */
struct pt_section_list *sections;
/* An optional read memory callback. */
struct {
/* The callback function. */
read_memory_callback_t *callback;
/* The callback context. */
void *context;
} readmem;
};
/* Initialize an image with an optional @name. */
extern void pt_image_init(struct pt_image *image, const char *name);
/* Finalize an image.
*
* This removes all sections and frees the name.
*/
extern void pt_image_fini(struct pt_image *image);
/* Add a section to an image.
*
* Add @section identified by @isid to @image at @vaddr in @asid. If @section
* overlaps with existing sections, the existing sections are shrunk, split, or
* removed to accomodate @section. Absence of a section identifier is indicated
* by an @isid of zero.
*
* Returns zero on success.
* Returns -pte_internal if @image, @section, or @asid is NULL.
*/
extern int pt_image_add(struct pt_image *image, struct pt_section *section,
const struct pt_asid *asid, uint64_t vaddr, int isid);
/* Remove a section from an image.
*
* Returns zero on success.
* Returns -pte_internal if @image, @section, or @asid is NULL.
* Returns -pte_bad_image if @image does not contain @section at @vaddr.
*/
extern int pt_image_remove(struct pt_image *image, struct pt_section *section,
const struct pt_asid *asid, uint64_t vaddr);
/* Read memory from an image.
*
* Reads at most @size bytes from @image at @addr in @asid into @buffer.
*
* Returns the number of bytes read on success, a negative error code otherwise.
* Returns -pte_internal if @image, @isid, @buffer, or @asid is NULL.
* Returns -pte_nomap if the section does not contain @addr.
*/
extern int pt_image_read(struct pt_image *image, int *isid, uint8_t *buffer,
uint16_t size, const struct pt_asid *asid,
uint64_t addr);
/* Find an image section.
*
* Find the section containing @vaddr in @asid and provide it in @msec. On
* success, takes a reference of @msec->section that the caller needs to put
* after use.
*
* Returns the section's identifier on success, a negative error code otherwise.
* Returns -pte_internal if @image, @msec, or @asid is NULL.
* Returns -pte_nomap if there is no such section in @image.
*/
extern int pt_image_find(struct pt_image *image, struct pt_mapped_section *msec,
const struct pt_asid *asid, uint64_t vaddr);
/* Validate an image section.
*
* Validate that a lookup of @vaddr in @msec->asid in @image would result in
* @msec identified by @isid.
*
* Validation may fail sporadically.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_invalid if @image or @msec is NULL.
* Returns -pte_nomap if validation failed.
*/
extern int pt_image_validate(const struct pt_image *image,
const struct pt_mapped_section *msec,
uint64_t vaddr, int isid);
#endif /* PT_IMAGE_H */

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#ifndef PT_IMAGE_SECTION_CACHE_H
#define PT_IMAGE_SECTION_CACHE_H
#include <stdint.h>
#if defined(FEATURE_THREADS)
# include <threads.h>
#endif /* defined(FEATURE_THREADS) */
struct pt_section;
/* An image section cache entry. */
struct pt_iscache_entry {
/* The section object.
*
* We hold a reference to the section - put it when the section is
* removed from the cache.
*/
struct pt_section *section;
/* The base address at which @section has been loaded. */
uint64_t laddr;
};
/* An image section cache least recently used cache entry. */
struct pt_iscache_lru_entry {
/* The next entry in a list ordered by recent use. */
struct pt_iscache_lru_entry *next;
/* The section mapped by the image section cache. */
struct pt_section *section;
/* The amount of memory used by mapping @section in bytes. */
uint64_t size;
};
/* A cache of image sections and their load addresses.
*
* We combine the section with its load address to reduce the amount of
* information we need to store in order to read from a cached section by
* virtual address.
*
* Internally, the section object will be shared if it is loaded at different
* addresses in the cache.
*
* The cache does not consider the address-space the section is mapped into.
* This is not relevant for reading from the section.
*/
struct pt_image_section_cache {
/* The optional name of the cache; NULL if not named. */
char *name;
/* An array of @nentries cached sections. */
struct pt_iscache_entry *entries;
/* A list of mapped sections ordered by time of last access. */
struct pt_iscache_lru_entry *lru;
/* The memory limit for our LRU cache. */
uint64_t limit;
/* The current size of our LRU cache. */
uint64_t used;
#if defined(FEATURE_THREADS)
/* A lock protecting this image section cache. */
mtx_t lock;
#endif /* defined(FEATURE_THREADS) */
/* The capacity of the @entries array.
*
* Cached sections are identified by a positive integer, the image
* section identifier (isid), which is derived from their index into the
* @entries array.
*
* We can't expand the section cache capacity beyond INT_MAX.
*/
uint16_t capacity;
/* The current size of the cache in number of entries.
*
* This is smaller than @capacity if there is still room in the @entries
* array; equal to @capacity if the @entries array is full and needs to
* be reallocated.
*/
uint16_t size;
};
/* Initialize an image section cache. */
extern int pt_iscache_init(struct pt_image_section_cache *iscache,
const char *name);
/* Finalize an image section cache. */
extern void pt_iscache_fini(struct pt_image_section_cache *iscache);
/* Add a section to the cache.
*
* Adds @section at @laddr to @iscache and returns its isid. If a similar
* section is already cached, returns that section's isid, instead.
*
* We take a full section rather than its filename and range in that file to
* avoid the dependency to pt_section.h. Callers are expected to query the
* cache before creating the section, so we should only see unnecessary section
* creation/destruction on insertion races.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @iscache or @section is NULL.
* Returns -pte_internal if @section's filename is NULL.
*/
extern int pt_iscache_add(struct pt_image_section_cache *iscache,
struct pt_section *section, uint64_t laddr);
/* Find a section in the cache.
*
* Returns a positive isid if a section matching @filename, @offset, @size
* loaded at @laddr is found in @iscache.
* Returns zero if no such section is found.
* Returns a negative error code otherwise.
* Returns -pte_internal if @iscache or @filename is NULL.
*/
extern int pt_iscache_find(struct pt_image_section_cache *iscache,
const char *filename, uint64_t offset,
uint64_t size, uint64_t laddr);
/* Lookup the section identified by its isid.
*
* Provides a reference to the section in @section and its load address in
* @laddr on success. The caller is expected to put the returned section after
* use.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @iscache, @section, or @laddr is NULL.
* Returns -pte_bad_image if @iscache does not contain @isid.
*/
extern int pt_iscache_lookup(struct pt_image_section_cache *iscache,
struct pt_section **section, uint64_t *laddr,
int isid);
/* Clear an image section cache. */
extern int pt_iscache_clear(struct pt_image_section_cache *iscache);
/* Notify about the mapping of a cached section.
*
* Notifies @iscache that @section has been mapped.
*
* The caller guarantees that @iscache contains @section (by using @section's
* iscache pointer) and prevents @iscache from detaching.
*
* The caller must not lock @section to allow @iscache to map it. This function
* must not try to detach from @section.
*
* Returns zero on success, a negative pt_error_code otherwise.
* Returns -pte_internal if @iscache or @section is NULL.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_iscache_notify_map(struct pt_image_section_cache *iscache,
struct pt_section *section);
/* Notify about a size change of a mapped section.
*
* Notifies @iscache that @section's size has changed while it was mapped.
*
* The caller guarantees that @iscache contains @section (by using @section's
* iscache pointer) and prevents @iscache from detaching.
*
* The caller must not lock @section to allow @iscache to map it. This function
* must not try to detach from @section.
*
* Returns zero on success, a negative pt_error_code otherwise.
* Returns -pte_internal if @iscache or @section is NULL.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_iscache_notify_resize(struct pt_image_section_cache *iscache,
struct pt_section *section, uint64_t size);
#endif /* PT_IMAGE_SECTION_CACHE_H */

View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#ifndef PT_INSN_H
#define PT_INSN_H
#include <inttypes.h>
#include "intel-pt.h"
struct pt_insn_ext;
/* A finer-grain classification of instructions used internally. */
typedef enum {
PTI_INST_INVALID,
PTI_INST_CALL_9A,
PTI_INST_CALL_FFr3,
PTI_INST_CALL_FFr2,
PTI_INST_CALL_E8,
PTI_INST_INT,
PTI_INST_INT3,
PTI_INST_INT1,
PTI_INST_INTO,
PTI_INST_IRET, /* includes IRETD and IRETQ (EOSZ determines) */
PTI_INST_JMP_E9,
PTI_INST_JMP_EB,
PTI_INST_JMP_EA,
PTI_INST_JMP_FFr5, /* REXW? */
PTI_INST_JMP_FFr4,
PTI_INST_JCC,
PTI_INST_JrCXZ,
PTI_INST_LOOP,
PTI_INST_LOOPE, /* aka Z */
PTI_INST_LOOPNE, /* aka NE */
PTI_INST_MOV_CR3,
PTI_INST_RET_C3,
PTI_INST_RET_C2,
PTI_INST_RET_CB,
PTI_INST_RET_CA,
PTI_INST_SYSCALL,
PTI_INST_SYSENTER,
PTI_INST_SYSEXIT,
PTI_INST_SYSRET,
PTI_INST_VMLAUNCH,
PTI_INST_VMRESUME,
PTI_INST_VMCALL,
PTI_INST_VMPTRLD,
PTI_INST_PTWRITE,
PTI_INST_LAST
} pti_inst_enum_t;
/* Information about an instruction we need internally in addition to the
* information provided in struct pt_insn.
*/
struct pt_insn_ext {
/* A more detailed instruction class. */
pti_inst_enum_t iclass;
/* Instruction-specific information. */
union {
/* For branch instructions. */
struct {
/* The branch displacement.
*
* This is only valid for direct calls/jumps.
*
* The displacement is applied to the address of the
* instruction following the branch.
*/
int32_t displacement;
/* A flag saying whether the branch is direct.
*
* non-zero: direct
* zero: indirect
*
* This is expected to go away someday when we extend
* enum pt_insn_class to distinguish direct and indirect
* branches.
*/
uint8_t is_direct;
} branch;
} variant;
};
/* Check if the instruction @insn/@iext changes the current privilege level.
*
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
*/
extern int pt_insn_changes_cpl(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Check if the instruction @insn/@iext changes CR3.
*
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
*/
extern int pt_insn_changes_cr3(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Check if the instruction @insn/@iext is a (near or far) branch.
*
* Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL).
*/
extern int pt_insn_is_branch(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Check if the instruction @insn/@iext is a far branch.
*
* Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL).
*/
extern int pt_insn_is_far_branch(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Check if the instruction @insn/@iext binds to a PIP packet.
*
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
*/
extern int pt_insn_binds_to_pip(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Check if the instruction @insn/@iext binds to a VMCS packet.
*
* Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL).
*/
extern int pt_insn_binds_to_vmcs(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Check if the instruction @insn/@iext is a ptwrite instruction.
*
* Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL).
*/
extern int pt_insn_is_ptwrite(const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Determine the IP of the next instruction.
*
* Tries to determine the IP of the next instruction without using trace and
* provides it in @ip unless @ip is NULL.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_bad_query if the IP can't be determined.
* Returns -pte_internal if @insn or @iext is NULL.
*/
extern int pt_insn_next_ip(uint64_t *ip, const struct pt_insn *insn,
const struct pt_insn_ext *iext);
/* Decode and analyze one instruction.
*
* Decodes the instructruction at @insn->ip in @insn->mode into @insn and @iext.
*
* If the instruction can not be decoded using a single memory read in a single
* section, sets @insn->truncated and reads the missing bytes from one or more
* other sections until either the instruction can be decoded or we're sure it
* is invalid.
*
* Returns the size in bytes on success, a negative error code otherwise.
* Returns -pte_bad_insn if the instruction could not be decoded.
*/
extern int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
struct pt_image *image, const struct pt_asid *asid);
/* Determine if a range of instructions is contiguous.
*
* Try to proceed from IP @begin to IP @end in @asid without using trace.
*
* Returns a positive integer if we reach @end from @begin.
* Returns zero if we couldn't reach @end within @nsteps steps.
* Returns a negative error code otherwise.
*/
extern int pt_insn_range_is_contiguous(uint64_t begin, uint64_t end,
enum pt_exec_mode mode,
struct pt_image *image,
const struct pt_asid *asid,
size_t nsteps);
#endif /* PT_INSN_H */

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_INSN_DECODER_H
#define PT_INSN_DECODER_H
#include "pt_query_decoder.h"
#include "pt_image.h"
#include "pt_retstack.h"
#include "pt_ild.h"
#include "pt_msec_cache.h"
#include <inttypes.h>
struct pt_insn_decoder {
/* The Intel(R) Processor Trace query decoder. */
struct pt_query_decoder query;
/* The configuration flags.
*
* Those are our flags set by the user. In @query.config.flags, we set
* the flags we need for the query decoder.
*/
struct pt_conf_flags flags;
/* The default image. */
struct pt_image default_image;
/* The image. */
struct pt_image *image;
/* The current cached section. */
struct pt_msec_cache scache;
/* The current address space. */
struct pt_asid asid;
/* The current Intel(R) Processor Trace event. */
struct pt_event event;
/* The call/return stack for ret compression. */
struct pt_retstack retstack;
/* The current instruction.
*
* This is only valid if @process_insn is set.
*/
struct pt_insn insn;
struct pt_insn_ext iext;
/* The current IP.
*
* If tracing is disabled, this is the IP at which we assume tracing to
* be resumed.
*/
uint64_t ip;
/* The current execution mode. */
enum pt_exec_mode mode;
/* The status of the last successful decoder query.
*
* Errors are reported directly; the status is always a non-negative
* pt_status_flag bit-vector.
*/
int status;
/* A collection of flags defining how to proceed flow reconstruction:
*
* - tracing is enabled.
*/
uint32_t enabled:1;
/* - process @event. */
uint32_t process_event:1;
/* - instructions are executed speculatively. */
uint32_t speculative:1;
/* - process @insn/@iext.
*
* We have started processing events binding to @insn/@iext. We have
* not yet proceeded past it.
*
* We will do so in pt_insn_event() after processing all events that
* bind to it.
*/
uint32_t process_insn:1;
/* - a paging event has already been bound to @insn/@iext. */
uint32_t bound_paging:1;
/* - a vmcs event has already been bound to @insn/@iext. */
uint32_t bound_vmcs:1;
/* - a ptwrite event has already been bound to @insn/@iext. */
uint32_t bound_ptwrite:1;
};
/* Initialize an instruction flow decoder.
*
* Returns zero on success; a negative error code otherwise.
* Returns -pte_internal, if @decoder is NULL.
* Returns -pte_invalid, if @config is NULL.
*/
extern int pt_insn_decoder_init(struct pt_insn_decoder *decoder,
const struct pt_config *config);
/* Finalize an instruction flow decoder. */
extern void pt_insn_decoder_fini(struct pt_insn_decoder *decoder);
#endif /* PT_INSN_DECODER_H */

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_LAST_IP_H
#define PT_LAST_IP_H
#include <stdint.h>
struct pt_packet_ip;
struct pt_config;
/* Keeping track of the last-ip in Intel PT packets. */
struct pt_last_ip {
/* The last IP. */
uint64_t ip;
/* Flags governing the handling of IP updates and queries:
*
* - we have seen an IP update.
*/
uint32_t have_ip:1;
/* - the IP has been suppressed in the last update. */
uint32_t suppressed:1;
};
/* Initialize (or reset) the last-ip. */
extern void pt_last_ip_init(struct pt_last_ip *last_ip);
/* Query the last-ip.
*
* If @ip is not NULL, provides the last-ip in @ip on success.
*
* Returns zero on success.
* Returns -pte_internal if @last_ip is NULL.
* Returns -pte_noip if there is no last-ip.
* Returns -pte_ip_suppressed if the last-ip has been suppressed.
*/
extern int pt_last_ip_query(uint64_t *ip, const struct pt_last_ip *last_ip);
/* Update last-ip.
*
* Updates @last_ip based on @packet and, if non-null, @config.
*
* Returns zero on success.
* Returns -pte_internal if @last_ip or @packet is NULL.
* Returns -pte_bad_packet if @packet appears to be corrupted.
*/
extern int pt_last_ip_update_ip(struct pt_last_ip *last_ip,
const struct pt_packet_ip *packet,
const struct pt_config *config);
#endif /* PT_LAST_IP_H */

View File

@ -0,0 +1,199 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_MAPPED_SECTION_H
#define PT_MAPPED_SECTION_H
#include "intel-pt.h"
#include "pt_section.h"
#include <stdint.h>
/* A section mapped into memory. */
struct pt_mapped_section {
/* The section that is mapped. */
struct pt_section *section;
/* The address space into which the section is mapped. */
struct pt_asid asid;
/* The virtual address at which the section is mapped. */
uint64_t vaddr;
/* The offset into the section.
*
* This is normally zero but when @section is split, @offset is added to
* the section/file offset when accessing @section.
*/
uint64_t offset;
/* The size of the section.
*
* This is normally @section->size but when @section is split, this is
* used to determine the size of the sub-section.
*/
uint64_t size;
};
static inline void pt_msec_init(struct pt_mapped_section *msec,
struct pt_section *section,
const struct pt_asid *asid,
uint64_t vaddr, uint64_t offset, uint64_t size)
{
if (!msec)
return;
msec->section = section;
msec->vaddr = vaddr;
msec->offset = offset;
msec->size = size;
if (asid)
msec->asid = *asid;
else
pt_asid_init(&msec->asid);
}
/* Destroy a mapped section - does not free @msec->section. */
static inline void pt_msec_fini(struct pt_mapped_section *msec)
{
(void) msec;
/* Nothing to do. */
}
/* Return the virtual address of the beginning of the memory region. */
static inline uint64_t pt_msec_begin(const struct pt_mapped_section *msec)
{
if (!msec)
return 0ull;
return msec->vaddr;
}
/* Return the virtual address one byte past the end of the memory region. */
static inline uint64_t pt_msec_end(const struct pt_mapped_section *msec)
{
if (!msec)
return 0ull;
return msec->vaddr + msec->size;
}
/* Return the section/file offset. */
static inline uint64_t pt_msec_offset(const struct pt_mapped_section *msec)
{
if (!msec)
return 0ull;
return msec->offset;
}
/* Return the section size. */
static inline uint64_t pt_msec_size(const struct pt_mapped_section *msec)
{
if (!msec)
return 0ull;
return msec->size;
}
/* Return the underlying section. */
static inline struct pt_section *
pt_msec_section(const struct pt_mapped_section *msec)
{
return msec->section;
}
/* Return an identifier for the address-space the section is mapped into. */
static inline const struct pt_asid *
pt_msec_asid(const struct pt_mapped_section *msec)
{
if (!msec)
return NULL;
return &msec->asid;
}
/* Translate a section/file offset into a virtual address. */
static inline uint64_t pt_msec_map(const struct pt_mapped_section *msec,
uint64_t offset)
{
return (offset - msec->offset) + msec->vaddr;
}
/* Translate a virtual address into a section/file offset. */
static inline uint64_t pt_msec_unmap(const struct pt_mapped_section *msec,
uint64_t vaddr)
{
return (vaddr - msec->vaddr) + msec->offset;
}
/* Read memory from a mapped section.
*
* The caller must check @msec->asid.
* The caller must ensure that @msec->section is mapped.
*
* Returns the number of bytes read on success.
* Returns a negative error code otherwise.
*/
static inline int pt_msec_read(const struct pt_mapped_section *msec,
uint8_t *buffer, uint16_t size,
uint64_t vaddr)
{
struct pt_section *section;
uint64_t begin, end, mbegin, mend, offset;
if (!msec)
return -pte_internal;
begin = vaddr;
end = begin + size;
if (end < begin)
end = UINT64_MAX;
mbegin = pt_msec_begin(msec);
mend = pt_msec_end(msec);
if (begin < mbegin || mend <= begin)
return -pte_nomap;
if (mend < end)
end = mend;
size = (uint16_t) (end - begin);
section = pt_msec_section(msec);
offset = pt_msec_unmap(msec, begin);
return pt_section_read(section, buffer, size, offset);
}
#endif /* PT_MAPPED_SECTION_H */

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2017-2018, 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.
*/
#ifndef PT_MSEC_CACHE_H
#define PT_MSEC_CACHE_H
#include "pt_mapped_section.h"
#include "intel-pt.h"
/* A single-entry mapped section cache.
*
* The cached section is implicitly mapped and unmapped. The cache is not
* thread-safe.
*/
struct pt_msec_cache {
/* The cached section.
*
* The cache is valid if and only if @msec.section is not NULL.
*
* It needs to be unmapped and put. Use pt_blk_scache_invalidate() to
* release the cached section and to invalidate the cache.
*/
struct pt_mapped_section msec;
/* The section identifier. */
int isid;
};
/* Initialize the cache. */
extern int pt_msec_cache_init(struct pt_msec_cache *cache);
/* Finalize the cache. */
extern void pt_msec_cache_fini(struct pt_msec_cache *cache);
/* Invalidate the cache. */
extern int pt_msec_cache_invalidate(struct pt_msec_cache *cache);
/* Read the cached section.
*
* If @cache is not empty and @image would find it when looking up @vaddr in
* @*pmsec->asid, provide a pointer to the cached section in @pmsec and return
* its image section identifier.
*
* The provided pointer remains valid until @cache is invalidated.
*
* Returns @*pmsec's isid on success, a negative pt_error_code otherwise.
*/
extern int pt_msec_cache_read(struct pt_msec_cache *cache,
const struct pt_mapped_section **pmsec,
struct pt_image *image, uint64_t vaddr);
/* Fill the cache.
*
* Look up @vaddr in @asid in @image and cache as well as provide the found
* section in @pmsec and return its image section identifier.
*
* Invalidates @cache.
*
* The provided pointer remains valid until @cache is invalidated.
*
* Returns @*pmsec's isid on success, a negative pt_error_code otherwise.
*/
extern int pt_msec_cache_fill(struct pt_msec_cache *cache,
const struct pt_mapped_section **pmsec,
struct pt_image *image,
const struct pt_asid *asid, uint64_t vaddr);
#endif /* PT_MSEC_CACHE_H */

View File

@ -0,0 +1,397 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_OPCODES_H
#define PT_OPCODES_H
/* A one byte opcode. */
enum pt_opcode {
pt_opc_pad = 0x00,
pt_opc_ext = 0x02,
pt_opc_psb = pt_opc_ext,
pt_opc_tip = 0x0d,
pt_opc_tnt_8 = 0x00,
pt_opc_tip_pge = 0x11,
pt_opc_tip_pgd = 0x01,
pt_opc_fup = 0x1d,
pt_opc_mode = 0x99,
pt_opc_tsc = 0x19,
pt_opc_mtc = 0x59,
pt_opc_cyc = 0x03,
/* A free opcode to trigger a decode fault. */
pt_opc_bad = 0xd9
};
/* A one byte extension code for ext opcodes. */
enum pt_ext_code {
pt_ext_psb = 0x82,
pt_ext_tnt_64 = 0xa3,
pt_ext_pip = 0x43,
pt_ext_ovf = 0xf3,
pt_ext_psbend = 0x23,
pt_ext_cbr = 0x03,
pt_ext_tma = 0x73,
pt_ext_stop = 0x83,
pt_ext_vmcs = 0xc8,
pt_ext_ext2 = 0xc3,
pt_ext_exstop = 0x62,
pt_ext_exstop_ip = 0xe2,
pt_ext_mwait = 0xc2,
pt_ext_pwre = 0x22,
pt_ext_pwrx = 0xa2,
pt_ext_ptw = 0x12,
pt_ext_bad = 0x04
};
/* A one byte extension 2 code for ext2 extension opcodes. */
enum pt_ext2_code {
pt_ext2_mnt = 0x88,
pt_ext2_bad = 0x00
};
/* A one byte opcode mask. */
enum pt_opcode_mask {
pt_opm_tip = 0x1f,
pt_opm_tnt_8 = 0x01,
pt_opm_tnt_8_shr = 1,
pt_opm_fup = pt_opm_tip,
/* The bit mask for the compression bits in the opcode. */
pt_opm_ipc = 0xe0,
/* The shift right value for ipc bits. */
pt_opm_ipc_shr = 5,
/* The bit mask for the compression bits after shifting. */
pt_opm_ipc_shr_mask = 0x7,
/* Shift counts and masks for decoding the cyc packet. */
pt_opm_cyc = 0x03,
pt_opm_cyc_ext = 0x04,
pt_opm_cyc_bits = 0xf8,
pt_opm_cyc_shr = 3,
pt_opm_cycx_ext = 0x01,
pt_opm_cycx_shr = 1,
/* The bit mask for the IP bit in the exstop packet. */
pt_opm_exstop_ip = 0x80,
/* The PTW opcode. */
pt_opm_ptw = 0x1f,
/* The bit mask for the IP bit in the ptw packet. */
pt_opm_ptw_ip = 0x80,
/* The bit mask and shr value for the payload bytes field in ptw. */
pt_opm_ptw_pb = 0x60,
pt_opm_ptw_pb_shr = 5,
/* The bit mask for the payload bytes field in ptw after shifting. */
pt_opm_ptw_pb_shr_mask = 0x3
};
/* The size of the various opcodes in bytes. */
enum pt_opcode_size {
pt_opcs_pad = 1,
pt_opcs_tip = 1,
pt_opcs_tip_pge = 1,
pt_opcs_tip_pgd = 1,
pt_opcs_fup = 1,
pt_opcs_tnt_8 = 1,
pt_opcs_mode = 1,
pt_opcs_tsc = 1,
pt_opcs_mtc = 1,
pt_opcs_cyc = 1,
pt_opcs_psb = 2,
pt_opcs_psbend = 2,
pt_opcs_ovf = 2,
pt_opcs_pip = 2,
pt_opcs_tnt_64 = 2,
pt_opcs_cbr = 2,
pt_opcs_tma = 2,
pt_opcs_stop = 2,
pt_opcs_vmcs = 2,
pt_opcs_mnt = 3,
pt_opcs_exstop = 2,
pt_opcs_mwait = 2,
pt_opcs_pwre = 2,
pt_opcs_pwrx = 2,
pt_opcs_ptw = 2
};
/* The psb magic payload.
*
* The payload is a repeating 2-byte pattern.
*/
enum pt_psb_pattern {
/* The high and low bytes in the pattern. */
pt_psb_hi = pt_opc_psb,
pt_psb_lo = pt_ext_psb,
/* Various combinations of the above parts. */
pt_psb_lohi = pt_psb_lo | pt_psb_hi << 8,
pt_psb_hilo = pt_psb_hi | pt_psb_lo << 8,
/* The repeat count of the payload, not including opc and ext. */
pt_psb_repeat_count = 7,
/* The size of the repeated pattern in bytes. */
pt_psb_repeat_size = 2
};
/* The payload details. */
enum pt_payload {
/* The shift counts for post-processing the PIP payload. */
pt_pl_pip_shr = 1,
pt_pl_pip_shl = 5,
/* The size of a PIP payload in bytes. */
pt_pl_pip_size = 6,
/* The non-root bit in the first byte of the PIP payload. */
pt_pl_pip_nr = 0x01,
/* The size of a 8bit TNT packet's payload in bits. */
pt_pl_tnt_8_bits = 8 - pt_opm_tnt_8_shr,
/* The size of a 64bit TNT packet's payload in bytes. */
pt_pl_tnt_64_size = 6,
/* The size of a 64bit TNT packet's payload in bits. */
pt_pl_tnt_64_bits = 48,
/* The size of a TSC packet's payload in bytes and in bits. */
pt_pl_tsc_size = 7,
pt_pl_tsc_bit_size = pt_pl_tsc_size * 8,
/* The size of a CBR packet's payload in bytes. */
pt_pl_cbr_size = 2,
/* The size of a PSB packet's payload in bytes. */
pt_pl_psb_size = pt_psb_repeat_count * pt_psb_repeat_size,
/* The size of a MODE packet's payload in bytes. */
pt_pl_mode_size = 1,
/* The size of an IP packet's payload with update-16 compression. */
pt_pl_ip_upd16_size = 2,
/* The size of an IP packet's payload with update-32 compression. */
pt_pl_ip_upd32_size = 4,
/* The size of an IP packet's payload with update-48 compression. */
pt_pl_ip_upd48_size = 6,
/* The size of an IP packet's payload with sext-48 compression. */
pt_pl_ip_sext48_size = 6,
/* The size of an IP packet's payload with full-ip compression. */
pt_pl_ip_full_size = 8,
/* Byte locations, sizes, and masks for processing TMA packets. */
pt_pl_tma_size = 5,
pt_pl_tma_ctc_size = 2,
pt_pl_tma_ctc_bit_size = pt_pl_tma_ctc_size * 8,
pt_pl_tma_ctc_0 = 2,
pt_pl_tma_ctc_1 = 3,
pt_pl_tma_ctc_mask = (1 << pt_pl_tma_ctc_bit_size) - 1,
pt_pl_tma_fc_size = 2,
pt_pl_tma_fc_bit_size = 9,
pt_pl_tma_fc_0 = 5,
pt_pl_tma_fc_1 = 6,
pt_pl_tma_fc_mask = (1 << pt_pl_tma_fc_bit_size) - 1,
/* The size of a MTC packet's payload in bytes and in bits. */
pt_pl_mtc_size = 1,
pt_pl_mtc_bit_size = pt_pl_mtc_size * 8,
/* A mask for the MTC payload bits. */
pt_pl_mtc_mask = (1 << pt_pl_mtc_bit_size) - 1,
/* The maximal payload size in bytes of a CYC packet. */
pt_pl_cyc_max_size = 15,
/* The size of a VMCS packet's payload in bytes. */
pt_pl_vmcs_size = 5,
/* The shift counts for post-processing the VMCS payload. */
pt_pl_vmcs_shl = 12,
/* The size of a MNT packet's payload in bytes. */
pt_pl_mnt_size = 8,
/* The bit-mask for the IP bit in the EXSTOP opcode extension. */
pt_pl_exstop_ip_mask = 0x80,
/* The size of the hints field in the MWAIT payload in bytes. */
pt_pl_mwait_hints_size = 4,
/* The size of the extensions field in the MWAIT payload in bytes. */
pt_pl_mwait_ext_size = 4,
/* The size of the MWAIT payload in bytes. */
pt_pl_mwait_size = pt_pl_mwait_hints_size + pt_pl_mwait_ext_size,
/* The size of the PWRE payload in bytes. */
pt_pl_pwre_size = 2,
/* The bit-mask for the h/w bit in the PWRE payload. */
pt_pl_pwre_hw_mask = 0x8,
/* The bit-mask for the resolved thread sub C-state in the PWRE
* payload.
*/
pt_pl_pwre_sub_state_mask = 0xf00,
/* The shift right value for the resolved thread sub C-state in the
* PWRE payload.
*/
pt_pl_pwre_sub_state_shr = 8,
/* The bit-mask for the resolved thread C-state in the PWRE payload. */
pt_pl_pwre_state_mask = 0xf000,
/* The shift right value for the resolved thread C-state in the
* PWRE payload.
*/
pt_pl_pwre_state_shr = 12,
/* The size of the PWRX payload in bytes. */
pt_pl_pwrx_size = 5,
/* The bit-mask for the deepest core C-state in the PWRX payload. */
pt_pl_pwrx_deepest_mask = 0xf,
/* The shift right value for the deepest core C-state in the PWRX
* payload.
*/
pt_pl_pwrx_deepest_shr = 0,
/* The bit-mask for the last core C-state in the PWRX payload. */
pt_pl_pwrx_last_mask = 0xf0,
/* The shift right value for the last core C-state in the PWRX
* payload.
*/
pt_pl_pwrx_last_shr = 4,
/* The bit-mask for the wake reason in the PWRX payload. */
pt_pl_pwrx_wr_mask = 0xf00,
/* The shift right value for the wake reason in the PWRX payload. */
pt_pl_pwrx_wr_shr = 8,
/* The bit-mask for the interrupt wake reason in the PWRX payload. */
pt_pl_pwrx_wr_int = 0x100,
/* The bit-mask for the store wake reason in the PWRX payload. */
pt_pl_pwrx_wr_store = 0x400,
/* The bit-mask for the autonomous wake reason in the PWRX payload. */
pt_pl_pwrx_wr_hw = 0x800
};
/* Mode packet masks. */
enum pt_mode_mask {
pt_mom_leaf = 0xe0,
pt_mom_leaf_shr = 5,
pt_mom_bits = 0x1f
};
/* Mode packet bits. */
enum pt_mode_bit {
/* mode.exec */
pt_mob_exec_csl = 0x01,
pt_mob_exec_csd = 0x02,
/* mode.tsx */
pt_mob_tsx_intx = 0x01,
pt_mob_tsx_abrt = 0x02
};
/* The size of the various packets in bytes. */
enum pt_packet_size {
ptps_pad = pt_opcs_pad,
ptps_tnt_8 = pt_opcs_tnt_8,
ptps_mode = pt_opcs_mode + pt_pl_mode_size,
ptps_tsc = pt_opcs_tsc + pt_pl_tsc_size,
ptps_mtc = pt_opcs_mtc + pt_pl_mtc_size,
ptps_psb = pt_opcs_psb + pt_pl_psb_size,
ptps_psbend = pt_opcs_psbend,
ptps_ovf = pt_opcs_ovf,
ptps_pip = pt_opcs_pip + pt_pl_pip_size,
ptps_tnt_64 = pt_opcs_tnt_64 + pt_pl_tnt_64_size,
ptps_cbr = pt_opcs_cbr + pt_pl_cbr_size,
ptps_tip_supp = pt_opcs_tip,
ptps_tip_upd16 = pt_opcs_tip + pt_pl_ip_upd16_size,
ptps_tip_upd32 = pt_opcs_tip + pt_pl_ip_upd32_size,
ptps_tip_upd48 = pt_opcs_tip + pt_pl_ip_upd48_size,
ptps_tip_sext48 = pt_opcs_tip + pt_pl_ip_sext48_size,
ptps_tip_full = pt_opcs_tip + pt_pl_ip_full_size,
ptps_tip_pge_supp = pt_opcs_tip_pge,
ptps_tip_pge_upd16 = pt_opcs_tip_pge + pt_pl_ip_upd16_size,
ptps_tip_pge_upd32 = pt_opcs_tip_pge + pt_pl_ip_upd32_size,
ptps_tip_pge_upd48 = pt_opcs_tip_pge + pt_pl_ip_upd48_size,
ptps_tip_pge_sext48 = pt_opcs_tip_pge + pt_pl_ip_sext48_size,
ptps_tip_pge_full = pt_opcs_tip_pge + pt_pl_ip_full_size,
ptps_tip_pgd_supp = pt_opcs_tip_pgd,
ptps_tip_pgd_upd16 = pt_opcs_tip_pgd + pt_pl_ip_upd16_size,
ptps_tip_pgd_upd32 = pt_opcs_tip_pgd + pt_pl_ip_upd32_size,
ptps_tip_pgd_upd48 = pt_opcs_tip_pgd + pt_pl_ip_upd48_size,
ptps_tip_pgd_sext48 = pt_opcs_tip_pgd + pt_pl_ip_sext48_size,
ptps_tip_pgd_full = pt_opcs_tip_pgd + pt_pl_ip_full_size,
ptps_fup_supp = pt_opcs_fup,
ptps_fup_upd16 = pt_opcs_fup + pt_pl_ip_upd16_size,
ptps_fup_upd32 = pt_opcs_fup + pt_pl_ip_upd32_size,
ptps_fup_upd48 = pt_opcs_fup + pt_pl_ip_upd48_size,
ptps_fup_sext48 = pt_opcs_fup + pt_pl_ip_sext48_size,
ptps_fup_full = pt_opcs_fup + pt_pl_ip_full_size,
ptps_tma = pt_opcs_tma + pt_pl_tma_size,
ptps_stop = pt_opcs_stop,
ptps_vmcs = pt_opcs_vmcs + pt_pl_vmcs_size,
ptps_mnt = pt_opcs_mnt + pt_pl_mnt_size,
ptps_exstop = pt_opcs_exstop,
ptps_mwait = pt_opcs_mwait + pt_pl_mwait_size,
ptps_pwre = pt_opcs_pwre + pt_pl_pwre_size,
ptps_pwrx = pt_opcs_pwrx + pt_pl_pwrx_size,
ptps_ptw_32 = pt_opcs_ptw + 4,
ptps_ptw_64 = pt_opcs_ptw + 8
};
/* Supported address range configurations. */
enum pt_addr_cfg {
pt_addr_cfg_disabled = 0,
pt_addr_cfg_filter = 1,
pt_addr_cfg_stop = 2
};
#endif /* PT_OPCODES_H */

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_PACKET_H
#define PT_PACKET_H
#include <stdint.h>
struct pt_config;
struct pt_packet;
struct pt_packet_ip;
struct pt_packet_tnt;
struct pt_packet_pip;
struct pt_packet_mode;
struct pt_packet_tsc;
struct pt_packet_cbr;
struct pt_packet_tma;
struct pt_packet_mtc;
struct pt_packet_cyc;
struct pt_packet_vmcs;
struct pt_packet_mnt;
struct pt_packet_exstop;
struct pt_packet_mwait;
struct pt_packet_pwre;
struct pt_packet_pwrx;
struct pt_packet_ptw;
/* Read the payload of an Intel PT packet.
*
* Reads the payload of the packet starting at @pos into @packet.
*
* For pt_pkt_read_psb(), the @packet parameter is omitted; the function
* validates that the payload matches the expected PSB pattern.
*
* Decoding an unknown packet uses @config's decode callback. If the callback
* is NULL, pt_pkt_read_unknown() returns -pte_bad_opc.
*
* Beware that the packet opcode is not checked. The caller is responsible
* for checking the opcode and calling the correct packet read function.
*
* Returns the packet size on success, a negative error code otherwise.
* Returns -pte_bad_packet if the packet payload is corrupt.
* Returns -pte_eos if the packet does not fit into the trace buffer.
* Returns -pte_internal if @packet, @pos, or @config is NULL.
*/
extern int pt_pkt_read_unknown(struct pt_packet *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_psb(const uint8_t *pos, const struct pt_config *config);
extern int pt_pkt_read_ip(struct pt_packet_ip *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_tnt_8(struct pt_packet_tnt *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_tnt_64(struct pt_packet_tnt *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_pip(struct pt_packet_pip *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_mode(struct pt_packet_mode *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_tsc(struct pt_packet_tsc *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_cbr(struct pt_packet_cbr *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_tma(struct pt_packet_tma *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_mtc(struct pt_packet_mtc *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_cyc(struct pt_packet_cyc *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_vmcs(struct pt_packet_vmcs *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_mnt(struct pt_packet_mnt *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_exstop(struct pt_packet_exstop *packet,
const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_mwait(struct pt_packet_mwait *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_pwre(struct pt_packet_pwre *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_pwrx(struct pt_packet_pwrx *packet, const uint8_t *pos,
const struct pt_config *config);
extern int pt_pkt_read_ptw(struct pt_packet_ptw *packet, const uint8_t *pos,
const struct pt_config *config);
#endif /* PT_PACKET_H */

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_PACKET_DECODER_H
#define PT_PACKET_DECODER_H
#include "intel-pt.h"
/* An Intel PT packet decoder. */
struct pt_packet_decoder {
/* The decoder configuration. */
struct pt_config config;
/* The current position in the trace buffer. */
const uint8_t *pos;
/* The position of the last PSB packet. */
const uint8_t *sync;
};
/* Initialize the packet decoder.
*
* Returns zero on success, a negative error code otherwise.
*/
extern int pt_pkt_decoder_init(struct pt_packet_decoder *,
const struct pt_config *);
/* Finalize the packet decoder. */
extern void pt_pkt_decoder_fini(struct pt_packet_decoder *);
/* Decoder functions for the packet decoder. */
extern int pt_pkt_decode_unknown(struct pt_packet_decoder *,
struct pt_packet *);
extern int pt_pkt_decode_pad(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_psb(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_tip(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_tnt_8(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_tnt_64(struct pt_packet_decoder *,
struct pt_packet *);
extern int pt_pkt_decode_tip_pge(struct pt_packet_decoder *,
struct pt_packet *);
extern int pt_pkt_decode_tip_pgd(struct pt_packet_decoder *,
struct pt_packet *);
extern int pt_pkt_decode_fup(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_pip(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_ovf(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_mode(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_psbend(struct pt_packet_decoder *,
struct pt_packet *);
extern int pt_pkt_decode_tsc(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_cbr(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_tma(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_mtc(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_cyc(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_stop(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_vmcs(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_mnt(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_exstop(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_mwait(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_pwre(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_pwrx(struct pt_packet_decoder *, struct pt_packet *);
extern int pt_pkt_decode_ptw(struct pt_packet_decoder *, struct pt_packet *);
#endif /* PT_PACKET_DECODER_H */

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_QUERY_DECODER_H
#define PT_QUERY_DECODER_H
#include "pt_last_ip.h"
#include "pt_tnt_cache.h"
#include "pt_time.h"
#include "pt_event_queue.h"
#include "intel-pt.h"
struct pt_decoder_function;
/* An Intel PT query decoder. */
struct pt_query_decoder {
/* The decoder configuration. */
struct pt_config config;
/* The current position in the trace buffer. */
const uint8_t *pos;
/* The position of the last PSB packet. */
const uint8_t *sync;
/* The decoding function for the next packet. */
const struct pt_decoder_function *next;
/* The last-ip. */
struct pt_last_ip ip;
/* The cached tnt indicators. */
struct pt_tnt_cache tnt;
/* Timing information. */
struct pt_time time;
/* The time at the last query (before reading ahead). */
struct pt_time last_time;
/* Timing calibration. */
struct pt_time_cal tcal;
/* Pending (incomplete) events. */
struct pt_event_queue evq;
/* The current event. */
struct pt_event *event;
/* A collection of flags relevant for decoding:
*
* - tracing is enabled.
*/
uint32_t enabled:1;
/* - consume the current packet. */
uint32_t consume_packet:1;
};
/* Initialize the query decoder.
*
* Returns zero on success, a negative error code otherwise.
*/
extern int pt_qry_decoder_init(struct pt_query_decoder *,
const struct pt_config *);
/* Finalize the query decoder. */
extern void pt_qry_decoder_fini(struct pt_query_decoder *);
/* Decoder functions (tracing context). */
extern int pt_qry_decode_unknown(struct pt_query_decoder *);
extern int pt_qry_decode_pad(struct pt_query_decoder *);
extern int pt_qry_decode_psb(struct pt_query_decoder *);
extern int pt_qry_decode_tip(struct pt_query_decoder *);
extern int pt_qry_decode_tnt_8(struct pt_query_decoder *);
extern int pt_qry_decode_tnt_64(struct pt_query_decoder *);
extern int pt_qry_decode_tip_pge(struct pt_query_decoder *);
extern int pt_qry_decode_tip_pgd(struct pt_query_decoder *);
extern int pt_qry_decode_fup(struct pt_query_decoder *);
extern int pt_qry_decode_pip(struct pt_query_decoder *);
extern int pt_qry_decode_ovf(struct pt_query_decoder *);
extern int pt_qry_decode_mode(struct pt_query_decoder *);
extern int pt_qry_decode_psbend(struct pt_query_decoder *);
extern int pt_qry_decode_tsc(struct pt_query_decoder *);
extern int pt_qry_header_tsc(struct pt_query_decoder *);
extern int pt_qry_decode_cbr(struct pt_query_decoder *);
extern int pt_qry_header_cbr(struct pt_query_decoder *);
extern int pt_qry_decode_tma(struct pt_query_decoder *);
extern int pt_qry_decode_mtc(struct pt_query_decoder *);
extern int pt_qry_decode_cyc(struct pt_query_decoder *);
extern int pt_qry_decode_stop(struct pt_query_decoder *);
extern int pt_qry_decode_vmcs(struct pt_query_decoder *);
extern int pt_qry_decode_mnt(struct pt_query_decoder *);
extern int pt_qry_decode_exstop(struct pt_query_decoder *);
extern int pt_qry_decode_mwait(struct pt_query_decoder *);
extern int pt_qry_decode_pwre(struct pt_query_decoder *);
extern int pt_qry_decode_pwrx(struct pt_query_decoder *);
extern int pt_qry_decode_ptw(struct pt_query_decoder *);
/* Decoder functions (header context). */
extern int pt_qry_header_fup(struct pt_query_decoder *);
extern int pt_qry_header_pip(struct pt_query_decoder *);
extern int pt_qry_header_mode(struct pt_query_decoder *);
extern int pt_qry_header_vmcs(struct pt_query_decoder *);
extern int pt_qry_header_mnt(struct pt_query_decoder *);
#endif /* PT_QUERY_DECODER_H */

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_RETSTACK_H
#define PT_RETSTACK_H
#include <stdint.h>
/* The size of the call/return stack in number of entries. */
enum {
pt_retstack_size = 64
};
/* A stack of return addresses used for return compression. */
struct pt_retstack {
/* The stack of return addresses.
*
* We use one additional entry in order to distinguish a full from
* an empty stack.
*/
uint64_t stack[pt_retstack_size + 1];
/* The top of the stack. */
uint8_t top;
/* The bottom of the stack. */
uint8_t bottom;
};
/* Initialize (or reset) a call/return stack. */
extern void pt_retstack_init(struct pt_retstack *);
/* Test a call/return stack for emptiness.
*
* Returns zero if @retstack contains at least one element.
* Returns a positive integer if @retstack is empty.
* Returns -pte_invalid if @retstack is NULL.
*/
extern int pt_retstack_is_empty(const struct pt_retstack *retstack);
/* Pop and return the topmost IP.
*
* If @ip is not NULL, provides the topmost return address on success.
* If @retstack is not empty, pops the topmost return address on success.
*
* Returns zero on success.
* Returns -pte_invalid if @retstack is NULL.
* Returns -pte_noip if @retstack is empty.
*/
extern int pt_retstack_pop(struct pt_retstack *retstack, uint64_t *ip);
/* Push a return address onto the stack.
*
* Pushes @ip onto @retstack.
* If @retstack is full, drops the oldest return address.
*
* Returns zero on success.
*/
extern int pt_retstack_push(struct pt_retstack *retstack, uint64_t ip);
#endif /* PT_RETSTACK_H */

View File

@ -0,0 +1,392 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_SECTION_H
#define PT_SECTION_H
#include <stdint.h>
#include <stddef.h>
#if defined(FEATURE_THREADS)
# include <threads.h>
#endif /* defined(FEATURE_THREADS) */
#include "intel-pt.h"
struct pt_block_cache;
/* A section of contiguous memory loaded from a file. */
struct pt_section {
/* The name of the file. */
char *filename;
/* The offset into the file. */
uint64_t offset;
/* The (adjusted) size in bytes. The size is truncated to match the
* actual file size.
*/
uint64_t size;
/* A pointer to OS-specific file status for detecting changes.
*
* The status is initialized on first pt_section_map() and will be
* left in the section until the section is destroyed. This field
* is owned by the OS-specific mmap-based section implementation.
*/
void *status;
/* A pointer to implementation-specific mapping information - NULL if
* the section is currently not mapped.
*
* This field is set in pt_section_map() and owned by the mapping
* implementation.
*/
void *mapping;
/* A pointer to an optional block cache.
*
* The cache is created on request and destroyed implicitly when the
* section is unmapped.
*
* We read this field without locking and only lock the section in order
* to install the block cache.
*
* We rely on guaranteed atomic operations as specified in section 8.1.1
* in Volume 3A of the Intel(R) Software Developer's Manual at
* http://www.intel.com/sdm.
*/
struct pt_block_cache *bcache;
/* A pointer to the iscache attached to this section.
*
* The pointer is initialized when the iscache attaches and cleared when
* it detaches again. There can be at most one iscache attached to this
* section at any time.
*
* In addition to attaching, the iscache will need to obtain a reference
* to the section, which it needs to drop again after detaching.
*/
struct pt_image_section_cache *iscache;
/* A pointer to the unmap function - NULL if the section is currently
* not mapped.
*
* This field is set in pt_section_map() and owned by the mapping
* implementation.
*/
int (*unmap)(struct pt_section *sec);
/* A pointer to the read function - NULL if the section is currently
* not mapped.
*
* This field is set in pt_section_map() and owned by the mapping
* implementation.
*/
int (*read)(const struct pt_section *sec, uint8_t *buffer,
uint16_t size, uint64_t offset);
/* A pointer to the memsize function - NULL if the section is currently
* not mapped.
*
* This field is set in pt_section_map() and owned by the mapping
* implementation.
*/
int (*memsize)(const struct pt_section *section, uint64_t *size);
#if defined(FEATURE_THREADS)
/* A lock protecting this section.
*
* Most operations do not require the section to be locked. All
* actual locking should be handled by pt_section_* functions.
*/
mtx_t lock;
/* A lock protecting the @iscache and @acount fields.
*
* We need separate locks to protect against a deadlock scenario when
* the iscache is mapping or unmapping this section.
*
* The attach lock must not be taken while holding the section lock; the
* other way round is OK.
*/
mtx_t alock;
#endif /* defined(FEATURE_THREADS) */
/* The number of current users. The last user destroys the section. */
uint16_t ucount;
/* The number of attaches. This must be <= @ucount. */
uint16_t acount;
/* The number of current mappers. The last unmaps the section. */
uint16_t mcount;
};
/* Create a section.
*
* The returned section describes the contents of @file starting at @offset
* for @size bytes.
*
* If @file is shorter than the requested @size, the section is silently
* truncated to the size of @file.
*
* If @offset lies beyond the end of @file, no section is created.
*
* The returned section is not mapped and starts with a user count of one and
* instruction caching enabled.
*
* Returns a new section on success, NULL otherwise.
*/
extern struct pt_section *pt_mk_section(const char *file, uint64_t offset,
uint64_t size);
/* Lock a section.
*
* Locks @section. The section must not be locked.
*
* Returns a new section on success, NULL otherwise.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_lock(struct pt_section *section);
/* Unlock a section.
*
* Unlocks @section. The section must be locked.
*
* Returns a new section on success, NULL otherwise.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_unlock(struct pt_section *section);
/* Add another user.
*
* Increments the user count of @section.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_overflow if the user count would overflow.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_get(struct pt_section *section);
/* Remove a user.
*
* Decrements the user count of @section. Destroys the section if the
* count reaches zero.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_internal if the user count is already zero.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_put(struct pt_section *section);
/* Attaches the image section cache user.
*
* Similar to pt_section_get() but sets @section->iscache to @iscache.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @iscache is NULL.
* Returns -pte_internal if a different cache is already attached.
* Returns -pte_overflow if the attach count would overflow.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_attach(struct pt_section *section,
struct pt_image_section_cache *iscache);
/* Detaches the image section cache user.
*
* Similar to pt_section_put() but clears @section->iscache.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @iscache is NULL.
* Returns -pte_internal if the attach count is already zero.
* Returns -pte_internal if @section->iscache is not equal to @iscache.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_detach(struct pt_section *section,
struct pt_image_section_cache *iscache);
/* Return the filename of @section. */
extern const char *pt_section_filename(const struct pt_section *section);
/* Return the offset of the section in bytes. */
extern uint64_t pt_section_offset(const struct pt_section *section);
/* Return the size of the section in bytes. */
extern uint64_t pt_section_size(const struct pt_section *section);
/* Return the amount of memory currently used by the section in bytes.
*
* We only consider the amount of memory required for mapping @section; we
* ignore the size of the section object itself and the size of the status
* object.
*
* If @section is currently not mapped, the size is zero.
*
* Returns zero on success, a negative pt_error_code otherwise.
* Returns -pte_internal if @size of @section is NULL.
*/
extern int pt_section_memsize(struct pt_section *section, uint64_t *size);
/* Allocate a block cache.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_nomem if the block cache can't be allocated.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_alloc_bcache(struct pt_section *section);
/* Request block caching.
*
* The caller must ensure that @section is mapped.
*/
static inline int pt_section_request_bcache(struct pt_section *section)
{
if (!section)
return -pte_internal;
if (section->bcache)
return 0;
return pt_section_alloc_bcache(section);
}
/* Return @section's block cache, if available.
*
* The caller must ensure that @section is mapped.
*
* The cache is not use-counted. It is only valid as long as the caller keeps
* @section mapped.
*/
static inline struct pt_block_cache *
pt_section_bcache(const struct pt_section *section)
{
if (!section)
return NULL;
return section->bcache;
}
/* Create the OS-specific file status.
*
* On success, allocates a status object, provides a pointer to it in @pstatus
* and provides the file size in @psize.
*
* The status object will be free()'ed when its section is.
*
* This function is implemented in the OS-specific section implementation.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @pstatus, @psize, or @filename is NULL.
* Returns -pte_bad_image if @filename can't be opened.
* Returns -pte_nomem if the status object can't be allocated.
*/
extern int pt_section_mk_status(void **pstatus, uint64_t *psize,
const char *filename);
/* Perform on-map maintenance work.
*
* Notifies an attached image section cache about the mapping of @section.
*
* This function is called by the OS-specific pt_section_map() implementation
* after @section has been successfully mapped and @section has been unlocked.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_on_map_lock(struct pt_section *section);
static inline int pt_section_on_map(struct pt_section *section)
{
if (section && !section->iscache)
return 0;
return pt_section_on_map_lock(section);
}
/* Map a section.
*
* Maps @section into memory. Mappings are use-counted. The number of
* pt_section_map() calls must match the number of pt_section_unmap()
* calls.
*
* This function is implemented in the OS-specific section implementation.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_bad_image if @section changed or can't be opened.
* Returns -pte_bad_lock on any locking error.
* Returns -pte_nomem if @section can't be mapped into memory.
* Returns -pte_overflow if the map count would overflow.
*/
extern int pt_section_map(struct pt_section *section);
/* Share a section mapping.
*
* Increases the map count for @section without notifying an attached image
* section cache.
*
* This function should only be used by the attached image section cache to
* resolve a deadlock scenario when mapping a section it intends to cache.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_internal if @section->mcount is zero.
* Returns -pte_bad_lock on any locking error.
*/
extern int pt_section_map_share(struct pt_section *section);
/* Unmap a section.
*
* Unmaps @section from memory.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_bad_lock on any locking error.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_section_unmap(struct pt_section *section);
/* Read memory from a section.
*
* Reads at most @size bytes from @section at @offset into @buffer. @section
* must be mapped.
*
* Returns the number of bytes read on success, a negative error code otherwise.
* Returns -pte_internal if @section or @buffer are NULL.
* Returns -pte_nomap if @offset is beyond the end of the section.
*/
extern int pt_section_read(const struct pt_section *section, uint8_t *buffer,
uint16_t size, uint64_t offset);
#endif /* PT_SECTION_H */

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_SECTION_FILE_H
#define PT_SECTION_FILE_H
#include <stdio.h>
#include <stdint.h>
#if defined(FEATURE_THREADS)
# include <threads.h>
#endif /* defined(FEATURE_THREADS) */
struct pt_section;
/* File-based section mapping information. */
struct pt_sec_file_mapping {
/* The FILE pointer. */
FILE *file;
/* The begin and end of the section as offset into @file. */
long begin, end;
#if defined(FEATURE_THREADS)
/* A lock protecting read access to this file.
*
* Since we need to first set the file position indication before
* we can read, there's a race on the file position.
*/
mtx_t lock;
#endif /* defined(FEATURE_THREADS) */
};
/* Map a section based on file operations.
*
* The caller has already opened the file for reading.
*
* On success, sets @section's mapping, unmap, and read pointers.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @file are NULL.
* Returns -pte_invalid if @section can't be mapped.
*/
extern int pt_sec_file_map(struct pt_section *section, FILE *file);
/* Unmap a section based on file operations.
*
* On success, clears @section's mapping, unmap, and read pointers.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_sec_file_unmap(struct pt_section *section);
/* Read memory from a file based section.
*
* Reads at most @size bytes from @section at @offset into @buffer.
*
* Returns the number of bytes read on success, a negative error code otherwise.
* Returns -pte_invalid if @section or @buffer are NULL.
* Returns -pte_nomap if @offset is beyond the end of the section.
*/
extern int pt_sec_file_read(const struct pt_section *section, uint8_t *buffer,
uint16_t size, uint64_t offset);
/* Compute the memory size of a section based on file operations.
*
* On success, provides the amount of memory used for mapping @section in bytes
* in @size.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @size is NULL.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_sec_file_memsize(const struct pt_section *section,
uint64_t *size);
#endif /* PT_SECTION_FILE_H */

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_SYNC_H
#define PT_SYNC_H
#include <stdint.h>
struct pt_config;
/* Synchronize onto the trace stream.
*
* Search for the next synchronization point in forward or backward direction
* starting at @pos using the trace configuration @config.
*
* On success, stores a pointer to the next synchronization point in @sync.
*
* Returns zero on success, a negative error code otherwise.
*
* Returns -pte_internal if @sync, @pos, or @config is NULL.
* Returns -pte_nosync if @pos lies outside of @config's buffer.
* Returns -pte_eos if no further synchronization point is found.
*/
extern int pt_sync_forward(const uint8_t **sync, const uint8_t *pos,
const struct pt_config *config);
extern int pt_sync_backward(const uint8_t **sync, const uint8_t *pos,
const struct pt_config *config);
/* Manually synchronize onto the trace stream.
*
* Validate that @pos is within the bounds of @config's trace buffer and that
* there is a synchronization point at @pos.
*
* On success, stores @pos in @sync.
*
* Returns zero on success, a negative error code otherwise.
*
* Returns -pte_eos if @pos is outside of @config's trace buffer.
* Returns -pte_internal if @sync, @pos, or @config is NULL.
* Returns -pte_bad_packet if there is no PSB at @pos.
*/
extern int pt_sync_set(const uint8_t **sync, const uint8_t *pos,
const struct pt_config *config);
#endif /* PT_SYNC_H */

View File

@ -0,0 +1,232 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#ifndef PT_TIME_H
#define PT_TIME_H
#include <stdint.h>
struct pt_config;
struct pt_packet_tsc;
struct pt_packet_cbr;
struct pt_packet_tma;
struct pt_packet_mtc;
struct pt_packet_cyc;
/* Intel(R) Processor Trace timing. */
struct pt_time {
/* The estimated Time Stamp Count. */
uint64_t tsc;
/* The base Time Stamp Count (from TSC and MTC). */
uint64_t base;
/* The estimated Fast Counter. */
uint64_t fc;
/* The adjusted last CTC value (from MTC and TMA). */
uint32_t ctc;
/* The adjusted CTC value when @fc was cleared (from MTC and TMA). */
uint32_t ctc_cyc;
/* The number of lost MTC updates. */
uint32_t lost_mtc;
/* The number of lost CYC updates. */
uint32_t lost_cyc;
/* The core:bus ratio. */
uint8_t cbr;
/* A flag saying whether we have seen a TSC packet. */
uint32_t have_tsc:1;
/* A flag saying whether we have seen a CBR packet. */
uint32_t have_cbr:1;
/* A flag saying whether we have seen a TMA packet. */
uint32_t have_tma:1;
/* A flag saying whether we have seen a MTC packet. */
uint32_t have_mtc:1;
};
/* Initialize (or reset) the time. */
extern void pt_time_init(struct pt_time *time);
/* Query the current time.
*
* Provides the estimated Time Stamp Count value in @tsc.
*
* If @lost_mtc is not NULL, provides the number of lost MTC packets.
* If @lost_cyc is not NULL, provides the number of lost CYC packets.
*
* Returns zero on success; a negative error code, otherwise.
* Returns -pte_internal if @tsc or @time is NULL.
* Returns -pte_no_time if there has not been a TSC packet.
*/
extern int pt_time_query_tsc(uint64_t *tsc, uint32_t *lost_mtc,
uint32_t *lost_cyc, const struct pt_time *time);
/* Query the current core:bus ratio.
*
* Provides the core:bus ratio in @cbr.
*
* Returns zero on success; a negative error code, otherwise.
* Returns -pte_internal if @cbr or @time is NULL.
* Returns -pte_no_cbr if there has not been a CBR packet.
*/
extern int pt_time_query_cbr(uint32_t *cbr, const struct pt_time *time);
/* Update the time based on an Intel PT packet.
*
* Returns zero on success.
* Returns a negative error code, otherwise.
*/
extern int pt_time_update_tsc(struct pt_time *, const struct pt_packet_tsc *,
const struct pt_config *);
extern int pt_time_update_cbr(struct pt_time *, const struct pt_packet_cbr *,
const struct pt_config *);
extern int pt_time_update_tma(struct pt_time *, const struct pt_packet_tma *,
const struct pt_config *);
extern int pt_time_update_mtc(struct pt_time *, const struct pt_packet_mtc *,
const struct pt_config *);
/* @fcr is the fast-counter:cycles ratio obtained by calibration. */
extern int pt_time_update_cyc(struct pt_time *, const struct pt_packet_cyc *,
const struct pt_config *, uint64_t fcr);
/* Timing calibration.
*
* Used for estimating the Fast-Counter:Cycles ratio.
*
* Ideally, we calibrate by counting CYCs between MTCs. Lacking MTCs, we
* use TSC, instead.
*/
struct pt_time_cal {
/* The estimated fast-counter:cycles ratio. */
uint64_t fcr;
/* The minimal and maximal @fcr values. */
uint64_t min_fcr, max_fcr;
/* The last TSC value.
*
* Used for calibrating at TSC.
*/
uint64_t tsc;
/* The number of cycles since the last TSC (from CYC).
*
* Used for calibrating at TSC.
*/
uint64_t cyc_tsc;
/* The number of cycles since the last MTC (from CYC).
*
* Used for calibrating at MTC.
*/
uint64_t cyc_mtc;
/* The adjusted last CTC value (from MTC).
*
* Used for calibrating at MTC.
*/
uint32_t ctc;
/* The number of lost MTC updates since the last successful update. */
uint32_t lost_mtc;
/* A flag saying whether we have seen a MTC packet. */
uint32_t have_mtc:1;
};
enum {
/* The amount by which the fcr value is right-shifted.
*
* Do not shift the value obtained by pt_tcal_fcr() when passing it to
* pt_time_update_cyc().
* Do shift the value passed to pt_tcal_set_fcr().
*/
pt_tcal_fcr_shr = 8
};
/* Initialize of reset timing calibration. */
extern void pt_tcal_init(struct pt_time_cal *tcal);
/* Query the estimated fast-counter:cycles ratio.
*
* Provides the estimated ratio in @fcr unless -pte_internal or
* -pte_no_time is returned.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @fcr or @tcal is NULL.
* Returns -pte_no_time if no information is available.
*/
extern int pt_tcal_fcr(uint64_t *fcr, const struct pt_time_cal *tcal);
/* Set the fast-counter:cycles ratio.
*
* Timing calibration takes one CBR or two MTC packets before it can provide
* first estimations. Use this to supply an initial value to be used in the
* meantime.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @cal is NULL.
*/
extern int pt_tcal_set_fcr(struct pt_time_cal *tcal, uint64_t fcr);
/* Update calibration based on an Intel PT packet.
*
* Returns zero on success, a negative error code otherwise.
*/
extern int pt_tcal_update_tsc(struct pt_time_cal *,
const struct pt_packet_tsc *,
const struct pt_config *);
extern int pt_tcal_header_tsc(struct pt_time_cal *,
const struct pt_packet_tsc *,
const struct pt_config *);
extern int pt_tcal_update_cbr(struct pt_time_cal *,
const struct pt_packet_cbr *,
const struct pt_config *);
extern int pt_tcal_header_cbr(struct pt_time_cal *,
const struct pt_packet_cbr *,
const struct pt_config *);
extern int pt_tcal_update_tma(struct pt_time_cal *,
const struct pt_packet_tma *,
const struct pt_config *);
extern int pt_tcal_update_mtc(struct pt_time_cal *,
const struct pt_packet_mtc *,
const struct pt_config *);
extern int pt_tcal_update_cyc(struct pt_time_cal *,
const struct pt_packet_cyc *,
const struct pt_config *);
#endif /* PT_TIME_H */

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#ifndef PT_TNT_CACHE_H
#define PT_TNT_CACHE_H
#include <stdint.h>
struct pt_packet_tnt;
struct pt_config;
/* Keeping track of tnt indicators. */
struct pt_tnt_cache {
/* The last tnt. */
uint64_t tnt;
/* The index into the above tnt.
*
* (tnt & index) gives the current tnt entry.
* (index >>= 1) moves the index to the next tnt entry.
* (index == 0) means that the current tnt is empty.
*/
uint64_t index;
};
/* Initialize (or reset) the tnt cache. */
extern void pt_tnt_cache_init(struct pt_tnt_cache *cache);
/* Check if the tnt cache is empty.
*
* Returns 0 if the tnt cache is not empty.
* Returns > 0 if the tnt cache is empty.
* Returns -pte_invalid if @cache is NULL.
*/
extern int pt_tnt_cache_is_empty(const struct pt_tnt_cache *cache);
/* Query the next tnt indicator.
*
* This consumes the returned tnt indicator in the cache.
*
* Returns 0 if the next branch is not taken.
* Returns > 0 if the next branch is taken.
* Returns -pte_invalid if @cache is NULL.
* Returns -pte_bad_query if there is no tnt cached.
*/
extern int pt_tnt_cache_query(struct pt_tnt_cache *cache);
/* Update the tnt cache based on Intel PT packets.
*
* Updates @cache based on @packet and, if non-null, @config.
*
* Returns zero on success.
* Returns -pte_invalid if @cache or @packet is NULL.
* Returns -pte_bad_packet if @packet appears to be corrupted.
* Returns -pte_bad_context if the tnt cache is not empty.
*/
extern int pt_tnt_cache_update_tnt(struct pt_tnt_cache *cache,
const struct pt_packet_tnt *packet,
const struct pt_config *config);
#endif /* PT_TNT_CACHE_H */

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#if !defined(PTI_DISP_DEFS_H)
#define PTI_DISP_DEFS_H
#define PTI_DISP_NONE 0
#define PTI_PRESERVE_DEFAULT 1
#define PTI_BRDISP8 2
#define PTI_DISP_BUCKET_0_l1 3
#define PTI_MEMDISPv_DISP_WIDTH_ASZ_NONTERM_EASZ_l2 4
#define PTI_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2 5
#define PTI_RESOLVE_BYREG_DISP_map0x0_op0xc7_l1 6
#endif

View File

@ -0,0 +1,544 @@
/*
* Copyright (c) 2013-2018, 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.
*/
static uint8_t disp_bytes_map_0x0[256] = {
/*opcode 0x0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf*/ 0,
/*opcode 0x10*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x11*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x12*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x13*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x14*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x15*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x16*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x17*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x18*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x19*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x20*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x21*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x22*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x23*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x24*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x25*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x26*/ 0,
/*opcode 0x27*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x28*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x29*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2e*/ 0,
/*opcode 0x2f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x30*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x31*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x32*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x33*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x34*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x35*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x36*/ 0,
/*opcode 0x37*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x38*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x39*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3e*/ 0,
/*opcode 0x3f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x40*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x41*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x42*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x43*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x44*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x45*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x46*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x47*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x48*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x49*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x50*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x51*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x52*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x53*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x54*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x55*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x56*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x57*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x58*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x59*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x60*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x61*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x62*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x63*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x64*/ 0,
/*opcode 0x65*/ 0,
/*opcode 0x66*/ 0,
/*opcode 0x67*/ 0,
/*opcode 0x68*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x69*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x70*/ PTI_BRDISP8,
/*opcode 0x71*/ PTI_BRDISP8,
/*opcode 0x72*/ PTI_BRDISP8,
/*opcode 0x73*/ PTI_BRDISP8,
/*opcode 0x74*/ PTI_BRDISP8,
/*opcode 0x75*/ PTI_BRDISP8,
/*opcode 0x76*/ PTI_BRDISP8,
/*opcode 0x77*/ PTI_BRDISP8,
/*opcode 0x78*/ PTI_BRDISP8,
/*opcode 0x79*/ PTI_BRDISP8,
/*opcode 0x7a*/ PTI_BRDISP8,
/*opcode 0x7b*/ PTI_BRDISP8,
/*opcode 0x7c*/ PTI_BRDISP8,
/*opcode 0x7d*/ PTI_BRDISP8,
/*opcode 0x7e*/ PTI_BRDISP8,
/*opcode 0x7f*/ PTI_BRDISP8,
/*opcode 0x80*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x81*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x82*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x83*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x84*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x85*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x86*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x87*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x88*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x89*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x90*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x91*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x92*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x93*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x94*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x95*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x96*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x97*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x98*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x99*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9a*/ PTI_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x9b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa0*/ PTI_MEMDISPv_DISP_WIDTH_ASZ_NONTERM_EASZ_l2,
/*opcode 0xa1*/ PTI_MEMDISPv_DISP_WIDTH_ASZ_NONTERM_EASZ_l2,
/*opcode 0xa2*/ PTI_MEMDISPv_DISP_WIDTH_ASZ_NONTERM_EASZ_l2,
/*opcode 0xa3*/ PTI_MEMDISPv_DISP_WIDTH_ASZ_NONTERM_EASZ_l2,
/*opcode 0xa4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xaa*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xab*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xac*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xad*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xae*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xaf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xba*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbe*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc7*/ PTI_RESOLVE_BYREG_DISP_map0x0_op0xc7_l1,
/*opcode 0xc8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xca*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xce*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xda*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xde*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe0*/ PTI_BRDISP8,
/*opcode 0xe1*/ PTI_BRDISP8,
/*opcode 0xe2*/ PTI_BRDISP8,
/*opcode 0xe3*/ PTI_BRDISP8,
/*opcode 0xe4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe8*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0xe9*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0xea*/ PTI_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xeb*/ PTI_BRDISP8,
/*opcode 0xec*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xed*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xee*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xef*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf0*/ 0,
/*opcode 0xf1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf2*/ 0,
/*opcode 0xf3*/ 0,
/*opcode 0xf4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfa*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfe*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xff*/ PTI_PRESERVE_DEFAULT,
};
static uint8_t disp_bytes_map_0x0F[256] = {
/*opcode 0x0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4*/ 0,
/*opcode 0x5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa*/ 0,
/*opcode 0xb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc*/ 0,
/*opcode 0xd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf*/ 0,
/*opcode 0x10*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x11*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x12*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x13*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x14*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x15*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x16*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x17*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x18*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x19*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x1f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x20*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x21*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x22*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x23*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x24*/ 0,
/*opcode 0x25*/ 0,
/*opcode 0x26*/ 0,
/*opcode 0x27*/ 0,
/*opcode 0x28*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x29*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x2f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x30*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x31*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x32*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x33*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x34*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x35*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x36*/ 0,
/*opcode 0x37*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x38*/ 0,
/*opcode 0x39*/ 0,
/*opcode 0x3a*/ 0,
/*opcode 0x3b*/ 0,
/*opcode 0x3c*/ 0,
/*opcode 0x3d*/ 0,
/*opcode 0x3e*/ 0,
/*opcode 0x3f*/ 0,
/*opcode 0x40*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x41*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x42*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x43*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x44*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x45*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x46*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x47*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x48*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x49*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x4f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x50*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x51*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x52*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x53*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x54*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x55*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x56*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x57*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x58*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x59*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x5f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x60*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x61*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x62*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x63*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x64*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x65*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x66*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x67*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x68*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x69*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x6f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x70*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x71*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x72*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x73*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x74*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x75*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x76*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x77*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x78*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x79*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x7f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x80*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x81*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x82*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x83*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x84*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x85*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x86*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x87*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x88*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x89*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x8a*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x8b*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x8c*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x8d*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x8e*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x8f*/ PTI_DISP_BUCKET_0_l1,
/*opcode 0x90*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x91*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x92*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x93*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x94*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x95*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x96*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x97*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x98*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x99*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9a*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9b*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9c*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9d*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9e*/ PTI_PRESERVE_DEFAULT,
/*opcode 0x9f*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa6*/ 0,
/*opcode 0xa7*/ 0,
/*opcode 0xa8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xa9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xaa*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xab*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xac*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xad*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xae*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xaf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xb9*/ 0,
/*opcode 0xba*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbe*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xbf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xc9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xca*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xce*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xcf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xd9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xda*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xde*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xdf*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xe9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xea*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xeb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xec*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xed*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xee*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xef*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf0*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf1*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf2*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf3*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf4*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf5*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf6*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf7*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf8*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xf9*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfa*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfb*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfc*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfd*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xfe*/ PTI_PRESERVE_DEFAULT,
/*opcode 0xff*/ 0,
};

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#if !defined(PTI_IMM_DEFS_H)
#define PTI_IMM_DEFS_H
#define PTI_IMM_NONE 0
#define PTI_0_IMM_WIDTH_CONST_l2 1
#define PTI_UIMM8_IMM_WIDTH_CONST_l2 2
#define PTI_SIMM8_IMM_WIDTH_CONST_l2 3
#define PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2 4
#define PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2 5
#define PTI_UIMM16_IMM_WIDTH_CONST_l2 6
#define PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xf7_l1 7
#define PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xc7_l1 8
#define PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_DF64_EOSZ_l2 9
#define PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xf6_l1 10
#define PTI_IMM_hasimm_map0x0_op0xc8_l1 11
#define PTI_IMM_hasimm_map0x0F_op0x78_l1 12
#endif

View File

@ -0,0 +1,544 @@
/*
* Copyright (c) 2013-2018, 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.
*/
static uint8_t imm_bytes_map_0x0[256] = {
/*opcode 0x0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x5*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xd*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xe*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf*/ 0,
/*opcode 0x10*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x11*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x12*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x13*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x14*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x15*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x16*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x17*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x18*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x19*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1c*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x1d*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x1e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x20*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x21*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x22*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x23*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x24*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x25*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x26*/ 0,
/*opcode 0x27*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x28*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x29*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2c*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x2d*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x2e*/ 0,
/*opcode 0x2f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x30*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x31*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x32*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x33*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x34*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x35*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x36*/ 0,
/*opcode 0x37*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x38*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x39*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x3a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x3b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x3c*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x3d*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x3e*/ 0,
/*opcode 0x3f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x40*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x41*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x42*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x43*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x44*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x45*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x46*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x47*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x48*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x49*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x50*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x51*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x52*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x53*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x54*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x55*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x56*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x57*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x58*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x59*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x60*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x61*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x62*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x63*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x64*/ 0,
/*opcode 0x65*/ 0,
/*opcode 0x66*/ 0,
/*opcode 0x67*/ 0,
/*opcode 0x68*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_DF64_EOSZ_l2,
/*opcode 0x69*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x6a*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x6b*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x6c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x70*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x71*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x72*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x73*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x74*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x75*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x76*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x77*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x78*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x79*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x80*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x81*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0x82*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x83*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x84*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x85*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x86*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x87*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x88*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x89*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x90*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x91*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x92*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x93*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x94*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x95*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x96*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x97*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x98*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x99*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9a*/ PTI_UIMM16_IMM_WIDTH_CONST_l2,
/*opcode 0x9b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa8*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xa9*/ PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xaa*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xab*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xac*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xad*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xae*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xaf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb0*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb1*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb2*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb3*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb4*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb5*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb6*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb7*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xb8*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xb9*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xba*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xbb*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xbc*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xbd*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xbe*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xbf*/ PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2,
/*opcode 0xc0*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc1*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc2*/ PTI_UIMM16_IMM_WIDTH_CONST_l2,
/*opcode 0xc3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc6*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc7*/ PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xc7_l1,
/*opcode 0xc8*/ PTI_IMM_hasimm_map0x0_op0xc8_l1,
/*opcode 0xc9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xca*/ PTI_UIMM16_IMM_WIDTH_CONST_l2,
/*opcode 0xcb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcd*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xce*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd4*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xd5*/ PTI_SIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xd6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xda*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xde*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe4*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xe5*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xe6*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xe7*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xe8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xea*/ PTI_UIMM16_IMM_WIDTH_CONST_l2,
/*opcode 0xeb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xec*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xed*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xee*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xef*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf0*/ 0,
/*opcode 0xf1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf2*/ 0,
/*opcode 0xf3*/ 0,
/*opcode 0xf4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf6*/ PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xf6_l1,
/*opcode 0xf7*/ PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xf7_l1,
/*opcode 0xf8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfa*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfe*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xff*/ PTI_0_IMM_WIDTH_CONST_l2,
};
static uint8_t imm_bytes_map_0x0F[256] = {
/*opcode 0x0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4*/ 0,
/*opcode 0x5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa*/ 0,
/*opcode 0xb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc*/ 0,
/*opcode 0xd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf*/ 0,
/*opcode 0x10*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x11*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x12*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x13*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x14*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x15*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x16*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x17*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x18*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x19*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x1f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x20*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x21*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x22*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x23*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x24*/ 0,
/*opcode 0x25*/ 0,
/*opcode 0x26*/ 0,
/*opcode 0x27*/ 0,
/*opcode 0x28*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x29*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x2f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x30*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x31*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x32*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x33*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x34*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x35*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x36*/ 0,
/*opcode 0x37*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x38*/ 0,
/*opcode 0x39*/ 0,
/*opcode 0x3a*/ 0,
/*opcode 0x3b*/ 0,
/*opcode 0x3c*/ 0,
/*opcode 0x3d*/ 0,
/*opcode 0x3e*/ 0,
/*opcode 0x3f*/ 0,
/*opcode 0x40*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x41*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x42*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x43*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x44*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x45*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x46*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x47*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x48*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x49*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x4f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x50*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x51*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x52*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x53*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x54*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x55*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x56*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x57*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x58*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x59*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x5f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x60*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x61*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x62*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x63*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x64*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x65*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x66*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x67*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x68*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x69*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x6f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x70*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x71*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x72*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x73*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0x74*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x75*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x76*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x77*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x78*/ PTI_IMM_hasimm_map0x0F_op0x78_l1,
/*opcode 0x79*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x7f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x80*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x81*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x82*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x83*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x84*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x85*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x86*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x87*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x88*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x89*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x8f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x90*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x91*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x92*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x93*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x94*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x95*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x96*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x97*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x98*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x99*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9a*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9b*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9c*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9d*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9e*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0x9f*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa4*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xa5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa6*/ 0,
/*opcode 0xa7*/ 0,
/*opcode 0xa8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xa9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xaa*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xab*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xac*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xad*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xae*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xaf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xb9*/ 0,
/*opcode 0xba*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xbb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xbc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xbd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xbe*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xbf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc2*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc4*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc5*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc6*/ PTI_UIMM8_IMM_WIDTH_CONST_l2,
/*opcode 0xc7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xc9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xca*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xce*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xcf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xd9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xda*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xde*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xdf*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xe9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xea*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xeb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xec*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xed*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xee*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xef*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf0*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf1*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf2*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf3*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf4*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf5*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf6*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf7*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf8*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xf9*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfa*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfb*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfc*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfd*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xfe*/ PTI_0_IMM_WIDTH_CONST_l2,
/*opcode 0xff*/ 0,
};

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#if !defined(PTI_MODRM_DEFS_H)
#define PTI_MODRM_DEFS_H
#define PTI_MODRM_FALSE 0
#define PTI_MODRM_TRUE 1
#define PTI_MODRM_IGNORE_MOD 2
#define PTI_MODRM_UNDEF 3
#endif

View File

@ -0,0 +1,544 @@
/*
* Copyright (c) 2013-2018, 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.
*/
static uint8_t has_modrm_map_0x0[256] = {
/*opcode 0x0*/ PTI_MODRM_TRUE,
/*opcode 0x1*/ PTI_MODRM_TRUE,
/*opcode 0x2*/ PTI_MODRM_TRUE,
/*opcode 0x3*/ PTI_MODRM_TRUE,
/*opcode 0x4*/ PTI_MODRM_FALSE,
/*opcode 0x5*/ PTI_MODRM_FALSE,
/*opcode 0x6*/ PTI_MODRM_FALSE,
/*opcode 0x7*/ PTI_MODRM_FALSE,
/*opcode 0x8*/ PTI_MODRM_TRUE,
/*opcode 0x9*/ PTI_MODRM_TRUE,
/*opcode 0xa*/ PTI_MODRM_TRUE,
/*opcode 0xb*/ PTI_MODRM_TRUE,
/*opcode 0xc*/ PTI_MODRM_FALSE,
/*opcode 0xd*/ PTI_MODRM_FALSE,
/*opcode 0xe*/ PTI_MODRM_FALSE,
/*opcode 0xf*/ PTI_MODRM_UNDEF,
/*opcode 0x10*/ PTI_MODRM_TRUE,
/*opcode 0x11*/ PTI_MODRM_TRUE,
/*opcode 0x12*/ PTI_MODRM_TRUE,
/*opcode 0x13*/ PTI_MODRM_TRUE,
/*opcode 0x14*/ PTI_MODRM_FALSE,
/*opcode 0x15*/ PTI_MODRM_FALSE,
/*opcode 0x16*/ PTI_MODRM_FALSE,
/*opcode 0x17*/ PTI_MODRM_FALSE,
/*opcode 0x18*/ PTI_MODRM_TRUE,
/*opcode 0x19*/ PTI_MODRM_TRUE,
/*opcode 0x1a*/ PTI_MODRM_TRUE,
/*opcode 0x1b*/ PTI_MODRM_TRUE,
/*opcode 0x1c*/ PTI_MODRM_FALSE,
/*opcode 0x1d*/ PTI_MODRM_FALSE,
/*opcode 0x1e*/ PTI_MODRM_FALSE,
/*opcode 0x1f*/ PTI_MODRM_FALSE,
/*opcode 0x20*/ PTI_MODRM_TRUE,
/*opcode 0x21*/ PTI_MODRM_TRUE,
/*opcode 0x22*/ PTI_MODRM_TRUE,
/*opcode 0x23*/ PTI_MODRM_TRUE,
/*opcode 0x24*/ PTI_MODRM_FALSE,
/*opcode 0x25*/ PTI_MODRM_FALSE,
/*opcode 0x26*/ PTI_MODRM_UNDEF,
/*opcode 0x27*/ PTI_MODRM_FALSE,
/*opcode 0x28*/ PTI_MODRM_TRUE,
/*opcode 0x29*/ PTI_MODRM_TRUE,
/*opcode 0x2a*/ PTI_MODRM_TRUE,
/*opcode 0x2b*/ PTI_MODRM_TRUE,
/*opcode 0x2c*/ PTI_MODRM_FALSE,
/*opcode 0x2d*/ PTI_MODRM_FALSE,
/*opcode 0x2e*/ PTI_MODRM_UNDEF,
/*opcode 0x2f*/ PTI_MODRM_FALSE,
/*opcode 0x30*/ PTI_MODRM_TRUE,
/*opcode 0x31*/ PTI_MODRM_TRUE,
/*opcode 0x32*/ PTI_MODRM_TRUE,
/*opcode 0x33*/ PTI_MODRM_TRUE,
/*opcode 0x34*/ PTI_MODRM_FALSE,
/*opcode 0x35*/ PTI_MODRM_FALSE,
/*opcode 0x36*/ PTI_MODRM_UNDEF,
/*opcode 0x37*/ PTI_MODRM_FALSE,
/*opcode 0x38*/ PTI_MODRM_TRUE,
/*opcode 0x39*/ PTI_MODRM_TRUE,
/*opcode 0x3a*/ PTI_MODRM_TRUE,
/*opcode 0x3b*/ PTI_MODRM_TRUE,
/*opcode 0x3c*/ PTI_MODRM_FALSE,
/*opcode 0x3d*/ PTI_MODRM_FALSE,
/*opcode 0x3e*/ PTI_MODRM_UNDEF,
/*opcode 0x3f*/ PTI_MODRM_FALSE,
/*opcode 0x40*/ PTI_MODRM_FALSE,
/*opcode 0x41*/ PTI_MODRM_FALSE,
/*opcode 0x42*/ PTI_MODRM_FALSE,
/*opcode 0x43*/ PTI_MODRM_FALSE,
/*opcode 0x44*/ PTI_MODRM_FALSE,
/*opcode 0x45*/ PTI_MODRM_FALSE,
/*opcode 0x46*/ PTI_MODRM_FALSE,
/*opcode 0x47*/ PTI_MODRM_FALSE,
/*opcode 0x48*/ PTI_MODRM_FALSE,
/*opcode 0x49*/ PTI_MODRM_FALSE,
/*opcode 0x4a*/ PTI_MODRM_FALSE,
/*opcode 0x4b*/ PTI_MODRM_FALSE,
/*opcode 0x4c*/ PTI_MODRM_FALSE,
/*opcode 0x4d*/ PTI_MODRM_FALSE,
/*opcode 0x4e*/ PTI_MODRM_FALSE,
/*opcode 0x4f*/ PTI_MODRM_FALSE,
/*opcode 0x50*/ PTI_MODRM_FALSE,
/*opcode 0x51*/ PTI_MODRM_FALSE,
/*opcode 0x52*/ PTI_MODRM_FALSE,
/*opcode 0x53*/ PTI_MODRM_FALSE,
/*opcode 0x54*/ PTI_MODRM_FALSE,
/*opcode 0x55*/ PTI_MODRM_FALSE,
/*opcode 0x56*/ PTI_MODRM_FALSE,
/*opcode 0x57*/ PTI_MODRM_FALSE,
/*opcode 0x58*/ PTI_MODRM_FALSE,
/*opcode 0x59*/ PTI_MODRM_FALSE,
/*opcode 0x5a*/ PTI_MODRM_FALSE,
/*opcode 0x5b*/ PTI_MODRM_FALSE,
/*opcode 0x5c*/ PTI_MODRM_FALSE,
/*opcode 0x5d*/ PTI_MODRM_FALSE,
/*opcode 0x5e*/ PTI_MODRM_FALSE,
/*opcode 0x5f*/ PTI_MODRM_FALSE,
/*opcode 0x60*/ PTI_MODRM_FALSE,
/*opcode 0x61*/ PTI_MODRM_FALSE,
/*opcode 0x62*/ PTI_MODRM_TRUE,
/*opcode 0x63*/ PTI_MODRM_TRUE,
/*opcode 0x64*/ PTI_MODRM_UNDEF,
/*opcode 0x65*/ PTI_MODRM_UNDEF,
/*opcode 0x66*/ PTI_MODRM_UNDEF,
/*opcode 0x67*/ PTI_MODRM_UNDEF,
/*opcode 0x68*/ PTI_MODRM_FALSE,
/*opcode 0x69*/ PTI_MODRM_TRUE,
/*opcode 0x6a*/ PTI_MODRM_FALSE,
/*opcode 0x6b*/ PTI_MODRM_TRUE,
/*opcode 0x6c*/ PTI_MODRM_FALSE,
/*opcode 0x6d*/ PTI_MODRM_FALSE,
/*opcode 0x6e*/ PTI_MODRM_FALSE,
/*opcode 0x6f*/ PTI_MODRM_FALSE,
/*opcode 0x70*/ PTI_MODRM_FALSE,
/*opcode 0x71*/ PTI_MODRM_FALSE,
/*opcode 0x72*/ PTI_MODRM_FALSE,
/*opcode 0x73*/ PTI_MODRM_FALSE,
/*opcode 0x74*/ PTI_MODRM_FALSE,
/*opcode 0x75*/ PTI_MODRM_FALSE,
/*opcode 0x76*/ PTI_MODRM_FALSE,
/*opcode 0x77*/ PTI_MODRM_FALSE,
/*opcode 0x78*/ PTI_MODRM_FALSE,
/*opcode 0x79*/ PTI_MODRM_FALSE,
/*opcode 0x7a*/ PTI_MODRM_FALSE,
/*opcode 0x7b*/ PTI_MODRM_FALSE,
/*opcode 0x7c*/ PTI_MODRM_FALSE,
/*opcode 0x7d*/ PTI_MODRM_FALSE,
/*opcode 0x7e*/ PTI_MODRM_FALSE,
/*opcode 0x7f*/ PTI_MODRM_FALSE,
/*opcode 0x80*/ PTI_MODRM_TRUE,
/*opcode 0x81*/ PTI_MODRM_TRUE,
/*opcode 0x82*/ PTI_MODRM_TRUE,
/*opcode 0x83*/ PTI_MODRM_TRUE,
/*opcode 0x84*/ PTI_MODRM_TRUE,
/*opcode 0x85*/ PTI_MODRM_TRUE,
/*opcode 0x86*/ PTI_MODRM_TRUE,
/*opcode 0x87*/ PTI_MODRM_TRUE,
/*opcode 0x88*/ PTI_MODRM_TRUE,
/*opcode 0x89*/ PTI_MODRM_TRUE,
/*opcode 0x8a*/ PTI_MODRM_TRUE,
/*opcode 0x8b*/ PTI_MODRM_TRUE,
/*opcode 0x8c*/ PTI_MODRM_TRUE,
/*opcode 0x8d*/ PTI_MODRM_TRUE,
/*opcode 0x8e*/ PTI_MODRM_TRUE,
/*opcode 0x8f*/ PTI_MODRM_TRUE,
/*opcode 0x90*/ PTI_MODRM_FALSE,
/*opcode 0x91*/ PTI_MODRM_FALSE,
/*opcode 0x92*/ PTI_MODRM_FALSE,
/*opcode 0x93*/ PTI_MODRM_FALSE,
/*opcode 0x94*/ PTI_MODRM_FALSE,
/*opcode 0x95*/ PTI_MODRM_FALSE,
/*opcode 0x96*/ PTI_MODRM_FALSE,
/*opcode 0x97*/ PTI_MODRM_FALSE,
/*opcode 0x98*/ PTI_MODRM_FALSE,
/*opcode 0x99*/ PTI_MODRM_FALSE,
/*opcode 0x9a*/ PTI_MODRM_FALSE,
/*opcode 0x9b*/ PTI_MODRM_FALSE,
/*opcode 0x9c*/ PTI_MODRM_FALSE,
/*opcode 0x9d*/ PTI_MODRM_FALSE,
/*opcode 0x9e*/ PTI_MODRM_FALSE,
/*opcode 0x9f*/ PTI_MODRM_FALSE,
/*opcode 0xa0*/ PTI_MODRM_FALSE,
/*opcode 0xa1*/ PTI_MODRM_FALSE,
/*opcode 0xa2*/ PTI_MODRM_FALSE,
/*opcode 0xa3*/ PTI_MODRM_FALSE,
/*opcode 0xa4*/ PTI_MODRM_FALSE,
/*opcode 0xa5*/ PTI_MODRM_FALSE,
/*opcode 0xa6*/ PTI_MODRM_FALSE,
/*opcode 0xa7*/ PTI_MODRM_FALSE,
/*opcode 0xa8*/ PTI_MODRM_FALSE,
/*opcode 0xa9*/ PTI_MODRM_FALSE,
/*opcode 0xaa*/ PTI_MODRM_FALSE,
/*opcode 0xab*/ PTI_MODRM_FALSE,
/*opcode 0xac*/ PTI_MODRM_FALSE,
/*opcode 0xad*/ PTI_MODRM_FALSE,
/*opcode 0xae*/ PTI_MODRM_FALSE,
/*opcode 0xaf*/ PTI_MODRM_FALSE,
/*opcode 0xb0*/ PTI_MODRM_FALSE,
/*opcode 0xb1*/ PTI_MODRM_FALSE,
/*opcode 0xb2*/ PTI_MODRM_FALSE,
/*opcode 0xb3*/ PTI_MODRM_FALSE,
/*opcode 0xb4*/ PTI_MODRM_FALSE,
/*opcode 0xb5*/ PTI_MODRM_FALSE,
/*opcode 0xb6*/ PTI_MODRM_FALSE,
/*opcode 0xb7*/ PTI_MODRM_FALSE,
/*opcode 0xb8*/ PTI_MODRM_FALSE,
/*opcode 0xb9*/ PTI_MODRM_FALSE,
/*opcode 0xba*/ PTI_MODRM_FALSE,
/*opcode 0xbb*/ PTI_MODRM_FALSE,
/*opcode 0xbc*/ PTI_MODRM_FALSE,
/*opcode 0xbd*/ PTI_MODRM_FALSE,
/*opcode 0xbe*/ PTI_MODRM_FALSE,
/*opcode 0xbf*/ PTI_MODRM_FALSE,
/*opcode 0xc0*/ PTI_MODRM_TRUE,
/*opcode 0xc1*/ PTI_MODRM_TRUE,
/*opcode 0xc2*/ PTI_MODRM_FALSE,
/*opcode 0xc3*/ PTI_MODRM_FALSE,
/*opcode 0xc4*/ PTI_MODRM_TRUE,
/*opcode 0xc5*/ PTI_MODRM_TRUE,
/*opcode 0xc6*/ PTI_MODRM_TRUE,
/*opcode 0xc7*/ PTI_MODRM_TRUE,
/*opcode 0xc8*/ PTI_MODRM_FALSE,
/*opcode 0xc9*/ PTI_MODRM_FALSE,
/*opcode 0xca*/ PTI_MODRM_FALSE,
/*opcode 0xcb*/ PTI_MODRM_FALSE,
/*opcode 0xcc*/ PTI_MODRM_FALSE,
/*opcode 0xcd*/ PTI_MODRM_FALSE,
/*opcode 0xce*/ PTI_MODRM_FALSE,
/*opcode 0xcf*/ PTI_MODRM_FALSE,
/*opcode 0xd0*/ PTI_MODRM_TRUE,
/*opcode 0xd1*/ PTI_MODRM_TRUE,
/*opcode 0xd2*/ PTI_MODRM_TRUE,
/*opcode 0xd3*/ PTI_MODRM_TRUE,
/*opcode 0xd4*/ PTI_MODRM_FALSE,
/*opcode 0xd5*/ PTI_MODRM_FALSE,
/*opcode 0xd6*/ PTI_MODRM_FALSE,
/*opcode 0xd7*/ PTI_MODRM_FALSE,
/*opcode 0xd8*/ PTI_MODRM_TRUE,
/*opcode 0xd9*/ PTI_MODRM_TRUE,
/*opcode 0xda*/ PTI_MODRM_TRUE,
/*opcode 0xdb*/ PTI_MODRM_TRUE,
/*opcode 0xdc*/ PTI_MODRM_TRUE,
/*opcode 0xdd*/ PTI_MODRM_TRUE,
/*opcode 0xde*/ PTI_MODRM_TRUE,
/*opcode 0xdf*/ PTI_MODRM_TRUE,
/*opcode 0xe0*/ PTI_MODRM_FALSE,
/*opcode 0xe1*/ PTI_MODRM_FALSE,
/*opcode 0xe2*/ PTI_MODRM_FALSE,
/*opcode 0xe3*/ PTI_MODRM_FALSE,
/*opcode 0xe4*/ PTI_MODRM_FALSE,
/*opcode 0xe5*/ PTI_MODRM_FALSE,
/*opcode 0xe6*/ PTI_MODRM_FALSE,
/*opcode 0xe7*/ PTI_MODRM_FALSE,
/*opcode 0xe8*/ PTI_MODRM_FALSE,
/*opcode 0xe9*/ PTI_MODRM_FALSE,
/*opcode 0xea*/ PTI_MODRM_FALSE,
/*opcode 0xeb*/ PTI_MODRM_FALSE,
/*opcode 0xec*/ PTI_MODRM_FALSE,
/*opcode 0xed*/ PTI_MODRM_FALSE,
/*opcode 0xee*/ PTI_MODRM_FALSE,
/*opcode 0xef*/ PTI_MODRM_FALSE,
/*opcode 0xf0*/ PTI_MODRM_UNDEF,
/*opcode 0xf1*/ PTI_MODRM_FALSE,
/*opcode 0xf2*/ PTI_MODRM_UNDEF,
/*opcode 0xf3*/ PTI_MODRM_UNDEF,
/*opcode 0xf4*/ PTI_MODRM_FALSE,
/*opcode 0xf5*/ PTI_MODRM_FALSE,
/*opcode 0xf6*/ PTI_MODRM_TRUE,
/*opcode 0xf7*/ PTI_MODRM_TRUE,
/*opcode 0xf8*/ PTI_MODRM_FALSE,
/*opcode 0xf9*/ PTI_MODRM_FALSE,
/*opcode 0xfa*/ PTI_MODRM_FALSE,
/*opcode 0xfb*/ PTI_MODRM_FALSE,
/*opcode 0xfc*/ PTI_MODRM_FALSE,
/*opcode 0xfd*/ PTI_MODRM_FALSE,
/*opcode 0xfe*/ PTI_MODRM_TRUE,
/*opcode 0xff*/ PTI_MODRM_TRUE,
};
static uint8_t has_modrm_map_0x0F[256] = {
/*opcode 0x0*/ PTI_MODRM_TRUE,
/*opcode 0x1*/ PTI_MODRM_TRUE,
/*opcode 0x2*/ PTI_MODRM_TRUE,
/*opcode 0x3*/ PTI_MODRM_TRUE,
/*opcode 0x4*/ PTI_MODRM_UNDEF,
/*opcode 0x5*/ PTI_MODRM_FALSE,
/*opcode 0x6*/ PTI_MODRM_FALSE,
/*opcode 0x7*/ PTI_MODRM_FALSE,
/*opcode 0x8*/ PTI_MODRM_FALSE,
/*opcode 0x9*/ PTI_MODRM_FALSE,
/*opcode 0xa*/ PTI_MODRM_UNDEF,
/*opcode 0xb*/ PTI_MODRM_FALSE,
/*opcode 0xc*/ PTI_MODRM_UNDEF,
/*opcode 0xd*/ PTI_MODRM_TRUE,
/*opcode 0xe*/ PTI_MODRM_FALSE,
/*opcode 0xf*/ PTI_MODRM_UNDEF,
/*opcode 0x10*/ PTI_MODRM_TRUE,
/*opcode 0x11*/ PTI_MODRM_TRUE,
/*opcode 0x12*/ PTI_MODRM_TRUE,
/*opcode 0x13*/ PTI_MODRM_TRUE,
/*opcode 0x14*/ PTI_MODRM_TRUE,
/*opcode 0x15*/ PTI_MODRM_TRUE,
/*opcode 0x16*/ PTI_MODRM_TRUE,
/*opcode 0x17*/ PTI_MODRM_TRUE,
/*opcode 0x18*/ PTI_MODRM_TRUE,
/*opcode 0x19*/ PTI_MODRM_TRUE,
/*opcode 0x1a*/ PTI_MODRM_TRUE,
/*opcode 0x1b*/ PTI_MODRM_TRUE,
/*opcode 0x1c*/ PTI_MODRM_TRUE,
/*opcode 0x1d*/ PTI_MODRM_TRUE,
/*opcode 0x1e*/ PTI_MODRM_TRUE,
/*opcode 0x1f*/ PTI_MODRM_TRUE,
/*opcode 0x20*/ PTI_MODRM_IGNORE_MOD,
/*opcode 0x21*/ PTI_MODRM_IGNORE_MOD,
/*opcode 0x22*/ PTI_MODRM_IGNORE_MOD,
/*opcode 0x23*/ PTI_MODRM_IGNORE_MOD,
/*opcode 0x24*/ PTI_MODRM_UNDEF,
/*opcode 0x25*/ PTI_MODRM_UNDEF,
/*opcode 0x26*/ PTI_MODRM_UNDEF,
/*opcode 0x27*/ PTI_MODRM_UNDEF,
/*opcode 0x28*/ PTI_MODRM_TRUE,
/*opcode 0x29*/ PTI_MODRM_TRUE,
/*opcode 0x2a*/ PTI_MODRM_TRUE,
/*opcode 0x2b*/ PTI_MODRM_TRUE,
/*opcode 0x2c*/ PTI_MODRM_TRUE,
/*opcode 0x2d*/ PTI_MODRM_TRUE,
/*opcode 0x2e*/ PTI_MODRM_TRUE,
/*opcode 0x2f*/ PTI_MODRM_TRUE,
/*opcode 0x30*/ PTI_MODRM_FALSE,
/*opcode 0x31*/ PTI_MODRM_FALSE,
/*opcode 0x32*/ PTI_MODRM_FALSE,
/*opcode 0x33*/ PTI_MODRM_FALSE,
/*opcode 0x34*/ PTI_MODRM_FALSE,
/*opcode 0x35*/ PTI_MODRM_FALSE,
/*opcode 0x36*/ PTI_MODRM_UNDEF,
/*opcode 0x37*/ PTI_MODRM_FALSE,
/*opcode 0x38*/ PTI_MODRM_UNDEF,
/*opcode 0x39*/ PTI_MODRM_UNDEF,
/*opcode 0x3a*/ PTI_MODRM_UNDEF,
/*opcode 0x3b*/ PTI_MODRM_UNDEF,
/*opcode 0x3c*/ PTI_MODRM_UNDEF,
/*opcode 0x3d*/ PTI_MODRM_UNDEF,
/*opcode 0x3e*/ PTI_MODRM_UNDEF,
/*opcode 0x3f*/ PTI_MODRM_UNDEF,
/*opcode 0x40*/ PTI_MODRM_TRUE,
/*opcode 0x41*/ PTI_MODRM_TRUE,
/*opcode 0x42*/ PTI_MODRM_TRUE,
/*opcode 0x43*/ PTI_MODRM_TRUE,
/*opcode 0x44*/ PTI_MODRM_TRUE,
/*opcode 0x45*/ PTI_MODRM_TRUE,
/*opcode 0x46*/ PTI_MODRM_TRUE,
/*opcode 0x47*/ PTI_MODRM_TRUE,
/*opcode 0x48*/ PTI_MODRM_TRUE,
/*opcode 0x49*/ PTI_MODRM_TRUE,
/*opcode 0x4a*/ PTI_MODRM_TRUE,
/*opcode 0x4b*/ PTI_MODRM_TRUE,
/*opcode 0x4c*/ PTI_MODRM_TRUE,
/*opcode 0x4d*/ PTI_MODRM_TRUE,
/*opcode 0x4e*/ PTI_MODRM_TRUE,
/*opcode 0x4f*/ PTI_MODRM_TRUE,
/*opcode 0x50*/ PTI_MODRM_TRUE,
/*opcode 0x51*/ PTI_MODRM_TRUE,
/*opcode 0x52*/ PTI_MODRM_TRUE,
/*opcode 0x53*/ PTI_MODRM_TRUE,
/*opcode 0x54*/ PTI_MODRM_TRUE,
/*opcode 0x55*/ PTI_MODRM_TRUE,
/*opcode 0x56*/ PTI_MODRM_TRUE,
/*opcode 0x57*/ PTI_MODRM_TRUE,
/*opcode 0x58*/ PTI_MODRM_TRUE,
/*opcode 0x59*/ PTI_MODRM_TRUE,
/*opcode 0x5a*/ PTI_MODRM_TRUE,
/*opcode 0x5b*/ PTI_MODRM_TRUE,
/*opcode 0x5c*/ PTI_MODRM_TRUE,
/*opcode 0x5d*/ PTI_MODRM_TRUE,
/*opcode 0x5e*/ PTI_MODRM_TRUE,
/*opcode 0x5f*/ PTI_MODRM_TRUE,
/*opcode 0x60*/ PTI_MODRM_TRUE,
/*opcode 0x61*/ PTI_MODRM_TRUE,
/*opcode 0x62*/ PTI_MODRM_TRUE,
/*opcode 0x63*/ PTI_MODRM_TRUE,
/*opcode 0x64*/ PTI_MODRM_TRUE,
/*opcode 0x65*/ PTI_MODRM_TRUE,
/*opcode 0x66*/ PTI_MODRM_TRUE,
/*opcode 0x67*/ PTI_MODRM_TRUE,
/*opcode 0x68*/ PTI_MODRM_TRUE,
/*opcode 0x69*/ PTI_MODRM_TRUE,
/*opcode 0x6a*/ PTI_MODRM_TRUE,
/*opcode 0x6b*/ PTI_MODRM_TRUE,
/*opcode 0x6c*/ PTI_MODRM_TRUE,
/*opcode 0x6d*/ PTI_MODRM_TRUE,
/*opcode 0x6e*/ PTI_MODRM_TRUE,
/*opcode 0x6f*/ PTI_MODRM_TRUE,
/*opcode 0x70*/ PTI_MODRM_TRUE,
/*opcode 0x71*/ PTI_MODRM_TRUE,
/*opcode 0x72*/ PTI_MODRM_TRUE,
/*opcode 0x73*/ PTI_MODRM_TRUE,
/*opcode 0x74*/ PTI_MODRM_TRUE,
/*opcode 0x75*/ PTI_MODRM_TRUE,
/*opcode 0x76*/ PTI_MODRM_TRUE,
/*opcode 0x77*/ PTI_MODRM_FALSE,
/*opcode 0x78*/ PTI_MODRM_TRUE,
/*opcode 0x79*/ PTI_MODRM_TRUE,
/*opcode 0x7a*/ PTI_MODRM_TRUE,
/*opcode 0x7b*/ PTI_MODRM_TRUE,
/*opcode 0x7c*/ PTI_MODRM_TRUE,
/*opcode 0x7d*/ PTI_MODRM_TRUE,
/*opcode 0x7e*/ PTI_MODRM_TRUE,
/*opcode 0x7f*/ PTI_MODRM_TRUE,
/*opcode 0x80*/ PTI_MODRM_FALSE,
/*opcode 0x81*/ PTI_MODRM_FALSE,
/*opcode 0x82*/ PTI_MODRM_FALSE,
/*opcode 0x83*/ PTI_MODRM_FALSE,
/*opcode 0x84*/ PTI_MODRM_FALSE,
/*opcode 0x85*/ PTI_MODRM_FALSE,
/*opcode 0x86*/ PTI_MODRM_FALSE,
/*opcode 0x87*/ PTI_MODRM_FALSE,
/*opcode 0x88*/ PTI_MODRM_FALSE,
/*opcode 0x89*/ PTI_MODRM_FALSE,
/*opcode 0x8a*/ PTI_MODRM_FALSE,
/*opcode 0x8b*/ PTI_MODRM_FALSE,
/*opcode 0x8c*/ PTI_MODRM_FALSE,
/*opcode 0x8d*/ PTI_MODRM_FALSE,
/*opcode 0x8e*/ PTI_MODRM_FALSE,
/*opcode 0x8f*/ PTI_MODRM_FALSE,
/*opcode 0x90*/ PTI_MODRM_TRUE,
/*opcode 0x91*/ PTI_MODRM_TRUE,
/*opcode 0x92*/ PTI_MODRM_TRUE,
/*opcode 0x93*/ PTI_MODRM_TRUE,
/*opcode 0x94*/ PTI_MODRM_TRUE,
/*opcode 0x95*/ PTI_MODRM_TRUE,
/*opcode 0x96*/ PTI_MODRM_TRUE,
/*opcode 0x97*/ PTI_MODRM_TRUE,
/*opcode 0x98*/ PTI_MODRM_TRUE,
/*opcode 0x99*/ PTI_MODRM_TRUE,
/*opcode 0x9a*/ PTI_MODRM_TRUE,
/*opcode 0x9b*/ PTI_MODRM_TRUE,
/*opcode 0x9c*/ PTI_MODRM_TRUE,
/*opcode 0x9d*/ PTI_MODRM_TRUE,
/*opcode 0x9e*/ PTI_MODRM_TRUE,
/*opcode 0x9f*/ PTI_MODRM_TRUE,
/*opcode 0xa0*/ PTI_MODRM_FALSE,
/*opcode 0xa1*/ PTI_MODRM_FALSE,
/*opcode 0xa2*/ PTI_MODRM_FALSE,
/*opcode 0xa3*/ PTI_MODRM_TRUE,
/*opcode 0xa4*/ PTI_MODRM_TRUE,
/*opcode 0xa5*/ PTI_MODRM_TRUE,
/*opcode 0xa6*/ PTI_MODRM_UNDEF,
/*opcode 0xa7*/ PTI_MODRM_UNDEF,
/*opcode 0xa8*/ PTI_MODRM_FALSE,
/*opcode 0xa9*/ PTI_MODRM_FALSE,
/*opcode 0xaa*/ PTI_MODRM_FALSE,
/*opcode 0xab*/ PTI_MODRM_TRUE,
/*opcode 0xac*/ PTI_MODRM_TRUE,
/*opcode 0xad*/ PTI_MODRM_TRUE,
/*opcode 0xae*/ PTI_MODRM_TRUE,
/*opcode 0xaf*/ PTI_MODRM_TRUE,
/*opcode 0xb0*/ PTI_MODRM_TRUE,
/*opcode 0xb1*/ PTI_MODRM_TRUE,
/*opcode 0xb2*/ PTI_MODRM_TRUE,
/*opcode 0xb3*/ PTI_MODRM_TRUE,
/*opcode 0xb4*/ PTI_MODRM_TRUE,
/*opcode 0xb5*/ PTI_MODRM_TRUE,
/*opcode 0xb6*/ PTI_MODRM_TRUE,
/*opcode 0xb7*/ PTI_MODRM_TRUE,
/*opcode 0xb8*/ PTI_MODRM_TRUE,
/*opcode 0xb9*/ PTI_MODRM_UNDEF,
/*opcode 0xba*/ PTI_MODRM_TRUE,
/*opcode 0xbb*/ PTI_MODRM_TRUE,
/*opcode 0xbc*/ PTI_MODRM_TRUE,
/*opcode 0xbd*/ PTI_MODRM_TRUE,
/*opcode 0xbe*/ PTI_MODRM_TRUE,
/*opcode 0xbf*/ PTI_MODRM_TRUE,
/*opcode 0xc0*/ PTI_MODRM_TRUE,
/*opcode 0xc1*/ PTI_MODRM_TRUE,
/*opcode 0xc2*/ PTI_MODRM_TRUE,
/*opcode 0xc3*/ PTI_MODRM_TRUE,
/*opcode 0xc4*/ PTI_MODRM_TRUE,
/*opcode 0xc5*/ PTI_MODRM_TRUE,
/*opcode 0xc6*/ PTI_MODRM_TRUE,
/*opcode 0xc7*/ PTI_MODRM_TRUE,
/*opcode 0xc8*/ PTI_MODRM_FALSE,
/*opcode 0xc9*/ PTI_MODRM_FALSE,
/*opcode 0xca*/ PTI_MODRM_FALSE,
/*opcode 0xcb*/ PTI_MODRM_FALSE,
/*opcode 0xcc*/ PTI_MODRM_FALSE,
/*opcode 0xcd*/ PTI_MODRM_FALSE,
/*opcode 0xce*/ PTI_MODRM_FALSE,
/*opcode 0xcf*/ PTI_MODRM_FALSE,
/*opcode 0xd0*/ PTI_MODRM_TRUE,
/*opcode 0xd1*/ PTI_MODRM_TRUE,
/*opcode 0xd2*/ PTI_MODRM_TRUE,
/*opcode 0xd3*/ PTI_MODRM_TRUE,
/*opcode 0xd4*/ PTI_MODRM_TRUE,
/*opcode 0xd5*/ PTI_MODRM_TRUE,
/*opcode 0xd6*/ PTI_MODRM_TRUE,
/*opcode 0xd7*/ PTI_MODRM_TRUE,
/*opcode 0xd8*/ PTI_MODRM_TRUE,
/*opcode 0xd9*/ PTI_MODRM_TRUE,
/*opcode 0xda*/ PTI_MODRM_TRUE,
/*opcode 0xdb*/ PTI_MODRM_TRUE,
/*opcode 0xdc*/ PTI_MODRM_TRUE,
/*opcode 0xdd*/ PTI_MODRM_TRUE,
/*opcode 0xde*/ PTI_MODRM_TRUE,
/*opcode 0xdf*/ PTI_MODRM_TRUE,
/*opcode 0xe0*/ PTI_MODRM_TRUE,
/*opcode 0xe1*/ PTI_MODRM_TRUE,
/*opcode 0xe2*/ PTI_MODRM_TRUE,
/*opcode 0xe3*/ PTI_MODRM_TRUE,
/*opcode 0xe4*/ PTI_MODRM_TRUE,
/*opcode 0xe5*/ PTI_MODRM_TRUE,
/*opcode 0xe6*/ PTI_MODRM_TRUE,
/*opcode 0xe7*/ PTI_MODRM_TRUE,
/*opcode 0xe8*/ PTI_MODRM_TRUE,
/*opcode 0xe9*/ PTI_MODRM_TRUE,
/*opcode 0xea*/ PTI_MODRM_TRUE,
/*opcode 0xeb*/ PTI_MODRM_TRUE,
/*opcode 0xec*/ PTI_MODRM_TRUE,
/*opcode 0xed*/ PTI_MODRM_TRUE,
/*opcode 0xee*/ PTI_MODRM_TRUE,
/*opcode 0xef*/ PTI_MODRM_TRUE,
/*opcode 0xf0*/ PTI_MODRM_TRUE,
/*opcode 0xf1*/ PTI_MODRM_TRUE,
/*opcode 0xf2*/ PTI_MODRM_TRUE,
/*opcode 0xf3*/ PTI_MODRM_TRUE,
/*opcode 0xf4*/ PTI_MODRM_TRUE,
/*opcode 0xf5*/ PTI_MODRM_TRUE,
/*opcode 0xf6*/ PTI_MODRM_TRUE,
/*opcode 0xf7*/ PTI_MODRM_TRUE,
/*opcode 0xf8*/ PTI_MODRM_TRUE,
/*opcode 0xf9*/ PTI_MODRM_TRUE,
/*opcode 0xfa*/ PTI_MODRM_TRUE,
/*opcode 0xfb*/ PTI_MODRM_TRUE,
/*opcode 0xfc*/ PTI_MODRM_TRUE,
/*opcode 0xfd*/ PTI_MODRM_TRUE,
/*opcode 0xfe*/ PTI_MODRM_TRUE,
/*opcode 0xff*/ PTI_MODRM_UNDEF,
};

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2015-2018, 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.
*/
#ifndef PT_SECTION_WINDOWS_H
#define PT_SECTION_WINDOWS_H
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
struct pt_section;
/* Fstat-based file status. */
struct pt_sec_windows_status {
/* The file status. */
struct _stat stat;
};
/* FileView-based section mapping information. */
struct pt_sec_windows_mapping {
/* The file descriptor. */
int fd;
/* The FileMapping handle. */
HANDLE mh;
/* The mmap base address. */
uint8_t *base;
/* The begin and end of the mapped memory. */
const uint8_t *begin, *end;
};
/* Map a section.
*
* The caller has already opened the file for reading.
*
* On success, sets @section's mapping, unmap, and read pointers.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_invalid if @section can't be mapped.
*/
extern int pt_sec_windows_map(struct pt_section *section, int fd);
/* Unmap a section.
*
* On success, clears @section's mapping, unmap, and read pointers.
*
* This function should not be called directly; call @section->unmap() instead.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section is NULL.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_sec_windows_unmap(struct pt_section *section);
/* Read memory from an mmaped section.
*
* Reads at most @size bytes from @section at @offset into @buffer.
*
* This function should not be called directly; call @section->read() instead.
*
* Returns the number of bytes read on success, a negative error code otherwise.
* Returns -pte_invalid if @section or @buffer are NULL.
* Returns -pte_nomap if @offset is beyond the end of the section.
*/
extern int pt_sec_windows_read(const struct pt_section *section,
uint8_t *buffer, uint16_t size,
uint64_t offset);
/* Compute the memory size of a section.
*
* On success, provides the amount of memory used for mapping @section in bytes
* in @size.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_internal if @section or @size is NULL.
* Returns -pte_internal if @section has not been mapped.
*/
extern int pt_sec_windows_memsize(const struct pt_section *section,
uint64_t *size);
#endif /* PT_SECTION_WINDOWS_H */

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_ild.h"
static void __attribute__((constructor)) init(void)
{
/* Initialize the Intel(R) Processor Trace instruction decoder. */
pt_ild_init();
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_cpuid.h"
#include <cpuid.h>
extern void pt_cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
__get_cpuid(leaf, eax, ebx, ecx, edx);
}

View File

@ -0,0 +1,326 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#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 <limits.h>
#include <sys/types.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;
int errcode;
if (!section)
return -pte_internal;
offset = section->offset;
size = section->size;
adjustment = offset % sysconf(_SC_PAGESIZE);
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;
if (SIZE_MAX < size)
return -pte_nomem;
if (INT_MAX < offset)
return -pte_nomem;
base = mmap(NULL, (size_t) size, PROT_READ, MAP_SHARED, fd,
(off_t) offset);
if (base == MAP_FAILED)
return -pte_nomem;
mapping = malloc(sizeof(*mapping));
if (!mapping) {
errcode = -pte_nomem;
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;
section->memsize = pt_sec_posix_memsize;
return 0;
out_map:
munmap(base, (size_t) size);
return errcode;
}
static int pt_sec_posix_map_success(struct pt_section *section)
{
uint16_t mcount;
int errcode, status;
if (!section)
return -pte_internal;
mcount = section->mcount + 1;
if (!mcount) {
(void) pt_section_unlock(section);
return -pte_overflow;
}
section->mcount = mcount;
errcode = pt_section_unlock(section);
if (errcode < 0)
return errcode;
status = pt_section_on_map(section);
if (status < 0) {
/* We had to release the section lock for pt_section_on_map() so
* @section may have meanwhile been mapped by other threads.
*
* We still want to return the error so we release our mapping.
* Our caller does not yet know whether pt_section_map()
* succeeded.
*/
(void) pt_section_unmap(section);
return status;
}
return 0;
}
int pt_section_map(struct pt_section *section)
{
const char *filename;
FILE *file;
int fd, errcode;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
if (section->mcount)
return pt_sec_posix_map_success(section);
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) {
close(fd);
return pt_sec_posix_map_success(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)
return pt_sec_posix_map_success(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 || !section->memsize)
return -pte_internal;
section->mapping = NULL;
section->unmap = NULL;
section->read = NULL;
section->memsize = NULL;
munmap(mapping->base, (size_t) 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_internal;
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;
}
int pt_sec_posix_memsize(const struct pt_section *section, uint64_t *size)
{
struct pt_sec_posix_mapping *mapping;
const uint8_t *begin, *end;
if (!section || !size)
return -pte_internal;
mapping = section->mapping;
if (!mapping)
return -pte_internal;
begin = mapping->base;
end = mapping->end;
if (!begin || !end || end < begin)
return -pte_internal;
*size = (uint64_t) (end - begin);
return 0;
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "pt_asid.h"
#include "intel-pt.h"
#include <string.h>
int pt_asid_from_user(struct pt_asid *asid, const struct pt_asid *user)
{
if (!asid)
return -pte_internal;
pt_asid_init(asid);
if (user) {
size_t size;
size = user->size;
/* Ignore fields in the user's asid we don't know. */
if (sizeof(*asid) < size)
size = sizeof(*asid);
/* Copy (portions of) the user's asid. */
memcpy(asid, user, size);
/* We copied user's size - fix it. */
asid->size = sizeof(*asid);
}
return 0;
}
int pt_asid_to_user(struct pt_asid *user, const struct pt_asid *asid,
size_t size)
{
if (!user || !asid)
return -pte_internal;
/* We need at least space for the size field. */
if (size < sizeof(asid->size))
return -pte_invalid;
/* Only provide the fields we actually have. */
if (sizeof(*asid) < size)
size = sizeof(*asid);
/* Copy (portions of) our asid to the user's. */
memcpy(user, asid, size);
/* We copied our size - fix it. */
user->size = size;
return 0;
}
int pt_asid_match(const struct pt_asid *lhs, const struct pt_asid *rhs)
{
uint64_t lcr3, rcr3, lvmcs, rvmcs;
if (!lhs || !rhs)
return -pte_internal;
lcr3 = lhs->cr3;
rcr3 = rhs->cr3;
if (lcr3 != rcr3 && lcr3 != pt_asid_no_cr3 && rcr3 != pt_asid_no_cr3)
return 0;
lvmcs = lhs->vmcs;
rvmcs = rhs->vmcs;
if (lvmcs != rvmcs && lvmcs != pt_asid_no_vmcs &&
rvmcs != pt_asid_no_vmcs)
return 0;
return 1;
}

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#include "pt_block_cache.h"
#include <stdlib.h>
#include <string.h>
struct pt_block_cache *pt_bcache_alloc(uint64_t nentries)
{
struct pt_block_cache *bcache;
uint64_t size;
if (!nentries || (UINT32_MAX < nentries))
return NULL;
size = sizeof(*bcache) + (nentries * sizeof(struct pt_bcache_entry));
if (SIZE_MAX < size)
return NULL;
bcache = malloc((size_t) size);
if (!bcache)
return NULL;
memset(bcache, 0, (size_t) size);
bcache->nentries = (uint32_t) nentries;
return bcache;
}
void pt_bcache_free(struct pt_block_cache *bcache)
{
free(bcache);
}
int pt_bcache_add(struct pt_block_cache *bcache, uint64_t index,
struct pt_bcache_entry bce)
{
if (!bcache)
return -pte_internal;
if (bcache->nentries <= index)
return -pte_internal;
/* We rely on guaranteed atomic operations as specified in section 8.1.1
* in Volume 3A of the Intel(R) Software Developer's Manual at
* http://www.intel.com/sdm.
*/
bcache->entry[(uint32_t) index] = bce;
return 0;
}
int pt_bcache_lookup(struct pt_bcache_entry *bce,
const struct pt_block_cache *bcache, uint64_t index)
{
if (!bce || !bcache)
return -pte_internal;
if (bcache->nentries <= index)
return -pte_internal;
/* We rely on guaranteed atomic operations as specified in section 8.1.1
* in Volume 3A of the Intel(R) Software Developer's Manual at
* http://www.intel.com/sdm.
*/
*bce = bcache->entry[(uint32_t) index];
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,251 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_config.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
#include <string.h>
#include <stddef.h>
int pt_cpu_errata(struct pt_errata *errata, const struct pt_cpu *cpu)
{
if (!errata || !cpu)
return -pte_invalid;
memset(errata, 0, sizeof(*errata));
/* We don't know about others. */
if (cpu->vendor != pcv_intel)
return -pte_bad_cpu;
switch (cpu->family) {
case 0x6:
switch (cpu->model) {
case 0x3d:
case 0x47:
case 0x4f:
case 0x56:
errata->bdm70 = 1;
errata->bdm64 = 1;
return 0;
case 0x4e:
case 0x5e:
errata->bdm70 = 1;
errata->skd007 = 1;
errata->skd022 = 1;
errata->skd010 = 1;
errata->skl014 = 1;
return 0;
case 0x8e:
case 0x9e:
errata->bdm70 = 1;
errata->skl014 = 1;
errata->skd022 = 1;
errata->skd010 = 1;
errata->skd007 = 1;
return 0;
case 0x5c:
case 0x5f:
errata->apl12 = 1;
errata->apl11 = 1;
return 0;
}
break;
}
return -pte_bad_cpu;
}
int pt_config_from_user(struct pt_config *config,
const struct pt_config *uconfig)
{
uint8_t *begin, *end;
size_t size;
if (!config)
return -pte_internal;
if (!uconfig)
return -pte_invalid;
size = uconfig->size;
if (size < offsetof(struct pt_config, decode))
return -pte_bad_config;
begin = uconfig->begin;
end = uconfig->end;
if (!begin || !end || end < begin)
return -pte_bad_config;
/* Ignore fields in the user's configuration we don't know; zero out
* fields the user didn't know about.
*/
if (sizeof(*config) <= size)
size = sizeof(*config);
else
memset(((uint8_t *) config) + size, 0, sizeof(*config) - size);
/* Copy (portions of) the user's configuration. */
memcpy(config, uconfig, size);
/* We copied user's size - fix it. */
config->size = size;
return 0;
}
/* The maximum number of filter addresses that fit into the configuration. */
static inline size_t pt_filter_addr_ncfg(void)
{
return (sizeof(struct pt_conf_addr_filter) -
offsetof(struct pt_conf_addr_filter, addr0_a)) /
(2 * sizeof(uint64_t));
}
uint32_t pt_filter_addr_cfg(const struct pt_conf_addr_filter *filter, uint8_t n)
{
if (!filter)
return 0u;
if (pt_filter_addr_ncfg() <= n)
return 0u;
return (filter->config.addr_cfg >> (4 * n)) & 0xf;
}
uint64_t pt_filter_addr_a(const struct pt_conf_addr_filter *filter, uint8_t n)
{
const uint64_t *addr;
if (!filter)
return 0ull;
if (pt_filter_addr_ncfg() <= n)
return 0ull;
addr = &filter->addr0_a;
return addr[2 * n];
}
uint64_t pt_filter_addr_b(const struct pt_conf_addr_filter *filter, uint8_t n)
{
const uint64_t *addr;
if (!filter)
return 0ull;
if (pt_filter_addr_ncfg() <= n)
return 0ull;
addr = &filter->addr0_a;
return addr[(2 * n) + 1];
}
static int pt_filter_check_cfg_filter(const struct pt_conf_addr_filter *filter,
uint64_t addr)
{
uint8_t n;
if (!filter)
return -pte_internal;
for (n = 0; n < pt_filter_addr_ncfg(); ++n) {
uint64_t addr_a, addr_b;
uint32_t addr_cfg;
addr_cfg = pt_filter_addr_cfg(filter, n);
if (addr_cfg != pt_addr_cfg_filter)
continue;
addr_a = pt_filter_addr_a(filter, n);
addr_b = pt_filter_addr_b(filter, n);
/* Note that both A and B are inclusive. */
if ((addr_a <= addr) && (addr <= addr_b))
return 1;
}
/* No filter hit. If we have at least one FilterEn filter, this means
* that tracing is disabled; otherwise, tracing is enabled.
*/
for (n = 0; n < pt_filter_addr_ncfg(); ++n) {
uint32_t addr_cfg;
addr_cfg = pt_filter_addr_cfg(filter, n);
if (addr_cfg == pt_addr_cfg_filter)
return 0;
}
return 1;
}
static int pt_filter_check_cfg_stop(const struct pt_conf_addr_filter *filter,
uint64_t addr)
{
uint8_t n;
if (!filter)
return -pte_internal;
for (n = 0; n < pt_filter_addr_ncfg(); ++n) {
uint64_t addr_a, addr_b;
uint32_t addr_cfg;
addr_cfg = pt_filter_addr_cfg(filter, n);
if (addr_cfg != pt_addr_cfg_stop)
continue;
addr_a = pt_filter_addr_a(filter, n);
addr_b = pt_filter_addr_b(filter, n);
/* Note that both A and B are inclusive. */
if ((addr_a <= addr) && (addr <= addr_b))
return 0;
}
return 1;
}
int pt_filter_addr_check(const struct pt_conf_addr_filter *filter,
uint64_t addr)
{
int status;
status = pt_filter_check_cfg_stop(filter, addr);
if (status <= 0)
return status;
return pt_filter_check_cfg_filter(filter, addr);
}

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_cpu.h"
#include "pt_cpuid.h"
#include "intel-pt.h"
#include <limits.h>
#include <stdlib.h>
static const char * const cpu_vendors[] = {
"",
"GenuineIntel"
};
enum {
pt_cpuid_vendor_size = 12
};
union cpu_vendor {
/* The raw data returned from cpuid. */
struct {
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
} cpuid;
/* The resulting vendor string. */
char vendor_string[pt_cpuid_vendor_size];
};
static enum pt_cpu_vendor cpu_vendor(void)
{
union cpu_vendor vendor;
uint32_t eax;
size_t i;
memset(&vendor, 0, sizeof(vendor));
eax = 0;
pt_cpuid(0u, &eax, &vendor.cpuid.ebx, &vendor.cpuid.ecx,
&vendor.cpuid.edx);
for (i = 0; i < sizeof(cpu_vendors)/sizeof(*cpu_vendors); i++)
if (strncmp(vendor.vendor_string,
cpu_vendors[i], pt_cpuid_vendor_size) == 0)
return (enum pt_cpu_vendor) i;
return pcv_unknown;
}
static uint32_t cpu_info(void)
{
uint32_t eax, ebx, ecx, edx;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
pt_cpuid(1u, &eax, &ebx, &ecx, &edx);
return eax;
}
int pt_cpu_parse(struct pt_cpu *cpu, const char *s)
{
const char sep = '/';
char *endptr;
long family, model, stepping;
if (!cpu || !s)
return -pte_invalid;
family = strtol(s, &endptr, 0);
if (s == endptr || *endptr == '\0' || *endptr != sep)
return -pte_invalid;
if (family < 0 || family > USHRT_MAX)
return -pte_invalid;
/* skip separator */
s = endptr + 1;
model = strtol(s, &endptr, 0);
if (s == endptr || (*endptr != '\0' && *endptr != sep))
return -pte_invalid;
if (model < 0 || model > UCHAR_MAX)
return -pte_invalid;
if (*endptr == '\0')
/* stepping was omitted, it defaults to 0 */
stepping = 0;
else {
/* skip separator */
s = endptr + 1;
stepping = strtol(s, &endptr, 0);
if (*endptr != '\0')
return -pte_invalid;
if (stepping < 0 || stepping > UCHAR_MAX)
return -pte_invalid;
}
cpu->vendor = pcv_intel;
cpu->family = (uint16_t) family;
cpu->model = (uint8_t) model;
cpu->stepping = (uint8_t) stepping;
return 0;
}
int pt_cpu_read(struct pt_cpu *cpu)
{
uint32_t info;
uint16_t family;
if (!cpu)
return -pte_invalid;
cpu->vendor = cpu_vendor();
info = cpu_info();
cpu->family = family = (info>>8) & 0xf;
if (family == 0xf)
cpu->family += (info>>20) & 0xf;
cpu->model = (info>>4) & 0xf;
if (family == 0x6 || family == 0xf)
cpu->model += (info>>12) & 0xf0;
cpu->stepping = (info>>0) & 0xf;
return 0;
}

View File

@ -0,0 +1,379 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_decoder_function.h"
#include "pt_packet_decoder.h"
#include "pt_query_decoder.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
const struct pt_decoder_function pt_decode_unknown = {
/* .packet = */ pt_pkt_decode_unknown,
/* .decode = */ pt_qry_decode_unknown,
/* .header = */ pt_qry_decode_unknown,
/* .flags = */ pdff_unknown
};
const struct pt_decoder_function pt_decode_pad = {
/* .packet = */ pt_pkt_decode_pad,
/* .decode = */ pt_qry_decode_pad,
/* .header = */ pt_qry_decode_pad,
/* .flags = */ pdff_pad
};
const struct pt_decoder_function pt_decode_psb = {
/* .packet = */ pt_pkt_decode_psb,
/* .decode = */ pt_qry_decode_psb,
/* .header = */ NULL,
/* .flags = */ 0
};
const struct pt_decoder_function pt_decode_tip = {
/* .packet = */ pt_pkt_decode_tip,
/* .decode = */ pt_qry_decode_tip,
/* .header = */ NULL,
/* .flags = */ pdff_tip
};
const struct pt_decoder_function pt_decode_tnt_8 = {
/* .packet = */ pt_pkt_decode_tnt_8,
/* .decode = */ pt_qry_decode_tnt_8,
/* .header = */ NULL,
/* .flags = */ pdff_tnt
};
const struct pt_decoder_function pt_decode_tnt_64 = {
/* .packet = */ pt_pkt_decode_tnt_64,
/* .decode = */ pt_qry_decode_tnt_64,
/* .header = */ NULL,
/* .flags = */ pdff_tnt
};
const struct pt_decoder_function pt_decode_tip_pge = {
/* .packet = */ pt_pkt_decode_tip_pge,
/* .decode = */ pt_qry_decode_tip_pge,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_tip_pgd = {
/* .packet = */ pt_pkt_decode_tip_pgd,
/* .decode = */ pt_qry_decode_tip_pgd,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_fup = {
/* .packet = */ pt_pkt_decode_fup,
/* .decode = */ pt_qry_decode_fup,
/* .header = */ pt_qry_header_fup,
/* .flags = */ pdff_fup
};
const struct pt_decoder_function pt_decode_pip = {
/* .packet = */ pt_pkt_decode_pip,
/* .decode = */ pt_qry_decode_pip,
/* .header = */ pt_qry_header_pip,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_ovf = {
/* .packet = */ pt_pkt_decode_ovf,
/* .decode = */ pt_qry_decode_ovf,
/* .header = */ NULL,
/* .flags = */ pdff_psbend | pdff_event
};
const struct pt_decoder_function pt_decode_mode = {
/* .packet = */ pt_pkt_decode_mode,
/* .decode = */ pt_qry_decode_mode,
/* .header = */ pt_qry_header_mode,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_psbend = {
/* .packet = */ pt_pkt_decode_psbend,
/* .decode = */ pt_qry_decode_psbend,
/* .header = */ NULL,
/* .flags = */ pdff_psbend
};
const struct pt_decoder_function pt_decode_tsc = {
/* .packet = */ pt_pkt_decode_tsc,
/* .decode = */ pt_qry_decode_tsc,
/* .header = */ pt_qry_header_tsc,
/* .flags = */ pdff_timing
};
const struct pt_decoder_function pt_decode_cbr = {
/* .packet = */ pt_pkt_decode_cbr,
/* .decode = */ pt_qry_decode_cbr,
/* .header = */ pt_qry_header_cbr,
/* .flags = */ pdff_timing | pdff_event
};
const struct pt_decoder_function pt_decode_tma = {
/* .packet = */ pt_pkt_decode_tma,
/* .decode = */ pt_qry_decode_tma,
/* .header = */ pt_qry_decode_tma,
/* .flags = */ pdff_timing
};
const struct pt_decoder_function pt_decode_mtc = {
/* .packet = */ pt_pkt_decode_mtc,
/* .decode = */ pt_qry_decode_mtc,
/* .header = */ pt_qry_decode_mtc,
/* .flags = */ pdff_timing
};
const struct pt_decoder_function pt_decode_cyc = {
/* .packet = */ pt_pkt_decode_cyc,
/* .decode = */ pt_qry_decode_cyc,
/* .header = */ pt_qry_decode_cyc,
/* .flags = */ pdff_timing
};
const struct pt_decoder_function pt_decode_stop = {
/* .packet = */ pt_pkt_decode_stop,
/* .decode = */ pt_qry_decode_stop,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_vmcs = {
/* .packet = */ pt_pkt_decode_vmcs,
/* .decode = */ pt_qry_decode_vmcs,
/* .header = */ pt_qry_header_vmcs,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_mnt = {
/* .packet = */ pt_pkt_decode_mnt,
/* .decode = */ pt_qry_decode_mnt,
/* .header = */ pt_qry_header_mnt,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_exstop = {
/* .packet = */ pt_pkt_decode_exstop,
/* .decode = */ pt_qry_decode_exstop,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_mwait = {
/* .packet = */ pt_pkt_decode_mwait,
/* .decode = */ pt_qry_decode_mwait,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_pwre = {
/* .packet = */ pt_pkt_decode_pwre,
/* .decode = */ pt_qry_decode_pwre,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_pwrx = {
/* .packet = */ pt_pkt_decode_pwrx,
/* .decode = */ pt_qry_decode_pwrx,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
const struct pt_decoder_function pt_decode_ptw = {
/* .packet = */ pt_pkt_decode_ptw,
/* .decode = */ pt_qry_decode_ptw,
/* .header = */ NULL,
/* .flags = */ pdff_event
};
int pt_df_fetch(const struct pt_decoder_function **dfun, const uint8_t *pos,
const struct pt_config *config)
{
const uint8_t *begin, *end;
uint8_t opc, ext, ext2;
if (!dfun || !config)
return -pte_internal;
/* Clear the decode function in case of errors. */
*dfun = NULL;
begin = config->begin;
end = config->end;
if (!pos || (pos < begin) || (end < pos))
return -pte_nosync;
if (pos == end)
return -pte_eos;
opc = *pos++;
switch (opc) {
default:
/* Check opcodes that require masking. */
if ((opc & pt_opm_tnt_8) == pt_opc_tnt_8) {
*dfun = &pt_decode_tnt_8;
return 0;
}
if ((opc & pt_opm_cyc) == pt_opc_cyc) {
*dfun = &pt_decode_cyc;
return 0;
}
if ((opc & pt_opm_tip) == pt_opc_tip) {
*dfun = &pt_decode_tip;
return 0;
}
if ((opc & pt_opm_fup) == pt_opc_fup) {
*dfun = &pt_decode_fup;
return 0;
}
if ((opc & pt_opm_tip) == pt_opc_tip_pge) {
*dfun = &pt_decode_tip_pge;
return 0;
}
if ((opc & pt_opm_tip) == pt_opc_tip_pgd) {
*dfun = &pt_decode_tip_pgd;
return 0;
}
*dfun = &pt_decode_unknown;
return 0;
case pt_opc_pad:
*dfun = &pt_decode_pad;
return 0;
case pt_opc_mode:
*dfun = &pt_decode_mode;
return 0;
case pt_opc_tsc:
*dfun = &pt_decode_tsc;
return 0;
case pt_opc_mtc:
*dfun = &pt_decode_mtc;
return 0;
case pt_opc_ext:
if (pos == end)
return -pte_eos;
ext = *pos++;
switch (ext) {
default:
/* Check opcodes that require masking. */
if ((ext & pt_opm_ptw) == pt_ext_ptw) {
*dfun = &pt_decode_ptw;
return 0;
}
*dfun = &pt_decode_unknown;
return 0;
case pt_ext_psb:
*dfun = &pt_decode_psb;
return 0;
case pt_ext_ovf:
*dfun = &pt_decode_ovf;
return 0;
case pt_ext_tnt_64:
*dfun = &pt_decode_tnt_64;
return 0;
case pt_ext_psbend:
*dfun = &pt_decode_psbend;
return 0;
case pt_ext_cbr:
*dfun = &pt_decode_cbr;
return 0;
case pt_ext_pip:
*dfun = &pt_decode_pip;
return 0;
case pt_ext_tma:
*dfun = &pt_decode_tma;
return 0;
case pt_ext_stop:
*dfun = &pt_decode_stop;
return 0;
case pt_ext_vmcs:
*dfun = &pt_decode_vmcs;
return 0;
case pt_ext_exstop:
case pt_ext_exstop_ip:
*dfun = &pt_decode_exstop;
return 0;
case pt_ext_mwait:
*dfun = &pt_decode_mwait;
return 0;
case pt_ext_pwre:
*dfun = &pt_decode_pwre;
return 0;
case pt_ext_pwrx:
*dfun = &pt_decode_pwrx;
return 0;
case pt_ext_ext2:
if (pos == end)
return -pte_eos;
ext2 = *pos++;
switch (ext2) {
default:
*dfun = &pt_decode_unknown;
return 0;
case pt_ext2_mnt:
*dfun = &pt_decode_mnt;
return 0;
}
}
}
}

View File

@ -0,0 +1,917 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "pt_encoder.h"
#include "pt_config.h"
#include "pt_opcodes.h"
#include <string.h>
#include <stdlib.h>
int pt_encoder_init(struct pt_encoder *encoder, const struct pt_config *config)
{
int errcode;
if (!encoder)
return -pte_invalid;
memset(encoder, 0, sizeof(*encoder));
errcode = pt_config_from_user(&encoder->config, config);
if (errcode < 0)
return errcode;
encoder->pos = encoder->config.begin;
return 0;
}
void pt_encoder_fini(struct pt_encoder *encoder)
{
(void) encoder;
/* Nothing to do. */
}
struct pt_encoder *pt_alloc_encoder(const struct pt_config *config)
{
struct pt_encoder *encoder;
int errcode;
encoder = malloc(sizeof(*encoder));
if (!encoder)
return NULL;
errcode = pt_encoder_init(encoder, config);
if (errcode < 0) {
free(encoder);
return NULL;
}
return encoder;
}
void pt_free_encoder(struct pt_encoder *encoder)
{
pt_encoder_fini(encoder);
free(encoder);
}
int pt_enc_sync_set(struct pt_encoder *encoder, uint64_t offset)
{
uint8_t *begin, *end, *pos;
if (!encoder)
return -pte_invalid;
begin = encoder->config.begin;
end = encoder->config.end;
pos = begin + offset;
if (end < pos || pos < begin)
return -pte_eos;
encoder->pos = pos;
return 0;
}
int pt_enc_get_offset(const struct pt_encoder *encoder, uint64_t *offset)
{
const uint8_t *raw, *begin;
if (!encoder || !offset)
return -pte_invalid;
/* The encoder is synchronized at all times. */
raw = encoder->pos;
if (!raw)
return -pte_internal;
begin = encoder->config.begin;
if (!begin)
return -pte_internal;
*offset = raw - begin;
return 0;
}
const struct pt_config *pt_enc_get_config(const struct pt_encoder *encoder)
{
if (!encoder)
return NULL;
return &encoder->config;
}
/* Check the remaining space.
*
* Returns zero if there are at least \@size bytes of free space available in
* \@encoder's Intel PT buffer.
*
* Returns -pte_eos if not enough space is available.
* Returns -pte_internal if \@encoder is NULL.
* Returns -pte_internal if \@encoder is not synchronized.
*/
static int pt_reserve(const struct pt_encoder *encoder, unsigned int size)
{
const uint8_t *begin, *end, *pos;
if (!encoder)
return -pte_internal;
/* The encoder is synchronized at all times. */
pos = encoder->pos;
if (!pos)
return -pte_internal;
begin = encoder->config.begin;
end = encoder->config.end;
pos += size;
if (pos < begin || end < pos)
return -pte_eos;
return 0;
}
/* Return the size of an IP payload based on its IP compression.
*
* Returns -pte_bad_packet if \@ipc is not a valid IP compression.
*/
static int pt_ipc_size(enum pt_ip_compression ipc)
{
switch (ipc) {
case pt_ipc_suppressed:
return 0;
case pt_ipc_update_16:
return pt_pl_ip_upd16_size;
case pt_ipc_update_32:
return pt_pl_ip_upd32_size;
case pt_ipc_update_48:
return pt_pl_ip_upd48_size;
case pt_ipc_sext_48:
return pt_pl_ip_sext48_size;
case pt_ipc_full:
return pt_pl_ip_full_size;
}
return -pte_invalid;
}
/* Encode an integer value.
*
* Writes the \@size least signifficant bytes of \@value starting from \@pos.
*
* The caller needs to ensure that there is enough space available.
*
* Returns the updated position.
*/
static uint8_t *pt_encode_int(uint8_t *pos, uint64_t val, int size)
{
for (; size; --size, val >>= 8)
*pos++ = (uint8_t) val;
return pos;
}
/* Encode an IP packet.
*
* Write an IP packet with opcode \@opc and payload from \@packet if there is
* enough space in \@encoder's Intel PT buffer.
*
* Returns the number of bytes written on success.
*
* Returns -pte_eos if there is not enough space.
* Returns -pte_internal if \@encoder or \@packet is NULL.
* Returns -pte_invalid if \@packet.ipc is not valid.
*/
static int pt_encode_ip(struct pt_encoder *encoder, enum pt_opcode op,
const struct pt_packet_ip *packet)
{
uint8_t *pos;
uint8_t opc, ipc;
int size, errcode;
if (!encoder || !packet)
return pte_internal;
size = pt_ipc_size(packet->ipc);
if (size < 0)
return size;
errcode = pt_reserve(encoder, /* opc size = */ 1 + size);
if (errcode < 0)
return errcode;
/* We already checked the ipc in pt_ipc_size(). */
ipc = (uint8_t) (packet->ipc << pt_opm_ipc_shr);
opc = (uint8_t) op;
pos = encoder->pos;
*pos++ = opc | ipc;
encoder->pos = pt_encode_int(pos, packet->ip, size);
return /* opc size = */ 1 + size;
}
int pt_enc_next(struct pt_encoder *encoder, const struct pt_packet *packet)
{
uint8_t *pos, *begin;
int errcode;
if (!encoder || !packet)
return -pte_invalid;
pos = begin = encoder->pos;
switch (packet->type) {
case ppt_pad:
errcode = pt_reserve(encoder, ptps_pad);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_pad;
encoder->pos = pos;
return (int) (pos - begin);
case ppt_psb: {
uint64_t psb;
errcode = pt_reserve(encoder, ptps_psb);
if (errcode < 0)
return errcode;
psb = ((uint64_t) pt_psb_hilo << 48 |
(uint64_t) pt_psb_hilo << 32 |
(uint64_t) pt_psb_hilo << 16 |
(uint64_t) pt_psb_hilo);
pos = pt_encode_int(pos, psb, 8);
pos = pt_encode_int(pos, psb, 8);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_psbend:
errcode = pt_reserve(encoder, ptps_psbend);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_psbend;
encoder->pos = pos;
return (int) (pos - begin);
case ppt_ovf:
errcode = pt_reserve(encoder, ptps_ovf);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_ovf;
encoder->pos = pos;
return (int) (pos - begin);
case ppt_fup:
return pt_encode_ip(encoder, pt_opc_fup, &packet->payload.ip);
case ppt_tip:
return pt_encode_ip(encoder, pt_opc_tip, &packet->payload.ip);
case ppt_tip_pge:
return pt_encode_ip(encoder, pt_opc_tip_pge,
&packet->payload.ip);
case ppt_tip_pgd:
return pt_encode_ip(encoder, pt_opc_tip_pgd,
&packet->payload.ip);
case ppt_tnt_8: {
uint8_t opc, stop;
if (packet->payload.tnt.bit_size >= 7)
return -pte_bad_packet;
errcode = pt_reserve(encoder, ptps_tnt_8);
if (errcode < 0)
return errcode;
stop = packet->payload.tnt.bit_size + pt_opm_tnt_8_shr;
opc = (uint8_t)
(packet->payload.tnt.payload << pt_opm_tnt_8_shr);
*pos++ = (uint8_t) (opc | (1u << stop));
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_tnt_64: {
uint64_t tnt, stop;
errcode = pt_reserve(encoder, ptps_tnt_64);
if (errcode < 0)
return errcode;
if (packet->payload.tnt.bit_size >= pt_pl_tnt_64_bits)
return -pte_invalid;
stop = 1ull << packet->payload.tnt.bit_size;
tnt = packet->payload.tnt.payload;
if (tnt & ~(stop - 1))
return -pte_invalid;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_tnt_64;
pos = pt_encode_int(pos, tnt | stop, pt_pl_tnt_64_size);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_mode: {
uint8_t mode;
errcode = pt_reserve(encoder, ptps_mode);
if (errcode < 0)
return errcode;
switch (packet->payload.mode.leaf) {
default:
return -pte_bad_packet;
case pt_mol_exec:
mode = pt_mol_exec;
if (packet->payload.mode.bits.exec.csl)
mode |= pt_mob_exec_csl;
if (packet->payload.mode.bits.exec.csd)
mode |= pt_mob_exec_csd;
break;
case pt_mol_tsx:
mode = pt_mol_tsx;
if (packet->payload.mode.bits.tsx.intx)
mode |= pt_mob_tsx_intx;
if (packet->payload.mode.bits.tsx.abrt)
mode |= pt_mob_tsx_abrt;
break;
}
*pos++ = pt_opc_mode;
*pos++ = mode;
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_pip: {
uint64_t cr3;
errcode = pt_reserve(encoder, ptps_pip);
if (errcode < 0)
return errcode;
cr3 = packet->payload.pip.cr3;
cr3 >>= pt_pl_pip_shl;
cr3 <<= pt_pl_pip_shr;
if (packet->payload.pip.nr)
cr3 |= (uint64_t) pt_pl_pip_nr;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_pip;
pos = pt_encode_int(pos, cr3, pt_pl_pip_size);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_tsc:
errcode = pt_reserve(encoder, ptps_tsc);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_tsc;
pos = pt_encode_int(pos, packet->payload.tsc.tsc,
pt_pl_tsc_size);
encoder->pos = pos;
return (int) (pos - begin);
case ppt_cbr:
errcode = pt_reserve(encoder, ptps_cbr);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_cbr;
*pos++ = packet->payload.cbr.ratio;
*pos++ = 0;
encoder->pos = pos;
return (int) (pos - begin);
case ppt_tma: {
uint16_t ctc, fc;
errcode = pt_reserve(encoder, ptps_tma);
if (errcode < 0)
return errcode;
ctc = packet->payload.tma.ctc;
fc = packet->payload.tma.fc;
if (fc & ~pt_pl_tma_fc_mask)
return -pte_bad_packet;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_tma;
pos = pt_encode_int(pos, ctc, pt_pl_tma_ctc_size);
*pos++ = 0;
pos = pt_encode_int(pos, fc, pt_pl_tma_fc_size);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_mtc:
errcode = pt_reserve(encoder, ptps_mtc);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_mtc;
*pos++ = packet->payload.mtc.ctc;
encoder->pos = pos;
return (int) (pos - begin);
case ppt_cyc: {
uint8_t byte[pt_pl_cyc_max_size], index, end;
uint64_t ctc;
ctc = (uint8_t) packet->payload.cyc.value;
ctc <<= pt_opm_cyc_shr;
byte[0] = pt_opc_cyc;
byte[0] |= (uint8_t) ctc;
ctc = packet->payload.cyc.value;
ctc >>= (8 - pt_opm_cyc_shr);
if (ctc)
byte[0] |= pt_opm_cyc_ext;
for (end = 1; ctc; ++end) {
/* Check if the CYC payload is too big. */
if (pt_pl_cyc_max_size <= end)
return -pte_bad_packet;
ctc <<= pt_opm_cycx_shr;
byte[end] = (uint8_t) ctc;
ctc >>= 8;
if (ctc)
byte[end] |= pt_opm_cycx_ext;
}
errcode = pt_reserve(encoder, end);
if (errcode < 0)
return errcode;
for (index = 0; index < end; ++index)
*pos++ = byte[index];
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_stop:
errcode = pt_reserve(encoder, ptps_stop);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_stop;
encoder->pos = pos;
return (int) (pos - begin);
case ppt_vmcs:
errcode = pt_reserve(encoder, ptps_vmcs);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_vmcs;
pos = pt_encode_int(pos,
packet->payload.vmcs.base >> pt_pl_vmcs_shl,
pt_pl_vmcs_size);
encoder->pos = pos;
return (int) (pos - begin);
case ppt_mnt:
errcode = pt_reserve(encoder, ptps_mnt);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_ext2;
*pos++ = pt_ext2_mnt;
pos = pt_encode_int(pos, packet->payload.mnt.payload,
pt_pl_mnt_size);
encoder->pos = pos;
return (int) (pos - begin);
case ppt_exstop: {
uint8_t ext;
errcode = pt_reserve(encoder, ptps_exstop);
if (errcode < 0)
return errcode;
ext = packet->payload.exstop.ip ?
pt_ext_exstop_ip : pt_ext_exstop;
*pos++ = pt_opc_ext;
*pos++ = ext;
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_mwait:
errcode = pt_reserve(encoder, ptps_mwait);
if (errcode < 0)
return errcode;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_mwait;
pos = pt_encode_int(pos, packet->payload.mwait.hints,
pt_pl_mwait_hints_size);
pos = pt_encode_int(pos, packet->payload.mwait.ext,
pt_pl_mwait_ext_size);
encoder->pos = pos;
return (int) (pos - begin);
case ppt_pwre: {
uint64_t payload;
errcode = pt_reserve(encoder, ptps_pwre);
if (errcode < 0)
return errcode;
payload = 0ull;
payload |= ((uint64_t) packet->payload.pwre.state <<
pt_pl_pwre_state_shr) &
(uint64_t) pt_pl_pwre_state_mask;
payload |= ((uint64_t) packet->payload.pwre.sub_state <<
pt_pl_pwre_sub_state_shr) &
(uint64_t) pt_pl_pwre_sub_state_mask;
if (packet->payload.pwre.hw)
payload |= (uint64_t) pt_pl_pwre_hw_mask;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_pwre;
pos = pt_encode_int(pos, payload, pt_pl_pwre_size);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_pwrx: {
uint64_t payload;
errcode = pt_reserve(encoder, ptps_pwrx);
if (errcode < 0)
return errcode;
payload = 0ull;
payload |= ((uint64_t) packet->payload.pwrx.last <<
pt_pl_pwrx_last_shr) &
(uint64_t) pt_pl_pwrx_last_mask;
payload |= ((uint64_t) packet->payload.pwrx.deepest <<
pt_pl_pwrx_deepest_shr) &
(uint64_t) pt_pl_pwrx_deepest_mask;
if (packet->payload.pwrx.interrupt)
payload |= (uint64_t) pt_pl_pwrx_wr_int;
if (packet->payload.pwrx.store)
payload |= (uint64_t) pt_pl_pwrx_wr_store;
if (packet->payload.pwrx.autonomous)
payload |= (uint64_t) pt_pl_pwrx_wr_hw;
*pos++ = pt_opc_ext;
*pos++ = pt_ext_pwrx;
pos = pt_encode_int(pos, payload, pt_pl_pwrx_size);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_ptw: {
uint8_t plc, ext;
int size;
plc = packet->payload.ptw.plc;
size = pt_ptw_size(plc);
if (size < 0)
return size;
errcode = pt_reserve(encoder, pt_opcs_ptw + size);
if (errcode < 0)
return errcode;
ext = pt_ext_ptw;
ext |= plc << pt_opm_ptw_pb_shr;
if (packet->payload.ptw.ip)
ext |= (uint8_t) pt_opm_ptw_ip;
*pos++ = pt_opc_ext;
*pos++ = ext;
pos = pt_encode_int(pos, packet->payload.ptw.payload, size);
encoder->pos = pos;
return (int) (pos - begin);
}
case ppt_unknown:
case ppt_invalid:
return -pte_bad_opc;
}
return -pte_bad_opc;
}
int pt_encode_pad(struct pt_encoder *encoder)
{
struct pt_packet packet;
packet.type = ppt_pad;
return pt_enc_next(encoder, &packet);
}
int pt_encode_psb(struct pt_encoder *encoder)
{
struct pt_packet packet;
packet.type = ppt_psb;
return pt_enc_next(encoder, &packet);
}
int pt_encode_psbend(struct pt_encoder *encoder)
{
struct pt_packet packet;
packet.type = ppt_psbend;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tip(struct pt_encoder *encoder, uint64_t ip,
enum pt_ip_compression ipc)
{
struct pt_packet packet;
packet.type = ppt_tip;
packet.payload.ip.ip = ip;
packet.payload.ip.ipc = ipc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tnt_8(struct pt_encoder *encoder, uint8_t tnt, int size)
{
struct pt_packet packet;
packet.type = ppt_tnt_8;
packet.payload.tnt.bit_size = (uint8_t) size;
packet.payload.tnt.payload = tnt;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tnt_64(struct pt_encoder *encoder, uint64_t tnt, int size)
{
struct pt_packet packet;
packet.type = ppt_tnt_64;
packet.payload.tnt.bit_size = (uint8_t) size;
packet.payload.tnt.payload = tnt;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tip_pge(struct pt_encoder *encoder, uint64_t ip,
enum pt_ip_compression ipc)
{
struct pt_packet packet;
packet.type = ppt_tip_pge;
packet.payload.ip.ip = ip;
packet.payload.ip.ipc = ipc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tip_pgd(struct pt_encoder *encoder, uint64_t ip,
enum pt_ip_compression ipc)
{
struct pt_packet packet;
packet.type = ppt_tip_pgd;
packet.payload.ip.ip = ip;
packet.payload.ip.ipc = ipc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_fup(struct pt_encoder *encoder, uint64_t ip,
enum pt_ip_compression ipc)
{
struct pt_packet packet;
packet.type = ppt_fup;
packet.payload.ip.ip = ip;
packet.payload.ip.ipc = ipc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_pip(struct pt_encoder *encoder, uint64_t cr3, uint8_t flags)
{
struct pt_packet packet;
packet.type = ppt_pip;
packet.payload.pip.cr3 = cr3;
packet.payload.pip.nr = (flags & pt_pl_pip_nr) != 0;
return pt_enc_next(encoder, &packet);
}
int pt_encode_ovf(struct pt_encoder *encoder)
{
struct pt_packet packet;
packet.type = ppt_ovf;
return pt_enc_next(encoder, &packet);
}
int pt_encode_mode_exec(struct pt_encoder *encoder, enum pt_exec_mode mode)
{
struct pt_packet packet;
packet.type = ppt_mode;
packet.payload.mode.leaf = pt_mol_exec;
packet.payload.mode.bits.exec = pt_set_exec_mode(mode);
return pt_enc_next(encoder, &packet);
}
int pt_encode_mode_tsx(struct pt_encoder *encoder, uint8_t bits)
{
struct pt_packet packet;
packet.type = ppt_mode;
packet.payload.mode.leaf = pt_mol_tsx;
if (bits & pt_mob_tsx_intx)
packet.payload.mode.bits.tsx.intx = 1;
else
packet.payload.mode.bits.tsx.intx = 0;
if (bits & pt_mob_tsx_abrt)
packet.payload.mode.bits.tsx.abrt = 1;
else
packet.payload.mode.bits.tsx.abrt = 0;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tsc(struct pt_encoder *encoder, uint64_t tsc)
{
struct pt_packet packet;
packet.type = ppt_tsc;
packet.payload.tsc.tsc = tsc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_cbr(struct pt_encoder *encoder, uint8_t cbr)
{
struct pt_packet packet;
packet.type = ppt_cbr;
packet.payload.cbr.ratio = cbr;
return pt_enc_next(encoder, &packet);
}
int pt_encode_tma(struct pt_encoder *encoder, uint16_t ctc, uint16_t fc)
{
struct pt_packet packet;
packet.type = ppt_tma;
packet.payload.tma.ctc = ctc;
packet.payload.tma.fc = fc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_mtc(struct pt_encoder *encoder, uint8_t ctc)
{
struct pt_packet packet;
packet.type = ppt_mtc;
packet.payload.mtc.ctc = ctc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_cyc(struct pt_encoder *encoder, uint32_t ctc)
{
struct pt_packet packet;
packet.type = ppt_cyc;
packet.payload.cyc.value = ctc;
return pt_enc_next(encoder, &packet);
}
int pt_encode_stop(struct pt_encoder *encoder)
{
struct pt_packet packet;
packet.type = ppt_stop;
return pt_enc_next(encoder, &packet);
}
int pt_encode_vmcs(struct pt_encoder *encoder, uint64_t payload)
{
struct pt_packet packet;
packet.type = ppt_vmcs;
packet.payload.vmcs.base = payload;
return pt_enc_next(encoder, &packet);
}
int pt_encode_mnt(struct pt_encoder *encoder, uint64_t payload)
{
struct pt_packet packet;
packet.type = ppt_mnt;
packet.payload.mnt.payload = payload;
return pt_enc_next(encoder, &packet);
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "intel-pt.h"
const char *pt_errstr(enum pt_error_code errcode)
{
switch (errcode) {
case pte_ok:
return "OK";
case pte_internal:
return "internal error";
case pte_invalid:
return "invalid argument";
case pte_nosync:
return "decoder out of sync";
case pte_bad_opc:
return "unknown opcode";
case pte_bad_packet:
return "unknown packet";
case pte_bad_context:
return "unexpected packet context";
case pte_eos:
return "reached end of trace stream";
case pte_bad_query:
return "trace stream does not match query";
case pte_nomem:
return "out of memory";
case pte_bad_config:
return "bad configuration";
case pte_noip:
return "no ip";
case pte_ip_suppressed:
return "ip has been suppressed";
case pte_nomap:
return "no memory mapped at this address";
case pte_bad_insn:
return "unknown instruction";
case pte_no_time:
return "no timing information";
case pte_no_cbr:
return "no core:bus ratio";
case pte_bad_image:
return "bad image";
case pte_bad_lock:
return "locking error";
case pte_not_supported:
return "not supported";
case pte_retstack_empty:
return "compressed return without call";
case pte_bad_retcomp:
return "bad compressed return";
case pte_bad_status_update:
return "bad status update";
case pte_no_enable:
return "expected tracing enabled event";
case pte_event_ignored:
return "event ignored";
case pte_overflow:
return "overflow";
case pte_bad_file:
return "bad file";
case pte_bad_cpu:
return "unknown cpu";
}
/* Should not reach here. */
return "internal error.";
}

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_event_queue.h"
#include <string.h>
static inline uint8_t pt_evq_inc(uint8_t idx)
{
idx += 1;
idx %= evq_max;
return idx;
}
static struct pt_event *pt_event_init(struct pt_event *event)
{
if (event)
memset(event, 0, sizeof(*event));
return event;
}
void pt_evq_init(struct pt_event_queue *evq)
{
if (!evq)
return;
memset(evq, 0, sizeof(*evq));
}
struct pt_event *pt_evq_standalone(struct pt_event_queue *evq)
{
if (!evq)
return NULL;
return pt_event_init(&evq->standalone);
}
struct pt_event *pt_evq_enqueue(struct pt_event_queue *evq,
enum pt_event_binding evb)
{
uint8_t begin, end, gap, idx;
if (!evq)
return NULL;
if (evb_max <= evb)
return NULL;
begin = evq->begin[evb];
idx = evq->end[evb];
if (evq_max <= begin)
return NULL;
if (evq_max <= idx)
return NULL;
end = pt_evq_inc(idx);
gap = pt_evq_inc(end);
/* Leave a gap so we don't overwrite the last dequeued event. */
if (begin == gap)
return NULL;
evq->end[evb] = end;
return pt_event_init(&evq->queue[evb][idx]);
}
struct pt_event *pt_evq_dequeue(struct pt_event_queue *evq,
enum pt_event_binding evb)
{
uint8_t begin, end;
if (!evq)
return NULL;
if (evb_max <= evb)
return NULL;
begin = evq->begin[evb];
end = evq->end[evb];
if (evq_max <= begin)
return NULL;
if (evq_max <= end)
return NULL;
if (begin == end)
return NULL;
evq->begin[evb] = pt_evq_inc(begin);
return &evq->queue[evb][begin];
}
int pt_evq_clear(struct pt_event_queue *evq, enum pt_event_binding evb)
{
if (!evq)
return -pte_internal;
if (evb_max <= evb)
return -pte_internal;
evq->begin[evb] = 0;
evq->end[evb] = 0;
return 0;
}
int pt_evq_empty(const struct pt_event_queue *evq, enum pt_event_binding evb)
{
uint8_t begin, end;
if (!evq)
return -pte_internal;
if (evb_max <= evb)
return -pte_internal;
begin = evq->begin[evb];
end = evq->end[evb];
if (evq_max <= begin)
return -pte_internal;
if (evq_max <= end)
return -pte_internal;
return begin == end;
}
int pt_evq_pending(const struct pt_event_queue *evq, enum pt_event_binding evb)
{
int errcode;
errcode = pt_evq_empty(evq, evb);
if (errcode < 0)
return errcode;
return !errcode;
}
struct pt_event *pt_evq_find(struct pt_event_queue *evq,
enum pt_event_binding evb,
enum pt_event_type evt)
{
uint8_t begin, end;
if (!evq)
return NULL;
if (evb_max <= evb)
return NULL;
begin = evq->begin[evb];
end = evq->end[evb];
if (evq_max <= begin)
return NULL;
if (evq_max <= end)
return NULL;
for (; begin != end; begin = pt_evq_inc(begin)) {
struct pt_event *ev;
ev = &evq->queue[evb][begin];
if (ev->type == evt)
return ev;
}
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,718 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_image.h"
#include "pt_section.h"
#include "pt_asid.h"
#include "pt_image_section_cache.h"
#include <stdlib.h>
#include <string.h>
static char *dupstr(const char *str)
{
char *dup;
size_t len;
if (!str)
return NULL;
len = strlen(str);
dup = malloc(len + 1);
if (!dup)
return NULL;
return strcpy(dup, str);
}
static struct pt_section_list *pt_mk_section_list(struct pt_section *section,
const struct pt_asid *asid,
uint64_t vaddr,
uint64_t offset,
uint64_t size, int isid)
{
struct pt_section_list *list;
int errcode;
list = malloc(sizeof(*list));
if (!list)
return NULL;
memset(list, 0, sizeof(*list));
errcode = pt_section_get(section);
if (errcode < 0)
goto out_mem;
pt_msec_init(&list->section, section, asid, vaddr, offset, size);
list->isid = isid;
return list;
out_mem:
free(list);
return NULL;
}
static void pt_section_list_free(struct pt_section_list *list)
{
if (!list)
return;
pt_section_put(list->section.section);
pt_msec_fini(&list->section);
free(list);
}
static void pt_section_list_free_tail(struct pt_section_list *list)
{
while (list) {
struct pt_section_list *trash;
trash = list;
list = list->next;
pt_section_list_free(trash);
}
}
void pt_image_init(struct pt_image *image, const char *name)
{
if (!image)
return;
memset(image, 0, sizeof(*image));
image->name = dupstr(name);
}
void pt_image_fini(struct pt_image *image)
{
if (!image)
return;
pt_section_list_free_tail(image->sections);
free(image->name);
memset(image, 0, sizeof(*image));
}
struct pt_image *pt_image_alloc(const char *name)
{
struct pt_image *image;
image = malloc(sizeof(*image));
if (image)
pt_image_init(image, name);
return image;
}
void pt_image_free(struct pt_image *image)
{
pt_image_fini(image);
free(image);
}
const char *pt_image_name(const struct pt_image *image)
{
if (!image)
return NULL;
return image->name;
}
int pt_image_add(struct pt_image *image, struct pt_section *section,
const struct pt_asid *asid, uint64_t vaddr, int isid)
{
struct pt_section_list **list, *next, *removed, *new;
uint64_t size, begin, end;
int errcode;
if (!image || !section)
return -pte_internal;
size = pt_section_size(section);
begin = vaddr;
end = begin + size;
next = pt_mk_section_list(section, asid, begin, 0ull, size, isid);
if (!next)
return -pte_nomem;
removed = NULL;
errcode = 0;
/* Check for overlaps while we move to the end of the list. */
list = &(image->sections);
while (*list) {
const struct pt_mapped_section *msec;
const struct pt_asid *masid;
struct pt_section_list *current;
struct pt_section *lsec;
uint64_t lbegin, lend, loff;
current = *list;
msec = &current->section;
masid = pt_msec_asid(msec);
errcode = pt_asid_match(masid, asid);
if (errcode < 0)
break;
if (!errcode) {
list = &((*list)->next);
continue;
}
lbegin = pt_msec_begin(msec);
lend = pt_msec_end(msec);
if ((end <= lbegin) || (lend <= begin)) {
list = &((*list)->next);
continue;
}
/* The new section overlaps with @msec's section. */
lsec = pt_msec_section(msec);
loff = pt_msec_offset(msec);
/* We remove @msec and insert new sections for the remaining
* parts, if any. Those new sections are not mapped initially
* and need to be added to the end of the section list.
*/
*list = current->next;
/* Keep a list of removed sections so we can re-add them in case
* of errors.
*/
current->next = removed;
removed = current;
/* Add a section covering the remaining bytes at the front. */
if (lbegin < begin) {
new = pt_mk_section_list(lsec, masid, lbegin, loff,
begin - lbegin, current->isid);
if (!new) {
errcode = -pte_nomem;
break;
}
new->next = next;
next = new;
}
/* Add a section covering the remaining bytes at the back. */
if (end < lend) {
new = pt_mk_section_list(lsec, masid, end,
loff + (end - lbegin),
lend - end, current->isid);
if (!new) {
errcode = -pte_nomem;
break;
}
new->next = next;
next = new;
}
}
if (errcode < 0) {
pt_section_list_free_tail(next);
/* Re-add removed sections to the tail of the section list. */
for (; *list; list = &((*list)->next))
;
*list = removed;
return errcode;
}
pt_section_list_free_tail(removed);
*list = next;
return 0;
}
int pt_image_remove(struct pt_image *image, struct pt_section *section,
const struct pt_asid *asid, uint64_t vaddr)
{
struct pt_section_list **list;
if (!image || !section)
return -pte_internal;
for (list = &image->sections; *list; list = &((*list)->next)) {
struct pt_mapped_section *msec;
const struct pt_section *sec;
const struct pt_asid *masid;
struct pt_section_list *trash;
uint64_t begin;
int errcode;
trash = *list;
msec = &trash->section;
masid = pt_msec_asid(msec);
errcode = pt_asid_match(masid, asid);
if (errcode < 0)
return errcode;
if (!errcode)
continue;
begin = pt_msec_begin(msec);
sec = pt_msec_section(msec);
if (sec == section && begin == vaddr) {
*list = trash->next;
pt_section_list_free(trash);
return 0;
}
}
return -pte_bad_image;
}
int pt_image_add_file(struct pt_image *image, const char *filename,
uint64_t offset, uint64_t size,
const struct pt_asid *uasid, uint64_t vaddr)
{
struct pt_section *section;
struct pt_asid asid;
int errcode;
if (!image || !filename)
return -pte_invalid;
errcode = pt_asid_from_user(&asid, uasid);
if (errcode < 0)
return errcode;
section = pt_mk_section(filename, offset, size);
if (!section)
return -pte_invalid;
errcode = pt_image_add(image, section, &asid, vaddr, 0);
if (errcode < 0) {
(void) pt_section_put(section);
return errcode;
}
/* The image list got its own reference; let's drop ours. */
errcode = pt_section_put(section);
if (errcode < 0)
return errcode;
return 0;
}
int pt_image_copy(struct pt_image *image, const struct pt_image *src)
{
struct pt_section_list *list;
int ignored;
if (!image || !src)
return -pte_invalid;
/* There is nothing to do if we copy an image to itself.
*
* Besides, pt_image_add() may move sections around, which would
* interfere with our section iteration.
*/
if (image == src)
return 0;
ignored = 0;
for (list = src->sections; list; list = list->next) {
int errcode;
errcode = pt_image_add(image, list->section.section,
&list->section.asid,
list->section.vaddr,
list->isid);
if (errcode < 0)
ignored += 1;
}
return ignored;
}
int pt_image_remove_by_filename(struct pt_image *image, const char *filename,
const struct pt_asid *uasid)
{
struct pt_section_list **list;
struct pt_asid asid;
int errcode, removed;
if (!image || !filename)
return -pte_invalid;
errcode = pt_asid_from_user(&asid, uasid);
if (errcode < 0)
return errcode;
removed = 0;
for (list = &image->sections; *list;) {
struct pt_mapped_section *msec;
const struct pt_section *sec;
const struct pt_asid *masid;
struct pt_section_list *trash;
const char *tname;
trash = *list;
msec = &trash->section;
masid = pt_msec_asid(msec);
errcode = pt_asid_match(masid, &asid);
if (errcode < 0)
return errcode;
if (!errcode) {
list = &trash->next;
continue;
}
sec = pt_msec_section(msec);
tname = pt_section_filename(sec);
if (tname && (strcmp(tname, filename) == 0)) {
*list = trash->next;
pt_section_list_free(trash);
removed += 1;
} else
list = &trash->next;
}
return removed;
}
int pt_image_remove_by_asid(struct pt_image *image,
const struct pt_asid *uasid)
{
struct pt_section_list **list;
struct pt_asid asid;
int errcode, removed;
if (!image)
return -pte_invalid;
errcode = pt_asid_from_user(&asid, uasid);
if (errcode < 0)
return errcode;
removed = 0;
for (list = &image->sections; *list;) {
struct pt_mapped_section *msec;
const struct pt_asid *masid;
struct pt_section_list *trash;
trash = *list;
msec = &trash->section;
masid = pt_msec_asid(msec);
errcode = pt_asid_match(masid, &asid);
if (errcode < 0)
return errcode;
if (!errcode) {
list = &trash->next;
continue;
}
*list = trash->next;
pt_section_list_free(trash);
removed += 1;
}
return removed;
}
int pt_image_set_callback(struct pt_image *image,
read_memory_callback_t *callback, void *context)
{
if (!image)
return -pte_invalid;
image->readmem.callback = callback;
image->readmem.context = context;
return 0;
}
static int pt_image_read_callback(struct pt_image *image, int *isid,
uint8_t *buffer, uint16_t size,
const struct pt_asid *asid, uint64_t addr)
{
read_memory_callback_t *callback;
if (!image || !isid)
return -pte_internal;
callback = image->readmem.callback;
if (!callback)
return -pte_nomap;
*isid = 0;
return callback(buffer, size, asid, addr, image->readmem.context);
}
/* Check whether a mapped section contains an address.
*
* Returns zero if @msec contains @vaddr.
* Returns a negative error code otherwise.
* Returns -pte_nomap if @msec does not contain @vaddr.
*/
static inline int pt_image_check_msec(const struct pt_mapped_section *msec,
const struct pt_asid *asid,
uint64_t vaddr)
{
const struct pt_asid *masid;
uint64_t begin, end;
int errcode;
if (!msec)
return -pte_internal;
begin = pt_msec_begin(msec);
end = pt_msec_end(msec);
if (vaddr < begin || end <= vaddr)
return -pte_nomap;
masid = pt_msec_asid(msec);
errcode = pt_asid_match(masid, asid);
if (errcode <= 0) {
if (!errcode)
errcode = -pte_nomap;
return errcode;
}
return 0;
}
/* Find the section containing a given address in a given address space.
*
* On success, the found section is moved to the front of the section list.
* If caching is enabled, maps the section.
*
* Returns zero on success, a negative error code otherwise.
*/
static int pt_image_fetch_section(struct pt_image *image,
const struct pt_asid *asid, uint64_t vaddr)
{
struct pt_section_list **start, **list;
if (!image)
return -pte_internal;
start = &image->sections;
for (list = start; *list;) {
struct pt_mapped_section *msec;
struct pt_section_list *elem;
int errcode;
elem = *list;
msec = &elem->section;
errcode = pt_image_check_msec(msec, asid, vaddr);
if (errcode < 0) {
if (errcode != -pte_nomap)
return errcode;
list = &elem->next;
continue;
}
/* Move the section to the front if it isn't already. */
if (list != start) {
*list = elem->next;
elem->next = *start;
*start = elem;
}
return 0;
}
return -pte_nomap;
}
int pt_image_read(struct pt_image *image, int *isid, uint8_t *buffer,
uint16_t size, const struct pt_asid *asid, uint64_t addr)
{
struct pt_mapped_section *msec;
struct pt_section_list *slist;
struct pt_section *section;
int errcode, status;
if (!image || !isid)
return -pte_internal;
errcode = pt_image_fetch_section(image, asid, addr);
if (errcode < 0) {
if (errcode != -pte_nomap)
return errcode;
return pt_image_read_callback(image, isid, buffer, size, asid,
addr);
}
slist = image->sections;
if (!slist)
return -pte_internal;
*isid = slist->isid;
msec = &slist->section;
section = pt_msec_section(msec);
errcode = pt_section_map(section);
if (errcode < 0)
return errcode;
status = pt_msec_read(msec, buffer, size, addr);
errcode = pt_section_unmap(section);
if (errcode < 0)
return errcode;
if (status < 0) {
if (status != -pte_nomap)
return status;
return pt_image_read_callback(image, isid, buffer, size, asid,
addr);
}
return status;
}
int pt_image_add_cached(struct pt_image *image,
struct pt_image_section_cache *iscache, int isid,
const struct pt_asid *uasid)
{
struct pt_section *section;
struct pt_asid asid;
uint64_t vaddr;
int errcode, status;
if (!image || !iscache)
return -pte_invalid;
errcode = pt_iscache_lookup(iscache, &section, &vaddr, isid);
if (errcode < 0)
return errcode;
errcode = pt_asid_from_user(&asid, uasid);
if (errcode < 0)
return errcode;
status = pt_image_add(image, section, &asid, vaddr, isid);
/* We grab a reference when we add the section. Drop the one we
* obtained from cache lookup.
*/
errcode = pt_section_put(section);
if (errcode < 0)
return errcode;
return status;
}
int pt_image_find(struct pt_image *image, struct pt_mapped_section *usec,
const struct pt_asid *asid, uint64_t vaddr)
{
struct pt_mapped_section *msec;
struct pt_section_list *slist;
struct pt_section *section;
int errcode;
if (!image || !usec)
return -pte_internal;
errcode = pt_image_fetch_section(image, asid, vaddr);
if (errcode < 0)
return errcode;
slist = image->sections;
if (!slist)
return -pte_internal;
msec = &slist->section;
section = pt_msec_section(msec);
errcode = pt_section_get(section);
if (errcode < 0)
return errcode;
*usec = *msec;
return slist->isid;
}
int pt_image_validate(const struct pt_image *image,
const struct pt_mapped_section *usec, uint64_t vaddr,
int isid)
{
const struct pt_section_list *slist;
uint64_t begin, end;
int status;
if (!image || !usec)
return -pte_internal;
/* Check that @vaddr lies within @usec. */
begin = pt_msec_begin(usec);
end = pt_msec_end(usec);
if (vaddr < begin || end <= vaddr)
return -pte_nomap;
/* We assume that @usec is a copy of the top of our stack and accept
* sporadic validation fails if it isn't, e.g. because it has moved
* down.
*
* A failed validation requires decoders to re-fetch the section so it
* only results in a (relatively small) performance loss.
*/
slist = image->sections;
if (!slist)
return -pte_nomap;
if (slist->isid != isid)
return -pte_nomap;
status = memcmp(&slist->section, usec, sizeof(*usec));
if (status)
return -pte_nomap;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,372 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#include "pt_insn.h"
#include "pt_ild.h"
#include "pt_image.h"
#include "pt_compiler.h"
#include "intel-pt.h"
int pt_insn_changes_cpl(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
(void) insn;
if (!iext)
return 0;
switch (iext->iclass) {
default:
return 0;
case PTI_INST_INT:
case PTI_INST_INT3:
case PTI_INST_INT1:
case PTI_INST_INTO:
case PTI_INST_IRET:
case PTI_INST_SYSCALL:
case PTI_INST_SYSENTER:
case PTI_INST_SYSEXIT:
case PTI_INST_SYSRET:
return 1;
}
}
int pt_insn_changes_cr3(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
(void) insn;
if (!iext)
return 0;
switch (iext->iclass) {
default:
return 0;
case PTI_INST_MOV_CR3:
return 1;
}
}
int pt_insn_is_branch(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
(void) iext;
if (!insn)
return 0;
switch (insn->iclass) {
default:
return 0;
case ptic_call:
case ptic_return:
case ptic_jump:
case ptic_cond_jump:
case ptic_far_call:
case ptic_far_return:
case ptic_far_jump:
return 1;
}
}
int pt_insn_is_far_branch(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
(void) iext;
if (!insn)
return 0;
switch (insn->iclass) {
default:
return 0;
case ptic_far_call:
case ptic_far_return:
case ptic_far_jump:
return 1;
}
}
int pt_insn_binds_to_pip(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
if (!iext)
return 0;
switch (iext->iclass) {
default:
return pt_insn_is_far_branch(insn, iext);
case PTI_INST_MOV_CR3:
case PTI_INST_VMLAUNCH:
case PTI_INST_VMRESUME:
return 1;
}
}
int pt_insn_binds_to_vmcs(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
if (!iext)
return 0;
switch (iext->iclass) {
default:
return pt_insn_is_far_branch(insn, iext);
case PTI_INST_VMPTRLD:
case PTI_INST_VMLAUNCH:
case PTI_INST_VMRESUME:
return 1;
}
}
int pt_insn_is_ptwrite(const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
(void) iext;
if (!insn)
return 0;
switch (insn->iclass) {
default:
return 0;
case ptic_ptwrite:
return 1;
}
}
int pt_insn_next_ip(uint64_t *pip, const struct pt_insn *insn,
const struct pt_insn_ext *iext)
{
uint64_t ip;
if (!insn || !iext)
return -pte_internal;
ip = insn->ip + insn->size;
switch (insn->iclass) {
case ptic_ptwrite:
case ptic_other:
break;
case ptic_call:
case ptic_jump:
if (iext->variant.branch.is_direct) {
ip += iext->variant.branch.displacement;
break;
}
fallthrough;
default:
return -pte_bad_query;
case ptic_error:
return -pte_bad_insn;
}
if (pip)
*pip = ip;
return 0;
}
/* Retry decoding an instruction after a preceding decode error.
*
* Instruction length decode typically fails due to 'not enough
* bytes'.
*
* This may be caused by partial updates of text sections
* represented via new image sections overlapping the original
* text section's image section. We stop reading memory at the
* end of the section so we do not read the full instruction if
* parts of it have been overwritten by the update.
*
* Try to read the remaining bytes and decode the instruction again. If we
* succeed, set @insn->truncated to indicate that the instruction is truncated
* in @insn->isid.
*
* Returns zero on success, a negative error code otherwise.
* Returns -pte_bad_insn if the instruction could not be decoded.
*/
static int pt_insn_decode_retry(struct pt_insn *insn, struct pt_insn_ext *iext,
struct pt_image *image,
const struct pt_asid *asid)
{
int size, errcode, isid;
uint8_t isize, remaining;
if (!insn)
return -pte_internal;
isize = insn->size;
remaining = sizeof(insn->raw) - isize;
/* We failed for real if we already read the maximum number of bytes for
* an instruction.
*/
if (!remaining)
return -pte_bad_insn;
/* Read the remaining bytes from the image. */
size = pt_image_read(image, &isid, &insn->raw[isize], remaining, asid,
insn->ip + isize);
if (size <= 0) {
/* We should have gotten an error if we were not able to read at
* least one byte. Check this to guarantee termination.
*/
if (!size)
return -pte_internal;
/* Preserve the original error if there are no more bytes. */
if (size == -pte_nomap)
size = -pte_bad_insn;
return size;
}
/* Add the newly read bytes to the instruction's size. */
insn->size += (uint8_t) size;
/* Store the new size to avoid infinite recursion in case instruction
* decode fails after length decode, which would set @insn->size to the
* actual length.
*/
size = insn->size;
/* Try to decode the instruction again.
*
* If we fail again, we recursively retry again until we either fail to
* read more bytes or reach the maximum number of bytes for an
* instruction.
*/
errcode = pt_ild_decode(insn, iext);
if (errcode < 0) {
if (errcode != -pte_bad_insn)
return errcode;
/* If instruction length decode already determined the size,
* there's no point in reading more bytes.
*/
if (insn->size != (uint8_t) size)
return errcode;
return pt_insn_decode_retry(insn, iext, image, asid);
}
/* We succeeded this time, so the instruction crosses image section
* boundaries.
*
* This poses the question which isid to use for the instruction.
*
* To reconstruct exactly this instruction at a later time, we'd need to
* store all isids involved together with the number of bytes read for
* each isid. Since @insn already provides the exact bytes for this
* instruction, we assume that the isid will be used solely for source
* correlation. In this case, it should refer to the first byte of the
* instruction - as it already does.
*/
insn->truncated = 1;
return errcode;
}
int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
struct pt_image *image, const struct pt_asid *asid)
{
int size, errcode;
if (!insn)
return -pte_internal;
/* Read the memory at the current IP in the current address space. */
size = pt_image_read(image, &insn->isid, insn->raw, sizeof(insn->raw),
asid, insn->ip);
if (size < 0)
return size;
/* We initialize @insn->size to the maximal possible size. It will be
* set to the actual size during instruction decode.
*/
insn->size = (uint8_t) size;
errcode = pt_ild_decode(insn, iext);
if (errcode < 0) {
if (errcode != -pte_bad_insn)
return errcode;
/* If instruction length decode already determined the size,
* there's no point in reading more bytes.
*/
if (insn->size != (uint8_t) size)
return errcode;
return pt_insn_decode_retry(insn, iext, image, asid);
}
return errcode;
}
int pt_insn_range_is_contiguous(uint64_t begin, uint64_t end,
enum pt_exec_mode mode, struct pt_image *image,
const struct pt_asid *asid, size_t steps)
{
struct pt_insn_ext iext;
struct pt_insn insn;
memset(&insn, 0, sizeof(insn));
insn.mode = mode;
insn.ip = begin;
while (insn.ip != end) {
int errcode;
if (!steps--)
return 0;
errcode = pt_insn_decode(&insn, &iext, image, asid);
if (errcode < 0)
return errcode;
errcode = pt_insn_next_ip(&insn.ip, &insn, &iext);
if (errcode < 0)
return errcode;
}
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_last_ip.h"
#include "intel-pt.h"
void pt_last_ip_init(struct pt_last_ip *last_ip)
{
if (!last_ip)
return;
last_ip->ip = 0ull;
last_ip->have_ip = 0;
last_ip->suppressed = 0;
}
int pt_last_ip_query(uint64_t *ip, const struct pt_last_ip *last_ip)
{
if (!last_ip)
return -pte_internal;
if (!last_ip->have_ip) {
if (ip)
*ip = 0ull;
return -pte_noip;
}
if (last_ip->suppressed) {
if (ip)
*ip = 0ull;
return -pte_ip_suppressed;
}
if (ip)
*ip = last_ip->ip;
return 0;
}
/* Sign-extend a uint64_t value. */
static uint64_t sext(uint64_t val, uint8_t sign)
{
uint64_t signbit, mask;
signbit = 1ull << (sign - 1);
mask = ~0ull << sign;
return val & signbit ? val | mask : val & ~mask;
}
int pt_last_ip_update_ip(struct pt_last_ip *last_ip,
const struct pt_packet_ip *packet,
const struct pt_config *config)
{
(void) config;
if (!last_ip || !packet)
return -pte_internal;
switch (packet->ipc) {
case pt_ipc_suppressed:
last_ip->suppressed = 1;
return 0;
case pt_ipc_sext_48:
last_ip->ip = sext(packet->ip, 48);
last_ip->have_ip = 1;
last_ip->suppressed = 0;
return 0;
case pt_ipc_update_16:
last_ip->ip = (last_ip->ip & ~0xffffull)
| (packet->ip & 0xffffull);
last_ip->have_ip = 1;
last_ip->suppressed = 0;
return 0;
case pt_ipc_update_32:
last_ip->ip = (last_ip->ip & ~0xffffffffull)
| (packet->ip & 0xffffffffull);
last_ip->have_ip = 1;
last_ip->suppressed = 0;
return 0;
case pt_ipc_update_48:
last_ip->ip = (last_ip->ip & ~0xffffffffffffull)
| (packet->ip & 0xffffffffffffull);
last_ip->have_ip = 1;
last_ip->suppressed = 0;
return 0;
case pt_ipc_full:
last_ip->ip = packet->ip;
last_ip->have_ip = 1;
last_ip->suppressed = 0;
return 0;
}
return -pte_bad_packet;
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2017-2018, 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.
*/
#include "pt_msec_cache.h"
#include "pt_section.h"
#include "pt_image.h"
#include <string.h>
int pt_msec_cache_init(struct pt_msec_cache *cache)
{
if (!cache)
return -pte_internal;
memset(cache, 0, sizeof(*cache));
return 0;
}
void pt_msec_cache_fini(struct pt_msec_cache *cache)
{
if (!cache)
return;
(void) pt_msec_cache_invalidate(cache);
pt_msec_fini(&cache->msec);
}
int pt_msec_cache_invalidate(struct pt_msec_cache *cache)
{
struct pt_section *section;
int errcode;
if (!cache)
return -pte_internal;
section = pt_msec_section(&cache->msec);
if (!section)
return 0;
errcode = pt_section_unmap(section);
if (errcode < 0)
return errcode;
cache->msec.section = NULL;
return pt_section_put(section);
}
int pt_msec_cache_read(struct pt_msec_cache *cache,
const struct pt_mapped_section **pmsec,
struct pt_image *image, uint64_t vaddr)
{
struct pt_mapped_section *msec;
int isid, errcode;
if (!cache || !pmsec)
return -pte_internal;
msec = &cache->msec;
isid = cache->isid;
errcode = pt_image_validate(image, msec, vaddr, isid);
if (errcode < 0)
return errcode;
*pmsec = msec;
return isid;
}
int pt_msec_cache_fill(struct pt_msec_cache *cache,
const struct pt_mapped_section **pmsec,
struct pt_image *image, const struct pt_asid *asid,
uint64_t vaddr)
{
struct pt_mapped_section *msec;
struct pt_section *section;
int errcode, isid;
if (!cache || !pmsec)
return -pte_internal;
errcode = pt_msec_cache_invalidate(cache);
if (errcode < 0)
return errcode;
msec = &cache->msec;
isid = pt_image_find(image, msec, asid, vaddr);
if (isid < 0)
return isid;
section = pt_msec_section(msec);
errcode = pt_section_map(section);
if (errcode < 0) {
(void) pt_section_put(section);
msec->section = NULL;
return errcode;
}
*pmsec = msec;
cache->isid = isid;
return isid;
}

View File

@ -0,0 +1,573 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_packet.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
#include <limits.h>
static uint64_t pt_pkt_read_value(const uint8_t *pos, int size)
{
uint64_t val;
int idx;
for (val = 0, idx = 0; idx < size; ++idx) {
uint64_t byte = *pos++;
byte <<= (idx * 8);
val |= byte;
}
return val;
}
int pt_pkt_read_unknown(struct pt_packet *packet, const uint8_t *pos,
const struct pt_config *config)
{
int (*decode)(struct pt_packet_unknown *, const struct pt_config *,
const uint8_t *, void *);
int size;
if (!packet || !pos || !config)
return -pte_internal;
decode = config->decode.callback;
if (!decode)
return -pte_bad_opc;
/* Fill in some default values. */
packet->payload.unknown.packet = pos;
packet->payload.unknown.priv = NULL;
/* We accept a size of zero to allow the callback to modify the
* trace buffer and resume normal decoding.
*/
size = (*decode)(&packet->payload.unknown, config, pos,
config->decode.context);
if (size < 0)
return size;
if (size > UCHAR_MAX)
return -pte_invalid;
packet->type = ppt_unknown;
packet->size = (uint8_t) size;
if (config->end < pos + size)
return -pte_eos;
return size;
}
int pt_pkt_read_psb(const uint8_t *pos, const struct pt_config *config)
{
int count;
if (!pos || !config)
return -pte_internal;
if (config->end < pos + ptps_psb)
return -pte_eos;
pos += pt_opcs_psb;
for (count = 0; count < pt_psb_repeat_count; ++count) {
if (*pos++ != pt_psb_hi)
return -pte_bad_packet;
if (*pos++ != pt_psb_lo)
return -pte_bad_packet;
}
return ptps_psb;
}
static int pt_pkt_ip_size(enum pt_ip_compression ipc)
{
switch (ipc) {
case pt_ipc_suppressed:
return 0;
case pt_ipc_update_16:
return 2;
case pt_ipc_update_32:
return 4;
case pt_ipc_update_48:
case pt_ipc_sext_48:
return 6;
case pt_ipc_full:
return 8;
}
return -pte_bad_packet;
}
int pt_pkt_read_ip(struct pt_packet_ip *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint64_t ip;
uint8_t ipc;
int ipsize;
if (!packet || !pos || !config)
return -pte_internal;
ipc = (*pos++ >> pt_opm_ipc_shr) & pt_opm_ipc_shr_mask;
ip = 0ull;
ipsize = pt_pkt_ip_size((enum pt_ip_compression) ipc);
if (ipsize < 0)
return ipsize;
if (config->end < pos + ipsize)
return -pte_eos;
if (ipsize)
ip = pt_pkt_read_value(pos, ipsize);
packet->ipc = (enum pt_ip_compression) ipc;
packet->ip = ip;
return ipsize + 1;
}
static uint8_t pt_pkt_tnt_bit_size(uint64_t payload)
{
uint8_t size;
/* The payload bit-size is the bit-index of the payload's stop-bit,
* which itself is not part of the payload proper.
*/
for (size = 0; ; size += 1) {
payload >>= 1;
if (!payload)
break;
}
return size;
}
static int pt_pkt_read_tnt(struct pt_packet_tnt *packet, uint64_t payload)
{
uint8_t bit_size;
if (!packet)
return -pte_internal;
bit_size = pt_pkt_tnt_bit_size(payload);
if (!bit_size)
return -pte_bad_packet;
/* Remove the stop bit from the payload. */
payload &= ~(1ull << bit_size);
packet->payload = payload;
packet->bit_size = bit_size;
return 0;
}
int pt_pkt_read_tnt_8(struct pt_packet_tnt *packet, const uint8_t *pos,
const struct pt_config *config)
{
int errcode;
(void) config;
if (!pos)
return -pte_internal;
errcode = pt_pkt_read_tnt(packet, pos[0] >> pt_opm_tnt_8_shr);
if (errcode < 0)
return errcode;
return ptps_tnt_8;
}
int pt_pkt_read_tnt_64(struct pt_packet_tnt *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint64_t payload;
int errcode;
if (!pos || !config)
return -pte_internal;
if (config->end < pos + ptps_tnt_64)
return -pte_eos;
payload = pt_pkt_read_value(pos + pt_opcs_tnt_64, pt_pl_tnt_64_size);
errcode = pt_pkt_read_tnt(packet, payload);
if (errcode < 0)
return errcode;
return ptps_tnt_64;
}
int pt_pkt_read_pip(struct pt_packet_pip *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint64_t payload;
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_pip)
return -pte_eos;
/* Read the payload. */
payload = pt_pkt_read_value(pos + pt_opcs_pip, pt_pl_pip_size);
/* Extract the non-root information from the payload. */
packet->nr = payload & pt_pl_pip_nr;
/* Create the cr3 value. */
payload >>= pt_pl_pip_shr;
payload <<= pt_pl_pip_shl;
packet->cr3 = payload;
return ptps_pip;
}
static int pt_pkt_read_mode_exec(struct pt_packet_mode_exec *packet,
uint8_t mode)
{
if (!packet)
return -pte_internal;
packet->csl = (mode & pt_mob_exec_csl) != 0;
packet->csd = (mode & pt_mob_exec_csd) != 0;
return ptps_mode;
}
static int pt_pkt_read_mode_tsx(struct pt_packet_mode_tsx *packet,
uint8_t mode)
{
if (!packet)
return -pte_internal;
packet->intx = (mode & pt_mob_tsx_intx) != 0;
packet->abrt = (mode & pt_mob_tsx_abrt) != 0;
return ptps_mode;
}
int pt_pkt_read_mode(struct pt_packet_mode *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint8_t payload, mode, leaf;
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_mode)
return -pte_eos;
payload = pos[pt_opcs_mode];
leaf = payload & pt_mom_leaf;
mode = payload & pt_mom_bits;
packet->leaf = (enum pt_mode_leaf) leaf;
switch (leaf) {
default:
return -pte_bad_packet;
case pt_mol_exec:
return pt_pkt_read_mode_exec(&packet->bits.exec, mode);
case pt_mol_tsx:
return pt_pkt_read_mode_tsx(&packet->bits.tsx, mode);
}
}
int pt_pkt_read_tsc(struct pt_packet_tsc *packet, const uint8_t *pos,
const struct pt_config *config)
{
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_tsc)
return -pte_eos;
packet->tsc = pt_pkt_read_value(pos + pt_opcs_tsc, pt_pl_tsc_size);
return ptps_tsc;
}
int pt_pkt_read_cbr(struct pt_packet_cbr *packet, const uint8_t *pos,
const struct pt_config *config)
{
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_cbr)
return -pte_eos;
packet->ratio = pos[2];
return ptps_cbr;
}
int pt_pkt_read_tma(struct pt_packet_tma *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint16_t ctc, fc;
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_tma)
return -pte_eos;
ctc = pos[pt_pl_tma_ctc_0];
ctc |= pos[pt_pl_tma_ctc_1] << 8;
fc = pos[pt_pl_tma_fc_0];
fc |= pos[pt_pl_tma_fc_1] << 8;
if (fc & ~pt_pl_tma_fc_mask)
return -pte_bad_packet;
packet->ctc = ctc;
packet->fc = fc;
return ptps_tma;
}
int pt_pkt_read_mtc(struct pt_packet_mtc *packet, const uint8_t *pos,
const struct pt_config *config)
{
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_mtc)
return -pte_eos;
packet->ctc = pos[pt_opcs_mtc];
return ptps_mtc;
}
int pt_pkt_read_cyc(struct pt_packet_cyc *packet, const uint8_t *pos,
const struct pt_config *config)
{
const uint8_t *begin, *end;
uint64_t value;
uint8_t cyc, ext, shl;
if (!packet || !pos || !config)
return -pte_internal;
begin = pos;
end = config->end;
/* The first byte contains the opcode and part of the payload.
* We already checked that this first byte is within bounds.
*/
cyc = *pos++;
ext = cyc & pt_opm_cyc_ext;
cyc >>= pt_opm_cyc_shr;
value = cyc;
shl = (8 - pt_opm_cyc_shr);
while (ext) {
uint64_t bits;
if (end <= pos)
return -pte_eos;
bits = *pos++;
ext = bits & pt_opm_cycx_ext;
bits >>= pt_opm_cycx_shr;
bits <<= shl;
shl += (8 - pt_opm_cycx_shr);
if (sizeof(value) * 8 < shl)
return -pte_bad_packet;
value |= bits;
}
packet->value = value;
return (int) (pos - begin);
}
int pt_pkt_read_vmcs(struct pt_packet_vmcs *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint64_t payload;
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_vmcs)
return -pte_eos;
payload = pt_pkt_read_value(pos + pt_opcs_vmcs, pt_pl_vmcs_size);
packet->base = payload << pt_pl_vmcs_shl;
return ptps_vmcs;
}
int pt_pkt_read_mnt(struct pt_packet_mnt *packet, const uint8_t *pos,
const struct pt_config *config)
{
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_mnt)
return -pte_eos;
packet->payload = pt_pkt_read_value(pos + pt_opcs_mnt, pt_pl_mnt_size);
return ptps_mnt;
}
int pt_pkt_read_exstop(struct pt_packet_exstop *packet, const uint8_t *pos,
const struct pt_config *config)
{
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_exstop)
return -pte_eos;
packet->ip = pos[1] & pt_pl_exstop_ip_mask ? 1 : 0;
return ptps_exstop;
}
int pt_pkt_read_mwait(struct pt_packet_mwait *packet, const uint8_t *pos,
const struct pt_config *config)
{
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_mwait)
return -pte_eos;
packet->hints = (uint32_t) pt_pkt_read_value(pos + pt_opcs_mwait,
pt_pl_mwait_hints_size);
packet->ext = (uint32_t) pt_pkt_read_value(pos + pt_opcs_mwait +
pt_pl_mwait_hints_size,
pt_pl_mwait_ext_size);
return ptps_mwait;
}
int pt_pkt_read_pwre(struct pt_packet_pwre *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint64_t payload;
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_pwre)
return -pte_eos;
payload = pt_pkt_read_value(pos + pt_opcs_pwre, pt_pl_pwre_size);
memset(packet, 0, sizeof(*packet));
packet->state = (uint8_t) ((payload & pt_pl_pwre_state_mask) >>
pt_pl_pwre_state_shr);
packet->sub_state = (uint8_t) ((payload & pt_pl_pwre_sub_state_mask) >>
pt_pl_pwre_sub_state_shr);
if (payload & pt_pl_pwre_hw_mask)
packet->hw = 1;
return ptps_pwre;
}
int pt_pkt_read_pwrx(struct pt_packet_pwrx *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint64_t payload;
if (!packet || !pos || !config)
return -pte_internal;
if (config->end < pos + ptps_pwrx)
return -pte_eos;
payload = pt_pkt_read_value(pos + pt_opcs_pwrx, pt_pl_pwrx_size);
memset(packet, 0, sizeof(*packet));
packet->last = (uint8_t) ((payload & pt_pl_pwrx_last_mask) >>
pt_pl_pwrx_last_shr);
packet->deepest = (uint8_t) ((payload & pt_pl_pwrx_deepest_mask) >>
pt_pl_pwrx_deepest_shr);
if (payload & pt_pl_pwrx_wr_int)
packet->interrupt = 1;
if (payload & pt_pl_pwrx_wr_store)
packet->store = 1;
if (payload & pt_pl_pwrx_wr_hw)
packet->autonomous = 1;
return ptps_pwrx;
}
int pt_pkt_read_ptw(struct pt_packet_ptw *packet, const uint8_t *pos,
const struct pt_config *config)
{
uint8_t opc, plc;
int size;
if (!packet || !pos || !config)
return -pte_internal;
/* Skip the ext opcode. */
pos++;
opc = *pos++;
plc = (opc >> pt_opm_ptw_pb_shr) & pt_opm_ptw_pb_shr_mask;
size = pt_ptw_size(plc);
if (size < 0)
return size;
if (config->end < pos + size)
return -pte_eos;
packet->payload = pt_pkt_read_value(pos, size);
packet->plc = plc;
packet->ip = opc & pt_opm_ptw_ip ? 1 : 0;
return pt_opcs_ptw + size;
}

View File

@ -0,0 +1,723 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "pt_packet_decoder.h"
#include "pt_decoder_function.h"
#include "pt_packet.h"
#include "pt_sync.h"
#include "pt_config.h"
#include "pt_opcodes.h"
#include <string.h>
#include <stdlib.h>
int pt_pkt_decoder_init(struct pt_packet_decoder *decoder,
const struct pt_config *config)
{
int errcode;
if (!decoder || !config)
return -pte_invalid;
memset(decoder, 0, sizeof(*decoder));
errcode = pt_config_from_user(&decoder->config, config);
if (errcode < 0)
return errcode;
return 0;
}
struct pt_packet_decoder *pt_pkt_alloc_decoder(const struct pt_config *config)
{
struct pt_packet_decoder *decoder;
int errcode;
decoder = malloc(sizeof(*decoder));
if (!decoder)
return NULL;
errcode = pt_pkt_decoder_init(decoder, config);
if (errcode < 0) {
free(decoder);
return NULL;
}
return decoder;
}
void pt_pkt_decoder_fini(struct pt_packet_decoder *decoder)
{
(void) decoder;
/* Nothing to do. */
}
void pt_pkt_free_decoder(struct pt_packet_decoder *decoder)
{
pt_pkt_decoder_fini(decoder);
free(decoder);
}
int pt_pkt_sync_forward(struct pt_packet_decoder *decoder)
{
const uint8_t *pos, *sync;
int errcode;
if (!decoder)
return -pte_invalid;
sync = decoder->sync;
pos = decoder->pos;
if (!pos)
pos = decoder->config.begin;
if (pos == sync)
pos += ptps_psb;
errcode = pt_sync_forward(&sync, pos, &decoder->config);
if (errcode < 0)
return errcode;
decoder->sync = sync;
decoder->pos = sync;
return 0;
}
int pt_pkt_sync_backward(struct pt_packet_decoder *decoder)
{
const uint8_t *pos, *sync;
int errcode;
if (!decoder)
return -pte_invalid;
pos = decoder->pos;
if (!pos)
pos = decoder->config.end;
errcode = pt_sync_backward(&sync, pos, &decoder->config);
if (errcode < 0)
return errcode;
decoder->sync = sync;
decoder->pos = sync;
return 0;
}
int pt_pkt_sync_set(struct pt_packet_decoder *decoder, uint64_t offset)
{
const uint8_t *begin, *end, *pos;
if (!decoder)
return -pte_invalid;
begin = decoder->config.begin;
end = decoder->config.end;
pos = begin + offset;
if (end < pos || pos < begin)
return -pte_eos;
decoder->sync = pos;
decoder->pos = pos;
return 0;
}
int pt_pkt_get_offset(const struct pt_packet_decoder *decoder, uint64_t *offset)
{
const uint8_t *begin, *pos;
if (!decoder || !offset)
return -pte_invalid;
begin = decoder->config.begin;
pos = decoder->pos;
if (!pos)
return -pte_nosync;
*offset = pos - begin;
return 0;
}
int pt_pkt_get_sync_offset(const struct pt_packet_decoder *decoder,
uint64_t *offset)
{
const uint8_t *begin, *sync;
if (!decoder || !offset)
return -pte_invalid;
begin = decoder->config.begin;
sync = decoder->sync;
if (!sync)
return -pte_nosync;
*offset = sync - begin;
return 0;
}
const struct pt_config *
pt_pkt_get_config(const struct pt_packet_decoder *decoder)
{
if (!decoder)
return NULL;
return &decoder->config;
}
static inline int pkt_to_user(struct pt_packet *upkt, size_t size,
const struct pt_packet *pkt)
{
if (!upkt || !pkt)
return -pte_internal;
if (upkt == pkt)
return 0;
/* Zero out any unknown bytes. */
if (sizeof(*pkt) < size) {
memset(upkt + sizeof(*pkt), 0, size - sizeof(*pkt));
size = sizeof(*pkt);
}
memcpy(upkt, pkt, size);
return 0;
}
int pt_pkt_next(struct pt_packet_decoder *decoder, struct pt_packet *packet,
size_t psize)
{
const struct pt_decoder_function *dfun;
struct pt_packet pkt, *ppkt;
int errcode, size;
if (!packet || !decoder)
return -pte_invalid;
ppkt = psize == sizeof(pkt) ? packet : &pkt;
errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
if (errcode < 0)
return errcode;
if (!dfun)
return -pte_internal;
if (!dfun->packet)
return -pte_internal;
size = dfun->packet(decoder, ppkt);
if (size < 0)
return size;
errcode = pkt_to_user(packet, psize, ppkt);
if (errcode < 0)
return errcode;
decoder->pos += size;
return size;
}
int pt_pkt_decode_unknown(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder)
return -pte_internal;
size = pt_pkt_read_unknown(packet, decoder->pos, &decoder->config);
if (size < 0)
return size;
return size;
}
int pt_pkt_decode_pad(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
(void) decoder;
if (!packet)
return -pte_internal;
packet->type = ppt_pad;
packet->size = ptps_pad;
return ptps_pad;
}
int pt_pkt_decode_psb(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder)
return -pte_internal;
size = pt_pkt_read_psb(decoder->pos, &decoder->config);
if (size < 0)
return size;
packet->type = ppt_psb;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_tip(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tip;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_tnt_8(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_tnt_8(&packet->payload.tnt, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tnt_8;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_tnt_64(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_tnt_64(&packet->payload.tnt, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tnt_64;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_tip_pge(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tip_pge;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_tip_pgd(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tip_pgd;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_fup(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_fup;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_pip(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_pip(&packet->payload.pip, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_pip;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_ovf(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
(void) decoder;
if (!packet)
return -pte_internal;
packet->type = ppt_ovf;
packet->size = ptps_ovf;
return ptps_ovf;
}
int pt_pkt_decode_mode(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_mode(&packet->payload.mode, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_mode;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_psbend(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
(void) decoder;
if (!packet)
return -pte_internal;
packet->type = ppt_psbend;
packet->size = ptps_psbend;
return ptps_psbend;
}
int pt_pkt_decode_tsc(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_tsc(&packet->payload.tsc, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tsc;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_cbr(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_cbr(&packet->payload.cbr, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_cbr;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_tma(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_tma(&packet->payload.tma, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_tma;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_mtc(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_mtc(&packet->payload.mtc, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_mtc;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_cyc(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_cyc(&packet->payload.cyc, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_cyc;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_stop(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
(void) decoder;
if (!packet)
return -pte_internal;
packet->type = ppt_stop;
packet->size = ptps_stop;
return ptps_stop;
}
int pt_pkt_decode_vmcs(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_vmcs(&packet->payload.vmcs, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_vmcs;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_mnt(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_mnt(&packet->payload.mnt, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_mnt;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_exstop(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_exstop(&packet->payload.exstop, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_exstop;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_mwait(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_mwait(&packet->payload.mwait, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_mwait;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_pwre(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_pwre(&packet->payload.pwre, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_pwre;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_pwrx(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_pwrx(&packet->payload.pwrx, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_pwrx;
packet->size = (uint8_t) size;
return size;
}
int pt_pkt_decode_ptw(struct pt_packet_decoder *decoder,
struct pt_packet *packet)
{
int size;
if (!decoder || !packet)
return -pte_internal;
size = pt_pkt_read_ptw(&packet->payload.ptw, decoder->pos,
&decoder->config);
if (size < 0)
return size;
packet->type = ppt_ptw;
packet->size = (uint8_t) size;
return size;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_retstack.h"
#include "intel-pt.h"
void pt_retstack_init(struct pt_retstack *retstack)
{
if (!retstack)
return;
retstack->top = 0;
retstack->bottom = 0;
}
int pt_retstack_is_empty(const struct pt_retstack *retstack)
{
if (!retstack)
return -pte_invalid;
return (retstack->top == retstack->bottom ? 1 : 0);
}
int pt_retstack_pop(struct pt_retstack *retstack, uint64_t *ip)
{
uint8_t top;
if (!retstack)
return -pte_invalid;
top = retstack->top;
if (top == retstack->bottom)
return -pte_retstack_empty;
top = (!top ? pt_retstack_size : top - 1);
retstack->top = top;
if (ip)
*ip = retstack->stack[top];
return 0;
}
int pt_retstack_push(struct pt_retstack *retstack, uint64_t ip)
{
uint8_t top, bottom;
if (!retstack)
return -pte_invalid;
top = retstack->top;
bottom = retstack->bottom;
retstack->stack[top] = ip;
top = (top == pt_retstack_size ? 0 : top + 1);
if (bottom == top)
bottom = (bottom == pt_retstack_size ? 0 : bottom + 1);
retstack->top = top;
retstack->bottom = bottom;
return 0;
}

View File

@ -0,0 +1,643 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_section.h"
#include "pt_block_cache.h"
#include "pt_image_section_cache.h"
#include "intel-pt.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static char *dupstr(const char *str)
{
char *dup;
size_t len;
if (!str)
return NULL;
len = strlen(str);
dup = malloc(len + 1);
if (!dup)
return NULL;
return strcpy(dup, str);
}
struct pt_section *pt_mk_section(const char *filename, uint64_t offset,
uint64_t size)
{
struct pt_section *section;
uint64_t fsize;
void *status;
int errcode;
errcode = pt_section_mk_status(&status, &fsize, filename);
if (errcode < 0)
return NULL;
/* Fail if the requested @offset lies beyond the end of @file. */
if (fsize <= offset)
goto out_status;
/* Truncate @size so the entire range lies within @file. */
fsize -= offset;
if (fsize < size)
size = fsize;
section = malloc(sizeof(*section));
if (!section)
goto out_status;
memset(section, 0, sizeof(*section));
section->filename = dupstr(filename);
section->status = status;
section->offset = offset;
section->size = size;
section->ucount = 1;
#if defined(FEATURE_THREADS)
errcode = mtx_init(&section->lock, mtx_plain);
if (errcode != thrd_success) {
free(section->filename);
free(section);
goto out_status;
}
errcode = mtx_init(&section->alock, mtx_plain);
if (errcode != thrd_success) {
mtx_destroy(&section->lock);
free(section->filename);
free(section);
goto out_status;
}
#endif /* defined(FEATURE_THREADS) */
return section;
out_status:
free(status);
return NULL;
}
int pt_section_lock(struct pt_section *section)
{
if (!section)
return -pte_internal;
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_lock(&section->lock);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
int pt_section_unlock(struct pt_section *section)
{
if (!section)
return -pte_internal;
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_unlock(&section->lock);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
static void pt_section_free(struct pt_section *section)
{
if (!section)
return;
#if defined(FEATURE_THREADS)
mtx_destroy(&section->alock);
mtx_destroy(&section->lock);
#endif /* defined(FEATURE_THREADS) */
free(section->filename);
free(section->status);
free(section);
}
int pt_section_get(struct pt_section *section)
{
uint16_t ucount;
int errcode;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
ucount = section->ucount + 1;
if (!ucount) {
(void) pt_section_unlock(section);
return -pte_overflow;
}
section->ucount = ucount;
return pt_section_unlock(section);
}
int pt_section_put(struct pt_section *section)
{
uint16_t ucount, mcount;
int errcode;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
mcount = section->mcount;
ucount = section->ucount;
if (ucount > 1) {
section->ucount = ucount - 1;
return pt_section_unlock(section);
}
errcode = pt_section_unlock(section);
if (errcode < 0)
return errcode;
if (!ucount || mcount)
return -pte_internal;
pt_section_free(section);
return 0;
}
static int pt_section_lock_attach(struct pt_section *section)
{
if (!section)
return -pte_internal;
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_lock(&section->alock);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
static int pt_section_unlock_attach(struct pt_section *section)
{
if (!section)
return -pte_internal;
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_unlock(&section->alock);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
int pt_section_attach(struct pt_section *section,
struct pt_image_section_cache *iscache)
{
uint16_t acount, ucount;
int errcode;
if (!section || !iscache)
return -pte_internal;
errcode = pt_section_lock_attach(section);
if (errcode < 0)
return errcode;
ucount = section->ucount;
acount = section->acount;
if (!acount) {
if (section->iscache || !ucount)
goto out_unlock;
section->iscache = iscache;
section->acount = 1;
return pt_section_unlock_attach(section);
}
acount += 1;
if (!acount) {
(void) pt_section_unlock_attach(section);
return -pte_overflow;
}
if (ucount < acount)
goto out_unlock;
if (section->iscache != iscache)
goto out_unlock;
section->acount = acount;
return pt_section_unlock_attach(section);
out_unlock:
(void) pt_section_unlock_attach(section);
return -pte_internal;
}
int pt_section_detach(struct pt_section *section,
struct pt_image_section_cache *iscache)
{
uint16_t acount, ucount;
int errcode;
if (!section || !iscache)
return -pte_internal;
errcode = pt_section_lock_attach(section);
if (errcode < 0)
return errcode;
if (section->iscache != iscache)
goto out_unlock;
acount = section->acount;
if (!acount)
goto out_unlock;
acount -= 1;
ucount = section->ucount;
if (ucount < acount)
goto out_unlock;
section->acount = acount;
if (!acount)
section->iscache = NULL;
return pt_section_unlock_attach(section);
out_unlock:
(void) pt_section_unlock_attach(section);
return -pte_internal;
}
const char *pt_section_filename(const struct pt_section *section)
{
if (!section)
return NULL;
return section->filename;
}
uint64_t pt_section_size(const struct pt_section *section)
{
if (!section)
return 0ull;
return section->size;
}
static int pt_section_bcache_memsize(const struct pt_section *section,
uint64_t *psize)
{
struct pt_block_cache *bcache;
if (!section || !psize)
return -pte_internal;
bcache = section->bcache;
if (!bcache) {
*psize = 0ull;
return 0;
}
*psize = sizeof(*bcache) +
(bcache->nentries * sizeof(struct pt_bcache_entry));
return 0;
}
static int pt_section_memsize_locked(const struct pt_section *section,
uint64_t *psize)
{
uint64_t msize, bcsize;
int (*memsize)(const struct pt_section *section, uint64_t *size);
int errcode;
if (!section || !psize)
return -pte_internal;
memsize = section->memsize;
if (!memsize) {
if (section->mcount)
return -pte_internal;
*psize = 0ull;
return 0;
}
errcode = memsize(section, &msize);
if (errcode < 0)
return errcode;
errcode = pt_section_bcache_memsize(section, &bcsize);
if (errcode < 0)
return errcode;
*psize = msize + bcsize;
return 0;
}
int pt_section_memsize(struct pt_section *section, uint64_t *size)
{
int errcode, status;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
status = pt_section_memsize_locked(section, size);
errcode = pt_section_unlock(section);
if (errcode < 0)
return errcode;
return status;
}
uint64_t pt_section_offset(const struct pt_section *section)
{
if (!section)
return 0ull;
return section->offset;
}
int pt_section_alloc_bcache(struct pt_section *section)
{
struct pt_image_section_cache *iscache;
struct pt_block_cache *bcache;
uint64_t ssize, memsize;
uint32_t csize;
int errcode;
if (!section)
return -pte_internal;
if (!section->mcount)
return -pte_internal;
ssize = pt_section_size(section);
csize = (uint32_t) ssize;
if (csize != ssize)
return -pte_not_supported;
memsize = 0ull;
/* We need to take both the attach and the section lock in order to pair
* the block cache allocation and the resize notification.
*
* This allows map notifications in between but they only change the
* order of sections in the cache.
*
* The attach lock needs to be taken first.
*/
errcode = pt_section_lock_attach(section);
if (errcode < 0)
return errcode;
errcode = pt_section_lock(section);
if (errcode < 0)
goto out_alock;
bcache = pt_section_bcache(section);
if (bcache) {
errcode = 0;
goto out_lock;
}
bcache = pt_bcache_alloc(csize);
if (!bcache) {
errcode = -pte_nomem;
goto out_lock;
}
/* Install the block cache. It will become visible and may be used
* immediately.
*
* If we fail later on, we leave the block cache and report the error to
* the allocating decoder thread.
*/
section->bcache = bcache;
errcode = pt_section_memsize_locked(section, &memsize);
if (errcode < 0)
goto out_lock;
errcode = pt_section_unlock(section);
if (errcode < 0)
goto out_alock;
if (memsize) {
iscache = section->iscache;
if (iscache) {
errcode = pt_iscache_notify_resize(iscache, section,
memsize);
if (errcode < 0)
goto out_alock;
}
}
return pt_section_unlock_attach(section);
out_lock:
(void) pt_section_unlock(section);
out_alock:
(void) pt_section_unlock_attach(section);
return errcode;
}
int pt_section_on_map_lock(struct pt_section *section)
{
struct pt_image_section_cache *iscache;
int errcode, status;
if (!section)
return -pte_internal;
errcode = pt_section_lock_attach(section);
if (errcode < 0)
return errcode;
iscache = section->iscache;
if (!iscache)
return pt_section_unlock_attach(section);
/* There is a potential deadlock when @section was unmapped again and
* @iscache tries to map it. This would cause this function to be
* re-entered while we're still holding the attach lock.
*
* This scenario is very unlikely, though, since our caller does not yet
* know whether pt_section_map() succeeded.
*/
status = pt_iscache_notify_map(iscache, section);
errcode = pt_section_unlock_attach(section);
if (errcode < 0)
return errcode;
return status;
}
int pt_section_map_share(struct pt_section *section)
{
uint16_t mcount;
int errcode;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
mcount = section->mcount;
if (!mcount) {
(void) pt_section_unlock(section);
return -pte_internal;
}
mcount += 1;
if (!mcount) {
(void) pt_section_unlock(section);
return -pte_overflow;
}
section->mcount = mcount;
return pt_section_unlock(section);
}
int pt_section_unmap(struct pt_section *section)
{
uint16_t mcount;
int errcode, status;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
mcount = section->mcount;
errcode = -pte_nomap;
if (!mcount)
goto out_unlock;
section->mcount = mcount -= 1;
if (mcount)
return pt_section_unlock(section);
errcode = -pte_internal;
if (!section->unmap)
goto out_unlock;
status = section->unmap(section);
pt_bcache_free(section->bcache);
section->bcache = NULL;
errcode = pt_section_unlock(section);
if (errcode < 0)
return errcode;
return status;
out_unlock:
(void) pt_section_unlock(section);
return errcode;
}
int pt_section_read(const struct pt_section *section, uint8_t *buffer,
uint16_t size, uint64_t offset)
{
uint64_t limit, space;
if (!section)
return -pte_internal;
if (!section->read)
return -pte_nomap;
limit = section->size;
if (limit <= offset)
return -pte_nomap;
/* Truncate if we try to read past the end of the section. */
space = limit - offset;
if (space < size)
size = (uint16_t) space;
return section->read(section, buffer, size, offset);
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_section.h"
#include "pt_section_file.h"
#include "intel-pt.h"
#include <stdlib.h>
#include <string.h>
static int fmap_init(struct pt_sec_file_mapping *mapping)
{
if (!mapping)
return -pte_internal;
memset(mapping, 0, sizeof(*mapping));
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_init(&mapping->lock, mtx_plain);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
static void fmap_fini(struct pt_sec_file_mapping *mapping)
{
if (!mapping)
return;
fclose(mapping->file);
#if defined(FEATURE_THREADS)
mtx_destroy(&mapping->lock);
#endif /* defined(FEATURE_THREADS) */
}
static int fmap_lock(struct pt_sec_file_mapping *mapping)
{
if (!mapping)
return -pte_internal;
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_lock(&mapping->lock);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
static int fmap_unlock(struct pt_sec_file_mapping *mapping)
{
if (!mapping)
return -pte_internal;
#if defined(FEATURE_THREADS)
{
int errcode;
errcode = mtx_unlock(&mapping->lock);
if (errcode != thrd_success)
return -pte_bad_lock;
}
#endif /* defined(FEATURE_THREADS) */
return 0;
}
int pt_sec_file_map(struct pt_section *section, FILE *file)
{
struct pt_sec_file_mapping *mapping;
uint64_t offset, size;
long begin, end, fsize;
int errcode;
if (!section)
return -pte_internal;
mapping = section->mapping;
if (mapping)
return -pte_internal;
offset = section->offset;
size = section->size;
begin = (long) offset;
end = begin + (long) size;
/* Check for overflows. */
if ((uint64_t) begin != offset)
return -pte_bad_image;
if ((uint64_t) end != (offset + size))
return -pte_bad_image;
if (end < begin)
return -pte_bad_image;
/* Validate that the section lies within the file. */
errcode = fseek(file, 0, SEEK_END);
if (errcode)
return -pte_bad_image;
fsize = ftell(file);
if (fsize < 0)
return -pte_bad_image;
if (fsize < end)
return -pte_bad_image;
mapping = malloc(sizeof(*mapping));
if (!mapping)
return -pte_nomem;
errcode = fmap_init(mapping);
if (errcode < 0)
goto out_mem;
mapping->file = file;
mapping->begin = begin;
mapping->end = end;
section->mapping = mapping;
section->unmap = pt_sec_file_unmap;
section->read = pt_sec_file_read;
section->memsize = pt_sec_file_memsize;
return 0;
out_mem:
free(mapping);
return errcode;
}
int pt_sec_file_unmap(struct pt_section *section)
{
struct pt_sec_file_mapping *mapping;
if (!section)
return -pte_internal;
mapping = section->mapping;
if (!mapping || !section->unmap || !section->read || !section->memsize)
return -pte_internal;
section->mapping = NULL;
section->unmap = NULL;
section->read = NULL;
section->memsize = NULL;
fmap_fini(mapping);
free(mapping);
return 0;
}
int pt_sec_file_read(const struct pt_section *section, uint8_t *buffer,
uint16_t size, uint64_t offset)
{
struct pt_sec_file_mapping *mapping;
FILE *file;
long begin;
size_t read;
int errcode;
if (!buffer || !section)
return -pte_internal;
mapping = section->mapping;
if (!mapping)
return -pte_internal;
file = mapping->file;
/* We already checked in pt_section_read() that the requested memory
* lies within the section's boundaries.
*
* And we checked that the file covers the entire section in
* pt_sec_file_map(). There's no need to check for overflows, again.
*/
begin = mapping->begin + (long) offset;
errcode = fmap_lock(mapping);
if (errcode < 0)
return errcode;
errcode = fseek(file, begin, SEEK_SET);
if (errcode)
goto out_unlock;
read = fread(buffer, 1, size, file);
errcode = fmap_unlock(mapping);
if (errcode < 0)
return errcode;
return (int) read;
out_unlock:
(void) fmap_unlock(mapping);
return -pte_nomap;
}
int pt_sec_file_memsize(const struct pt_section *section, uint64_t *size)
{
if (!section || !size)
return -pte_internal;
if (!section->mapping)
return -pte_internal;
*size = 0ull;
return 0;
}

View File

@ -0,0 +1,241 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_sync.h"
#include "pt_packet.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
/* A psb packet contains a unique 2-byte repeating pattern.
*
* There are only two ways to fill up a 64bit work with such a pattern.
*/
static const uint64_t psb_pattern[] = {
((uint64_t) pt_psb_lohi | (uint64_t) pt_psb_lohi << 16 |
(uint64_t) pt_psb_lohi << 32 | (uint64_t) pt_psb_lohi << 48),
((uint64_t) pt_psb_hilo | (uint64_t) pt_psb_hilo << 16 |
(uint64_t) pt_psb_hilo << 32 | (uint64_t) pt_psb_hilo << 48)
};
static const uint8_t *truncate(const uint8_t *pointer, size_t alignment)
{
uintptr_t raw = (uintptr_t) pointer;
raw /= alignment;
raw *= alignment;
return (const uint8_t *) raw;
}
static const uint8_t *align(const uint8_t *pointer, size_t alignment)
{
return truncate(pointer + alignment - 1, alignment);
}
/* Find a psb packet given a position somewhere in the payload.
*
* Return the position of the psb packet.
* Return NULL, if this is not a psb packet.
*/
static const uint8_t *pt_find_psb(const uint8_t *pos,
const struct pt_config *config)
{
const uint8_t *begin, *end;
int errcode;
if (!pos || !config)
return NULL;
begin = config->begin;
end = config->end;
/* Navigate to the end of the psb payload pattern.
*
* Beware that PSB is an extended opcode. We must not confuse the extend
* opcode of the following packet as belonging to the PSB.
*/
if (*pos != pt_psb_hi)
pos++;
for (; (pos + 1) < end; pos += 2) {
uint8_t hi, lo;
hi = pos[0];
lo = pos[1];
if (hi != pt_psb_hi)
break;
if (lo != pt_psb_lo)
break;
}
/*
* We're right after the psb payload and within the buffer.
* Navigate to the expected beginning of the psb packet.
*/
pos -= ptps_psb;
/* Check if we're still inside the buffer. */
if (pos < begin)
return NULL;
/* Check that this is indeed a psb packet we're at. */
if (pos[0] != pt_opc_psb || pos[1] != pt_ext_psb)
return NULL;
errcode = pt_pkt_read_psb(pos, config);
if (errcode < 0)
return NULL;
return pos;
}
static int pt_sync_within_bounds(const uint8_t *pos, const uint8_t *begin,
const uint8_t *end)
{
/* We allow @pos == @end representing the very end of the trace.
*
* This will result in -pte_eos when we actually try to read from @pos.
*/
return (begin <= pos) && (pos <= end);
}
int pt_sync_set(const uint8_t **sync, const uint8_t *pos,
const struct pt_config *config)
{
const uint8_t *begin, *end;
int errcode;
if (!sync || !pos || !config)
return -pte_internal;
begin = config->begin;
end = config->end;
if (!pt_sync_within_bounds(pos, begin, end))
return -pte_eos;
if (end < pos + 2)
return -pte_eos;
/* Check that this is indeed a psb packet we're at. */
if (pos[0] != pt_opc_psb || pos[1] != pt_ext_psb)
return -pte_nosync;
errcode = pt_pkt_read_psb(pos, config);
if (errcode < 0)
return errcode;
*sync = pos;
return 0;
}
int pt_sync_forward(const uint8_t **sync, const uint8_t *pos,
const struct pt_config *config)
{
const uint8_t *begin, *end;
if (!sync || !pos || !config)
return -pte_internal;
begin = config->begin;
end = config->end;
if (!pt_sync_within_bounds(pos, begin, end))
return -pte_internal;
/* We search for a full 64bit word. It's OK to skip the current one. */
pos = align(pos, sizeof(*psb_pattern));
/* Search for the psb payload pattern in the buffer. */
for (;;) {
const uint8_t *current = pos;
uint64_t val;
pos += sizeof(uint64_t);
if (end < pos)
return -pte_eos;
val = * (const uint64_t *) current;
if ((val != psb_pattern[0]) && (val != psb_pattern[1]))
continue;
/* We found a 64bit word's worth of psb payload pattern. */
current = pt_find_psb(pos, config);
if (!current)
continue;
*sync = current;
return 0;
}
}
int pt_sync_backward(const uint8_t **sync, const uint8_t *pos,
const struct pt_config *config)
{
const uint8_t *begin, *end;
if (!sync || !pos || !config)
return -pte_internal;
begin = config->begin;
end = config->end;
if (!pt_sync_within_bounds(pos, begin, end))
return -pte_internal;
/* We search for a full 64bit word. It's OK to skip the current one. */
pos = truncate(pos, sizeof(*psb_pattern));
/* Search for the psb payload pattern in the buffer. */
for (;;) {
const uint8_t *next = pos;
uint64_t val;
pos -= sizeof(uint64_t);
if (pos < begin)
return -pte_eos;
val = * (const uint64_t *) pos;
if ((val != psb_pattern[0]) && (val != psb_pattern[1]))
continue;
/* We found a 64bit word's worth of psb payload pattern. */
next = pt_find_psb(next, config);
if (!next)
continue;
*sync = next;
return 0;
}
}

View File

@ -0,0 +1,674 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "pt_time.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
#include <string.h>
#include <limits.h>
void pt_time_init(struct pt_time *time)
{
if (!time)
return;
memset(time, 0, sizeof(*time));
}
int pt_time_query_tsc(uint64_t *tsc, uint32_t *lost_mtc,
uint32_t *lost_cyc, const struct pt_time *time)
{
if (!tsc || !time)
return -pte_internal;
*tsc = time->tsc;
if (lost_mtc)
*lost_mtc = time->lost_mtc;
if (lost_cyc)
*lost_cyc = time->lost_cyc;
if (!time->have_tsc)
return -pte_no_time;
return 0;
}
int pt_time_query_cbr(uint32_t *cbr, const struct pt_time *time)
{
if (!cbr || !time)
return -pte_internal;
if (!time->have_cbr)
return -pte_no_cbr;
*cbr = time->cbr;
return 0;
}
/* Compute the distance between two CTC sources.
*
* We adjust a single wrap-around but fail if the distance is bigger than that.
*
* Returns zero on success, a negative error code otherwise.
*/
static int pt_time_ctc_delta(uint32_t *ctc_delta, uint32_t ctc,
uint32_t last_ctc, const struct pt_config *config)
{
if (!config || !ctc_delta)
return -pte_internal;
/* Correct a single wrap-around. If we lost enough MTCs to wrap
* around twice, timing will be wrong until the next TSC.
*/
if (ctc < last_ctc) {
ctc += 1u << (config->mtc_freq + pt_pl_mtc_bit_size);
/* Since we only store the CTC between TMA/MTC or MTC/TMC a
* single correction should suffice.
*/
if (ctc < last_ctc)
return -pte_bad_packet;
}
*ctc_delta = ctc - last_ctc;
return 0;
}
/* Translate CTC into the same unit as the FastCounter by multiplying with P.
*
* Returns zero on success, a negative error code otherwise.
*/
static int pt_time_ctc_fc(uint64_t *fc, uint64_t ctc,
const struct pt_config *config)
{
uint32_t eax, ebx;
if (!fc || !config)
return -pte_internal;
eax = config->cpuid_0x15_eax;
ebx = config->cpuid_0x15_ebx;
/* Neither multiply nor divide by zero. */
if (!eax || !ebx)
return -pte_bad_config;
*fc = (ctc * ebx) / eax;
return 0;
}
int pt_time_update_tsc(struct pt_time *time,
const struct pt_packet_tsc *packet,
const struct pt_config *config)
{
(void) config;
if (!time || !packet)
return -pte_internal;
time->have_tsc = 1;
time->have_tma = 0;
time->have_mtc = 0;
time->tsc = time->base = packet->tsc;
time->ctc = 0;
time->fc = 0ull;
/* We got the full time; we recover from previous losses. */
time->lost_mtc = 0;
time->lost_cyc = 0;
return 0;
}
int pt_time_update_cbr(struct pt_time *time,
const struct pt_packet_cbr *packet,
const struct pt_config *config)
{
(void) config;
if (!time || !packet)
return -pte_internal;
time->have_cbr = 1;
time->cbr = packet->ratio;
return 0;
}
int pt_time_update_tma(struct pt_time *time,
const struct pt_packet_tma *packet,
const struct pt_config *config)
{
uint32_t ctc, mtc_freq, mtc_hi, ctc_mask;
uint64_t fc;
if (!time || !packet || !config)
return -pte_internal;
/* Without a TSC something is seriously wrong. */
if (!time->have_tsc)
return -pte_bad_context;
/* We shouldn't have more than one TMA per TSC. */
if (time->have_tma)
return -pte_bad_context;
/* We're ignoring MTC between TSC and TMA. */
if (time->have_mtc)
return -pte_internal;
ctc = packet->ctc;
fc = packet->fc;
mtc_freq = config->mtc_freq;
mtc_hi = mtc_freq + pt_pl_mtc_bit_size;
/* A mask for the relevant CTC bits ignoring high-order bits that are
* not provided by MTC.
*/
ctc_mask = (1u << mtc_hi) - 1u;
time->have_tma = 1;
time->base -= fc;
time->fc += fc;
/* If the MTC frequency is low enough that TMA provides the full CTC
* value, we can use the TMA as an MTC.
*
* If it isn't, we will estimate the preceding MTC based on the CTC bits
* the TMA provides at the next MTC. We forget about the previous MTC
* in this case.
*
* If no MTC packets are dropped around TMA, we will estimate the
* forgotten value again at the next MTC.
*
* If MTC packets are dropped, we can't really tell where in this
* extended MTC period the TSC occurred. The estimation will place it
* right before the next MTC.
*/
if (mtc_hi <= pt_pl_tma_ctc_bit_size)
time->have_mtc = 1;
/* In both cases, we store the TMA's CTC bits until the next MTC. */
time->ctc = time->ctc_cyc = ctc & ctc_mask;
return 0;
}
int pt_time_update_mtc(struct pt_time *time,
const struct pt_packet_mtc *packet,
const struct pt_config *config)
{
uint32_t last_ctc, ctc, ctc_delta;
uint64_t tsc, base;
uint8_t mtc_freq;
int errcode, have_tsc, have_tma, have_mtc;
if (!time || !packet || !config)
return -pte_internal;
have_tsc = time->have_tsc;
have_tma = time->have_tma;
have_mtc = time->have_mtc;
/* We ignore MTCs between TSC and TMA to avoid apparent CTC overflows.
*
* Later MTCs will ensure that no time is lost - provided TMA provides
* enough bits. If TMA doesn't provide any of the MTC bits we may place
* the TSC into the wrong MTC period.
*/
if (have_tsc && !have_tma)
return 0;
base = time->base;
last_ctc = time->ctc;
mtc_freq = config->mtc_freq;
ctc = packet->ctc << mtc_freq;
/* Store our CTC value if we have or would have reset FC. */
if (time->fc || time->lost_cyc || !have_mtc)
time->ctc_cyc = ctc;
/* Prepare for the next packet in case we error out below. */
time->have_mtc = 1;
time->fc = 0ull;
time->ctc = ctc;
/* We recover from previous CYC losses. */
time->lost_cyc = 0;
/* Avoid a big jump when we see the first MTC with an arbitrary CTC
* payload.
*/
if (!have_mtc) {
uint32_t ctc_lo, ctc_hi;
/* If we have not seen a TMA, we ignore this first MTC.
*
* We have no idea where in this MTC period tracing started.
* We could lose an entire MTC period or just a tiny fraction.
*
* On the other hand, if we assumed a previous MTC value, we
* might make just the same error.
*/
if (!have_tma)
return 0;
/* The TMA's CTC value didn't provide enough bits - otherwise,
* we would have treated the TMA as an MTC.
*/
if (last_ctc & ~pt_pl_tma_ctc_mask)
return -pte_internal;
/* Split this MTC's CTC value into low and high parts with
* respect to the bits provided by TMA.
*/
ctc_lo = ctc & pt_pl_tma_ctc_mask;
ctc_hi = ctc & ~pt_pl_tma_ctc_mask;
/* We estimate the high-order CTC bits that are not provided by
* TMA based on the CTC bits provided by this MTC.
*
* We assume that no MTC packets were dropped around TMA. If
* there are, we might place the TSC into the wrong MTC period
* depending on how many CTC bits TMA provides and how many MTC
* packets were dropped.
*
* Note that we may underflow which results in more bits to be
* set than MTC packets may provide. Drop those extra bits.
*/
if (ctc_lo < last_ctc) {
ctc_hi -= 1u << pt_pl_tma_ctc_bit_size;
ctc_hi &= pt_pl_mtc_mask << mtc_freq;
}
last_ctc |= ctc_hi;
}
errcode = pt_time_ctc_delta(&ctc_delta, ctc, last_ctc, config);
if (errcode < 0) {
time->lost_mtc += 1;
return errcode;
}
errcode = pt_time_ctc_fc(&tsc, ctc_delta, config);
if (errcode < 0)
return errcode;
base += tsc;
time->tsc = time->base = base;
return 0;
}
/* Adjust a CYC packet's payload spanning multiple MTC periods.
*
* CYC packets measure the Fast Counter since the last CYC(-eligible) packet.
* Depending on the CYC threshold, we may not get a CYC for each MTC, so a CYC
* period may overlap with or even span multiple MTC periods.
*
* We can't do much about the overlap case without examining all packets in
* the respective periods. We leave this as expected imprecision.
*
* If we find a CYC packet to span multiple MTC packets, though, we try to
* approximate the portion for the current MTC period by subtracting the
* estimated portion for previous MTC periods using calibration information.
*
* We only consider MTC. For the first CYC after TSC, the corresponding TMA
* will contain the Fast Counter at TSC.
*
* Returns zero on success, a negative error code otherwise.
*/
static int pt_time_adjust_cyc(uint64_t *cyc, const struct pt_time *time,
const struct pt_config *config, uint64_t fcr)
{
uint32_t last_ctc, ctc, ctc_delta;
uint64_t fc, total_cyc, old_cyc;
int errcode;
if (!time || !config || !fcr)
return -pte_internal;
last_ctc = time->ctc_cyc;
ctc = time->ctc;
/* There is nothing to do if this is the current MTC period. */
if (ctc == last_ctc)
return 0;
/* Calibration computes
*
* fc = (ctc_delta * cpuid[0x15].ebx) / cpuid[0x15].eax.
* fcr = (fc << pt_tcal_fcr_shr) / cyc
*
* So cyc = (fc << pt_tcal_fcr_shr) / fcr.
*/
errcode = pt_time_ctc_delta(&ctc_delta, ctc, last_ctc, config);
if (errcode < 0)
return errcode;
errcode = pt_time_ctc_fc(&fc, ctc_delta, config);
if (errcode < 0)
return errcode;
old_cyc = (fc << pt_tcal_fcr_shr) / fcr;
total_cyc = *cyc;
/* Make sure we don't wrap around. If we would, attribute the entire
* CYC payload to any previous MTC period.
*
* We lost an unknown portion of the CYC payload for the current MTC
* period, but it's usually better to run too slow than too fast.
*/
if (total_cyc < old_cyc)
total_cyc = old_cyc;
*cyc = total_cyc - old_cyc;
return 0;
}
int pt_time_update_cyc(struct pt_time *time,
const struct pt_packet_cyc *packet,
const struct pt_config *config, uint64_t fcr)
{
uint64_t cyc, fc;
if (!time || !packet || !config)
return -pte_internal;
if (!fcr) {
time->lost_cyc += 1;
return 0;
}
cyc = packet->value;
fc = time->fc;
if (!fc) {
int errcode;
errcode = pt_time_adjust_cyc(&cyc, time, config, fcr);
if (errcode < 0)
return errcode;
}
fc += (cyc * fcr) >> pt_tcal_fcr_shr;
time->fc = fc;
time->tsc = time->base + fc;
return 0;
}
void pt_tcal_init(struct pt_time_cal *tcal)
{
if (!tcal)
return;
memset(tcal, 0, sizeof(*tcal));
tcal->min_fcr = UINT64_MAX;
}
static int pt_tcal_have_fcr(const struct pt_time_cal *tcal)
{
if (!tcal)
return 0;
return (tcal->min_fcr <= tcal->max_fcr);
}
int pt_tcal_fcr(uint64_t *fcr, const struct pt_time_cal *tcal)
{
if (!fcr || !tcal)
return -pte_internal;
if (!pt_tcal_have_fcr(tcal))
return -pte_no_time;
*fcr = tcal->fcr;
return 0;
}
int pt_tcal_set_fcr(struct pt_time_cal *tcal, uint64_t fcr)
{
if (!tcal)
return -pte_internal;
tcal->fcr = fcr;
if (fcr < tcal->min_fcr)
tcal->min_fcr = fcr;
if (fcr > tcal->max_fcr)
tcal->max_fcr = fcr;
return 0;
}
int pt_tcal_update_tsc(struct pt_time_cal *tcal,
const struct pt_packet_tsc *packet,
const struct pt_config *config)
{
(void) config;
if (!tcal || !packet)
return -pte_internal;
/* A TSC outside of PSB+ may indicate loss of time. We do not use it
* for calibration. We store the TSC value for calibration at the next
* TSC in PSB+, though.
*/
tcal->tsc = packet->tsc;
tcal->cyc_tsc = 0ull;
return 0;
}
int pt_tcal_header_tsc(struct pt_time_cal *tcal,
const struct pt_packet_tsc *packet,
const struct pt_config *config)
{
uint64_t tsc, last_tsc, tsc_delta, cyc, fcr;
(void) config;
if (!tcal || !packet)
return -pte_internal;
last_tsc = tcal->tsc;
cyc = tcal->cyc_tsc;
tsc = packet->tsc;
tcal->tsc = tsc;
tcal->cyc_tsc = 0ull;
if (!last_tsc || !cyc)
return 0;
/* Correct a single wrap-around. */
if (tsc < last_tsc) {
tsc += 1ull << pt_pl_tsc_bit_size;
if (tsc < last_tsc)
return -pte_bad_packet;
}
tsc_delta = tsc - last_tsc;
/* We shift the nominator to improve rounding precision.
*
* Since we're only collecting the CYCs between two TSC, we shouldn't
* overflow. Let's rather fail than overflow.
*/
if (tsc_delta & ~(~0ull >> pt_tcal_fcr_shr))
return -pte_internal;
fcr = (tsc_delta << pt_tcal_fcr_shr) / cyc;
return pt_tcal_set_fcr(tcal, fcr);
}
int pt_tcal_update_cbr(struct pt_time_cal *tcal,
const struct pt_packet_cbr *packet,
const struct pt_config *config)
{
/* A CBR outside of PSB+ indicates a frequency change. Reset our
* calibration state.
*/
pt_tcal_init(tcal);
return pt_tcal_header_cbr(tcal, packet, config);
}
int pt_tcal_header_cbr(struct pt_time_cal *tcal,
const struct pt_packet_cbr *packet,
const struct pt_config *config)
{
uint64_t cbr, p1, fcr;
if (!tcal || !packet || !config)
return -pte_internal;
p1 = config->nom_freq;
if (!p1)
return 0;
/* If we know the nominal frequency, we can use it for calibration. */
cbr = packet->ratio;
fcr = (p1 << pt_tcal_fcr_shr) / cbr;
return pt_tcal_set_fcr(tcal, fcr);
}
int pt_tcal_update_tma(struct pt_time_cal *tcal,
const struct pt_packet_tma *packet,
const struct pt_config *config)
{
(void) tcal;
(void) packet;
(void) config;
/* Nothing to do. */
return 0;
}
int pt_tcal_update_mtc(struct pt_time_cal *tcal,
const struct pt_packet_mtc *packet,
const struct pt_config *config)
{
uint32_t last_ctc, ctc, ctc_delta, have_mtc;
uint64_t cyc, fc, fcr;
int errcode;
if (!tcal || !packet || !config)
return -pte_internal;
last_ctc = tcal->ctc;
have_mtc = tcal->have_mtc;
cyc = tcal->cyc_mtc;
ctc = packet->ctc << config->mtc_freq;
/* We need at least two MTC (including this). */
if (!have_mtc) {
tcal->cyc_mtc = 0ull;
tcal->ctc = ctc;
tcal->have_mtc = 1;
return 0;
}
/* Without any cycles, we can't calibrate. Try again at the next
* MTC and distribute the cycles over the combined MTC period.
*/
if (!cyc)
return 0;
/* Prepare for the next packet in case we error out below. */
tcal->have_mtc = 1;
tcal->cyc_mtc = 0ull;
tcal->ctc = ctc;
/* Let's pretend we will fail. We'll correct it at the end. */
tcal->lost_mtc += 1;
errcode = pt_time_ctc_delta(&ctc_delta, ctc, last_ctc, config);
if (errcode < 0)
return errcode;
errcode = pt_time_ctc_fc(&fc, ctc_delta, config);
if (errcode < 0)
return errcode;
/* We shift the nominator to improve rounding precision.
*
* Since we're only collecting the CYCs between two MTC, we shouldn't
* overflow. Let's rather fail than overflow.
*/
if (fc & ~(~0ull >> pt_tcal_fcr_shr))
return -pte_internal;
fcr = (fc << pt_tcal_fcr_shr) / cyc;
errcode = pt_tcal_set_fcr(tcal, fcr);
if (errcode < 0)
return errcode;
/* We updated the FCR. This recovers from previous MTC losses. */
tcal->lost_mtc = 0;
return 0;
}
int pt_tcal_update_cyc(struct pt_time_cal *tcal,
const struct pt_packet_cyc *packet,
const struct pt_config *config)
{
uint64_t cyc;
(void) config;
if (!tcal || !packet)
return -pte_internal;
cyc = packet->value;
tcal->cyc_mtc += cyc;
tcal->cyc_tsc += cyc;
return 0;
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_tnt_cache.h"
#include "intel-pt.h"
void pt_tnt_cache_init(struct pt_tnt_cache *cache)
{
if (!cache)
return;
cache->tnt = 0ull;
cache->index = 0ull;
}
int pt_tnt_cache_is_empty(const struct pt_tnt_cache *cache)
{
if (!cache)
return -pte_invalid;
return cache->index == 0;
}
int pt_tnt_cache_query(struct pt_tnt_cache *cache)
{
int taken;
if (!cache)
return -pte_invalid;
if (!cache->index)
return -pte_bad_query;
taken = (cache->tnt & cache->index) != 0;
cache->index >>= 1;
return taken;
}
int pt_tnt_cache_update_tnt(struct pt_tnt_cache *cache,
const struct pt_packet_tnt *packet,
const struct pt_config *config)
{
uint8_t bit_size;
(void) config;
if (!cache || !packet)
return -pte_invalid;
if (cache->index)
return -pte_bad_context;
bit_size = packet->bit_size;
if (!bit_size)
return -pte_bad_packet;
cache->tnt = packet->payload;
cache->index = 1ull << (bit_size - 1);
return 0;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "intel-pt.h"
struct pt_version pt_library_version(void)
{
struct pt_version v = {
/* .major = */ PT_VERSION_MAJOR,
/* .minor = */ PT_VERSION_MINOR,
/* .reserved = */ 0,
/* .build = */ PT_VERSION_BUILD,
/* .ext = */ PT_VERSION_EXT
};
return v;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_ild.h"
#include <windows.h>
BOOLEAN WINAPI DllMain(HINSTANCE handle, DWORD reason, LPVOID reserved)
{
(void) handle;
(void) reserved;
switch (reason) {
case DLL_PROCESS_ATTACH:
/* Initialize the Intel(R) Processor Trace instruction
decoder. */
pt_ild_init();
break;
default:
break;
}
return TRUE;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "pt_cpuid.h"
#include <intrin.h>
extern void pt_cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
int cpu_info[4];
__cpuid(cpu_info, leaf);
*eax = cpu_info[0];
*ebx = cpu_info[1];
*ecx = cpu_info[2];
*edx = cpu_info[3];
}

View File

@ -0,0 +1,397 @@
/*
* Copyright (c) 2015-2018, 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.
*/
#include "pt_section.h"
#include "pt_section_windows.h"
#include "pt_section_file.h"
#include "intel-pt.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
static int pt_sec_windows_fstat(const char *filename, struct _stat *stat)
{
int fd, errcode;
if (!filename || !stat)
return -pte_internal;
fd = _open(filename, _O_RDONLY);
if (fd == -1)
return -pte_bad_image;
errcode = _fstat(fd, stat);
_close(fd);
if (errcode)
return -pte_bad_image;
return 0;
}
int pt_section_mk_status(void **pstatus, uint64_t *psize, const char *filename)
{
struct pt_sec_windows_status *status;
struct _stat stat;
int errcode;
if (!pstatus || !psize)
return -pte_internal;
errcode = pt_sec_windows_fstat(filename, &stat);
if (errcode < 0)
return errcode;
if (stat.st_size < 0)
return -pte_bad_image;
status = malloc(sizeof(*status));
if (!status)
return -pte_nomem;
status->stat = stat;
*pstatus = status;
*psize = stat.st_size;
return 0;
}
static int check_file_status(struct pt_section *section, int fd)
{
struct pt_sec_windows_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;
}
static DWORD granularity(void)
{
struct _SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwAllocationGranularity;
}
int pt_sec_windows_map(struct pt_section *section, int fd)
{
struct pt_sec_windows_mapping *mapping;
uint64_t offset, size, adjustment;
HANDLE fh, mh;
DWORD dsize;
uint8_t *base;
int errcode;
if (!section)
return -pte_internal;
offset = section->offset;
size = section->size;
adjustment = offset % granularity();
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;
dsize = (DWORD) size;
if ((uint64_t) dsize != size)
return -pte_internal;
fh = (HANDLE) _get_osfhandle(fd);
mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);
if (!mh)
return -pte_bad_image;
base = MapViewOfFile(mh, FILE_MAP_READ, (DWORD) (offset >> 32),
(DWORD) (uint32_t) offset, dsize);
if (!base) {
errcode = -pte_bad_image;
goto out_mh;
}
mapping = malloc(sizeof(*mapping));
if (!mapping) {
errcode = -pte_nomem;
goto out_map;
}
mapping->fd = fd;
mapping->mh = mh;
mapping->base = base;
mapping->begin = base + adjustment;
mapping->end = base + size;
section->mapping = mapping;
section->unmap = pt_sec_windows_unmap;
section->read = pt_sec_windows_read;
section->memsize = pt_sec_windows_memsize;
return 0;
out_map:
UnmapViewOfFile(base);
out_mh:
CloseHandle(mh);
return errcode;
}
static int pt_sec_windows_map_success(struct pt_section *section)
{
uint16_t mcount;
int errcode, status;
if (!section)
return -pte_internal;
mcount = section->mcount + 1;
if (!mcount) {
(void) pt_section_unlock(section);
return -pte_overflow;
}
section->mcount = mcount;
errcode = pt_section_unlock(section);
if (errcode < 0)
return errcode;
status = pt_section_on_map(section);
if (status < 0) {
/* We had to release the section lock for pt_section_on_map() so
* @section may have meanwhile been mapped by other threads.
*
* We still want to return the error so we release our mapping.
* Our caller does not yet know whether pt_section_map()
* succeeded.
*/
(void) pt_section_unmap(section);
return status;
}
return 0;
}
int pt_section_map(struct pt_section *section)
{
const char *filename;
HANDLE fh;
FILE *file;
int fd, errcode;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
if (section->mcount)
return pt_sec_windows_map_success(section);
if (section->mapping) {
errcode = -pte_internal;
goto out_unlock;
}
filename = section->filename;
if (!filename) {
errcode = -pte_internal;
goto out_unlock;
}
fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
/* We failed to open the file read-only. Let's try to open it
* read-write; maybe our user has the file open for writing.
*
* We will detect changes to the file via fstat().
*/
fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
errcode = -pte_bad_image;
goto out_unlock;
}
}
fd = _open_osfhandle((intptr_t) fh, _O_RDONLY);
if (fd == -1) {
errcode = -pte_bad_image;
goto out_fh;
}
errcode = check_file_status(section, fd);
if (errcode < 0) {
errcode = -pte_bad_image;
goto out_fd;
}
/* We leave the file open on success. It will be closed when the
* section is unmapped.
*/
errcode = pt_sec_windows_map(section, fd);
if (!errcode)
return pt_sec_windows_map_success(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) {
errcode = -pte_bad_image;
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)
return pt_sec_windows_map_success(section);
fclose(file);
goto out_unlock;
out_fd:
_close(fd);
return errcode;
out_fh:
CloseHandle(fh);
out_unlock:
(void) pt_section_unlock(section);
return errcode;
}
int pt_sec_windows_unmap(struct pt_section *section)
{
struct pt_sec_windows_mapping *mapping;
if (!section)
return -pte_internal;
mapping = section->mapping;
if (!mapping || !section->unmap || !section->read || !section->memsize)
return -pte_internal;
section->mapping = NULL;
section->unmap = NULL;
section->read = NULL;
section->memsize = NULL;
UnmapViewOfFile(mapping->begin);
CloseHandle(mapping->mh);
_close(mapping->fd);
free(mapping);
return 0;
}
int pt_sec_windows_read(const struct pt_section *section, uint8_t *buffer,
uint16_t size, uint64_t offset)
{
struct pt_sec_windows_mapping *mapping;
const uint8_t *begin;
if (!buffer || !section)
return -pte_internal;
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;
}
int pt_sec_windows_memsize(const struct pt_section *section, uint64_t *size)
{
struct pt_sec_windows_mapping *mapping;
const uint8_t *begin, *end;
if (!section || !size)
return -pte_internal;
mapping = section->mapping;
if (!mapping)
return -pte_internal;
begin = mapping->base;
end = mapping->end;
if (!begin || !end || end < begin)
return -pte_internal;
*size = (uint64_t) (end - begin);
return 0;
}

View File

@ -0,0 +1,425 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "ptunit.h"
#include "pt_asid.h"
#include "intel-pt.h"
#include <stddef.h>
static struct ptunit_result from_user_null(void)
{
struct pt_asid user;
int errcode;
pt_asid_init(&user);
errcode = pt_asid_from_user(NULL, NULL);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_asid_from_user(NULL, &user);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result from_user_default(void)
{
struct pt_asid asid;
int errcode;
errcode = pt_asid_from_user(&asid, NULL);
ptu_int_eq(errcode, 0);
ptu_uint_eq(asid.size, sizeof(asid));
ptu_uint_eq(asid.cr3, pt_asid_no_cr3);
ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs);
return ptu_passed();
}
static struct ptunit_result from_user_small(void)
{
struct pt_asid asid, user;
int errcode;
user.size = sizeof(user.size);
errcode = pt_asid_from_user(&asid, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(asid.size, sizeof(asid));
ptu_uint_eq(asid.cr3, pt_asid_no_cr3);
ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs);
return ptu_passed();
}
static struct ptunit_result from_user_big(void)
{
struct pt_asid asid, user;
int errcode;
user.size = sizeof(user) + 4;
user.cr3 = 0x4200ull;
user.vmcs = 0x23000ull;
errcode = pt_asid_from_user(&asid, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(asid.size, sizeof(asid));
ptu_uint_eq(asid.cr3, 0x4200ull);
ptu_uint_eq(asid.vmcs, 0x23000ull);
return ptu_passed();
}
static struct ptunit_result from_user(void)
{
struct pt_asid asid, user;
int errcode;
user.size = sizeof(user);
user.cr3 = 0x4200ull;
user.vmcs = 0x23000ull;
errcode = pt_asid_from_user(&asid, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(asid.size, sizeof(asid));
ptu_uint_eq(asid.cr3, 0x4200ull);
ptu_uint_eq(asid.vmcs, 0x23000ull);
return ptu_passed();
}
static struct ptunit_result from_user_cr3(void)
{
struct pt_asid asid, user;
int errcode;
user.size = offsetof(struct pt_asid, vmcs);
user.cr3 = 0x4200ull;
user.vmcs = 0x23000ull;
errcode = pt_asid_from_user(&asid, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(asid.size, sizeof(asid));
ptu_uint_eq(asid.cr3, 0x4200ull);
ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs);
return ptu_passed();
}
static struct ptunit_result to_user_null(void)
{
struct pt_asid asid;
int errcode;
pt_asid_init(&asid);
errcode = pt_asid_to_user(NULL, NULL, sizeof(asid));
ptu_int_eq(errcode, -pte_internal);
errcode = pt_asid_to_user(NULL, &asid, sizeof(asid));
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result to_user_too_small(void)
{
struct pt_asid asid, user;
int errcode;
pt_asid_init(&asid);
errcode = pt_asid_to_user(&user, &asid, 0);
ptu_int_eq(errcode, -pte_invalid);
errcode = pt_asid_to_user(&user, &asid, sizeof(user.size) - 1);
ptu_int_eq(errcode, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result to_user_small(void)
{
struct pt_asid asid, user;
int errcode;
memset(&user, 0xcc, sizeof(user));
pt_asid_init(&asid);
errcode = pt_asid_to_user(&user, &asid, sizeof(user.size));
ptu_int_eq(errcode, 0);
ptu_uint_eq(user.size, sizeof(user.size));
ptu_uint_eq(user.cr3, 0xccccccccccccccccull);
ptu_uint_eq(user.vmcs, 0xccccccccccccccccull);
return ptu_passed();
}
static struct ptunit_result to_user_big(void)
{
struct pt_asid asid, user;
int errcode;
memset(&user, 0xcc, sizeof(user));
pt_asid_init(&asid);
asid.cr3 = 0x4200ull;
asid.vmcs = 0x23000ull;
errcode = pt_asid_to_user(&user, &asid, sizeof(user) + 8);
ptu_int_eq(errcode, 0);
ptu_uint_eq(user.size, sizeof(asid));
ptu_uint_eq(user.cr3, 0x4200ull);
ptu_uint_eq(user.vmcs, 0x23000ull);
return ptu_passed();
}
static struct ptunit_result to_user(void)
{
struct pt_asid asid, user;
int errcode;
memset(&user, 0xcc, sizeof(user));
pt_asid_init(&asid);
asid.cr3 = 0x4200ull;
asid.vmcs = 0x23000ull;
errcode = pt_asid_to_user(&user, &asid, sizeof(user));
ptu_int_eq(errcode, 0);
ptu_uint_eq(user.size, sizeof(asid));
ptu_uint_eq(user.cr3, 0x4200ull);
ptu_uint_eq(user.vmcs, 0x23000ull);
return ptu_passed();
}
static struct ptunit_result to_user_cr3(void)
{
struct pt_asid asid, user;
int errcode;
memset(&user, 0xcc, sizeof(user));
pt_asid_init(&asid);
asid.cr3 = 0x4200ull;
errcode = pt_asid_to_user(&user, &asid, offsetof(struct pt_asid, vmcs));
ptu_int_eq(errcode, 0);
ptu_uint_eq(user.size, offsetof(struct pt_asid, vmcs));
ptu_uint_eq(user.cr3, 0x4200ull);
ptu_uint_eq(user.vmcs, 0xccccccccccccccccull);
return ptu_passed();
}
static struct ptunit_result match_null(void)
{
struct pt_asid asid;
int errcode;
pt_asid_init(&asid);
errcode = pt_asid_match(NULL, NULL);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_asid_match(NULL, &asid);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_asid_match(&asid, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result match_default(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
lhs.cr3 = 0x2300ull;
lhs.vmcs = 0x42000ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
errcode = pt_asid_match(&rhs, &lhs);
ptu_int_eq(errcode, 1);
return ptu_passed();
}
static struct ptunit_result match_default_mixed(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
lhs.cr3 = 0x2300ull;
rhs.vmcs = 0x42000ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
errcode = pt_asid_match(&rhs, &lhs);
ptu_int_eq(errcode, 1);
return ptu_passed();
}
static struct ptunit_result match_cr3(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
lhs.cr3 = 0x2300ull;
rhs.cr3 = 0x2300ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
return ptu_passed();
}
static struct ptunit_result match_vmcs(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
lhs.vmcs = 0x23000ull;
rhs.vmcs = 0x23000ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
return ptu_passed();
}
static struct ptunit_result match(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
lhs.cr3 = 0x2300ull;
rhs.cr3 = 0x2300ull;
lhs.vmcs = 0x23000ull;
rhs.vmcs = 0x23000ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 1);
return ptu_passed();
}
static struct ptunit_result match_cr3_false(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
lhs.cr3 = 0x4200ull;
rhs.cr3 = 0x2300ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 0);
return ptu_passed();
}
static struct ptunit_result match_vmcs_false(void)
{
struct pt_asid lhs, rhs;
int errcode;
pt_asid_init(&lhs);
pt_asid_init(&rhs);
lhs.vmcs = 0x42000ull;
rhs.vmcs = 0x23000ull;
errcode = pt_asid_match(&lhs, &rhs);
ptu_int_eq(errcode, 0);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, from_user_null);
ptu_run(suite, from_user_default);
ptu_run(suite, from_user_small);
ptu_run(suite, from_user_big);
ptu_run(suite, from_user);
ptu_run(suite, from_user_cr3);
ptu_run(suite, to_user_null);
ptu_run(suite, to_user_too_small);
ptu_run(suite, to_user_small);
ptu_run(suite, to_user_big);
ptu_run(suite, to_user);
ptu_run(suite, to_user_cr3);
ptu_run(suite, match_null);
ptu_run(suite, match_default);
ptu_run(suite, match_default_mixed);
ptu_run(suite, match_cr3);
ptu_run(suite, match_vmcs);
ptu_run(suite, match);
ptu_run(suite, match_cr3_false);
ptu_run(suite, match_vmcs_false);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,370 @@
/*
* Copyright (c) 2016-2018, 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.
*/
#include "ptunit_threads.h"
#include "pt_block_cache.h"
#include <string.h>
/* A test fixture optionally providing a block cache and automatically freeing
* the cache.
*/
struct bcache_fixture {
/* Threading support. */
struct ptunit_thrd_fixture thrd;
/* The cache - it will be freed automatically. */
struct pt_block_cache *bcache;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct bcache_fixture *);
struct ptunit_result (*fini)(struct bcache_fixture *);
};
enum {
/* The number of entries in fixture-provided caches. */
bfix_nentries = 0x10000,
#if defined(FEATURE_THREADS)
/* The number of additional threads to use for stress testing. */
bfix_threads = 3,
#endif /* defined(FEATURE_THREADS) */
/* The number of iterations in stress testing. */
bfix_iterations = 0x10
};
static struct ptunit_result cfix_init(struct bcache_fixture *bfix)
{
ptu_test(ptunit_thrd_init, &bfix->thrd);
bfix->bcache = NULL;
return ptu_passed();
}
static struct ptunit_result bfix_init(struct bcache_fixture *bfix)
{
ptu_test(cfix_init, bfix);
bfix->bcache = pt_bcache_alloc(bfix_nentries);
ptu_ptr(bfix->bcache);
return ptu_passed();
}
static struct ptunit_result bfix_fini(struct bcache_fixture *bfix)
{
int thrd;
ptu_test(ptunit_thrd_fini, &bfix->thrd);
for (thrd = 0; thrd < bfix->thrd.nthreads; ++thrd)
ptu_int_eq(bfix->thrd.result[thrd], 0);
pt_bcache_free(bfix->bcache);
return ptu_passed();
}
static struct ptunit_result bcache_entry_size(void)
{
ptu_uint_eq(sizeof(struct pt_bcache_entry), sizeof(uint32_t));
return ptu_passed();
}
static struct ptunit_result bcache_size(void)
{
ptu_uint_le(sizeof(struct pt_block_cache),
2 * sizeof(struct pt_bcache_entry));
return ptu_passed();
}
static struct ptunit_result free_null(void)
{
pt_bcache_free(NULL);
return ptu_passed();
}
static struct ptunit_result add_null(void)
{
struct pt_bcache_entry bce;
int errcode;
memset(&bce, 0, sizeof(bce));
errcode = pt_bcache_add(NULL, 0ull, bce);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result lookup_null(void)
{
struct pt_bcache_entry bce;
struct pt_block_cache bcache;
int errcode;
errcode = pt_bcache_lookup(&bce, NULL, 0ull);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_bcache_lookup(NULL, &bcache, 0ull);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result alloc(struct bcache_fixture *bfix)
{
bfix->bcache = pt_bcache_alloc(0x10000ull);
ptu_ptr(bfix->bcache);
return ptu_passed();
}
static struct ptunit_result alloc_min(struct bcache_fixture *bfix)
{
bfix->bcache = pt_bcache_alloc(1ull);
ptu_ptr(bfix->bcache);
return ptu_passed();
}
static struct ptunit_result alloc_too_big(struct bcache_fixture *bfix)
{
bfix->bcache = pt_bcache_alloc(UINT32_MAX + 1ull);
ptu_null(bfix->bcache);
return ptu_passed();
}
static struct ptunit_result alloc_zero(struct bcache_fixture *bfix)
{
bfix->bcache = pt_bcache_alloc(0ull);
ptu_null(bfix->bcache);
return ptu_passed();
}
static struct ptunit_result initially_empty(struct bcache_fixture *bfix)
{
uint64_t index;
for (index = 0; index < bfix_nentries; ++index) {
struct pt_bcache_entry bce;
int status;
memset(&bce, 0xff, sizeof(bce));
status = pt_bcache_lookup(&bce, bfix->bcache, index);
ptu_int_eq(status, 0);
status = pt_bce_is_valid(bce);
ptu_int_eq(status, 0);
}
return ptu_passed();
}
static struct ptunit_result add_bad_index(struct bcache_fixture *bfix)
{
struct pt_bcache_entry bce;
int errcode;
memset(&bce, 0, sizeof(bce));
errcode = pt_bcache_add(bfix->bcache, bfix_nentries, bce);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result lookup_bad_index(struct bcache_fixture *bfix)
{
struct pt_bcache_entry bce;
int errcode;
errcode = pt_bcache_lookup(&bce, bfix->bcache, bfix_nentries);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result add(struct bcache_fixture *bfix, uint64_t index)
{
struct pt_bcache_entry bce, exp;
int errcode;
memset(&bce, 0xff, sizeof(bce));
memset(&exp, 0x00, sizeof(exp));
exp.ninsn = 1;
exp.displacement = 7;
exp.mode = ptem_64bit;
exp.qualifier = ptbq_decode;
exp.isize = 7;
errcode = pt_bcache_add(bfix->bcache, index, exp);
ptu_int_eq(errcode, 0);
errcode = pt_bcache_lookup(&bce, bfix->bcache, index);
ptu_int_eq(errcode, 0);
ptu_uint_eq(bce.ninsn, exp.ninsn);
ptu_int_eq(bce.displacement, exp.displacement);
ptu_uint_eq(pt_bce_exec_mode(bce), pt_bce_exec_mode(exp));
ptu_uint_eq(pt_bce_qualifier(bce), pt_bce_qualifier(exp));
ptu_uint_eq(bce.isize, exp.isize);
return ptu_passed();
}
static int worker(void *arg)
{
struct pt_bcache_entry exp;
struct pt_block_cache *bcache;
uint64_t iter, index;
bcache = arg;
if (!bcache)
return -pte_internal;
memset(&exp, 0x00, sizeof(exp));
exp.ninsn = 5;
exp.displacement = 28;
exp.mode = ptem_64bit;
exp.qualifier = ptbq_again;
exp.isize = 3;
for (index = 0; index < bfix_nentries; ++index) {
for (iter = 0; iter < bfix_iterations; ++iter) {
struct pt_bcache_entry bce;
int errcode;
memset(&bce, 0xff, sizeof(bce));
errcode = pt_bcache_lookup(&bce, bcache, index);
if (errcode < 0)
return errcode;
if (!pt_bce_is_valid(bce)) {
errcode = pt_bcache_add(bcache, index, exp);
if (errcode < 0)
return errcode;
}
errcode = pt_bcache_lookup(&bce, bcache, index);
if (errcode < 0)
return errcode;
if (!pt_bce_is_valid(bce))
return -pte_nosync;
if (bce.ninsn != exp.ninsn)
return -pte_nosync;
if (bce.displacement != exp.displacement)
return -pte_nosync;
if (pt_bce_exec_mode(bce) != pt_bce_exec_mode(exp))
return -pte_nosync;
if (pt_bce_qualifier(bce) != pt_bce_qualifier(exp))
return -pte_nosync;
if (bce.isize != exp.isize)
return -pte_nosync;
}
}
return 0;
}
static struct ptunit_result stress(struct bcache_fixture *bfix)
{
int errcode;
#if defined(FEATURE_THREADS)
{
int thrd;
for (thrd = 0; thrd < bfix_threads; ++thrd)
ptu_test(ptunit_thrd_create, &bfix->thrd, worker,
bfix->bcache);
}
#endif /* defined(FEATURE_THREADS) */
errcode = worker(bfix->bcache);
ptu_int_eq(errcode, 0);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct bcache_fixture bfix, cfix;
struct ptunit_suite suite;
bfix.init = bfix_init;
bfix.fini = bfix_fini;
cfix.init = cfix_init;
cfix.fini = bfix_fini;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, bcache_entry_size);
ptu_run(suite, bcache_size);
ptu_run(suite, free_null);
ptu_run(suite, add_null);
ptu_run(suite, lookup_null);
ptu_run_f(suite, alloc, cfix);
ptu_run_f(suite, alloc_min, cfix);
ptu_run_f(suite, alloc_too_big, cfix);
ptu_run_f(suite, alloc_zero, cfix);
ptu_run_f(suite, initially_empty, bfix);
ptu_run_f(suite, add_bad_index, bfix);
ptu_run_f(suite, lookup_bad_index, bfix);
ptu_run_fp(suite, add, bfix, 0ull);
ptu_run_fp(suite, add, bfix, bfix_nentries - 1ull);
ptu_run_f(suite, stress, bfix);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,496 @@
/*
* Copyright (c) 2015-2018, 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.
*/
#include "ptunit.h"
#include "pt_config.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
#include <stddef.h>
/* A global fake buffer to pacify static analyzers. */
static uint8_t buffer[8];
static struct ptunit_result from_user_null(void)
{
struct pt_config config;
int errcode;
errcode = pt_config_from_user(NULL, &config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_config_from_user(&config, NULL);
ptu_int_eq(errcode, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result from_user_too_small(void)
{
struct pt_config config, user;
int errcode;
user.size = sizeof(config.size);
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, -pte_bad_config);
return ptu_passed();
}
static struct ptunit_result from_user_bad_buffer(void)
{
struct pt_config config, user;
int errcode;
pt_config_init(&user);
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, -pte_bad_config);
user.begin = buffer;
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, -pte_bad_config);
user.begin = NULL;
user.end = buffer;
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, -pte_bad_config);
user.begin = &buffer[1];
user.end = buffer;
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, -pte_bad_config);
return ptu_passed();
}
static struct ptunit_result from_user(void)
{
struct pt_config config, user;
int errcode;
user.size = sizeof(user);
user.begin = buffer;
user.end = &buffer[sizeof(buffer)];
user.cpu.vendor = pcv_intel;
user.errata.bdm70 = 1;
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(config.size, sizeof(config));
ptu_ptr_eq(config.begin, buffer);
ptu_ptr_eq(config.end, &buffer[sizeof(buffer)]);
ptu_int_eq(config.cpu.vendor, pcv_intel);
ptu_uint_eq(config.errata.bdm70, 1);
return ptu_passed();
}
static struct ptunit_result from_user_small(void)
{
struct pt_config config, user;
int errcode;
memset(&config, 0xcd, sizeof(config));
user.size = offsetof(struct pt_config, cpu);
user.begin = buffer;
user.end = &buffer[sizeof(buffer)];
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(config.size, offsetof(struct pt_config, cpu));
ptu_ptr_eq(config.begin, buffer);
ptu_ptr_eq(config.end, &buffer[sizeof(buffer)]);
ptu_int_eq(config.cpu.vendor, pcv_unknown);
ptu_uint_eq(config.errata.bdm70, 0);
return ptu_passed();
}
static struct ptunit_result from_user_big(void)
{
struct pt_config config, user;
int errcode;
user.size = sizeof(user) + 4;
user.begin = buffer;
user.end = &buffer[sizeof(buffer)];
user.cpu.vendor = pcv_intel;
user.errata.bdm70 = 1;
errcode = pt_config_from_user(&config, &user);
ptu_int_eq(errcode, 0);
ptu_uint_eq(config.size, sizeof(config));
ptu_ptr_eq(config.begin, buffer);
ptu_ptr_eq(config.end, &buffer[sizeof(buffer)]);
ptu_int_eq(config.cpu.vendor, pcv_intel);
ptu_uint_eq(config.errata.bdm70, 1);
return ptu_passed();
}
static struct ptunit_result size(void)
{
ptu_uint_eq(sizeof(struct pt_errata), 16 * 4);
return ptu_passed();
}
static struct ptunit_result addr_filter_size(void)
{
struct pt_conf_addr_filter conf;
ptu_uint_eq(sizeof(conf.config), 8);
return ptu_passed();
}
static struct ptunit_result addr_filter_none(void)
{
struct pt_config config;
uint8_t filter;
pt_config_init(&config);
ptu_uint_eq(config.addr_filter.config.addr_cfg, 0ull);
for (filter = 0; filter < 4; ++filter) {
uint32_t addr_cfg;
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, filter);
ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
}
return ptu_passed();
}
static struct ptunit_result addr_filter_0(void)
{
struct pt_config config;
uint64_t addr_a, addr_b;
uint32_t addr_cfg;
uint8_t filter;
pt_config_init(&config);
config.addr_filter.config.ctl.addr0_cfg = pt_addr_cfg_filter;
config.addr_filter.addr0_a = 0xa000ull;
config.addr_filter.addr0_b = 0xb000ull;
ptu_uint_ne(config.addr_filter.config.addr_cfg, 0ull);
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 0);
ptu_uint_eq(addr_cfg, pt_addr_cfg_filter);
addr_a = pt_filter_addr_a(&config.addr_filter, 0);
ptu_uint_eq(addr_a, 0xa000ull);
addr_b = pt_filter_addr_b(&config.addr_filter, 0);
ptu_uint_eq(addr_b, 0xb000ull);
for (filter = 1; filter < 4; ++filter) {
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, filter);
ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
}
return ptu_passed();
}
static struct ptunit_result addr_filter_1_3(void)
{
struct pt_config config;
uint64_t addr_a, addr_b;
uint32_t addr_cfg;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
config.addr_filter.addr1_a = 0xa000ull;
config.addr_filter.addr1_b = 0xb000ull;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
config.addr_filter.addr3_a = 0x100a000ull;
config.addr_filter.addr3_b = 0x100b000ull;
ptu_uint_ne(config.addr_filter.config.addr_cfg, 0ull);
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 0);
ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 1);
ptu_uint_eq(addr_cfg, pt_addr_cfg_filter);
addr_a = pt_filter_addr_a(&config.addr_filter, 1);
ptu_uint_eq(addr_a, 0xa000ull);
addr_b = pt_filter_addr_b(&config.addr_filter, 1);
ptu_uint_eq(addr_b, 0xb000ull);
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 2);
ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, 3);
ptu_uint_eq(addr_cfg, pt_addr_cfg_stop);
addr_a = pt_filter_addr_a(&config.addr_filter, 3);
ptu_uint_eq(addr_a, 0x100a000ull);
addr_b = pt_filter_addr_b(&config.addr_filter, 3);
ptu_uint_eq(addr_b, 0x100b000ull);
return ptu_passed();
}
static struct ptunit_result addr_filter_oob(uint8_t filter)
{
struct pt_config config;
uint64_t addr_a, addr_b;
uint32_t addr_cfg;
pt_config_init(&config);
memset(&config.addr_filter, 0xcc, sizeof(config.addr_filter));
addr_cfg = pt_filter_addr_cfg(&config.addr_filter, filter);
ptu_uint_eq(addr_cfg, pt_addr_cfg_disabled);
addr_a = pt_filter_addr_a(&config.addr_filter, filter);
ptu_uint_eq(addr_a, 0ull);
addr_b = pt_filter_addr_b(&config.addr_filter, filter);
ptu_uint_eq(addr_b, 0ull);
return ptu_passed();
}
static struct ptunit_result addr_filter_ip_in(void)
{
struct pt_config config;
int status;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
config.addr_filter.addr1_a = 0xa000;
config.addr_filter.addr1_b = 0xb000;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_filter;
config.addr_filter.addr3_a = 0x10a000;
config.addr_filter.addr3_b = 0x10b000;
status = pt_filter_addr_check(&config.addr_filter, 0xa000);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0xaf00);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0xb000);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0x10a000);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0x10af00);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0x10b000);
ptu_int_eq(status, 1);
return ptu_passed();
}
static struct ptunit_result addr_filter_ip_out(void)
{
struct pt_config config;
int status;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
config.addr_filter.addr1_a = 0xa000;
config.addr_filter.addr1_b = 0xb000;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_filter;
config.addr_filter.addr3_a = 0x10a000;
config.addr_filter.addr3_b = 0x10b000;
status = pt_filter_addr_check(&config.addr_filter, 0xfff);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0xb001);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x100fff);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x10b001);
ptu_int_eq(status, 0);
return ptu_passed();
}
static struct ptunit_result addr_filter_stop_in(void)
{
struct pt_config config;
int status;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_stop;
config.addr_filter.addr1_a = 0xa000;
config.addr_filter.addr1_b = 0xb000;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
config.addr_filter.addr3_a = 0x10a000;
config.addr_filter.addr3_b = 0x10b000;
status = pt_filter_addr_check(&config.addr_filter, 0xa000);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0xaf00);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0xb000);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x10a000);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x10af00);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x10b000);
ptu_int_eq(status, 0);
return ptu_passed();
}
static struct ptunit_result addr_filter_stop_out(void)
{
struct pt_config config;
int status;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_stop;
config.addr_filter.addr1_a = 0xa000;
config.addr_filter.addr1_b = 0xb000;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
config.addr_filter.addr3_a = 0x10a000;
config.addr_filter.addr3_b = 0x10b000;
status = pt_filter_addr_check(&config.addr_filter, 0xfff);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0xb001);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0x100fff);
ptu_int_eq(status, 1);
status = pt_filter_addr_check(&config.addr_filter, 0x10b001);
ptu_int_eq(status, 1);
return ptu_passed();
}
static struct ptunit_result addr_filter_ip_out_stop_in(void)
{
struct pt_config config;
int status;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
config.addr_filter.addr1_a = 0x100f00;
config.addr_filter.addr1_b = 0x10af00;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
config.addr_filter.addr3_a = 0x10a000;
config.addr_filter.addr3_b = 0x10b000;
status = pt_filter_addr_check(&config.addr_filter, 0x10af01);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x10b000);
ptu_int_eq(status, 0);
return ptu_passed();
}
static struct ptunit_result addr_filter_ip_in_stop_in(void)
{
struct pt_config config;
int status;
pt_config_init(&config);
config.addr_filter.config.ctl.addr1_cfg = pt_addr_cfg_filter;
config.addr_filter.addr1_a = 0x100f00;
config.addr_filter.addr1_b = 0x10af00;
config.addr_filter.config.ctl.addr3_cfg = pt_addr_cfg_stop;
config.addr_filter.addr3_a = 0x10a000;
config.addr_filter.addr3_b = 0x10b000;
status = pt_filter_addr_check(&config.addr_filter, 0x10af00);
ptu_int_eq(status, 0);
status = pt_filter_addr_check(&config.addr_filter, 0x10a0ff);
ptu_int_eq(status, 0);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, from_user_null);
ptu_run(suite, from_user_too_small);
ptu_run(suite, from_user_bad_buffer);
ptu_run(suite, from_user);
ptu_run(suite, from_user_small);
ptu_run(suite, from_user_big);
ptu_run(suite, size);
ptu_run(suite, addr_filter_size);
ptu_run(suite, addr_filter_none);
ptu_run(suite, addr_filter_0);
ptu_run(suite, addr_filter_1_3);
ptu_run_p(suite, addr_filter_oob, 255);
ptu_run_p(suite, addr_filter_oob, 8);
ptu_run(suite, addr_filter_ip_in);
ptu_run(suite, addr_filter_ip_out);
ptu_run(suite, addr_filter_stop_in);
ptu_run(suite, addr_filter_stop_out);
ptu_run(suite, addr_filter_ip_out_stop_in);
ptu_run(suite, addr_filter_ip_in_stop_in);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "ptunit.h"
#include "intel-pt.h"
static struct ptunit_result init_packet_decoder(void)
{
uint8_t buf[1];
struct pt_config config;
struct pt_packet_decoder *decoder;
pt_config_init(&config);
config.begin = buf;
config.end = buf + sizeof(buf);
decoder = pt_pkt_alloc_decoder(&config);
ptu_ptr(decoder);
pt_pkt_free_decoder(decoder);
return ptu_passed();
}
static struct ptunit_result init_query_decoder(void)
{
uint8_t buf[1];
struct pt_config config;
struct pt_query_decoder *query_decoder;
pt_config_init(&config);
config.begin = buf;
config.end = buf + sizeof(buf);
query_decoder = pt_qry_alloc_decoder(&config);
ptu_ptr(query_decoder);
pt_qry_free_decoder(query_decoder);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, init_packet_decoder);
ptu_run(suite, init_query_decoder);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "ptunit.h"
#include "pt_cpu.h"
#include "pt_cpuid.h"
#include "intel-pt.h"
#include <stdlib.h>
void pt_cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx)
{
(void) leaf;
(void) eax;
(void) ebx;
(void) ecx;
(void) edx;
}
static struct ptunit_result cpu_valid(void)
{
struct pt_cpu cpu;
int error;
error = pt_cpu_parse(&cpu, "6/44/2");
ptu_int_eq(error, 0);
ptu_int_eq(cpu.vendor, pcv_intel);
ptu_uint_eq(cpu.family, 6);
ptu_uint_eq(cpu.model, 44);
ptu_uint_eq(cpu.stepping, 2);
error = pt_cpu_parse(&cpu, "0xf/0x2c/0xf");
ptu_int_eq(error, 0);
ptu_int_eq(cpu.vendor, pcv_intel);
ptu_uint_eq(cpu.family, 0xf);
ptu_uint_eq(cpu.model, 0x2c);
ptu_uint_eq(cpu.stepping, 0xf);
error = pt_cpu_parse(&cpu, "022/054/017");
ptu_int_eq(error, 0);
ptu_int_eq(cpu.vendor, pcv_intel);
ptu_uint_eq(cpu.family, 022);
ptu_uint_eq(cpu.model, 054);
ptu_uint_eq(cpu.stepping, 017);
error = pt_cpu_parse(&cpu, "6/44");
ptu_int_eq(error, 0);
ptu_int_eq(cpu.vendor, pcv_intel);
ptu_uint_eq(cpu.family, 6);
ptu_uint_eq(cpu.model, 44);
ptu_uint_eq(cpu.stepping, 0);
return ptu_passed();
}
static struct ptunit_result cpu_null(void)
{
struct pt_cpu cpu;
int error;
error = pt_cpu_parse(&cpu, NULL);
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(NULL, "");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(NULL, NULL);
ptu_int_eq(error, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result cpu_incomplete(void)
{
struct pt_cpu cpu;
int error;
error = pt_cpu_parse(&cpu, "");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6//2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "//");
ptu_int_eq(error, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result cpu_invalid(void)
{
struct pt_cpu cpu;
int error;
error = pt_cpu_parse(&cpu, "e/44/2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/e/2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/44/e");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "65536/44/2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/256/2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/44/256");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "-1/44/2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/-1/2");
ptu_int_eq(error, -pte_invalid);
error = pt_cpu_parse(&cpu, "6/44/-1");
ptu_int_eq(error, -pte_invalid);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, cpu_valid);
ptu_run(suite, cpu_null);
ptu_run(suite, cpu_incomplete);
ptu_run(suite, cpu_invalid);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,470 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "ptunit.h"
#include "pt_event_queue.h"
/* A test fixture providing an initialized event queue. */
struct evq_fixture {
/* The event queue. */
struct pt_event_queue evq;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct evq_fixture *);
struct ptunit_result (*fini)(struct evq_fixture *);
};
static struct ptunit_result efix_init(struct evq_fixture *efix)
{
pt_evq_init(&efix->evq);
return ptu_passed();
}
static struct ptunit_result efix_init_pending(struct evq_fixture *efix)
{
struct pt_event *ev;
int evb;
pt_evq_init(&efix->evq);
for (evb = 0; evb < evb_max; ++evb) {
ev = pt_evq_enqueue(&efix->evq, (enum pt_event_binding) evb);
ptu_ptr(ev);
}
return ptu_passed();
}
static struct ptunit_result standalone_null(void)
{
struct pt_event *ev;
ev = pt_evq_standalone(NULL);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result standalone(struct evq_fixture *efix)
{
struct pt_event *ev;
ev = pt_evq_standalone(&efix->evq);
ptu_ptr(ev);
ptu_uint_eq(ev->ip_suppressed, 0ul);
ptu_uint_eq(ev->status_update, 0ul);
return ptu_passed();
}
static struct ptunit_result enqueue_null(enum pt_event_binding evb)
{
struct pt_event *ev;
ev = pt_evq_enqueue(NULL, evb);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result dequeue_null(enum pt_event_binding evb)
{
struct pt_event *ev;
ev = pt_evq_dequeue(NULL, evb);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result dequeue_empty(struct evq_fixture *efix,
enum pt_event_binding evb)
{
struct pt_event *ev;
ev = pt_evq_dequeue(&efix->evq, evb);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result evq_empty(struct evq_fixture *efix,
enum pt_event_binding evb)
{
int status;
status = pt_evq_empty(&efix->evq, evb);
ptu_int_gt(status, 0);
status = pt_evq_pending(&efix->evq, evb);
ptu_int_eq(status, 0);
return ptu_passed();
}
static struct ptunit_result evq_pending(struct evq_fixture *efix,
enum pt_event_binding evb)
{
int status;
status = pt_evq_empty(&efix->evq, evb);
ptu_int_eq(status, 0);
status = pt_evq_pending(&efix->evq, evb);
ptu_int_gt(status, 0);
return ptu_passed();
}
static struct ptunit_result evq_others_empty(struct evq_fixture *efix,
enum pt_event_binding evb)
{
int other;
for (other = 0; other < evb_max; ++other) {
enum pt_event_binding ob;
ob = (enum pt_event_binding) other;
if (ob != evb)
ptu_test(evq_empty, efix, ob);
}
return ptu_passed();
}
static struct ptunit_result enqueue_all_dequeue(struct evq_fixture *efix,
enum pt_event_binding evb,
size_t num)
{
struct pt_event *in[evq_max], *out[evq_max];
size_t idx;
ptu_uint_le(num, evq_max - 2);
for (idx = 0; idx < num; ++idx) {
in[idx] = pt_evq_enqueue(&efix->evq, evb);
ptu_ptr(in[idx]);
}
ptu_test(evq_pending, efix, evb);
ptu_test(evq_others_empty, efix, evb);
for (idx = 0; idx < num; ++idx) {
out[idx] = pt_evq_dequeue(&efix->evq, evb);
ptu_ptr_eq(out[idx], in[idx]);
}
ptu_test(evq_empty, efix, evb);
return ptu_passed();
}
static struct ptunit_result enqueue_one_dequeue(struct evq_fixture *efix,
enum pt_event_binding evb,
size_t num)
{
size_t idx;
for (idx = 0; idx < num; ++idx) {
struct pt_event *in, *out;
in = pt_evq_enqueue(&efix->evq, evb);
ptu_ptr(in);
out = pt_evq_dequeue(&efix->evq, evb);
ptu_ptr_eq(out, in);
}
return ptu_passed();
}
static struct ptunit_result overflow(struct evq_fixture *efix,
enum pt_event_binding evb,
size_t num)
{
struct pt_event *in[evq_max], *out[evq_max], *ev;
size_t idx;
ptu_uint_le(num, evq_max - 2);
for (idx = 0; idx < (evq_max - 2); ++idx) {
in[idx] = pt_evq_enqueue(&efix->evq, evb);
ptu_ptr(in[idx]);
}
for (idx = 0; idx < num; ++idx) {
ev = pt_evq_enqueue(&efix->evq, evb);
ptu_null(ev);
}
for (idx = 0; idx < num; ++idx) {
out[idx] = pt_evq_dequeue(&efix->evq, evb);
ptu_ptr_eq(out[idx], in[idx]);
}
return ptu_passed();
}
static struct ptunit_result clear_null(enum pt_event_binding evb)
{
int errcode;
errcode = pt_evq_clear(NULL, evb);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result clear(struct evq_fixture *efix,
enum pt_event_binding evb)
{
int errcode;
errcode = pt_evq_clear(&efix->evq, evb);
ptu_int_eq(errcode, 0);
ptu_test(evq_empty, efix, evb);
return ptu_passed();
}
static struct ptunit_result empty_null(enum pt_event_binding evb)
{
int errcode;
errcode = pt_evq_empty(NULL, evb);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result pending_null(enum pt_event_binding evb)
{
int errcode;
errcode = pt_evq_pending(NULL, evb);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result find_null(enum pt_event_binding evb,
enum pt_event_type evt)
{
struct pt_event *ev;
ev = pt_evq_find(NULL, evb, evt);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result find_empty(struct evq_fixture *efix,
enum pt_event_binding evb,
enum pt_event_type evt)
{
struct pt_event *ev;
ev = pt_evq_find(&efix->evq, evb, evt);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result find_none_evb(struct evq_fixture *efix,
enum pt_event_binding evb,
enum pt_event_type evt)
{
struct pt_event *ev;
size_t other;
for (other = 0; other < evb_max; ++other) {
enum pt_event_binding ob;
ob = (enum pt_event_binding) other;
if (ob != evb) {
ev = pt_evq_enqueue(&efix->evq, ob);
ptu_ptr(ev);
ev->type = evt;
}
}
ev = pt_evq_find(&efix->evq, evb, evt);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result evq_enqueue_other(struct evq_fixture *efix,
enum pt_event_binding evb,
enum pt_event_type evt,
size_t num)
{
enum pt_event_type ot;
struct pt_event *ev;
size_t other;
for (other = 0; other < num; ++other) {
ot = (enum pt_event_type) other;
if (ot != evt) {
ev = pt_evq_enqueue(&efix->evq, evb);
ptu_ptr(ev);
ev->type = ot;
}
}
return ptu_passed();
}
static struct ptunit_result find_none_evt(struct evq_fixture *efix,
enum pt_event_binding evb,
enum pt_event_type evt,
size_t num)
{
struct pt_event *ev;
ptu_test(evq_enqueue_other, efix, evb, evt, num);
ev = pt_evq_find(&efix->evq, evb, evt);
ptu_null(ev);
return ptu_passed();
}
static struct ptunit_result find(struct evq_fixture *efix,
enum pt_event_binding evb,
enum pt_event_type evt,
size_t before, size_t after)
{
struct pt_event *in, *out;
ptu_test(evq_enqueue_other, efix, evb, evt, before);
in = pt_evq_enqueue(&efix->evq, evb);
ptu_ptr(in);
in->type = evt;
ptu_test(evq_enqueue_other, efix, evb, evt, after);
out = pt_evq_find(&efix->evq, evb, evt);
ptu_ptr_eq(out, in);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct evq_fixture efix, pfix;
struct ptunit_suite suite;
efix.init = efix_init;
efix.fini = NULL;
pfix.init = efix_init_pending;
pfix.fini = NULL;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, standalone_null);
ptu_run_f(suite, standalone, efix);
ptu_run_p(suite, enqueue_null, evb_psbend);
ptu_run_p(suite, enqueue_null, evb_tip);
ptu_run_p(suite, enqueue_null, evb_fup);
ptu_run_p(suite, dequeue_null, evb_psbend);
ptu_run_p(suite, dequeue_null, evb_tip);
ptu_run_p(suite, dequeue_null, evb_fup);
ptu_run_fp(suite, dequeue_empty, efix, evb_psbend);
ptu_run_fp(suite, dequeue_empty, efix, evb_tip);
ptu_run_fp(suite, dequeue_empty, efix, evb_fup);
ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_psbend, 1);
ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_psbend, 2);
ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_tip, 1);
ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_tip, 3);
ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_fup, 1);
ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_fup, 4);
ptu_run_fp(suite, enqueue_one_dequeue, efix, evb_psbend, evb_max * 2);
ptu_run_fp(suite, enqueue_one_dequeue, efix, evb_tip, evb_max * 2);
ptu_run_fp(suite, enqueue_one_dequeue, efix, evb_fup, evb_max * 2);
ptu_run_fp(suite, overflow, efix, evb_psbend, 1);
ptu_run_fp(suite, overflow, efix, evb_tip, 2);
ptu_run_fp(suite, overflow, efix, evb_fup, 3);
ptu_run_p(suite, clear_null, evb_psbend);
ptu_run_p(suite, clear_null, evb_tip);
ptu_run_p(suite, clear_null, evb_fup);
ptu_run_fp(suite, clear, efix, evb_psbend);
ptu_run_fp(suite, clear, pfix, evb_psbend);
ptu_run_fp(suite, clear, efix, evb_tip);
ptu_run_fp(suite, clear, pfix, evb_tip);
ptu_run_fp(suite, clear, efix, evb_fup);
ptu_run_fp(suite, clear, pfix, evb_fup);
ptu_run_p(suite, empty_null, evb_psbend);
ptu_run_p(suite, empty_null, evb_tip);
ptu_run_p(suite, empty_null, evb_fup);
ptu_run_p(suite, pending_null, evb_psbend);
ptu_run_p(suite, pending_null, evb_tip);
ptu_run_p(suite, pending_null, evb_fup);
ptu_run_p(suite, find_null, evb_psbend, ptev_enabled);
ptu_run_p(suite, find_null, evb_tip, ptev_disabled);
ptu_run_p(suite, find_null, evb_fup, ptev_paging);
ptu_run_fp(suite, find_empty, efix, evb_psbend, ptev_enabled);
ptu_run_fp(suite, find_empty, efix, evb_tip, ptev_disabled);
ptu_run_fp(suite, find_empty, efix, evb_fup, ptev_paging);
ptu_run_fp(suite, find_none_evb, efix, evb_psbend, ptev_enabled);
ptu_run_fp(suite, find_none_evb, efix, evb_tip, ptev_disabled);
ptu_run_fp(suite, find_none_evb, efix, evb_fup, ptev_paging);
ptu_run_fp(suite, find_none_evt, efix, evb_psbend, ptev_enabled, 3);
ptu_run_fp(suite, find_none_evt, efix, evb_tip, ptev_disabled, 4);
ptu_run_fp(suite, find_none_evt, efix, evb_fup, ptev_paging, 2);
ptu_run_fp(suite, find, efix, evb_psbend, ptev_enabled, 0, 3);
ptu_run_fp(suite, find, efix, evb_tip, ptev_disabled, 2, 0);
ptu_run_fp(suite, find, efix, evb_fup, ptev_paging, 1, 4);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,693 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "ptunit.h"
#include "pt_decoder_function.h"
#include "pt_packet_decoder.h"
#include "pt_query_decoder.h"
#include "pt_encoder.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
/* A test fixture for decoder function fetch tests. */
struct fetch_fixture {
/* The trace buffer. */
uint8_t buffer[1024];
/* A trace configuration. */
struct pt_config config;
/* A trace encoder. */
struct pt_encoder encoder;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct fetch_fixture *);
struct ptunit_result (*fini)(struct fetch_fixture *);
};
static struct ptunit_result ffix_init(struct fetch_fixture *ffix)
{
memset(ffix->buffer, pt_opc_bad, sizeof(ffix->buffer));
memset(&ffix->config, 0, sizeof(ffix->config));
ffix->config.size = sizeof(ffix->config);
ffix->config.begin = ffix->buffer;
ffix->config.end = ffix->buffer + sizeof(ffix->buffer);
pt_encoder_init(&ffix->encoder, &ffix->config);
return ptu_passed();
}
static struct ptunit_result ffix_fini(struct fetch_fixture *ffix)
{
pt_encoder_fini(&ffix->encoder);
return ptu_passed();
}
static struct ptunit_result fetch_null(struct fetch_fixture *ffix)
{
const struct pt_decoder_function *dfun;
int errcode;
errcode = pt_df_fetch(NULL, ffix->config.begin, &ffix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_df_fetch(&dfun, NULL, &ffix->config);
ptu_int_eq(errcode, -pte_nosync);
errcode = pt_df_fetch(&dfun, ffix->config.begin, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result fetch_empty(struct fetch_fixture *ffix)
{
const struct pt_decoder_function *dfun;
int errcode;
errcode = pt_df_fetch(&dfun, ffix->config.end, &ffix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result fetch_unknown(struct fetch_fixture *ffix)
{
const struct pt_decoder_function *dfun;
int errcode;
ffix->config.begin[0] = pt_opc_bad;
errcode = pt_df_fetch(&dfun, ffix->config.begin, &ffix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(dfun, &pt_decode_unknown);
return ptu_passed();
}
static struct ptunit_result fetch_unknown_ext(struct fetch_fixture *ffix)
{
const struct pt_decoder_function *dfun;
int errcode;
ffix->config.begin[0] = pt_opc_ext;
ffix->config.begin[1] = pt_ext_bad;
errcode = pt_df_fetch(&dfun, ffix->config.begin, &ffix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(dfun, &pt_decode_unknown);
return ptu_passed();
}
static struct ptunit_result fetch_unknown_ext2(struct fetch_fixture *ffix)
{
const struct pt_decoder_function *dfun;
int errcode;
ffix->config.begin[0] = pt_opc_ext;
ffix->config.begin[1] = pt_ext_ext2;
ffix->config.begin[2] = pt_ext2_bad;
errcode = pt_df_fetch(&dfun, ffix->config.begin, &ffix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(dfun, &pt_decode_unknown);
return ptu_passed();
}
static struct ptunit_result fetch_packet(struct fetch_fixture *ffix,
const struct pt_packet *packet,
const struct pt_decoder_function *df)
{
const struct pt_decoder_function *dfun;
int errcode;
errcode = pt_enc_next(&ffix->encoder, packet);
ptu_int_ge(errcode, 0);
errcode = pt_df_fetch(&dfun, ffix->config.begin, &ffix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(dfun, df);
return ptu_passed();
}
static struct ptunit_result fetch_type(struct fetch_fixture *ffix,
enum pt_packet_type type,
const struct pt_decoder_function *dfun)
{
struct pt_packet packet;
memset(&packet, 0, sizeof(packet));
packet.type = type;
ptu_test(fetch_packet, ffix, &packet, dfun);
return ptu_passed();
}
static struct ptunit_result fetch_tnt_8(struct fetch_fixture *ffix)
{
struct pt_packet packet;
memset(&packet, 0, sizeof(packet));
packet.type = ppt_tnt_8;
packet.payload.tnt.bit_size = 1;
ptu_test(fetch_packet, ffix, &packet, &pt_decode_tnt_8);
return ptu_passed();
}
static struct ptunit_result fetch_mode_exec(struct fetch_fixture *ffix)
{
struct pt_packet packet;
memset(&packet, 0, sizeof(packet));
packet.type = ppt_mode;
packet.payload.mode.leaf = pt_mol_exec;
ptu_test(fetch_packet, ffix, &packet, &pt_decode_mode);
return ptu_passed();
}
static struct ptunit_result fetch_mode_tsx(struct fetch_fixture *ffix)
{
struct pt_packet packet;
memset(&packet, 0, sizeof(packet));
packet.type = ppt_mode;
packet.payload.mode.leaf = pt_mol_tsx;
ptu_test(fetch_packet, ffix, &packet, &pt_decode_mode);
return ptu_passed();
}
static struct ptunit_result fetch_exstop_ip(struct fetch_fixture *ffix)
{
struct pt_packet packet;
memset(&packet, 0, sizeof(packet));
packet.type = ppt_exstop;
packet.payload.exstop.ip = 1;
ptu_test(fetch_packet, ffix, &packet, &pt_decode_exstop);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct fetch_fixture ffix;
struct ptunit_suite suite;
ffix.init = ffix_init;
ffix.fini = ffix_fini;
suite = ptunit_mk_suite(argc, argv);
ptu_run_f(suite, fetch_null, ffix);
ptu_run_f(suite, fetch_empty, ffix);
ptu_run_f(suite, fetch_unknown, ffix);
ptu_run_f(suite, fetch_unknown_ext, ffix);
ptu_run_f(suite, fetch_unknown_ext2, ffix);
ptu_run_fp(suite, fetch_type, ffix, ppt_pad, &pt_decode_pad);
ptu_run_fp(suite, fetch_type, ffix, ppt_psb, &pt_decode_psb);
ptu_run_fp(suite, fetch_type, ffix, ppt_tip, &pt_decode_tip);
ptu_run_fp(suite, fetch_type, ffix, ppt_tnt_64, &pt_decode_tnt_64);
ptu_run_fp(suite, fetch_type, ffix, ppt_tip_pge, &pt_decode_tip_pge);
ptu_run_fp(suite, fetch_type, ffix, ppt_tip_pgd, &pt_decode_tip_pgd);
ptu_run_fp(suite, fetch_type, ffix, ppt_fup, &pt_decode_fup);
ptu_run_fp(suite, fetch_type, ffix, ppt_pip, &pt_decode_pip);
ptu_run_fp(suite, fetch_type, ffix, ppt_ovf, &pt_decode_ovf);
ptu_run_fp(suite, fetch_type, ffix, ppt_psbend, &pt_decode_psbend);
ptu_run_fp(suite, fetch_type, ffix, ppt_tsc, &pt_decode_tsc);
ptu_run_fp(suite, fetch_type, ffix, ppt_cbr, &pt_decode_cbr);
ptu_run_fp(suite, fetch_type, ffix, ppt_tma, &pt_decode_tma);
ptu_run_fp(suite, fetch_type, ffix, ppt_mtc, &pt_decode_mtc);
ptu_run_fp(suite, fetch_type, ffix, ppt_cyc, &pt_decode_cyc);
ptu_run_fp(suite, fetch_type, ffix, ppt_stop, &pt_decode_stop);
ptu_run_fp(suite, fetch_type, ffix, ppt_vmcs, &pt_decode_vmcs);
ptu_run_fp(suite, fetch_type, ffix, ppt_mnt, &pt_decode_mnt);
ptu_run_fp(suite, fetch_type, ffix, ppt_exstop, &pt_decode_exstop);
ptu_run_fp(suite, fetch_type, ffix, ppt_mwait, &pt_decode_mwait);
ptu_run_fp(suite, fetch_type, ffix, ppt_pwre, &pt_decode_pwre);
ptu_run_fp(suite, fetch_type, ffix, ppt_pwrx, &pt_decode_pwrx);
ptu_run_fp(suite, fetch_type, ffix, ppt_ptw, &pt_decode_ptw);
ptu_run_f(suite, fetch_tnt_8, ffix);
ptu_run_f(suite, fetch_mode_exec, ffix);
ptu_run_f(suite, fetch_mode_tsx, ffix);
ptu_run_f(suite, fetch_exstop_ip, ffix);
return ptunit_report(&suite);
}
/* Dummy decode functions to satisfy link dependencies.
*
* As a nice side-effect, we will know if we need to add more tests when
* adding new decoder functions.
*/
int pt_pkt_decode_unknown(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_unknown(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_pad(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_pad(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_psb(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_psb(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tip(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tip(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tnt_8(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tnt_8(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tnt_64(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tnt_64(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tip_pge(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tip_pge(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tip_pgd(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tip_pgd(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_fup(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_fup(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_fup(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_pip(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_pip(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_pip(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_ovf(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_ovf(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_mode(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_mode(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_mode(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_psbend(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_psbend(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tsc(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tsc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_tsc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_cbr(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_cbr(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_cbr(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_tma(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_tma(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_mtc(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_mtc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_cyc(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_cyc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_stop(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_stop(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_vmcs(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_vmcs(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_vmcs(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_mnt(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_mnt(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_mnt(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_exstop(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_exstop(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_mwait(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_mwait(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_pwre(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_pwre(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_pwrx(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_pwrx(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_pkt_decode_ptw(struct pt_packet_decoder *d, struct pt_packet *p)
{
(void) d;
(void) p;
return -pte_internal;
}
int pt_qry_decode_ptw(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}

View File

@ -0,0 +1,759 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "ptunit.h"
#include "pt_ild.h"
#include <string.h>
/* Check that an instruction is decoded correctly. */
static struct ptunit_result ptunit_ild_decode(uint8_t *raw, uint8_t size,
enum pt_exec_mode mode)
{
struct pt_insn_ext iext;
struct pt_insn insn;
int errcode;
memset(&iext, 0, sizeof(iext));
memset(&insn, 0, sizeof(insn));
memcpy(insn.raw, raw, size);
insn.size = size;
insn.mode = mode;
errcode = pt_ild_decode(&insn, &iext);
ptu_int_eq(errcode, 0);
ptu_uint_eq(insn.size, size);
ptu_int_eq(insn.iclass, ptic_other);
ptu_int_eq(iext.iclass, PTI_INST_INVALID);
return ptu_passed();
}
/* Check that an instruction is decoded and classified correctly. */
static struct ptunit_result ptunit_ild_classify(uint8_t *raw, uint8_t size,
enum pt_exec_mode mode,
pti_inst_enum_t iclass)
{
struct pt_insn_ext iext;
struct pt_insn insn;
int errcode;
memset(&iext, 0, sizeof(iext));
memset(&insn, 0, sizeof(insn));
memcpy(insn.raw, raw, size);
insn.size = size;
insn.mode = mode;
errcode = pt_ild_decode(&insn, &iext);
ptu_int_eq(errcode, 0);
ptu_uint_eq(insn.size, size);
ptu_int_eq(iext.iclass, iclass);
return ptu_passed();
}
/* Check that an invalid instruction is detected correctly.
*
* Note that we intentionally do not detect all invalid instructions. This test
* therefore only covers some that we care about.
*/
static struct ptunit_result ptunit_ild_invalid(uint8_t *raw, uint8_t size,
enum pt_exec_mode mode)
{
struct pt_insn_ext iext;
struct pt_insn insn;
int errcode;
memset(&iext, 0, sizeof(iext));
memset(&insn, 0, sizeof(insn));
memcpy(insn.raw, raw, size);
insn.size = size;
insn.mode = mode;
errcode = pt_ild_decode(&insn, &iext);
ptu_int_eq(errcode, -pte_bad_insn);
return ptu_passed();
}
/* Macros to automatically update the test location. */
#define ptu_decode(insn, size, mode) \
ptu_check(ptunit_ild_decode, insn, size, mode)
#define ptu_classify(insn, size, mode, iclass) \
ptu_check(ptunit_ild_classify, insn, size, mode, iclass)
/* Macros to also automatically supply the instruction size. */
#define ptu_decode_s(insn, mode) \
ptu_decode(insn, sizeof(insn), mode)
#define ptu_classify_s(insn, mode, iclass) \
ptu_classify(insn, sizeof(insn), mode, iclass)
#define ptu_invalid_s(insn, mode) \
ptu_check(ptunit_ild_invalid, insn, sizeof(insn), mode)
static struct ptunit_result push(void)
{
uint8_t insn[] = { 0x68, 0x11, 0x22, 0x33, 0x44 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result jmp_rel(void)
{
uint8_t insn[] = { 0xE9, 0x60, 0xF9, 0xFF, 0xFF };
ptu_classify_s(insn, ptem_64bit, PTI_INST_JMP_E9);
return ptu_passed();
}
static struct ptunit_result long_nop(void)
{
uint8_t insn[] = { 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0X2E, 0X0F,
0X1F, 0x84, 0x00, 0x00,
0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_al_64(void)
{
uint8_t insn[] = { 0x48, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
0xff, 0x11 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_al_32_em64(void)
{
uint8_t insn[] = { 0x67, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
0xff, 0X11 };
ptu_decode(insn, 6, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_al_32(void)
{
uint8_t insn[] = { 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
ptu_decode(insn, 5, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result mov_al_32_em16(void)
{
uint8_t insn[] = { 0x67, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
ptu_decode(insn, 6, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result mov_al_16_em32(void)
{
uint8_t insn[] = { 0x67, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
ptu_decode(insn, 4, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result mov_al_16(void)
{
uint8_t insn[] = { 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
ptu_decode(insn, 3, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result rdtsc(void)
{
uint8_t insn[] = { 0x0f, 0x31 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result pcmpistri(void)
{
uint8_t insn[] = { 0x66, 0x0f, 0x3a, 0x63, 0x04, 0x16, 0x1a };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result vmovdqa(void)
{
uint8_t insn[] = { 0xc5, 0xf9, 0x6f, 0x25, 0xa9, 0x55, 0x04, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result vpandn(void)
{
uint8_t insn[] = { 0xc4, 0x41, 0x29, 0xdf, 0xd1 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result syscall(void)
{
uint8_t insn[] = { 0x0f, 0x05 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSCALL);
return ptu_passed();
}
static struct ptunit_result sysret(void)
{
uint8_t insn[] = { 0x0f, 0x07 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSRET);
return ptu_passed();
}
static struct ptunit_result sysenter(void)
{
uint8_t insn[] = { 0x0f, 0x34 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSENTER);
return ptu_passed();
}
static struct ptunit_result sysexit(void)
{
uint8_t insn[] = { 0x0f, 0x35 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSEXIT);
return ptu_passed();
}
static struct ptunit_result int3(void)
{
uint8_t insn[] = { 0xcc };
ptu_classify_s(insn, ptem_64bit, PTI_INST_INT3);
return ptu_passed();
}
static struct ptunit_result intn(void)
{
uint8_t insn[] = { 0xcd, 0x06 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_INT);
return ptu_passed();
}
static struct ptunit_result iret(void)
{
uint8_t insn[] = { 0xcf };
ptu_classify_s(insn, ptem_64bit, PTI_INST_IRET);
return ptu_passed();
}
static struct ptunit_result call_9a_cd(void)
{
uint8_t insn[] = { 0x9a, 0x00, 0x00, 0x00, 0x00 };
ptu_classify_s(insn, ptem_16bit, PTI_INST_CALL_9A);
return ptu_passed();
}
static struct ptunit_result call_9a_cp(void)
{
uint8_t insn[] = { 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ptu_classify_s(insn, ptem_32bit, PTI_INST_CALL_9A);
return ptu_passed();
}
static struct ptunit_result call_ff_3(void)
{
uint8_t insn[] = { 0xff, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_CALL_FFr3);
return ptu_passed();
}
static struct ptunit_result jmp_ff_5(void)
{
uint8_t insn[] = { 0xff, 0x2c, 0x25, 0x00, 0x00, 0x00, 0x00 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_JMP_FFr5);
return ptu_passed();
}
static struct ptunit_result jmp_ea_cd(void)
{
uint8_t insn[] = { 0xea, 0x00, 0x00, 0x00, 0x00 };
ptu_classify_s(insn, ptem_16bit, PTI_INST_JMP_EA);
return ptu_passed();
}
static struct ptunit_result jmp_ea_cp(void)
{
uint8_t insn[] = { 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ptu_classify_s(insn, ptem_32bit, PTI_INST_JMP_EA);
return ptu_passed();
}
static struct ptunit_result ret_ca(void)
{
uint8_t insn[] = { 0xca, 0x00, 0x00 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_RET_CA);
return ptu_passed();
}
static struct ptunit_result vmlaunch(void)
{
uint8_t insn[] = { 0x0f, 0x01, 0xc2 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_VMLAUNCH);
return ptu_passed();
}
static struct ptunit_result vmresume(void)
{
uint8_t insn[] = { 0x0f, 0x01, 0xc3 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_VMRESUME);
return ptu_passed();
}
static struct ptunit_result vmcall(void)
{
uint8_t insn[] = { 0x0f, 0x01, 0xc1 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_VMCALL);
return ptu_passed();
}
static struct ptunit_result vmptrld(void)
{
uint8_t insn[] = { 0x0f, 0xc7, 0x30 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_VMPTRLD);
return ptu_passed();
}
static struct ptunit_result jrcxz(void)
{
uint8_t insn[] = { 0xe3, 0x00 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_JrCXZ);
return ptu_passed();
}
static struct ptunit_result mov_eax_moffs64(void)
{
uint8_t insn[] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_eax_moffs64_32(void)
{
uint8_t insn[] = { 0x67, 0xa1, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_rax_moffs64(void)
{
uint8_t insn[] = { 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_rax_moffs64_32(void)
{
uint8_t insn[] = { 0x67, 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_ax_moffs64(void)
{
uint8_t insn[] = { 0x66, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_ax_moffs64_32(void)
{
uint8_t insn[] = { 0x67, 0x66, 0xa1, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result mov_eax_moffs32(void)
{
uint8_t insn[] = { 0xa1, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result mov_ax_moffs32(void)
{
uint8_t insn[] = { 0x66, 0xa1, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result mov_ax_moffs16(void)
{
uint8_t insn[] = { 0xa1, 0x00, 0x00 };
ptu_decode_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result les(void)
{
uint8_t insn[] = { 0xc4, 0x00 };
ptu_decode_s(insn, ptem_16bit);
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result les_disp16(void)
{
uint8_t insn[] = { 0xc4, 0x06, 0x00, 0x00 };
ptu_decode_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result les_disp32(void)
{
uint8_t insn[] = { 0xc4, 0x05, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result les_ind_disp8(void)
{
uint8_t insn[] = { 0xc4, 0x40, 0x00 };
ptu_decode_s(insn, ptem_16bit);
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result les_ind_disp16(void)
{
uint8_t insn[] = { 0xc4, 0x80, 0x00, 0x00 };
ptu_decode_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result les_ind_disp32(void)
{
uint8_t insn[] = { 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result lds(void)
{
uint8_t insn[] = { 0xc5, 0x00 };
ptu_decode_s(insn, ptem_16bit);
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result lds_disp16(void)
{
uint8_t insn[] = { 0xc5, 0x06, 0x00, 0x00 };
ptu_decode_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result lds_disp32(void)
{
uint8_t insn[] = { 0xc5, 0x05, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result lds_ind_disp8(void)
{
uint8_t insn[] = { 0xc5, 0x40, 0x00 };
ptu_decode_s(insn, ptem_16bit);
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result lds_ind_disp16(void)
{
uint8_t insn[] = { 0xc5, 0x80, 0x00, 0x00 };
ptu_decode_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result lds_ind_disp32(void)
{
uint8_t insn[] = { 0xc5, 0x80, 0x00, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_32bit);
return ptu_passed();
}
static struct ptunit_result vpshufb(void)
{
uint8_t insn[] = { 0x62, 0x02, 0x05, 0x00, 0x00, 0x00 };
ptu_decode_s(insn, ptem_64bit);
return ptu_passed();
}
static struct ptunit_result bound(void)
{
uint8_t insn[] = { 0x62, 0x02 };
ptu_decode_s(insn, ptem_32bit);
ptu_decode_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result evex_cutoff(void)
{
uint8_t insn[] = { 0x62 };
ptu_invalid_s(insn, ptem_64bit);
ptu_invalid_s(insn, ptem_32bit);
ptu_invalid_s(insn, ptem_16bit);
return ptu_passed();
}
static struct ptunit_result ptwrite_r32(void)
{
uint8_t insn[] = { 0xf3, 0x0f, 0xae, 0xe7 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
ptu_classify_s(insn, ptem_32bit, PTI_INST_PTWRITE);
ptu_classify_s(insn, ptem_16bit, PTI_INST_PTWRITE);
return ptu_passed();
}
static struct ptunit_result ptwrite_m32(void)
{
uint8_t insn[] = { 0xf3, 0x0f, 0xae, 0x67, 0xcc };
ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
ptu_classify_s(insn, ptem_32bit, PTI_INST_PTWRITE);
ptu_classify_s(insn, ptem_16bit, PTI_INST_PTWRITE);
return ptu_passed();
}
static struct ptunit_result ptwrite_r64(void)
{
uint8_t insn[] = { 0xf3, 0x48, 0x0f, 0xae, 0xe7 };
ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
return ptu_passed();
}
static struct ptunit_result ptwrite_m64(void)
{
uint8_t insn[] = { 0xf3, 0x48, 0x0f, 0xae, 0x67, 0xcc };
ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
pt_ild_init();
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, push);
ptu_run(suite, jmp_rel);
ptu_run(suite, long_nop);
ptu_run(suite, mov_al_64);
ptu_run(suite, mov_al_32);
ptu_run(suite, mov_al_32_em64);
ptu_run(suite, mov_al_32_em16);
ptu_run(suite, mov_al_16_em32);
ptu_run(suite, mov_al_16);
ptu_run(suite, rdtsc);
ptu_run(suite, pcmpistri);
ptu_run(suite, vmovdqa);
ptu_run(suite, vpandn);
ptu_run(suite, syscall);
ptu_run(suite, sysret);
ptu_run(suite, sysenter);
ptu_run(suite, sysexit);
ptu_run(suite, int3);
ptu_run(suite, intn);
ptu_run(suite, iret);
ptu_run(suite, call_9a_cd);
ptu_run(suite, call_9a_cp);
ptu_run(suite, call_ff_3);
ptu_run(suite, jmp_ff_5);
ptu_run(suite, jmp_ea_cd);
ptu_run(suite, jmp_ea_cp);
ptu_run(suite, ret_ca);
ptu_run(suite, vmlaunch);
ptu_run(suite, vmresume);
ptu_run(suite, vmcall);
ptu_run(suite, vmptrld);
ptu_run(suite, jrcxz);
ptu_run(suite, mov_eax_moffs64);
ptu_run(suite, mov_eax_moffs64_32);
ptu_run(suite, mov_rax_moffs64);
ptu_run(suite, mov_rax_moffs64_32);
ptu_run(suite, mov_ax_moffs64);
ptu_run(suite, mov_ax_moffs64_32);
ptu_run(suite, mov_eax_moffs32);
ptu_run(suite, mov_ax_moffs32);
ptu_run(suite, mov_ax_moffs16);
ptu_run(suite, les);
ptu_run(suite, les_disp16);
ptu_run(suite, les_disp32);
ptu_run(suite, les_ind_disp8);
ptu_run(suite, les_ind_disp16);
ptu_run(suite, les_ind_disp32);
ptu_run(suite, lds);
ptu_run(suite, lds_disp16);
ptu_run(suite, lds_disp32);
ptu_run(suite, lds_ind_disp8);
ptu_run(suite, lds_ind_disp16);
ptu_run(suite, lds_ind_disp32);
ptu_run(suite, vpshufb);
ptu_run(suite, bound);
ptu_run(suite, evex_cutoff);
ptu_run(suite, ptwrite_r32);
ptu_run(suite, ptwrite_m32);
ptu_run(suite, ptwrite_r64);
ptu_run(suite, ptwrite_m64);
return ptunit_report(&suite);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,374 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "ptunit.h"
#include "pt_last_ip.h"
#include "intel-pt.h"
#include <string.h>
static struct ptunit_result init(void)
{
struct pt_last_ip last_ip;
memset(&last_ip, 0xcd, sizeof(last_ip));
pt_last_ip_init(&last_ip);
ptu_uint_eq(last_ip.ip, 0ull);
ptu_uint_eq(last_ip.have_ip, 0);
ptu_uint_eq(last_ip.suppressed, 0);
return ptu_passed();
}
static struct ptunit_result init_null(void)
{
pt_last_ip_init(NULL);
return ptu_passed();
}
static struct ptunit_result status_initial(void)
{
struct pt_last_ip last_ip;
int errcode;
pt_last_ip_init(&last_ip);
errcode = pt_last_ip_query(NULL, &last_ip);
ptu_int_eq(errcode, -pte_noip);
return ptu_passed();
}
static struct ptunit_result status(void)
{
struct pt_last_ip last_ip;
int errcode;
last_ip.have_ip = 1;
last_ip.suppressed = 0;
errcode = pt_last_ip_query(NULL, &last_ip);
ptu_int_eq(errcode, 0);
return ptu_passed();
}
static struct ptunit_result status_null(void)
{
int errcode;
errcode = pt_last_ip_query(NULL, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result status_noip(void)
{
struct pt_last_ip last_ip;
int errcode;
last_ip.have_ip = 0;
last_ip.suppressed = 0;
errcode = pt_last_ip_query(NULL, &last_ip);
ptu_int_eq(errcode, -pte_noip);
return ptu_passed();
}
static struct ptunit_result status_suppressed(void)
{
struct pt_last_ip last_ip;
int errcode;
last_ip.have_ip = 1;
last_ip.suppressed = 1;
errcode = pt_last_ip_query(NULL, &last_ip);
ptu_int_eq(errcode, -pte_ip_suppressed);
return ptu_passed();
}
static struct ptunit_result query_initial(void)
{
struct pt_last_ip last_ip;
uint64_t ip;
int errcode;
pt_last_ip_init(&last_ip);
errcode = pt_last_ip_query(&ip, &last_ip);
ptu_int_eq(errcode, -pte_noip);
return ptu_passed();
}
static struct ptunit_result query(void)
{
struct pt_last_ip last_ip;
uint64_t ip, exp = 42ull;
int errcode;
last_ip.ip = 42ull;
last_ip.have_ip = 1;
last_ip.suppressed = 0;
errcode = pt_last_ip_query(&ip, &last_ip);
ptu_int_eq(errcode, 0);
ptu_uint_eq(last_ip.ip, exp);
return ptu_passed();
}
static struct ptunit_result query_null(void)
{
uint64_t ip = 13ull;
int errcode;
errcode = pt_last_ip_query(&ip, NULL);
ptu_int_eq(errcode, -pte_internal);
ptu_uint_eq(ip, 13ull);
return ptu_passed();
}
static struct ptunit_result query_noip(void)
{
struct pt_last_ip last_ip;
uint64_t ip = 13ull;
int errcode;
last_ip.ip = 42ull;
last_ip.have_ip = 0;
last_ip.suppressed = 0;
errcode = pt_last_ip_query(&ip, &last_ip);
ptu_int_eq(errcode, -pte_noip);
ptu_uint_eq(ip, 0ull);
return ptu_passed();
}
static struct ptunit_result query_suppressed(void)
{
struct pt_last_ip last_ip;
uint64_t ip = 13ull;
int errcode;
last_ip.ip = 42ull;
last_ip.have_ip = 1;
last_ip.suppressed = 1;
errcode = pt_last_ip_query(&ip, &last_ip);
ptu_int_eq(errcode, -pte_ip_suppressed);
ptu_uint_eq(ip, 0ull);
return ptu_passed();
}
static struct ptunit_result update_ip_suppressed(uint32_t have_ip)
{
struct pt_last_ip last_ip;
struct pt_packet_ip packet;
int errcode;
last_ip.ip = 42ull;
last_ip.have_ip = have_ip;
last_ip.suppressed = 0;
packet.ipc = pt_ipc_suppressed;
packet.ip = 13ull;
errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
ptu_int_eq(errcode, 0);
ptu_uint_eq(last_ip.ip, 42ull);
ptu_uint_eq(last_ip.have_ip, have_ip);
ptu_uint_eq(last_ip.suppressed, 1);
return ptu_passed();
}
static struct ptunit_result update_ip_upd16(uint32_t have_ip)
{
struct pt_last_ip last_ip;
struct pt_packet_ip packet;
int errcode;
last_ip.ip = 0xff0042ull;
last_ip.have_ip = have_ip;
last_ip.suppressed = 0;
packet.ipc = pt_ipc_update_16;
packet.ip = 0xccc013ull;
errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
ptu_int_eq(errcode, 0);
ptu_uint_eq(last_ip.ip, 0xffc013ull);
ptu_uint_eq(last_ip.have_ip, 1);
ptu_uint_eq(last_ip.suppressed, 0);
return ptu_passed();
}
static struct ptunit_result update_ip_upd32(uint32_t have_ip)
{
struct pt_last_ip last_ip;
struct pt_packet_ip packet;
int errcode;
last_ip.ip = 0xff00000420ull;
last_ip.have_ip = have_ip;
last_ip.suppressed = 0;
packet.ipc = pt_ipc_update_32;
packet.ip = 0xcc0000c013ull;
errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
ptu_int_eq(errcode, 0);
ptu_uint_eq(last_ip.ip, 0xff0000c013ull);
ptu_uint_eq(last_ip.have_ip, 1);
ptu_uint_eq(last_ip.suppressed, 0);
return ptu_passed();
}
static struct ptunit_result update_ip_sext48(uint32_t have_ip)
{
struct pt_last_ip last_ip;
struct pt_packet_ip packet;
int errcode;
last_ip.ip = 0x7fffffffffffffffull;
last_ip.have_ip = have_ip;
last_ip.suppressed = 0;
packet.ipc = pt_ipc_sext_48;
packet.ip = 0xff00000000ffull;
errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
ptu_int_eq(errcode, 0);
ptu_uint_eq(last_ip.ip, 0xffffff00000000ffull);
ptu_uint_eq(last_ip.have_ip, 1);
ptu_uint_eq(last_ip.suppressed, 0);
return ptu_passed();
}
static struct ptunit_result update_ip_bad_packet(uint32_t have_ip)
{
struct pt_last_ip last_ip;
struct pt_packet_ip packet;
int errcode;
last_ip.ip = 0x7fffffffffffffffull;
last_ip.have_ip = have_ip;
last_ip.suppressed = 0;
packet.ipc = (enum pt_ip_compression) 0xff;
packet.ip = 0ull;
errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
ptu_int_eq(errcode, -pte_bad_packet);
ptu_uint_eq(last_ip.ip, 0x7fffffffffffffffull);
ptu_uint_eq(last_ip.have_ip, have_ip);
ptu_uint_eq(last_ip.suppressed, 0);
return ptu_passed();
}
static struct ptunit_result update_ip_null_ip(void)
{
struct pt_packet_ip packet;
int errcode;
errcode = pt_last_ip_update_ip(NULL, &packet, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result update_ip_null_packet(uint32_t have_ip)
{
struct pt_last_ip last_ip;
int errcode;
last_ip.ip = 0x7fffffffffffffffull;
last_ip.have_ip = have_ip;
last_ip.suppressed = 0;
errcode = pt_last_ip_update_ip(&last_ip, NULL, NULL);
ptu_int_eq(errcode, -pte_internal);
ptu_uint_eq(last_ip.ip, 0x7fffffffffffffffull);
ptu_uint_eq(last_ip.have_ip, have_ip);
ptu_uint_eq(last_ip.suppressed, 0);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, init);
ptu_run(suite, init_null);
ptu_run(suite, status_initial);
ptu_run(suite, status);
ptu_run(suite, status_null);
ptu_run(suite, status_noip);
ptu_run(suite, status_suppressed);
ptu_run(suite, query_initial);
ptu_run(suite, query);
ptu_run(suite, query_null);
ptu_run(suite, query_noip);
ptu_run(suite, query_suppressed);
ptu_run_p(suite, update_ip_suppressed, 0);
ptu_run_p(suite, update_ip_suppressed, 1);
ptu_run_p(suite, update_ip_upd16, 0);
ptu_run_p(suite, update_ip_upd16, 1);
ptu_run_p(suite, update_ip_upd32, 0);
ptu_run_p(suite, update_ip_upd32, 1);
ptu_run_p(suite, update_ip_sext48, 0);
ptu_run_p(suite, update_ip_sext48, 1);
ptu_run_p(suite, update_ip_bad_packet, 0);
ptu_run_p(suite, update_ip_bad_packet, 1);
ptu_run(suite, update_ip_null_ip);
ptu_run_p(suite, update_ip_null_packet, 0);
ptu_run_p(suite, update_ip_null_packet, 1);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "ptunit.h"
#include "pt_mapped_section.h"
#include "intel-pt.h"
static struct ptunit_result begin(void)
{
struct pt_mapped_section msec;
struct pt_section sec;
uint64_t begin;
pt_msec_init(&msec, &sec, NULL, 0x2000ull, 0x100ull, 0x1000ull);
begin = pt_msec_begin(&msec);
ptu_uint_eq(begin, 0x2000);
return ptu_passed();
}
static struct ptunit_result end(void)
{
struct pt_mapped_section msec;
struct pt_section sec;
uint64_t end;
pt_msec_init(&msec, &sec, NULL, 0x2000ull, 0x100ull, 0x1000ull);
end = pt_msec_end(&msec);
ptu_uint_eq(end, 0x3000);
return ptu_passed();
}
static struct ptunit_result offset(void)
{
struct pt_mapped_section msec;
struct pt_section sec;
uint64_t offset;
pt_msec_init(&msec, &sec, NULL, 0x2000ull, 0x100ull, 0x1000ull);
offset = pt_msec_offset(&msec);
ptu_uint_eq(offset, 0x100ull);
return ptu_passed();
}
static struct ptunit_result size(void)
{
struct pt_mapped_section msec;
struct pt_section sec;
uint64_t size;
pt_msec_init(&msec, &sec, NULL, 0x2000ull, 0x100ull, 0x1000ull);
size = pt_msec_size(&msec);
ptu_uint_eq(size, 0x1000ull);
return ptu_passed();
}
static struct ptunit_result asid(void)
{
struct pt_mapped_section msec;
struct pt_asid asid;
const struct pt_asid *pasid;
pt_asid_init(&asid);
asid.cr3 = 0xa00000ull;
asid.vmcs = 0xb00000ull;
pt_msec_init(&msec, NULL, &asid, 0x2000ull, 0x100ull, 0x1000ull);
pasid = pt_msec_asid(&msec);
ptu_ptr(pasid);
ptu_uint_eq(pasid->cr3, asid.cr3);
ptu_uint_eq(pasid->vmcs, asid.vmcs);
return ptu_passed();
}
static struct ptunit_result asid_null(void)
{
struct pt_mapped_section msec;
const struct pt_asid *pasid;
pt_msec_init(&msec, NULL, NULL, 0x2000ull, 0x100ull, 0x1000ull);
pasid = pt_msec_asid(&msec);
ptu_ptr(pasid);
ptu_uint_eq(pasid->cr3, pt_asid_no_cr3);
ptu_uint_eq(pasid->vmcs, pt_asid_no_vmcs);
return ptu_passed();
}
static struct ptunit_result map(void)
{
struct pt_mapped_section msec;
uint64_t mapped;
pt_msec_init(&msec, NULL, NULL, 0x2000ull, 0x100ull, 0x1000ull);
mapped = pt_msec_map(&msec, 0x900);
ptu_uint_eq(mapped, 0x2800);
return ptu_passed();
}
static struct ptunit_result unmap(void)
{
struct pt_mapped_section msec;
uint64_t offset;
pt_msec_init(&msec, NULL, NULL, 0x2000ull, 0x100ull, 0x1000ull);
offset = pt_msec_unmap(&msec, 0x3000);
ptu_uint_eq(offset, 0x1100);
return ptu_passed();
}
static struct ptunit_result section(void)
{
static struct pt_section section;
struct pt_mapped_section msec;
struct pt_section *psection;
pt_msec_init(&msec, &section, NULL, 0x2000ull, 0x100ull, 0x1000ull);
psection = pt_msec_section(&msec);
ptu_ptr_eq(psection, &section);
return ptu_passed();
}
static struct ptunit_result section_null(void)
{
struct pt_mapped_section msec;
struct pt_section *psection;
pt_msec_init(&msec, NULL, NULL, 0x2000ull, 0x100ull, 0x1000ull);
psection = pt_msec_section(&msec);
ptu_ptr_eq(psection, NULL);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, begin);
ptu_run(suite, end);
ptu_run(suite, offset);
ptu_run(suite, size);
ptu_run(suite, asid);
ptu_run(suite, asid_null);
ptu_run(suite, map);
ptu_run(suite, unmap);
ptu_run(suite, section);
ptu_run(suite, section_null);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,419 @@
/*
* Copyright (c) 2017-2018, 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.
*/
#include "ptunit.h"
#include "pt_msec_cache.h"
#include "intel-pt.h"
int pt_section_get(struct pt_section *section)
{
uint16_t ucount;
if (!section)
return -pte_internal;
ucount = section->ucount + 1;
if (!ucount)
return -pte_overflow;
section->ucount = ucount;
return 0;
}
int pt_section_put(struct pt_section *section)
{
uint16_t ucount;
if (!section)
return -pte_internal;
ucount = section->ucount;
if (!ucount)
return -pte_overflow;
section->ucount = ucount - 1;
return 0;
}
int pt_section_map(struct pt_section *section)
{
uint16_t ucount, mcount;
if (!section)
return -pte_internal;
ucount = section->ucount;
if (!ucount)
return -pte_internal;
mcount = section->mcount + 1;
if (!mcount)
return -pte_overflow;
section->mcount = mcount;
return 0;
}
int pt_section_unmap(struct pt_section *section)
{
uint16_t ucount, mcount;
if (!section)
return -pte_internal;
ucount = section->ucount;
if (!ucount)
return -pte_internal;
mcount = section->mcount;
if (!mcount)
return -pte_overflow;
section->mcount = mcount - 1;
return 0;
}
/* A mock image. */
struct pt_image {
/* The section stored in the image.
*
* This is either the fixture's section or NULL.
*/
struct pt_section *section;
};
extern int pt_image_validate(struct pt_image *, struct pt_mapped_section *,
uint64_t, int);
extern int pt_image_find(struct pt_image *, struct pt_mapped_section *,
const struct pt_asid *, uint64_t);
int pt_image_validate(struct pt_image *image, struct pt_mapped_section *msec,
uint64_t vaddr, int isid)
{
struct pt_section *section;
(void) vaddr;
(void) isid;
if (!image || !msec)
return -pte_internal;
section = image->section;
if (!section)
return -pte_nomap;
if (section != msec->section)
return -pte_nomap;
return 0;
}
int pt_image_find(struct pt_image *image, struct pt_mapped_section *msec,
const struct pt_asid *asid, uint64_t vaddr)
{
struct pt_section *section;
(void) vaddr;
if (!image || !msec || !asid)
return -pte_internal;
section = image->section;
if (!section)
return -pte_nomap;
if (msec->section)
return -pte_internal;
msec->section = section;
return pt_section_get(section);
}
/* A test fixture providing a section and checking the use and map count. */
struct test_fixture {
/* A test section. */
struct pt_section section;
/* A test cache. */
struct pt_msec_cache mcache;
/* A test image. */
struct pt_image image;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct test_fixture *);
struct ptunit_result (*fini)(struct test_fixture *);
};
static struct ptunit_result init_null(void)
{
int status;
status = pt_msec_cache_init(NULL);
ptu_int_eq(status, -pte_internal);
return ptu_passed();
}
static struct ptunit_result fini_null(void)
{
pt_msec_cache_fini(NULL);
return ptu_passed();
}
static struct ptunit_result invalidate_null(void)
{
int status;
status = pt_msec_cache_invalidate(NULL);
ptu_int_eq(status, -pte_internal);
return ptu_passed();
}
static struct ptunit_result read_null(void)
{
const struct pt_mapped_section *msec;
struct pt_msec_cache mcache;
struct pt_image image;
int status;
status = pt_msec_cache_read(NULL, &msec, &image, 0ull);
ptu_int_eq(status, -pte_internal);
status = pt_msec_cache_read(&mcache, NULL, &image, 0ull);
ptu_int_eq(status, -pte_internal);
status = pt_msec_cache_read(&mcache, &msec, NULL, 0ull);
ptu_int_eq(status, -pte_internal);
return ptu_passed();
}
static struct ptunit_result fill_null(void)
{
const struct pt_mapped_section *msec;
struct pt_msec_cache mcache;
struct pt_image image;
struct pt_asid asid;
int status;
memset(&mcache, 0, sizeof(mcache));
status = pt_msec_cache_fill(NULL, &msec, &image, &asid, 0ull);
ptu_int_eq(status, -pte_internal);
status = pt_msec_cache_fill(&mcache, NULL, &image, &asid, 0ull);
ptu_int_eq(status, -pte_internal);
status = pt_msec_cache_fill(&mcache, &msec, NULL, &asid, 0ull);
ptu_int_eq(status, -pte_internal);
status = pt_msec_cache_fill(&mcache, &msec, &image, NULL, 0ull);
ptu_int_eq(status, -pte_internal);
return ptu_passed();
}
static struct ptunit_result invalidate(struct test_fixture *tfix)
{
struct pt_section *section;
int status;
status = pt_msec_cache_invalidate(&tfix->mcache);
ptu_int_eq(status, 0);
section = pt_msec_section(&tfix->mcache.msec);
ptu_null(section);
ptu_uint_eq(tfix->section.mcount, 0);
ptu_uint_eq(tfix->section.ucount, 0);
return ptu_passed();
}
static struct ptunit_result read_nomap(struct test_fixture *tfix)
{
const struct pt_mapped_section *msec;
int status;
msec = NULL;
status = pt_msec_cache_read(&tfix->mcache, &msec, &tfix->image, 0ull);
ptu_int_eq(status, -pte_nomap);
ptu_null(msec);
return ptu_passed();
}
static struct ptunit_result read(struct test_fixture *tfix)
{
const struct pt_mapped_section *msec;
struct pt_section *section;
int status;
status = pt_msec_cache_read(&tfix->mcache, &msec, &tfix->image, 0ull);
ptu_int_eq(status, 0);
ptu_ptr_eq(msec, &tfix->mcache.msec);
section = pt_msec_section(msec);
ptu_ptr_eq(section, &tfix->section);
return ptu_passed();
}
static struct ptunit_result fill_nomap(struct test_fixture *tfix)
{
const struct pt_mapped_section *msec;
struct pt_asid asid;
struct pt_section *section;
int status;
msec = NULL;
status = pt_msec_cache_fill(&tfix->mcache, &msec, &tfix->image, &asid,
0ull);
ptu_int_eq(status, -pte_nomap);
section = pt_msec_section(&tfix->mcache.msec);
ptu_null(section);
ptu_null(msec);
ptu_uint_eq(tfix->section.mcount, 0);
ptu_uint_eq(tfix->section.ucount, 0);
return ptu_passed();
}
static struct ptunit_result fill(struct test_fixture *tfix)
{
const struct pt_mapped_section *msec;
struct pt_section *section;
struct pt_asid asid;
int status;
status = pt_msec_cache_fill(&tfix->mcache, &msec, &tfix->image, &asid,
0ull);
ptu_int_eq(status, 0);
ptu_ptr_eq(msec, &tfix->mcache.msec);
section = pt_msec_section(msec);
ptu_ptr_eq(section, &tfix->section);
ptu_uint_eq(section->mcount, 1);
ptu_uint_eq(section->ucount, 1);
return ptu_passed();
}
static struct ptunit_result sfix_init(struct test_fixture *tfix)
{
memset(&tfix->section, 0, sizeof(tfix->section));
memset(&tfix->mcache, 0, sizeof(tfix->mcache));
memset(&tfix->image, 0, sizeof(tfix->image));
return ptu_passed();
}
static struct ptunit_result ifix_init(struct test_fixture *tfix)
{
ptu_test(sfix_init, tfix);
tfix->image.section = &tfix->section;
return ptu_passed();
}
static struct ptunit_result cfix_init(struct test_fixture *tfix)
{
ptu_test(sfix_init, tfix);
tfix->mcache.msec.section = &tfix->section;
tfix->section.ucount = 1;
tfix->section.mcount = 1;
return ptu_passed();
}
static struct ptunit_result cifix_init(struct test_fixture *tfix)
{
ptu_test(cfix_init, tfix);
tfix->image.section = &tfix->section;
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
struct test_fixture sfix, ifix, cfix, cifix;
sfix.init = sfix_init;
sfix.fini = NULL;
ifix.init = ifix_init;
ifix.fini = NULL;
cfix.init = cfix_init;
cfix.fini = NULL;
cifix.init = cifix_init;
cifix.fini = NULL;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, init_null);
ptu_run(suite, fini_null);
ptu_run(suite, invalidate_null);
ptu_run(suite, read_null);
ptu_run(suite, fill_null);
ptu_run_f(suite, invalidate, sfix);
ptu_run_f(suite, invalidate, cfix);
ptu_run_f(suite, read_nomap, sfix);
ptu_run_f(suite, read_nomap, ifix);
ptu_run_f(suite, read_nomap, cfix);
ptu_run_f(suite, read, cifix);
ptu_run_f(suite, fill_nomap, sfix);
ptu_run_f(suite, fill_nomap, cfix);
ptu_run_f(suite, fill, ifix);
ptu_run_f(suite, fill, cifix);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,859 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "ptunit.h"
#include "pt_packet_decoder.h"
#include "pt_query_decoder.h"
#include "pt_encoder.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
#include <string.h>
/* A test fixture providing everything needed for packet en- and de-coding. */
struct packet_fixture {
/* The trace buffer. */
uint8_t buffer[64];
/* Two packets for encoding[0] and decoding[1]. */
struct pt_packet packet[2];
/* The configuration. */
struct pt_config config;
/* The encoder. */
struct pt_encoder encoder;
/* The decoder. */
struct pt_packet_decoder decoder;
/* The return value for an unknown decode. */
int unknown;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct packet_fixture *);
struct ptunit_result (*fini)(struct packet_fixture *);
};
static int pfix_decode_unknown(struct pt_packet_unknown *packet,
const struct pt_config *config,
const uint8_t *pos, void *context)
{
struct packet_fixture *pfix;
if (!packet || !config)
return -pte_internal;
pfix = (struct packet_fixture *) context;
if (!pfix)
return -pte_internal;
if (config->begin != pfix->buffer)
return -pte_internal;
if (config->end != pfix->buffer + sizeof(pfix->buffer))
return -pte_internal;
if (pos != pfix->buffer)
return -pte_internal;
packet->priv = pfix;
return pfix->unknown;
}
static struct ptunit_result pfix_init(struct packet_fixture *pfix)
{
int errcode;
memset(pfix->buffer, 0, sizeof(pfix->buffer));
memset(pfix->packet, 0, sizeof(pfix->packet));
memset(&pfix->config, 0, sizeof(pfix->config));
pfix->config.size = sizeof(pfix->config);
pfix->config.begin = pfix->buffer;
pfix->config.end = pfix->buffer + sizeof(pfix->buffer);
pfix->config.decode.callback = pfix_decode_unknown;
pfix->config.decode.context = pfix;
pt_encoder_init(&pfix->encoder, &pfix->config);
pt_pkt_decoder_init(&pfix->decoder, &pfix->config);
errcode = pt_pkt_sync_set(&pfix->decoder, 0x0ull);
ptu_int_eq(errcode, 0);
pfix->unknown = 0;
return ptu_passed();
}
static struct ptunit_result pfix_fini(struct packet_fixture *pfix)
{
pt_encoder_fini(&pfix->encoder);
pt_pkt_decoder_fini(&pfix->decoder);
return ptu_passed();
}
static struct ptunit_result ptu_pkt_eq(const struct pt_packet *enc,
const struct pt_packet *dec)
{
const uint8_t *renc, *rdec;
size_t byte;
ptu_ptr(enc);
ptu_ptr(dec);
renc = (const uint8_t *) enc;
rdec = (const uint8_t *) dec;
for (byte = 0; byte < sizeof(*enc); ++byte)
ptu_uint_eq(renc[byte], rdec[byte]);
return ptu_passed();
}
static struct ptunit_result pfix_test(struct packet_fixture *pfix)
{
int size;
size = pt_enc_next(&pfix->encoder, &pfix->packet[0]);
ptu_int_gt(size, 0);
pfix->packet[0].size = (uint8_t) size;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_gt(size, 0);
return ptu_pkt_eq(&pfix->packet[0], &pfix->packet[1]);
}
static struct ptunit_result no_payload(struct packet_fixture *pfix,
enum pt_packet_type type)
{
pfix->packet[0].type = type;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result unknown(struct packet_fixture *pfix, int exp)
{
int size;
pfix->buffer[0] = pt_opc_bad;
pfix->unknown = exp;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, pfix->unknown);
if (size >= 0) {
ptu_int_eq(pfix->packet[1].type, ppt_unknown);
ptu_uint_eq(pfix->packet[1].size, (uint8_t) size);
ptu_ptr_eq(pfix->packet[1].payload.unknown.packet,
pfix->buffer);
ptu_ptr_eq(pfix->packet[1].payload.unknown.priv, pfix);
}
return ptu_passed();
}
static struct ptunit_result unknown_ext(struct packet_fixture *pfix, int exp)
{
int size;
pfix->buffer[0] = pt_opc_ext;
pfix->buffer[1] = pt_ext_bad;
pfix->unknown = exp;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, pfix->unknown);
if (size >= 0) {
ptu_int_eq(pfix->packet[1].type, ppt_unknown);
ptu_uint_eq(pfix->packet[1].size, (uint8_t) size);
ptu_ptr_eq(pfix->packet[1].payload.unknown.packet,
pfix->buffer);
ptu_ptr_eq(pfix->packet[1].payload.unknown.priv, pfix);
}
return ptu_passed();
}
static struct ptunit_result unknown_ext2(struct packet_fixture *pfix, int exp)
{
int size;
pfix->buffer[0] = pt_opc_ext;
pfix->buffer[1] = pt_ext_ext2;
pfix->buffer[2] = pt_ext2_bad;
pfix->unknown = exp;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, exp);
if (exp >= 0) {
ptu_int_eq(pfix->packet[1].type, ppt_unknown);
ptu_uint_eq(pfix->packet[1].size, (uint8_t) size);
ptu_ptr_eq(pfix->packet[1].payload.unknown.packet,
pfix->buffer);
ptu_ptr_eq(pfix->packet[1].payload.unknown.priv, pfix);
}
return ptu_passed();
}
static struct ptunit_result tnt_8(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_tnt_8;
pfix->packet[0].payload.tnt.bit_size = 4;
pfix->packet[0].payload.tnt.payload = 0x5ull;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result tnt_64(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_tnt_64;
pfix->packet[0].payload.tnt.bit_size = 23;
pfix->packet[0].payload.tnt.payload = 0xabcdeull;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result ip(struct packet_fixture *pfix,
enum pt_packet_type type,
enum pt_ip_compression ipc,
uint64_t ip)
{
pfix->packet[0].type = type;
pfix->packet[0].payload.ip.ipc = ipc;
pfix->packet[0].payload.ip.ip = ip;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result mode_exec(struct packet_fixture *pfix,
enum pt_exec_mode mode)
{
struct pt_packet_mode_exec packet;
packet = pt_set_exec_mode(mode);
pfix->packet[0].type = ppt_mode;
pfix->packet[0].payload.mode.leaf = pt_mol_exec;
pfix->packet[0].payload.mode.bits.exec.csl = packet.csl;
pfix->packet[0].payload.mode.bits.exec.csd = packet.csd;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result mode_tsx(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_mode;
pfix->packet[0].payload.mode.leaf = pt_mol_tsx;
pfix->packet[0].payload.mode.bits.tsx.intx = 1;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result pip(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_pip;
pfix->packet[0].payload.pip.cr3 = 0x4200ull;
pfix->packet[0].payload.pip.nr = 1;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result tsc(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_tsc;
pfix->packet[0].payload.tsc.tsc = 0x42ull;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result cbr(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_cbr;
pfix->packet[0].payload.cbr.ratio = 0x23;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result tma(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_tma;
pfix->packet[0].payload.tma.ctc = 0x42;
pfix->packet[0].payload.tma.fc = 0x123;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result tma_bad(struct packet_fixture *pfix)
{
int errcode;
pfix->packet[0].type = ppt_tma;
pfix->packet[0].payload.tma.ctc = 0x42;
pfix->packet[0].payload.tma.fc = 0x200;
errcode = pt_enc_next(&pfix->encoder, &pfix->packet[0]);
ptu_int_eq(errcode, -pte_bad_packet);
return ptu_passed();
}
static struct ptunit_result mtc(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_mtc;
pfix->packet[0].payload.mtc.ctc = 0x23;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result cyc(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_cyc;
pfix->packet[0].payload.cyc.value = 0x23;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result vmcs(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_vmcs;
pfix->packet[0].payload.vmcs.base = 0xabcdef000ull;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result mnt(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_mnt;
pfix->packet[0].payload.mnt.payload = 0x1234567890abcdefull;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result exstop(struct packet_fixture *pfix, int ip)
{
pfix->packet[0].type = ppt_exstop;
pfix->packet[0].payload.exstop.ip = ip ? 1 : 0;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result mwait(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_mwait;
pfix->packet[0].payload.mwait.hints = 0xc;
pfix->packet[0].payload.mwait.ext = 0x1;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result pwre(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_pwre;
pfix->packet[0].payload.pwre.state = 0x0;
pfix->packet[0].payload.pwre.sub_state = 0x3;
pfix->packet[0].payload.pwre.hw = 1;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result pwrx(struct packet_fixture *pfix)
{
pfix->packet[0].type = ppt_pwrx;
pfix->packet[0].payload.pwrx.last = 0x3;
pfix->packet[0].payload.pwrx.deepest = 0xa;
pfix->packet[0].payload.pwrx.store = 1;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result ptw(struct packet_fixture *pfix, uint8_t plc,
int ip)
{
uint64_t pl, mask;
int size;
size = pt_ptw_size(plc);
ptu_int_gt(size, 0);
pl = 0x1234567890abcdefull;
ptu_uint_le((size_t) size, sizeof(mask));
mask = ~0ull >> ((sizeof(mask) - (size_t) size) * 8);
pfix->packet[0].type = ppt_ptw;
pfix->packet[0].payload.ptw.payload = pl & mask;
pfix->packet[0].payload.ptw.plc = plc;
pfix->packet[0].payload.ptw.ip = ip ? 1 : 0;
ptu_test(pfix_test, pfix);
return ptu_passed();
}
static struct ptunit_result cutoff(struct packet_fixture *pfix,
enum pt_packet_type type)
{
int size;
pfix->packet[0].type = type;
size = pt_enc_next(&pfix->encoder, &pfix->packet[0]);
ptu_int_gt(size, 0);
pfix->decoder.config.end = pfix->encoder.pos - 1;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, -pte_eos);
return ptu_passed();
}
static struct ptunit_result cutoff_ip(struct packet_fixture *pfix,
enum pt_packet_type type)
{
int size;
pfix->packet[0].type = type;
pfix->packet[0].payload.ip.ipc = pt_ipc_sext_48;
size = pt_enc_next(&pfix->encoder, &pfix->packet[0]);
ptu_int_gt(size, 0);
pfix->decoder.config.end = pfix->encoder.pos - 1;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, -pte_eos);
return ptu_passed();
}
static struct ptunit_result cutoff_cyc(struct packet_fixture *pfix)
{
int size;
pfix->packet[0].type = ppt_cyc;
pfix->packet[0].payload.cyc.value = 0xa8;
size = pt_enc_next(&pfix->encoder, &pfix->packet[0]);
ptu_int_gt(size, 0);
pfix->decoder.config.end = pfix->encoder.pos - 1;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, -pte_eos);
return ptu_passed();
}
static struct ptunit_result cutoff_mode(struct packet_fixture *pfix,
enum pt_mode_leaf leaf)
{
int size;
pfix->packet[0].type = ppt_mode;
pfix->packet[0].payload.mode.leaf = leaf;
size = pt_enc_next(&pfix->encoder, &pfix->packet[0]);
ptu_int_gt(size, 0);
pfix->decoder.config.end = pfix->encoder.pos - 1;
size = pt_pkt_next(&pfix->decoder, &pfix->packet[1],
sizeof(pfix->packet[1]));
ptu_int_eq(size, -pte_eos);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct packet_fixture pfix;
struct ptunit_suite suite;
pfix.init = pfix_init;
pfix.fini = pfix_fini;
suite = ptunit_mk_suite(argc, argv);
ptu_run_fp(suite, no_payload, pfix, ppt_pad);
ptu_run_fp(suite, no_payload, pfix, ppt_psb);
ptu_run_fp(suite, no_payload, pfix, ppt_ovf);
ptu_run_fp(suite, no_payload, pfix, ppt_psbend);
ptu_run_fp(suite, no_payload, pfix, ppt_stop);
ptu_run_fp(suite, unknown, pfix, 4);
ptu_run_fp(suite, unknown, pfix, -pte_nomem);
ptu_run_fp(suite, unknown_ext, pfix, 4);
ptu_run_fp(suite, unknown_ext, pfix, -pte_nomem);
ptu_run_fp(suite, unknown_ext2, pfix, 4);
ptu_run_fp(suite, unknown_ext2, pfix, -pte_nomem);
ptu_run_f(suite, tnt_8, pfix);
ptu_run_f(suite, tnt_64, pfix);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_suppressed, 0x0ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_update_16, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_update_32, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_update_48, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_sext_48, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_full, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_suppressed, 0x0ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_update_16, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_update_32, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_update_48, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_sext_48, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip, pt_ipc_full, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pge, pt_ipc_suppressed, 0x0ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pge, pt_ipc_update_16, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pge, pt_ipc_update_32, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pge, pt_ipc_update_48, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pge, pt_ipc_sext_48, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pge, pt_ipc_full, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pgd, pt_ipc_suppressed, 0x0ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pgd, pt_ipc_update_16, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pgd, pt_ipc_update_32, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pgd, pt_ipc_update_48, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pgd, pt_ipc_sext_48, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_tip_pgd, pt_ipc_full, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_fup, pt_ipc_suppressed, 0x0ull);
ptu_run_fp(suite, ip, pfix, ppt_fup, pt_ipc_update_16, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_fup, pt_ipc_update_32, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_fup, pt_ipc_update_48, 0x4200ull);
ptu_run_fp(suite, ip, pfix, ppt_fup, pt_ipc_sext_48, 0x42ull);
ptu_run_fp(suite, ip, pfix, ppt_fup, pt_ipc_full, 0x42ull);
ptu_run_fp(suite, mode_exec, pfix, ptem_16bit);
ptu_run_fp(suite, mode_exec, pfix, ptem_32bit);
ptu_run_fp(suite, mode_exec, pfix, ptem_64bit);
ptu_run_f(suite, mode_tsx, pfix);
ptu_run_f(suite, pip, pfix);
ptu_run_f(suite, tsc, pfix);
ptu_run_f(suite, cbr, pfix);
ptu_run_f(suite, tma, pfix);
ptu_run_f(suite, tma_bad, pfix);
ptu_run_f(suite, mtc, pfix);
ptu_run_f(suite, cyc, pfix);
ptu_run_f(suite, vmcs, pfix);
ptu_run_f(suite, mnt, pfix);
ptu_run_fp(suite, exstop, pfix, 0);
ptu_run_fp(suite, exstop, pfix, 1);
ptu_run_f(suite, mwait, pfix);
ptu_run_f(suite, pwre, pfix);
ptu_run_f(suite, pwrx, pfix);
ptu_run_fp(suite, ptw, pfix, 0, 1);
ptu_run_fp(suite, ptw, pfix, 1, 0);
ptu_run_fp(suite, cutoff, pfix, ppt_psb);
ptu_run_fp(suite, cutoff_ip, pfix, ppt_tip);
ptu_run_fp(suite, cutoff_ip, pfix, ppt_tip_pge);
ptu_run_fp(suite, cutoff_ip, pfix, ppt_tip_pgd);
ptu_run_fp(suite, cutoff_ip, pfix, ppt_fup);
ptu_run_fp(suite, cutoff, pfix, ppt_ovf);
ptu_run_fp(suite, cutoff, pfix, ppt_psbend);
ptu_run_fp(suite, cutoff, pfix, ppt_tnt_64);
ptu_run_fp(suite, cutoff, pfix, ppt_tsc);
ptu_run_fp(suite, cutoff, pfix, ppt_cbr);
ptu_run_fp(suite, cutoff, pfix, ppt_tma);
ptu_run_fp(suite, cutoff, pfix, ppt_mtc);
ptu_run_f(suite, cutoff_cyc, pfix);
ptu_run_fp(suite, cutoff_mode, pfix, pt_mol_exec);
ptu_run_fp(suite, cutoff_mode, pfix, pt_mol_tsx);
ptu_run_fp(suite, cutoff, pfix, ppt_vmcs);
ptu_run_fp(suite, cutoff, pfix, ppt_mnt);
ptu_run_fp(suite, cutoff, pfix, ppt_exstop);
ptu_run_fp(suite, cutoff, pfix, ppt_mwait);
ptu_run_fp(suite, cutoff, pfix, ppt_pwre);
ptu_run_fp(suite, cutoff, pfix, ppt_pwrx);
ptu_run_fp(suite, cutoff, pfix, ppt_ptw);
return ptunit_report(&suite);
}
/* Dummy decode functions to satisfy link dependencies.
*
* As a nice side-effect, we will know if we need to add more tests when
* adding new decoder functions.
*/
struct pt_query_decoder;
int pt_qry_decode_unknown(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_pad(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_psb(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tip(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tnt_8(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tnt_64(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tip_pge(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tip_pgd(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_fup(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_fup(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_pip(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_pip(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_ovf(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_mode(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_mode(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_psbend(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tsc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_tsc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_cbr(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_cbr(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_tma(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_mtc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_cyc(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_stop(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_vmcs(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_vmcs(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_mnt(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_header_mnt(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_exstop(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_mwait(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_pwre(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_pwrx(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}
int pt_qry_decode_ptw(struct pt_query_decoder *d)
{
(void) d;
return -pte_internal;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,232 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "ptunit.h"
#include "pt_retstack.h"
#include "intel-pt.h"
static struct ptunit_result init(void)
{
struct pt_retstack retstack;
int status;
memset(&retstack, 0xcd, sizeof(retstack));
pt_retstack_init(&retstack);
status = pt_retstack_is_empty(&retstack);
ptu_int_ne(status, 0);
return ptu_passed();
}
static struct ptunit_result init_null(void)
{
pt_retstack_init(NULL);
return ptu_passed();
}
static struct ptunit_result query(void)
{
struct pt_retstack retstack;
uint64_t ip;
int status;
pt_retstack_init(&retstack);
status = pt_retstack_push(&retstack, 0x42ull);
ptu_int_eq(status, 0);
status = pt_retstack_is_empty(&retstack);
ptu_int_eq(status, 0);
status = pt_retstack_pop(&retstack, &ip);
ptu_int_eq(status, 0);
ptu_uint_eq(ip, 0x42ull);
status = pt_retstack_is_empty(&retstack);
ptu_int_ne(status, 0);
return ptu_passed();
}
static struct ptunit_result query_empty(void)
{
struct pt_retstack retstack;
uint64_t ip;
int status;
pt_retstack_init(&retstack);
ip = 0x42ull;
status = pt_retstack_pop(&retstack, &ip);
ptu_int_eq(status, -pte_retstack_empty);
ptu_uint_eq(ip, 0x42ull);
return ptu_passed();
}
static struct ptunit_result query_null(void)
{
uint64_t ip;
int status;
ip = 0x42ull;
status = pt_retstack_pop(NULL, &ip);
ptu_int_eq(status, -pte_invalid);
ptu_uint_eq(ip, 0x42ull);
return ptu_passed();
}
static struct ptunit_result pop(void)
{
struct pt_retstack retstack;
int status;
pt_retstack_init(&retstack);
status = pt_retstack_push(&retstack, 0x42ull);
ptu_int_eq(status, 0);
status = pt_retstack_is_empty(&retstack);
ptu_int_eq(status, 0);
status = pt_retstack_pop(&retstack, NULL);
ptu_int_eq(status, 0);
status = pt_retstack_is_empty(&retstack);
ptu_int_ne(status, 0);
return ptu_passed();
}
static struct ptunit_result pop_empty(void)
{
struct pt_retstack retstack;
int status;
pt_retstack_init(&retstack);
status = pt_retstack_pop(&retstack, NULL);
ptu_int_eq(status, -pte_retstack_empty);
return ptu_passed();
}
static struct ptunit_result pop_null(void)
{
int status;
status = pt_retstack_pop(NULL, NULL);
ptu_int_eq(status, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result full(void)
{
struct pt_retstack retstack;
uint64_t ip, idx;
int status;
pt_retstack_init(&retstack);
for (idx = 0; idx < pt_retstack_size; ++idx) {
status = pt_retstack_push(&retstack, idx);
ptu_int_eq(status, 0);
}
status = pt_retstack_is_empty(&retstack);
ptu_int_eq(status, 0);
for (idx = pt_retstack_size; idx > 0;) {
idx -= 1;
status = pt_retstack_pop(&retstack, &ip);
ptu_int_eq(status, 0);
ptu_uint_eq(ip, idx);
}
status = pt_retstack_is_empty(&retstack);
ptu_int_ne(status, 0);
return ptu_passed();
}
static struct ptunit_result overflow(void)
{
struct pt_retstack retstack;
uint64_t ip, idx;
int status;
pt_retstack_init(&retstack);
for (idx = 0; idx <= pt_retstack_size; ++idx) {
status = pt_retstack_push(&retstack, idx);
ptu_int_eq(status, 0);
}
status = pt_retstack_is_empty(&retstack);
ptu_int_eq(status, 0);
for (idx = pt_retstack_size; idx > 0; --idx) {
status = pt_retstack_pop(&retstack, &ip);
ptu_int_eq(status, 0);
ptu_uint_eq(ip, idx);
}
status = pt_retstack_is_empty(&retstack);
ptu_int_ne(status, 0);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, init);
ptu_run(suite, init_null);
ptu_run(suite, query);
ptu_run(suite, query_empty);
ptu_run(suite, query_null);
ptu_run(suite, pop);
ptu_run(suite, pop_empty);
ptu_run(suite, pop_null);
ptu_run(suite, full);
ptu_run(suite, overflow);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2015-2018, 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.
*/
#include "pt_section.h"
#include "pt_section_file.h"
#include "intel-pt.h"
#include <stdlib.h>
#include <stdio.h>
/* This is a variation of ptunit-section.c.
*
* We provide pt_section_map() et.al. that are normally provided by mmap-based
* section implementations. Our implementation falls back to file-based
* sections so we're able to test them.
*
* The actual test is in ptunit-section.c.
*/
/* The file status used for detecting changes to a file between unmap and map.
*
* In our case, the changes always affect the size of the file.
*/
struct pt_file_status {
/* The size in bytes. */
long size;
};
int pt_section_mk_status(void **pstatus, uint64_t *psize, const char *filename)
{
struct pt_file_status *status;
FILE *file;
long size;
int errcode;
if (!pstatus || !psize)
return -pte_internal;
file = fopen(filename, "rb");
if (!file)
return -pte_bad_image;
errcode = fseek(file, 0, SEEK_END);
if (errcode) {
errcode = -pte_bad_image;
goto out_file;
}
size = ftell(file);
if (size < 0) {
errcode = -pte_bad_image;
goto out_file;
}
status = malloc(sizeof(*status));
if (!status) {
errcode = -pte_nomem;
goto out_file;
}
status->size = size;
*pstatus = status;
*psize = (uint64_t) size;
errcode = 0;
out_file:
fclose(file);
return errcode;
}
static int pt_section_map_success(struct pt_section *section)
{
uint16_t mcount;
int errcode, status;
if (!section)
return -pte_internal;
mcount = section->mcount + 1;
if (!mcount) {
(void) pt_section_unlock(section);
return -pte_overflow;
}
section->mcount = mcount;
errcode = pt_section_unlock(section);
if (errcode < 0)
return errcode;
status = pt_section_on_map(section);
if (status < 0) {
(void) pt_section_unmap(section);
return status;
}
return 0;
}
int pt_section_map(struct pt_section *section)
{
struct pt_file_status *status;
const char *filename;
uint16_t mcount;
FILE *file;
long size;
int errcode;
if (!section)
return -pte_internal;
errcode = pt_section_lock(section);
if (errcode < 0)
return errcode;
mcount = section->mcount;
if (mcount)
return pt_section_map_success(section);
if (section->mapping)
goto out_unlock;
filename = section->filename;
if (!filename)
goto out_unlock;
status = section->status;
if (!status)
goto out_unlock;
errcode = -pte_bad_image;
file = fopen(filename, "rb");
if (!file)
goto out_unlock;
errcode = fseek(file, 0, SEEK_END);
if (errcode) {
errcode = -pte_bad_image;
goto out_file;
}
errcode = -pte_bad_image;
size = ftell(file);
if (size < 0)
goto out_file;
if (size != status->size)
goto out_file;
/* 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)
return pt_section_map_success(section);
out_file:
fclose(file);
out_unlock:
(void) pt_section_unlock(section);
return errcode;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,306 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "ptunit.h"
#include "pt_sync.h"
#include "pt_opcodes.h"
#include "intel-pt.h"
/* A test fixture for sync tests. */
struct sync_fixture {
/* The trace buffer. */
uint8_t buffer[1024];
/* A trace configuration. */
struct pt_config config;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct sync_fixture *);
struct ptunit_result (*fini)(struct sync_fixture *);
};
static struct ptunit_result sfix_init(struct sync_fixture *sfix)
{
memset(sfix->buffer, 0xcd, sizeof(sfix->buffer));
memset(&sfix->config, 0, sizeof(sfix->config));
sfix->config.size = sizeof(sfix->config);
sfix->config.begin = sfix->buffer;
sfix->config.end = sfix->buffer + sizeof(sfix->buffer);
return ptu_passed();
}
static void sfix_encode_psb(uint8_t *pos)
{
int i;
*pos++ = pt_opc_psb;
*pos++ = pt_ext_psb;
for (i = 0; i < pt_psb_repeat_count; ++i) {
*pos++ = pt_psb_hi;
*pos++ = pt_psb_lo;
}
}
static struct ptunit_result sync_fwd_null(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
errcode = pt_sync_forward(NULL, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_sync_forward(&sync, NULL, &sfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_sync_forward(&sync, sfix->config.begin, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result sync_bwd_null(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
errcode = pt_sync_backward(NULL, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_sync_backward(&sync, NULL, &sfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_sync_backward(&sync, sfix->config.begin, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result sync_fwd_empty(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix->config.end = sfix->config.begin;
errcode = pt_sync_forward(&sync, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_bwd_empty(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix->config.end = sfix->config.begin;
errcode = pt_sync_backward(&sync, sfix->config.end, &sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_fwd_none(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
errcode = pt_sync_forward(&sync, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_bwd_none(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
errcode = pt_sync_backward(&sync, sfix->config.end, &sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_fwd_here(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.begin);
errcode = pt_sync_forward(&sync, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(sync, sfix->config.begin);
return ptu_passed();
}
static struct ptunit_result sync_bwd_here(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.end - ptps_psb);
errcode = pt_sync_backward(&sync, sfix->config.end, &sfix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(sync, sfix->config.end - ptps_psb);
return ptu_passed();
}
static struct ptunit_result sync_fwd(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.begin + 0x23);
errcode = pt_sync_forward(&sync, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(sync, sfix->config.begin + 0x23);
return ptu_passed();
}
static struct ptunit_result sync_bwd(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.begin + 0x23);
errcode = pt_sync_backward(&sync, sfix->config.end, &sfix->config);
ptu_int_eq(errcode, 0);
ptu_ptr_eq(sync, sfix->config.begin + 0x23);
return ptu_passed();
}
static struct ptunit_result sync_fwd_past(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.begin);
errcode = pt_sync_forward(&sync, sfix->config.begin + ptps_psb,
&sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_bwd_past(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.end - ptps_psb);
errcode = pt_sync_backward(&sync, sfix->config.end - ptps_psb,
&sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_fwd_cutoff(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.begin);
sfix_encode_psb(sfix->config.end - ptps_psb);
sfix->config.begin += 1;
sfix->config.end -= 1;
errcode = pt_sync_forward(&sync, sfix->config.begin, &sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
static struct ptunit_result sync_bwd_cutoff(struct sync_fixture *sfix)
{
const uint8_t *sync;
int errcode;
sfix_encode_psb(sfix->config.begin);
sfix_encode_psb(sfix->config.end - ptps_psb);
sfix->config.begin += 1;
sfix->config.end -= 1;
errcode = pt_sync_backward(&sync, sfix->config.end, &sfix->config);
ptu_int_eq(errcode, -pte_eos);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct sync_fixture sfix;
struct ptunit_suite suite;
sfix.init = sfix_init;
sfix.fini = NULL;
suite = ptunit_mk_suite(argc, argv);
ptu_run_f(suite, sync_fwd_null, sfix);
ptu_run_f(suite, sync_bwd_null, sfix);
ptu_run_f(suite, sync_fwd_empty, sfix);
ptu_run_f(suite, sync_bwd_empty, sfix);
ptu_run_f(suite, sync_fwd_none, sfix);
ptu_run_f(suite, sync_bwd_none, sfix);
ptu_run_f(suite, sync_fwd_here, sfix);
ptu_run_f(suite, sync_bwd_here, sfix);
ptu_run_f(suite, sync_fwd, sfix);
ptu_run_f(suite, sync_bwd, sfix);
ptu_run_f(suite, sync_fwd_past, sfix);
ptu_run_f(suite, sync_bwd_past, sfix);
ptu_run_f(suite, sync_fwd_cutoff, sfix);
ptu_run_f(suite, sync_bwd_cutoff, sfix);
return ptunit_report(&suite);
}

View File

@ -0,0 +1,368 @@
/*
* Copyright (c) 2014-2018, 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.
*/
#include "pt_time.h"
#include "intel-pt.h"
#include "ptunit.h"
/* A time unit test fixture. */
struct time_fixture {
/* The configuration to use. */
struct pt_config config;
/* The calibration to use. */
struct pt_time_cal tcal;
/* The time struct to update. */
struct pt_time time;
/* The test fixture initialization and finalization functions. */
struct ptunit_result (*init)(struct time_fixture *);
struct ptunit_result (*fini)(struct time_fixture *);
};
static struct ptunit_result tfix_init(struct time_fixture *tfix)
{
memset(&tfix->config, 0, sizeof(tfix->config));
tfix->config.size = sizeof(tfix->config);
tfix->config.cpuid_0x15_eax = 2;
tfix->config.cpuid_0x15_ebx = 1;
tfix->config.mtc_freq = 4;
pt_tcal_init(&tfix->tcal);
pt_tcal_set_fcr(&tfix->tcal, 0x2ull << pt_tcal_fcr_shr);
pt_time_init(&tfix->time);
return ptu_passed();
}
static struct ptunit_result tsc_null(struct time_fixture *tfix)
{
struct pt_packet_tsc packet;
int errcode;
errcode = pt_time_update_tsc(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_tsc(&tfix->time, NULL, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result cbr_null(struct time_fixture *tfix)
{
struct pt_packet_cbr packet;
int errcode;
errcode = pt_time_update_cbr(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_cbr(&tfix->time, NULL, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result tma_null(struct time_fixture *tfix)
{
struct pt_packet_tma packet;
int errcode;
errcode = pt_time_update_tma(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_tma(&tfix->time, NULL, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_tma(&tfix->time, &packet, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result mtc_null(struct time_fixture *tfix)
{
struct pt_packet_mtc packet;
int errcode;
errcode = pt_time_update_mtc(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_mtc(&tfix->time, NULL, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_mtc(&tfix->time, &packet, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result cyc_null(struct time_fixture *tfix)
{
struct pt_packet_cyc packet;
int errcode;
errcode = pt_time_update_cyc(NULL, &packet, &tfix->config, 0ull);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_cyc(&tfix->time, NULL, &tfix->config, 0ull);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_update_cyc(&tfix->time, &packet, NULL, 0ull);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result query_tsc_null(struct time_fixture *tfix)
{
uint64_t tsc;
int errcode;
errcode = pt_time_query_tsc(NULL, NULL, NULL, &tfix->time);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_query_tsc(&tsc, NULL, NULL, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result query_tsc_none(struct time_fixture *tfix)
{
uint64_t tsc;
int errcode;
errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
ptu_int_eq(errcode, -pte_no_time);
return ptu_passed();
}
static struct ptunit_result query_cbr_null(struct time_fixture *tfix)
{
uint32_t cbr;
int errcode;
errcode = pt_time_query_cbr(NULL, &tfix->time);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_time_query_cbr(&cbr, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result query_cbr_none(struct time_fixture *tfix)
{
uint32_t cbr;
int errcode;
errcode = pt_time_query_cbr(&cbr, &tfix->time);
ptu_int_eq(errcode, -pte_no_cbr);
return ptu_passed();
}
static struct ptunit_result tcal_cbr_null(struct time_fixture *tfix)
{
struct pt_packet_cbr packet;
int errcode;
errcode = pt_tcal_update_cbr(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result tcal_mtc_null(struct time_fixture *tfix)
{
struct pt_packet_mtc packet;
int errcode;
errcode = pt_tcal_update_mtc(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_tcal_update_mtc(&tfix->tcal, NULL, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_tcal_update_mtc(&tfix->tcal, &packet, NULL);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result tcal_cyc_null(struct time_fixture *tfix)
{
struct pt_packet_cyc packet;
int errcode;
errcode = pt_tcal_update_cyc(NULL, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
errcode = pt_tcal_update_cyc(&tfix->tcal, NULL, &tfix->config);
ptu_int_eq(errcode, -pte_internal);
return ptu_passed();
}
static struct ptunit_result tsc(struct time_fixture *tfix)
{
struct pt_packet_tsc packet;
uint64_t tsc;
uint32_t lost_mtc, lost_cyc;
int errcode;
packet.tsc = 0xdedededeull;
errcode = pt_time_update_tsc(&tfix->time, &packet, &tfix->config);
ptu_int_eq(errcode, 0);
errcode = pt_time_query_tsc(&tsc, &lost_mtc, &lost_cyc, &tfix->time);
ptu_int_eq(errcode, 0);
ptu_uint_eq(tsc, 0xdedededeull);
ptu_uint_eq(lost_mtc, 0);
ptu_uint_eq(lost_cyc, 0);
return ptu_passed();
}
static struct ptunit_result cbr(struct time_fixture *tfix)
{
struct pt_packet_cbr packet;
uint32_t cbr;
int errcode;
packet.ratio = 0x38;
errcode = pt_time_update_cbr(&tfix->time, &packet, &tfix->config);
ptu_int_eq(errcode, 0);
errcode = pt_time_query_cbr(&cbr, &tfix->time);
ptu_int_eq(errcode, 0);
ptu_uint_eq(cbr, 0x38);
return ptu_passed();
}
static struct ptunit_result tma(struct time_fixture *tfix)
{
struct pt_packet_tma packet;
int errcode;
packet.ctc = 0xdc;
packet.fc = 0xf;
errcode = pt_time_update_tma(&tfix->time, &packet, &tfix->config);
ptu_int_eq(errcode, -pte_bad_context);
return ptu_passed();
}
static struct ptunit_result mtc(struct time_fixture *tfix)
{
struct pt_packet_mtc packet;
uint64_t tsc;
int errcode;
packet.ctc = 0xdc;
errcode = pt_time_update_mtc(&tfix->time, &packet, &tfix->config);
ptu_int_eq(errcode, 0);
errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
ptu_int_eq(errcode, -pte_no_time);
return ptu_passed();
}
static struct ptunit_result cyc(struct time_fixture *tfix)
{
struct pt_packet_cyc packet;
uint64_t fcr, tsc;
int errcode;
errcode = pt_tcal_fcr(&fcr, &tfix->tcal);
ptu_int_eq(errcode, 0);
packet.value = 0xdc;
errcode = pt_time_update_cyc(&tfix->time, &packet, &tfix->config, fcr);
ptu_int_eq(errcode, 0);
errcode = pt_time_query_tsc(&tsc, NULL, NULL, &tfix->time);
ptu_int_eq(errcode, -pte_no_time);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
struct time_fixture tfix;
suite = ptunit_mk_suite(argc, argv);
tfix.init = tfix_init;
tfix.fini = NULL;
ptu_run_f(suite, tsc_null, tfix);
ptu_run_f(suite, cbr_null, tfix);
ptu_run_f(suite, tma_null, tfix);
ptu_run_f(suite, mtc_null, tfix);
ptu_run_f(suite, cyc_null, tfix);
ptu_run_f(suite, query_tsc_null, tfix);
ptu_run_f(suite, query_tsc_none, tfix);
ptu_run_f(suite, query_cbr_null, tfix);
ptu_run_f(suite, query_cbr_none, tfix);
ptu_run_f(suite, tcal_cbr_null, tfix);
ptu_run_f(suite, tcal_mtc_null, tfix);
ptu_run_f(suite, tcal_cyc_null, tfix);
ptu_run_f(suite, tsc, tfix);
ptu_run_f(suite, cbr, tfix);
ptu_run_f(suite, tma, tfix);
ptu_run_f(suite, mtc, tfix);
ptu_run_f(suite, cyc, tfix);
/* The bulk is covered in ptt tests. */
return ptunit_report(&suite);
}

View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2013-2018, 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.
*/
#include "ptunit.h"
#include "pt_tnt_cache.h"
#include "intel-pt.h"
#include <string.h>
static struct ptunit_result init(void)
{
struct pt_tnt_cache tnt_cache;
memset(&tnt_cache, 0xcd, sizeof(tnt_cache));
pt_tnt_cache_init(&tnt_cache);
ptu_uint_eq(tnt_cache.tnt, 0ull);
ptu_uint_eq(tnt_cache.index, 0ull);
return ptu_passed();
}
static struct ptunit_result init_null(void)
{
pt_tnt_cache_init(NULL);
return ptu_passed();
}
static struct ptunit_result is_empty_initial(void)
{
struct pt_tnt_cache tnt_cache;
int status;
pt_tnt_cache_init(&tnt_cache);
status = pt_tnt_cache_is_empty(&tnt_cache);
ptu_int_eq(status, 1);
return ptu_passed();
}
static struct ptunit_result is_empty_no(void)
{
struct pt_tnt_cache tnt_cache;
int status;
tnt_cache.index = 1ull;
status = pt_tnt_cache_is_empty(&tnt_cache);
ptu_int_eq(status, 0);
return ptu_passed();
}
static struct ptunit_result is_empty_yes(void)
{
struct pt_tnt_cache tnt_cache;
int status;
tnt_cache.index = 0ull;
status = pt_tnt_cache_is_empty(&tnt_cache);
ptu_int_eq(status, 1);
return ptu_passed();
}
static struct ptunit_result is_empty_null(void)
{
int status;
status = pt_tnt_cache_is_empty(NULL);
ptu_int_eq(status, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result query_taken(void)
{
struct pt_tnt_cache tnt_cache;
int status;
tnt_cache.tnt = 1ull;
tnt_cache.index = 1ull;
status = pt_tnt_cache_query(&tnt_cache);
ptu_int_eq(status, 1);
ptu_uint_eq(tnt_cache.index, 0);
return ptu_passed();
}
static struct ptunit_result query_not_taken(void)
{
struct pt_tnt_cache tnt_cache;
int status;
tnt_cache.tnt = 0ull;
tnt_cache.index = 1ull;
status = pt_tnt_cache_query(&tnt_cache);
ptu_int_eq(status, 0);
ptu_uint_eq(tnt_cache.index, 0);
return ptu_passed();
}
static struct ptunit_result query_empty(void)
{
struct pt_tnt_cache tnt_cache;
int status;
tnt_cache.index = 0ull;
status = pt_tnt_cache_query(&tnt_cache);
ptu_int_eq(status, -pte_bad_query);
return ptu_passed();
}
static struct ptunit_result query_null(void)
{
int status;
status = pt_tnt_cache_query(NULL);
ptu_int_eq(status, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result update_tnt(void)
{
struct pt_tnt_cache tnt_cache;
struct pt_packet_tnt packet;
int errcode;
pt_tnt_cache_init(&tnt_cache);
packet.bit_size = 4ull;
packet.payload = 8ull;
errcode = pt_tnt_cache_update_tnt(&tnt_cache, &packet, NULL);
ptu_int_eq(errcode, 0);
ptu_uint_eq(tnt_cache.tnt, 8ull);
ptu_uint_eq(tnt_cache.index, 1ull << 3);
return ptu_passed();
}
static struct ptunit_result update_tnt_not_empty(void)
{
struct pt_tnt_cache tnt_cache;
struct pt_packet_tnt packet;
int errcode;
tnt_cache.tnt = 42ull;
tnt_cache.index = 12ull;
errcode = pt_tnt_cache_update_tnt(&tnt_cache, &packet, NULL);
ptu_int_eq(errcode, -pte_bad_context);
ptu_uint_eq(tnt_cache.tnt, 42ull);
ptu_uint_eq(tnt_cache.index, 12ull);
return ptu_passed();
}
static struct ptunit_result update_tnt_null_tnt(void)
{
struct pt_packet_tnt packet;
int errcode;
errcode = pt_tnt_cache_update_tnt(NULL, &packet, NULL);
ptu_int_eq(errcode, -pte_invalid);
return ptu_passed();
}
static struct ptunit_result update_tnt_null_packet(void)
{
struct pt_tnt_cache tnt_cache;
int errcode;
tnt_cache.tnt = 42ull;
tnt_cache.index = 12ull;
errcode = pt_tnt_cache_update_tnt(&tnt_cache, NULL, NULL);
ptu_int_eq(errcode, -pte_invalid);
ptu_uint_eq(tnt_cache.tnt, 42ull);
ptu_uint_eq(tnt_cache.index, 12ull);
return ptu_passed();
}
int main(int argc, char **argv)
{
struct ptunit_suite suite;
suite = ptunit_mk_suite(argc, argv);
ptu_run(suite, init);
ptu_run(suite, init_null);
ptu_run(suite, is_empty_initial);
ptu_run(suite, is_empty_no);
ptu_run(suite, is_empty_yes);
ptu_run(suite, is_empty_null);
ptu_run(suite, query_taken);
ptu_run(suite, query_not_taken);
ptu_run(suite, query_empty);
ptu_run(suite, query_null);
ptu_run(suite, update_tnt);
ptu_run(suite, update_tnt_not_empty);
ptu_run(suite, update_tnt_null_tnt);
ptu_run(suite, update_tnt_null_packet);
return ptunit_report(&suite);
}