We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
crash in command start after running sstart
### Description

crash when running start after sstart

### Steps to reproduce

Gdb session history:
```
sstart
start
set exception-verbose on
start
bugreport --run-broweser
```

### My setup

```
Platform: Linux-6.2.0-26-generic-x86_64-with-glibc2.35
OS: Ubuntu 22.04.3 LTS
OS ABI: #26~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jul 13 16:27:29 UTC 2
Architecture: x86_64
Endian: little
Charset: utf-8
Width: 156
Height: 78
Gdb:      12.1
Python:   3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0]
Pwndbg:   2023.07.17 build: e959a47
Capstone: 5.0.1280
Unicorn:  2.0.1
This GDB was configured as follows:
   configure --host=x86_64-linux-gnu --target=x86_64-linux-gnu
	     --with-auto-load-dir=$debugdir:$datadir/auto-load
	     --with-auto-load-safe-path=$debugdir:$datadir/auto-load
	     --with-expat
	     --with-gdb-datadir=/usr/share/gdb (relocatable)
	     --with-jit-reader-dir=/usr/lib/gdb (relocatable)
	     --without-libunwind-ia64
	     --with-lzma
	     --with-babeltrace
	     --with-intel-pt
	     --with-mpfr
	     --with-xxhash
	     --with-python=/usr (relocatable)
	     --with-python-libdir=/usr/lib (relocatable)
	     --with-debuginfod
	     --without-guile
	     --enable-source-highlight
	     --with-separate-debug-dir=/usr/lib/debug (relocatable)
	     --with-system-gdbinit=/etc/gdb/gdbinit
	     --with-system-gdbinit-dir=/etc/gdb/gdbinit.d

("Relocatable" means the directory can be moved with the GDB installation
tree, and GDB will still find it.)

```

![image](https://github.com/pwndbg/pwndbg/assets/93072266/f13bd64a-fff2-46f2-8b1b-df25db23bdfb)


--- 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/gdblib/symbol.py`
Content:
```
1 """
2 Looking up addresses for function names / symbols, and
3 vice-versa.
4 
5 Uses IDA when available if there isn't sufficient symbol
6 information available.
7 """
8 from __future__ import annotations
9 
10 import re
11 
12 import gdb
13 
14 import pwndbg.gdblib.android
15 import pwndbg.gdblib.arch
16 import pwndbg.gdblib.elf
17 import pwndbg.gdblib.events
18 import pwndbg.gdblib.file
19 import pwndbg.gdblib.memory
20 import pwndbg.gdblib.qemu
21 import pwndbg.gdblib.remote
22 import pwndbg.gdblib.stack
23 import pwndbg.gdblib.vmmap
24 import pwndbg.ida
25 import pwndbg.lib.cache
26 
27 
28 def _get_debug_file_directory():
29     """
30     Retrieve the debug file directory path.
31 
32     The debug file directory path ('show debug-file-directory') is a comma-
33     separated list of directories which GDB will look in to find the binaries
34     currently loaded.
35     """
36     result = gdb.execute("show debug-file-directory", to_string=True, from_tty=False)
37     expr = r'The directory where separate debug symbols are searched for is "(.*)".\n'
38 
39     match = re.search(expr, result)
40 
41     if match:
42         return match.group(1)
43     return ""
44 
45 
46 def _set_debug_file_directory(d) -> None:
47     gdb.execute(f"set debug-file-directory {d}", to_string=True, from_tty=False)
48 
49 
50 def _add_debug_file_directory(d) -> None:
51     current = _get_debug_file_directory()
52     if current:
53         _set_debug_file_directory(f"{current}:{d}")
54     else:
55         _set_debug_file_directory(d)
56 
57 
58 if "/usr/lib/debug" not in _get_debug_file_directory():
59     _add_debug_file_directory("/usr/lib/debug")
60 
61 
62 @pwndbg.lib.cache.cache_until("objfile")
63 def get(address: int, gdb_only=False) -> str:
64     """
65     Retrieve the name for the symbol located at `address` - either from GDB or from IDA sync
66     Passing `gdb_only=True`
67     """
68     # Note: we do not return "" on `address < pwndbg.gdblib.memory.MMAP_MIN_ADDR`
69     # because this may be used to find out the symbol name on PIE binaries that weren't started yet
70     # and then their symbol addresses can be found by GDB on their (non-rebased) offsets
71 
72     # Fast path: GDB's `info symbol` returns 'Numeric constant too large' here
73     if address >= ((1 << 64) - 1):
74         return ""
75 
76     # This sucks, but there's not a GDB API for this.
77     result = gdb.execute("info symbol %#x" % int(address), to_string=True, from_tty=False)
78 
79     if not gdb_only and result.startswith("No symbol"):
80         address = int(address)
81         exe = pwndbg.gdblib.elf.exe()
82         if exe:
83             exe_map = pwndbg.gdblib.vmmap.find(exe.address)
84             if exe_map and address in exe_map:
85                 res = pwndbg.ida.Name(address) or pwndbg.ida.GetFuncOffset(address)
86                 return res or ""
87 
88     # If there are newlines, which means that there are multiple symbols for the address
89     # then use the first one (see also #1610)
90     result = result[: result.index("\n")]
91 
92     # See https://github.com/bminor/binutils-gdb/blob/d1702fea87aa62dff7de465464097dba63cc8c0f/gdb/printcmd.c#L1594-L1624
93     # The most often encountered formats looks like this:
94     #   "main in section .text of /bin/bash"
95     #   "main + 3 in section .text of /bin/bash"
96     #   "system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6"
97     #   "No symbol matches system-1"
98     # But there are some others that we have to account for as well
99     if " in section " in result:
100         loc_string, _ = result.split(" in section ")
101     elif " in load address range of " in result:
102         loc_string, _ = result.split(" in load address range of ")
103     elif " overlay section " in result:
104         result, _ = result.split(" overlay section ")
105         loc_string, _ = result.split(" in ")
106     else:
107         loc_string = ""
108 
109     # If there is 'main + 87' we want to replace it with 'main+87' etc.
110     return loc_string.replace(" + ", "+")
111 
112 
113 @pwndbg.lib.cache.cache_until("objfile")
114 def address(symbol: str) -> int:
115     """
116     Get the address for `symbol`
117     """
118     try:
119         symbol_obj = gdb.lookup_symbol(symbol)[0]
120         if symbol_obj:
121             return int(symbol_obj.value().address)
122     except gdb.error as e:
123         # Symbol lookup only throws exceptions on errors, not if it failed to
124         # lookup a symbol. We want to raise these errors so we can handle them
125         # properly, but there are some we haven't figured out how to fix yet, so
126         # we ignore those here
127         skipped_exceptions = []
128 
129         # This is exception is being thrown by the Go typeinfo tests, we should
130         # investigate why this is happening and see if we can explicitly check
131         # for it with `gdb.selected_frame()`
132         skipped_exceptions.append("No frame selected")
133 
134         # If we try to look up a TLS variable when there is no TLS, this
135         # exception occurs. Ideally we should come up with a way to check for
136         # this case before calling `gdb.lookup_symbol`
137         skipped_exceptions.append("Cannot find thread-local")
138 
139         if all(x not in str(e) for x in skipped_exceptions):
140             raise e
141 
142     try:
143         # Unfortunately, `gdb.lookup_symbol` does not seem to handle all
144         # symbols, so we need to fallback to using `gdb.parse_and_eval`. See
145         # https://sourceware.org/pipermail/gdb/2022-October/050362.html
146         # (We tried parsing the output of the `info address` before, but there were some issues. See #1628 and #1666)
147         if "\\" in symbol:
148             # Is it possible that happens? Probably not, but just in case
149             raise ValueError(f"Symbol {symbol!r} contains a backslash")
150         sanitized_symbol_name = symbol.replace("'", "\\'")
151         return int(gdb.parse_and_eval(f"&'{sanitized_symbol_name}'"))
152 
153     except gdb.error:
154         return None
155 
156 
157 @pwndbg.lib.cache.cache_until("objfile", "thread")
158 def static_linkage_symbol_address(symbol: str) -> int:
159     """
160     Get the address for static linkage `symbol`
161     """
162 
163     try:
164         symbol_obj = gdb.lookup_static_symbol(symbol)
165         return int(symbol_obj.value().address) if symbol_obj else None
166     except gdb.error:
167         return None
168 
169 
170 @pwndbg.lib.cache.cache_until("stop", "start")
171 def selected_frame_source_absolute_filename():
172     """
173     Retrieve the symbol table’s source absolute file name from the selected frame.
174 
175     In case of missing symbol table or frame information, None is returned.
176     """
177     try:
178         frame = gdb.selected_frame()
179     except gdb.error:
180         return None
181 
182     if not frame:
183         return None
184 
185     sal = frame.find_sal()
186     if not sal:
187         return None
188 
189     symtab = sal.symtab
190     if not symtab:
191         return None
192 
193     return symtab.fullname()
194 
195 
196 def parse_and_eval(expression: str) -> gdb.Value | None:
197     """Error handling wrapper for GDBs parse_and_eval function"""
198     try:
199         return gdb.parse_and_eval(expression)
200     except gdb.error:
201         return None
202
```
--- 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/gdblib/symbol.py b/pwndbg/gdblib/symbol.py
--- a/pwndbg/gdblib/symbol.py
+++ b/pwndbg/gdblib/symbol.py
@@ -136,6 +136,9 @@
         # this case before calling `gdb.lookup_symbol`
         skipped_exceptions.append("Cannot find thread-local")
 
+        # This reproduced on GDB 12.1 and caused #1878
+        skipped_exceptions.append("symbol requires a frame to compute its value")
+
         if all(x not in str(e) for x in skipped_exceptions):
             raise e

{"golden_diff": "diff --git a/pwndbg/gdblib/symbol.py b/pwndbg/gdblib/symbol.py\n--- a/pwndbg/gdblib/symbol.py\n+++ b/pwndbg/gdblib/symbol.py\n@@ -136,6 +136,9 @@\n         # this case before calling `gdb.lookup_symbol`\n         skipped_exceptions.append(\"Cannot find thread-local\")\n \n+        # This reproduced on GDB 12.1 and caused #1878\n+        skipped_exceptions.append(\"symbol requires a frame to compute its value\")\n+\n         if all(x not in str(e) for x in skipped_exceptions):\n             raise e\n", "issue": "crash in command start after running sstart\n### Description\r\n\r\ncrash when running start after sstart\r\n\r\n### Steps to reproduce\r\n\r\nGdb session history:\r\n```\r\nsstart\r\nstart\r\nset exception-verbose on\r\nstart\r\nbugreport --run-broweser\r\n```\r\n\r\n### My setup\r\n\r\n```\r\nPlatform: Linux-6.2.0-26-generic-x86_64-with-glibc2.35\r\nOS: Ubuntu 22.04.3 LTS\r\nOS ABI: #26~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jul 13 16:27:29 UTC 2\r\nArchitecture: x86_64\r\nEndian: little\r\nCharset: utf-8\r\nWidth: 156\r\nHeight: 78\r\nGdb:      12.1\r\nPython:   3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0]\r\nPwndbg:   2023.07.17 build: e959a47\r\nCapstone: 5.0.1280\r\nUnicorn:  2.0.1\r\nThis GDB was configured as follows:\r\n   configure --host=x86_64-linux-gnu --target=x86_64-linux-gnu\r\n\t     --with-auto-load-dir=$debugdir:$datadir/auto-load\r\n\t     --with-auto-load-safe-path=$debugdir:$datadir/auto-load\r\n\t     --with-expat\r\n\t     --with-gdb-datadir=/usr/share/gdb (relocatable)\r\n\t     --with-jit-reader-dir=/usr/lib/gdb (relocatable)\r\n\t     --without-libunwind-ia64\r\n\t     --with-lzma\r\n\t     --with-babeltrace\r\n\t     --with-intel-pt\r\n\t     --with-mpfr\r\n\t     --with-xxhash\r\n\t     --with-python=/usr (relocatable)\r\n\t     --with-python-libdir=/usr/lib (relocatable)\r\n\t     --with-debuginfod\r\n\t     --without-guile\r\n\t     --enable-source-highlight\r\n\t     --with-separate-debug-dir=/usr/lib/debug (relocatable)\r\n\t     --with-system-gdbinit=/etc/gdb/gdbinit\r\n\t     --with-system-gdbinit-dir=/etc/gdb/gdbinit.d\r\n\r\n(\"Relocatable\" means the directory can be moved with the GDB installation\r\ntree, and GDB will still find it.)\r\n\r\n```\r\n\r\n![image](https://github.com/pwndbg/pwndbg/assets/93072266/f13bd64a-fff2-46f2-8b1b-df25db23bdfb)\r\n\n", "before_files": [{"content": "\"\"\"\nLooking up addresses for function names / symbols, and\nvice-versa.\n\nUses IDA when available if there isn't sufficient symbol\ninformation available.\n\"\"\"\nfrom __future__ import annotations\n\nimport re\n\nimport gdb\n\nimport pwndbg.gdblib.android\nimport pwndbg.gdblib.arch\nimport pwndbg.gdblib.elf\nimport pwndbg.gdblib.events\nimport pwndbg.gdblib.file\nimport pwndbg.gdblib.memory\nimport pwndbg.gdblib.qemu\nimport pwndbg.gdblib.remote\nimport pwndbg.gdblib.stack\nimport pwndbg.gdblib.vmmap\nimport pwndbg.ida\nimport pwndbg.lib.cache\n\n\ndef _get_debug_file_directory():\n    \"\"\"\n    Retrieve the debug file directory path.\n\n    The debug file directory path ('show debug-file-directory') is a comma-\n    separated list of directories which GDB will look in to find the binaries\n    currently loaded.\n    \"\"\"\n    result = gdb.execute(\"show debug-file-directory\", to_string=True, from_tty=False)\n    expr = r'The directory where separate debug symbols are searched for is \"(.*)\".\\n'\n\n    match = re.search(expr, result)\n\n    if match:\n        return match.group(1)\n    return \"\"\n\n\ndef _set_debug_file_directory(d) -> None:\n    gdb.execute(f\"set debug-file-directory {d}\", to_string=True, from_tty=False)\n\n\ndef _add_debug_file_directory(d) -> None:\n    current = _get_debug_file_directory()\n    if current:\n        _set_debug_file_directory(f\"{current}:{d}\")\n    else:\n        _set_debug_file_directory(d)\n\n\nif \"/usr/lib/debug\" not in _get_debug_file_directory():\n    _add_debug_file_directory(\"/usr/lib/debug\")\n\n\n@pwndbg.lib.cache.cache_until(\"objfile\")\ndef get(address: int, gdb_only=False) -> str:\n    \"\"\"\n    Retrieve the name for the symbol located at `address` - either from GDB or from IDA sync\n    Passing `gdb_only=True`\n    \"\"\"\n    # Note: we do not return \"\" on `address < pwndbg.gdblib.memory.MMAP_MIN_ADDR`\n    # because this may be used to find out the symbol name on PIE binaries that weren't started yet\n    # and then their symbol addresses can be found by GDB on their (non-rebased) offsets\n\n    # Fast path: GDB's `info symbol` returns 'Numeric constant too large' here\n    if address >= ((1 << 64) - 1):\n        return \"\"\n\n    # This sucks, but there's not a GDB API for this.\n    result = gdb.execute(\"info symbol %#x\" % int(address), to_string=True, from_tty=False)\n\n    if not gdb_only and result.startswith(\"No symbol\"):\n        address = int(address)\n        exe = pwndbg.gdblib.elf.exe()\n        if exe:\n            exe_map = pwndbg.gdblib.vmmap.find(exe.address)\n            if exe_map and address in exe_map:\n                res = pwndbg.ida.Name(address) or pwndbg.ida.GetFuncOffset(address)\n                return res or \"\"\n\n    # If there are newlines, which means that there are multiple symbols for the address\n    # then use the first one (see also #1610)\n    result = result[: result.index(\"\\n\")]\n\n    # See https://github.com/bminor/binutils-gdb/blob/d1702fea87aa62dff7de465464097dba63cc8c0f/gdb/printcmd.c#L1594-L1624\n    # The most often encountered formats looks like this:\n    #   \"main in section .text of /bin/bash\"\n    #   \"main + 3 in section .text of /bin/bash\"\n    #   \"system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6\"\n    #   \"No symbol matches system-1\"\n    # But there are some others that we have to account for as well\n    if \" in section \" in result:\n        loc_string, _ = result.split(\" in section \")\n    elif \" in load address range of \" in result:\n        loc_string, _ = result.split(\" in load address range of \")\n    elif \" overlay section \" in result:\n        result, _ = result.split(\" overlay section \")\n        loc_string, _ = result.split(\" in \")\n    else:\n        loc_string = \"\"\n\n    # If there is 'main + 87' we want to replace it with 'main+87' etc.\n    return loc_string.replace(\" + \", \"+\")\n\n\n@pwndbg.lib.cache.cache_until(\"objfile\")\ndef address(symbol: str) -> int:\n    \"\"\"\n    Get the address for `symbol`\n    \"\"\"\n    try:\n        symbol_obj = gdb.lookup_symbol(symbol)[0]\n        if symbol_obj:\n            return int(symbol_obj.value().address)\n    except gdb.error as e:\n        # Symbol lookup only throws exceptions on errors, not if it failed to\n        # lookup a symbol. We want to raise these errors so we can handle them\n        # properly, but there are some we haven't figured out how to fix yet, so\n        # we ignore those here\n        skipped_exceptions = []\n\n        # This is exception is being thrown by the Go typeinfo tests, we should\n        # investigate why this is happening and see if we can explicitly check\n        # for it with `gdb.selected_frame()`\n        skipped_exceptions.append(\"No frame selected\")\n\n        # If we try to look up a TLS variable when there is no TLS, this\n        # exception occurs. Ideally we should come up with a way to check for\n        # this case before calling `gdb.lookup_symbol`\n        skipped_exceptions.append(\"Cannot find thread-local\")\n\n        if all(x not in str(e) for x in skipped_exceptions):\n            raise e\n\n    try:\n        # Unfortunately, `gdb.lookup_symbol` does not seem to handle all\n        # symbols, so we need to fallback to using `gdb.parse_and_eval`. See\n        # https://sourceware.org/pipermail/gdb/2022-October/050362.html\n        # (We tried parsing the output of the `info address` before, but there were some issues. See #1628 and #1666)\n        if \"\\\\\" in symbol:\n            # Is it possible that happens? Probably not, but just in case\n            raise ValueError(f\"Symbol {symbol!r} contains a backslash\")\n        sanitized_symbol_name = symbol.replace(\"'\", \"\\\\'\")\n        return int(gdb.parse_and_eval(f\"&'{sanitized_symbol_name}'\"))\n\n    except gdb.error:\n        return None\n\n\n@pwndbg.lib.cache.cache_until(\"objfile\", \"thread\")\ndef static_linkage_symbol_address(symbol: str) -> int:\n    \"\"\"\n    Get the address for static linkage `symbol`\n    \"\"\"\n\n    try:\n        symbol_obj = gdb.lookup_static_symbol(symbol)\n        return int(symbol_obj.value().address) if symbol_obj else None\n    except gdb.error:\n        return None\n\n\n@pwndbg.lib.cache.cache_until(\"stop\", \"start\")\ndef selected_frame_source_absolute_filename():\n    \"\"\"\n    Retrieve the symbol table\u2019s source absolute file name from the selected frame.\n\n    In case of missing symbol table or frame information, None is returned.\n    \"\"\"\n    try:\n        frame = gdb.selected_frame()\n    except gdb.error:\n        return None\n\n    if not frame:\n        return None\n\n    sal = frame.find_sal()\n    if not sal:\n        return None\n\n    symtab = sal.symtab\n    if not symtab:\n        return None\n\n    return symtab.fullname()\n\n\ndef parse_and_eval(expression: str) -> gdb.Value | None:\n    \"\"\"Error handling wrapper for GDBs parse_and_eval function\"\"\"\n    try:\n        return gdb.parse_and_eval(expression)\n    except gdb.error:\n        return None\n", "path": "pwndbg/gdblib/symbol.py"}], "after_files": [{"content": "\"\"\"\nLooking up addresses for function names / symbols, and\nvice-versa.\n\nUses IDA when available if there isn't sufficient symbol\ninformation available.\n\"\"\"\nfrom __future__ import annotations\n\nimport re\n\nimport gdb\n\nimport pwndbg.gdblib.android\nimport pwndbg.gdblib.arch\nimport pwndbg.gdblib.elf\nimport pwndbg.gdblib.events\nimport pwndbg.gdblib.file\nimport pwndbg.gdblib.memory\nimport pwndbg.gdblib.qemu\nimport pwndbg.gdblib.remote\nimport pwndbg.gdblib.stack\nimport pwndbg.gdblib.vmmap\nimport pwndbg.ida\nimport pwndbg.lib.cache\n\n\ndef _get_debug_file_directory():\n    \"\"\"\n    Retrieve the debug file directory path.\n\n    The debug file directory path ('show debug-file-directory') is a comma-\n    separated list of directories which GDB will look in to find the binaries\n    currently loaded.\n    \"\"\"\n    result = gdb.execute(\"show debug-file-directory\", to_string=True, from_tty=False)\n    expr = r'The directory where separate debug symbols are searched for is \"(.*)\".\\n'\n\n    match = re.search(expr, result)\n\n    if match:\n        return match.group(1)\n    return \"\"\n\n\ndef _set_debug_file_directory(d) -> None:\n    gdb.execute(f\"set debug-file-directory {d}\", to_string=True, from_tty=False)\n\n\ndef _add_debug_file_directory(d) -> None:\n    current = _get_debug_file_directory()\n    if current:\n        _set_debug_file_directory(f\"{current}:{d}\")\n    else:\n        _set_debug_file_directory(d)\n\n\nif \"/usr/lib/debug\" not in _get_debug_file_directory():\n    _add_debug_file_directory(\"/usr/lib/debug\")\n\n\n@pwndbg.lib.cache.cache_until(\"objfile\")\ndef get(address: int, gdb_only=False) -> str:\n    \"\"\"\n    Retrieve the name for the symbol located at `address` - either from GDB or from IDA sync\n    Passing `gdb_only=True`\n    \"\"\"\n    # Note: we do not return \"\" on `address < pwndbg.gdblib.memory.MMAP_MIN_ADDR`\n    # because this may be used to find out the symbol name on PIE binaries that weren't started yet\n    # and then their symbol addresses can be found by GDB on their (non-rebased) offsets\n\n    # Fast path: GDB's `info symbol` returns 'Numeric constant too large' here\n    if address >= ((1 << 64) - 1):\n        return \"\"\n\n    # This sucks, but there's not a GDB API for this.\n    result = gdb.execute(\"info symbol %#x\" % int(address), to_string=True, from_tty=False)\n\n    if not gdb_only and result.startswith(\"No symbol\"):\n        address = int(address)\n        exe = pwndbg.gdblib.elf.exe()\n        if exe:\n            exe_map = pwndbg.gdblib.vmmap.find(exe.address)\n            if exe_map and address in exe_map:\n                res = pwndbg.ida.Name(address) or pwndbg.ida.GetFuncOffset(address)\n                return res or \"\"\n\n    # If there are newlines, which means that there are multiple symbols for the address\n    # then use the first one (see also #1610)\n    result = result[: result.index(\"\\n\")]\n\n    # See https://github.com/bminor/binutils-gdb/blob/d1702fea87aa62dff7de465464097dba63cc8c0f/gdb/printcmd.c#L1594-L1624\n    # The most often encountered formats looks like this:\n    #   \"main in section .text of /bin/bash\"\n    #   \"main + 3 in section .text of /bin/bash\"\n    #   \"system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6\"\n    #   \"No symbol matches system-1\"\n    # But there are some others that we have to account for as well\n    if \" in section \" in result:\n        loc_string, _ = result.split(\" in section \")\n    elif \" in load address range of \" in result:\n        loc_string, _ = result.split(\" in load address range of \")\n    elif \" overlay section \" in result:\n        result, _ = result.split(\" overlay section \")\n        loc_string, _ = result.split(\" in \")\n    else:\n        loc_string = \"\"\n\n    # If there is 'main + 87' we want to replace it with 'main+87' etc.\n    return loc_string.replace(\" + \", \"+\")\n\n\n@pwndbg.lib.cache.cache_until(\"objfile\")\ndef address(symbol: str) -> int:\n    \"\"\"\n    Get the address for `symbol`\n    \"\"\"\n    try:\n        symbol_obj = gdb.lookup_symbol(symbol)[0]\n        if symbol_obj:\n            return int(symbol_obj.value().address)\n    except gdb.error as e:\n        # Symbol lookup only throws exceptions on errors, not if it failed to\n        # lookup a symbol. We want to raise these errors so we can handle them\n        # properly, but there are some we haven't figured out how to fix yet, so\n        # we ignore those here\n        skipped_exceptions = []\n\n        # This is exception is being thrown by the Go typeinfo tests, we should\n        # investigate why this is happening and see if we can explicitly check\n        # for it with `gdb.selected_frame()`\n        skipped_exceptions.append(\"No frame selected\")\n\n        # If we try to look up a TLS variable when there is no TLS, this\n        # exception occurs. Ideally we should come up with a way to check for\n        # this case before calling `gdb.lookup_symbol`\n        skipped_exceptions.append(\"Cannot find thread-local\")\n\n        # This reproduced on GDB 12.1 and caused #1878\n        skipped_exceptions.append(\"symbol requires a frame to compute its value\")\n\n        if all(x not in str(e) for x in skipped_exceptions):\n            raise e\n\n    try:\n        # Unfortunately, `gdb.lookup_symbol` does not seem to handle all\n        # symbols, so we need to fallback to using `gdb.parse_and_eval`. See\n        # https://sourceware.org/pipermail/gdb/2022-October/050362.html\n        # (We tried parsing the output of the `info address` before, but there were some issues. See #1628 and #1666)\n        if \"\\\\\" in symbol:\n            # Is it possible that happens? Probably not, but just in case\n            raise ValueError(f\"Symbol {symbol!r} contains a backslash\")\n        sanitized_symbol_name = symbol.replace(\"'\", \"\\\\'\")\n        return int(gdb.parse_and_eval(f\"&'{sanitized_symbol_name}'\"))\n\n    except gdb.error:\n        return None\n\n\n@pwndbg.lib.cache.cache_until(\"objfile\", \"thread\")\ndef static_linkage_symbol_address(symbol: str) -> int:\n    \"\"\"\n    Get the address for static linkage `symbol`\n    \"\"\"\n\n    try:\n        symbol_obj = gdb.lookup_static_symbol(symbol)\n        return int(symbol_obj.value().address) if symbol_obj else None\n    except gdb.error:\n        return None\n\n\n@pwndbg.lib.cache.cache_until(\"stop\", \"start\")\ndef selected_frame_source_absolute_filename():\n    \"\"\"\n    Retrieve the symbol table\u2019s source absolute file name from the selected frame.\n\n    In case of missing symbol table or frame information, None is returned.\n    \"\"\"\n    try:\n        frame = gdb.selected_frame()\n    except gdb.error:\n        return None\n\n    if not frame:\n        return None\n\n    sal = frame.find_sal()\n    if not sal:\n        return None\n\n    symtab = sal.symtab\n    if not symtab:\n        return None\n\n    return symtab.fullname()\n\n\ndef parse_and_eval(expression: str) -> gdb.Value | None:\n    \"\"\"Error handling wrapper for GDBs parse_and_eval function\"\"\"\n    try:\n        return gdb.parse_and_eval(expression)\n    except gdb.error:\n        return None\n", "path": "pwndbg/gdblib/symbol.py"}]}