在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:nakst/gf开源软件地址:https://github.com/nakst/gf开源编程语言:C 59.4%开源软件介绍:gf – A GDB FrontendBuildingDownload this project's source. git clone https://github.com/nakst/gf.git And compile the application. ./build.sh Please read the rest of this file to learn about using and configuring Extension packAll tiers on my Patreon, https://www.patreon.com/nakst, get access to the extension pack. This currently includes:
Make sure you use the latest version of the extension pack with the latest commit of Tips
SettingsOn startup, settings are loaded from GDB configurationYou can pass additional arguments to GDB in the [gdb]
argument=-nx
argument=-ex record You can also change the location of the GDB executable. For example, [gdb]
path=/home/a/opt/gdb You can direct all output from GDB to be sent to the "Log" window, if you have one in your layout string. This will work even if you haven't setup a log pipe. This can be used to view the stderr output from your target dynamically as it is running. [gdb]
log_all_output=1 Custom keyboard shortcutsKeyboard shortcuts are placed in the [shortcuts]
Ctrl+I=print i
Ctrl+Shift+F10=reverse-next
Ctrl+Shift+F11=reverse-step You can use any standard GDB command, or any of the commands listed in "Special commands" below. User interfaceYou can change the font and user interface scaling in the [ui]
scale=1.5
font_path=/usr/share/fonts/TTF/DejaVuSansMono.ttf
font_size_interface=17
font_size_code=20 To change the font, FreeType must have been available when you compiled gf. You can enable subpixel font rendering by recompiling with You can also configure the interface layout, with the layout=h(75,v(75,Source,Console),v(50,t(Watch,Breakpoints,Commands,Struct,Exe),t(Stack,Files,Registers,Data,Thread)))) NB: Horizontal and vertical splits must have exactly two children. Instead, you can nest them to create more complex layouts. You can maximize the window at startup with You can request for the expressions in the watch window to be saved and restored by setting ThemesYou can change the theme in the Preset commandsYou can create a list of quickly accessible commands, available in the "Commands" tab in the UI. Separate individual commands using a semicolon. Each command in the list is run one after another; to run the final command asynchronously, put a [commands]
Compile=shell gcc -o bin/app src/main.c
Run normal=file bin/app;run&
Run tests=file bin/app;run test_cases.txt&
Set breakpoints=b main;b LoadFile;b AssertionFailure You can use any standard GDB command, or any of the commands listed in "Special commands" below. Vim integrationYou can change the server name with the [vim]
server_name=MyVimServer Control pipeYou can change the loaded file and line by sending commands to the control pipe. First, you must set the location of the control pipe. In the Then, you can send commands to the pipe. For example, # Load the specified file (must be a full path).
echo f /home/a/test.c > /home/a/control_pipe.dat
# Go to line 123.
echo l 123 > /home/a/control_pipe.dat
# Send a GDB command.
echo c file myapp > /home/a/control_pipe.dat This can be used for text editor integration. Log windowYou can show messages send to a pipe using the log window. First, you must set the location of the log pipe. In the Here is an example of how to send messages to the pipe: #define LOG(...) do { fprintf(logFile, __VA_ARGS__); fflush(logFile); } while (0)
#define LOG_OPEN(path) logFile = fopen(path, "w")
FILE *logFile;
...
LOG_OPEN("...");
LOG("Hello, world!\n"); Special commandsgf-step
gf-next
gf-step-out-of-block
gf-restart-gdb
gf-get-pwd
gf-switch-to
gf-command
gf-inspect-line
Watch window hooksYou can customize the behaviour of the watch window when displaying specific types using Python. When the watch window wants to display the fields of a value, it will look a hook function at
For example, the following hook add a width and height custom field for a rectangle type. def RectangleHook(item, field):
if field:
if field == '[width]':
# item['...'] looks up a field in the struct, returned as a gdb.Value
# int(...) converts the gdb.Value to an int so we can do arithmetic on it
# gdb.Value(...) converts the result back to a gdb.Value
return gdb.Value(int(item['right']) - item['left'])
if field == '[height]':
# do something similar for the height
return gdb.Value(int(item['bottom']) - item['top'])
else:
print('[width]') # add the width custom field
print('[height]') # add the height custom field
_gf_fields_recurse(item) # add the fields actually in the struct
gf_hooks = { 'Rectangle': RectangleHook } # create the hook dictionary If you want to create a custom dynamic array type, instead of printing field names, print struct MyArray {
int length;
float *items;
}; This is the hook definition: def MyArrayHook(item, field):
if field: return item['items'][int(field[1:-1])]
else: print('(d_arr)', int(item['length'])) Templates are removed from the name of the type. For example, PluginsThere is a simple plugin system. Make a file called gf uses the Luigi UI library. It is documented here: https://github.com/nakst/luigi/blob/main/README.md. You can register new windows, command and data viewers in a constructor function. For example, __attribute__((constructor))
void MyPluginRegister() {
interfaceWindows.Add({
"Hello", // The window's name. Used to match it against the UI layout string.
MyPluginHelloWindowCreate, // The callback to create an instance of the window.
MyPluginHelloWindowUpdate // The callback to update an instance of the window (called every time the target pauses/steps).
});
interfaceDataViewers.Add({
"Add test...", // The label of the button to show in the Data tab.
MyPluginTestViewerCreate // The callback to create the data viewer.
});
interfaceCommands.Add({
"My command", // The label to show in the application menu.
{ /* UIShortcut */ }
});
} The interface window creation callback is passed the parent UIElement and should return the UIElement it creates. UIElement *MyPluginHelloWindowCreate(UIElement *parent) {
UIPanel *panel = UIPanelCreate(parent, UI_PANEL_GRAY | UI_PANEL_EXPAND);
UILabelCreate(&panel->e, 0, "Hello, world!", -1);
return &panel->e;
} The interface window update callback is passed the output of GDB from the most recent step, and the UIElement returned by the creation callback. void MyPluginHelloWindowUpdate(const char *gdbOutput, UIElement *element) {
// TODO Update the window.
} The interface data viewer creation callback should create a MDI child of the data tab as follows: void MyPluginTestViewerCreate(void *unused) {
UIMDIChild *window = UIMDIChildCreate(&dataWindow->e, UI_MDI_CHILD_CLOSE_BUTTON, UI_RECT_1(0), "Title", -1);
// TODO Configure the viewer.
UIElementRefresh(&dataWindow->e);
} For communicating with GDB, there are the following functions. // Evaluate an expression. The result is overwritten between calls!
const char *EvaluateExpression(const char *expression, const char *format = nullptr);
// Send and run a command in GDB. Set `echo` to log the command in the console window.
// If `synchronous` is set the function will wait for the command to complete before it returns.
void DebuggerSend(const char *string, bool echo, bool synchronous); There are many examples of how to do these things in Contributors
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论