diff --git a/examples/ex_dbg.py b/examples/ex_dbg.py
new file mode 100644
index 0000000..6f2f8b9
--- /dev/null
+++ b/examples/ex_dbg.py
@@ -0,0 +1,48 @@
+#
+# Demonstrates some functions from the "dbg" class
+#
+
+import idaapi
+#from idaapi import dbg_write_memory, dbg_read_memory, dbg_get_thread_sreg_base, dbg_get_registers, dbg_get_memory_info
+
+def dump_meminfo(L):
+ # startEA, endEA, name, sclass, sbase, bitness, perm
+ for (startEA, endEA, name, sclass, sbase, bitness, perm) in L:
+ print "%x: %x name=<%s> sclass=<%s> sbase=%x bitness=%2x perm=%2x" % (startEA, endEA, name, sclass, sbase, bitness, perm)
+
+def test_getmeminfo():
+ L = idaapi.dbg_get_memory_info()
+ dump_meminfo(L)
+
+def test_getregs():
+ L = idaapi.dbg_get_registers()
+ # name flags class dtyp bit_strings bit_strings_default_mask
+ for (name, flags, cls, dtype, bit_strings, bit_strings_default_mask) in L:
+ print "name=<%s> flags=%x class=%x dtype=%x bit_strings_mask=%x" % (name, flags, cls, dtype, bit_strings_default_mask)
+ if bit_strings:
+ for s in bit_strings:
+ print " %s" % s
+
+def test_manual_regions():
+ L = idaapi.get_manual_regions()
+ if not L:
+ print "no manual regions!"
+ else:
+ dump_meminfo(L)
+
+def test_readwrite():
+ ea = cpu.Eip
+ buf = idaapi.dbg_read_memory(ea, 5)
+ print "read: ", [hex(ord(x)) for x in buf]
+ idaapi.dbg_write_memory(ea, buf)
+
+test_manual_regions()
+
+if idaapi.dbg_can_query():
+ print "%x: fs" % (idaapi.dbg_get_thread_sreg_base(idc.GetCurrentThreadId(), cpu.fs))
+ test_getmeminfo()
+ test_getregs()
+ test_readwrite()
+
+else:
+ print "run and suspend the debugger first"
\ No newline at end of file
diff --git a/swig/dbg.i b/swig/dbg.i
index 794904b..af3b948 100644
--- a/swig/dbg.i
+++ b/swig/dbg.i
@@ -5,12 +5,31 @@ typedef struct
ushort fval[6]; // 12: floating point value in the internal representation (see ieee.h)
} regval_t;
-%immutable dbg;
+%ignore dbg;
+%ignore get_manual_regions;
+%rename (get_manual_regions) py_get_manual_regions;
+%ignore set_manual_regions;
%include "dbg.hpp"
%feature("director") DBG_Hooks;
+%{
+//
+PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
+//
+%}
+
%inline %{
+
+//
+PyObject *py_get_manual_regions()
+{
+ meminfo_vec_t areas;
+ get_manual_regions(&areas);
+ return meminfo_vec_t_to_py(areas);
+}
+//
+
int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
diff --git a/swig/idd.i b/swig/idd.i
index 5fc0c11..cd1c00c 100644
--- a/swig/idd.i
+++ b/swig/idd.i
@@ -1,4 +1,6 @@
%ignore debugger_t;
+%ignore memory_info_t;
+%ignore register_info_t;
%apply unsigned char { char dtyp };
@@ -6,8 +8,166 @@
%clear(char dtyp);
+%{
+//
+#ifndef __PYDBG__
+#define __PYDBG__
+
+#ifndef PYUL_DEFINED
+#define PYUL_DEFINED
+ typedef unsigned PY_LONG_LONG pyul_t;
+#endif
+
+bool dbg_can_query()
+{
+ // Reject the request only if no debugger is set
+ // or the debugger cannot be queried while not in suspended state
+ return !(dbg == NULL || (!dbg->may_disturb() && get_process_state() != DSTATE_SUSP));
+}
+
+PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas)
+{
+ PyObject *py_list = PyList_New(areas.size());
+ meminfo_vec_t::const_iterator it, it_end(areas.end());
+ Py_ssize_t i = 0;
+ for (it=areas.begin();it!=it_end;++it, ++i)
+ {
+ const memory_info_t &mi = *it;
+ // startEA endEA name sclass sbase bitness perm
+ PyList_SetItem(py_list, i,
+ Py_BuildValue("(KKssKii)",
+ pyul_t(mi.startEA),
+ pyul_t(mi.endEA),
+ mi.name.c_str(),
+ mi.sclass.c_str(),
+ pyul_t(mi.sbase),
+ (unsigned int)(mi.bitness),
+ (unsigned int)mi.perm));
+ }
+ return py_list;
+}
+
+PyObject *dbg_get_memory_info()
+{
+ if (!dbg_can_query())
+ Py_RETURN_NONE;
+
+ // Invalidate memory
+ invalidate_dbgmem_config();
+ invalidate_dbgmem_contents(BADADDR, BADADDR);
+
+ meminfo_vec_t areas;
+ dbg->get_memory_info(areas);
+ return meminfo_vec_t_to_py(areas);
+}
+
+PyObject *dbg_get_registers()
+{
+ if (dbg == NULL)
+ Py_RETURN_NONE;
+
+ PyObject *py_list = PyList_New(dbg->registers_size);
+
+ for (int i=0;iregisters_size;i++)
+ {
+ register_info_t &ri = dbg->registers[i];
+ PyObject *py_bits;
+
+ // Does this register have bit strings?
+ if (ri.bit_strings != NULL)
+ {
+ int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4;
+ py_bits = PyList_New(nbits);
+ for (int i=0;ithread_get_sreg_base(tid, sreg_value, &answer) != 1)
+ Py_RETURN_NONE;
+ return Py_BuildValue("K", pyul_t(answer));
+}
+
+PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
+{
+ if (!dbg_can_query() || !PyNumber_Check(py_ea) || !PyNumber_Check(py_sz))
+ Py_RETURN_NONE;
+
+ ea_t ea = ea_t(PyInt_AsSsize_t(py_ea));
+ size_t sz = ea_t(PyInt_AsSsize_t(py_sz));
+
+ char *buf = new char[sz];
+ if (buf == NULL)
+ Py_RETURN_NONE;
+
+ PyObject *ret;
+ if (dbg->read_memory(ea_t(ea), buf, sz) == sz)
+ {
+ ret = PyString_FromStringAndSize(buf, sz);
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ ret = Py_None;
+ }
+ delete [] buf;
+ return ret;
+}
+
+PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
+{
+ if (!dbg_can_query() || !PyString_Check(py_buf) || !PyNumber_Check(py_ea))
+ Py_RETURN_NONE;
+
+ ea_t ea = ea_t(PyInt_AsSsize_t(py_ea));
+ size_t sz = PyString_GET_SIZE(py_buf);
+ void *buf = (void *)PyString_AS_STRING(py_buf);
+ if (dbg->write_memory(ea, buf, sz) != sz)
+ Py_RETURN_FALSE;
+ Py_RETURN_TRUE;
+}
+#endif
+//
+%}
%inline %{
+
+//
+PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf);
+PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz);
+PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value);
+PyObject *dbg_get_registers();
+PyObject *dbg_get_memory_info();
+bool dbg_can_query();
+//
+
char get_event_module_name(const debug_event_t* ev, char *buf, size_t bufsize)
{
qstrncpy(buf, ev->modinfo.name, bufsize);