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