/* Handle ROCm Code Objects for GDB, the GNU Debugger.

   Copyright (C) 2019-2025 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


#include "amd-dbgapi-target.h"
#include "amdgpu-tdep.h"
#include "arch-utils.h"
#include "elf-bfd.h"
#include "elf/amdgpu.h"
#include "event-top.h"
#include "gdbsupport/fileio.h"
#include "inferior.h"
#include "observable.h"
#include "solib.h"
#include "solib-svr4.h"
#include "symfile.h"

#include <unordered_map>

namespace {

/* Per inferior cache of opened file descriptors.  */
struct rocm_solib_fd_cache
{
  explicit rocm_solib_fd_cache (inferior *inf) : m_inferior (inf) {}
  DISABLE_COPY_AND_ASSIGN (rocm_solib_fd_cache);

  /* Return a read-only file descriptor to FILENAME and increment the
     associated reference count.

     Open the file FILENAME if it is not already opened, reuse the existing file
     descriptor otherwise.

     On error -1 is returned, and TARGET_ERRNO is set.  */
  int open (const std::string &filename, fileio_error *target_errno);

  /* Decrement the reference count to FD and close FD if the reference count
     reaches 0.

     On success, return 0.  On error, return -1 and set TARGET_ERRNO.  */
  int close (int fd, fileio_error *target_errno);

private:
  struct refcnt_fd
  {
    DISABLE_COPY_AND_ASSIGN (refcnt_fd);
    refcnt_fd (int fd, int refcnt) : fd (fd), refcnt (refcnt) {}

    int fd = -1;
    int refcnt = 0;
  };

  inferior *m_inferior;
  std::unordered_map<std::string, refcnt_fd> m_cache;
};

int
rocm_solib_fd_cache::open (const std::string &filename,
			   fileio_error *target_errno)
{
  auto it = m_cache.find (filename);
  if (it == m_cache.end ())
    {
      /* The file is not yet opened on the target.  */
      int fd
	= target_fileio_open (m_inferior, filename.c_str (), FILEIO_O_RDONLY,
			      false, 0, target_errno);
      if (fd != -1)
	m_cache.emplace (std::piecewise_construct,
			 std::forward_as_tuple (filename),
			 std::forward_as_tuple (fd, 1));
      return fd;
    }
  else
    {
      /* The file is already opened.  Increment the refcnt and return the
	 already opened FD.  */
      it->second.refcnt++;
      gdb_assert (it->second.fd != -1);
      return it->second.fd;
    }
}

int
rocm_solib_fd_cache::close (int fd, fileio_error *target_errno)
{
  using cache_val = std::unordered_map<std::string, refcnt_fd>::value_type;
  auto it
    = std::find_if (m_cache.begin (), m_cache.end (),
		    [fd](const cache_val &s) { return s.second.fd == fd; });

  gdb_assert (it != m_cache.end ());

  it->second.refcnt--;
  if (it->second.refcnt == 0)
    {
      int ret = target_fileio_close (it->second.fd, target_errno);
      m_cache.erase (it);
      return ret;
    }
  else
    {
      /* Keep the FD open for the other users, return success.  */
      return 0;
    }
}

} /* Anonymous namespace.  */

/* ROCm-specific inferior data.  */

struct rocm_so
{
  rocm_so (const char *name, std::string unique_name, lm_info_svr4_up lm_info)
    : name (name),
      unique_name (std::move (unique_name)),
      lm_info (std::move (lm_info))
  {}

  std::string name, unique_name;
  lm_info_svr4_up lm_info;
};

struct solib_info
{
  explicit solib_info (inferior *inf)
    : fd_cache (inf)
  {};

  /* List of code objects loaded into the inferior.  */
  std::vector<rocm_so> solib_list;

  /* Cache of opened FD in the inferior.  */
  rocm_solib_fd_cache fd_cache;
};

/* Per-inferior data key.  */
static const registry<inferior>::key<solib_info> rocm_solib_data;

static solib_ops rocm_solib_ops;

/* Fetch the solib_info data for INF.  */

static struct solib_info *
get_solib_info (inferior *inf)
{
  solib_info *info = rocm_solib_data.get (inf);

  if (info == nullptr)
    info = rocm_solib_data.emplace (inf, inf);

  return info;
}

/* Relocate section addresses.  */

static void
rocm_solib_relocate_section_addresses (solib &so,
				       struct target_section *sec)
{
  if (!is_amdgpu_arch (gdbarch_from_bfd (so.abfd.get ())))
    {
      svr4_so_ops.relocate_section_addresses (so, sec);
      return;
    }

  auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
  sec->addr = sec->addr + li->l_addr;
  sec->endaddr = sec->endaddr + li->l_addr;
}

static void rocm_update_solib_list ();

static void
rocm_solib_handle_event ()
{
  /* Since we sit on top of svr4_so_ops, we might get called following an event
     concerning host libraries.  We must therefore forward the call.  If the
     event was for a ROCm code object, it will be a no-op.  On the other hand,
     if the event was for host libraries, rocm_update_solib_list will be
     essentially be a no-op (it will reload the same code object list as was
     previously loaded).  */
  svr4_so_ops.handle_event ();

  rocm_update_solib_list ();
}

/* Create solib objects from rocm_so objects in SOS.  */

static owning_intrusive_list<solib>
solibs_from_rocm_sos (const std::vector<rocm_so> &sos)
{
  owning_intrusive_list<solib> dst;

  for (const rocm_so &so : sos)
    {
      auto &newobj = dst.emplace_back ();

      newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
      newobj.name = so.name;
      newobj.original_name = so.unique_name;
    }

  return dst;
}

/* Build a list of `struct solib' objects describing the shared
   objects currently loaded in the inferior.  */

static owning_intrusive_list<solib>
rocm_solib_current_sos ()
{
  /* First, retrieve the host-side shared library list.  */
  owning_intrusive_list<solib> sos = svr4_so_ops.current_sos ();

  /* Then, the device-side shared library list.  */
  std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;

  if (dev_sos.empty ())
    return sos;

  owning_intrusive_list<solib> dev_solibs = solibs_from_rocm_sos (dev_sos);

  if (sos.empty ())
    return dev_solibs;

  /* Append our libraries to the end of the list.  */
  sos.splice (std::move (dev_solibs));

  return sos;
}

namespace {

/* Interface to interact with a ROCm code object stream.  */

struct rocm_code_object_stream : public gdb_bfd_iovec_base
{
  DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream);

  int stat (bfd *abfd, struct stat *sb) final override;

  ~rocm_code_object_stream () override = default;

protected:
  rocm_code_object_stream () = default;

  /* Return the size of the object file, or -1 if the size cannot be
     determined.

     This is a helper function for stat.  */
  virtual LONGEST size () = 0;
};

int
rocm_code_object_stream::stat (bfd *, struct stat *sb)
{
  const LONGEST size = this->size ();
  if (size == -1)
    return -1;

  memset (sb, '\0', sizeof (struct stat));
  sb->st_size = size;
  return 0;
}

/* Interface to a ROCm object stream which is embedded in an ELF file
   accessible to the debugger.  */

struct rocm_code_object_stream_file final : rocm_code_object_stream
{
  DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream_file);

  rocm_code_object_stream_file (inferior *inf, int fd, ULONGEST offset,
				ULONGEST size);

  file_ptr read (bfd *abfd, void *buf, file_ptr size,
		 file_ptr offset) override;

  LONGEST size () override;

  ~rocm_code_object_stream_file () override;

protected:

  /* The inferior owning this code object stream.  */
  inferior *m_inf;

  /* The target file descriptor for this stream.  */
  int m_fd;

  /* The offset of the ELF file image in the target file.  */
  ULONGEST m_offset;

  /* The size of the ELF file image.  The value 0 means that it was
     unspecified in the URI descriptor.  */
  ULONGEST m_size;
};

rocm_code_object_stream_file::rocm_code_object_stream_file
  (inferior *inf, int fd, ULONGEST offset, ULONGEST size)
  : m_inf (inf), m_fd (fd), m_offset (offset), m_size (size)
{
}

file_ptr
rocm_code_object_stream_file::read (bfd *, void *buf, file_ptr size,
				    file_ptr offset)
{
  fileio_error target_errno;
  file_ptr nbytes = 0;
  while (size > 0)
    {
      QUIT;

      file_ptr bytes_read
	= target_fileio_pread (m_fd, static_cast<gdb_byte *> (buf) + nbytes,
			       size, m_offset + offset + nbytes,
			       &target_errno);

      if (bytes_read == 0)
	break;

      if (bytes_read < 0)
	{
	  errno = fileio_error_to_host (target_errno);
	  bfd_set_error (bfd_error_system_call);
	  return -1;
	}

      nbytes += bytes_read;
      size -= bytes_read;
    }

  return nbytes;
}

LONGEST
rocm_code_object_stream_file::size ()
{
  if (m_size == 0)
    {
      fileio_error target_errno;
      struct stat stat;
      if (target_fileio_fstat (m_fd, &stat, &target_errno) < 0)
	{
	  errno = fileio_error_to_host (target_errno);
	  bfd_set_error (bfd_error_system_call);
	  return -1;
	}

      /* Check that the offset is valid.  */
      if (m_offset >= stat.st_size)
	{
	  bfd_set_error (bfd_error_bad_value);
	  return -1;
	}

      m_size = stat.st_size - m_offset;
    }

  return m_size;
}

rocm_code_object_stream_file::~rocm_code_object_stream_file ()
{
  auto info = get_solib_info (m_inf);
  fileio_error target_errno;
  if (info->fd_cache.close (m_fd, &target_errno) != 0)
    warning (_("Failed to close solib: %s"),
	     strerror (fileio_error_to_host (target_errno)));
}

/* Interface to a code object which lives in the inferior's memory.  */

struct rocm_code_object_stream_memory final : public rocm_code_object_stream
{
  DISABLE_COPY_AND_ASSIGN (rocm_code_object_stream_memory);

  rocm_code_object_stream_memory (gdb::byte_vector buffer);

  file_ptr read (bfd *abfd, void *buf, file_ptr size,
		 file_ptr offset) override;

protected:

  /* Snapshot of the original ELF image taken during load.  This is done to
     support the situation where an inferior uses an in-memory image, and
     releases or reuses this memory before GDB is done using it.  */
  gdb::byte_vector m_objfile_image;

  LONGEST size () override
  {
    return m_objfile_image.size ();
  }
};

rocm_code_object_stream_memory::rocm_code_object_stream_memory
  (gdb::byte_vector buffer)
  : m_objfile_image (std::move (buffer))
{
}

file_ptr
rocm_code_object_stream_memory::read (bfd *, void *buf, file_ptr size,
				      file_ptr offset)
{
  if (size > m_objfile_image.size () - offset)
    size = m_objfile_image.size () - offset;

  memcpy (buf, m_objfile_image.data () + offset, size);
  return size;
}

} /* anonymous namespace */

static gdb_bfd_iovec_base *
rocm_bfd_iovec_open (bfd *abfd, inferior *inferior)
{
  std::string_view uri (bfd_get_filename (abfd));
  std::string_view protocol_delim = "://";
  size_t protocol_end = uri.find (protocol_delim);
  std::string protocol (uri.substr (0, protocol_end));
  protocol_end += protocol_delim.length ();

  std::transform (protocol.begin (), protocol.end (), protocol.begin (),
		  [] (unsigned char c) { return std::tolower (c); });

  std::string_view path;
  size_t path_end = uri.find_first_of ("#?", protocol_end);
  if (path_end != std::string::npos)
    path = uri.substr (protocol_end, path_end++ - protocol_end);
  else
    path = uri.substr (protocol_end);

  /* %-decode the string.  */
  std::string decoded_path;
  decoded_path.reserve (path.length ());
  for (size_t i = 0; i < path.length (); ++i)
    if (path[i] == '%'
	&& i < path.length () - 2
	&& std::isxdigit (path[i + 1])
	&& std::isxdigit (path[i + 2]))
      {
	std::string_view hex_digits = path.substr (i + 1, 2);
	decoded_path += std::stoi (std::string (hex_digits), 0, 16);
	i += 2;
      }
    else
      decoded_path += path[i];

  /* Tokenize the query/fragment.  */
  std::vector<std::string_view> tokens;
  size_t pos, last = path_end;
  while ((pos = uri.find ('&', last)) != std::string::npos)
    {
      tokens.emplace_back (uri.substr (last, pos - last));
      last = pos + 1;
    }

  if (last != std::string::npos)
    tokens.emplace_back (uri.substr (last));

  /* Create a tag-value map from the tokenized query/fragment.  */
  std::unordered_map<std::string_view, std::string_view,
		     gdb::string_view_hash> params;
  for (std::string_view token : tokens)
    {
      size_t delim = token.find ('=');
      if (delim != std::string::npos)
	{
	  std::string_view tag = token.substr (0, delim);
	  std::string_view val = token.substr (delim + 1);
	  params.emplace (tag, val);
	}
    }

  try
    {
      ULONGEST offset = 0;
      ULONGEST size = 0;

      auto try_strtoulst = [] (std::string_view v)
	{
	  errno = 0;
	  ULONGEST value = strtoulst (v.data (), nullptr, 0);
	  if (errno != 0)
	    {
	      /* The actual message doesn't matter, the exception is caught
		 below, transformed in a BFD error, and the message is lost.  */
	      error (_("Failed to parse integer."));
	    }

	  return value;
	};

      auto offset_it = params.find ("offset");
      if (offset_it != params.end ())
	offset = try_strtoulst (offset_it->second);

      auto size_it = params.find ("size");
      if (size_it != params.end ())
	{
	  size = try_strtoulst (size_it->second);
	  if (size == 0)
	    error (_("Invalid size value"));
	}

      if (protocol == "file")
	{
	  auto info = get_solib_info (inferior);
	  fileio_error target_errno;
	  int fd = info->fd_cache.open (decoded_path, &target_errno);

	  if (fd == -1)
	    {
	      errno = fileio_error_to_host (target_errno);
	      bfd_set_error (bfd_error_system_call);
	      return nullptr;
	    }

	  return new rocm_code_object_stream_file (inferior, fd, offset,
						   size);
	}

      if (protocol == "memory")
	{
	  ULONGEST pid = try_strtoulst (path);
	  if (pid != inferior->pid)
	    {
	      warning (_("`%s': code object is from another inferior"),
		       std::string (uri).c_str ());
	      bfd_set_error (bfd_error_bad_value);
	      return nullptr;
	    }

	  gdb::byte_vector buffer (size);
	  if (target_read_memory (offset, buffer.data (), size) != 0)
	    {
	      warning (_("Failed to copy the code object from the inferior"));
	      bfd_set_error (bfd_error_bad_value);
	      return nullptr;
	    }

	  return new rocm_code_object_stream_memory (std::move (buffer));
	}

      warning (_("`%s': protocol not supported: %s"),
	       std::string (uri).c_str (), protocol.c_str ());
      bfd_set_error (bfd_error_bad_value);
      return nullptr;
    }
  catch (const gdb_exception_quit &ex)
    {
      set_quit_flag ();
      bfd_set_error (bfd_error_bad_value);
      return nullptr;
    }
  catch (const gdb_exception &ex)
    {
      bfd_set_error (bfd_error_bad_value);
      return nullptr;
    }
}

static gdb_bfd_ref_ptr
rocm_solib_bfd_open (const char *pathname)
{
  /* Handle regular files with SVR4 open.  */
  if (strstr (pathname, "://") == nullptr)
    return svr4_so_ops.bfd_open (pathname);

  auto open = [] (bfd *nbfd) -> gdb_bfd_iovec_base *
  {
    return rocm_bfd_iovec_open (nbfd, current_inferior ());
  };

  gdb_bfd_ref_ptr abfd = gdb_bfd_openr_iovec (pathname, "elf64-amdgcn", open);

  if (abfd == nullptr)
    error (_("Could not open `%s' as an executable file: %s"), pathname,
	   bfd_errmsg (bfd_get_error ()));

  /* Check bfd format.  */
  if (!bfd_check_format (abfd.get (), bfd_object))
    error (_("`%s': not in executable format: %s"),
	   bfd_get_filename (abfd.get ()), bfd_errmsg (bfd_get_error ()));

  unsigned char osabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
  unsigned char osabiversion = elf_elfheader (abfd)->e_ident[EI_ABIVERSION];

  /* Check that the code object is using the HSA OS ABI.  */
  if (osabi != ELFOSABI_AMDGPU_HSA)
    error (_("`%s': ELF file OS ABI is not supported (%d)."),
	   bfd_get_filename (abfd.get ()), osabi);

  /* We support HSA code objects V3 and greater.  */
  if (osabiversion < ELFABIVERSION_AMDGPU_HSA_V3)
    error (_("`%s': ELF file HSA OS ABI version is not supported (%d)."),
	   bfd_get_filename (abfd.get ()), osabiversion);

  /* For GDB to be able to use this solib, the exact AMDGPU processor type
     must be supported by both BFD and the amd-dbgapi library.  */
  const unsigned char gfx_arch
    = elf_elfheader (abfd)->e_flags & EF_AMDGPU_MACH ;
  const bfd_arch_info_type *bfd_arch_info
    = bfd_lookup_arch (bfd_arch_amdgcn, gfx_arch);

  amd_dbgapi_architecture_id_t architecture_id;
  amd_dbgapi_status_t dbgapi_query_arch
    = amd_dbgapi_get_architecture (gfx_arch, &architecture_id);

  if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS
      || bfd_arch_info ==  nullptr)
    {
      if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS
	  && bfd_arch_info ==  nullptr)
	{
	  /* Neither of the libraries knows about this arch, so we cannot
	     provide a human readable name for it.  */
	  error (_("'%s': AMDGCN architecture %#02x is not supported."),
		 bfd_get_filename (abfd.get ()), gfx_arch);
	}
      else if (dbgapi_query_arch != AMD_DBGAPI_STATUS_SUCCESS)
	{
	  gdb_assert (bfd_arch_info != nullptr);
	  error (_("'%s': AMDGCN architecture %s not supported by "
		   "amd-dbgapi."),
		 bfd_get_filename (abfd.get ()),
		 bfd_arch_info->printable_name);
	}
      else
	{
	  gdb_assert (dbgapi_query_arch == AMD_DBGAPI_STATUS_SUCCESS);
	  char *arch_name;
	  if (amd_dbgapi_architecture_get_info
	      (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_NAME,
	       sizeof (arch_name), &arch_name) != AMD_DBGAPI_STATUS_SUCCESS)
	    error ("amd_dbgapi_architecture_get_info call failed for arch "
		   "%#02x.", gfx_arch);
	  gdb::unique_xmalloc_ptr<char> arch_name_cleaner (arch_name);

	  error (_("'%s': AMDGCN architecture %s not supported."),
		 bfd_get_filename (abfd.get ()),
		 arch_name);
	}
    }

  gdb_assert (gdbarch_from_bfd (abfd.get ()) != nullptr);
  gdb_assert (is_amdgpu_arch (gdbarch_from_bfd (abfd.get ())));

  return abfd;
}

static void
rocm_solib_create_inferior_hook (int from_tty)
{
  get_solib_info (current_inferior ())->solib_list.clear ();

  svr4_so_ops.solib_create_inferior_hook (from_tty);
}

static void
rocm_update_solib_list ()
{
  inferior *inf = current_inferior ();

  amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (inf);
  if (process_id.handle == AMD_DBGAPI_PROCESS_NONE.handle)
    return;

  solib_info *info = get_solib_info (inf);

  info->solib_list.clear ();
  std::vector<rocm_so> &sos = info->solib_list;

  amd_dbgapi_code_object_id_t *code_object_list;
  size_t count;

  amd_dbgapi_status_t status
    = amd_dbgapi_process_code_object_list (process_id, &count,
					   &code_object_list, nullptr);
  if (status != AMD_DBGAPI_STATUS_SUCCESS)
    {
      warning (_("amd_dbgapi_process_code_object_list failed (%s)"),
	       get_status_string (status));
      return;
    }

  gdb::unique_xmalloc_ptr<amd_dbgapi_code_object_id_t> code_object_list_holder
    (code_object_list);

  for (size_t i = 0; i < count; ++i)
    {
      CORE_ADDR l_addr;
      char *uri_bytes;

      status = amd_dbgapi_code_object_get_info
	(code_object_list[i], AMD_DBGAPI_CODE_OBJECT_INFO_LOAD_ADDRESS,
	 sizeof (l_addr), &l_addr);
      if (status != AMD_DBGAPI_STATUS_SUCCESS)
	continue;

      status = amd_dbgapi_code_object_get_info
	(code_object_list[i], AMD_DBGAPI_CODE_OBJECT_INFO_URI_NAME,
	 sizeof (uri_bytes), &uri_bytes);
      if (status != AMD_DBGAPI_STATUS_SUCCESS)
	continue;

      gdb::unique_xmalloc_ptr<char> uri_bytes_holder (uri_bytes);

      lm_info_svr4_up li = std::make_unique<lm_info_svr4> ();
      li->l_addr = l_addr;

      /* Generate a unique name so that code objects with the same URI but
	 different load addresses are seen by gdb core as different shared
	 objects.  */
      std::string unique_name
	= string_printf ("code_object_%ld", code_object_list[i].handle);

      sos.emplace_back (uri_bytes, std::move (unique_name), std::move (li));
    }

  if (rocm_solib_ops.current_sos == NULL)
    {
      /* Override what we need to.  */
      rocm_solib_ops = svr4_so_ops;
      rocm_solib_ops.current_sos = rocm_solib_current_sos;
      rocm_solib_ops.solib_create_inferior_hook
	= rocm_solib_create_inferior_hook;
      rocm_solib_ops.bfd_open = rocm_solib_bfd_open;
      rocm_solib_ops.relocate_section_addresses
	= rocm_solib_relocate_section_addresses;
      rocm_solib_ops.handle_event = rocm_solib_handle_event;

      /* Engage the ROCm so_ops.  */
      set_gdbarch_so_ops (current_inferior ()->arch (), &rocm_solib_ops);
    }
}

static void
rocm_solib_target_inferior_created (inferior *inf)
{
  get_solib_info (inf)->solib_list.clear ();

  rocm_update_solib_list ();

  /* Force GDB to reload the solibs.  */
  current_inferior ()->pspace->clear_solib_cache ();
  solib_add (nullptr, 0, auto_solib_add);
}

/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_rocm_solib;

void
_initialize_rocm_solib ()
{
  /* The dependency on the amd-dbgapi exists because solib-rocm's
     inferior_created observer needs amd-dbgapi to have attached the process,
     which happens in amd_dbgapi_target's inferior_created observer.  */
  gdb::observers::inferior_created.attach
    (rocm_solib_target_inferior_created,
     "solib-rocm",
     { &get_amd_dbgapi_target_inferior_created_observer_token () });
}
