void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length, llvm::Function* llvm_func) { assert(addr); assert(functions.count(addr) == 0); functions.insert(std::make_pair(addr, FuncInfo(name, length, llvm_func))); }
FuncInfo find_func_info(const Func* func) { auto finfo = FuncInfo(func->unit(), func); auto label_num = uint32_t{0}; auto gen_label = [&] (const char* kind) { return folly::format("{}{}", kind, label_num++).str(); }; auto add_target = [&] (const char* kind, Offset off) -> std::string { auto it = finfo.labels.find(off); if (it != end(finfo.labels)) return it->second; auto const label = gen_label(kind); finfo.labels[off] = label; return label; }; auto find_jump_targets = [&] { auto it = func->unit()->at(func->base()); auto const stop = func->unit()->at(func->past()); auto const bcBase = reinterpret_cast<const Op*>(func->unit()->at(0)); for (; it != stop; it += instrLen(reinterpret_cast<const Op*>(it))) { auto const pop = reinterpret_cast<const Op*>(it); auto const off = func->unit()->offsetOf(pop); if (isSwitch(*pop)) { foreachSwitchTarget(pop, [&] (Offset off) { add_target("L", pop - bcBase + off); }); continue; } auto const target = instrJumpTarget(bcBase, off); if (target != InvalidAbsoluteOffset) { add_target("L", target); continue; } } }; auto find_eh_entries = [&] { for (auto& eh : func->ehtab()) { finfo.ehInfo[&eh] = [&]() -> EHInfo { switch (eh.m_type) { case EHEnt::Type::Catch: { auto catches = EHCatch {}; for (auto& kv : eh.m_catches) { auto const clsName = func->unit()->lookupLitstrId(kv.first); catches.blocks[clsName->data()] = add_target("C", kv.second); } return catches; } case EHEnt::Type::Fault: return EHFault { add_target("F", eh.m_fault) }; } not_reached(); }(); finfo.ehStarts.emplace_back(eh.m_base, &eh); } }; auto find_dv_entries = [&] { for (auto i = uint32_t{0}; i < func->numParams(); ++i) { auto& param = func->params()[i]; if (param.hasDefaultValue()) { add_target("DV", func->params()[i].funcletOff()); } } }; find_jump_targets(); find_eh_entries(); find_dv_entries(); return finfo; }