| 29 | using namespace binaryninja; |
| 30 | |
| 31 | dw::Function* FunctionEngine::add_function(bn::Function& func) { |
| 32 | bn::Ref<bn::Symbol> sym = func.GetSymbol(); |
| 33 | std::unique_ptr<dw::Function> dw_func = unit_.create_function(sym->GetShortName()); |
| 34 | BN_DEBUG("Adding function: {}", sym->GetShortName()); |
| 35 | std::vector<BNAddressRange> ranges = func.GetAddressRanges(); |
| 36 | if (ranges.size() == 1) { |
| 37 | dw_func->set_low_high(ranges[0].start, ranges[0].end); |
| 38 | } else { |
| 39 | std::vector<dw::Function::range_t> dw_ranges; |
| 40 | dw_ranges.reserve(ranges.size()); |
| 41 | for (const BNAddressRange& range : ranges) { |
| 42 | dw::Function::range_t dw_range{range.start, range.end}; |
| 43 | dw_ranges.push_back(dw_range); |
| 44 | } |
| 45 | dw_func->set_ranges(dw_ranges); |
| 46 | } |
| 47 | |
| 48 | if (ranges[0].start != func.GetStart()) { |
| 49 | dw_func->set_address(func.GetStart()); |
| 50 | } |
| 51 | |
| 52 | auto ret_type = func.GetReturnType(); |
| 53 | if (!ret_type->IsVoid()) { |
| 54 | dw_func->set_return_type(types_.add_type(ret_type->GetTypeName(), api_compat::get_type(ret_type))); |
| 55 | } |
| 56 | |
| 57 | std::vector<bn::FunctionParameter> parameters = func.GetType()->GetParameters(); |
| 58 | for (size_t i = 0; i < parameters.size(); ++i) { |
| 59 | const bn::FunctionParameter& p = parameters[i]; |
| 60 | std::string name = p.name.empty() ? fmt::format("arg_{}", i) : p.name; |
| 61 | dw::Type& type = types_.add_type(p.type->GetTypeName(), api_compat::get_type(p.type)); |
| 62 | dw_func->add_parameter(name, type); |
| 63 | } |
| 64 | |
| 65 | for (const auto& [addr, stack_var] : func.GetStackLayout()) { |
| 66 | for (const bn::VariableNameAndType& info : stack_var) { |
| 67 | if (!info.autoDefined) { |
| 68 | std::unique_ptr<dw::Variable> dw_var = dw_func->create_stack_variable(info.name); |
| 69 | dw_var->set_stack_offset(std::abs(addr)); |
| 70 | if (auto var_type = info.type; api_compat::as_bool(var_type)) { |
| 71 | dw::Type& dw_type = types_.add_type(var_type->GetTypeName(), api_compat::get_type(var_type)); |
| 72 | dw_var->set_type(dw_type); |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | for (const bn::Ref<bn::BasicBlock>& BB : func.GetBasicBlocks()) { |
| 79 | dw_func->add_lexical_block(BB->GetStart(), BB->GetEnd()); |
| 80 | } |
| 81 | |
| 82 | //for (uint64_t addr : func.GetCommentedAddresses()) { |
| 83 | // const std::string& comment = func.GetCommentForAddress(addr); |
| 84 | // if (!comment.empty()) { |
| 85 | // dw_func->add_label(addr, comment); |
| 86 | // } |
| 87 | //} |
| 88 |
no test coverage detected