Make find_thread_ptid lookup thread map instead of iterate
[deliverable/binutils-gdb.git] / gdb / solib-rocm.c
CommitLineData
5922befa
LM
1/* Handle ROCm Code Objects for GDB, the GNU Debugger.
2
4e5106e6
LM
3 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
5922befa
LM
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21#include "defs.h"
22
23#include "arch-utils.h"
24#include "elf-bfd.h"
25#include "gdbcore.h"
26#include "inferior.h"
27#include "objfiles.h"
28#include "observable.h"
29#include "rocm-tdep.h"
30#include "solib-svr4.h"
31#include "solib.h"
32#include "solist.h"
33#include "symfile.h"
34
35#include <functional>
36#include <string>
37
66388092 38#define ROCM_DSO_NAME_PREFIX "AMDGPU shared object [loaded from memory "
5922befa
LM
39
40#define ROCM_DSO_NAME_SUFFIX "]"
41
42/* ROCm-specific inferior data. */
43
44struct solib_info
45{
46 /* List of code objects loaded into the inferior. */
47 struct so_list *solib_list;
48};
49
50/* Per-inferior data key. */
51static const struct inferior_key<solib_info> rocm_solib_data;
52
53struct target_so_ops rocm_solib_ops;
54
55/* Free the solib linked list. */
56
57static void
58rocm_free_solib_list (struct solib_info *info)
59{
60 while (info->solib_list != NULL)
61 {
62 struct so_list *next = info->solib_list->next;
63
64 free_so (info->solib_list);
65 info->solib_list = next;
66 }
67
68 info->solib_list = NULL;
69}
70
71/* Fetch the solib_info data for the current inferior. */
72
73static struct solib_info *
74get_solib_info (void)
75{
76 struct inferior *inf = current_inferior ();
77
78 struct solib_info *info = rocm_solib_data.get (inf);
79 if (info == NULL)
80 info = rocm_solib_data.emplace (inf);
81
82 return info;
83}
84
85/* Relocate section addresses. */
86
87static void
88rocm_solib_relocate_section_addresses (struct so_list *so,
89 struct target_section *sec)
90{
91 if (!rocm_is_amdgcn_gdbarch (gdbarch_from_bfd (so->abfd)))
92 {
93 svr4_so_ops.relocate_section_addresses (so, sec);
94 return;
95 }
96
97 lm_info_svr4 *li = (lm_info_svr4 *)so->lm_info;
98 sec->addr = sec->addr + li->l_addr;
99 sec->endaddr = sec->endaddr + li->l_addr;
100}
101
102/* Make a deep copy of the solib linked list. */
103
104static struct so_list *
105rocm_solib_copy_list (const struct so_list *src)
106{
107 struct so_list *dst = NULL;
108 struct so_list **link = &dst;
109
110 while (src != NULL)
111 {
112 struct so_list *newobj;
113
114 newobj = XNEW (struct so_list);
115 memcpy (newobj, src, sizeof (struct so_list));
116
117 lm_info_svr4 *src_li = (lm_info_svr4 *)src->lm_info;
118 newobj->lm_info = new lm_info_svr4 (*src_li);
119
120 newobj->next = NULL;
121 *link = newobj;
122 link = &newobj->next;
123
124 src = src->next;
125 }
126
127 return dst;
128}
129
130/* Build a list of `struct so_list' objects describing the shared
131 objects currently loaded in the inferior. */
132
133static struct so_list *
134rocm_solib_current_sos (void)
135{
136 /* First, retrieve the host-side shared library list. */
137 struct so_list *head = svr4_so_ops.current_sos ();
138
139 /* Then, the device-side shared library list. */
140 struct so_list *list = get_solib_info ()->solib_list;
141
142 if (!list)
143 return head;
144
145 list = rocm_solib_copy_list (list);
146
147 if (!head)
148 return list;
149
150 /* Append our libraries to the end of the list. */
151 struct so_list *tail;
152 for (tail = head; tail->next; tail = tail->next)
153 /* Nothing. */;
154 tail->next = list;
155
156 return head;
157}
158
159struct target_elf_image
160{
161 /* The base address of the ELF file image in the inferior's memory. */
162 CORE_ADDR base_addr;
163
164 /* The size of the ELF file image. */
165 ULONGEST size;
166};
167
168static void *
169rocm_bfd_iovec_open (bfd *nbfd, void *open_closure)
170{
171 return open_closure;
172}
173
174static int
175rocm_bfd_iovec_close (bfd *nbfd, void *stream)
176{
177 xfree (stream);
178 return 0;
179}
180
181static file_ptr
182rocm_bfd_iovec_pread (bfd *abfd, void *stream, void *buf, file_ptr nbytes,
183 file_ptr offset)
184{
185 CORE_ADDR addr = ((target_elf_image *)stream)->base_addr;
186
187 if (target_read_memory (addr + offset, (gdb_byte *)buf, nbytes) != 0)
188 {
189 bfd_set_error (bfd_error_invalid_operation);
190 return -1;
191 }
192
193 return nbytes;
194}
195
196static int
197rocm_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb)
198{
199 memset (sb, '\0', sizeof (struct stat));
200 sb->st_size = ((struct target_elf_image *)stream)->size;
201 return 0;
202}
203
204static gdb_bfd_ref_ptr
205rocm_solib_bfd_open (const char *pathname)
206{
207 struct target_elf_image *open_closure;
208 CORE_ADDR addr, end;
209
210 /* Handle regular SVR4 libraries. */
211 if (strstr (pathname, ROCM_DSO_NAME_PREFIX) != pathname)
212 return svr4_so_ops.bfd_open (pathname);
213
214 /* Decode the start and end addresses. */
215 if (sscanf (pathname + sizeof (ROCM_DSO_NAME_PREFIX) - 1, "0x%lx..0x%lx",
216 &addr, &end)
217 != 2)
218 internal_error (__FILE__, __LINE__, "ROCm-GDB Error: bad DSO name: `%s'",
219 pathname);
220
221 open_closure = XNEW (struct target_elf_image);
222 open_closure->base_addr = addr;
223 open_closure->size = end - addr;
224
225 gdb_bfd_ref_ptr abfd (gdb_bfd_openr_iovec (
226 pathname, "elf64-amdgcn", rocm_bfd_iovec_open, open_closure,
227 rocm_bfd_iovec_pread, rocm_bfd_iovec_close, rocm_bfd_iovec_stat));
228
229 /* Check bfd format. */
230 if (!bfd_check_format (abfd.get (), bfd_object))
231 error (_ ("`%s': not in executable format: %s"),
232 bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
233
234 unsigned char osabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
235 unsigned char osabiversion = elf_elfheader (abfd)->e_ident[EI_ABIVERSION];
236
237 /* Make a check if the code object in the elf is V3. ROCM-gdb has
238 support only for V3. */
239 if (osabi != ELFOSABI_AMDGPU_HSA)
240 error (_ ("`%s': ELF file OS ABI invalid (%d)."),
241 bfd_get_filename (abfd.get ()), osabi);
242
243 if (osabi == ELFOSABI_AMDGPU_HSA && osabiversion < 1)
244 error (_ ("`%s': ELF file ABI version (%d) is not supported."),
245 bfd_get_filename (abfd.get ()), osabiversion);
246
247 return abfd;
248}
249
250static void
251rocm_solib_create_inferior_hook (int from_tty)
252{
253 rocm_free_solib_list (get_solib_info ());
254
255 svr4_so_ops.solib_create_inferior_hook (from_tty);
256}
257
258static void
259rocm_update_solib_list ()
260{
261 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
262 solib_info *info = get_solib_info ();
263 amd_dbgapi_status_t status;
264
265 rocm_free_solib_list (info);
266 struct so_list **link = &info->solib_list;
267
268 amd_dbgapi_code_object_id_t *code_object_list;
269 size_t count;
270
271 if ((status = amd_dbgapi_code_object_list (process_id, &count,
272 &code_object_list, nullptr))
273 != AMD_DBGAPI_STATUS_SUCCESS)
274 {
275 warning (_ ("amd_dbgapi_code_object_list failed (%d)"), status);
276 return;
277 }
278
279 for (size_t i = 0; i < count; ++i)
280 {
281 struct so_list *so = XCNEW (struct so_list);
282 lm_info_svr4 *li = new lm_info_svr4;
283 so->lm_info = li;
284
285 char *uri_bytes;
286
287 if (amd_dbgapi_code_object_get_info (
288 process_id, code_object_list[i],
289 AMD_DBGAPI_CODE_OBJECT_INFO_LOAD_ADDRESS, sizeof (li->l_addr),
290 &li->l_addr)
291 != AMD_DBGAPI_STATUS_SUCCESS
292 || amd_dbgapi_code_object_get_info (
293 process_id, code_object_list[i],
294 AMD_DBGAPI_CODE_OBJECT_INFO_URI_NAME, sizeof (uri_bytes),
295 &uri_bytes)
296 != AMD_DBGAPI_STATUS_SUCCESS)
297 continue;
298
299 /* FIXME: We need to properly decode the URI. */
300
301 std::string uri (uri_bytes);
302 xfree (uri_bytes);
303
304 size_t address_pos = uri.find ("://");
305 if (address_pos == std::string::npos)
306 continue;
307 address_pos += 3;
308
309 size_t fragment_pos = uri.find ('#', address_pos);
310 if (address_pos == std::string::npos)
311 continue;
312
313 std::string fragment = uri.substr (fragment_pos);
314
315 /* Decode the offset and size. */
316 amd_dbgapi_global_address_t mem_addr;
317 amd_dbgapi_size_t mem_size;
318
319 if (sscanf (fragment.c_str (), "#offset=0x%lx&size=0x%lx", &mem_addr,
320 &mem_size)
321 != 2)
322 internal_error (__FILE__, __LINE__,
323 "ROCm-GDB Error: bad DSO name: `%s'", uri.c_str ());
324
325 xsnprintf (so->so_name, sizeof so->so_name,
326 ROCM_DSO_NAME_PREFIX "%s..%s" ROCM_DSO_NAME_SUFFIX,
327 hex_string (mem_addr), hex_string (mem_addr + mem_size));
328 strcpy (so->so_original_name, so->so_name);
329
330 so->next = nullptr;
331 *link = so;
332 link = &so->next;
333 }
334
335 xfree (code_object_list);
336
337 /* Force GDB to reload the solibs. */
338 clear_program_space_solib_cache (current_inferior ()->pspace);
339
340 /* Switch terminal for any messages produced by
341 breakpoint_re_set. */
342 target_terminal::ours_for_output ();
343
344 solib_add (NULL, 0, auto_solib_add);
345
346 /* Switch it back. */
347 target_terminal::inferior ();
348}
349
350static void
351rocm_solib_dbgapi_activated ()
352{
353 if (rocm_solib_ops.current_sos == NULL)
354 {
355 /* Override what we need to */
356 rocm_solib_ops = svr4_so_ops;
357 rocm_solib_ops.current_sos = rocm_solib_current_sos;
358 rocm_solib_ops.solib_create_inferior_hook
359 = rocm_solib_create_inferior_hook;
360 rocm_solib_ops.bfd_open = rocm_solib_bfd_open;
361 rocm_solib_ops.relocate_section_addresses
362 = rocm_solib_relocate_section_addresses;
363 }
364
365 /* Engage the ROCm so_ops. */
366 set_solib_ops (target_gdbarch (), &rocm_solib_ops);
367}
368
369static void
370rocm_solib_dbgapi_deactivated ()
371{
372 /* Disengage the ROCm so_ops. */
373 set_solib_ops (target_gdbarch (), &svr4_so_ops);
374}
375
376static void
377rocm_solib_target_inferior_created (struct target_ops *target, int from_tty)
378{
379 rocm_free_solib_list (get_solib_info ());
380 rocm_update_solib_list ();
381}
382
383/* -Wmissing-prototypes */
384extern initialize_file_ftype _initialize_rocm_solib;
385
386void
387_initialize_rocm_solib (void)
388{
389 /* Install our observers. */
390 amd_dbgapi_activated.attach (rocm_solib_dbgapi_activated);
391 amd_dbgapi_deactivated.attach (rocm_solib_dbgapi_deactivated);
392 amd_dbgapi_code_object_list_updated.attach (rocm_update_solib_list);
393
394 /* FIXME: remove this when we can clear the solist in
395 rocm_solib_create_inferior_hook. */
396 gdb::observers::inferior_created.attach (rocm_solib_target_inferior_created);
397}
This page took 0.039189 seconds and 4 git commands to generate.