Import Intel Processor Trace decoder library from
vendor/processor-trace/24982c1a6fce48f1e416461d42899805f74fbb26 Sponsored by: DARPA, AFRL
This commit is contained in:
commit
c27a7c453c
259
contrib/processor-trace/include/posix/threads.h
Normal file
259
contrib/processor-trace/include/posix/threads.h
Normal 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 */
|
47
contrib/processor-trace/include/pt_compiler.h
Normal file
47
contrib/processor-trace/include/pt_compiler.h
Normal 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 */
|
65
contrib/processor-trace/include/windows/inttypes.h
Normal file
65
contrib/processor-trace/include/windows/inttypes.h
Normal 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
|
239
contrib/processor-trace/include/windows/threads.h
Normal file
239
contrib/processor-trace/include/windows/threads.h
Normal 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 */
|
172
contrib/processor-trace/libipt/CMakeLists.txt
Normal file
172
contrib/processor-trace/libipt/CMakeLists.txt
Normal 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)
|
2463
contrib/processor-trace/libipt/include/intel-pt.h
Executable file
2463
contrib/processor-trace/libipt/include/intel-pt.h
Executable file
File diff suppressed because it is too large
Load Diff
2463
contrib/processor-trace/libipt/include/intel-pt.h.in
Executable file
2463
contrib/processor-trace/libipt/include/intel-pt.h.in
Executable file
File diff suppressed because it is too large
Load Diff
@ -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 */
|
74
contrib/processor-trace/libipt/internal/include/pt_asid.h
Normal file
74
contrib/processor-trace/libipt/internal/include/pt_asid.h
Normal 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 */
|
225
contrib/processor-trace/libipt/internal/include/pt_block_cache.h
Normal file
225
contrib/processor-trace/libipt/internal/include/pt_block_cache.h
Normal 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 */
|
@ -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 */
|
82
contrib/processor-trace/libipt/internal/include/pt_config.h
Normal file
82
contrib/processor-trace/libipt/internal/include/pt_config.h
Normal 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);
|
54
contrib/processor-trace/libipt/internal/include/pt_cpu.h
Normal file
54
contrib/processor-trace/libipt/internal/include/pt_cpu.h
Normal 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 */
|
40
contrib/processor-trace/libipt/internal/include/pt_cpuid.h
Normal file
40
contrib/processor-trace/libipt/internal/include/pt_cpuid.h
Normal 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 */
|
@ -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 */
|
125
contrib/processor-trace/libipt/internal/include/pt_encoder.h
Normal file
125
contrib/processor-trace/libipt/internal/include/pt_encoder.h
Normal 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 */
|
143
contrib/processor-trace/libipt/internal/include/pt_event_queue.h
Normal file
143
contrib/processor-trace/libipt/internal/include/pt_event_queue.h
Normal 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 */
|
128
contrib/processor-trace/libipt/internal/include/pt_ild.h
Normal file
128
contrib/processor-trace/libipt/internal/include/pt_ild.h
Normal 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 */
|
140
contrib/processor-trace/libipt/internal/include/pt_image.h
Normal file
140
contrib/processor-trace/libipt/internal/include/pt_image.h
Normal 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 */
|
@ -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 */
|
212
contrib/processor-trace/libipt/internal/include/pt_insn.h
Normal file
212
contrib/processor-trace/libipt/internal/include/pt_insn.h
Normal 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 */
|
@ -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 */
|
79
contrib/processor-trace/libipt/internal/include/pt_last_ip.h
Normal file
79
contrib/processor-trace/libipt/internal/include/pt_last_ip.h
Normal 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 */
|
@ -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 */
|
@ -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 */
|
397
contrib/processor-trace/libipt/internal/include/pt_opcodes.h
Normal file
397
contrib/processor-trace/libipt/internal/include/pt_opcodes.h
Normal 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 */
|
111
contrib/processor-trace/libipt/internal/include/pt_packet.h
Normal file
111
contrib/processor-trace/libipt/internal/include/pt_packet.h
Normal 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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
392
contrib/processor-trace/libipt/internal/include/pt_section.h
Normal file
392
contrib/processor-trace/libipt/internal/include/pt_section.h
Normal 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 */
|
@ -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 */
|
71
contrib/processor-trace/libipt/internal/include/pt_sync.h
Normal file
71
contrib/processor-trace/libipt/internal/include/pt_sync.h
Normal 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 */
|
232
contrib/processor-trace/libipt/internal/include/pt_time.h
Normal file
232
contrib/processor-trace/libipt/internal/include/pt_time.h
Normal 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 */
|
@ -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 */
|
@ -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
|
544
contrib/processor-trace/libipt/internal/include/pti-disp.h
Normal file
544
contrib/processor-trace/libipt/internal/include/pti-disp.h
Normal 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,
|
||||
};
|
@ -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
|
544
contrib/processor-trace/libipt/internal/include/pti-imm.h
Normal file
544
contrib/processor-trace/libipt/internal/include/pti-imm.h
Normal 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,
|
||||
};
|
@ -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
|
544
contrib/processor-trace/libipt/internal/include/pti-modrm.h
Normal file
544
contrib/processor-trace/libipt/internal/include/pti-modrm.h
Normal 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,
|
||||
};
|
@ -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 */
|
36
contrib/processor-trace/libipt/src/posix/init.c
Normal file
36
contrib/processor-trace/libipt/src/posix/init.c
Normal 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();
|
||||
}
|
37
contrib/processor-trace/libipt/src/posix/pt_cpuid.c
Normal file
37
contrib/processor-trace/libipt/src/posix/pt_cpuid.c
Normal 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);
|
||||
}
|
326
contrib/processor-trace/libipt/src/posix/pt_section_posix.c
Normal file
326
contrib/processor-trace/libipt/src/posix/pt_section_posix.c
Normal 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;
|
||||
}
|
106
contrib/processor-trace/libipt/src/pt_asid.c
Normal file
106
contrib/processor-trace/libipt/src/pt_asid.c
Normal 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;
|
||||
}
|
96
contrib/processor-trace/libipt/src/pt_block_cache.c
Normal file
96
contrib/processor-trace/libipt/src/pt_block_cache.c
Normal 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;
|
||||
}
|
3469
contrib/processor-trace/libipt/src/pt_block_decoder.c
Normal file
3469
contrib/processor-trace/libipt/src/pt_block_decoder.c
Normal file
File diff suppressed because it is too large
Load Diff
251
contrib/processor-trace/libipt/src/pt_config.c
Normal file
251
contrib/processor-trace/libipt/src/pt_config.c
Normal 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);
|
||||
}
|
164
contrib/processor-trace/libipt/src/pt_cpu.c
Normal file
164
contrib/processor-trace/libipt/src/pt_cpu.c
Normal 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;
|
||||
}
|
379
contrib/processor-trace/libipt/src/pt_decoder_function.c
Normal file
379
contrib/processor-trace/libipt/src/pt_decoder_function.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
917
contrib/processor-trace/libipt/src/pt_encoder.c
Normal file
917
contrib/processor-trace/libipt/src/pt_encoder.c
Normal 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);
|
||||
}
|
122
contrib/processor-trace/libipt/src/pt_error.c
Normal file
122
contrib/processor-trace/libipt/src/pt_error.c
Normal 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.";
|
||||
}
|
203
contrib/processor-trace/libipt/src/pt_event_queue.c
Normal file
203
contrib/processor-trace/libipt/src/pt_event_queue.c
Normal 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;
|
||||
}
|
1223
contrib/processor-trace/libipt/src/pt_ild.c
Normal file
1223
contrib/processor-trace/libipt/src/pt_ild.c
Normal file
File diff suppressed because it is too large
Load Diff
718
contrib/processor-trace/libipt/src/pt_image.c
Normal file
718
contrib/processor-trace/libipt/src/pt_image.c
Normal 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 = ¤t->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, §ion, &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;
|
||||
}
|
1091
contrib/processor-trace/libipt/src/pt_image_section_cache.c
Normal file
1091
contrib/processor-trace/libipt/src/pt_image_section_cache.c
Normal file
File diff suppressed because it is too large
Load Diff
372
contrib/processor-trace/libipt/src/pt_insn.c
Normal file
372
contrib/processor-trace/libipt/src/pt_insn.c
Normal 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;
|
||||
}
|
1765
contrib/processor-trace/libipt/src/pt_insn_decoder.c
Normal file
1765
contrib/processor-trace/libipt/src/pt_insn_decoder.c
Normal file
File diff suppressed because it is too large
Load Diff
127
contrib/processor-trace/libipt/src/pt_last_ip.c
Normal file
127
contrib/processor-trace/libipt/src/pt_last_ip.c
Normal 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;
|
||||
}
|
136
contrib/processor-trace/libipt/src/pt_msec_cache.c
Normal file
136
contrib/processor-trace/libipt/src/pt_msec_cache.c
Normal 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;
|
||||
}
|
573
contrib/processor-trace/libipt/src/pt_packet.c
Normal file
573
contrib/processor-trace/libipt/src/pt_packet.c
Normal 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;
|
||||
}
|
723
contrib/processor-trace/libipt/src/pt_packet_decoder.c
Normal file
723
contrib/processor-trace/libipt/src/pt_packet_decoder.c
Normal 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;
|
||||
}
|
3630
contrib/processor-trace/libipt/src/pt_query_decoder.c
Normal file
3630
contrib/processor-trace/libipt/src/pt_query_decoder.c
Normal file
File diff suppressed because it is too large
Load Diff
94
contrib/processor-trace/libipt/src/pt_retstack.c
Normal file
94
contrib/processor-trace/libipt/src/pt_retstack.c
Normal 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;
|
||||
}
|
643
contrib/processor-trace/libipt/src/pt_section.c
Normal file
643
contrib/processor-trace/libipt/src/pt_section.c
Normal 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(§ion->lock, mtx_plain);
|
||||
if (errcode != thrd_success) {
|
||||
free(section->filename);
|
||||
free(section);
|
||||
goto out_status;
|
||||
}
|
||||
|
||||
errcode = mtx_init(§ion->alock, mtx_plain);
|
||||
if (errcode != thrd_success) {
|
||||
mtx_destroy(§ion->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(§ion->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(§ion->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(§ion->alock);
|
||||
mtx_destroy(§ion->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(§ion->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(§ion->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);
|
||||
}
|
255
contrib/processor-trace/libipt/src/pt_section_file.c
Normal file
255
contrib/processor-trace/libipt/src/pt_section_file.c
Normal 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;
|
||||
}
|
241
contrib/processor-trace/libipt/src/pt_sync.c
Normal file
241
contrib/processor-trace/libipt/src/pt_sync.c
Normal 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;
|
||||
}
|
||||
}
|
674
contrib/processor-trace/libipt/src/pt_time.c
Normal file
674
contrib/processor-trace/libipt/src/pt_time.c
Normal 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;
|
||||
}
|
89
contrib/processor-trace/libipt/src/pt_tnt_cache.c
Normal file
89
contrib/processor-trace/libipt/src/pt_tnt_cache.c
Normal 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;
|
||||
}
|
43
contrib/processor-trace/libipt/src/pt_version.c
Normal file
43
contrib/processor-trace/libipt/src/pt_version.c
Normal 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;
|
||||
}
|
51
contrib/processor-trace/libipt/src/windows/init.c
Normal file
51
contrib/processor-trace/libipt/src/windows/init.c
Normal 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;
|
||||
}
|
43
contrib/processor-trace/libipt/src/windows/pt_cpuid.c
Normal file
43
contrib/processor-trace/libipt/src/windows/pt_cpuid.c
Normal 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];
|
||||
}
|
397
contrib/processor-trace/libipt/src/windows/pt_section_windows.c
Normal file
397
contrib/processor-trace/libipt/src/windows/pt_section_windows.c
Normal 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;
|
||||
}
|
425
contrib/processor-trace/libipt/test/src/ptunit-asid.c
Normal file
425
contrib/processor-trace/libipt/test/src/ptunit-asid.c
Normal 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);
|
||||
}
|
370
contrib/processor-trace/libipt/test/src/ptunit-block_cache.c
Normal file
370
contrib/processor-trace/libipt/test/src/ptunit-block_cache.c
Normal 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);
|
||||
}
|
496
contrib/processor-trace/libipt/test/src/ptunit-config.c
Normal file
496
contrib/processor-trace/libipt/test/src/ptunit-config.c
Normal 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);
|
||||
}
|
78
contrib/processor-trace/libipt/test/src/ptunit-cpp.cpp
Normal file
78
contrib/processor-trace/libipt/test/src/ptunit-cpp.cpp
Normal 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);
|
||||
}
|
173
contrib/processor-trace/libipt/test/src/ptunit-cpu.c
Normal file
173
contrib/processor-trace/libipt/test/src/ptunit-cpu.c
Normal 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);
|
||||
}
|
470
contrib/processor-trace/libipt/test/src/ptunit-event_queue.c
Normal file
470
contrib/processor-trace/libipt/test/src/ptunit-event_queue.c
Normal 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);
|
||||
}
|
693
contrib/processor-trace/libipt/test/src/ptunit-fetch.c
Normal file
693
contrib/processor-trace/libipt/test/src/ptunit-fetch.c
Normal 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;
|
||||
}
|
759
contrib/processor-trace/libipt/test/src/ptunit-ild.c
Normal file
759
contrib/processor-trace/libipt/test/src/ptunit-ild.c
Normal 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);
|
||||
}
|
2286
contrib/processor-trace/libipt/test/src/ptunit-image.c
Normal file
2286
contrib/processor-trace/libipt/test/src/ptunit-image.c
Normal file
File diff suppressed because it is too large
Load Diff
2027
contrib/processor-trace/libipt/test/src/ptunit-image_section_cache.c
Normal file
2027
contrib/processor-trace/libipt/test/src/ptunit-image_section_cache.c
Normal file
File diff suppressed because it is too large
Load Diff
374
contrib/processor-trace/libipt/test/src/ptunit-last_ip.c
Normal file
374
contrib/processor-trace/libipt/test/src/ptunit-last_ip.c
Normal 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);
|
||||
}
|
198
contrib/processor-trace/libipt/test/src/ptunit-mapped_section.c
Normal file
198
contrib/processor-trace/libipt/test/src/ptunit-mapped_section.c
Normal 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, §ion, NULL, 0x2000ull, 0x100ull, 0x1000ull);
|
||||
|
||||
psection = pt_msec_section(&msec);
|
||||
ptu_ptr_eq(psection, §ion);
|
||||
|
||||
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);
|
||||
}
|
419
contrib/processor-trace/libipt/test/src/ptunit-msec_cache.c
Normal file
419
contrib/processor-trace/libipt/test/src/ptunit-msec_cache.c
Normal 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);
|
||||
}
|
859
contrib/processor-trace/libipt/test/src/ptunit-packet.c
Normal file
859
contrib/processor-trace/libipt/test/src/ptunit-packet.c
Normal 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;
|
||||
}
|
2873
contrib/processor-trace/libipt/test/src/ptunit-query.c
Normal file
2873
contrib/processor-trace/libipt/test/src/ptunit-query.c
Normal file
File diff suppressed because it is too large
Load Diff
232
contrib/processor-trace/libipt/test/src/ptunit-retstack.c
Normal file
232
contrib/processor-trace/libipt/test/src/ptunit-retstack.c
Normal 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);
|
||||
}
|
192
contrib/processor-trace/libipt/test/src/ptunit-section-file.c
Normal file
192
contrib/processor-trace/libipt/test/src/ptunit-section-file.c
Normal 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;
|
||||
}
|
1396
contrib/processor-trace/libipt/test/src/ptunit-section.c
Normal file
1396
contrib/processor-trace/libipt/test/src/ptunit-section.c
Normal file
File diff suppressed because it is too large
Load Diff
306
contrib/processor-trace/libipt/test/src/ptunit-sync.c
Normal file
306
contrib/processor-trace/libipt/test/src/ptunit-sync.c
Normal 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);
|
||||
}
|
368
contrib/processor-trace/libipt/test/src/ptunit-time.c
Normal file
368
contrib/processor-trace/libipt/test/src/ptunit-time.c
Normal 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);
|
||||
}
|
246
contrib/processor-trace/libipt/test/src/ptunit-tnt_cache.c
Normal file
246
contrib/processor-trace/libipt/test/src/ptunit-tnt_cache.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user