diff options
Diffstat (limited to 'libipt/src/pt_decoder_function.c')
-rw-r--r-- | libipt/src/pt_decoder_function.c | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/libipt/src/pt_decoder_function.c b/libipt/src/pt_decoder_function.c new file mode 100644 index 0000000000000..96734cac69202 --- /dev/null +++ b/libipt/src/pt_decoder_function.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2013-2019, 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; + } + } + } +} |