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