]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/solib-rocm.c
gdb: move a bunch of quit-related things to event-top.{c,h}
[thirdparty/binutils-gdb.git] / gdb / solib-rocm.c
CommitLineData
18b4d073
SM
1/* Handle ROCm Code Objects for GDB, the GNU Debugger.
2
1d506c26 3 Copyright (C) 2019-2024 Free Software Foundation, Inc.
18b4d073
SM
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
18b4d073
SM
20
21#include "amd-dbgapi-target.h"
22#include "amdgpu-tdep.h"
23#include "arch-utils.h"
24#include "elf-bfd.h"
25#include "elf/amdgpu.h"
e5dc0d5d 26#include "event-top.h"
18b4d073
SM
27#include "gdbsupport/fileio.h"
28#include "inferior.h"
29#include "observable.h"
30#include "solib.h"
31#include "solib-svr4.h"
32#include "solist.h"
33#include "symfile.h"
34
1c850ca8
LS
35#include <unordered_map>
36
37namespace {
38
39/* Per inferior cache of opened file descriptors. */
40struct rocm_solib_fd_cache
41{
42 explicit rocm_solib_fd_cache (inferior *inf) : m_inferior (inf) {}
43 DISABLE_COPY_AND_ASSIGN (rocm_solib_fd_cache);
44
45 /* Return a read-only file descriptor to FILENAME and increment the
46 associated reference count.
47
48 Open the file FILENAME if it is not already opened, reuse the existing file
49 descriptor otherwise.
50
51 On error -1 is returned, and TARGET_ERRNO is set. */
52 int open (const std::string &filename, fileio_error *target_errno);
53
54 /* Decrement the reference count to FD and close FD if the reference count
55 reaches 0.
56
57 On success, return 0. On error, return -1 and set TARGET_ERRNO. */
58 int close (int fd, fileio_error *target_errno);
59
60private:
61 struct refcnt_fd
62 {
63 DISABLE_COPY_AND_ASSIGN (refcnt_fd);
64 refcnt_fd (int fd, int refcnt) : fd (fd), refcnt (refcnt) {}
65
66 int fd = -1;
67 int refcnt = 0;
68 };
69
70 inferior *m_inferior;
71 std::unordered_map<std::string, refcnt_fd> m_cache;
72};
73
74int
75rocm_solib_fd_cache::open (const std::string &filename,
76 fileio_error *target_errno)
77{
78 auto it = m_cache.find (filename);
79 if (it == m_cache.end ())
80 {
81 /* The file is not yet opened on the target. */
82 int fd
83 = target_fileio_open (m_inferior, filename.c_str (), FILEIO_O_RDONLY,
84 false, 0, target_errno);
85 if (fd != -1)
86 m_cache.emplace (std::piecewise_construct,
87 std::forward_as_tuple (filename),
88 std::forward_as_tuple (fd, 1));
89 return fd;
90 }
91 else
92 {
93 /* The file is already opened. Increment the refcnt and return the
94 already opened FD. */
95 it->second.refcnt++;
96 gdb_assert (it->second.fd != -1);
97 return it->second.fd;
98 }
99}
100
101int
102rocm_solib_fd_cache::close (int fd, fileio_error *target_errno)
103{
104 using cache_val = std::unordered_map<std::string, refcnt_fd>::value_type;
105 auto it
106 = std::find_if (m_cache.begin (), m_cache.end (),
107 [fd](const cache_val &s) { return s.second.fd == fd; });
108
109 gdb_assert (it != m_cache.end ());
110
111 it->second.refcnt--;
112 if (it->second.refcnt == 0)
113 {
114 int ret = target_fileio_close (it->second.fd, target_errno);
115 m_cache.erase (it);
116 return ret;
117 }
118 else
119 {
120 /* Keep the FD open for the other users, return success. */
121 return 0;
122 }
123}
124
125} /* Anonymous namespace. */
126
18b4d073
SM
127/* ROCm-specific inferior data. */
128
5340140e
SM
129struct rocm_so
130{
131 rocm_so (const char *name, std::string unique_name, lm_info_svr4_up lm_info)
132 : name (name),
133 unique_name (std::move (unique_name)),
134 lm_info (std::move (lm_info))
135 {}
136
137 std::string name, unique_name;
138 lm_info_svr4_up lm_info;
139};
140
18b4d073
SM
141struct solib_info
142{
1c850ca8 143 explicit solib_info (inferior *inf)
5340140e 144 : fd_cache (inf)
1c850ca8
LS
145 {};
146
18b4d073 147 /* List of code objects loaded into the inferior. */
5340140e 148 std::vector<rocm_so> solib_list;
1c850ca8
LS
149
150 /* Cache of opened FD in the inferior. */
151 rocm_solib_fd_cache fd_cache;
18b4d073
SM
152};
153
154/* Per-inferior data key. */
155static const registry<inferior>::key<solib_info> rocm_solib_data;
156
6cedf3bc 157static solib_ops rocm_solib_ops;
18b4d073 158
18b4d073
SM
159/* Fetch the solib_info data for INF. */
160
161static struct solib_info *
162get_solib_info (inferior *inf)
163{
164 solib_info *info = rocm_solib_data.get (inf);
165
166 if (info == nullptr)
1c850ca8 167 info = rocm_solib_data.emplace (inf, inf);
18b4d073
SM
168
169 return info;
170}
171
172/* Relocate section addresses. */
173
174static void
7b323785 175rocm_solib_relocate_section_addresses (solib &so,
18b4d073
SM
176 struct target_section *sec)
177{
200b8563 178 if (!is_amdgpu_arch (gdbarch_from_bfd (so.abfd.get ())))
18b4d073
SM
179 {
180 svr4_so_ops.relocate_section_addresses (so, sec);
181 return;
182 }
183
7ad0a42e 184 auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
18b4d073
SM
185 sec->addr = sec->addr + li->l_addr;
186 sec->endaddr = sec->endaddr + li->l_addr;
187}
188
189static void rocm_update_solib_list ();
190
191static void
192rocm_solib_handle_event ()
193{
194 /* Since we sit on top of svr4_so_ops, we might get called following an event
195 concerning host libraries. We must therefore forward the call. If the
196 event was for a ROCm code object, it will be a no-op. On the other hand,
197 if the event was for host libraries, rocm_update_solib_list will be
198 essentially be a no-op (it will reload the same code object list as was
199 previously loaded). */
200 svr4_so_ops.handle_event ();
201
202 rocm_update_solib_list ();
203}
204
5340140e 205/* Create so_list objects from rocm_so objects in SOS. */
18b4d073 206
7b323785 207static intrusive_list<solib>
5340140e 208so_list_from_rocm_sos (const std::vector<rocm_so> &sos)
18b4d073 209{
7b323785 210 intrusive_list<solib> dst;
18b4d073 211
5340140e 212 for (const rocm_so &so : sos)
18b4d073 213 {
7b323785 214 solib *newobj = new solib;
6b62451a 215 newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
5340140e 216
98107b0b
SM
217 newobj->so_name = so.name;
218 newobj->so_original_name = so.unique_name;
18b4d073 219
8971d278 220 dst.push_back (*newobj);
18b4d073
SM
221 }
222
223 return dst;
224}
225
7b323785 226/* Build a list of `struct solib' objects describing the shared
18b4d073
SM
227 objects currently loaded in the inferior. */
228
7b323785 229static intrusive_list<solib>
18b4d073
SM
230rocm_solib_current_sos ()
231{
232 /* First, retrieve the host-side shared library list. */
7b323785 233 intrusive_list<solib> sos = svr4_so_ops.current_sos ();
18b4d073
SM
234
235 /* Then, the device-side shared library list. */
5340140e 236 std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;
18b4d073 237
5340140e 238 if (dev_sos.empty ())
8971d278 239 return sos;
18b4d073 240
7b323785 241 intrusive_list<solib> dev_so_list = so_list_from_rocm_sos (dev_sos);
18b4d073 242
8971d278 243 if (sos.empty ())
5340140e 244 return dev_so_list;
18b4d073
SM
245
246 /* Append our libraries to the end of the list. */
8971d278 247 sos.splice (std::move (dev_so_list));
18b4d073 248
8971d278 249 return sos;
18b4d073
SM
250}
251
252namespace {
253
254/* Interface to interact with a ROCm code object stream. */
255
e537ccc2 256struct rocm_code_object_stream : public gdb_bfd_iovec_base
18b4d073
SM
257{
258 DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream);
259
e537ccc2 260 int stat (bfd *abfd, struct stat *sb) final override;
18b4d073 261
e537ccc2 262 ~rocm_code_object_stream () override = default;
18b4d073
SM
263
264protected:
265 rocm_code_object_stream () = default;
266
267 /* Return the size of the object file, or -1 if the size cannot be
268 determined.
269
270 This is a helper function for stat. */
271 virtual LONGEST size () = 0;
272};
273
274int
e537ccc2 275rocm_code_object_stream::stat (bfd *, struct stat *sb)
18b4d073
SM
276{
277 const LONGEST size = this->size ();
278 if (size == -1)
279 return -1;
280
281 memset (sb, '\0', sizeof (struct stat));
282 sb->st_size = size;
283 return 0;
284}
285
286/* Interface to a ROCm object stream which is embedded in an ELF file
287 accessible to the debugger. */
288
289struct rocm_code_object_stream_file final : rocm_code_object_stream
290{
291 DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream_file);
292
1c850ca8
LS
293 rocm_code_object_stream_file (inferior *inf, int fd, ULONGEST offset,
294 ULONGEST size);
18b4d073 295
e537ccc2
TT
296 file_ptr read (bfd *abfd, void *buf, file_ptr size,
297 file_ptr offset) override;
18b4d073
SM
298
299 LONGEST size () override;
300
301 ~rocm_code_object_stream_file () override;
302
303protected:
304
1c850ca8
LS
305 /* The inferior owning this code object stream. */
306 inferior *m_inf;
307
18b4d073
SM
308 /* The target file descriptor for this stream. */
309 int m_fd;
310
311 /* The offset of the ELF file image in the target file. */
312 ULONGEST m_offset;
313
314 /* The size of the ELF file image. The value 0 means that it was
315 unspecified in the URI descriptor. */
316 ULONGEST m_size;
317};
318
319rocm_code_object_stream_file::rocm_code_object_stream_file
1c850ca8
LS
320 (inferior *inf, int fd, ULONGEST offset, ULONGEST size)
321 : m_inf (inf), m_fd (fd), m_offset (offset), m_size (size)
18b4d073
SM
322{
323}
324
325file_ptr
e537ccc2 326rocm_code_object_stream_file::read (bfd *, void *buf, file_ptr size,
18b4d073
SM
327 file_ptr offset)
328{
329 fileio_error target_errno;
330 file_ptr nbytes = 0;
331 while (size > 0)
332 {
333 QUIT;
334
335 file_ptr bytes_read
336 = target_fileio_pread (m_fd, static_cast<gdb_byte *> (buf) + nbytes,
337 size, m_offset + offset + nbytes,
338 &target_errno);
339
340 if (bytes_read == 0)
341 break;
342
343 if (bytes_read < 0)
344 {
345 errno = fileio_error_to_host (target_errno);
346 bfd_set_error (bfd_error_system_call);
347 return -1;
348 }
349
350 nbytes += bytes_read;
351 size -= bytes_read;
352 }
353
354 return nbytes;
355}
356
357LONGEST
358rocm_code_object_stream_file::size ()
359{
360 if (m_size == 0)
361 {
362 fileio_error target_errno;
363 struct stat stat;
364 if (target_fileio_fstat (m_fd, &stat, &target_errno) < 0)
365 {
366 errno = fileio_error_to_host (target_errno);
367 bfd_set_error (bfd_error_system_call);
368 return -1;
369 }
370
371 /* Check that the offset is valid. */
372 if (m_offset >= stat.st_size)
373 {
374 bfd_set_error (bfd_error_bad_value);
375 return -1;
376 }
377
378 m_size = stat.st_size - m_offset;
379 }
380
381 return m_size;
382}
383
384rocm_code_object_stream_file::~rocm_code_object_stream_file ()
385{
1c850ca8 386 auto info = get_solib_info (m_inf);
18b4d073 387 fileio_error target_errno;
1c850ca8
LS
388 if (info->fd_cache.close (m_fd, &target_errno) != 0)
389 warning (_("Failed to close solib: %s"),
390 strerror (fileio_error_to_host (target_errno)));
18b4d073
SM
391}
392
393/* Interface to a code object which lives in the inferior's memory. */
394
395struct rocm_code_object_stream_memory final : public rocm_code_object_stream
396{
397 DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream_memory);
398
399 rocm_code_object_stream_memory (gdb::byte_vector buffer);
400
e537ccc2
TT
401 file_ptr read (bfd *abfd, void *buf, file_ptr size,
402 file_ptr offset) override;
18b4d073
SM
403
404protected:
405
406 /* Snapshot of the original ELF image taken during load. This is done to
407 support the situation where an inferior uses an in-memory image, and
408 releases or re-uses this memory before GDB is done using it. */
409 gdb::byte_vector m_objfile_image;
410
411 LONGEST size () override
412 {
413 return m_objfile_image.size ();
414 }
415};
416
417rocm_code_object_stream_memory::rocm_code_object_stream_memory
418 (gdb::byte_vector buffer)
419 : m_objfile_image (std::move (buffer))
420{
421}
422
423file_ptr
e537ccc2 424rocm_code_object_stream_memory::read (bfd *, void *buf, file_ptr size,
18b4d073
SM
425 file_ptr offset)
426{
427 if (size > m_objfile_image.size () - offset)
428 size = m_objfile_image.size () - offset;
429
430 memcpy (buf, m_objfile_image.data () + offset, size);
431 return size;
432}
433
434} /* anonymous namespace */
435
e537ccc2
TT
436static gdb_bfd_iovec_base *
437rocm_bfd_iovec_open (bfd *abfd, inferior *inferior)
18b4d073 438{
8082468f
LS
439 std::string_view uri (bfd_get_filename (abfd));
440 std::string_view protocol_delim = "://";
18b4d073 441 size_t protocol_end = uri.find (protocol_delim);
882b0505 442 std::string protocol (uri.substr (0, protocol_end));
18b4d073
SM
443 protocol_end += protocol_delim.length ();
444
445 std::transform (protocol.begin (), protocol.end (), protocol.begin (),
446 [] (unsigned char c) { return std::tolower (c); });
447
8082468f 448 std::string_view path;
18b4d073
SM
449 size_t path_end = uri.find_first_of ("#?", protocol_end);
450 if (path_end != std::string::npos)
451 path = uri.substr (protocol_end, path_end++ - protocol_end);
452 else
453 path = uri.substr (protocol_end);
454
455 /* %-decode the string. */
456 std::string decoded_path;
457 decoded_path.reserve (path.length ());
458 for (size_t i = 0; i < path.length (); ++i)
459 if (path[i] == '%'
460 && i < path.length () - 2
461 && std::isxdigit (path[i + 1])
462 && std::isxdigit (path[i + 2]))
463 {
8082468f 464 std::string_view hex_digits = path.substr (i + 1, 2);
882b0505 465 decoded_path += std::stoi (std::string (hex_digits), 0, 16);
18b4d073
SM
466 i += 2;
467 }
468 else
469 decoded_path += path[i];
470
471 /* Tokenize the query/fragment. */
8082468f 472 std::vector<std::string_view> tokens;
18b4d073
SM
473 size_t pos, last = path_end;
474 while ((pos = uri.find ('&', last)) != std::string::npos)
475 {
476 tokens.emplace_back (uri.substr (last, pos - last));
477 last = pos + 1;
478 }
479
480 if (last != std::string::npos)
481 tokens.emplace_back (uri.substr (last));
482
483 /* Create a tag-value map from the tokenized query/fragment. */
8082468f 484 std::unordered_map<std::string_view, std::string_view,
18b4d073 485 gdb::string_view_hash> params;
8082468f 486 for (std::string_view token : tokens)
18b4d073
SM
487 {
488 size_t delim = token.find ('=');
489 if (delim != std::string::npos)
490 {
8082468f
LS
491 std::string_view tag = token.substr (0, delim);
492 std::string_view val = token.substr (delim + 1);
18b4d073
SM
493 params.emplace (tag, val);
494 }
495 }
496
497 try
498 {
499 ULONGEST offset = 0;
500 ULONGEST size = 0;
18b4d073 501
8082468f 502 auto try_strtoulst = [] (std::string_view v)
18b4d073
SM
503 {
504 errno = 0;
505 ULONGEST value = strtoulst (v.data (), nullptr, 0);
506 if (errno != 0)
507 {
508 /* The actual message doesn't matter, the exception is caught
09e5f695 509 below, transformed in a BFD error, and the message is lost. */
18b4d073
SM
510 error (_("Failed to parse integer."));
511 }
512
513 return value;
514 };
515
516 auto offset_it = params.find ("offset");
517 if (offset_it != params.end ())
518 offset = try_strtoulst (offset_it->second);
519
520 auto size_it = params.find ("size");
521 if (size_it != params.end ())
522 {
523 size = try_strtoulst (size_it->second);
524 if (size == 0)
525 error (_("Invalid size value"));
526 }
527
528 if (protocol == "file")
529 {
1c850ca8 530 auto info = get_solib_info (inferior);
18b4d073 531 fileio_error target_errno;
1c850ca8 532 int fd = info->fd_cache.open (decoded_path, &target_errno);
18b4d073
SM
533
534 if (fd == -1)
535 {
536 errno = fileio_error_to_host (target_errno);
537 bfd_set_error (bfd_error_system_call);
538 return nullptr;
539 }
540
1c850ca8
LS
541 return new rocm_code_object_stream_file (inferior, fd, offset,
542 size);
18b4d073
SM
543 }
544
545 if (protocol == "memory")
546 {
547 ULONGEST pid = try_strtoulst (path);
548 if (pid != inferior->pid)
549 {
550 warning (_("`%s': code object is from another inferior"),
882b0505 551 std::string (uri).c_str ());
18b4d073
SM
552 bfd_set_error (bfd_error_bad_value);
553 return nullptr;
554 }
555
556 gdb::byte_vector buffer (size);
557 if (target_read_memory (offset, buffer.data (), size) != 0)
558 {
559 warning (_("Failed to copy the code object from the inferior"));
560 bfd_set_error (bfd_error_bad_value);
561 return nullptr;
562 }
563
564 return new rocm_code_object_stream_memory (std::move (buffer));
565 }
566
567 warning (_("`%s': protocol not supported: %s"),
882b0505 568 std::string (uri).c_str (), protocol.c_str ());
18b4d073
SM
569 bfd_set_error (bfd_error_bad_value);
570 return nullptr;
571 }
572 catch (const gdb_exception_quit &ex)
573 {
574 set_quit_flag ();
575 bfd_set_error (bfd_error_bad_value);
576 return nullptr;
577 }
578 catch (const gdb_exception &ex)
579 {
580 bfd_set_error (bfd_error_bad_value);
581 return nullptr;
582 }
583}
584
18b4d073
SM
585static gdb_bfd_ref_ptr
586rocm_solib_bfd_open (const char *pathname)
587{
588 /* Handle regular files with SVR4 open. */
589 if (strstr (pathname, "://") == nullptr)
590 return svr4_so_ops.bfd_open (pathname);
591
e537ccc2
TT
592 auto open = [] (bfd *nbfd) -> gdb_bfd_iovec_base *
593 {
594 return rocm_bfd_iovec_open (nbfd, current_inferior ());
595 };
596
597 gdb_bfd_ref_ptr abfd = gdb_bfd_openr_iovec (pathname, "elf64-amdgcn", open);
18b4d073
SM
598
599 if (abfd == nullptr)
600 error (_("Could not open `%s' as an executable file: %s"), pathname,
601 bfd_errmsg (bfd_get_error ()));
602
603 /* Check bfd format. */
604 if (!bfd_check_format (abfd.get (), bfd_object))
605 error (_("`%s': not in executable format: %s"),
606 bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
607
608 unsigned char osabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
609 unsigned char osabiversion = elf_elfheader (abfd)->e_ident[EI_ABIVERSION];
610
611 /* Check that the code object is using the HSA OS ABI. */
612 if (osabi != ELFOSABI_AMDGPU_HSA)
613 error (_("`%s': ELF file OS ABI is not supported (%d)."),
614 bfd_get_filename (abfd.get ()), osabi);
615
616 /* We support HSA code objects V3 and greater. */
617 if (osabiversion < ELFABIVERSION_AMDGPU_HSA_V3)
618 error (_("`%s': ELF file HSA OS ABI version is not supported (%d)."),
619 bfd_get_filename (abfd.get ()), osabiversion);
620
540a5904
LS
621 /* For GDB to be able to use this solib, the exact AMDGPU processor type
622 must be supported by both BFD and the amd-dbgapi library. */
623 const unsigned char gfx_arch
624 = elf_elfheader (abfd)->e_flags & EF_AMDGPU_MACH ;
625 const bfd_arch_info_type *bfd_arch_info
626 = bfd_lookup_arch (bfd_arch_amdgcn, gfx_arch);
627
628 amd_dbgapi_architecture_id_t architecture_id;
629 amd_dbgapi_status_t dbgapi_query_arch
630 = amd_dbgapi_get_architecture (gfx_arch, &architecture_id);
631
632 if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS
633 || bfd_arch_info == nullptr)
634 {
635 if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS
636 && bfd_arch_info == nullptr)
637 {
638 /* Neither of the libraries knows about this arch, so we cannot
639 provide a human readable name for it. */
640 error (_("'%s': AMDGCN architecture %#02x is not supported."),
641 bfd_get_filename (abfd.get ()), gfx_arch);
642 }
643 else if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS)
644 {
645 gdb_assert (bfd_arch_info != nullptr);
646 error (_("'%s': AMDGCN architecture %s not supported by "
647 "amd-dbgapi."),
648 bfd_get_filename (abfd.get ()),
649 bfd_arch_info->printable_name);
650 }
651 else
652 {
653 gdb_assert (dbgapi_query_arch == AMD_DBGAPI_STATUS_SUCCESS);
654 char *arch_name;
655 if (amd_dbgapi_architecture_get_info
656 (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_NAME,
657 sizeof (arch_name), &arch_name) != AMD_DBGAPI_STATUS_SUCCESS)
658 error ("amd_dbgapi_architecture_get_info call failed for arch "
659 "%#02x.", gfx_arch);
660 gdb::unique_xmalloc_ptr<char> arch_name_cleaner (arch_name);
661
662 error (_("'%s': AMDGCN architecture %s not supported."),
663 bfd_get_filename (abfd.get ()),
664 arch_name);
665 }
666 }
667
668 gdb_assert (gdbarch_from_bfd (abfd.get ()) != nullptr);
669 gdb_assert (is_amdgpu_arch (gdbarch_from_bfd (abfd.get ())));
670
18b4d073
SM
671 return abfd;
672}
673
674static void
675rocm_solib_create_inferior_hook (int from_tty)
676{
5340140e 677 get_solib_info (current_inferior ())->solib_list.clear ();
18b4d073
SM
678
679 svr4_so_ops.solib_create_inferior_hook (from_tty);
680}
681
682static void
683rocm_update_solib_list ()
684{
685 inferior *inf = current_inferior ();
686
687 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (inf);
688 if (process_id.handle == AMD_DBGAPI_PROCESS_NONE.handle)
689 return;
690
691 solib_info *info = get_solib_info (inf);
692
5340140e
SM
693 info->solib_list.clear ();
694 std::vector<rocm_so> &sos = info->solib_list;
18b4d073
SM
695
696 amd_dbgapi_code_object_id_t *code_object_list;
697 size_t count;
698
699 amd_dbgapi_status_t status
700 = amd_dbgapi_process_code_object_list (process_id, &count,
701 &code_object_list, nullptr);
702 if (status != AMD_DBGAPI_STATUS_SUCCESS)
703 {
704 warning (_("amd_dbgapi_process_code_object_list failed (%s)"),
705 get_status_string (status));
706 return;
707 }
708
709 for (size_t i = 0; i < count; ++i)
710 {
711 CORE_ADDR l_addr;
712 char *uri_bytes;
713
714 status = amd_dbgapi_code_object_get_info
715 (code_object_list[i], AMD_DBGAPI_CODE_OBJECT_INFO_LOAD_ADDRESS,
716 sizeof (l_addr), &l_addr);
717 if (status != AMD_DBGAPI_STATUS_SUCCESS)
718 continue;
719
720 status = amd_dbgapi_code_object_get_info
721 (code_object_list[i], AMD_DBGAPI_CODE_OBJECT_INFO_URI_NAME,
722 sizeof (uri_bytes), &uri_bytes);
723 if (status != AMD_DBGAPI_STATUS_SUCCESS)
724 continue;
725
5340140e 726 gdb::unique_xmalloc_ptr<char> uri_bytes_holder (uri_bytes);
18b4d073 727
6b62451a 728 lm_info_svr4_up li = std::make_unique<lm_info_svr4> ();
5340140e 729 li->l_addr = l_addr;
18b4d073 730
5340140e
SM
731 /* Generate a unique name so that code objects with the same URI but
732 different load addresses are seen by gdb core as different shared
18b4d073 733 objects. */
5340140e
SM
734 std::string unique_name
735 = string_printf ("code_object_%ld", code_object_list[i].handle);
18b4d073 736
5340140e 737 sos.emplace_back (uri_bytes, std::move (unique_name), std::move (li));
18b4d073
SM
738 }
739
740 xfree (code_object_list);
741
742 if (rocm_solib_ops.current_sos == NULL)
743 {
744 /* Override what we need to. */
745 rocm_solib_ops = svr4_so_ops;
746 rocm_solib_ops.current_sos = rocm_solib_current_sos;
747 rocm_solib_ops.solib_create_inferior_hook
748 = rocm_solib_create_inferior_hook;
749 rocm_solib_ops.bfd_open = rocm_solib_bfd_open;
750 rocm_solib_ops.relocate_section_addresses
751 = rocm_solib_relocate_section_addresses;
752 rocm_solib_ops.handle_event = rocm_solib_handle_event;
753
754 /* Engage the ROCm so_ops. */
27b1f19f 755 set_gdbarch_so_ops (current_inferior ()->arch (), &rocm_solib_ops);
18b4d073
SM
756 }
757}
758
759static void
760rocm_solib_target_inferior_created (inferior *inf)
761{
5340140e
SM
762 get_solib_info (inf)->solib_list.clear ();
763
18b4d073
SM
764 rocm_update_solib_list ();
765
766 /* Force GDB to reload the solibs. */
767 current_inferior ()->pspace->clear_solib_cache ();
768 solib_add (nullptr, 0, auto_solib_add);
769}
770
771/* -Wmissing-prototypes */
772extern initialize_file_ftype _initialize_rocm_solib;
773
774void
775_initialize_rocm_solib ()
776{
777 /* The dependency on the amd-dbgapi exists because solib-rocm's
778 inferior_created observer needs amd-dbgapi to have attached the process,
779 which happens in amd_dbgapi_target's inferior_created observer. */
780 gdb::observers::inferior_created.attach
781 (rocm_solib_target_inferior_created,
782 "solib-rocm",
783 { &get_amd_dbgapi_target_inferior_created_observer_token () });
784}