We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix cymbol command on Ubuntu 18.04
There's a cymbol test that fails on the Ubuntu 18.04 CI, this issue is there to track it

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pwndbg/commands/cymbol.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 """
5 Add, load, show, edit, or delete symbols for custom structures.
6 
7 For the generation of the symbols g++/gcc is being used under the hood.
8 
9 In case of remote debugging a binary which is not native to your architecture it
10 is advised to configure the 'gcc-config-path' config parameter to your own cross-platform
11 gnu gcc compiled toolchain for your target architecture.
12 
13 You are advised to configure the 'cymbol-editor' config parameter to the path of your
14 favorite text editor. Otherwise cymbol exapnds $EDITOR and $VISUAL environment variables
15 to find the path to the default text editor.
16 """
17 
18 import argparse
19 import functools
20 import os
21 import subprocess
22 import sys
23 import tempfile
24 
25 import gdb
26 
27 import pwndbg
28 import pwndbg.commands
29 import pwndbg.gdblib.arch
30 import pwndbg.lib.gcc
31 import pwndbg.lib.tempfile
32 from pwndbg.color import message
33 
34 gcc_compiler_path = pwndbg.gdblib.config.add_param(
35     "gcc-compiler-path",
36     "",
37     "Path to the gcc/g++ toolchain for generating imported symbols",
38 )
39 
40 cymbol_editor = pwndbg.gdblib.config.add_param(
41     "cymbol-editor", "", "Path to the editor for editing custom structures"
42 )
43 
44 # Remeber loaded symbols. This would be useful for 'remove-symbol-file'.
45 loaded_symbols = {}
46 
47 # Where generated symbol source files are saved.
48 pwndbg_cachedir = pwndbg.lib.tempfile.cachedir("custom-symbols")
49 
50 
51 def unload_loaded_symbol(custom_structure_name):
52     custom_structure_symbols_file = loaded_symbols.get(custom_structure_name)
53     if custom_structure_symbols_file is not None:
54         gdb.execute(f"remove-symbol-file {custom_structure_symbols_file}")
55         loaded_symbols.pop(custom_structure_name)
56 
57 
58 def OnlyWhenStructFileExists(func):
59     @functools.wraps(func)
60     def wrapper(custom_structure_name):
61         pwndbg_custom_structure_path = os.path.join(pwndbg_cachedir, custom_structure_name) + ".c"
62         if not os.path.exists(pwndbg_custom_structure_path):
63             print(message.error("No custom structure was found with the given name!"))
64             return
65         return func(custom_structure_name, pwndbg_custom_structure_path)
66 
67     return wrapper
68 
69 
70 def generate_debug_symbols(custom_structure_path, pwndbg_debug_symbols_output_file=None):
71     if not pwndbg_debug_symbols_output_file:
72         _, pwndbg_debug_symbols_output_file = tempfile.mkstemp(prefix="custom-", suffix=".dbg")
73 
74     # -fno-eliminate-unused-debug-types is a handy gcc flag that lets us extract debug symbols from non-used defined structures.
75     gcc_extra_flags = [
76         custom_structure_path,
77         "-c",
78         "-g",
79         "-fno-eliminate-unused-debug-types",
80         "-o",
81         pwndbg_debug_symbols_output_file,
82     ]
83 
84     # TODO: implement remote debugging support.
85     gcc_flags = pwndbg.lib.gcc.which(pwndbg.gdblib.arch)
86     if gcc_compiler_path != "":
87         gcc_flags[0] = gcc_compiler_path
88 
89     gcc_cmd = gcc_flags + gcc_extra_flags
90 
91     try:
92         subprocess.run(gcc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
93     except subprocess.CalledProcessError as exception:
94         print(message.error(exception))
95         print(
96             message.error(
97                 "Failed to compile the .c file with custom structures. Please fix any compilation errors there may be."
98             )
99         )
100         return None
101     except Exception as exception:
102         print(message.error(exception))
103         print(message.error("An error occured while generating the debug symbols."))
104         return None
105 
106     return pwndbg_debug_symbols_output_file
107 
108 
109 def add_custom_structure(custom_structure_name):
110     pwndbg_custom_structure_path = os.path.join(pwndbg_cachedir, custom_structure_name) + ".c"
111 
112     if os.path.exists(pwndbg_custom_structure_path):
113         option = input(
114             message.notice(
115                 "A custom structure was found with the given name, would you like to overwrite it? [y/n] "
116             )
117         )
118         if option != "y":
119             return
120 
121     print(
122         message.notice("Enter your custom structure in a C header style, press Ctrl+D to save:\n")
123     )
124 
125     custom_structures_source = sys.stdin.read().strip()
126     if custom_structures_source == "":
127         print(message.notice("An empty structure is entered, skipping ..."))
128         return
129 
130     with open(pwndbg_custom_structure_path, "w") as f:
131         f.write(custom_structures_source)
132 
133     # Avoid checking for file existance. Call the decorator wrapper directly.
134     load_custom_structure.__wrapped__(custom_structure_name, pwndbg_custom_structure_path)
135 
136 
137 @OnlyWhenStructFileExists
138 def edit_custom_structure(custom_structure_name, custom_structure_path):
139 
140     # Lookup an editor to use for editing the custom structure.
141     editor_preference = os.getenv("EDITOR")
142     if not editor_preference:
143         editor_preference = os.getenv("VISUAL")
144     if not editor_preference:
145         editor_preference = "vi"
146 
147     if cymbol_editor != "":
148         editor_preference = cymbol_editor
149 
150     try:
151         subprocess.run(
152             [editor_preference, custom_structure_path],
153             check=True,
154         )
155     except Exception as exception:
156         print(message.error("An error occured during opening the source file."))
157         print(message.error(f"Path to the custom structure: {custom_structure_path}"))
158         print(message.error("Please try to manually edit the structure."))
159         print(
160             message.error(
161                 '\nTry to set a path to an editor with:\n\tset "cymbol-editor" /usr/bin/nano'
162             )
163         )
164         return
165 
166     input(message.notice("Press enter when finished editing."))
167 
168     load_custom_structure(custom_structure_name)
169 
170 
171 @OnlyWhenStructFileExists
172 def remove_custom_structure(custom_structure_name, custom_structure_path):
173     unload_loaded_symbol(custom_structure_name)
174     os.remove(custom_structure_path)
175     print(message.success("Symbols are removed!"))
176 
177 
178 @OnlyWhenStructFileExists
179 def load_custom_structure(custom_structure_name, custom_structure_path):
180     unload_loaded_symbol(custom_structure_name)
181     pwndbg_debug_symbols_output_file = generate_debug_symbols(custom_structure_path)
182     if not pwndbg_debug_symbols_output_file:
183         return  # generate_debug_symbols prints on failures
184     gdb.execute(f"add-symbol-file {pwndbg_debug_symbols_output_file}", to_string=True)
185     loaded_symbols[custom_structure_name] = pwndbg_debug_symbols_output_file
186     print(message.success("Symbols are loaded!"))
187 
188 
189 @OnlyWhenStructFileExists
190 def show_custom_structure(custom_structure_name, custom_structure_path):
191     # Call wrapper .func() to avoid memoization.
192     highlighted_source = pwndbg.pwndbg.commands.context.get_highlight_source.func(
193         custom_structure_path
194     )
195     print("\n".join(highlighted_source))
196 
197 
198 parser = argparse.ArgumentParser(
199     description="Add, show, load, edit, or delete custom structures in plain C"
200 )
201 parser.add_argument(
202     "-a",
203     "--add",
204     metavar="name",
205     help="Add a new custom structure",
206     default=None,
207     type=str,
208 )
209 parser.add_argument(
210     "-r",
211     "--remove",
212     metavar="name",
213     help="Remove an existing custom structure",
214     default=None,
215     type=str,
216 )
217 parser.add_argument(
218     "-e",
219     "--edit",
220     metavar="name",
221     help="Edit an existing custom structure",
222     default=None,
223     type=str,
224 )
225 parser.add_argument(
226     "-l",
227     "--load",
228     metavar="name",
229     help="Load an existing custom structure",
230     default=None,
231     type=str,
232 )
233 parser.add_argument(
234     "-s",
235     "--show",
236     metavar="name",
237     help="Show the source code of an existing custom structure",
238     default=None,
239     type=str,
240 )
241 
242 
243 @pwndbg.commands.ArgparsedCommand(parser)
244 @pwndbg.commands.OnlyAmd64
245 @pwndbg.commands.OnlyWhenRunning
246 def cymbol(add, remove, edit, load, show):
247     if add:
248         add_custom_structure(add)
249     elif remove:
250         remove_custom_structure(remove)
251     elif edit:
252         edit_custom_structure(edit)
253     elif load:
254         load_custom_structure(load)
255     elif show:
256         show_custom_structure(show)
257     else:
258         parser.print_help()
259
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pwndbg/commands/cymbol.py b/pwndbg/commands/cymbol.py
--- a/pwndbg/commands/cymbol.py
+++ b/pwndbg/commands/cymbol.py
@@ -181,7 +181,10 @@
     pwndbg_debug_symbols_output_file = generate_debug_symbols(custom_structure_path)
     if not pwndbg_debug_symbols_output_file:
         return  # generate_debug_symbols prints on failures
-    gdb.execute(f"add-symbol-file {pwndbg_debug_symbols_output_file}", to_string=True)
+    # Old GDB versions (e.g. 8.2) requires addr argument in add-symbol-file
+    # we set that address to which to load the symbols to 0 since it doesn't matter here
+    # (because we are only loading types information)
+    gdb.execute(f"add-symbol-file {pwndbg_debug_symbols_output_file} 0", to_string=True)
     loaded_symbols[custom_structure_name] = pwndbg_debug_symbols_output_file
     print(message.success("Symbols are loaded!"))

{"golden_diff": "diff --git a/pwndbg/commands/cymbol.py b/pwndbg/commands/cymbol.py\n--- a/pwndbg/commands/cymbol.py\n+++ b/pwndbg/commands/cymbol.py\n@@ -181,7 +181,10 @@\n     pwndbg_debug_symbols_output_file = generate_debug_symbols(custom_structure_path)\n     if not pwndbg_debug_symbols_output_file:\n         return  # generate_debug_symbols prints on failures\n-    gdb.execute(f\"add-symbol-file {pwndbg_debug_symbols_output_file}\", to_string=True)\n+    # Old GDB versions (e.g. 8.2) requires addr argument in add-symbol-file\n+    # we set that address to which to load the symbols to 0 since it doesn't matter here\n+    # (because we are only loading types information)\n+    gdb.execute(f\"add-symbol-file {pwndbg_debug_symbols_output_file} 0\", to_string=True)\n     loaded_symbols[custom_structure_name] = pwndbg_debug_symbols_output_file\n     print(message.success(\"Symbols are loaded!\"))\n", "issue": "Fix cymbol command on Ubuntu 18.04\nThere's a cymbol test that fails on the Ubuntu 18.04 CI, this issue is there to track it\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n\"\"\"\nAdd, load, show, edit, or delete symbols for custom structures.\n\nFor the generation of the symbols g++/gcc is being used under the hood.\n\nIn case of remote debugging a binary which is not native to your architecture it\nis advised to configure the 'gcc-config-path' config parameter to your own cross-platform\ngnu gcc compiled toolchain for your target architecture.\n\nYou are advised to configure the 'cymbol-editor' config parameter to the path of your\nfavorite text editor. Otherwise cymbol exapnds $EDITOR and $VISUAL environment variables\nto find the path to the default text editor.\n\"\"\"\n\nimport argparse\nimport functools\nimport os\nimport subprocess\nimport sys\nimport tempfile\n\nimport gdb\n\nimport pwndbg\nimport pwndbg.commands\nimport pwndbg.gdblib.arch\nimport pwndbg.lib.gcc\nimport pwndbg.lib.tempfile\nfrom pwndbg.color import message\n\ngcc_compiler_path = pwndbg.gdblib.config.add_param(\n    \"gcc-compiler-path\",\n    \"\",\n    \"Path to the gcc/g++ toolchain for generating imported symbols\",\n)\n\ncymbol_editor = pwndbg.gdblib.config.add_param(\n    \"cymbol-editor\", \"\", \"Path to the editor for editing custom structures\"\n)\n\n# Remeber loaded symbols. This would be useful for 'remove-symbol-file'.\nloaded_symbols = {}\n\n# Where generated symbol source files are saved.\npwndbg_cachedir = pwndbg.lib.tempfile.cachedir(\"custom-symbols\")\n\n\ndef unload_loaded_symbol(custom_structure_name):\n    custom_structure_symbols_file = loaded_symbols.get(custom_structure_name)\n    if custom_structure_symbols_file is not None:\n        gdb.execute(f\"remove-symbol-file {custom_structure_symbols_file}\")\n        loaded_symbols.pop(custom_structure_name)\n\n\ndef OnlyWhenStructFileExists(func):\n    @functools.wraps(func)\n    def wrapper(custom_structure_name):\n        pwndbg_custom_structure_path = os.path.join(pwndbg_cachedir, custom_structure_name) + \".c\"\n        if not os.path.exists(pwndbg_custom_structure_path):\n            print(message.error(\"No custom structure was found with the given name!\"))\n            return\n        return func(custom_structure_name, pwndbg_custom_structure_path)\n\n    return wrapper\n\n\ndef generate_debug_symbols(custom_structure_path, pwndbg_debug_symbols_output_file=None):\n    if not pwndbg_debug_symbols_output_file:\n        _, pwndbg_debug_symbols_output_file = tempfile.mkstemp(prefix=\"custom-\", suffix=\".dbg\")\n\n    # -fno-eliminate-unused-debug-types is a handy gcc flag that lets us extract debug symbols from non-used defined structures.\n    gcc_extra_flags = [\n        custom_structure_path,\n        \"-c\",\n        \"-g\",\n        \"-fno-eliminate-unused-debug-types\",\n        \"-o\",\n        pwndbg_debug_symbols_output_file,\n    ]\n\n    # TODO: implement remote debugging support.\n    gcc_flags = pwndbg.lib.gcc.which(pwndbg.gdblib.arch)\n    if gcc_compiler_path != \"\":\n        gcc_flags[0] = gcc_compiler_path\n\n    gcc_cmd = gcc_flags + gcc_extra_flags\n\n    try:\n        subprocess.run(gcc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)\n    except subprocess.CalledProcessError as exception:\n        print(message.error(exception))\n        print(\n            message.error(\n                \"Failed to compile the .c file with custom structures. Please fix any compilation errors there may be.\"\n            )\n        )\n        return None\n    except Exception as exception:\n        print(message.error(exception))\n        print(message.error(\"An error occured while generating the debug symbols.\"))\n        return None\n\n    return pwndbg_debug_symbols_output_file\n\n\ndef add_custom_structure(custom_structure_name):\n    pwndbg_custom_structure_path = os.path.join(pwndbg_cachedir, custom_structure_name) + \".c\"\n\n    if os.path.exists(pwndbg_custom_structure_path):\n        option = input(\n            message.notice(\n                \"A custom structure was found with the given name, would you like to overwrite it? [y/n] \"\n            )\n        )\n        if option != \"y\":\n            return\n\n    print(\n        message.notice(\"Enter your custom structure in a C header style, press Ctrl+D to save:\\n\")\n    )\n\n    custom_structures_source = sys.stdin.read().strip()\n    if custom_structures_source == \"\":\n        print(message.notice(\"An empty structure is entered, skipping ...\"))\n        return\n\n    with open(pwndbg_custom_structure_path, \"w\") as f:\n        f.write(custom_structures_source)\n\n    # Avoid checking for file existance. Call the decorator wrapper directly.\n    load_custom_structure.__wrapped__(custom_structure_name, pwndbg_custom_structure_path)\n\n\n@OnlyWhenStructFileExists\ndef edit_custom_structure(custom_structure_name, custom_structure_path):\n\n    # Lookup an editor to use for editing the custom structure.\n    editor_preference = os.getenv(\"EDITOR\")\n    if not editor_preference:\n        editor_preference = os.getenv(\"VISUAL\")\n    if not editor_preference:\n        editor_preference = \"vi\"\n\n    if cymbol_editor != \"\":\n        editor_preference = cymbol_editor\n\n    try:\n        subprocess.run(\n            [editor_preference, custom_structure_path],\n            check=True,\n        )\n    except Exception as exception:\n        print(message.error(\"An error occured during opening the source file.\"))\n        print(message.error(f\"Path to the custom structure: {custom_structure_path}\"))\n        print(message.error(\"Please try to manually edit the structure.\"))\n        print(\n            message.error(\n                '\\nTry to set a path to an editor with:\\n\\tset \"cymbol-editor\" /usr/bin/nano'\n            )\n        )\n        return\n\n    input(message.notice(\"Press enter when finished editing.\"))\n\n    load_custom_structure(custom_structure_name)\n\n\n@OnlyWhenStructFileExists\ndef remove_custom_structure(custom_structure_name, custom_structure_path):\n    unload_loaded_symbol(custom_structure_name)\n    os.remove(custom_structure_path)\n    print(message.success(\"Symbols are removed!\"))\n\n\n@OnlyWhenStructFileExists\ndef load_custom_structure(custom_structure_name, custom_structure_path):\n    unload_loaded_symbol(custom_structure_name)\n    pwndbg_debug_symbols_output_file = generate_debug_symbols(custom_structure_path)\n    if not pwndbg_debug_symbols_output_file:\n        return  # generate_debug_symbols prints on failures\n    gdb.execute(f\"add-symbol-file {pwndbg_debug_symbols_output_file}\", to_string=True)\n    loaded_symbols[custom_structure_name] = pwndbg_debug_symbols_output_file\n    print(message.success(\"Symbols are loaded!\"))\n\n\n@OnlyWhenStructFileExists\ndef show_custom_structure(custom_structure_name, custom_structure_path):\n    # Call wrapper .func() to avoid memoization.\n    highlighted_source = pwndbg.pwndbg.commands.context.get_highlight_source.func(\n        custom_structure_path\n    )\n    print(\"\\n\".join(highlighted_source))\n\n\nparser = argparse.ArgumentParser(\n    description=\"Add, show, load, edit, or delete custom structures in plain C\"\n)\nparser.add_argument(\n    \"-a\",\n    \"--add\",\n    metavar=\"name\",\n    help=\"Add a new custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-r\",\n    \"--remove\",\n    metavar=\"name\",\n    help=\"Remove an existing custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-e\",\n    \"--edit\",\n    metavar=\"name\",\n    help=\"Edit an existing custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-l\",\n    \"--load\",\n    metavar=\"name\",\n    help=\"Load an existing custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-s\",\n    \"--show\",\n    metavar=\"name\",\n    help=\"Show the source code of an existing custom structure\",\n    default=None,\n    type=str,\n)\n\n\n@pwndbg.commands.ArgparsedCommand(parser)\n@pwndbg.commands.OnlyAmd64\n@pwndbg.commands.OnlyWhenRunning\ndef cymbol(add, remove, edit, load, show):\n    if add:\n        add_custom_structure(add)\n    elif remove:\n        remove_custom_structure(remove)\n    elif edit:\n        edit_custom_structure(edit)\n    elif load:\n        load_custom_structure(load)\n    elif show:\n        show_custom_structure(show)\n    else:\n        parser.print_help()\n", "path": "pwndbg/commands/cymbol.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\n\"\"\"\nAdd, load, show, edit, or delete symbols for custom structures.\n\nFor the generation of the symbols g++/gcc is being used under the hood.\n\nIn case of remote debugging a binary which is not native to your architecture it\nis advised to configure the 'gcc-config-path' config parameter to your own cross-platform\ngnu gcc compiled toolchain for your target architecture.\n\nYou are advised to configure the 'cymbol-editor' config parameter to the path of your\nfavorite text editor. Otherwise cymbol exapnds $EDITOR and $VISUAL environment variables\nto find the path to the default text editor.\n\"\"\"\n\nimport argparse\nimport functools\nimport os\nimport subprocess\nimport sys\nimport tempfile\n\nimport gdb\n\nimport pwndbg\nimport pwndbg.commands\nimport pwndbg.gdblib.arch\nimport pwndbg.lib.gcc\nimport pwndbg.lib.tempfile\nfrom pwndbg.color import message\n\ngcc_compiler_path = pwndbg.gdblib.config.add_param(\n    \"gcc-compiler-path\",\n    \"\",\n    \"Path to the gcc/g++ toolchain for generating imported symbols\",\n)\n\ncymbol_editor = pwndbg.gdblib.config.add_param(\n    \"cymbol-editor\", \"\", \"Path to the editor for editing custom structures\"\n)\n\n# Remeber loaded symbols. This would be useful for 'remove-symbol-file'.\nloaded_symbols = {}\n\n# Where generated symbol source files are saved.\npwndbg_cachedir = pwndbg.lib.tempfile.cachedir(\"custom-symbols\")\n\n\ndef unload_loaded_symbol(custom_structure_name):\n    custom_structure_symbols_file = loaded_symbols.get(custom_structure_name)\n    if custom_structure_symbols_file is not None:\n        gdb.execute(f\"remove-symbol-file {custom_structure_symbols_file}\")\n        loaded_symbols.pop(custom_structure_name)\n\n\ndef OnlyWhenStructFileExists(func):\n    @functools.wraps(func)\n    def wrapper(custom_structure_name):\n        pwndbg_custom_structure_path = os.path.join(pwndbg_cachedir, custom_structure_name) + \".c\"\n        if not os.path.exists(pwndbg_custom_structure_path):\n            print(message.error(\"No custom structure was found with the given name!\"))\n            return\n        return func(custom_structure_name, pwndbg_custom_structure_path)\n\n    return wrapper\n\n\ndef generate_debug_symbols(custom_structure_path, pwndbg_debug_symbols_output_file=None):\n    if not pwndbg_debug_symbols_output_file:\n        _, pwndbg_debug_symbols_output_file = tempfile.mkstemp(prefix=\"custom-\", suffix=\".dbg\")\n\n    # -fno-eliminate-unused-debug-types is a handy gcc flag that lets us extract debug symbols from non-used defined structures.\n    gcc_extra_flags = [\n        custom_structure_path,\n        \"-c\",\n        \"-g\",\n        \"-fno-eliminate-unused-debug-types\",\n        \"-o\",\n        pwndbg_debug_symbols_output_file,\n    ]\n\n    # TODO: implement remote debugging support.\n    gcc_flags = pwndbg.lib.gcc.which(pwndbg.gdblib.arch)\n    if gcc_compiler_path != \"\":\n        gcc_flags[0] = gcc_compiler_path\n\n    gcc_cmd = gcc_flags + gcc_extra_flags\n\n    try:\n        subprocess.run(gcc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)\n    except subprocess.CalledProcessError as exception:\n        print(message.error(exception))\n        print(\n            message.error(\n                \"Failed to compile the .c file with custom structures. Please fix any compilation errors there may be.\"\n            )\n        )\n        return None\n    except Exception as exception:\n        print(message.error(exception))\n        print(message.error(\"An error occured while generating the debug symbols.\"))\n        return None\n\n    return pwndbg_debug_symbols_output_file\n\n\ndef add_custom_structure(custom_structure_name):\n    pwndbg_custom_structure_path = os.path.join(pwndbg_cachedir, custom_structure_name) + \".c\"\n\n    if os.path.exists(pwndbg_custom_structure_path):\n        option = input(\n            message.notice(\n                \"A custom structure was found with the given name, would you like to overwrite it? [y/n] \"\n            )\n        )\n        if option != \"y\":\n            return\n\n    print(\n        message.notice(\"Enter your custom structure in a C header style, press Ctrl+D to save:\\n\")\n    )\n\n    custom_structures_source = sys.stdin.read().strip()\n    if custom_structures_source == \"\":\n        print(message.notice(\"An empty structure is entered, skipping ...\"))\n        return\n\n    with open(pwndbg_custom_structure_path, \"w\") as f:\n        f.write(custom_structures_source)\n\n    # Avoid checking for file existance. Call the decorator wrapper directly.\n    load_custom_structure.__wrapped__(custom_structure_name, pwndbg_custom_structure_path)\n\n\n@OnlyWhenStructFileExists\ndef edit_custom_structure(custom_structure_name, custom_structure_path):\n\n    # Lookup an editor to use for editing the custom structure.\n    editor_preference = os.getenv(\"EDITOR\")\n    if not editor_preference:\n        editor_preference = os.getenv(\"VISUAL\")\n    if not editor_preference:\n        editor_preference = \"vi\"\n\n    if cymbol_editor != \"\":\n        editor_preference = cymbol_editor\n\n    try:\n        subprocess.run(\n            [editor_preference, custom_structure_path],\n            check=True,\n        )\n    except Exception as exception:\n        print(message.error(\"An error occured during opening the source file.\"))\n        print(message.error(f\"Path to the custom structure: {custom_structure_path}\"))\n        print(message.error(\"Please try to manually edit the structure.\"))\n        print(\n            message.error(\n                '\\nTry to set a path to an editor with:\\n\\tset \"cymbol-editor\" /usr/bin/nano'\n            )\n        )\n        return\n\n    input(message.notice(\"Press enter when finished editing.\"))\n\n    load_custom_structure(custom_structure_name)\n\n\n@OnlyWhenStructFileExists\ndef remove_custom_structure(custom_structure_name, custom_structure_path):\n    unload_loaded_symbol(custom_structure_name)\n    os.remove(custom_structure_path)\n    print(message.success(\"Symbols are removed!\"))\n\n\n@OnlyWhenStructFileExists\ndef load_custom_structure(custom_structure_name, custom_structure_path):\n    unload_loaded_symbol(custom_structure_name)\n    pwndbg_debug_symbols_output_file = generate_debug_symbols(custom_structure_path)\n    if not pwndbg_debug_symbols_output_file:\n        return  # generate_debug_symbols prints on failures\n    # Old GDB versions (e.g. 8.2) requires addr argument in add-symbol-file\n    # we set that address to which to load the symbols to 0 since it doesn't matter here\n    # (because we are only loading types information)\n    gdb.execute(f\"add-symbol-file {pwndbg_debug_symbols_output_file} 0\", to_string=True)\n    loaded_symbols[custom_structure_name] = pwndbg_debug_symbols_output_file\n    print(message.success(\"Symbols are loaded!\"))\n\n\n@OnlyWhenStructFileExists\ndef show_custom_structure(custom_structure_name, custom_structure_path):\n    # Call wrapper .func() to avoid memoization.\n    highlighted_source = pwndbg.pwndbg.commands.context.get_highlight_source.func(\n        custom_structure_path\n    )\n    print(\"\\n\".join(highlighted_source))\n\n\nparser = argparse.ArgumentParser(\n    description=\"Add, show, load, edit, or delete custom structures in plain C\"\n)\nparser.add_argument(\n    \"-a\",\n    \"--add\",\n    metavar=\"name\",\n    help=\"Add a new custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-r\",\n    \"--remove\",\n    metavar=\"name\",\n    help=\"Remove an existing custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-e\",\n    \"--edit\",\n    metavar=\"name\",\n    help=\"Edit an existing custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-l\",\n    \"--load\",\n    metavar=\"name\",\n    help=\"Load an existing custom structure\",\n    default=None,\n    type=str,\n)\nparser.add_argument(\n    \"-s\",\n    \"--show\",\n    metavar=\"name\",\n    help=\"Show the source code of an existing custom structure\",\n    default=None,\n    type=str,\n)\n\n\n@pwndbg.commands.ArgparsedCommand(parser)\n@pwndbg.commands.OnlyAmd64\n@pwndbg.commands.OnlyWhenRunning\ndef cymbol(add, remove, edit, load, show):\n    if add:\n        add_custom_structure(add)\n    elif remove:\n        remove_custom_structure(remove)\n    elif edit:\n        edit_custom_structure(edit)\n    elif load:\n        load_custom_structure(load)\n    elif show:\n        show_custom_structure(show)\n    else:\n        parser.print_help()\n", "path": "pwndbg/commands/cymbol.py"}]}