예제 #1
0
파일: init.cpp 프로젝트: aulwes/Byfl
  // Initialize the BytesFlops pass.
  bool BytesFlops::doInitialization(Module& module) {
    // Inject external declarations to various variables defined in byfl.c.
    LLVMContext& globctx = module.getContext();
    IntegerType* i64type = Type::getInt64Ty(globctx);
    PointerType* i64ptrtype = Type::getInt64PtrTy(globctx);
      
    mem_insts_var      = declare_global_var(module, i64ptrtype, "bf_mem_insts_count", true);
    inst_mix_histo_var = declare_global_var(module, i64ptrtype, "bf_inst_mix_histo", true);
    terminator_var     = declare_global_var(module, i64ptrtype, "bf_terminator_count", true);
    mem_intrinsics_var = declare_global_var(module, i64ptrtype, "bf_mem_intrin_count", true);
    load_var       = declare_global_var(module, i64type, "bf_load_count");
    store_var      = declare_global_var(module, i64type, "bf_store_count");
    load_inst_var  = declare_global_var(module, i64type, "bf_load_ins_count");
    store_inst_var = declare_global_var(module, i64type, "bf_store_ins_count");
    flop_var       = declare_global_var(module, i64type, "bf_flop_count");
    fp_bits_var    = declare_global_var(module, i64type, "bf_fp_bits_count");

    op_var         = declare_global_var(module, i64type, "bf_op_count");
    op_bits_var    = declare_global_var(module, i64type, "bf_op_bits_count");

    // Assign a few constant values.
    not_end_of_bb = ConstantInt::get(globctx, APInt(32, 0));
    uncond_end_bb = ConstantInt::get(globctx, APInt(32, 1));
    cond_end_bb = ConstantInt::get(globctx, APInt(32, 2));
    zero = ConstantInt::get(globctx, APInt(64, 0));
    one = ConstantInt::get(globctx, APInt(64, 1));

    // Construct a set of functions to instrument and a set of
    // functions not to instrument.
    instrument_only = parse_function_names(IncludedFunctions);
    dont_instrument = parse_function_names(ExcludedFunctions);
    if (instrument_only && dont_instrument)
      report_fatal_error("-bf-include and -bf-exclude are mutually exclusive");

    // Assign a value to bf_bb_merge.
    create_global_constant(module, "bf_bb_merge", uint64_t(BBMergeCount));

    // Assign a value to bf_every_bb.
    create_global_constant(module, "bf_every_bb", bool(InstrumentEveryBB));

    // Assign a value to bf_types.
    create_global_constant(module, "bf_types", bool(TallyTypes));

    // Assign a value to bf_tally_inst_mix (instruction mix).
    create_global_constant(module, "bf_tally_inst_mix", bool(TallyInstMix));

    // Assign a value to bf_per_func.
    create_global_constant(module, "bf_per_func", bool(TallyByFunction));

    // Assign a value to bf_call_stack.
    if (TrackCallStack && !TallyByFunction)
      report_fatal_error("-bf-call-stack is allowed only in conjuction with -bf-by-func");
    create_global_constant(module, "bf_call_stack", bool(TrackCallStack));

    // Assign a value to bf_unique_bytes.
    create_global_constant(module, "bf_unique_bytes", bool(TrackUniqueBytes));

    // Assign a value to bf_mem_footprint.
    create_global_constant(module, "bf_mem_footprint", bool(FindMemFootprint));

    // Assign a value to bf_vectors.
    create_global_constant(module, "bf_vectors", bool(TallyVectors));

    // Assign a value to bf_max_reuse_dist.
    create_global_constant(module, "bf_max_reuse_distance", uint64_t(MaxReuseDist));

    // Create a global string that stores all of our command-line options.
    ifstream cmdline("/proc/self/cmdline");   // Full command line passed to opt
    string bf_cmdline("[failed to read /proc/self/cmdline]");  // Reconstructed command line with -bf-* options only
    if (cmdline.is_open()) {
      // Read the command line into a buffer.
      const size_t maxcmdlinelen = 65536;
      char cmdline_chars[maxcmdlinelen] = {0};
      cmdline.read(cmdline_chars, maxcmdlinelen);
      cmdline.close();

      // Parse the command line.  Each argument is terminated by a
      // null character, and the command line as a whole is terminated
      // by two null characters.
      if (!cmdline.bad()) {
        char* arg = cmdline_chars;
        bf_cmdline = "";
        while (1) {
          size_t arglen = strlen(arg);
          if (arglen == 0)
            break;
          if (!strncmp(arg, "-bf", 3)) {
            bf_cmdline += ' ';
            bf_cmdline += arg;
          }
          arg += arglen + 1;
        }
      }
    }
    const char *bf_cmdline_str = bf_cmdline.c_str();
    if (bf_cmdline_str[0] == ' ')
      bf_cmdline_str++;
    bf_cmdline_str = strdup(bf_cmdline_str);
    create_global_constant(module, "bf_option_string", bf_cmdline_str);

    /**
     * Instead of using a map with the function names as keys, we associate a unique
     * integer with each function and use that as the key.  We maintain the association
     * of the function names to their integer keys at compile time, then create a
     * constructor to record the map via a call to bf_record_funcs2keys.
     */
    vector<Type*> func_arg;
    func_arg.push_back(IntegerType::get(globctx, 8*sizeof(uint32_t)));
    func_arg.push_back(PointerType::get(IntegerType::get(globctx, 8*sizeof(uint64_t)),0));

    PointerType* char_ptr = PointerType::get(IntegerType::get(globctx, 8), 0);
    PointerType* char_ptr_ptr = PointerType::get(char_ptr, 0);
    func_arg.push_back(char_ptr_ptr);

    FunctionType* void_int_func_result =
            FunctionType::get(Type::getVoidTy(globctx), func_arg, false);

    record_funcs2keys = declare_extern_c(void_int_func_result,
                   "bf_record_funcs2keys",
                   &module);

    // Inject external declarations for
    // bf_initialize_if_necessary(), bf_push_basic_block(), and
    // bf_pop_basic_block().
    init_if_necessary = declare_thunk(&module, "bf_initialize_if_necessary");
    push_bb = declare_thunk(&module, "bf_push_basic_block");
    pop_bb = declare_thunk(&module, "bf_pop_basic_block");

    // Inject external declarations for bf_accumulate_bb_tallies(),
    // bf_reset_bb_tallies(), and bf_report_bb_tallies().
    if (InstrumentEveryBB) {
      accum_bb_tallies = declare_thunk(&module, "bf_accumulate_bb_tallies");
      reset_bb_tallies = declare_thunk(&module, "bf_reset_bb_tallies");
      report_bb_tallies = declare_thunk(&module, "bf_report_bb_tallies");
    }

    // Inject an external declarations for bf_increment_func_tally().
    assoc_counts_with_func = 0;
    tally_function = 0;
    push_function = 0;
    pop_function = 0;

    if (TallyByFunction) {
        // bf_assoc_counters_with_func
        vector<Type*> func_arg;

        // arg: key ID
        func_arg.push_back(IntegerType::get(globctx, 8*sizeof(FunctionKeyGen::KeyID)));
        FunctionType* void_func_result =
          FunctionType::get(Type::getVoidTy(globctx), func_arg, false);
        assoc_counts_with_func =
          declare_extern_c(void_func_result,
                           "bf_assoc_counters_with_func",
                           &module);

        vector<Type*> taly_func_arg;
        taly_func_arg.push_back(PointerType::get(IntegerType::get(globctx, 8), 0));
        // add 2nd arg for function key
        taly_func_arg.push_back(IntegerType::get(globctx, 8*sizeof(FunctionKeyGen::KeyID)));
        FunctionType* void_str_int_func_result =
                  FunctionType::get(Type::getVoidTy(globctx), taly_func_arg, false);

      tally_function =
        declare_extern_c(void_func_result,
                         "bf_incr_func_tally",
                         &module);

      if ( TrackCallStack )
      {
          // Inject external declarations for bf_push_function() and
          // bf_pop_function().
          // bf_push_function()
          push_function =
                  declare_extern_c(void_str_int_func_result,
                                   "bf_push_function",
                                   &module);
          // bf_pop_function()
          pop_function = declare_thunk(&module, "bf_pop_function");
      }
    }

    // Declare bf_tally_vector_operation() only if we were asked
    // to track vector operations.
    if (TallyVectors) {
      vector<Type*> all_function_args;
      all_function_args.push_back(PointerType::get(IntegerType::get(globctx, 8), 0));
      all_function_args.push_back(IntegerType::get(globctx, 64));
      all_function_args.push_back(IntegerType::get(globctx, 64));
      all_function_args.push_back(IntegerType::get(globctx, 8));
      FunctionType* void_func_result =
        FunctionType::get(Type::getVoidTy(globctx), all_function_args, false);
      tally_vector =
        declare_extern_c(void_func_result,
                         "bf_tally_vector_operation",
                         &module);
    }

    // Inject external declarations for bf_assoc_addresses_with_prog()
    // and bf_assoc_addresses_with_func().
    if (TrackUniqueBytes) {
      // Declare bf_assoc_addresses_with_prog() any time we need to
      // track unique bytes.
      vector<Type*> all_function_args;
      all_function_args.push_back(IntegerType::get(globctx, 64));
      all_function_args.push_back(IntegerType::get(globctx, 64));
      FunctionType* void_func_result =
        FunctionType::get(Type::getVoidTy(globctx), all_function_args, false);
      assoc_addrs_with_prog =
        declare_extern_c(void_func_result,
			 FindMemFootprint
			 ? "bf_assoc_addresses_with_prog_tb"
                         : "bf_assoc_addresses_with_prog",
                         &module);

      // Declare bf_assoc_addresses_with_func() only if we were
      // asked to track unique addresses by function.
      if (TallyByFunction) {
        vector<Type*> all_function_args;
        all_function_args.push_back(PointerType::get(IntegerType::get(globctx, 8), 0));
        all_function_args.push_back(IntegerType::get(globctx, 64));
        all_function_args.push_back(IntegerType::get(globctx, 64));
        FunctionType* void_func_result =
          FunctionType::get(Type::getVoidTy(globctx), all_function_args, false);
        assoc_addrs_with_func =
          declare_extern_c(void_func_result,
			   FindMemFootprint
			   ? "bf_assoc_addresses_with_func_tb"
			   : "bf_assoc_addresses_with_func",
                           &module);
      }
    }

    // Inject an external declaration for llvm.memset.p0i8.i64().
    memset_intrinsic = module.getFunction("llvm.memset.p0i8.i64");
    if (memset_intrinsic == NULL) {
      vector<Type*> all_function_args;
      all_function_args.push_back(PointerType::get(IntegerType::get(globctx, 8), 0));
      all_function_args.push_back(IntegerType::get(globctx, 8));
      all_function_args.push_back(IntegerType::get(globctx, 64));
      all_function_args.push_back(IntegerType::get(globctx, 32));
      all_function_args.push_back(IntegerType::get(globctx, 1));
      FunctionType* void_func_result =
        FunctionType::get(Type::getVoidTy(globctx), all_function_args, false);
      memset_intrinsic =
        declare_extern_c(void_func_result,
                         "llvm.memset.p0i8.i64",
                         &module);
    }

    // Simplify ReuseDist.getBits() into rd_bits.
    rd_bits = ReuseDist.getBits();
    if ((rd_bits&(1<<RD_BOTH)) != 0)
      rd_bits = (1<<RD_LOADS) | (1<<RD_STORES);

    // Inject external declarations for bf_reuse_dist_addrs_prog().
    if (rd_bits > 0) {
      vector<Type*> all_function_args;
      all_function_args.push_back(IntegerType::get(globctx, 64));
      all_function_args.push_back(IntegerType::get(globctx, 64));
      FunctionType* void_func_result =
        FunctionType::get(Type::getVoidTy(globctx), all_function_args, false);
      reuse_dist_prog =
        declare_extern_c(void_func_result,
                         "bf_reuse_dist_addrs_prog",
                         &module);
    }

    // Inject external declarations for bf_acquire_mega_lock() and
    // bf_release_mega_lock().
    if (ThreadSafety) {
      take_mega_lock = declare_thunk(&module, "bf_acquire_mega_lock");
      release_mega_lock = declare_thunk(&module, "bf_release_mega_lock");
    }

    // initialize the function key generator
    FunctionKeyGen::Seed_t  seed;
    std::hash<std::string> hash_key;
    seed = hash_key(module.getModuleIdentifier());

    m_keygen = std::unique_ptr<FunctionKeyGen>(new FunctionKeyGen(seed));


    return true;
  }
예제 #2
0
ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
  OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
  if (!obj)
    report_fatal_error("Unable to create object image from memory buffer!");

  Arch = (Triple::ArchType)obj->getArch();

  // Symbols found in this object
  StringMap<SymbolLoc> LocalSymbols;
  // Used sections from the object file
  ObjSectionToIDMap LocalSections;

  // Common symbols requiring allocation, with their sizes and alignments
  CommonSymbolMap CommonSymbols;
  // Maximum required total memory to allocate all common symbols
  uint64_t CommonSize = 0;

  error_code err;
  // Parse symbols
  DEBUG(dbgs() << "Parse symbols:\n");
  for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols();
       i != e; i.increment(err)) {
    Check(err);
    object::SymbolRef::Type SymType;
    StringRef Name;
    Check(i->getType(SymType));
    Check(i->getName(Name));

    uint32_t flags;
    Check(i->getFlags(flags));

    bool isCommon = flags & SymbolRef::SF_Common;
    if (isCommon) {
      // Add the common symbols to a list.  We'll allocate them all below.
      uint32_t Align;
      Check(i->getAlignment(Align));
      uint64_t Size = 0;
      Check(i->getSize(Size));
      CommonSize += Size + Align;
      CommonSymbols[*i] = CommonSymbolInfo(Size, Align);
    } else {
      if (SymType == object::SymbolRef::ST_Function ||
          SymType == object::SymbolRef::ST_Data ||
          SymType == object::SymbolRef::ST_Unknown) {
        uint64_t FileOffset;
        StringRef SectionData;
        bool IsCode;
        section_iterator si = obj->end_sections();
        Check(i->getFileOffset(FileOffset));
        Check(i->getSection(si));
        if (si == obj->end_sections()) continue;
        Check(si->getContents(SectionData));
        Check(si->isText(IsCode));
        const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() +
                                (uintptr_t)FileOffset;
        uintptr_t SectOffset = (uintptr_t)(SymPtr -
                                           (const uint8_t*)SectionData.begin());
        unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections);
        LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
        DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset)
                     << " flags: " << flags
                     << " SID: " << SectionID
                     << " Offset: " << format("%p", SectOffset));
        GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
      }
    }
    DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n");
  }

  // Allocate common symbols
  if (CommonSize != 0)
    emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols);

  // Parse and process relocations
  DEBUG(dbgs() << "Parse relocations:\n");
  for (section_iterator si = obj->begin_sections(),
       se = obj->end_sections(); si != se; si.increment(err)) {
    Check(err);
    bool isFirstRelocation = true;
    unsigned SectionID = 0;
    StubMap Stubs;

    for (relocation_iterator i = si->begin_relocations(),
         e = si->end_relocations(); i != e; i.increment(err)) {
      Check(err);

      // If it's the first relocation in this section, find its SectionID
      if (isFirstRelocation) {
        SectionID = findOrEmitSection(*obj, *si, true, LocalSections);
        DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
        isFirstRelocation = false;
      }

      processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols,
			   Stubs);
    }
  }

  return obj.take();
}
예제 #3
0
파일: ELFDump.cpp 프로젝트: jvesely/llvm
template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
  outs() << "Program Header:\n";
  auto ProgramHeaderOrError = o->program_headers();
  if (!ProgramHeaderOrError)
    report_fatal_error(toString(ProgramHeaderOrError.takeError()));
  for (const typename ELFT::Phdr &Phdr : *ProgramHeaderOrError) {
    switch (Phdr.p_type) {
    case ELF::PT_DYNAMIC:
      outs() << " DYNAMIC ";
      break;
    case ELF::PT_GNU_EH_FRAME:
      outs() << "EH_FRAME ";
      break;
    case ELF::PT_GNU_RELRO:
      outs() << "   RELRO ";
      break;
    case ELF::PT_GNU_STACK:
      outs() << "   STACK ";
      break;
    case ELF::PT_INTERP:
      outs() << "  INTERP ";
      break;
    case ELF::PT_LOAD:
      outs() << "    LOAD ";
      break;
    case ELF::PT_NOTE:
      outs() << "    NOTE ";
      break;
    case ELF::PT_OPENBSD_BOOTDATA:
      outs() << "    OPENBSD_BOOTDATA ";
      break;
    case ELF::PT_OPENBSD_RANDOMIZE:
      outs() << "    OPENBSD_RANDOMIZE ";
      break;
    case ELF::PT_OPENBSD_WXNEEDED:
      outs() << "    OPENBSD_WXNEEDED ";
      break;
    case ELF::PT_PHDR:
      outs() << "    PHDR ";
      break;
    case ELF::PT_TLS:
      outs() << "    TLS ";
      break;
    default:
      outs() << " UNKNOWN ";
    }

    const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " ";

    outs() << "off    " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr "
           << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr "
           << format(Fmt, (uint64_t)Phdr.p_paddr)
           << format("align 2**%u\n",
                     countTrailingZeros<uint64_t>(Phdr.p_align))
           << "         filesz " << format(Fmt, (uint64_t)Phdr.p_filesz)
           << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags "
           << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-")
           << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-")
           << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n";
  }
  outs() << "\n";
}
예제 #4
0
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
                                      const SectionRef &Section,
                                      bool IsCode) {

  unsigned StubBufSize = 0,
           StubSize = getMaxStubSize();
  error_code err;
  if (StubSize > 0) {
    for (relocation_iterator i = Section.begin_relocations(),
         e = Section.end_relocations(); i != e; i.increment(err), Check(err))
      StubBufSize += StubSize;
  }
  StringRef data;
  uint64_t Alignment64;
  Check(Section.getContents(data));
  Check(Section.getAlignment(Alignment64));

  unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
  bool IsRequired;
  bool IsVirtual;
  bool IsZeroInit;
  bool IsReadOnly;
  uint64_t DataSize;
  StringRef Name;
  Check(Section.isRequiredForExecution(IsRequired));
  Check(Section.isVirtual(IsVirtual));
  Check(Section.isZeroInit(IsZeroInit));
  Check(Section.isReadOnlyData(IsReadOnly));
  Check(Section.getSize(DataSize));
  Check(Section.getName(Name));
  if (StubSize > 0) {
    unsigned StubAlignment = getStubAlignment();
    unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
    if (StubAlignment > EndAlignment)
      StubBufSize += StubAlignment - EndAlignment;
  }

  unsigned Allocate;
  unsigned SectionID = Sections.size();
  uint8_t *Addr;
  const char *pData = 0;

  // Some sections, such as debug info, don't need to be loaded for execution.
  // Leave those where they are.
  if (IsRequired) {
    Allocate = DataSize + StubBufSize;
    Addr = IsCode
      ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID)
      : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly);
    if (!Addr)
      report_fatal_error("Unable to allocate section memory!");

    // Virtual sections have no data in the object image, so leave pData = 0
    if (!IsVirtual)
      pData = data.data();

    // Zero-initialize or copy the data from the image
    if (IsZeroInit || IsVirtual)
      memset(Addr, 0, DataSize);
    else
      memcpy(Addr, pData, DataSize);

    DEBUG(dbgs() << "emitSection SectionID: " << SectionID
                 << " Name: " << Name
                 << " obj addr: " << format("%p", pData)
                 << " new addr: " << format("%p", Addr)
                 << " DataSize: " << DataSize
                 << " StubBufSize: " << StubBufSize
                 << " Allocate: " << Allocate
                 << "\n");
    Obj.updateSectionAddress(Section, (uint64_t)Addr);
  }
  else {
    // Even if we didn't load the section, we need to record an entry for it
    // to handle later processing (and by 'handle' I mean don't do anything
    // with these sections).
    Allocate = 0;
    Addr = 0;
    DEBUG(dbgs() << "emitSection SectionID: " << SectionID
                 << " Name: " << Name
                 << " obj addr: " << format("%p", data.data())
                 << " new addr: 0"
                 << " DataSize: " << DataSize
                 << " StubBufSize: " << StubBufSize
                 << " Allocate: " << Allocate
                 << "\n");
  }

  Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
  return SectionID;
}