"Fossies" - the Fresh Open Source Software Archive

Member "honggfuzz-2.2/linux/pt.c" (23 Apr 2020, 5200 Bytes) of package /linux/privat/honggfuzz-2.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pt.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1_vs_2.2.

    1 /*
    2  *
    3  * honggfuzz - Intel PT decoder
    4  * -----------------------------------------
    5  *
    6  * Author: Robert Swiecki <swiecki@google.com>
    7  *
    8  * Copyright 2010-2018 by Google Inc. All Rights Reserved.
    9  *
   10  * Licensed under the Apache License, Version 2.0 (the "License"); you may
   11  * not use this file except in compliance with the License. You may obtain
   12  * a copy of the License at
   13  *
   14  * http://www.apache.org/licenses/LICENSE-2.0
   15  *
   16  * Unless required by applicable law or agreed to in writing, software
   17  * distributed under the License is distributed on an "AS IS" BASIS,
   18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   19  * implied. See the License for the specific language governing
   20  * permissions and limitations under the License.
   21  *
   22  */
   23 
   24 #include "pt.h"
   25 
   26 #include <inttypes.h>
   27 #include <linux/perf_event.h>
   28 #include <stdio.h>
   29 
   30 #include "libhfcommon/common.h"
   31 #include "libhfcommon/log.h"
   32 #include "libhfcommon/util.h"
   33 
   34 #ifdef _HF_LINUX_INTEL_PT_LIB
   35 
   36 #include <intel-pt.h>
   37 
   38 struct pt_cpu ptCpu = {
   39     .vendor = pcv_unknown,
   40     .family = 0,
   41     .model = 0,
   42     .stepping = 0,
   43 };
   44 
   45 void perf_ptInit(void) {
   46     FILE* f = fopen("/proc/cpuinfo", "rb");
   47     if (!f) {
   48         PLOG_E("Couldn't open '/proc/cpuinfo'");
   49         return;
   50     }
   51     for (;;) {
   52         char k[1024], t[1024], v[1024];
   53         int ret = fscanf(f, "%1023[^\t]%1023[\t]: %1023[^\n]\n", k, t, v);
   54         if (ret == EOF) {
   55             break;
   56         }
   57         if (ret != 3) {
   58             break;
   59         }
   60         if (strcmp(k, "vendor_id") == 0) {
   61             if (strcmp(v, "GenuineIntel") == 0) {
   62                 ptCpu.vendor = pcv_intel;
   63                 LOG_D("IntelPT vendor: Intel");
   64             } else {
   65                 ptCpu.vendor = pcv_unknown;
   66                 LOG_D("Current processor is not Intel, IntelPT will not work");
   67             }
   68         }
   69         if (strcmp(k, "cpu family") == 0) {
   70             ptCpu.family = atoi(v);
   71             LOG_D("IntelPT family: %" PRIu16, ptCpu.family);
   72         }
   73         if (strcmp(k, "model") == 0) {
   74             ptCpu.model = atoi(v);
   75             LOG_D("IntelPT model: %" PRIu8, ptCpu.model);
   76         }
   77         if (strcmp(k, "stepping") == 0) {
   78             ptCpu.stepping = atoi(v);
   79             LOG_D("IntelPT stepping: %" PRIu8, ptCpu.stepping);
   80         }
   81     }
   82     fclose(f);
   83 }
   84 
   85 /* Sign-extend a uint64_t value. */
   86 inline static uint64_t sext(uint64_t val, uint8_t sign) {
   87     uint64_t signbit, mask;
   88 
   89     signbit = 1ull << (sign - 1);
   90     mask = ~0ull << sign;
   91 
   92     return val & signbit ? val | mask : val & ~mask;
   93 }
   94 
   95 __attribute__((hot)) inline static void perf_ptAnalyzePkt(run_t* run, struct pt_packet* packet) {
   96     if (packet->type != ppt_tip) {
   97         return;
   98     }
   99 
  100     uint64_t ip;
  101     switch (packet->payload.ip.ipc) {
  102         case pt_ipc_update_16:
  103             ip = packet->payload.ip.ip & 0xFFFF;
  104             break;
  105         case pt_ipc_update_32:
  106             ip = packet->payload.ip.ip & 0xFFFFFFFF;
  107             break;
  108         case pt_ipc_update_48:
  109             ip = packet->payload.ip.ip & 0xFFFFFFFFFFFF;
  110             break;
  111         case pt_ipc_sext_48:
  112             ip = sext(packet->payload.ip.ip, 48);
  113             break;
  114         case pt_ipc_full:
  115             ip = packet->payload.ip.ip;
  116             break;
  117         default:
  118             return;
  119     }
  120 
  121     if (ip >= run->global->arch_linux.dynamicCutOffAddr) {
  122         return;
  123     }
  124 
  125     ip &= _HF_PERF_BITMAP_BITSZ_MASK;
  126     register bool prev = ATOMIC_BITMAP_SET(run->global->feedback.covFeedbackMap->bbMapPc, ip);
  127     if (!prev) {
  128         run->hwCnts.newBBCnt++;
  129     }
  130 }
  131 
  132 void arch_ptAnalyze(run_t* run) {
  133     struct perf_event_mmap_page* pem = (struct perf_event_mmap_page*)run->arch_linux.perfMmapBuf;
  134 
  135     uint64_t aux_tail = ATOMIC_GET(pem->aux_tail);
  136     uint64_t aux_head = ATOMIC_GET(pem->aux_head);
  137 
  138     /* smp_rmb() required as per /usr/include/linux/perf_event.h */
  139     rmb();
  140 
  141     struct pt_config ptc;
  142     pt_config_init(&ptc);
  143     ptc.begin = &run->arch_linux.perfMmapAux[aux_tail];
  144     ptc.end = &run->arch_linux.perfMmapAux[aux_head];
  145     ptc.cpu = ptCpu;
  146 
  147     int errcode = pt_cpu_errata(&ptc.errata, &ptc.cpu);
  148     if (errcode < 0) {
  149         LOG_F("pt_errata() failed: %s", pt_errstr(-errcode));
  150     }
  151 
  152     struct pt_packet_decoder* ptd = pt_pkt_alloc_decoder(&ptc);
  153     if (ptd == NULL) {
  154         LOG_F("pt_pkt_alloc_decoder() failed");
  155     }
  156     defer {
  157         pt_pkt_free_decoder(ptd);
  158     };
  159 
  160     errcode = pt_pkt_sync_forward(ptd);
  161     if (errcode < 0) {
  162         LOG_W("pt_pkt_sync_forward() failed: %s", pt_errstr(-errcode));
  163         return;
  164     }
  165 
  166     for (;;) {
  167         struct pt_packet packet;
  168         errcode = pt_pkt_next(ptd, &packet, sizeof(packet));
  169         if (errcode == -pte_eos) {
  170             break;
  171         }
  172         if (errcode < 0) {
  173             LOG_W("pt_pkt_next() failed: %s", pt_errstr(-errcode));
  174             break;
  175         }
  176         perf_ptAnalyzePkt(run, &packet);
  177     }
  178 }
  179 
  180 #else /* _HF_LINUX_INTEL_PT_LIB */
  181 
  182 void perf_ptInit(void) {
  183     return;
  184 }
  185 
  186 void arch_ptAnalyze(run_t* fuzzer HF_ATTR_UNUSED) {
  187     LOG_F(
  188         "The program has not been linked against the Intel's Processor Trace Library (libipt.so)");
  189 }
  190 
  191 #endif /* _HF_LINUX_INTEL_PT_LIB */