static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data ) { //get the storage typedef converter::rvalue_from_python_storage< multi_array_t > storage_t; storage_t * the_storage = reinterpret_cast< storage_t * >( data ); void * memory_chunk = the_storage->storage.bytes; //new (memory_chunk) multi_array_t(obj); //new placement object py_obj( handle<>( borrowed( obj ) ) ); shape_t shape; get_shape( py_obj, shape ); multi_array_t * a = new (memory_chunk) multi_array_t( shape ); //extract each element from numpy array and put in c array index i( a->num_dimensions(), 0 ); do { boost::python::list numpy_index; for( unsigned dim = 0; a->num_dimensions() != dim; ++dim ) { numpy_index.append( i[ dim ] ); } (*a)(i) = extract<typename multi_array_t::element>(py_obj[ boost::python::tuple( numpy_index ) ]); } while( increment_index( i, *a ) ); data->convertible = memory_chunk; }
//------------------------------------------------------------------------- //<code(py_idp)> //------------------------------------------------------------------------- int idaapi IDP_Callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; IDP_Hooks *proxy = (IDP_Hooks *)ud; int ret = 0; try { switch ( notification_code ) { case processor_t::custom_ana: ret = proxy->custom_ana() ? 1 + cmd.size : 0; break; case processor_t::custom_out: ret = proxy->custom_out() ? 2 : 0; break; case processor_t::custom_emu: ret = proxy->custom_emu() ? 2 : 0; break; case processor_t::custom_outop: { op_t *op = va_arg(va, op_t *); ref_t py_obj(create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op)); if ( py_obj == NULL ) break; ret = proxy->custom_outop(py_obj.o) ? 2 : 0; break; } case processor_t::custom_mnem: { PYW_GIL_CHECK_LOCKED_SCOPE(); PyObject *py_ret = proxy->custom_mnem(); if ( py_ret != NULL && PyString_Check(py_ret) ) { char *outbuffer = va_arg(va, char *); size_t bufsize = va_arg(va, size_t); qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize); ret = 2; } else { ret = 0; } Py_XDECREF(py_ret); break; } case processor_t::is_sane_insn: { int no_crefs = va_arg(va, int); ret = proxy->is_sane_insn(no_crefs); break; } case processor_t::may_be_func: { int state = va_arg(va, int); ret = proxy->may_be_func(state); break; } case processor_t::closebase: { proxy->closebase(); break; } case processor_t::savebase: { proxy->savebase(); break; } case processor_t::auto_empty_finally: { proxy->auto_empty_finally(); break; } case processor_t::rename: { ea_t ea = va_arg(va, ea_t); const char *new_name = va_arg(va, const char *); ret = proxy->rename(ea, new_name); break; } case processor_t::renamed: { ea_t ea = va_arg(va, ea_t); const char *new_name = va_arg(va, const char *); bool local_name = va_argi(va, bool); proxy->renamed(ea, new_name, local_name); break; } case processor_t::undefine: { ea_t ea = va_arg(va, ea_t); ret = proxy->undefine(ea); break; } case processor_t::make_code: { ea_t ea = va_arg(va, ea_t); asize_t size = va_arg(va, asize_t); ret = proxy->make_code(ea, size); break; } case processor_t::make_data: { ea_t ea = va_arg(va, ea_t); flags_t flags = va_arg(va, flags_t); tid_t tid = va_arg(va, tid_t); asize_t len = va_arg(va, asize_t); ret = proxy->make_data(ea, flags, tid, len); break; } case processor_t::load_idasgn: { const char *short_sig_name = va_arg(va, const char *); proxy->load_idasgn(short_sig_name); break; } case processor_t::auto_empty: { proxy->auto_empty(); break; } case processor_t::auto_queue_empty: { atype_t type = va_arg(va, atype_t); ret = proxy->auto_queue_empty(type); break; } case processor_t::add_func: { func_t *func = va_arg(va, func_t *); proxy->add_func(func); break; } case processor_t::del_func: { func_t *func = va_arg(va, func_t *); ret = proxy->del_func(func); break; } case processor_t::is_call_insn: { ea_t ea = va_arg(va, ea_t); ret = proxy->is_call_insn(ea); break; } case processor_t::is_ret_insn: { ea_t ea = va_arg(va, ea_t); bool strict = va_argi(va, bool); ret = proxy->is_ret_insn(ea, strict); break; } case processor_t::assemble: { ea_t ea = va_arg(va, ea_t); ea_t cs = va_arg(va, ea_t); ea_t ip = va_arg(va, ea_t); bool use32 = va_argi(va, bool); const char *line = va_arg(va, const char *); // Extract user buffer (we hardcode the MAXSTR size limit) uchar *bin = va_arg(va, uchar *); // Call python PYW_GIL_CHECK_LOCKED_SCOPE(); PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line); if ( py_buffer != NULL && PyString_Check(py_buffer) ) { char *s; Py_ssize_t len; if ( PyString_AsStringAndSize(py_buffer, &s, &len) != -1 ) { if ( len > MAXSTR ) len = MAXSTR; memcpy(bin, s, len); ret = len; } } // ret = 0 otherwise Py_XDECREF(py_buffer); break; } // validate_flirt_func, // flirt has recognized a library function // // this callback can be used by a plugin or proc module // // to intercept it and validate such a function // // args: ea_t start_ea // // const char *funcname // // returns: -1-do not create a function, // // 1-function is validated // // the idp module is allowed to modify 'cmd' // set_func_start, // Function chunk start address will be changed // // args: func_t *pfn // // ea_t new_start // // Returns: 1-ok,<=0-do not change // set_func_end, // Function chunk end address will be changed // // args: func_t *pfn // // ea_t new_end // // Returns: 1-ok,<=0-do not change // outlabel, // The kernel is going to generate an instruction // // label line or a function header // // args: // // ea_t ea - // // const char *colored_name - // // If returns value <=0, then the kernel should // // not generate the label // may_show_sreg, // The kernel wants to display the segment registers // // in the messages window. // // arg - ea_t current_ea // // if this function returns 0 // // then the kernel will not show // // the segment registers. // // (assuming that the module have done it) // coagulate, // Try to define some unexplored bytes // // This notification will be called if the // // kernel tried all possibilities and could // // not find anything more useful than to // // convert to array of bytes. // // The module can help the kernel and convert // // the bytes into something more useful. // // arg: // // ea_t start_ea // // returns: number of converted bytes + 1 // auto_empty, // Info: all analysis queues are empty // // args: none // // returns: none // // This callback is called once when the // // initial analysis is finished. If the queue is // // not empty upon the return from this callback, // // it will be called later again. // // See also auto_empty_finally. // auto_queue_empty, // One analysis queue is empty // // args: atype_t type // // returns: 1-yes, keep the queue empty // // <=0-no, the queue is not empty anymore // // This callback can be called many times, so // // only the autoMark() functions can be used from it // // (other functions may work but it is not tested) // func_bounds, // find_func_bounds() finished its work // // The module may fine tune the function bounds // // args: int *possible_return_code // // func_t *pfn // // ea_t max_func_end_ea (from the kernel's point of view) // // returns: none // is_jump_func, // is the function a trivial "jump" function? // // args: func_t *pfn // // ea_t *jump_target // // ea_t *func_pointer // // returns: 0-no, 1-don't know, 2-yes, see jump_target // // and func_pointer // gen_regvar_def, // generate register variable definition line // // args: regvar_t *v // // returns: 0-ok // setsgr, // The kernel has changed a segment register value // // args: ea_t startEA // // ea_t endEA // // int regnum // // sel_t value // // sel_t old_value // // uchar tag (SR_... values) // // returns: 1-ok, 0-error // set_compiler, // The kernel has changed the compiler information // // (inf.cc structure) // is_basic_block_end, // Is the current instruction end of a basic block? // // This function should be defined for processors // // with delayed jump slots. The current instruction // // is stored in 'cmd' // // args: bool call_insn_stops_block // // returns: 1-unknown, 0-no, 2-yes // reglink, // IBM PC only, ignore it // get_vxd_name, // IBM PC only, ignore it // // Get Vxd function name // // args: int vxdnum // // int funcnum // // char *outbuf // // returns: nothing // // // moving_segm, // May the kernel move the segment? // // args: segment_t - segment to move // // ea_t to - new segment start address // // returns: 1-yes, <=0-the kernel should stop // move_segm, // A segment is moved // // Fix processor dependent address sensitive information // // args: ea_t from - old segment address // // segment_t* - moved segment // // returns: nothing // // // get_stkvar_scale_factor,// Should stack variable references be multiplied by // // a coefficient before being used in the stack frame? // // Currently used by TMS320C55 because the references into // // the stack should be multiplied by 2 // // Returns: scaling factor // // Note: PR_SCALE_STKVARS should be set to use this callback // // create_flat_group, // Create special segment representing the flat group // // (to use for PC mainly) // // args - ea_t image_base, int bitness, sel_t dataseg_sel // // kernel_config_loaded, // This callback is called when ida.cfg is parsed // // args - none, returns - nothing // // might_change_sp, // Does the instruction at 'ea' modify the stack pointer? // // args: ea_t ea // // returns: 1-yes, 0-false // // (not used yet) // // is_alloca_probe, // Does the function at 'ea' behave as __alloca_probe? // // args: ea_t ea // // returns: 2-yes, 1-false // // out_3byte, // Generate text representation of 3byte data // // init_out_buffer() is called before this function // // and all Out... function can be used. // // uFlag contains the flags. // // This callback might be implemented by the processor // // module to generate custom representation of 3byte data. // // args: // // ea_t dataea - address of the data item // // uint32 value - value to output // // bool analyze_only - only create xrefs if necessary // // do not generate text representation // // returns: 2-yes, 1-false // // get_reg_name, // Generate text representation of a register // // int reg - internal register number as defined in the processor module // // size_t width - register width in bytes // // char *buf - output buffer // // size_t bufsize - size of output buffer // // int reghi - if not -1 then this function will return the register pair // // returns: -1 if error, strlen(buf)+2 otherwise // // Most processor modules do not need to implement this callback // // It is useful only if ph.regNames[reg] does not provide // // the correct register names // // save its local data // out_src_file_lnnum, // Callback: generate analog of // // #line "file.c" 123 // // directive. // // const char *file - source file (may be NULL) // // size_t lnnum - line number // // returns: 2-directive has been generated // get_autocmt, // Callback: get dynamic auto comment // // Will be called if the autocomments are enabled // // and the comment retrieved from ida.int starts with // // '$!'. 'cmd' is contains valid info. // // char *buf - output buffer // // size_t bufsize - output buffer size // // returns: 2-new comment has been generated // // 1-callback has not been handled // // the buffer must not be changed in this case // is_insn_table_jump, // Callback: determine if instruction is a table jump or call // // If CF_JUMP bit can not describe all kinds of table // // jumps, please define this callback. // // It will be called for insns with CF_JUMP bit set. // // input: cmd structure contains the current instruction // // returns: 1-yes, 0-no // auto_empty_finally, // Info: all analysis queues are empty definitively // // args: none // // returns: none // // This callback is called only once. // // See also auto_empty. // loader_finished, // Event: external file loader finished its work // // linput_t *li // // uint16 neflags // // const char *filetypename // // Use this event to augment the existing loader functionality // loader_elf_machine, // Event: ELF loader machine type checkpoint // // linput_t *li // // int machine_type // // const char **p_procname // // proc_def **p_pd (see ldr\elf.h) // // set_elf_reloc_t *set_reloc // // A plugin check the machine_type. If it is the desired one, // // the the plugin fills p_procname with the processor name. // // p_pd is used to handle relocations, otherwise can be left untouched // // set_reloc can be later used by the plugin to specify relocations // // returns: e_machine value (if it is different from the // // original e_machine value, procname and p_pd will be ignored // // and the new value will be used) // // This event occurs for each loaded ELF file // is_indirect_jump, // Callback: determine if instruction is an indrect jump // // If CF_JUMP bit can not describe all jump types // // jumps, please define this callback. // // input: cmd structure contains the current instruction // // returns: 1-use CF_JUMP, 2-no, 3-yes // verify_noreturn, // The kernel wants to set 'noreturn' flags for a function // // func_t *pfn // // Returns: 1-ok, any other value-do not set 'noreturn' flag // verify_sp, // All function instructions have been analyzed // // Now the processor module can analyze the stack pointer // // for the whole function // // input: func_t *pfn // // Returns: 1-ok, 0-bad stack pointer // treat_hindering_item, // An item hinders creation of another item // // args: ea_t hindering_item_ea // // flags_t new_item_flags (0 for code) // // ea_t new_item_ea // // asize_t new_item_length // // Returns: 1-no reaction, <=0-the kernel may delete the hindering item // str2reg, // Convert a register name to a register number // // args: const char *regname // // Returns: register number + 2 // // The register number is the register index in the regNames array // // Most processor modules do not need to implement this callback // // It is useful only if ph.regNames[reg] does not provide // // the correct register names // create_switch_xrefs, // Create xrefs for a custom jump table // // in: ea_t jumpea; - address of the jump insn // // switch_info_ex_t *; - switch information // // returns: must return 2 // calc_switch_cases, // Calculate case values and targets for a custom jump table // // in: ea_t insn_ea - address of the 'indirect jump' instruction // // switch_info_ex_t *si - switch information // // casevec_t *casevec - vector of case values... // // evec_t *targets - ...and corresponding target addresses // // casevec and targets may be NULL // // returns: 2-ok, 1-failed // determined_main, // The main() function has been determined // // in: ea_t main - address of the main() function // // returns: none // preprocess_chart, // gui has retrieved a function flow chart // // in: qflow_chart_t *fc // // returns: none // // Plugins may modify the flow chart in this callback // get_bg_color, // Get item background color // // in: ea_t ea, bgcolor_t *color // // Returns: 1-not implemented, 2-color set // // Plugins can hook this callback to color disassembly lines // // dynamically // get_operand_string, // Request text string for operand (cli, java, ...) // // args: int opnum // // char *buf // // size_t buflen // // (cmd structure must contain info for the desired insn) // // opnum is the operand number; -1 means any string operand // // returns: 1 - no string (or empty string) // // >1 - original string length with terminating zero // // // the following 5 events are very low level // // take care of possible recursion // add_cref, // a code reference is being created // // args: ea_t from, ea_t to, cref_t type // // returns: <0 - cancel cref creation // add_dref, // a data reference is being created // // args: ea_t from, ea_t to, dref_t type // // returns: <0 - cancel dref creation // del_cref, // a code reference is being deleted // // args: ea_t from, ea_t to, bool expand // // returns: <0 - cancel cref deletion // del_dref, // a data reference is being deleted // // args: ea_t from, ea_t to // // returns: <0 - cancel dref deletion // coagulate_dref, // data reference is being analyzed // // args: ea_t from, ea_t to, bool may_define, ea_t *code_ea // // plugin may correct code_ea (e.g. for thumb mode refs, we clear the last bit) // // returns: <0 - cancel dref analysis // custom_fixup, // mutipurpose notification for FIXUP_CUSTOM // // args: cust_fix oper, ea_t ea, const fixup_data_t*, ... (see cust_fix) // // returns: 1 - no accepted (fixup ignored by ida) // // >1 - accepted (see cust_fix) // off_preproc, // called from get_offset_expr, when refinfo_t // // contain flag REFINFO_PREPROC. Normally this // // notification used in a combination with custom_fixup // // args: ea_t ea, int numop, ea_t* opval, const refinfo_t* ri, // // char* buf, size_t bufsize, ea_t* target, // // ea_t* fullvalue, ea_t from, int getn_flags // // returns: 2 - buf filled as simple expression // // 3 - buf filled as complex expression // // 4 - apply standard processing (with - possible - changed values) // // others - can't convert to offset expression // // set_proc_options, // called if the user specified an option string in the command line: // // -p<processor name>:<options> // // can be used for e.g. setting a processor subtype // // also called if option string is passed to set_processor_type() // // and IDC's SetProcessorType() // // args: const char * options // // returns: <0 - bad option string // }