Skip to content

Commit

Permalink
Added commands and Python API improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanrhu committed Oct 2, 2020
1 parent 2c0e215 commit 503cadb
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 15 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,46 @@ Specifies plugins directory.
#### `--verbose`, `-V`
Enables verbose output.

### GDB Commands
GDBFrontend's GDB commands starts with `gf-`.

#### `gf-refresh`
Refreshes all browser clients.

#### `gf-theme [theme-name]`
Switch to desired theme. For example: `gf-theme light` or `gf-theme default` for default theme.

#### `gf-list-plugins`
Lists all GDBFrontend plugins in the plugin directory.

#### `gf-load-plugin [plugin-name]`
Loads GDBFrontend plugin.

#### `gf-unload-plugin [plugin-name]`
Unloads GDBFrontend plugin.

### GDBFrontend Python API
You can access GDBFrontend's Python API via `gdbfrontend` module.

```
(gdb) python-interactive
```
```python
>>> dir(gdbfrontend)
```

For example, you can get all client sockets like this:
```python
>>> gdbfrontend.api.globalvars.dbgServer.server.connections
{1: <server.GDBFrontendSocket object at 0x...>}
```

or you can get all plugins:
```python
>>> gdbfrontend.plugin.getAll()
['hello', 'theme_light']
```

## Troubleshooting
### Zombie Processes
Sometimes GDB and gdb-frontend may not be closed correctly. In this case, you can terminate gdb-frontend shell.
Expand Down
4 changes: 4 additions & 0 deletions api/globalvars.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

lock = False
debugFlags = False
dbgServer = False

def init():
global lock
Expand All @@ -22,9 +23,12 @@ def init():
global debugFlags
debugFlags = api.flags.AtomicDebugFlags()

global dbgServer

def access(function):
global lock
global debugFlags
global dbgServer

lock.acquire()
function()
Expand Down
131 changes: 131 additions & 0 deletions commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-
#
# gdb-frontend is a easy, flexible and extensionable gui debugger
#
# https://github.com/rohanrhu/gdb-frontend
# https://oguzhaneroglu.com/projects/gdb-frontend/
#
# Licensed under GNU/GPLv3
# Copyright (C) 2019, Oğuzhan Eroğlu (https://oguzhaneroglu.com/) <[email protected]>

import sys
import importlib
import json

gdb = importlib.import_module("gdb")

import config
import plugin
import api.globalvars

class GDBFrontendLoadPluginPrefixCommand(gdb.Command):
"Loads GDBFrontend plugin."

def __init__(self):
super(GDBFrontendLoadPluginPrefixCommand, self).__init__ (
"gf-load-plugin",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
True
)

def invoke(self, plugin_name, from_tty):
if not plugin.load(plugin_name):
print("Plugin not found:", plugin_name)

GDBFrontendLoadPluginPrefixCommand()

class GDBFrontendUnloadPluginPrefixCommand(gdb.Command):
"Unloads GDBFrontend plugin."

def __init__(self):
super(GDBFrontendUnloadPluginPrefixCommand, self).__init__ (
"gf-unload-plugin",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
True
)

def invoke(self, plugin_name, from_tty):
if not plugin.unload(plugin_name):
print("Plugin is already not loaded:", plugin_name)

GDBFrontendUnloadPluginPrefixCommand()

class GDBFrontendListPluginsPrefixCommand(gdb.Command):
"Lists all GDBFrontend plugins in the plugin directory."

def __init__(self):
super(GDBFrontendListPluginsPrefixCommand, self).__init__ (
"gf-list-plugins",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
True
)

def invoke(self, args, from_tty):
for _plugin_name in plugin.getAll():
_plugin = plugin.getPlugin(_plugin_name)

sys.stdout.write(_plugin_name)
sys.stdout.write(" - ")

if _plugin:
sys.stdout.write("Enabled")
else:
sys.stdout.write("Disabled")

sys.stdout.write("\n")

GDBFrontendListPluginsPrefixCommand()

class GDBFrontendRefreshPrefixCommand(gdb.Command):
"Refreshes all browser clients."

def __init__(self):
super(GDBFrontendRefreshPrefixCommand, self).__init__ (
"gf-refresh",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
True
)

def invoke(self, arg, from_tty):
for client_id, client in api.globalvars.dbgServer.server.connections.items():
client.sendMessage(json.dumps({
"event": "refresh"
}))

GDBFrontendRefreshPrefixCommand()

class GDBFrontendThemePrefixCommand(gdb.Command):
"Switch to desired theme."

def __init__(self):
super(GDBFrontendThemePrefixCommand, self).__init__ (
"gf-theme",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
True
)

def invoke(self, theme_name, from_tty):
if not theme_name:
theme_name = "default"

if not theme_name.startswith("theme_"):
theme_name = "theme_" + theme_name

for _plugin_name in list(plugin.plugins.keys()).copy():
plugin.unload(_plugin_name)

if theme_name and theme_name != "theme_default":
if not plugin.load(theme_name):
print("Plugin not found:", theme_name)

for client_id, client in api.globalvars.dbgServer.server.connections.items():
client.sendMessage(json.dumps({
"event": "refresh"
}))

GDBFrontendThemePrefixCommand()
12 changes: 12 additions & 0 deletions frontend/components/GDBFrontend/js/GDBFrontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,18 @@
});
};

$gdbFrontend.on('GDBFrontend_debug_refresh.GDBFrontend', function (event, message) {
window.location.reload();
});

$gdbFrontend.on('GDBFrontend_debug_plugin_loaded.GDBFrontend', function (event, message) {
GDBFrontend.verbose('Plugin loaded: ', message.plugin.name);
});

$gdbFrontend.on('GDBFrontend_debug_plugin_unloaded.GDBFrontend', function (event, message) {
GDBFrontend.verbose('Plugin unloaded: ', message.plugin.name);
});

$gdbFrontend.on('GDBFrontend_debug_exited.GDBFrontend', function (event, message) {
data.debug.setExited(message);
});
Expand Down
18 changes: 10 additions & 8 deletions main.py → gdbfrontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "python-libs"))

import config

sys.path.insert(0, config.PLUGINS_DIR)

import settings
import http_server
import http_handler
Expand All @@ -25,8 +28,7 @@
import util
import urls
import api.url

sys.path.insert(0, config.PLUGINS_DIR)
import commands

gdb = importlib.import_module("gdb")

Expand All @@ -36,7 +38,7 @@
api.globalvars.init()
settings.init()
plugin.init()
plugin.load_all()
plugin.loadAll()

all_urls = urls.urls

Expand All @@ -55,12 +57,12 @@
thread.setDaemon(True)
thread.start()

dbgServer = server.GDBFrontendServer()
dbgServer.setDaemon(True)
dbgServer.start()
api.globalvars.dbgServer = server.GDBFrontendServer()
api.globalvars.dbgServer.setDaemon(True)
api.globalvars.dbgServer.start()

config.HTTP_PORT = httpServer.server_port
config.SERVER_PORT = dbgServer.server.serversocket.getsockname()[1]
config.SERVER_PORT = api.globalvars.dbgServer.server.serversocket.getsockname()[1]

if config.MMAP_PATH:
import mmap
Expand All @@ -73,4 +75,4 @@
server_port = ctypes.c_uint16.from_buffer(mmapBuff, 2)

http_port.value = httpServer.server_port
server_port.value = dbgServer.server.serversocket.getsockname()[1]
server_port.value = api.globalvars.dbgServer.server.serversocket.getsockname()[1]
47 changes: 42 additions & 5 deletions plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,24 @@
urls.py
hello.py
Plugins those are inside plugins directory will be loaded automatically.
Plugins that are inside plugins directory will be loaded automatically.
Plugin Name Format:
On File System: hello
Plugin Backend Class: HelloPlugin
On File System: hello, hello_world
Plugin Backend Class: HelloPlugin, HelloWorldPlugin
Theme Plugin Name Format:
On File System: theme_light, night_blue
Plugin Backend Class: ThemeLightPlugin, ThemeNightBluePlugin
"""

import os
import importlib
import json

import config
import util
import api.globalvars

def webFSPath(plugin_name, path):
return os.path.join(config.PLUGINS_DIR, plugin_name, "frontend", path)
Expand All @@ -48,6 +54,9 @@ def init():

plugins = {}

def getAll():
return os.listdir(config.PLUGINS_DIR)

def getPlugin(plugin_name):
global plugins

Expand All @@ -60,6 +69,10 @@ def load(plugin_name):
global plugins

plugin_location = os.path.join(config.PLUGINS_DIR, plugin_name)

if not os.path.exists(plugin_location):
return False

module_path = os.path.join(plugin_location, plugin_name)+".py"
config_path = os.path.join(plugin_location, "config")+".py"
urls_path = os.path.join(plugin_location, "urls")+".py"
Expand Down Expand Up @@ -90,21 +103,45 @@ def load(plugin_name):

plugins[plugin_name] = plugin

for client_id, client in api.globalvars.dbgServer.server.connections.items():
client.sendMessage(json.dumps({
"event": "plugin_loaded",
"plugin": {
"name": plugin_name
}
}))

plugin.loaded()

util.verbose("Plugin loaded:", plugin_name)

return True

def unload(plugin_name):
global plugins

plugin = plugins[plugin_name]
try:
plugin = plugins[plugin_name]
except KeyError:
return False

del plugins[plugin_name]

for client_id, client in api.globalvars.dbgServer.server.connections.items():
client.sendMessage(json.dumps({
"event": "plugin_unloaded",
"plugin": {
"name": plugin_name
}
}))

plugin.unloaded()

util.verbose("Plugin unloaded:", plugin_name)

def load_all():
return True

def loadAll():
global plugins

plugin_dirs = config.plugin_order
Expand Down
4 changes: 2 additions & 2 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def argHandler_version():
" -f tmux.conf new-session -s " + terminal_id +
" -d '" + gdb_executable +
" -ex \"python import sys, os; sys.path.insert(0, \\\""+path+"\\\"); import config, json, base64; config.init(); " +
"config.setJSON(base64.b64decode(\\\""+base64.b64encode(json.dumps(arg_config).encode()).decode()+"\\\").decode()); import main\"; read;'"
"config.setJSON(base64.b64decode(\\\""+base64.b64encode(json.dumps(arg_config).encode()).decode()+"\\\").decode()); import gdbfrontend\"; read;'"
)
else:
os.system(
Expand Down Expand Up @@ -303,7 +303,7 @@ def argHandler_version():
" \"" +
gdb_executable +
" -ex \\\"python import sys, os; sys.path.insert(0, '"+path+"'); import config, json, base64; config.init(); " +
"config.setJSON(base64.b64decode('"+base64.b64encode(json.dumps(arg_config).encode()).decode()+"').decode()); import main\\\"; read;"
"config.setJSON(base64.b64decode('"+base64.b64encode(json.dumps(arg_config).encode()).decode()+"').decode()); import gdbfrontend\\\"; read;"
"\" "
)
os.system(
Expand Down

0 comments on commit 503cadb

Please sign in to comment.