We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make symbol.get bulletproof against duplicated symbols
@lebr0nli pointed out an interesting case with `symbol.get` failing when Pwntools+Pwndbg is used: https://github.com/pwndbg/pwndbg/pull/1605#discussion_r1126105118

The bug actually does not require Pwntools at all and was partially caused by our `_add_main_to_symbols` hook. I am going to remove that hook in https://github.com/pwndbg/pwndbg/pull/1609 if tests passes, since it seems reduntant.

However, that does not really fix the problem as there may always be duplicated symbols such that `info symbols main` would show:
```
pwndbg> info symbol main
main in section .text of /pwndbg/bug/vaccine
main in section .text of /pwndbg/bug/vaccine
```

This can probably be mitigated by doing something like:
```py
loc_string, *_ = result.split(...)
```

instead of:
```py
loc_string, _ = result.split(...)
```

In the `symbol.get` implementation.

This would also mean we would effectively always assume the first symbol is the one we want to use, but I also do not see a good other way to resolve the duplicated symbol issue.

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

{"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@@ -84,6 +84,10 @@\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", "issue": "Make symbol.get bulletproof against duplicated symbols\n@lebr0nli pointed out an interesting case with `symbol.get` failing when Pwntools+Pwndbg is used: https://github.com/pwndbg/pwndbg/pull/1605#discussion_r1126105118\r\n\r\nThe bug actually does not require Pwntools at all and was partially caused by our `_add_main_to_symbols` hook. I am going to remove that hook in https://github.com/pwndbg/pwndbg/pull/1609 if tests passes, since it seems reduntant.\r\n\r\nHowever, that does not really fix the problem as there may always be duplicated symbols such that `info symbols main` would show:\r\n```\r\npwndbg> info symbol main\r\nmain in section .text of /pwndbg/bug/vaccine\r\nmain in section .text of /pwndbg/bug/vaccine\r\n```\r\n\r\nThis can probably be mitigated by doing something like:\r\n```py\r\nloc_string, *_ = result.split(...)\r\n```\r\n\r\ninstead of:\r\n```py\r\nloc_string, _ = result.split(...)\r\n```\r\n\r\nIn the `symbol.get` implementation.\r\n\r\nThis would also mean we would effectively always assume the first symbol is the one we want to use, but I also do not see a good other way to resolve the duplicated symbol issue.\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\"\"\"\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.info\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.memoize\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(\"set debug-file-directory %s\" % 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(\"%s:%s\" % (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.memoize.reset_on_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    # 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.memoize.reset_on_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 `info address`. See\n        # https://sourceware.org/pipermail/gdb/2022-October/050362.html\n        address = pwndbg.gdblib.info.address(symbol)\n        if address is None or not pwndbg.gdblib.vmmap.find(address):\n            return None\n\n        return address\n\n    except gdb.error:\n        return None\n\n    try:\n        # TODO: We should properly check if we have a connection to the IDA server first\n        address = pwndbg.ida.LocByName(symbol)\n        if address:\n            return address\n    except Exception:\n        pass\n\n    return None\n\n\n@pwndbg.lib.memoize.reset_on_objfile\n@pwndbg.lib.memoize.reset_on_thread\ndef static_linkage_symbol_address(symbol: str) -> int:\n    \"\"\"\n    Get the address for static linkage `symbol`\n    \"\"\"\n\n    try:\n        if hasattr(gdb, \"lookup_static_symbol\"):\n            symbol_obj = gdb.lookup_static_symbol(symbol)\n        else:\n            # GDB < 9.x does not have `gdb.lookup_static_symbol`\n            # We will fallback to `gdb.lookup_symbol` here, but the drawback is that we might find incorrect symbol if there is a symbol with the same name which is not static linkage\n            # But this is better than just returning None\n            # TODO/FIXME: Find a way to get the static linkage symbol's address in GDB < 9.x\n            symbol_obj = gdb.lookup_symbol(symbol)[0]\n        return int(symbol_obj.value().address) if symbol_obj else None\n    except gdb.error:\n        return None\n\n\n@pwndbg.lib.memoize.reset_on_stop\n@pwndbg.lib.memoize.reset_on_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", "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\"\"\"\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.info\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.memoize\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(\"set debug-file-directory %s\" % 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(\"%s:%s\" % (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.memoize.reset_on_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.memoize.reset_on_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 `info address`. See\n        # https://sourceware.org/pipermail/gdb/2022-October/050362.html\n        address = pwndbg.gdblib.info.address(symbol)\n        if address is None or not pwndbg.gdblib.vmmap.find(address):\n            return None\n\n        return address\n\n    except gdb.error:\n        return None\n\n    try:\n        # TODO: We should properly check if we have a connection to the IDA server first\n        address = pwndbg.ida.LocByName(symbol)\n        if address:\n            return address\n    except Exception:\n        pass\n\n    return None\n\n\n@pwndbg.lib.memoize.reset_on_objfile\n@pwndbg.lib.memoize.reset_on_thread\ndef static_linkage_symbol_address(symbol: str) -> int:\n    \"\"\"\n    Get the address for static linkage `symbol`\n    \"\"\"\n\n    try:\n        if hasattr(gdb, \"lookup_static_symbol\"):\n            symbol_obj = gdb.lookup_static_symbol(symbol)\n        else:\n            # GDB < 9.x does not have `gdb.lookup_static_symbol`\n            # We will fallback to `gdb.lookup_symbol` here, but the drawback is that we might find incorrect symbol if there is a symbol with the same name which is not static linkage\n            # But this is better than just returning None\n            # TODO/FIXME: Find a way to get the static linkage symbol's address in GDB < 9.x\n            symbol_obj = gdb.lookup_symbol(symbol)[0]\n        return int(symbol_obj.value().address) if symbol_obj else None\n    except gdb.error:\n        return None\n\n\n@pwndbg.lib.memoize.reset_on_stop\n@pwndbg.lib.memoize.reset_on_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", "path": "pwndbg/gdblib/symbol.py"}]}