// vi:set ft=cpp: -*- Mode: C++ -*-
/**
 * \file
 * The debugger interface specifies common debugging related definitions.
 */
/*
 * (c) 2010-2011 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
 *               Alexander Warg <warg@os.inf.tu-dresden.de>
 *     economic rights: Technische Universität Dresden (Germany)
 *
 * License: see LICENSE.spdx (in this directory or the directories above)
 */
#pragma once

#include <l4/sys/debugger.h>
#include <l4/sys/kobject>

namespace L4 {

/**
 * C++ kernel debugger API.
 *
 * \attention This API is subject to change! Do not rely on it in production
 *            code.
 *
 * This API is to be used for debugging exclusively.
 *
 * This is the API for accessing kernel-debugger functionality from user-level
 * programs. Specifically, it provides functionality to enrich the kernel
 * debugger with insights into the program. The purpose is to facilitate
 * debugging with the kernel debugger. For instance, a developer might choose
 * to name the threads of her program so that she can find them in the kernel
 * debugger thread list.
 *
 * This API interacts with a kernel object that interfaces with the kernel
 * debugger, the jdb-kernel object. The jdb-kernel object is fix and only
 * available when the kernel debugger is built into the microkernel. The
 * developer needs to pass the capability through to her program.
 *
 * \includefile{l4/sys/debugger}
 */
class Debugger : public Kobject_t<Debugger, Kobject, L4_PROTO_DEBUGGER>
{
public:
  enum
  {
    Switch_log_on  = L4_DEBUGGER_SWITCH_LOG_ON,
    Switch_log_off = L4_DEBUGGER_SWITCH_LOG_OFF,
  };

  /**
   * \copybrief l4_debugger_set_object_name()
   *
   * \param name  Name
   * \utcb_def{utcb}
   *
   * \return System call return tag.
   */
  l4_msgtag_t set_object_name(const char *name,
                              l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_set_object_name_u(cap(), name, utcb); }

  /**
   * \copybrief l4_debugger_global_id()
   *
   * \utcb_def{utcb}
   *
   * \retval ~0UL  The capability is invalid.
   * \retval >=0   The global debugger id.
   */
  unsigned long global_id(l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_global_id_u(cap(), utcb); }

  /**
   * \copybrief l4_debugger_kobj_to_id()
   *
   * \param kobjp  Kobject pointer
   * \utcb{utcb}
   *
   * \retval ~0UL  The capability or the Kobject pointer are invalid.
   * \retval >=0   The globally unique id.
   */
  unsigned long kobj_to_id(l4_addr_t kobjp,
                           l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_kobj_to_id_u(cap(), kobjp, utcb); }

  /**
   * \copybrief l4_debugger_query_log_typeid()
   *
   * \param name   Name to query for.
   * \param idx    Idx to start searching, start with 0
   * \utcb{utcb}
   *
   * \retval >=0  Id
   * \retval <0   Error
   */
  long query_log_typeid(const char *name, unsigned idx,
                        l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_query_log_typeid_u(cap(), name, idx, utcb); }

  /**
   * \copybrief l4_debugger_query_log_name()
   *
   * \param      idx           ID to query.
   * \param[out] name          Buffer to copy name to. The buffer must be
   *                           allocated by the caller.
   * \param      namelen       Buffer length of name.
   * \param[out] shortname     Buffer to copy `shortname` to. The buffer must
   *                           be allocated by the caller.
   * \param      shortnamelen  Buffer length of `shortname`.
   * \utcb{utcb}
   *
   * \retval 0   Success
   * \retval <0  Error
   */
  long query_log_name(unsigned idx,
                      char *name, unsigned namelen,
                      char *shortname, unsigned shortnamelen,
                      l4_utcb_t *utcb = l4_utcb()) noexcept
  {
    return l4_debugger_query_log_name_u(cap(), idx, name, namelen,
                                        shortname, shortnamelen, utcb);
  }

  /**
   * \copybrief l4_debugger_switch_log()
   * \param name    Name of the log type.
   * \param on_off  1: turn log on, 0: turn log off
   * \utcb{utcb}
   *
   * \return Syscall return tag
   */
  l4_msgtag_t switch_log(const char *name, unsigned on_off,
                         l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_switch_log_u(cap(), name, on_off, utcb); }

  /**
   * Get name of object with Id `id`.
   *
   * \param      id    Id of the object whose name is asked.
   * \param[out] name  Buffer to copy the name into. The buffer must be
   *                   allocated by the caller.
   * \param      size  Length of the `name` buffer.
   * \utcb{utcb}
   *
   * \return Syscall return tag
   */
  l4_msgtag_t query_object_name(unsigned id, char *name, unsigned size,
                       l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_query_object_name_u(cap(), id, name, size, utcb); }

  /**
   * Get name of object.
   *
   * \param[out] name  Buffer to copy the name into. The buffer must be
   *                   allocated by the caller.
   * \param      size  Length of the `name` buffer.
   * \utcb{utcb}
   *
   * \return Syscall return tag
   */
  l4_msgtag_t get_object_name(char *name, unsigned size,
                              l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_get_object_name_u(cap(), name, size, utcb); }

  /**
   * \copybrief l4_debugger_add_image_info()
   *
   * \param base  Image load base address
   * \param name  Image name
   * \param utcb  The UTCB to use for the operation.
   *
   * \return System call return tag.
   */
  l4_msgtag_t add_image_info(l4_addr_t base, const char *name,
                             l4_utcb_t *utcb = l4_utcb()) noexcept
  { return l4_debugger_add_image_info_u(cap(), base, name, utcb); }
};
}
