direct-io.hg

changeset 9143:8ed131452f27

Consolidate xc_ptrace and xc_ptrace_core

* xc_ptrace
- Merge xc_ptrace_core into xc_ptrace
- ATTACH now reads the data argument. If non-zero then
a corefile is being debuged. Otherwise a thread has
been attached to. This allows xc_waitdomain_core() or
xc_waitdomain() to be called as appropriate in
subsequent xc_ptrace() calls.
* xc_waitdomain
- Rename xc_waitdomain (xc_ptrace.c version) __xc_waitdomain
- Rename xc_waitdomain (xc_ptrace_core.c version) xc_waitdomain_core
- Create xc_waitdomain (in xc_ptrace.c), a wrapper for __xc_waitdomain
and xc_waitdomain_core.
Consolidation seemed difficult but ctxt needs to be
passed into xc_waitdomain_core or made global.
Alternatively, xc_waitdomain_core could be moved into xc_ptrace.c,
but this seems messy.
* map_domain_va
- Rename map_domain_va (xc_ptrace_core.c version) map_domain_va_core
- Have it accept ctxt, like xc_waitdomain_core
* myptrace and myxcwait (linux-xen-low.c)
Removed, call the now generic xc_ptrace() and xc_waitdomain() instead

When calling xc_ptrace ATTACH, if a corefile is in use, a fd will
be passed, otherwise a pid. The fd part is important, as this
is saved internally in xc_ptrace_core.c, and passed to xc_waitdomain_core()
as neccessary. Pereviously xc_waitdomain_core() received a pid and
thus could not open the corefile.

Signed-Off-By: Horms <horms@verge.net.au>
author kaf24@firebug.cl.cam.ac.uk
date Mon Mar 06 12:06:55 2006 +0100 (2006-03-06)
parents 26eff2448966
children 0161a721bad5
files tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c tools/libxc/xc_ptrace.c tools/libxc/xc_ptrace_core.c tools/libxc/xenctrl.h
line diff
     1.1 --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Mon Mar 06 12:05:44 2006 +0100
     1.2 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Mon Mar 06 12:06:55 2006 +0100
     1.3 @@ -41,8 +41,6 @@
     1.4  
     1.5  #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
     1.6  
     1.7 -long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long);
     1.8 -int (*myxcwait)(int xc_handle, int domain, int *status, int options) ;
     1.9  static int xc_handle;
    1.10  
    1.11  static inline int
    1.12 @@ -170,7 +168,7 @@ linux_attach (int domid)
    1.13      add_thread (0, new_process);
    1.14      new_process->stop_expected = 0;
    1.15  
    1.16 -    if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) {
    1.17 +    if (xc_ptrace (xc_handle, PTRACE_ATTACH, domid, 0, isfile) != 0) {
    1.18  	fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid,
    1.19  		 strerror (errno), errno);
    1.20  	fflush (stderr);
    1.21 @@ -188,7 +186,7 @@ linux_kill_one_process (struct inferior_
    1.22  {
    1.23    struct thread_info *thread = (struct thread_info *) entry;
    1.24    struct process_info *process = get_thread_process (thread);
    1.25 -  myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0);
    1.26 +  xc_ptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0);
    1.27  }
    1.28  
    1.29  
    1.30 @@ -202,7 +200,7 @@ static void
    1.31  linux_detach_one_process (struct inferior_list_entry *entry)
    1.32  {
    1.33  
    1.34 -  myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0);
    1.35 +  xc_ptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0);
    1.36  }
    1.37  
    1.38  
    1.39 @@ -228,7 +226,7 @@ static unsigned char
    1.40  linux_wait (char *status)
    1.41  {
    1.42    int w;
    1.43 -  if (myxcwait(xc_handle, current_domid, &w, 0))
    1.44 +  if (xc_waitdomain(xc_handle, current_domid, &w, 0))
    1.45        return -1;
    1.46    
    1.47    linux_set_inferior();
    1.48 @@ -250,7 +248,7 @@ linux_resume (struct thread_resume *resu
    1.49    for_each_inferior(&all_threads, regcache_invalidate_one);
    1.50    if (debug_threads)
    1.51      fprintf(stderr, "step: %d\n", step);
    1.52 -  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, 
    1.53 +  xc_ptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, 
    1.54  	    resume_info->thread, 0, 0);
    1.55  
    1.56  }
    1.57 @@ -275,7 +273,7 @@ regsets_fetch_inferior_registers ()
    1.58  	}
    1.59  
    1.60        buf = malloc (regset->size);
    1.61 -      res = myptrace (xc_handle, regset->get_request, 
    1.62 +      res = xc_ptrace (xc_handle, regset->get_request, 
    1.63  		      curvcpuid(),
    1.64  		      0, (PTRACE_XFER_TYPE)buf);
    1.65        if (res < 0)
    1.66 @@ -329,7 +327,7 @@ regsets_store_inferior_registers ()
    1.67  
    1.68        buf = malloc (regset->size);
    1.69        regset->fill_function (buf);
    1.70 -      res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf);
    1.71 +      res = xc_ptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf);
    1.72        if (res < 0)
    1.73  	{
    1.74  	  if (errno == EIO)
    1.75 @@ -407,7 +405,7 @@ linux_read_memory (CORE_ADDR memaddr, ch
    1.76    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
    1.77      {
    1.78        errno = 0;
    1.79 -      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0);
    1.80 +      buffer[i] = xc_ptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0);
    1.81        if (errno)
    1.82  	return errno;
    1.83      }
    1.84 @@ -440,13 +438,13 @@ linux_write_memory (CORE_ADDR memaddr, c
    1.85  
    1.86    /* Fill start and end extra bytes of buffer with existing memory data.  */
    1.87  
    1.88 -  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
    1.89 +  buffer[0] = xc_ptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
    1.90  		      (PTRACE_ARG3_TYPE) addr, 0);
    1.91  
    1.92    if (count > 1)
    1.93      {
    1.94        buffer[count - 1]
    1.95 -	= myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
    1.96 +	= xc_ptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
    1.97  		  (PTRACE_ARG3_TYPE) (addr + (count - 1)
    1.98  				      * sizeof (PTRACE_XFER_TYPE)),
    1.99  		  0);
   1.100 @@ -460,7 +458,7 @@ linux_write_memory (CORE_ADDR memaddr, c
   1.101    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
   1.102      {
   1.103        errno = 0;
   1.104 -      myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), 
   1.105 +      xc_ptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), 
   1.106  		(PTRACE_ARG3_TYPE) addr, buffer[i]);
   1.107        if (errno)
   1.108  	return errno;
   1.109 @@ -561,13 +559,6 @@ initialize_low (void)
   1.110  		       the_low_target.breakpoint_len);
   1.111    init_registers ();
   1.112    linux_init_signals ();
   1.113 -  if (isfile) {
   1.114 -      myptrace = xc_ptrace_core;
   1.115 -      myxcwait = xc_waitdomain_core;
   1.116 -  } else {
   1.117 -      myptrace = xc_ptrace;
   1.118 -      myxcwait = xc_waitdomain;
   1.119 -  }
   1.120    using_threads = thread_db_init ();
   1.121  
   1.122  }
     2.1 --- a/tools/libxc/xc_ptrace.c	Mon Mar 06 12:05:44 2006 +0100
     2.2 +++ b/tools/libxc/xc_ptrace.c	Mon Mar 06 12:06:55 2006 +0100
     2.3 @@ -9,38 +9,11 @@
     2.4  #include "xg_private.h"
     2.5  #include "xc_ptrace.h"
     2.6  
     2.7 -const char const * ptrace_names[] = {
     2.8 -    "PTRACE_TRACEME",
     2.9 -    "PTRACE_PEEKTEXT",
    2.10 -    "PTRACE_PEEKDATA",
    2.11 -    "PTRACE_PEEKUSER",
    2.12 -    "PTRACE_POKETEXT",
    2.13 -    "PTRACE_POKEDATA",
    2.14 -    "PTRACE_POKEUSER",
    2.15 -    "PTRACE_CONT",
    2.16 -    "PTRACE_KILL",
    2.17 -    "PTRACE_SINGLESTEP",
    2.18 -    "PTRACE_INVALID",
    2.19 -    "PTRACE_INVALID",
    2.20 -    "PTRACE_GETREGS",
    2.21 -    "PTRACE_SETREGS",
    2.22 -    "PTRACE_GETFPREGS",
    2.23 -    "PTRACE_SETFPREGS",
    2.24 -    "PTRACE_ATTACH",
    2.25 -    "PTRACE_DETACH",
    2.26 -    "PTRACE_GETFPXREGS",
    2.27 -    "PTRACE_SETFPXREGS",
    2.28 -    "PTRACE_INVALID",
    2.29 -    "PTRACE_INVALID",
    2.30 -    "PTRACE_INVALID",
    2.31 -    "PTRACE_INVALID",
    2.32 -    "PTRACE_SYSCALL",
    2.33 -};
    2.34 -
    2.35  /* XXX application state */
    2.36  static long                     nr_pages = 0;
    2.37  static unsigned long           *page_array = NULL;
    2.38  static int                      current_domid = -1;
    2.39 +static int                      current_isfile;
    2.40  
    2.41  static cpumap_t                 online_cpumap;
    2.42  static cpumap_t                 regs_valid;
    2.43 @@ -298,8 +271,8 @@ map_domain_va(
    2.44      return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
    2.45  }
    2.46  
    2.47 -int 
    2.48 -xc_waitdomain(
    2.49 +static int 
    2.50 +__xc_waitdomain(
    2.51      int xc_handle,
    2.52      int domain,
    2.53      int *status,
    2.54 @@ -368,8 +341,12 @@ xc_ptrace(
    2.55      { 
    2.56      case PTRACE_PEEKTEXT:
    2.57      case PTRACE_PEEKDATA:
    2.58 -        guest_va = (unsigned long *)map_domain_va(
    2.59 -            xc_handle, cpu, addr, PROT_READ);
    2.60 +        if (current_isfile)
    2.61 +            guest_va = (unsigned long *)map_domain_va_core(current_domid, 
    2.62 +                                cpu, addr, ctxt);
    2.63 +        else
    2.64 +            guest_va = (unsigned long *)map_domain_va(xc_handle, 
    2.65 +                                cpu, addr, PROT_READ);
    2.66          if ( guest_va == NULL )
    2.67              goto out_error;
    2.68          retval = *guest_va;
    2.69 @@ -378,15 +355,19 @@ xc_ptrace(
    2.70      case PTRACE_POKETEXT:
    2.71      case PTRACE_POKEDATA:
    2.72          /* XXX assume that all CPUs have the same address space */
    2.73 -        guest_va = (unsigned long *)map_domain_va(
    2.74 -                            xc_handle, cpu, addr, PROT_READ|PROT_WRITE);
    2.75 +        if (current_isfile)
    2.76 +            guest_va = (unsigned long *)map_domain_va_core(current_domid, 
    2.77 +                                cpu, addr, ctxt);
    2.78 +        else
    2.79 +            guest_va = (unsigned long *)map_domain_va(xc_handle, 
    2.80 +                                cpu, addr, PROT_READ|PROT_WRITE);
    2.81          if ( guest_va == NULL ) 
    2.82              goto out_error;
    2.83          *guest_va = (unsigned long)data;
    2.84          break;
    2.85  
    2.86      case PTRACE_GETREGS:
    2.87 -        if (fetch_regs(xc_handle, cpu, NULL))
    2.88 +        if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) 
    2.89              goto out_error;
    2.90          SET_PT_REGS(pt, ctxt[cpu].user_regs); 
    2.91          memcpy(data, &pt, sizeof(struct gdb_regs));
    2.92 @@ -394,12 +375,14 @@ xc_ptrace(
    2.93  
    2.94      case PTRACE_GETFPREGS:
    2.95      case PTRACE_GETFPXREGS:
    2.96 -        if (fetch_regs(xc_handle, cpu, NULL)) 
    2.97 -            goto out_error;
    2.98 +        if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) 
    2.99 +                goto out_error;
   2.100          memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
   2.101          break;
   2.102  
   2.103      case PTRACE_SETREGS:
   2.104 +        if (!current_isfile)
   2.105 +                goto out_unspported; /* XXX not yet supported */
   2.106          SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
   2.107          if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, 
   2.108                                  &ctxt[cpu])))
   2.109 @@ -407,6 +390,8 @@ xc_ptrace(
   2.110          break;
   2.111  
   2.112      case PTRACE_SINGLESTEP:
   2.113 +        if (!current_isfile)
   2.114 +              goto out_unspported; /* XXX not yet supported */
   2.115          /*  XXX we can still have problems if the user switches threads
   2.116           *  during single-stepping - but that just seems retarded
   2.117           */
   2.118 @@ -418,6 +403,8 @@ xc_ptrace(
   2.119  
   2.120      case PTRACE_CONT:
   2.121      case PTRACE_DETACH:
   2.122 +        if (!current_isfile)
   2.123 +            goto out_unspported; /* XXX not yet supported */
   2.124          if ( request != PTRACE_SINGLESTEP )
   2.125          {
   2.126              FOREACH_CPU(cpumap, index) {
   2.127 @@ -450,6 +437,9 @@ xc_ptrace(
   2.128  
   2.129      case PTRACE_ATTACH:
   2.130          current_domid = domid_tid;
   2.131 +        current_isfile = (int)edata;
   2.132 +        if (current_isfile)
   2.133 +            break;
   2.134          op.cmd = DOM0_GETDOMAININFO;
   2.135          op.u.getdomaininfo.domain = current_domid;
   2.136          retval = do_dom0_op(xc_handle, &op);
   2.137 @@ -477,12 +467,7 @@ xc_ptrace(
   2.138      case PTRACE_POKEUSER:
   2.139      case PTRACE_SYSCALL:
   2.140      case PTRACE_KILL:
   2.141 -#ifdef DEBUG
   2.142 -        printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
   2.143 -#endif
   2.144 -        /* XXX not yet supported */
   2.145 -        errno = ENOSYS;
   2.146 -        return -1;
   2.147 +        goto out_unspported; /* XXX not yet supported */
   2.148  
   2.149      case PTRACE_TRACEME:
   2.150          printf("PTRACE_TRACEME is an invalid request under Xen\n");
   2.151 @@ -496,6 +481,26 @@ xc_ptrace(
   2.152   out_error:
   2.153      errno = EINVAL;
   2.154      return retval;
   2.155 +
   2.156 + out_unspported:
   2.157 +#ifdef DEBUG
   2.158 +    printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
   2.159 +#endif
   2.160 +    errno = ENOSYS;
   2.161 +    return -1;
   2.162 +
   2.163 +}
   2.164 +
   2.165 +int 
   2.166 +xc_waitdomain(
   2.167 +    int xc_handle,
   2.168 +    int domain,
   2.169 +    int *status,
   2.170 +    int options)
   2.171 +{
   2.172 +    if (current_isfile)
   2.173 +        return xc_waitdomain_core(xc_handle, domain, status, options, ctxt);
   2.174 +    return __xc_waitdomain(xc_handle, domain, status, options);
   2.175  }
   2.176  
   2.177  /*
     3.1 --- a/tools/libxc/xc_ptrace_core.c	Mon Mar 06 12:05:44 2006 +0100
     3.2 +++ b/tools/libxc/xc_ptrace_core.c	Mon Mar 06 12:06:55 2006 +0100
     3.3 @@ -6,8 +6,6 @@
     3.4  #include "xc_ptrace.h"
     3.5  #include <time.h>
     3.6  
     3.7 -#define VCPU            0               /* XXX */
     3.8 -
     3.9  /* XXX application state */
    3.10  
    3.11  static long   nr_pages = 0;
    3.12 @@ -15,7 +13,6 @@ static unsigned long  *p2m_array = NULL;
    3.13  static unsigned long  *m2p_array = NULL;
    3.14  static unsigned long            pages_offset;
    3.15  static unsigned long            cr3[MAX_VIRT_CPUS];
    3.16 -static vcpu_guest_context_t     ctxt[MAX_VIRT_CPUS];
    3.17  
    3.18  /* --------------------- */
    3.19  
    3.20 @@ -23,11 +20,13 @@ static unsigned long
    3.21  map_mtop_offset(unsigned long ma)
    3.22  {
    3.23      return pages_offset + (m2p_array[ma >> PAGE_SHIFT] << PAGE_SHIFT);
    3.24 +    return 0;
    3.25  }
    3.26  
    3.27  
    3.28 -static void *
    3.29 -map_domain_va(unsigned long domfd, int cpu, void * guest_va)
    3.30 +void *
    3.31 +map_domain_va_core(unsigned long domfd, int cpu, void * guest_va,
    3.32 +                        vcpu_guest_context_t *ctxt)
    3.33  {
    3.34      unsigned long pde, page;
    3.35      unsigned long va = (unsigned long)guest_va;
    3.36 @@ -99,7 +98,8 @@ xc_waitdomain_core(
    3.37      int xc_handle,
    3.38      int domfd,
    3.39      int *status,
    3.40 -    int options)
    3.41 +    int options,
    3.42 +    vcpu_guest_context_t *ctxt)
    3.43  {
    3.44      int nr_vcpus;
    3.45      int i;
    3.46 @@ -146,85 +146,6 @@ xc_waitdomain_core(
    3.47      return 0;
    3.48  }
    3.49  
    3.50 -long
    3.51 -xc_ptrace_core(
    3.52 -    int xc_handle,
    3.53 -    enum __ptrace_request request,
    3.54 -    uint32_t domfd,
    3.55 -    long eaddr,
    3.56 -    long edata)
    3.57 -{
    3.58 -    int             status = 0;
    3.59 -    struct gdb_regs pt;
    3.60 -    long            retval = 0;
    3.61 -    unsigned long  *guest_va;
    3.62 -    int             cpu = VCPU;
    3.63 -    void           *addr = (char *)eaddr;
    3.64 -    void           *data = (char *)edata;
    3.65 -
    3.66 -#if 0
    3.67 -    printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
    3.68 -#endif
    3.69 -    switch (request) { 
    3.70 -    case PTRACE_PEEKTEXT:
    3.71 -    case PTRACE_PEEKDATA:
    3.72 -        if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
    3.73 -            status = EFAULT;
    3.74 -            goto error_out;
    3.75 -        }
    3.76 -
    3.77 -        retval = *guest_va;
    3.78 -        break;
    3.79 -    case PTRACE_POKETEXT:
    3.80 -    case PTRACE_POKEDATA:
    3.81 -        if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
    3.82 -            status = EFAULT;
    3.83 -            goto error_out;
    3.84 -        }
    3.85 -        *guest_va = (unsigned long)data;
    3.86 -        break;
    3.87 -    case PTRACE_GETREGS:
    3.88 -    case PTRACE_GETFPREGS:
    3.89 -    case PTRACE_GETFPXREGS:
    3.90 -        if (request == PTRACE_GETREGS) {
    3.91 -            SET_PT_REGS(pt, ctxt[cpu].user_regs); 
    3.92 -            memcpy(data, &pt, sizeof(struct gdb_regs));
    3.93 -        } else if (request == PTRACE_GETFPREGS)
    3.94 -            memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
    3.95 -        else /*if (request == PTRACE_GETFPXREGS)*/
    3.96 -            memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
    3.97 -        break;
    3.98 -    case PTRACE_ATTACH:
    3.99 -        retval = 0;
   3.100 -        break;
   3.101 -    case PTRACE_SETREGS:
   3.102 -    case PTRACE_SINGLESTEP:
   3.103 -    case PTRACE_CONT:
   3.104 -    case PTRACE_DETACH:
   3.105 -    case PTRACE_SETFPREGS:
   3.106 -    case PTRACE_SETFPXREGS:
   3.107 -    case PTRACE_PEEKUSER:
   3.108 -    case PTRACE_POKEUSER:
   3.109 -    case PTRACE_SYSCALL:
   3.110 -    case PTRACE_KILL:
   3.111 -#ifdef DEBUG
   3.112 -        printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
   3.113 -#endif
   3.114 -        status = ENOSYS;
   3.115 -        break;
   3.116 -    case PTRACE_TRACEME:
   3.117 -        printf("PTRACE_TRACEME is an invalid request under Xen\n");
   3.118 -        status = EINVAL;
   3.119 -    }
   3.120 -    
   3.121 -    if (status) {
   3.122 -        errno = status;
   3.123 -        retval = -1;
   3.124 -    }
   3.125 - error_out:
   3.126 -    return retval;
   3.127 -}
   3.128 -
   3.129  /*
   3.130   * Local variables:
   3.131   * mode: C
     4.1 --- a/tools/libxc/xenctrl.h	Mon Mar 06 12:05:44 2006 +0100
     4.2 +++ b/tools/libxc/xenctrl.h	Mon Mar 06 12:06:55 2006 +0100
     4.3 @@ -98,13 +98,19 @@ long xc_ptrace_core(
     4.4      enum __ptrace_request request, 
     4.5      uint32_t domid, 
     4.6      long addr, 
     4.7 -    long data);
     4.8 -
     4.9 +    long data,
    4.10 +    vcpu_guest_context_t *ctxt);
    4.11 +void * map_domain_va_core(
    4.12 +    unsigned long domfd, 
    4.13 +    int cpu, 
    4.14 +    void *guest_va,
    4.15 +    vcpu_guest_context_t *ctxt);
    4.16  int xc_waitdomain_core(
    4.17      int xc_handle,
    4.18      int domain, 
    4.19      int *status, 
    4.20 -    int options);
    4.21 +    int options,
    4.22 +    vcpu_guest_context_t *ctxt);
    4.23  
    4.24  /*
    4.25   * DOMAIN MANAGEMENT FUNCTIONS