Skip to content

Commit d912c25

Browse files
author
Chad Smith
authored
merge various updates to master (cs01#137)
* make modal into react; move more from pug to react/js * cleanup modal and settings * convert everything to react; parse executable+args with spaces (cs01#116) * add gzip compression to flask * add gzip; rename index.js to build.js * everything in a single div id * add javascript unit tests * add button to toggle assembly flavors (cs01#110); refresh state when clicking return button
1 parent 5538984 commit d912c25

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1793
-762
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
## dev
44
Changes that are in master but have not yet been pushed to PyPI.
55

6+
## 0.9.0.0
7+
* Compress responses from server (massive bandwidth improvement)
8+
* Add button to toggle assembly flavors (issue #110)
9+
* Parse executable+args with spaces (issue #116)
10+
* Turn modals into components
11+
* Move everything into a single root React component
12+
* Refresh state when clicking "return" button
13+
* Add javascript unit tests
14+
615
## 0.8.2.0
716
* Add optional authentication (@nickamon, issue #132)
817
* Support the `--args` flag (issue #126)

README.rst

+15-40
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A browser-based frontend for GDB
77
.. image:: https://travis-ci.org/cs01/gdbgui.svg?branch=master
88
:target: https://travis-ci.org/cs01/gdbgui
99

10-
.. image:: https://img.shields.io/badge/pypi-0.8.2.0-blue.svg
10+
.. image:: https://img.shields.io/badge/pypi-0.9.0.0-blue.svg
1111
:target: https://pypi.python.org/pypi/gdbgui/
1212

1313
.. image:: https://img.shields.io/badge/python-2.7,3.4,3.5,3.6,pypy-blue.svg
@@ -115,45 +115,20 @@ Positional arguments:
115115
``command``: (Optional) The quote-enclosed executable and arguments to run in gdb. This is a way to script the intial loading of the inferior program you wish to debug. For example ``gdbgui "./mybinary -myarg value -flag1 -flag2"`` (note the quotes around the executable and arguments!). Executables and arguments can also be input through the browser interface after launching (no quotes required there).
116116

117117
Flags (all are optional):
118-
-h, --help show this help message and exit
119-
-p PORT, --port PORT The port on which gdbgui will be hosted. Defaults to
120-
5000
121-
--host HOST The host ip address on which gdbgui serve. Defaults to
122-
127.0.0.1
123-
-r, --remote Shortcut to sets host to 0.0.0.0 and suppress browser
124-
from opening. This allows remote access to gdbgui and
125-
is useful when running on a remote machine that you
126-
want to view/debug from your local browser, or let
127-
someone else debug your application remotely.
128-
-g GDB, --gdb GDB Path to gdb or lldb executable. Defaults to gdb. lldb
129-
support is experimental.
130-
--lldb Use lldb commands (experimental)
131-
-v, --version Print version
132-
--hide_gdbgui_upgrades
133-
Hide messages regarding newer version of gdbgui.
134-
Defaults to False.
135-
--debug The debug flag of this Flask application. Pass this
136-
flag when debugging gdbgui itself to automatically
137-
reload the server when changes are detected
138-
-n, --no_browser By default, the browser will open with gdb gui. Pass
139-
this flag so the browser does not open.
140-
-x GDB_CMD_FILE, --gdb_cmd_file GDB_CMD_FILE
141-
Execute GDB commands from file.
142-
143-
--args ARGS [ARGS ...]
144-
(Optional) The binary and arguments to run in gdb.
145-
Example: gdbgui --args "./mybinary myarg -flag1
146-
-flag2"
147-
148-
--auth (Optional) Require authentication before accessing
149-
gdbgui in the browser. Prompt will be displayed in
150-
terminal asking for username and password before
151-
running server. NOTE: gdbgui does not use https.
152-
--auth-file AUTH_FILE
153-
(Optional) Require authentication before accessing
154-
gdbgui in the browser. Specify a file that contains
155-
the HTTP Basic auth username and password separate by
156-
newline. NOTE: gdbgui does not use https.
118+
-h, --help show this help message and exit
119+
-p PORT, --port PORT The port on which gdbgui will be hosted. Defaults to 5000
120+
--host HOST The host ip address on which gdbgui serve. Defaults to 127.0.0.1
121+
-r, --remote Shortcut to sets host to 0.0.0.0 and suppress browser from opening. This allows remote access to gdbgui and is useful when running on a remote machine that you want to view/debug from your local browser, or let someone else debug your application remotely.
122+
-g GDB, --gdb GDB Path to gdb or lldb executable. Defaults to gdb. lldb support is experimental.
123+
--lldb Use lldb commands (experimental)
124+
-v, --version Print version
125+
--hide_gdbgui_upgrades Hide messages regarding newer version of gdbgui. Defaults to False.
126+
--debug The debug flag of this Flask application. Pass this flag when debugging gdbgui itself to automatically reload the server when changes are detected
127+
-n, --no_browser By default, the browser will open with gdb gui. Pass this flag so the browser does not open
128+
-x GDB_CMD_FILE GDB_CMD_FILE Execute GDB commands from file
129+
--args ARGS The binary and arguments to run in gdb. Example: gdbgui --args "./mybinary myarg -flag1 -flag2"
130+
--auth Require authentication before accessing gdbgui in the browser. Prompt will be displayed in terminal asking for username and password before running server. NOTE: gdbgui does not use https
131+
--auth-file AUTH_FILE Require authentication before accessing gdbgui in the browser. Specify a file that contains the HTTP Basic auth username and password separate by newline. NOTE: gdbgui does not use https.
157132

158133

159134
Examples

examples/c/hello.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ struct mystruct_t {
2424
union {
2525
int unionint;
2626
double uniondouble;
27-
}
27+
};
2828
};
2929

30+
3031
int main(void) {
3132
printf("Hello World\n");
3233

gdbgui/VERSION.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.8.2.0
1+
0.9.0.0

gdbgui/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
__title__ = 'gdbgui'
2-
__version__ = '0.8.2.0'
2+
__version__ = '0.9.0.0'
33
__author__ = 'Chad Smith'
44
__copyright__ = 'Copyright Chad Smith'

gdbgui/backend.py

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from flask import Flask, request, Response, render_template, jsonify, redirect
3131
from functools import wraps
3232
from flask_socketio import SocketIO, emit
33+
from flask_compress import Compress
3334
from pygdbmi.gdbcontroller import GdbController
3435
BASE_PATH = os.path.dirname(os.path.realpath(__file__))
3536
PARENTDIR = os.path.dirname(BASE_PATH)
@@ -62,6 +63,8 @@
6263

6364
# Create flask application and add some configuration keys to be used in various callbacks
6465
app = Flask(__name__, template_folder=TEMPLATE_DIR, static_folder=STATIC_DIR)
66+
Compress(app) # add gzip compression to Flask. see https://github.com/libwilliam/flask-compress
67+
6568
# templates are written in pug, so add that capability to flask
6669
app.jinja_env.add_extension('pypugjs.ext.jinja.PyPugJSExtension')
6770
app.config['initial_binary_and_args'] = []

gdbgui/src/js/Actions.js

+40
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,47 @@ const Actions = {
7272
}
7373

7474
store.set('gdb_console_entries', new_entries)
75+
},
76+
toggle_modal_visibility(){
77+
store.set('show_modal', !store.get('show_modal'))
78+
},
79+
show_modal(header, body){
80+
store.set('modal_header', header)
81+
store.set('modal_body', body)
82+
store.set('show_modal', true)
83+
},
84+
set_gdb_binary_and_arguments(binary, args){
85+
// remove list of source files associated with the loaded binary since we're loading a new one
86+
store.set('source_file_paths', [])
87+
store.set('language', 'c_family')
88+
store.set('inferior_binary_path', binary)
89+
Actions.inferior_program_exited()
90+
let cmds = GdbApi.get_load_binary_and_arguments_cmds(binary, args)
91+
GdbApi.run_gdb_command(cmds)
92+
GdbApi.get_inferior_binary_last_modified_unix_sec(binary)
93+
},
94+
fetch_source_files(){
95+
store.set('source_file_paths', [`${constants.ANIMATED_REFRESH_ICON} fetching source files for inferior program`])
96+
GdbApi.run_gdb_command('-file-list-exec-source-files')
97+
},
98+
view_file(fullname, line){
99+
store.set('render_paused_frame_or_user_selection', 'user_selection')
100+
store.set('fullname_to_render', fullname)
101+
Actions.set_line_state(line)
102+
},
103+
set_line_state(line){
104+
store.set('line_of_source_to_flash', parseInt(line))
105+
store.set('make_current_line_visible', true)
106+
},
107+
clear_cached_assembly(){
108+
store.set('disassembly_for_missing_file', [])
109+
let cached_source_files = store.get('cached_source_files')
110+
for(let file of cached_source_files){
111+
file.assembly = {}
112+
}
113+
store.set('cached_source_files', cached_source_files)
75114
}
115+
76116
}
77117

78118
export default Actions

gdbgui/src/js/BinaryLoader.js

-109
This file was deleted.

gdbgui/src/js/BinaryLoader.jsx

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import React from 'react';
2+
import {store} from './store.js';
3+
import constants from './constants.js';
4+
import Actions from './Actions.js';
5+
import Util from './Util.js';
6+
7+
/**
8+
* The BinaryLoader component allows the user to select their binary
9+
* and specify inputs
10+
*/
11+
class BinaryLoader extends React.Component {
12+
constructor(props){
13+
super()
14+
15+
this.state = {
16+
past_binaries: [],
17+
user_input: props.initial_user_input,
18+
set_target_app: props.initial_user_input !== '' // if user supplied initial binary, load it immediately
19+
}
20+
21+
try{
22+
this.state.past_binaries = _.uniq(JSON.parse(localStorage.getItem('past_binaries')))
23+
if(!this.state.user_input){
24+
let most_recent_binary = this.state.past_binaries[0]
25+
this.state.user_input = most_recent_binary
26+
}
27+
} catch(err){
28+
this.state.past_binaries = []
29+
}
30+
}
31+
render(){
32+
return(
33+
<form style={{marginBottom: 1, flex: '2 0 0'}}>
34+
<div className="input-group input-group-sm">
35+
<span className="input-group-btn">
36+
<button
37+
type="button"
38+
title="Loads the binary and any arguments present in the input to the right"
39+
onClick={this.click_set_target_app.bind(this)}
40+
className="btn btn-primary">Load Binary</button>
41+
</span>
42+
<input id="binary"
43+
type="text"
44+
placeholder="/path/to/target/executable -and -flags"
45+
list="past_binaries"
46+
style={{fontFamily: 'courier'}}
47+
className="form-control"
48+
onKeyUp={this.onkeyup_user_input.bind(this)}
49+
onChange={this.onchange_user_inpu.bind(this)}
50+
value={this.state.user_input}/>
51+
</div>
52+
<datalist id="past_binaries">
53+
{this.state.past_binaries.map((b, i) => <option key={i}>{b}</option>)}
54+
</datalist>
55+
</form>
56+
)
57+
}
58+
componentDidMount(){
59+
if(this.state.set_target_app){
60+
this.setState({'set_target_app': false})
61+
this.set_target_app()
62+
}
63+
}
64+
onkeyup_user_input(e){
65+
if(e.keyCode === constants.ENTER_BUTTON_NUM) {
66+
this.set_target_app()
67+
}
68+
}
69+
onchange_user_inpu(e){
70+
this.setState({'user_input': e.target.value})
71+
}
72+
click_set_target_app(){
73+
this.set_target_app()
74+
}
75+
// save to list of binaries used that autopopulates the input dropdown
76+
_add_user_input_to_history(binary_and_args){
77+
_.remove(this.state.past_binaries, i => i === binary_and_args)
78+
this.state.past_binaries.unshift(binary_and_args) // add to beginning
79+
this.setState({past_binaries: this.state.past_binaries})
80+
localStorage.setItem('past_binaries', JSON.stringify(this.state.past_binaries) || [])
81+
}
82+
/**
83+
* parse tokens with awareness of double quotes
84+
*
85+
* @param {string} user_input raw input from user
86+
* @return {Object} { the binary (string) and arguments (array) parsed from user input }
87+
*/
88+
_parse_binary_and_args_from_user_input(user_input){
89+
let list_of_params = Util.string_to_array_safe_quotes(user_input)
90+
, binary = ''
91+
, args = []
92+
, len = list_of_params.length
93+
if(len === 1){
94+
binary = list_of_params[0]
95+
}else if(len > 1){
96+
binary = list_of_params[0]
97+
args = list_of_params.slice(1, len)
98+
}
99+
return {binary: binary, args: args}
100+
}
101+
set_target_app(){
102+
let user_input = _.trim(this.state.user_input)
103+
104+
if (_.trim(user_input) === ''){
105+
store.set('status', {text: 'enter a binary path and arguments', error: true})
106+
return
107+
}
108+
109+
this._add_user_input_to_history(user_input)
110+
111+
const {binary, args} = this._parse_binary_and_args_from_user_input(user_input)
112+
Actions.set_gdb_binary_and_arguments(binary, args)
113+
}
114+
}
115+
116+
export default BinaryLoader

0 commit comments

Comments
 (0)