Exemple #1
0
void printTopTrans() {
    if (!nTopTrans) return;

    // The summary currently includes all translations, so it's misleading
    // if we're filtering a specific kind of translations or address range.
    if (kindFilter == "all" && minAddr == 0 && maxAddr == (TCA)-1) {
        transPerfEvents.printEventsSummary(sortBy,
                                           "TransId",
                                           nTopTrans,
                                           verboseStats,
                                           helpersMinPercentage);
    }

    // Sort and print the top translations.
    std::vector<TransID> transIds;

    for (TransID t = 0; t < NTRANS; t++) {
        if (TREC(t)->isValid() &&
                (kindFilter == "all" || kindFilter == show(TREC(t)->kind).c_str()) &&
                ((minAddr <= TREC(t)->aStart     && TREC(t)->aStart      <= maxAddr) ||
                 (minAddr <= TREC(t)->acoldStart && TREC(t)->acoldStart <= maxAddr))) {
            transIds.push_back(t);
        }
    }

    CompTrans compTrans(transPerfEvents, sortBy);
    sort(transIds.begin(), transIds.end(), compTrans);

    size_t nPrint = nTopTrans;
    if (transIds.size() < nTopTrans) {
        fprintf(stderr, "Warning: too few translations selected (%lu)\n",
                transIds.size());
        nPrint = transIds.size();
    }
    for (size_t i = 0; i < nPrint; i++) printTrans(transIds[i]);
}
Exemple #2
0
void loadPerfEvents() {
    FILE* profFile;

    profFile = fopen(profFileName.c_str(), "rt");

    if (!profFile) {
        error("Error opening file " + profFileName);
    }

    char   program[MAX_SYM_LEN];
    char   eventCaption[MAX_SYM_LEN];
    char   line[2*MAX_SYM_LEN];
    TCA    addr;
    uint32_t tcSamples[NUM_EVENT_TYPES];
    uint32_t hhvmSamples[NUM_EVENT_TYPES];
    size_t numEntries = 0;
    PerfEventType eventType = NUM_EVENT_TYPES;
    // samplesPerKind[event][kind]
    uint32_t samplesPerKind[NUM_EVENT_TYPES][NumTransKinds];
    uint32_t samplesPerTCRegion[NUM_EVENT_TYPES][TCRCount];

    memset(tcSamples  , 0, sizeof(tcSamples));
    memset(hhvmSamples, 0, sizeof(hhvmSamples));
    memset(samplesPerKind, 0, sizeof(samplesPerKind));
    memset(samplesPerTCRegion, 0, sizeof(samplesPerTCRegion));

    while (fgets(line, 2*MAX_SYM_LEN, profFile) != nullptr) {
        always_assert(sscanf(line, "%s %s %lu", program, eventCaption, &numEntries)
                      == 3);
        always_assert(numEntries);

        std::vector<std::pair<TCA,std::string>> entries;

        for (size_t i = 0; i < numEntries; i++) {
            fscanf(profFile, "%p %s\n", &addr, line);
            entries.push_back(std::pair<TCA,std::string>(addr, line));
        }

        if (strncmp(program, "hhvm", 4) == 0) {
            eventType = perfScriptOutputToEventType(eventCaption);
            if (eventType == NUM_EVENT_TYPES) {
                snprintf(errMsgBuff,
                         MAX_SYM_LEN,
                         "loadProfData: invalid event caption '%s'",
                         eventCaption);
                error(errMsgBuff);
            }

            hhvmSamples[eventType]++;

            size_t selIdx = 0;
            addr = entries[0].first;

            if (inclusiveStats) {
                for (size_t i = 0; i < entries.size(); i++) {
                    if (g_transData->isAddrInSomeTrans(entries[i].first)) {
                        addr = entries[i].first;
                        selIdx = i;
                        break;
                    }
                }
            }

            if (!(minAddr <= addr && addr <= maxAddr)) continue;
            if (!g_transData->isAddrInSomeTrans(addr)) continue;
            TransID transId = g_transData->getTransContaining(addr);
            always_assert(transId != INVALID_ID);
            tcSamples[eventType]++;

            const TransRec* trec = g_transData->getTransRec(transId);
            TransKind kind = trec->kind;
            samplesPerKind[eventType][static_cast<uint32_t>(kind)]++;
            TCRegion region = transCode->findTCRegionContaining(addr);
            always_assert(region != TCRCount);
            samplesPerTCRegion[eventType][region]++;

            std::vector<std::string> stackTrace;
            if (verboseStats) {
                for (size_t i = 0; i < selIdx; i++) {

                    if (!strcmp(entries[i].second.c_str(), "[unknown]")) {

                        // Append the address to disambiguate.
                        entries[i].second += std::string("@")
                                             +  toString((void*)entries[i].first);
                    }

                    stackTrace.push_back(entries[i].second);
                }
                reverse(stackTrace.begin(), stackTrace.end());
            }

            if (selIdx) addr--;
            tcaPerfEvents.addEvent(addr, (PerfEvent) {
                eventType, 1
            }, stackTrace);
        }
    }

    AddrToTransMapper transMapper(g_transData);
    transPerfEvents = tcaPerfEvents.mapTo(transMapper);

    printf("# Number of hhvm samples read (%% in TC) from file %s\n",
           profFileName.c_str());

    for (size_t i = 0; i < NUM_EVENT_TYPES; i++) {
        if (!hhvmSamples[i]) continue;

        printf("#  %-19s TOTAL: %10u (%u in TC = %5.2lf%%)\n",
               eventTypeToCommandLineArgument((PerfEventType)i),
               hhvmSamples[i],
               tcSamples[i],
               100.0 * tcSamples[i] / hhvmSamples[i]);

        for (size_t j = 0; j < NumTransKinds; ++j) {
            auto ct = samplesPerKind[i][j];
            if (!ct) continue;
            std::string kind = show(static_cast<TransKind>(j));
            printf("# %26s:             %-8u (%5.2lf%%)\n",
                   kind.c_str(), ct, 100.0 * ct / tcSamples[i]);
        }
        printf("#\n");
    }
    printf("\n");

    // print per-TCRegion information

    // header
    printf("# TCRegion ");
    for (size_t i = 0; i < NUM_EVENT_TYPES; i++) {
        printf("%17s ", eventTypeToCommandLineArgument((PerfEventType)i));
    }
    printf("\n");

    // HW events for each region
    for (size_t i = 0 ; i < TCRCount ; i++) {
        printf("# %8s ", tcRegionToString(static_cast<TCRegion>(i)).c_str());
        for (size_t j = 0; j < NUM_EVENT_TYPES; j++) {
            auto ct = samplesPerTCRegion[j][i];
            printf("%8u (%5.2lf%%) ", ct, ct ? (100.0 * ct / tcSamples[j]) : 0);
        }
        printf("\n");
    }
    printf("#\n\n");

    fclose(profFile);
}
Exemple #3
0
 bool operator()(TransID t1, TransID t2) const {
     return transPerfEvents.getEventCount(t1, etype) >
            transPerfEvents.getEventCount(t2, etype);
 }
Exemple #4
0
void OfflineX86Code::disasm(FILE* file,
                            TCA   fileStartAddr,
                            TCA   codeStartAddr,
                            uint64_t codeLen,
                            const PerfEventsMap<TCA>& perfEvents,
                            BCMappingInfo bcMappingInfo,
                            bool printAddr /* =true */,
                            bool printBinary /* =false */) {

  char codeStr[MAX_INSTR_ASM_LEN];
  xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen);
  xed_uint8_t* frontier;
  TCA          ip;
  TCA          r10val = 0;
  size_t       currBC = 0;

  if (codeLen == 0) return;

  auto const offset = codeStartAddr - fileStartAddr;
  if (fseek(file, offset, SEEK_SET)) {
    error("disasm error: seeking file");
  }

  size_t readLen = fread(code, codeLen, 1, file);
  if (readLen != 1) {
    error("Failed to read {} bytes at offset {} from code file due to {}",
          codeLen, offset, feof(file) ? "EOF" : "read error");
  }

  xed_decoded_inst_t xedd;

  // Decode and print each instruction
  for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) {

    xed_decoded_inst_zero_set_mode(&xedd, &xed_state);
    xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID);
    xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15);

    if (xed_error != XED_ERROR_NONE) break;

    // Get disassembled instruction in codeStr
    if (!xed_format_context(xed_syntax, &xedd, codeStr,
                            MAX_INSTR_ASM_LEN, (uint64_t)ip, nullptr
#if XED_ENCODE_ORDER_MAX_ENTRIES != 28 // Newer version of XED library
                            , 0
#endif
                           )) {
      error("disasm error: xed_format_context failed");
    }

    // Annotate the x86 with its bytecode.
    currBC = printBCMapping(bcMappingInfo, currBC, (TCA)ip);

    if (printAddr) printf("%14p: ", ip);

    uint32_t instrLen = xed_decoded_inst_get_length(&xedd);

    if (printBinary) {
      uint32_t i;
      for (i=0; i < instrLen; i++) {
        printf("%02X", frontier[i]);
      }
      for (; i < 16; i++) {
        printf("  ");
      }
    }

    // For calls, we try to figure out the destination symbol name.
    // We look both at relative branches and the pattern:
    //    move r10, IMMEDIATE
    //    call r10
    xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd);
    string callDest = "";

    if (iclass == XED_ICLASS_CALL_NEAR || iclass == XED_ICLASS_CALL_FAR) {
      const xed_inst_t    *xi       = xed_decoded_inst_inst(&xedd);
      always_assert(xed_inst_noperands(xi) >= 1);
      const xed_operand_t *opnd     = xed_inst_operand(xi, 0);
      xed_operand_enum_t   opndName = xed_operand_name(opnd);

      if (opndName == XED_OPERAND_RELBR) {
        if (xed_decoded_inst_get_branch_displacement_width(&xedd)) {
          xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd);
          TCA         addr = ip + instrLen + disp;
          callDest = getSymbolName(addr);
        }
      } else if (opndName == XED_OPERAND_REG0) {
        if (xed_decoded_inst_get_reg(&xedd, opndName) == XED_REG_R10) {
          callDest = getSymbolName(r10val);
        }
      }
    } else if (iclass == XED_ICLASS_MOV) {
      // Look for moves into r10 and keep r10val updated
      const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);

      always_assert(xed_inst_noperands(xi) >= 2);

      const xed_operand_t *destOpnd     = xed_inst_operand(xi, 0);
      xed_operand_enum_t   destOpndName = xed_operand_name(destOpnd);

      if (destOpndName == XED_OPERAND_REG0 &&
          xed_decoded_inst_get_reg(&xedd, destOpndName) == XED_REG_R10) {
        const xed_operand_t *srcOpnd     = xed_inst_operand(xi, 1);
        xed_operand_enum_t   srcOpndName = xed_operand_name(srcOpnd);
        if (srcOpndName == XED_OPERAND_IMM0) {
          TCA addr = (TCA)xed_decoded_inst_get_unsigned_immediate(&xedd);
          r10val = addr;
        }
      }
    }

    if (!perfEvents.empty()) {
      printEventStats((TCA)ip, instrLen, perfEvents);
    } else {
      printf("%48s", "");
    }
    printf("%s%s\n", codeStr, callDest.c_str());

    frontier += instrLen;
    ip       += instrLen;
  }
}