26#include "elf/amdgpu.h"
27#include "gdbsupport/fileio.h"
35#include <unordered_map>
40struct rocm_solib_fd_cache
43 DISABLE_COPY_AND_ASSIGN (rocm_solib_fd_cache);
52 int open (
const std::string &filename, fileio_error *target_errno);
58 int close (
int fd, fileio_error *target_errno);
63 DISABLE_COPY_AND_ASSIGN (refcnt_fd);
64 refcnt_fd (
int fd,
int refcnt) : fd (fd), refcnt (refcnt) {}
71 std::unordered_map<std::string, refcnt_fd> m_cache;
75rocm_solib_fd_cache::open (
const std::string &filename,
76 fileio_error *target_errno)
78 auto it = m_cache.find (filename);
79 if (it == m_cache.end ())
84 false, 0, target_errno);
86 m_cache.emplace (std::piecewise_construct,
87 std::forward_as_tuple (filename),
88 std::forward_as_tuple (fd, 1));
96 gdb_assert (it->second.fd != -1);
102rocm_solib_fd_cache::close (
int fd, fileio_error *target_errno)
104 using cache_val = std::unordered_map<std::string, refcnt_fd>::value_type;
106 = std::find_if (m_cache.begin (), m_cache.end (),
107 [fd](
const cache_val &s) { return s.second.fd == fd; });
109 gdb_assert (it != m_cache.end ());
112 if (it->second.refcnt == 0)
152 while (info->solib_list !=
nullptr)
154 struct so_list *next = info->solib_list->next;
157 info->solib_list =
next;
160 info->solib_list =
nullptr;
218 while (src !=
nullptr)
222 newobj = XNEW (
struct so_list);
223 memcpy (newobj, src,
sizeof (
struct so_list));
228 newobj->
next =
nullptr;
230 link = &newobj->
next;
260 for (tail = head; tail->
next; tail = tail->
next)
273 DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream);
275 int stat (bfd *abfd,
struct stat *sb)
final override;
277 ~rocm_code_object_stream ()
override =
default;
280 rocm_code_object_stream () =
default;
286 virtual LONGEST
size () = 0;
290rocm_code_object_stream::stat (bfd *,
struct stat *sb)
296 memset (sb,
'\0',
sizeof (
struct stat));
304struct rocm_code_object_stream_file final : rocm_code_object_stream
306 DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream_file);
308 rocm_code_object_stream_file (
inferior *
inf,
int fd, ULONGEST offset,
311 file_ptr
read (bfd *abfd,
void *buf, file_ptr
size,
312 file_ptr offset)
override;
314 LONGEST
size ()
override;
316 ~rocm_code_object_stream_file ()
override;
334rocm_code_object_stream_file::rocm_code_object_stream_file
336 : m_inf (
inf), m_fd (fd), m_offset (offset), m_size (
size)
341rocm_code_object_stream_file::read (bfd *,
void *buf, file_ptr
size,
344 fileio_error target_errno;
352 size, m_offset + offset + nbytes,
360 errno = fileio_error_to_host (target_errno);
361 bfd_set_error (bfd_error_system_call);
365 nbytes += bytes_read;
373rocm_code_object_stream_file::size ()
377 fileio_error target_errno;
381 errno = fileio_error_to_host (target_errno);
382 bfd_set_error (bfd_error_system_call);
387 if (m_offset >= stat.st_size)
389 bfd_set_error (bfd_error_bad_value);
393 m_size = stat.st_size - m_offset;
399rocm_code_object_stream_file::~rocm_code_object_stream_file ()
402 fileio_error target_errno;
403 if (
info->fd_cache.close (m_fd, &target_errno) != 0)
404 warning (_(
"Failed to close solib: %s"),
405 strerror (fileio_error_to_host (target_errno)));
410struct rocm_code_object_stream_memory final :
public rocm_code_object_stream
412 DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream_memory);
414 rocm_code_object_stream_memory (gdb::byte_vector buffer);
416 file_ptr
read (bfd *abfd,
void *buf, file_ptr
size,
417 file_ptr offset)
override;
424 gdb::byte_vector m_objfile_image;
426 LONGEST
size ()
override
428 return m_objfile_image.size ();
432rocm_code_object_stream_memory::rocm_code_object_stream_memory
433 (gdb::byte_vector buffer)
434 : m_objfile_image (
std::move (buffer))
439rocm_code_object_stream_memory::read (bfd *,
void *buf, file_ptr
size,
442 if (
size > m_objfile_image.size () - offset)
443 size = m_objfile_image.size () - offset;
445 memcpy (buf, m_objfile_image.data () + offset,
size);
454 gdb::string_view uri (bfd_get_filename (abfd));
455 gdb::string_view protocol_delim =
"://";
456 size_t protocol_end = uri.find (protocol_delim);
457 std::string protocol = gdb::to_string (uri.substr (0, protocol_end));
458 protocol_end += protocol_delim.length ();
460 std::transform (protocol.begin (), protocol.end (), protocol.begin (),
461 [] (
unsigned char c) { return std::tolower (c); });
463 gdb::string_view path;
464 size_t path_end = uri.find_first_of (
"#?", protocol_end);
465 if (path_end != std::string::npos)
466 path = uri.substr (protocol_end, path_end++ - protocol_end);
468 path = uri.substr (protocol_end);
471 std::string decoded_path;
472 decoded_path.reserve (path.length ());
473 for (
size_t i = 0; i < path.length (); ++i)
475 && i < path.length () - 2
476 && std::isxdigit (path[i + 1])
477 && std::isxdigit (path[i + 2]))
479 gdb::string_view hex_digits = path.substr (i + 1, 2);
480 decoded_path += std::stoi (gdb::to_string (hex_digits), 0, 16);
484 decoded_path += path[i];
487 std::vector<gdb::string_view> tokens;
488 size_t pos, last = path_end;
489 while ((pos = uri.find (
'&', last)) != std::string::npos)
491 tokens.emplace_back (uri.substr (last, pos - last));
495 if (last != std::string::npos)
496 tokens.emplace_back (uri.substr (last));
499 std::unordered_map<gdb::string_view, gdb::string_view,
500 gdb::string_view_hash> params;
501 for (gdb::string_view
token : tokens)
503 size_t delim =
token.find (
'=');
504 if (delim != std::string::npos)
506 gdb::string_view tag =
token.substr (0, delim);
507 gdb::string_view val =
token.substr (delim + 1);
508 params.emplace (tag, val);
520 ULONGEST
value = strtoulst (v.data (),
nullptr, 0);
525 error (_(
"Failed to parse integer."));
531 auto offset_it = params.find (
"offset");
532 if (offset_it != params.end ())
535 auto size_it = params.find (
"size");
536 if (size_it != params.end ())
540 error (_(
"Invalid size value"));
543 if (protocol ==
"file")
546 fileio_error target_errno;
547 int fd = info->fd_cache.open (decoded_path, &target_errno);
551 errno = fileio_error_to_host (target_errno);
552 bfd_set_error (bfd_error_system_call);
556 return new rocm_code_object_stream_file (
inferior, fd, offset,
560 if (protocol ==
"memory")
565 warning (_(
"`%s': code object is from another inferior"),
566 gdb::to_string (uri).c_str ());
567 bfd_set_error (bfd_error_bad_value);
571 gdb::byte_vector buffer (
size);
574 warning (_(
"Failed to copy the code object from the inferior"));
575 bfd_set_error (bfd_error_bad_value);
579 return new rocm_code_object_stream_memory (std::move (buffer));
582 warning (_(
"`%s': protocol not supported: %s"),
583 gdb::to_string (uri).c_str (), protocol.c_str ());
584 bfd_set_error (bfd_error_bad_value);
587 catch (
const gdb_exception_quit &ex)
590 bfd_set_error (bfd_error_bad_value);
593 catch (
const gdb_exception &ex)
595 bfd_set_error (bfd_error_bad_value);
604 if (strstr (pathname,
"://") ==
nullptr)
615 error (_(
"Could not open `%s' as an executable file: %s"), pathname,
616 bfd_errmsg (bfd_get_error ()));
619 if (!bfd_check_format (abfd.get (), bfd_object))
620 error (_(
"`%s': not in executable format: %s"),
621 bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));
623 unsigned char osabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
624 unsigned char osabiversion = elf_elfheader (abfd)->e_ident[EI_ABIVERSION];
627 if (osabi != ELFOSABI_AMDGPU_HSA)
628 error (_(
"`%s': ELF file OS ABI is not supported (%d)."),
629 bfd_get_filename (abfd.get ()), osabi);
632 if (osabiversion < ELFABIVERSION_AMDGPU_HSA_V3)
633 error (_(
"`%s': ELF file HSA OS ABI version is not supported (%d)."),
634 bfd_get_filename (abfd.get ()), osabiversion);
638 const unsigned char gfx_arch
639 = elf_elfheader (abfd)->e_flags & EF_AMDGPU_MACH ;
640 const bfd_arch_info_type *bfd_arch_info
641 = bfd_lookup_arch (bfd_arch_amdgcn, gfx_arch);
643 amd_dbgapi_architecture_id_t architecture_id;
644 amd_dbgapi_status_t dbgapi_query_arch
645 = amd_dbgapi_get_architecture (gfx_arch, &architecture_id);
647 if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS
648 || bfd_arch_info ==
nullptr)
650 if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS
651 && bfd_arch_info ==
nullptr)
655 error (_(
"'%s': AMDGCN architecture %#02x is not supported."),
656 bfd_get_filename (abfd.get ()), gfx_arch);
658 else if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS)
660 gdb_assert (bfd_arch_info !=
nullptr);
661 error (_(
"'%s': AMDGCN architecture %s not supported by "
663 bfd_get_filename (abfd.get ()),
664 bfd_arch_info->printable_name);
668 gdb_assert (dbgapi_query_arch == AMD_DBGAPI_STATUS_SUCCESS);
670 if (amd_dbgapi_architecture_get_info
671 (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_NAME,
672 sizeof (arch_name), &arch_name) != AMD_DBGAPI_STATUS_SUCCESS)
673 error (
"amd_dbgapi_architecture_get_info call failed for arch "
675 gdb::unique_xmalloc_ptr<char> arch_name_cleaner (arch_name);
677 error (_(
"'%s': AMDGCN architecture %s not supported."),
678 bfd_get_filename (abfd.get ()),
703 if (process_id.handle == AMD_DBGAPI_PROCESS_NONE.handle)
709 struct so_list **link = &info->solib_list;
711 amd_dbgapi_code_object_id_t *code_object_list;
714 amd_dbgapi_status_t
status
715 = amd_dbgapi_process_code_object_list (process_id, &count,
716 &code_object_list,
nullptr);
717 if (
status != AMD_DBGAPI_STATUS_SUCCESS)
719 warning (_(
"amd_dbgapi_process_code_object_list failed (%s)"),
724 for (
size_t i = 0; i < count; ++i)
729 status = amd_dbgapi_code_object_get_info
730 (code_object_list[i], AMD_DBGAPI_CODE_OBJECT_INFO_LOAD_ADDRESS,
731 sizeof (l_addr), &l_addr);
732 if (
status != AMD_DBGAPI_STATUS_SUCCESS)
735 status = amd_dbgapi_code_object_get_info
736 (code_object_list[i], AMD_DBGAPI_CODE_OBJECT_INFO_URI_NAME,
737 sizeof (uri_bytes), &uri_bytes);
738 if (
status != AMD_DBGAPI_STATUS_SUCCESS)
754 "code_object_%ld", code_object_list[i].handle);
761 xfree (code_object_list);
amd_dbgapi_process_id_t get_amd_dbgapi_process_id(inferior *inf)
const gdb::observers::token & get_amd_dbgapi_target_inferior_created_observer_token()
static const char * get_status_string(amd_dbgapi_status_t status)
static ULONGEST try_strtoulst(gdb::string_view s)
bool is_amdgpu_arch(struct gdbarch *arch)
struct gdbarch * gdbarch_from_bfd(bfd *abfd)
struct program_space * pspace
void initialize_file_ftype(void)
ssize_t read(int fd, void *buf, size_t count)
gdb_bfd_ref_ptr gdb_bfd_openr_iovec(const char *filename, const char *target, gdb_iovec_opener_ftype open_fn)
gdb::ref_ptr< struct bfd, gdb_bfd_ref_policy > gdb_bfd_ref_ptr
void set_gdbarch_so_ops(struct gdbarch *gdbarch, const struct target_so_ops *so_ops)
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int status
struct inferior * current_inferior(void)
observable< inferior * > inferior_created
initialize_file_ftype _initialize_rocm_solib
static void rocm_solib_handle_event()
static gdb_bfd_ref_ptr rocm_solib_bfd_open(const char *pathname)
static struct solib_info * get_solib_info(inferior *inf)
static target_so_ops rocm_solib_ops
static const registry< inferior >::key< solib_info > rocm_solib_data
static void rocm_solib_create_inferior_hook(int from_tty)
static void rocm_solib_target_inferior_created(inferior *inf)
static struct so_list * rocm_solib_current_sos()
static so_list * rocm_solib_copy_list(const so_list *src)
static void rocm_solib_relocate_section_addresses(struct so_list *so, struct target_section *sec)
static gdb_bfd_iovec_base * rocm_bfd_iovec_open(bfd *abfd, inferior *inferior)
static void rocm_update_solib_list()
static void rocm_free_solib_list(struct solib_info *info)
const struct target_so_ops svr4_so_ops
void free_so(struct so_list *so)
void solib_add(const char *pattern, int from_tty, int readsyms)
char so_name[SO_NAME_MAX_PATH_SIZE]
char so_original_name[SO_NAME_MAX_PATH_SIZE]
rocm_solib_fd_cache fd_cache
solib_info(inferior *inf)
void(* solib_create_inferior_hook)(int from_tty)
void(* handle_event)(void)
struct so_list *(* current_sos)(void)
gdb_bfd_ref_ptr(* bfd_open)(const char *pathname)
void(* relocate_section_addresses)(struct so_list *so, struct target_section *)
int target_fileio_fstat(int fd, struct stat *sb, fileio_error *target_errno)
int target_fileio_open(struct inferior *inf, const char *filename, int flags, int mode, bool warn_if_slow, fileio_error *target_errno)
int target_fileio_close(int fd, fileio_error *target_errno)
int target_fileio_pread(int fd, gdb_byte *read_buf, int len, ULONGEST offset, fileio_error *target_errno)
int target_read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)