mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
Backported fixes
This commit is contained in:
+18
-9
@@ -151,10 +151,10 @@ static bool find_libpython_dt_needed_info(
|
||||
//-------------------------------------------------------------------------
|
||||
static bool patch_dt_needed(
|
||||
const char *path,
|
||||
const qstring &replacement,
|
||||
const qstring &_replacement,
|
||||
qstring *errbuf)
|
||||
{
|
||||
out_verb("Setting relevant DT_NEEDED of \"%s\" to \"%s\"\n", path, replacement.c_str());
|
||||
out_verb("Setting relevant DT_NEEDED of \"%s\" to \"%s\"\n", path, _replacement.c_str());
|
||||
out_ident_inc_t iinc;
|
||||
linput_t *linput = open_linput(path, /*remote=*/ false);
|
||||
if ( linput == nullptr )
|
||||
@@ -214,13 +214,24 @@ static bool patch_dt_needed(
|
||||
room = qltell(reader.get_linput()) - dt_needed_off - 1;
|
||||
}
|
||||
|
||||
const size_t nbytes = replacement.length();
|
||||
bytevec_t replacement;
|
||||
replacement.append(_replacement.c_str(), _replacement.length() + 1);
|
||||
size_t nbytes = replacement.size();
|
||||
out_verb("We have room for %" FMT_Z " bytes, and need to write %" FMT_Z "\n",
|
||||
room, nbytes);
|
||||
|
||||
// and patch
|
||||
if ( room >= nbytes )
|
||||
{
|
||||
if ( room > nbytes )
|
||||
{
|
||||
out_verb("Expanding replacement with %" FMT_Z " '\\0' bytes, to "
|
||||
"override possible previous soname that could derail "
|
||||
"later computation of available room.\n", room - nbytes);
|
||||
replacement.resize(room, 0);
|
||||
nbytes = replacement.size();
|
||||
}
|
||||
|
||||
FILE *fp = openM(path);
|
||||
if ( fp != nullptr )
|
||||
{
|
||||
@@ -230,7 +241,7 @@ static bool patch_dt_needed(
|
||||
if ( !args.dry_run )
|
||||
{
|
||||
// we want to write the zero as well!
|
||||
if ( qfwrite(fp, replacement.c_str(), nbytes+1) == nbytes+1 )
|
||||
if ( qfwrite(fp, replacement.begin(), nbytes) == nbytes )
|
||||
{
|
||||
out_verb("File \"%s\" successfully patched\n", path);
|
||||
}
|
||||
@@ -243,7 +254,7 @@ static bool patch_dt_needed(
|
||||
else
|
||||
{
|
||||
out("Would write %" FMT_Z " bytes (\"%s\") to file\n",
|
||||
nbytes, replacement.c_str());
|
||||
nbytes, replacement.begin());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -263,7 +274,7 @@ static bool patch_dt_needed(
|
||||
errbuf->sprnt("Replacement \"%s\" has a length of %" FMT_Z
|
||||
" bytes, but there is only room for %" FMT_Z ""
|
||||
" bytes in the file. Cannot proceed.\n",
|
||||
replacement.c_str(), nbytes, room);
|
||||
replacement.begin(), nbytes, room);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -460,9 +471,7 @@ static bool split_debug_expand_libpython3_dtneeded_room(
|
||||
out_verb("\"%s\" command successful. Restoring the "
|
||||
"original DT_NEEDED of \"%s\"\n",
|
||||
cmdline.c_str(), dt_needed);
|
||||
qstring padded_dt_needed(dt_needed);
|
||||
padded_dt_needed.resize(SLOT_SIZE, '\0');
|
||||
if ( !patch_dt_needed(path, padded_dt_needed, errbuf) )
|
||||
if ( !patch_dt_needed(path, dt_needed, errbuf) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
+8
-3
@@ -167,14 +167,19 @@ static bool has_appx_path(qstrvec_t paths)
|
||||
if ( appx_path.empty() )
|
||||
{
|
||||
HKEY hkey;
|
||||
bool ok = false;
|
||||
if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Appx", 0, KEY_READ, &hkey) == ERROR_SUCCESS )
|
||||
{
|
||||
if ( !read_string(&appx_path, hkey, L"PackageRoot") )
|
||||
appx_path = "<none>";
|
||||
ok = read_string(&appx_path, hkey, L"PackageRoot");
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
if ( !ok )
|
||||
{
|
||||
// no Appx support, set to dummy value which doesn't occur in paths
|
||||
appx_path = "<none>";
|
||||
}
|
||||
}
|
||||
for ( auto path : paths )
|
||||
for ( const qstring &path : paths )
|
||||
if ( path.find(appx_path) != qstring::npos )
|
||||
return true;
|
||||
|
||||
|
||||
+32
-7
@@ -254,6 +254,9 @@ void ida_export idapython_hide_wait_box()
|
||||
#define LEXEC(...)
|
||||
#endif
|
||||
|
||||
#define AVERAGE_STEPS_COUNT 10
|
||||
#define MAX_STEPS_COUNT ((AVERAGE_STEPS_COUNT * 2) + 1)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void execution_t::reset_steps()
|
||||
{
|
||||
@@ -268,7 +271,7 @@ void execution_t::reset_steps()
|
||||
// If we never hit the 'trace' callback while in the 'while True' loop
|
||||
// but always when performing the call to the processor module's 'out/outop'
|
||||
// then the loop will never stop. That was happening on windows (optimized.)
|
||||
steps_before_action = 1 + rand() % 20;
|
||||
steps_before_action = 1 + rand() % (AVERAGE_STEPS_COUNT*2);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -300,6 +303,7 @@ void execution_t::stop_tracking()
|
||||
void execution_t::sync_to_present_time()
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
LEXEC("execution_t (%p)::sync_to_present_time() now=%d\n", this, int(now));
|
||||
for ( size_t i = 0, n = entries.size(); i < n; ++i )
|
||||
entries[i].etime = now;
|
||||
maybe_hide_wait_box();
|
||||
@@ -342,16 +346,38 @@ void execution_t::reset_current_start_time()
|
||||
//------------------------------------------------------------------------
|
||||
int execution_t::on_trace(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)
|
||||
{
|
||||
LEXEC("on_trace() (steps=%d, nentries=%d)\n",
|
||||
#ifdef TESTABLE_BUILD
|
||||
// ensure there was no decrement overflow
|
||||
QASSERT(0, execution.steps_before_action <= MAX_STEPS_COUNT);
|
||||
#endif
|
||||
LEXEC("on_trace() (steps_before_action=%u, entries.size()=%d, timeout=%d)\n",
|
||||
int(execution.steps_before_action),
|
||||
int(execution.entries.size()));
|
||||
// we don't want to query for time at every trace event
|
||||
if ( execution.steps_before_action-- > 0 )
|
||||
int(execution.entries.size()),
|
||||
execution.timeout);
|
||||
if ( execution.timeout < 0 )
|
||||
{
|
||||
LEXEC("on_trace()::no timeout currently set (%d).\n", execution.timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// we don't want to query for time at every trace event
|
||||
if ( execution.steps_before_action > 0 )
|
||||
{
|
||||
--execution.steps_before_action;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( get_active_modal_widget() != NULL )
|
||||
{
|
||||
LEXEC("on_trace()::a modal widget is active. Not showing our 'interrupt dialog'.\n");
|
||||
|
||||
// in addition, we want to sync the "start time" to now, so that
|
||||
// the timeout will be relative to that (otherwise, calling
|
||||
// ask_file() might end up showing the waitdialog for a fraction
|
||||
// of a second after `_ida_kernwin.ask_file()` returns, but before
|
||||
// the `ida_kernwin.ask_file()` one does.)
|
||||
execution.sync_to_present_time();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -377,8 +403,7 @@ int execution_t::on_trace(PyObject *obj, PyFrameObject *frame, int what, PyObjec
|
||||
{
|
||||
if ( PyErr_Occurred() == NULL )
|
||||
{
|
||||
LEXEC("on_trace()::INTERRUPTING (setting 'User interrupted' exception) at line %d\n",
|
||||
PyFrame_GetLineNumber(frame));
|
||||
LEXEC("on_trace()::INTERRUPTING (setting 'User interrupted' exception)\n");
|
||||
PyErr_SetString(PyExc_KeyboardInterrupt, "User interrupted");
|
||||
}
|
||||
return -1;
|
||||
|
||||
Binary file not shown.
+6
-18
@@ -444,8 +444,7 @@ def save_database(idbname, flags=0):
|
||||
if len(idbname) == 0:
|
||||
idbname = get_idb_path()
|
||||
mask = ida_loader.DBFL_KILL | ida_loader.DBFL_COMP | ida_loader.DBFL_BAK
|
||||
res = ida_loader.save_database_ex(idbname, flags & mask)
|
||||
return res
|
||||
return ida_loader.save_database(idbname, flags & mask)
|
||||
|
||||
DBFL_BAK = ida_loader.DBFL_BAK # for compatiblity with older versions, eventually delete this
|
||||
|
||||
@@ -509,14 +508,14 @@ def delete_all_segments():
|
||||
ida_name.del_global_name(ea)
|
||||
func = ida_funcs.get_func(ea)
|
||||
if func:
|
||||
ida_funcs.del_func_cmt(func, False)
|
||||
ida_funcs.del_func_cmt(func, True)
|
||||
ida_funcs.set_func_cmt(func, "", False)
|
||||
ida_funcs.set_func_cmt(func, "", True)
|
||||
ida_funcs.del_func(ea)
|
||||
ida_bytes.del_hidden_range(ea)
|
||||
seg = ida_segment.getseg(ea)
|
||||
if seg:
|
||||
ida_segment.del_segment_cmt(seg, False)
|
||||
ida_segment.del_segment_cmt(seg, True)
|
||||
ida_segment.set_segment_cmt(seg, "", False)
|
||||
ida_segment.set_segment_cmt(seg, "", True)
|
||||
ida_segment.del_segm(ea, ida_segment.SEGMOD_KEEP | ida_segment.SEGMOD_SILENT)
|
||||
|
||||
ea = ida_bytes.next_head(ea, ida_ida.cvar.inf.max_ea)
|
||||
@@ -1007,18 +1006,7 @@ def op_offset_high16(ea, n, target):
|
||||
|
||||
|
||||
def MakeVar(ea):
|
||||
"""
|
||||
Mark the location as "variable"
|
||||
|
||||
@param ea: address to mark
|
||||
|
||||
@return: None
|
||||
|
||||
@note: All that IDA does is to mark the location as "variable".
|
||||
Nothing else, no additional analysis is performed.
|
||||
This function may disappear in the future.
|
||||
"""
|
||||
ida_bytes.doVar(ea, 1)
|
||||
pass
|
||||
|
||||
# Every anterior/posterior line has its number.
|
||||
# Anterior lines have numbers from E_PREV
|
||||
|
||||
+18
-12
@@ -358,6 +358,12 @@ static int get_pyidc_cvt_type(PyObject *py_var)
|
||||
return int(IDAPyIntOrLong_AsLong(attr.o));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static inline bool is_pyidc_cvt_type_int64(PyObject *py_var)
|
||||
{
|
||||
return get_pyidc_cvt_type(py_var) == PY_ICID_INT64;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Utility function to convert a python object to an IDC object
|
||||
// and sets a python exception on failure.
|
||||
@@ -736,15 +742,9 @@ int ida_export pyvar_to_idcvar(
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline PyObject *cvt_to_pylong(int32 v)
|
||||
{
|
||||
return PyLong_FromLong(v);
|
||||
}
|
||||
|
||||
inline PyObject *cvt_to_pylong(int64 v)
|
||||
{
|
||||
return PyLong_FromLongLong(v);
|
||||
}
|
||||
// helpers to use with idc_value_t::num (which can be 32-, or 64-bit.)
|
||||
inline PyObject *cvt_to_pylong(int32 v) { return PyLong_FromLong(v); }
|
||||
inline PyObject *cvt_to_pylong(int64 v) { return PyLong_FromLongLong(v); }
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Converts an IDC variable to a Python variable
|
||||
@@ -786,8 +786,7 @@ int ida_export idcvar_to_pyvar(
|
||||
if ( *py_var != NULL )
|
||||
{
|
||||
// Recycling an int64 object?
|
||||
int t = get_pyidc_cvt_type(py_var->o);
|
||||
if ( t != PY_ICID_INT64 )
|
||||
if ( !is_pyidc_cvt_type_int64(py_var->o) )
|
||||
return CIP_IMMUTABLE; // Cannot recycle immutable object
|
||||
// Update the attribute
|
||||
PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64));
|
||||
@@ -818,7 +817,14 @@ int ida_export idcvar_to_pyvar(
|
||||
case VT_LONG:
|
||||
// Cannot recycle immutable objects
|
||||
if ( *py_var != NULL )
|
||||
return CIP_IMMUTABLE;
|
||||
{
|
||||
// Recycling an int64 object?
|
||||
if ( !is_pyidc_cvt_type_int64(py_var->o) )
|
||||
return CIP_IMMUTABLE;
|
||||
// Update the attribute
|
||||
PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, cvt_to_pylong(idc_var.num));
|
||||
return CIP_OK;
|
||||
}
|
||||
*py_var = newref_t(cvt_to_pylong(idc_var.num));
|
||||
break;
|
||||
case VT_FLOAT:
|
||||
|
||||
+3
-1
@@ -842,7 +842,9 @@ protected:
|
||||
{
|
||||
// identifier
|
||||
{
|
||||
ref_t py_id = newref_t(PyObject_GetAttrString(self, "id"));
|
||||
ref_t py_id;
|
||||
if ( PyObject_HasAttrString(self, "id") )
|
||||
py_id = newref_t(PyObject_GetAttrString(self, "id"));
|
||||
if ( py_id == NULL || !IDAPyStr_Check(py_id.o) )
|
||||
py_id = newref_t(PyObject_Repr(self));
|
||||
if ( py_id != NULL && IDAPyStr_Check(py_id.o) )
|
||||
|
||||
@@ -126,6 +126,15 @@ class quick_widget_commands_t:
|
||||
cmd.icon)
|
||||
attach_dynamic_action_to_popup(widget, popup, desc)
|
||||
|
||||
class disabled_script_timeout_t(object):
|
||||
def __enter__(self):
|
||||
import _ida_idaapi
|
||||
self.was_timeout = _ida_idaapi.set_script_timeout(0)
|
||||
|
||||
def __exit__(self, type, value, tb):
|
||||
import _ida_idaapi
|
||||
_ida_idaapi.set_script_timeout(self.was_timeout)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# bw-compat/deprecated. You shouldn't rely on this in new code
|
||||
from ida_pro import str2user
|
||||
|
||||
@@ -1384,15 +1384,12 @@ except:
|
||||
|
||||
def __call_form_callable(call, *args):
|
||||
assert(len(args))
|
||||
old = _ida_idaapi.set_script_timeout(0)
|
||||
try:
|
||||
with disabled_script_timeout_t():
|
||||
if sys.version_info.major >= 3 and isinstance(args[0], str):
|
||||
largs = list(args)
|
||||
largs[0] = largs[0].encode("UTF-8")
|
||||
args = tuple(largs)
|
||||
r = call(*args)
|
||||
finally:
|
||||
_ida_idaapi.set_script_timeout(old)
|
||||
return r
|
||||
|
||||
def ask_form(*args):
|
||||
|
||||
@@ -205,9 +205,8 @@ class Choose(object):
|
||||
self.flags |= Choose.CH_MODAL
|
||||
|
||||
# Disable the timeout
|
||||
old = _ida_idaapi.set_script_timeout(0)
|
||||
n = _ida_kernwin.choose_choose(self)
|
||||
_ida_idaapi.set_script_timeout(old)
|
||||
with disabled_script_timeout_t():
|
||||
n = _ida_kernwin.choose_choose(self)
|
||||
|
||||
# Delete the modal chooser instance
|
||||
self.Close()
|
||||
|
||||
@@ -46114,6 +46114,24 @@ detach_action_from_toolbar(*args)
|
||||
@param name: the action name (C++: const char *)
|
||||
@return: success
|
||||
|
||||
Help on class disabled_script_timeout_t in module ida_kernwin:
|
||||
|
||||
class disabled_script_timeout_t(__builtin__.object)
|
||||
| Methods defined here:
|
||||
|
|
||||
| __enter__(self)
|
||||
|
|
||||
| __exit__(self, type, value, tb)
|
||||
|
|
||||
| ----------------------------------------------------------------------
|
||||
| Data descriptors defined here:
|
||||
|
|
||||
| __dict__
|
||||
| dictionary for instance variables (if defined)
|
||||
|
|
||||
| __weakref__
|
||||
| list of weak references to the object (if defined)
|
||||
|
||||
Help on class disasm_line_t in module ida_kernwin:
|
||||
|
||||
class disasm_line_t(__builtin__.object)
|
||||
@@ -73313,15 +73331,6 @@ LoadFile(filepath, pos, ea, size)
|
||||
Help on function MakeVar in module idc:
|
||||
|
||||
MakeVar(ea)
|
||||
Mark the location as "variable"
|
||||
|
||||
@param ea: address to mark
|
||||
|
||||
@return: None
|
||||
|
||||
@note: All that IDA does is to mark the location as "variable".
|
||||
Nothing else, no additional analysis is performed.
|
||||
This function may disappear in the future.
|
||||
|
||||
Help on function SaveFile in module idc:
|
||||
|
||||
|
||||
@@ -46249,6 +46249,24 @@ detach_action_from_toolbar(*args) -> 'bool'
|
||||
@param name: the action name (C++: const char *)
|
||||
@return: success
|
||||
|
||||
Help on class disabled_script_timeout_t in module ida_kernwin:
|
||||
|
||||
class disabled_script_timeout_t(builtins.object)
|
||||
| Methods defined here:
|
||||
|
|
||||
| __enter__(self)
|
||||
|
|
||||
| __exit__(self, type, value, tb)
|
||||
|
|
||||
| ----------------------------------------------------------------------
|
||||
| Data descriptors defined here:
|
||||
|
|
||||
| __dict__
|
||||
| dictionary for instance variables (if defined)
|
||||
|
|
||||
| __weakref__
|
||||
| list of weak references to the object (if defined)
|
||||
|
||||
Help on class disasm_line_t in module ida_kernwin:
|
||||
|
||||
class disasm_line_t(builtins.object)
|
||||
@@ -73351,15 +73369,6 @@ LoadFile(filepath, pos, ea, size)
|
||||
Help on function MakeVar in module idc:
|
||||
|
||||
MakeVar(ea)
|
||||
Mark the location as "variable"
|
||||
|
||||
@param ea: address to mark
|
||||
|
||||
@return: None
|
||||
|
||||
@note: All that IDA does is to mark the location as "variable".
|
||||
Nothing else, no additional analysis is performed.
|
||||
This function may disappear in the future.
|
||||
|
||||
Help on function SaveFile in module idc:
|
||||
|
||||
|
||||
+6
-6
@@ -42,12 +42,12 @@ extern plugin_t PLUGIN;
|
||||
%ignore ask_text;
|
||||
%ignore vwarning;
|
||||
// Note: don't do that for ask_form(), since that calls back into Python.
|
||||
%thread ask_addr;
|
||||
%thread ask_seg;
|
||||
%thread ask_long;
|
||||
%thread ask_yn;
|
||||
%thread ask_buttons;
|
||||
%thread ask_file;
|
||||
%modal_dialog_triggering_function(ask_addr);
|
||||
%modal_dialog_triggering_function(ask_seg);
|
||||
%modal_dialog_triggering_function(ask_long);
|
||||
%modal_dialog_triggering_function(ask_yn);
|
||||
%modal_dialog_triggering_function(ask_buttons);
|
||||
%modal_dialog_triggering_function(ask_file);
|
||||
|
||||
%ignore simpleline_t::simpleline_t(const qstring &);
|
||||
|
||||
|
||||
@@ -1681,6 +1681,21 @@ SWIGINTERN bool __chkreqidb()
|
||||
|
||||
%}
|
||||
|
||||
%define %modal_dialog_triggering_function(NAME)
|
||||
%thread NAME;
|
||||
%pythonprepend NAME
|
||||
%{
|
||||
import ida_kernwin
|
||||
# kludge: we can't use %feature("shadow") for top-level
|
||||
# functions (see https://github.com/swig/swig/issues/980)
|
||||
# Thus we'll %pythonprepend some code, and return from it,
|
||||
# making the original code unreachable. Not pretty, but I
|
||||
# don't have anything better at the moment.
|
||||
with ida_kernwin.disabled_script_timeout_t():
|
||||
return _ida_kernwin.NAME(*args)
|
||||
%}
|
||||
%enddef
|
||||
|
||||
%include <constraints.i>
|
||||
|
||||
// If the module is 'pro', don't import pro.h, or the %include
|
||||
|
||||
Reference in New Issue
Block a user