ARMSymbolType_t StELFFile::getTypeOfSymbolAtIndex(unsigned symbolIndex)
{
    ARMSymbolType_t symType = eARMSymbol;
    const Elf32_Sym &symbol = getSymbolAtIndex(symbolIndex);

    if (m_elfVariant == eGHSVariant)
    {
        if (symbol.st_other & STO_THUMB)
            symType = eThumbSymbol;
    }
    else
    {
        unsigned mappingSymStart = 1;
        unsigned mappingSymCount = getSymbolCount() - 1; // don't include first undefined symbol
        bool mapSymsFirst = (m_header.e_flags & EF_ARM_MAPSYMSFIRST) != 0;
        if (mapSymsFirst)
        {
            // first symbol '$m' is number of mapping syms
            const Elf32_Sym &mappingSymCountSym = getSymbolAtIndex(1);
            if (getSymbolName(mappingSymCountSym) == MAPPING_SYMBOL_COUNT_TAGSYM)
            {
                mappingSymCount = mappingSymCountSym.st_value;
                mappingSymStart = 2;
            }
        }

        uint32_t lastMappingSymAddress = 0;
        unsigned mappingSymIndex = mappingSymStart;
        for (; mappingSymIndex < mappingSymCount + mappingSymStart; ++mappingSymIndex)
        {
            const Elf32_Sym &mappingSym = getSymbolAtIndex(mappingSymIndex);
            std::string mappingSymName = getSymbolName(mappingSym);
            ARMSymbolType_t nextSymType = eUnknownSymbol;

            if (mappingSymName == ARM_SEQUENCE_MAPSYM)
                symType = eARMSymbol;
            else if (mappingSymName == DATA_SEQUENCE_MAPSYM)
                symType = eDataSymbol;
            else if (mappingSymName == THUMB_SEQUENCE_MAPSYM)
                symType = eThumbSymbol;

            if (nextSymType != eUnknownSymbol)
            {
                if (symbol.st_value >= lastMappingSymAddress && symbol.st_value < mappingSym.st_value)
                    break;

                symType = nextSymType;
                lastMappingSymAddress = mappingSym.st_value;
            }
        }
    }

    return symType;
}
//! Returns STN_UNDEF if it cannot find a symbol at the given \a symbolAddress.
unsigned StELFFile::getIndexOfSymbolAtAddress(uint32_t symbolAddress, bool strict)
{
    unsigned symbolCount = getSymbolCount();
    unsigned symbolIndex = 0;
    for (; symbolIndex < symbolCount; ++symbolIndex)
    {
        const Elf32_Sym &symbol = getSymbolAtIndex(symbolIndex);

        // the GHS toolchain puts in STT_FUNC symbols marking the beginning and ending of each
        // file. if the entry point happens to be at the beginning of the file, the beginning-
        // of-file symbol will have the same value and type. fortunately, the size of these
        // symbols is 0 (or seems to be). we also ignore symbols that start with two dots just
        // in case.
        if (symbol.st_value == symbolAddress &&
            (strict && ELF32_ST_TYPE(symbol.st_info) == STT_FUNC && symbol.st_size != 0))
        {
            std::string symbolName = getSymbolName(symbol);

            // ignore symbols that start with two dots
            if (symbolName[0] == '.' && symbolName[1] == '.')
                continue;

            // found the symbol!
            return symbolIndex;
        }
    }

    return STN_UNDEF;
}
void StELFFile::dumpSymbolTable()
{
    const char *symbolTypes[5] = { "NOTYPE", "OBJECT", "FUNC", "SECTION", "FILE" };
    const char *symbolBinding[3] = { "LOCAL", "GLOBAL", "WEAK" };

    unsigned count = getSymbolCount();
    unsigned i = 0;

    for (; i < count; ++i)
    {
        const Elf32_Sym &symbol = getSymbolAtIndex(i);
        std::string name = getSymbolName(symbol);

        printf("'%s': %s, %s, 0x%08x, 0x%08x, %d. 0x%08x\n", name.c_str(), symbolTypes[ELF32_ST_TYPE(symbol.st_info)],
               symbolBinding[ELF32_ST_BIND(symbol.st_info)], symbol.st_value, symbol.st_size, symbol.st_shndx,
               symbol.st_other);
    }
}
uint32_t SymbolTable::findSymbol4Addr(uint64_t addr, Symbol** buffer, uint32_t buffCnt, char** namestr){
    uint32_t retValue = 0;

    // turns out we CANNOT use a sort-by-value scheme with a symbol table because
    // gnu hash tables require a different sorting. so we use a linear search
    for (uint32_t i = 0; i < symbols.size(); i++){
        if (symbols[i]->GET(st_value) == addr){
            if (retValue < buffCnt){
                buffer[retValue++] = symbols[i];
            }
        }
    }

    if (namestr){
        if(!retValue){
            *namestr = new char[__MAX_STRING_SIZE];
            sprintf(*namestr,"<__no_symbol_found>");
        } else {
            char* allnames = new char[__MAX_STRING_SIZE+2];
            *allnames = '\0';
            for(uint32_t i=0;i<retValue;i++){
                char* nm = getSymbolName(buffer[i]->getIndex());
                if((__MAX_STRING_SIZE-strlen(allnames)) > strlen(nm)){
                    sprintf(allnames+strlen(allnames),"%s ",nm);
                } else {
                    sprintf(allnames+strlen(allnames),"?");
                }
            }
            *namestr = allnames;
        }
    }

    return retValue;

    /*
    Symbol** sortedSymbols = new Symbol*[symbols.size()];
    for (uint32_t i = 0; i < symbols.size(); i++){
        sortedSymbols[i] = symbols[i];
    }
    qsort(sortedSymbols, symbols.size(), sizeof(Symbol*), compareSymbolValue);

    void* checkRes = bsearch(&addr,sortedSymbols,symbols.size(),sizeof(Symbol*),searchSymbolValue);

    if (checkRes){

        uint32_t sidx = (((char*)checkRes)-((char*)sortedSymbols))/sizeof(Symbol*);
        uint32_t eidx = sidx;
        for (;eidx < symbols.size();eidx++){
            Symbol* sym = sortedSymbols[eidx];
            if(sym->GET(st_value) != addr){
                break;
            }
        }
        eidx--;
        ASSERT(eidx < symbols.size() && "result of bsearch could not be verified");

        retValue = 0;
        for (;sidx<=eidx;sidx++){
            if(retValue < buffCnt){
                buffer[retValue++] = sortedSymbols[sidx];
            } else {
                break;
            }
        }
    }

    if (namestr){
        if(!retValue){
            *namestr = new char[__MAX_STRING_SIZE];
            sprintf(*namestr,"<__no_symbol_found>");
        } else {
            char* allnames = new char[__MAX_STRING_SIZE+2];
            *allnames = '\0';
            for(uint32_t i=0;i<retValue;i++){
                char* nm = getSymbolName(buffer[i]->getIndex());
                if((__MAX_STRING_SIZE-strlen(allnames)) > strlen(nm)){
                    sprintf(allnames+strlen(allnames),"%s ",nm);
                } else {
                    sprintf(allnames+strlen(allnames),"?");
                }
            }
            *namestr = allnames;
        }
    }

    return retValue;
    */
}
Пример #5
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;
  }
}