We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
add-symbol-file should not specify a base address
This happens when connecting to a remote target:
```
hacker@babyrop_level10:~$ gdb -ex 'target remote :1234'
...
add-symbol-file /tmp/tmp_yea7f3g/babyrop_level10.0 0x555555554000
...
pwndbg> b main
Breakpoint 1 at 0x555555555581 (2 locations)
pwndbg> info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   <MULTIPLE>         
1.1                         y   0x0000555555555581 <main>
1.2                         y   0x00005555555567c1 
```
This double breakpoint results in `\xcc` bytes incorrectly polluting memory, and I've seen this corrupt the GOT and crash my program as a result.

https://github.com/pwndbg/pwndbg/blob/05036defa01d4d47bfad56867f53470a29fcdc89/pwndbg/symbol.py#L261

Why is the base address being specified here? According to the help info for `add-symbol-file`, if anything is specified for `[ADDR]`, it should be the location of the `.text` section.

```
(gdb) help add-symbol-file
Load symbols from FILE, assuming FILE has been dynamically loaded.
Usage: add-symbol-file FILE [-readnow | -readnever] [-o OFF] [ADDR] [-s SECT-NAME SECT-ADDR]...
ADDR is the starting address of the file's text.
Each '-s' argument provides a section name and address, and
should be specified if the data and bss segments are not contiguous
with the text.  SECT-NAME is a section name to be loaded at SECT-ADDR.
OFF is an optional offset which is added to the default load addresses
of all sections for which no other address was specified.
The '-readnow' option will cause GDB to read the entire symbol file
immediately.  This makes the command slower, but may make future operations
faster.
The '-readnever' option will prevent GDB from reading the symbol file's
symbolic debug information.
```

If we just omit the address, `gdb` will automatically find the `.text` section and use that address. Things would probably fail if there isn't a `.text` section defined, but I'm not really sure what the correct solution would be in this case anyways.

--- 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/symbol.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4 Looking up addresses for function names / symbols, and
5 vice-versa.
6 
7 Uses IDA when available if there isn't sufficient symbol
8 information available.
9 """
10 import os
11 import re
12 import shutil
13 import tempfile
14 
15 import elftools.common.exceptions
16 import elftools.elf.constants
17 import elftools.elf.elffile
18 import elftools.elf.segments
19 import gdb
20 
21 import pwndbg.arch
22 import pwndbg.elf
23 import pwndbg.events
24 import pwndbg.file
25 import pwndbg.ida
26 import pwndbg.memoize
27 import pwndbg.memory
28 import pwndbg.qemu
29 import pwndbg.remote
30 import pwndbg.stack
31 import pwndbg.vmmap
32 
33 
34 def get_directory():
35     """
36     Retrieve the debug file directory path.
37 
38     The debug file directory path ('show debug-file-directory') is a comma-
39     separated list of directories which GDB will look in to find the binaries
40     currently loaded.
41     """
42     result = gdb.execute('show debug-file-directory', to_string=True, from_tty=False)
43     expr   = r'The directory where separate debug symbols are searched for is "(.*)".\n'
44 
45     match = re.search(expr, result)
46 
47     if match:
48         return match.group(1)
49     return ''
50 
51 def set_directory(d):
52     gdb.execute('set debug-file-directory %s' % d, to_string=True, from_tty=False)
53 
54 def add_directory(d):
55     current = get_directory()
56     if current:
57         set_directory('%s:%s' % (current, d))
58     else:
59         set_directory(d)
60 
61 remote_files = {}
62 remote_files_dir = None
63 
64 @pwndbg.events.exit
65 def reset_remote_files():
66     global remote_files
67     global remote_files_dir
68     remote_files = {}
69     if remote_files_dir is not None:
70         shutil.rmtree(remote_files_dir)
71         remote_files_dir = None
72 
73 @pwndbg.events.new_objfile
74 def autofetch():
75     """
76     """
77     global remote_files_dir
78     if not pwndbg.remote.is_remote():
79         return
80 
81     if pwndbg.qemu.is_qemu_usermode():
82         return
83 
84     if pwndbg.android.is_android():
85         return
86 
87     if not remote_files_dir:
88         remote_files_dir = tempfile.mkdtemp()
89         add_directory(remote_files_dir)
90 
91     searchpath = get_directory()
92 
93     for mapping in pwndbg.vmmap.get():
94         objfile = mapping.objfile
95 
96         # Don't attempt to download things like '[stack]' and '[heap]'
97         if not objfile.startswith('/'):
98             continue
99 
100         # Don't re-download things that we have already downloaded
101         if not objfile or objfile in remote_files:
102             continue
103 
104         msg = "Downloading %r from the remote server" % objfile
105         print(msg, end='')
106 
107         try:
108             data = pwndbg.file.get(objfile)
109             print('\r' + msg + ': OK')
110         except OSError:
111             # The file could not be downloaded :(
112             print('\r' + msg + ': Failed')
113             return
114 
115         filename = os.path.basename(objfile)
116         local_path = os.path.join(remote_files_dir, filename)
117 
118         with open(local_path, 'wb+') as f:
119             f.write(data)
120 
121         remote_files[objfile] = local_path
122 
123         base = None
124         for mapping in pwndbg.vmmap.get():
125             if mapping.objfile != objfile:
126                 continue
127 
128             if base is None or mapping.vaddr < base.vaddr:
129                 base = mapping
130 
131         if not base:
132             continue
133 
134         base = base.vaddr
135 
136         try:
137             elf = elftools.elf.elffile.ELFFile(open(local_path, 'rb'))
138         except elftools.common.exceptions.ELFError:
139             continue
140 
141         gdb_command = ['add-symbol-file', local_path, hex(int(base))]
142         for section in elf.iter_sections():
143             name = section.name #.decode('latin-1')
144             section = section.header
145             if not section.sh_flags & elftools.elf.constants.SH_FLAGS.SHF_ALLOC:
146                 continue
147             gdb_command += ['-s', name, hex(int(base + section.sh_addr))]
148 
149         print(' '.join(gdb_command))
150         # gdb.execute(' '.join(gdb_command), from_tty=False, to_string=True)
151 
152 @pwndbg.memoize.reset_on_objfile
153 def get(address, gdb_only=False):
154     """
155     Retrieve the textual name for a symbol
156     """
157     # Fast path
158     if address < pwndbg.memory.MMAP_MIN_ADDR or address >= ((1 << 64)-1):
159         return ''
160 
161     # Don't look up stack addresses
162     if pwndbg.stack.find(address):
163         return ''
164 
165     # This sucks, but there's not a GDB API for this.
166     result = gdb.execute('info symbol %#x' % int(address), to_string=True, from_tty=False)
167 
168     if not gdb_only and result.startswith('No symbol'):
169         address = int(address)
170         exe     = pwndbg.elf.exe()
171         if exe:
172             exe_map = pwndbg.vmmap.find(exe.address)
173             if exe_map and address in exe_map:
174                 res =  pwndbg.ida.Name(address) or pwndbg.ida.GetFuncOffset(address)
175                 return res or ''
176 
177     # Expected format looks like this:
178     # main in section .text of /bin/bash
179     # main + 3 in section .text of /bin/bash
180     # system + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6
181     # No symbol matches system-1.
182     a, b, c, _ = result.split(None, 3)
183 
184 
185     if b == '+':
186         return "%s+%s" % (a, c)
187     if b == 'in':
188         return a
189 
190     return ''
191 
192 @pwndbg.memoize.reset_on_objfile
193 def address(symbol, allow_unmapped=False):
194     if isinstance(symbol, int):
195         return symbol
196 
197     try:
198         return int(symbol, 0)
199     except:
200         pass
201 
202     try:
203         symbol_obj = gdb.lookup_symbol(symbol)[0]
204         if symbol_obj:
205             return int(symbol_obj.value().address)
206     except Exception:
207         pass
208 
209     try:
210         result = gdb.execute('info address %s' % symbol, to_string=True, from_tty=False)
211         address = int(re.search('0x[0-9a-fA-F]+', result).group(), 0)
212 
213         # The address found should lie in one of the memory maps
214         # There are cases when GDB shows offsets e.g.:
215         # pwndbg> info address tcache
216         # Symbol "tcache" is a thread-local variable at offset 0x40
217         # in the thread-local storage for `/lib/x86_64-linux-gnu/libc.so.6'.
218         if not allow_unmapped and not pwndbg.vmmap.find(address):
219             return None
220 
221         return address
222 
223     except gdb.error:
224         return None
225 
226     try:
227         address = pwndbg.ida.LocByName(symbol)
228         if address:
229             return address
230     except Exception:
231         pass
232 
233 @pwndbg.events.stop
234 @pwndbg.memoize.reset_on_start
235 def add_main_exe_to_symbols():
236     if not pwndbg.remote.is_remote():
237         return
238 
239     if pwndbg.android.is_android():
240         return
241 
242     exe  = pwndbg.elf.exe()
243 
244     if not exe:
245         return
246 
247     addr = exe.address
248 
249     if not addr:
250         return
251 
252     addr = int(addr)
253 
254     mmap = pwndbg.vmmap.find(addr)
255     if not mmap:
256         return
257 
258     path = mmap.objfile
259     if path and (pwndbg.arch.endian == pwndbg.arch.native_endian):
260         try:
261             gdb.execute('add-symbol-file %s %#x' % (path, addr), from_tty=False, to_string=True)
262         except gdb.error:
263             pass
264 
265 
266 @pwndbg.memoize.reset_on_stop
267 @pwndbg.memoize.reset_on_start
268 def selected_frame_source_absolute_filename():
269     """
270     Retrieve the symbol table’s source absolute file name from the selected frame.
271 
272     In case of missing symbol table or frame information, None is returned.
273     """
274     try:
275         frame = gdb.selected_frame()
276     except gdb.error:
277         return None
278 
279     if not frame:
280         return None
281 
282     sal = frame.find_sal()
283     if not sal:
284         return None
285 
286     symtab = sal.symtab
287     if not symtab:
288         return None
289 
290     return symtab.fullname()
291 
292 
293 if '/usr/lib/debug' not in get_directory():
294     set_directory(get_directory() + ':/usr/lib/debug')
295
```
--- 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/symbol.py b/pwndbg/symbol.py
--- a/pwndbg/symbol.py
+++ b/pwndbg/symbol.py
@@ -258,7 +258,7 @@
     path = mmap.objfile
     if path and (pwndbg.arch.endian == pwndbg.arch.native_endian):
         try:
-            gdb.execute('add-symbol-file %s %#x' % (path, addr), from_tty=False, to_string=True)
+            gdb.execute('add-symbol-file %s' % (path,), from_tty=False, to_string=True)
         except gdb.error:
             pass

{"golden_diff": "diff --git a/pwndbg/symbol.py b/pwndbg/symbol.py\n--- a/pwndbg/symbol.py\n+++ b/pwndbg/symbol.py\n@@ -258,7 +258,7 @@\n     path = mmap.objfile\n     if path and (pwndbg.arch.endian == pwndbg.arch.native_endian):\n         try:\n-            gdb.execute('add-symbol-file %s %#x' % (path, addr), from_tty=False, to_string=True)\n+            gdb.execute('add-symbol-file %s' % (path,), from_tty=False, to_string=True)\n         except gdb.error:\n             pass\n", "issue": "add-symbol-file should not specify a base address\nThis happens when connecting to a remote target:\r\n```\r\nhacker@babyrop_level10:~$ gdb -ex 'target remote :1234'\r\n...\r\nadd-symbol-file /tmp/tmp_yea7f3g/babyrop_level10.0 0x555555554000\r\n...\r\npwndbg> b main\r\nBreakpoint 1 at 0x555555555581 (2 locations)\r\npwndbg> info b\r\nNum     Type           Disp Enb Address            What\r\n1       breakpoint     keep y   <MULTIPLE>         \r\n1.1                         y   0x0000555555555581 <main>\r\n1.2                         y   0x00005555555567c1 \r\n```\r\nThis double breakpoint results in `\\xcc` bytes incorrectly polluting memory, and I've seen this corrupt the GOT and crash my program as a result.\r\n\r\nhttps://github.com/pwndbg/pwndbg/blob/05036defa01d4d47bfad56867f53470a29fcdc89/pwndbg/symbol.py#L261\r\n\r\nWhy is the base address being specified here? According to the help info for `add-symbol-file`, if anything is specified for `[ADDR]`, it should be the location of the `.text` section.\r\n\r\n```\r\n(gdb) help add-symbol-file\r\nLoad symbols from FILE, assuming FILE has been dynamically loaded.\r\nUsage: add-symbol-file FILE [-readnow | -readnever] [-o OFF] [ADDR] [-s SECT-NAME SECT-ADDR]...\r\nADDR is the starting address of the file's text.\r\nEach '-s' argument provides a section name and address, and\r\nshould be specified if the data and bss segments are not contiguous\r\nwith the text.  SECT-NAME is a section name to be loaded at SECT-ADDR.\r\nOFF is an optional offset which is added to the default load addresses\r\nof all sections for which no other address was specified.\r\nThe '-readnow' option will cause GDB to read the entire symbol file\r\nimmediately.  This makes the command slower, but may make future operations\r\nfaster.\r\nThe '-readnever' option will prevent GDB from reading the symbol file's\r\nsymbolic debug information.\r\n```\r\n\r\nIf we just omit the address, `gdb` will automatically find the `.text` section and use that address. Things would probably fail if there isn't a `.text` section defined, but I'm not really sure what the correct solution would be in this case anyways.\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\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 os\nimport re\nimport shutil\nimport tempfile\n\nimport elftools.common.exceptions\nimport elftools.elf.constants\nimport elftools.elf.elffile\nimport elftools.elf.segments\nimport gdb\n\nimport pwndbg.arch\nimport pwndbg.elf\nimport pwndbg.events\nimport pwndbg.file\nimport pwndbg.ida\nimport pwndbg.memoize\nimport pwndbg.memory\nimport pwndbg.qemu\nimport pwndbg.remote\nimport pwndbg.stack\nimport pwndbg.vmmap\n\n\ndef get_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\ndef set_directory(d):\n    gdb.execute('set debug-file-directory %s' % d, to_string=True, from_tty=False)\n\ndef add_directory(d):\n    current = get_directory()\n    if current:\n        set_directory('%s:%s' % (current, d))\n    else:\n        set_directory(d)\n\nremote_files = {}\nremote_files_dir = None\n\n@pwndbg.events.exit\ndef reset_remote_files():\n    global remote_files\n    global remote_files_dir\n    remote_files = {}\n    if remote_files_dir is not None:\n        shutil.rmtree(remote_files_dir)\n        remote_files_dir = None\n\n@pwndbg.events.new_objfile\ndef autofetch():\n    \"\"\"\n    \"\"\"\n    global remote_files_dir\n    if not pwndbg.remote.is_remote():\n        return\n\n    if pwndbg.qemu.is_qemu_usermode():\n        return\n\n    if pwndbg.android.is_android():\n        return\n\n    if not remote_files_dir:\n        remote_files_dir = tempfile.mkdtemp()\n        add_directory(remote_files_dir)\n\n    searchpath = get_directory()\n\n    for mapping in pwndbg.vmmap.get():\n        objfile = mapping.objfile\n\n        # Don't attempt to download things like '[stack]' and '[heap]'\n        if not objfile.startswith('/'):\n            continue\n\n        # Don't re-download things that we have already downloaded\n        if not objfile or objfile in remote_files:\n            continue\n\n        msg = \"Downloading %r from the remote server\" % objfile\n        print(msg, end='')\n\n        try:\n            data = pwndbg.file.get(objfile)\n            print('\\r' + msg + ': OK')\n        except OSError:\n            # The file could not be downloaded :(\n            print('\\r' + msg + ': Failed')\n            return\n\n        filename = os.path.basename(objfile)\n        local_path = os.path.join(remote_files_dir, filename)\n\n        with open(local_path, 'wb+') as f:\n            f.write(data)\n\n        remote_files[objfile] = local_path\n\n        base = None\n        for mapping in pwndbg.vmmap.get():\n            if mapping.objfile != objfile:\n                continue\n\n            if base is None or mapping.vaddr < base.vaddr:\n                base = mapping\n\n        if not base:\n            continue\n\n        base = base.vaddr\n\n        try:\n            elf = elftools.elf.elffile.ELFFile(open(local_path, 'rb'))\n        except elftools.common.exceptions.ELFError:\n            continue\n\n        gdb_command = ['add-symbol-file', local_path, hex(int(base))]\n        for section in elf.iter_sections():\n            name = section.name #.decode('latin-1')\n            section = section.header\n            if not section.sh_flags & elftools.elf.constants.SH_FLAGS.SHF_ALLOC:\n                continue\n            gdb_command += ['-s', name, hex(int(base + section.sh_addr))]\n\n        print(' '.join(gdb_command))\n        # gdb.execute(' '.join(gdb_command), from_tty=False, to_string=True)\n\n@pwndbg.memoize.reset_on_objfile\ndef get(address, gdb_only=False):\n    \"\"\"\n    Retrieve the textual name for a symbol\n    \"\"\"\n    # Fast path\n    if address < pwndbg.memory.MMAP_MIN_ADDR or address >= ((1 << 64)-1):\n        return ''\n\n    # Don't look up stack addresses\n    if pwndbg.stack.find(address):\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.elf.exe()\n        if exe:\n            exe_map = pwndbg.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    # Expected format 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    a, b, c, _ = result.split(None, 3)\n\n\n    if b == '+':\n        return \"%s+%s\" % (a, c)\n    if b == 'in':\n        return a\n\n    return ''\n\n@pwndbg.memoize.reset_on_objfile\ndef address(symbol, allow_unmapped=False):\n    if isinstance(symbol, int):\n        return symbol\n\n    try:\n        return int(symbol, 0)\n    except:\n        pass\n\n    try:\n        symbol_obj = gdb.lookup_symbol(symbol)[0]\n        if symbol_obj:\n            return int(symbol_obj.value().address)\n    except Exception:\n        pass\n\n    try:\n        result = gdb.execute('info address %s' % symbol, to_string=True, from_tty=False)\n        address = int(re.search('0x[0-9a-fA-F]+', result).group(), 0)\n\n        # The address found should lie in one of the memory maps\n        # There are cases when GDB shows offsets e.g.:\n        # pwndbg> info address tcache\n        # Symbol \"tcache\" is a thread-local variable at offset 0x40\n        # in the thread-local storage for `/lib/x86_64-linux-gnu/libc.so.6'.\n        if not allow_unmapped and not pwndbg.vmmap.find(address):\n            return None\n\n        return address\n\n    except gdb.error:\n        return None\n\n    try:\n        address = pwndbg.ida.LocByName(symbol)\n        if address:\n            return address\n    except Exception:\n        pass\n\n@pwndbg.events.stop\n@pwndbg.memoize.reset_on_start\ndef add_main_exe_to_symbols():\n    if not pwndbg.remote.is_remote():\n        return\n\n    if pwndbg.android.is_android():\n        return\n\n    exe  = pwndbg.elf.exe()\n\n    if not exe:\n        return\n\n    addr = exe.address\n\n    if not addr:\n        return\n\n    addr = int(addr)\n\n    mmap = pwndbg.vmmap.find(addr)\n    if not mmap:\n        return\n\n    path = mmap.objfile\n    if path and (pwndbg.arch.endian == pwndbg.arch.native_endian):\n        try:\n            gdb.execute('add-symbol-file %s %#x' % (path, addr), from_tty=False, to_string=True)\n        except gdb.error:\n            pass\n\n\n@pwndbg.memoize.reset_on_stop\n@pwndbg.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\n\nif '/usr/lib/debug' not in get_directory():\n    set_directory(get_directory() + ':/usr/lib/debug')\n", "path": "pwndbg/symbol.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\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 os\nimport re\nimport shutil\nimport tempfile\n\nimport elftools.common.exceptions\nimport elftools.elf.constants\nimport elftools.elf.elffile\nimport elftools.elf.segments\nimport gdb\n\nimport pwndbg.arch\nimport pwndbg.elf\nimport pwndbg.events\nimport pwndbg.file\nimport pwndbg.ida\nimport pwndbg.memoize\nimport pwndbg.memory\nimport pwndbg.qemu\nimport pwndbg.remote\nimport pwndbg.stack\nimport pwndbg.vmmap\n\n\ndef get_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\ndef set_directory(d):\n    gdb.execute('set debug-file-directory %s' % d, to_string=True, from_tty=False)\n\ndef add_directory(d):\n    current = get_directory()\n    if current:\n        set_directory('%s:%s' % (current, d))\n    else:\n        set_directory(d)\n\nremote_files = {}\nremote_files_dir = None\n\n@pwndbg.events.exit\ndef reset_remote_files():\n    global remote_files\n    global remote_files_dir\n    remote_files = {}\n    if remote_files_dir is not None:\n        shutil.rmtree(remote_files_dir)\n        remote_files_dir = None\n\n@pwndbg.events.new_objfile\ndef autofetch():\n    \"\"\"\n    \"\"\"\n    global remote_files_dir\n    if not pwndbg.remote.is_remote():\n        return\n\n    if pwndbg.qemu.is_qemu_usermode():\n        return\n\n    if pwndbg.android.is_android():\n        return\n\n    if not remote_files_dir:\n        remote_files_dir = tempfile.mkdtemp()\n        add_directory(remote_files_dir)\n\n    searchpath = get_directory()\n\n    for mapping in pwndbg.vmmap.get():\n        objfile = mapping.objfile\n\n        # Don't attempt to download things like '[stack]' and '[heap]'\n        if not objfile.startswith('/'):\n            continue\n\n        # Don't re-download things that we have already downloaded\n        if not objfile or objfile in remote_files:\n            continue\n\n        msg = \"Downloading %r from the remote server\" % objfile\n        print(msg, end='')\n\n        try:\n            data = pwndbg.file.get(objfile)\n            print('\\r' + msg + ': OK')\n        except OSError:\n            # The file could not be downloaded :(\n            print('\\r' + msg + ': Failed')\n            return\n\n        filename = os.path.basename(objfile)\n        local_path = os.path.join(remote_files_dir, filename)\n\n        with open(local_path, 'wb+') as f:\n            f.write(data)\n\n        remote_files[objfile] = local_path\n\n        base = None\n        for mapping in pwndbg.vmmap.get():\n            if mapping.objfile != objfile:\n                continue\n\n            if base is None or mapping.vaddr < base.vaddr:\n                base = mapping\n\n        if not base:\n            continue\n\n        base = base.vaddr\n\n        try:\n            elf = elftools.elf.elffile.ELFFile(open(local_path, 'rb'))\n        except elftools.common.exceptions.ELFError:\n            continue\n\n        gdb_command = ['add-symbol-file', local_path, hex(int(base))]\n        for section in elf.iter_sections():\n            name = section.name #.decode('latin-1')\n            section = section.header\n            if not section.sh_flags & elftools.elf.constants.SH_FLAGS.SHF_ALLOC:\n                continue\n            gdb_command += ['-s', name, hex(int(base + section.sh_addr))]\n\n        print(' '.join(gdb_command))\n        # gdb.execute(' '.join(gdb_command), from_tty=False, to_string=True)\n\n@pwndbg.memoize.reset_on_objfile\ndef get(address, gdb_only=False):\n    \"\"\"\n    Retrieve the textual name for a symbol\n    \"\"\"\n    # Fast path\n    if address < pwndbg.memory.MMAP_MIN_ADDR or address >= ((1 << 64)-1):\n        return ''\n\n    # Don't look up stack addresses\n    if pwndbg.stack.find(address):\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.elf.exe()\n        if exe:\n            exe_map = pwndbg.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    # Expected format 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    a, b, c, _ = result.split(None, 3)\n\n\n    if b == '+':\n        return \"%s+%s\" % (a, c)\n    if b == 'in':\n        return a\n\n    return ''\n\n@pwndbg.memoize.reset_on_objfile\ndef address(symbol, allow_unmapped=False):\n    if isinstance(symbol, int):\n        return symbol\n\n    try:\n        return int(symbol, 0)\n    except:\n        pass\n\n    try:\n        symbol_obj = gdb.lookup_symbol(symbol)[0]\n        if symbol_obj:\n            return int(symbol_obj.value().address)\n    except Exception:\n        pass\n\n    try:\n        result = gdb.execute('info address %s' % symbol, to_string=True, from_tty=False)\n        address = int(re.search('0x[0-9a-fA-F]+', result).group(), 0)\n\n        # The address found should lie in one of the memory maps\n        # There are cases when GDB shows offsets e.g.:\n        # pwndbg> info address tcache\n        # Symbol \"tcache\" is a thread-local variable at offset 0x40\n        # in the thread-local storage for `/lib/x86_64-linux-gnu/libc.so.6'.\n        if not allow_unmapped and not pwndbg.vmmap.find(address):\n            return None\n\n        return address\n\n    except gdb.error:\n        return None\n\n    try:\n        address = pwndbg.ida.LocByName(symbol)\n        if address:\n            return address\n    except Exception:\n        pass\n\n@pwndbg.events.stop\n@pwndbg.memoize.reset_on_start\ndef add_main_exe_to_symbols():\n    if not pwndbg.remote.is_remote():\n        return\n\n    if pwndbg.android.is_android():\n        return\n\n    exe  = pwndbg.elf.exe()\n\n    if not exe:\n        return\n\n    addr = exe.address\n\n    if not addr:\n        return\n\n    addr = int(addr)\n\n    mmap = pwndbg.vmmap.find(addr)\n    if not mmap:\n        return\n\n    path = mmap.objfile\n    if path and (pwndbg.arch.endian == pwndbg.arch.native_endian):\n        try:\n            gdb.execute('add-symbol-file %s' % (path,), from_tty=False, to_string=True)\n        except gdb.error:\n            pass\n\n\n@pwndbg.memoize.reset_on_stop\n@pwndbg.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\n\nif '/usr/lib/debug' not in get_directory():\n    set_directory(get_directory() + ':/usr/lib/debug')\n", "path": "pwndbg/symbol.py"}]}