/* * Copyright (c) 2013-2017, 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 "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 }; 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_decode_mnt, /* .flags = */ pdff_pad }; 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: *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_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; } } } }