[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/9] golang/xenlight: Don't try to marshall zero-length arrays


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: George Dunlap <george.dunlap@xxxxxxxxxx>
  • Date: Fri, 27 Dec 2019 16:32:16 +0000
  • Authentication-results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=george.dunlap@xxxxxxxxxx; spf=Pass smtp.mailfrom=George.Dunlap@xxxxxxxxxx; spf=None smtp.helo=postmaster@xxxxxxxxxxxxxxx
  • Cc: Nick Rosbrook <rosbrookn@xxxxxxxxxxxx>, George Dunlap <george.dunlap@xxxxxxxxxx>
  • Delivery-date: Fri, 27 Dec 2019 16:33:02 +0000
  • Ironport-sdr: 5fyPRwcyK9lcZtHXPQD0t7Xs4XyrYBtNn3BqJvatbWJdab7M3LFwBT3DJIjiU3mFP6DC7LiMLw 4c6fhuboVDHQoB+EkcrSDs7vZTFSsnMOfkRv7kSAe0JIOo0We5PsCof9798by1ETPWDxkLgMhG Xqk4/jdx6I6BmYJEMbH/gK3eGxkvD5jHLgFT1cStSt+twdEZz/5NXklzkm1dXBjFkmEdwb6D63 mhtZ9VOz4ID3Zm0Js9X5ZbXtmRoJuw0cLItAlnFWqvojXpdE+NlNbAkCF0TTiIPN3BAEqPzUGd L1Q=
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

The current fromC array code will do the "magic" casting and
martialling even when num_foo variable is 0.  Go crashes when doing
the cast.

Furthermore, the current toC array code will convert a nil slice into
a zero-length malloc.  The resulting pointer is non-NULL, and confuses
libxl.

Only do array marshalling if the number of elements is non-zero;
otherwise, leave the target pointer empty (nil for Go slices, NULL for
C arrays).

The toC half of this should be folded into "golang/xenlight:
implement array Go to C marshaling".

Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxx>
---
CC: Nick Rosbrook <rosbrookn@xxxxxxxxxxxx>
---
 tools/golang/xenlight/gengotypes.py  |   13 +-
 tools/golang/xenlight/helpers.gen.go | 1232 ++++++++++++++------------
 2 files changed, 671 insertions(+), 574 deletions(-)

diff --git a/tools/golang/xenlight/gengotypes.py 
b/tools/golang/xenlight/gengotypes.py
index a972754d36..5363ca062d 100644
--- a/tools/golang/xenlight/gengotypes.py
+++ b/tools/golang/xenlight/gengotypes.py
@@ -419,7 +419,8 @@ def xenlight_golang_array_from_C(ty = None):
     clenvar    = ty.type.lenvar.name
     golenvar   = xenlight_golang_fmt_name(clenvar,exported=False)
 
-    s += '{} := int(xc.{})\n'.format(golenvar, clenvar)
+    s += 'x.{} = nil\n'.format(goname)
+    s += 'if {} := int(xc.{}); {} > 0 {{\n'.format(golenvar, clenvar, golenvar)
     s += '{} := '.format(cslice)
     s +='(*[1<<28]C.{})(unsafe.Pointer(xc.{}))[:{}:{}]\n'.format(ctypename, 
cname,
                                                                 golenvar, 
golenvar)
@@ -433,7 +434,7 @@ def xenlight_golang_array_from_C(ty = None):
         s += 'if err := x.{}[i].fromC(&v); err != nil {{\n'.format(goname)
         s += 'return err }\n'
 
-    s += '}\n'
+    s += '}\n}\n'
 
     return s
 
@@ -599,7 +600,7 @@ def xenlight_golang_array_to_C(ty = None, dispose_fn = ''):
 
     is_enum = isinstance(ty.type.elem_type,idl.Enumeration)
     if gotypename in go_builtin_types or is_enum:
-        s += '{} := len(x.{})\n'.format(golenvar,goname)
+        s += 'if {} := len(x.{}); {} > 0 {{\n'.format(golenvar,goname, 
golenvar)
         s += 'xc.{} = 
(*C.{})(C.malloc(C.size_t({}*{})))\n'.format(cname,ctypename,
                                                                    
golenvar,golenvar)
         s += 'xc.{} = C.int({})\n'.format(clenvar,golenvar)
@@ -608,11 +609,11 @@ def xenlight_golang_array_to_C(ty = None, dispose_fn = 
''):
                                                                       
golenvar,golenvar)
         s += 'for i,v := range x.{} {{\n'.format(goname)
         s += 'c{}[i] = C.{}(v)\n'.format(goname,ctypename)
-        s += '}\n'
+        s += '}\n}\n'
 
         return s
 
-    s += '{} := len(x.{})\n'.format(golenvar,goname)
+    s += 'if {} := len(x.{}); {} > 0 {{\n'.format(golenvar,goname, golenvar)
     s += 'xc.{} = 
(*C.{})(C.malloc(C.ulong({})*C.sizeof_{}))\n'.format(cname,ctypename,
                                                                    
golenvar,ctypename)
     s += 'xc.{} = C.int({})\n'.format(clenvar,golenvar)
@@ -625,7 +626,7 @@ def xenlight_golang_array_to_C(ty = None, dispose_fn = ''):
     s += 'C.{}(&xc)\n'.format(dispose_fn)
     s += 'return xc,err\n}\n'
     s += 'c{}[i] = tmp\n'.format(goname)
-    s += '}\n'
+    s += '}\n}\n'
 
     return s
 
diff --git a/tools/golang/xenlight/helpers.gen.go 
b/tools/golang/xenlight/helpers.gen.go
index 3e588dd1c2..61cd73595e 100644
--- a/tools/golang/xenlight/helpers.gen.go
+++ b/tools/golang/xenlight/helpers.gen.go
@@ -528,12 +528,14 @@ func (x *SchedParams) toC() (xc C.libxl_sched_params, err 
error) {
 
 func (x *VcpuSchedParams) fromC(xc *C.libxl_vcpu_sched_params) error {
        x.Sched = Scheduler(xc.sched)
-       numVcpus := int(xc.num_vcpus)
-       cVcpus := (*[1 << 
28]C.libxl_sched_params)(unsafe.Pointer(xc.vcpus))[:numVcpus:numVcpus]
-       x.Vcpus = make([]SchedParams, numVcpus)
-       for i, v := range cVcpus {
-               if err := x.Vcpus[i].fromC(&v); err != nil {
-                       return err
+       x.Vcpus = nil
+       if numVcpus := int(xc.num_vcpus); numVcpus > 0 {
+               cVcpus := (*[1 << 
28]C.libxl_sched_params)(unsafe.Pointer(xc.vcpus))[:numVcpus:numVcpus]
+               x.Vcpus = make([]SchedParams, numVcpus)
+               for i, v := range cVcpus {
+                       if err := x.Vcpus[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -543,17 +545,18 @@ func (x *VcpuSchedParams) fromC(xc 
*C.libxl_vcpu_sched_params) error {
 func (x *VcpuSchedParams) toC() (xc C.libxl_vcpu_sched_params, err error) {
        C.libxl_vcpu_sched_params_init(&xc)
        xc.sched = C.libxl_scheduler(x.Sched)
-       numVcpus := len(x.Vcpus)
-       xc.vcpus = (*C.libxl_sched_params)(C.malloc(C.ulong(numVcpus) * 
C.sizeof_libxl_sched_params))
-       xc.num_vcpus = C.int(numVcpus)
-       cVcpus := (*[1 << 
28]C.libxl_sched_params)(unsafe.Pointer(xc.vcpus))[:numVcpus:numVcpus]
-       for i, v := range x.Vcpus {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_vcpu_sched_params_dispose(&xc)
-                       return xc, err
+       if numVcpus := len(x.Vcpus); numVcpus > 0 {
+               xc.vcpus = (*C.libxl_sched_params)(C.malloc(C.ulong(numVcpus) * 
C.sizeof_libxl_sched_params))
+               xc.num_vcpus = C.int(numVcpus)
+               cVcpus := (*[1 << 
28]C.libxl_sched_params)(unsafe.Pointer(xc.vcpus))[:numVcpus:numVcpus]
+               for i, v := range x.Vcpus {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_vcpu_sched_params_dispose(&xc)
+                               return xc, err
+                       }
+                       cVcpus[i] = tmp
                }
-               cVcpus[i] = tmp
        }
        return xc, nil
 }
@@ -586,11 +589,13 @@ func (x *DomainSchedParams) toC() (xc 
C.libxl_domain_sched_params, err error) {
 
 func (x *VnodeInfo) fromC(xc *C.libxl_vnode_info) error {
        x.Memkb = uint64(xc.memkb)
-       numDistances := int(xc.num_distances)
-       cDistances := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.distances))[:numDistances:numDistances]
-       x.Distances = make([]uint32, numDistances)
-       for i, v := range cDistances {
-               x.Distances[i] = uint32(v)
+       x.Distances = nil
+       if numDistances := int(xc.num_distances); numDistances > 0 {
+               cDistances := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.distances))[:numDistances:numDistances]
+               x.Distances = make([]uint32, numDistances)
+               for i, v := range cDistances {
+                       x.Distances[i] = uint32(v)
+               }
        }
        x.Pnode = uint32(xc.pnode)
        if err := x.Vcpus.fromC(&xc.vcpus); err != nil {
@@ -603,12 +608,13 @@ func (x *VnodeInfo) fromC(xc *C.libxl_vnode_info) error {
 func (x *VnodeInfo) toC() (xc C.libxl_vnode_info, err error) {
        C.libxl_vnode_info_init(&xc)
        xc.memkb = C.uint64_t(x.Memkb)
-       numDistances := len(x.Distances)
-       xc.distances = (*C.uint32_t)(C.malloc(C.size_t(numDistances * 
numDistances)))
-       xc.num_distances = C.int(numDistances)
-       cDistances := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.distances))[:numDistances:numDistances]
-       for i, v := range x.Distances {
-               cDistances[i] = C.uint32_t(v)
+       if numDistances := len(x.Distances); numDistances > 0 {
+               xc.distances = (*C.uint32_t)(C.malloc(C.size_t(numDistances * 
numDistances)))
+               xc.num_distances = C.int(numDistances)
+               cDistances := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.distances))[:numDistances:numDistances]
+               for i, v := range x.Distances {
+                       cDistances[i] = C.uint32_t(v)
+               }
        }
        xc.pnode = C.uint32_t(x.Pnode)
        xc.vcpus, err = x.Vcpus.toC()
@@ -644,20 +650,24 @@ func (x *DomainBuildInfo) fromC(xc 
*C.libxl_domain_build_info) error {
        if err := x.Nodemap.fromC(&xc.nodemap); err != nil {
                return err
        }
-       numVcpuHardAffinity := int(xc.num_vcpu_hard_affinity)
-       cVcpuHardAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_hard_affinity))[:numVcpuHardAffinity:numVcpuHardAffinity]
-       x.VcpuHardAffinity = make([]Bitmap, numVcpuHardAffinity)
-       for i, v := range cVcpuHardAffinity {
-               if err := x.VcpuHardAffinity[i].fromC(&v); err != nil {
-                       return err
+       x.VcpuHardAffinity = nil
+       if numVcpuHardAffinity := int(xc.num_vcpu_hard_affinity); 
numVcpuHardAffinity > 0 {
+               cVcpuHardAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_hard_affinity))[:numVcpuHardAffinity:numVcpuHardAffinity]
+               x.VcpuHardAffinity = make([]Bitmap, numVcpuHardAffinity)
+               for i, v := range cVcpuHardAffinity {
+                       if err := x.VcpuHardAffinity[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
-       numVcpuSoftAffinity := int(xc.num_vcpu_soft_affinity)
-       cVcpuSoftAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_soft_affinity))[:numVcpuSoftAffinity:numVcpuSoftAffinity]
-       x.VcpuSoftAffinity = make([]Bitmap, numVcpuSoftAffinity)
-       for i, v := range cVcpuSoftAffinity {
-               if err := x.VcpuSoftAffinity[i].fromC(&v); err != nil {
-                       return err
+       x.VcpuSoftAffinity = nil
+       if numVcpuSoftAffinity := int(xc.num_vcpu_soft_affinity); 
numVcpuSoftAffinity > 0 {
+               cVcpuSoftAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_soft_affinity))[:numVcpuSoftAffinity:numVcpuSoftAffinity]
+               x.VcpuSoftAffinity = make([]Bitmap, numVcpuSoftAffinity)
+               for i, v := range cVcpuSoftAffinity {
+                       if err := x.VcpuSoftAffinity[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
        if err := x.NumaPlacement.fromC(&xc.numa_placement); err != nil {
@@ -682,12 +692,14 @@ func (x *DomainBuildInfo) fromC(xc 
*C.libxl_domain_build_info) error {
                return err
        }
        x.BlkdevStart = C.GoString(xc.blkdev_start)
-       numVnumaNodes := int(xc.num_vnuma_nodes)
-       cVnumaNodes := (*[1 << 
28]C.libxl_vnode_info)(unsafe.Pointer(xc.vnuma_nodes))[:numVnumaNodes:numVnumaNodes]
-       x.VnumaNodes = make([]VnodeInfo, numVnumaNodes)
-       for i, v := range cVnumaNodes {
-               if err := x.VnumaNodes[i].fromC(&v); err != nil {
-                       return err
+       x.VnumaNodes = nil
+       if numVnumaNodes := int(xc.num_vnuma_nodes); numVnumaNodes > 0 {
+               cVnumaNodes := (*[1 << 
28]C.libxl_vnode_info)(unsafe.Pointer(xc.vnuma_nodes))[:numVnumaNodes:numVnumaNodes]
+               x.VnumaNodes = make([]VnodeInfo, numVnumaNodes)
+               for i, v := range cVnumaNodes {
+                       if err := x.VnumaNodes[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
        x.MaxGrantFrames = uint32(xc.max_grant_frames)
@@ -712,26 +724,32 @@ func (x *DomainBuildInfo) fromC(xc 
*C.libxl_domain_build_info) error {
        if err := x.SchedParams.fromC(&xc.sched_params); err != nil {
                return err
        }
-       numIoports := int(xc.num_ioports)
-       cIoports := (*[1 << 
28]C.libxl_ioport_range)(unsafe.Pointer(xc.ioports))[:numIoports:numIoports]
-       x.Ioports = make([]IoportRange, numIoports)
-       for i, v := range cIoports {
-               if err := x.Ioports[i].fromC(&v); err != nil {
-                       return err
+       x.Ioports = nil
+       if numIoports := int(xc.num_ioports); numIoports > 0 {
+               cIoports := (*[1 << 
28]C.libxl_ioport_range)(unsafe.Pointer(xc.ioports))[:numIoports:numIoports]
+               x.Ioports = make([]IoportRange, numIoports)
+               for i, v := range cIoports {
+                       if err := x.Ioports[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
-       numIrqs := int(xc.num_irqs)
-       cIrqs := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.irqs))[:numIrqs:numIrqs]
-       x.Irqs = make([]uint32, numIrqs)
-       for i, v := range cIrqs {
-               x.Irqs[i] = uint32(v)
+       x.Irqs = nil
+       if numIrqs := int(xc.num_irqs); numIrqs > 0 {
+               cIrqs := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.irqs))[:numIrqs:numIrqs]
+               x.Irqs = make([]uint32, numIrqs)
+               for i, v := range cIrqs {
+                       x.Irqs[i] = uint32(v)
+               }
        }
-       numIomem := int(xc.num_iomem)
-       cIomem := (*[1 << 
28]C.libxl_iomem_range)(unsafe.Pointer(xc.iomem))[:numIomem:numIomem]
-       x.Iomem = make([]IomemRange, numIomem)
-       for i, v := range cIomem {
-               if err := x.Iomem[i].fromC(&v); err != nil {
-                       return err
+       x.Iomem = nil
+       if numIomem := int(xc.num_iomem); numIomem > 0 {
+               cIomem := (*[1 << 
28]C.libxl_iomem_range)(unsafe.Pointer(xc.iomem))[:numIomem:numIomem]
+               x.Iomem = make([]IomemRange, numIomem)
+               for i, v := range cIomem {
+                       if err := x.Iomem[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
        if err := x.ClaimMode.fromC(&xc.claim_mode); err != nil {
@@ -762,18 +780,18 @@ func (x *DomainBuildInfo) fromC(xc 
*C.libxl_domain_build_info) error {
        x.Tee = TeeType(xc.tee)
        x.Type = DomainType(xc._type)
        switch x.Type {
-       case DomainTypePv:
-               var typePv DomainBuildInfoTypeUnionPv
-               if err := typePv.fromC(xc); err != nil {
-                       return err
-               }
-               x.TypeUnion = typePv
        case DomainTypeHvm:
                var typeHvm DomainBuildInfoTypeUnionHvm
                if err := typeHvm.fromC(xc); err != nil {
                        return err
                }
                x.TypeUnion = typeHvm
+       case DomainTypePv:
+               var typePv DomainBuildInfoTypeUnionPv
+               if err := typePv.fromC(xc); err != nil {
+                       return err
+               }
+               x.TypeUnion = typePv
        case DomainTypePvh:
                var typePvh DomainBuildInfoTypeUnionPvh
                if err := typePvh.fromC(xc); err != nil {
@@ -953,29 +971,31 @@ func (x *DomainBuildInfo) toC() (xc 
C.libxl_domain_build_info, err error) {
                C.libxl_domain_build_info_dispose(&xc)
                return xc, err
        }
-       numVcpuHardAffinity := len(x.VcpuHardAffinity)
-       xc.vcpu_hard_affinity = 
(*C.libxl_bitmap)(C.malloc(C.ulong(numVcpuHardAffinity) * 
C.sizeof_libxl_bitmap))
-       xc.num_vcpu_hard_affinity = C.int(numVcpuHardAffinity)
-       cVcpuHardAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_hard_affinity))[:numVcpuHardAffinity:numVcpuHardAffinity]
-       for i, v := range x.VcpuHardAffinity {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_build_info_dispose(&xc)
-                       return xc, err
-               }
-               cVcpuHardAffinity[i] = tmp
-       }
-       numVcpuSoftAffinity := len(x.VcpuSoftAffinity)
-       xc.vcpu_soft_affinity = 
(*C.libxl_bitmap)(C.malloc(C.ulong(numVcpuSoftAffinity) * 
C.sizeof_libxl_bitmap))
-       xc.num_vcpu_soft_affinity = C.int(numVcpuSoftAffinity)
-       cVcpuSoftAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_soft_affinity))[:numVcpuSoftAffinity:numVcpuSoftAffinity]
-       for i, v := range x.VcpuSoftAffinity {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_build_info_dispose(&xc)
-                       return xc, err
+       if numVcpuHardAffinity := len(x.VcpuHardAffinity); numVcpuHardAffinity 
> 0 {
+               xc.vcpu_hard_affinity = 
(*C.libxl_bitmap)(C.malloc(C.ulong(numVcpuHardAffinity) * 
C.sizeof_libxl_bitmap))
+               xc.num_vcpu_hard_affinity = C.int(numVcpuHardAffinity)
+               cVcpuHardAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_hard_affinity))[:numVcpuHardAffinity:numVcpuHardAffinity]
+               for i, v := range x.VcpuHardAffinity {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_build_info_dispose(&xc)
+                               return xc, err
+                       }
+                       cVcpuHardAffinity[i] = tmp
+               }
+       }
+       if numVcpuSoftAffinity := len(x.VcpuSoftAffinity); numVcpuSoftAffinity 
> 0 {
+               xc.vcpu_soft_affinity = 
(*C.libxl_bitmap)(C.malloc(C.ulong(numVcpuSoftAffinity) * 
C.sizeof_libxl_bitmap))
+               xc.num_vcpu_soft_affinity = C.int(numVcpuSoftAffinity)
+               cVcpuSoftAffinity := (*[1 << 
28]C.libxl_bitmap)(unsafe.Pointer(xc.vcpu_soft_affinity))[:numVcpuSoftAffinity:numVcpuSoftAffinity]
+               for i, v := range x.VcpuSoftAffinity {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_build_info_dispose(&xc)
+                               return xc, err
+                       }
+                       cVcpuSoftAffinity[i] = tmp
                }
-               cVcpuSoftAffinity[i] = tmp
        }
        xc.numa_placement, err = x.NumaPlacement.toC()
        if err != nil {
@@ -1007,17 +1027,18 @@ func (x *DomainBuildInfo) toC() (xc 
C.libxl_domain_build_info, err error) {
                return xc, err
        }
        xc.blkdev_start = C.CString(x.BlkdevStart)
-       numVnumaNodes := len(x.VnumaNodes)
-       xc.vnuma_nodes = (*C.libxl_vnode_info)(C.malloc(C.ulong(numVnumaNodes) 
* C.sizeof_libxl_vnode_info))
-       xc.num_vnuma_nodes = C.int(numVnumaNodes)
-       cVnumaNodes := (*[1 << 
28]C.libxl_vnode_info)(unsafe.Pointer(xc.vnuma_nodes))[:numVnumaNodes:numVnumaNodes]
-       for i, v := range x.VnumaNodes {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_build_info_dispose(&xc)
-                       return xc, err
+       if numVnumaNodes := len(x.VnumaNodes); numVnumaNodes > 0 {
+               xc.vnuma_nodes = 
(*C.libxl_vnode_info)(C.malloc(C.ulong(numVnumaNodes) * 
C.sizeof_libxl_vnode_info))
+               xc.num_vnuma_nodes = C.int(numVnumaNodes)
+               cVnumaNodes := (*[1 << 
28]C.libxl_vnode_info)(unsafe.Pointer(xc.vnuma_nodes))[:numVnumaNodes:numVnumaNodes]
+               for i, v := range x.VnumaNodes {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_build_info_dispose(&xc)
+                               return xc, err
+                       }
+                       cVnumaNodes[i] = tmp
                }
-               cVnumaNodes[i] = tmp
        }
        xc.max_grant_frames = C.uint32_t(x.MaxGrantFrames)
        xc.max_maptrack_frames = C.uint32_t(x.MaxMaptrackFrames)
@@ -1051,36 +1072,39 @@ func (x *DomainBuildInfo) toC() (xc 
C.libxl_domain_build_info, err error) {
                C.libxl_domain_build_info_dispose(&xc)
                return xc, err
        }
-       numIoports := len(x.Ioports)
-       xc.ioports = (*C.libxl_ioport_range)(C.malloc(C.ulong(numIoports) * 
C.sizeof_libxl_ioport_range))
-       xc.num_ioports = C.int(numIoports)
-       cIoports := (*[1 << 
28]C.libxl_ioport_range)(unsafe.Pointer(xc.ioports))[:numIoports:numIoports]
-       for i, v := range x.Ioports {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_build_info_dispose(&xc)
-                       return xc, err
-               }
-               cIoports[i] = tmp
-       }
-       numIrqs := len(x.Irqs)
-       xc.irqs = (*C.uint32_t)(C.malloc(C.size_t(numIrqs * numIrqs)))
-       xc.num_irqs = C.int(numIrqs)
-       cIrqs := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.irqs))[:numIrqs:numIrqs]
-       for i, v := range x.Irqs {
-               cIrqs[i] = C.uint32_t(v)
-       }
-       numIomem := len(x.Iomem)
-       xc.iomem = (*C.libxl_iomem_range)(C.malloc(C.ulong(numIomem) * 
C.sizeof_libxl_iomem_range))
-       xc.num_iomem = C.int(numIomem)
-       cIomem := (*[1 << 
28]C.libxl_iomem_range)(unsafe.Pointer(xc.iomem))[:numIomem:numIomem]
-       for i, v := range x.Iomem {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_build_info_dispose(&xc)
-                       return xc, err
+       if numIoports := len(x.Ioports); numIoports > 0 {
+               xc.ioports = 
(*C.libxl_ioport_range)(C.malloc(C.ulong(numIoports) * 
C.sizeof_libxl_ioport_range))
+               xc.num_ioports = C.int(numIoports)
+               cIoports := (*[1 << 
28]C.libxl_ioport_range)(unsafe.Pointer(xc.ioports))[:numIoports:numIoports]
+               for i, v := range x.Ioports {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_build_info_dispose(&xc)
+                               return xc, err
+                       }
+                       cIoports[i] = tmp
+               }
+       }
+       if numIrqs := len(x.Irqs); numIrqs > 0 {
+               xc.irqs = (*C.uint32_t)(C.malloc(C.size_t(numIrqs * numIrqs)))
+               xc.num_irqs = C.int(numIrqs)
+               cIrqs := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.irqs))[:numIrqs:numIrqs]
+               for i, v := range x.Irqs {
+                       cIrqs[i] = C.uint32_t(v)
+               }
+       }
+       if numIomem := len(x.Iomem); numIomem > 0 {
+               xc.iomem = (*C.libxl_iomem_range)(C.malloc(C.ulong(numIomem) * 
C.sizeof_libxl_iomem_range))
+               xc.num_iomem = C.int(numIomem)
+               cIomem := (*[1 << 
28]C.libxl_iomem_range)(unsafe.Pointer(xc.iomem))[:numIomem:numIomem]
+               for i, v := range x.Iomem {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_build_info_dispose(&xc)
+                               return xc, err
+                       }
+                       cIomem[i] = tmp
                }
-               cIomem[i] = tmp
        }
        xc.claim_mode, err = x.ClaimMode.toC()
        if err != nil {
@@ -1889,12 +1913,14 @@ func (x *DeviceVdispl) fromC(xc *C.libxl_device_vdispl) 
error {
        x.BackendDomname = C.GoString(xc.backend_domname)
        x.Devid = Devid(xc.devid)
        x.BeAlloc = bool(xc.be_alloc)
-       numConnectors := int(xc.num_connectors)
-       cConnectors := (*[1 << 
28]C.libxl_connector_param)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
-       x.Connectors = make([]ConnectorParam, numConnectors)
-       for i, v := range cConnectors {
-               if err := x.Connectors[i].fromC(&v); err != nil {
-                       return err
+       x.Connectors = nil
+       if numConnectors := int(xc.num_connectors); numConnectors > 0 {
+               cConnectors := (*[1 << 
28]C.libxl_connector_param)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
+               x.Connectors = make([]ConnectorParam, numConnectors)
+               for i, v := range cConnectors {
+                       if err := x.Connectors[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -1907,33 +1933,38 @@ func (x *DeviceVdispl) toC() (xc C.libxl_device_vdispl, 
err error) {
        xc.backend_domname = C.CString(x.BackendDomname)
        xc.devid = C.libxl_devid(x.Devid)
        xc.be_alloc = C.bool(x.BeAlloc)
-       numConnectors := len(x.Connectors)
-       xc.connectors = 
(*C.libxl_connector_param)(C.malloc(C.ulong(numConnectors) * 
C.sizeof_libxl_connector_param))
-       xc.num_connectors = C.int(numConnectors)
-       cConnectors := (*[1 << 
28]C.libxl_connector_param)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
-       for i, v := range x.Connectors {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_device_vdispl_dispose(&xc)
-                       return xc, err
+       if numConnectors := len(x.Connectors); numConnectors > 0 {
+               xc.connectors = 
(*C.libxl_connector_param)(C.malloc(C.ulong(numConnectors) * 
C.sizeof_libxl_connector_param))
+               xc.num_connectors = C.int(numConnectors)
+               cConnectors := (*[1 << 
28]C.libxl_connector_param)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
+               for i, v := range x.Connectors {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_device_vdispl_dispose(&xc)
+                               return xc, err
+                       }
+                       cConnectors[i] = tmp
                }
-               cConnectors[i] = tmp
        }
        return xc, nil
 }
 
 func (x *VsndParams) fromC(xc *C.libxl_vsnd_params) error {
-       numSampleRates := int(xc.num_sample_rates)
-       cSampleRates := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.sample_rates))[:numSampleRates:numSampleRates]
-       x.SampleRates = make([]uint32, numSampleRates)
-       for i, v := range cSampleRates {
-               x.SampleRates[i] = uint32(v)
-       }
-       numSampleFormats := int(xc.num_sample_formats)
-       cSampleFormats := (*[1 << 
28]C.libxl_vsnd_pcm_format)(unsafe.Pointer(xc.sample_formats))[:numSampleFormats:numSampleFormats]
-       x.SampleFormats = make([]VsndPcmFormat, numSampleFormats)
-       for i, v := range cSampleFormats {
-               x.SampleFormats[i] = VsndPcmFormat(v)
+       x.SampleRates = nil
+       if numSampleRates := int(xc.num_sample_rates); numSampleRates > 0 {
+               cSampleRates := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.sample_rates))[:numSampleRates:numSampleRates]
+               x.SampleRates = make([]uint32, numSampleRates)
+               for i, v := range cSampleRates {
+                       x.SampleRates[i] = uint32(v)
+               }
+       }
+       x.SampleFormats = nil
+       if numSampleFormats := int(xc.num_sample_formats); numSampleFormats > 0 
{
+               cSampleFormats := (*[1 << 
28]C.libxl_vsnd_pcm_format)(unsafe.Pointer(xc.sample_formats))[:numSampleFormats:numSampleFormats]
+               x.SampleFormats = make([]VsndPcmFormat, numSampleFormats)
+               for i, v := range cSampleFormats {
+                       x.SampleFormats[i] = VsndPcmFormat(v)
+               }
        }
        x.ChannelsMin = uint32(xc.channels_min)
        x.ChannelsMax = uint32(xc.channels_max)
@@ -1944,19 +1975,21 @@ func (x *VsndParams) fromC(xc *C.libxl_vsnd_params) 
error {
 
 func (x *VsndParams) toC() (xc C.libxl_vsnd_params, err error) {
        C.libxl_vsnd_params_init(&xc)
-       numSampleRates := len(x.SampleRates)
-       xc.sample_rates = (*C.uint32_t)(C.malloc(C.size_t(numSampleRates * 
numSampleRates)))
-       xc.num_sample_rates = C.int(numSampleRates)
-       cSampleRates := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.sample_rates))[:numSampleRates:numSampleRates]
-       for i, v := range x.SampleRates {
-               cSampleRates[i] = C.uint32_t(v)
-       }
-       numSampleFormats := len(x.SampleFormats)
-       xc.sample_formats = 
(*C.libxl_vsnd_pcm_format)(C.malloc(C.size_t(numSampleFormats * 
numSampleFormats)))
-       xc.num_sample_formats = C.int(numSampleFormats)
-       cSampleFormats := (*[1 << 
28]C.libxl_vsnd_pcm_format)(unsafe.Pointer(xc.sample_formats))[:numSampleFormats:numSampleFormats]
-       for i, v := range x.SampleFormats {
-               cSampleFormats[i] = C.libxl_vsnd_pcm_format(v)
+       if numSampleRates := len(x.SampleRates); numSampleRates > 0 {
+               xc.sample_rates = 
(*C.uint32_t)(C.malloc(C.size_t(numSampleRates * numSampleRates)))
+               xc.num_sample_rates = C.int(numSampleRates)
+               cSampleRates := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.sample_rates))[:numSampleRates:numSampleRates]
+               for i, v := range x.SampleRates {
+                       cSampleRates[i] = C.uint32_t(v)
+               }
+       }
+       if numSampleFormats := len(x.SampleFormats); numSampleFormats > 0 {
+               xc.sample_formats = 
(*C.libxl_vsnd_pcm_format)(C.malloc(C.size_t(numSampleFormats * 
numSampleFormats)))
+               xc.num_sample_formats = C.int(numSampleFormats)
+               cSampleFormats := (*[1 << 
28]C.libxl_vsnd_pcm_format)(unsafe.Pointer(xc.sample_formats))[:numSampleFormats:numSampleFormats]
+               for i, v := range x.SampleFormats {
+                       cSampleFormats[i] = C.libxl_vsnd_pcm_format(v)
+               }
        }
        xc.channels_min = C.uint32_t(x.ChannelsMin)
        xc.channels_max = C.uint32_t(x.ChannelsMax)
@@ -1991,12 +2024,14 @@ func (x *VsndPcm) fromC(xc *C.libxl_vsnd_pcm) error {
        if err := x.Params.fromC(&xc.params); err != nil {
                return err
        }
-       numVsndStreams := int(xc.num_vsnd_streams)
-       cStreams := (*[1 << 
28]C.libxl_vsnd_stream)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
-       x.Streams = make([]VsndStream, numVsndStreams)
-       for i, v := range cStreams {
-               if err := x.Streams[i].fromC(&v); err != nil {
-                       return err
+       x.Streams = nil
+       if numVsndStreams := int(xc.num_vsnd_streams); numVsndStreams > 0 {
+               cStreams := (*[1 << 
28]C.libxl_vsnd_stream)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
+               x.Streams = make([]VsndStream, numVsndStreams)
+               for i, v := range cStreams {
+                       if err := x.Streams[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -2011,17 +2046,18 @@ func (x *VsndPcm) toC() (xc C.libxl_vsnd_pcm, err 
error) {
                C.libxl_vsnd_pcm_dispose(&xc)
                return xc, err
        }
-       numVsndStreams := len(x.Streams)
-       xc.streams = (*C.libxl_vsnd_stream)(C.malloc(C.ulong(numVsndStreams) * 
C.sizeof_libxl_vsnd_stream))
-       xc.num_vsnd_streams = C.int(numVsndStreams)
-       cStreams := (*[1 << 
28]C.libxl_vsnd_stream)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
-       for i, v := range x.Streams {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_vsnd_pcm_dispose(&xc)
-                       return xc, err
+       if numVsndStreams := len(x.Streams); numVsndStreams > 0 {
+               xc.streams = 
(*C.libxl_vsnd_stream)(C.malloc(C.ulong(numVsndStreams) * 
C.sizeof_libxl_vsnd_stream))
+               xc.num_vsnd_streams = C.int(numVsndStreams)
+               cStreams := (*[1 << 
28]C.libxl_vsnd_stream)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
+               for i, v := range x.Streams {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_vsnd_pcm_dispose(&xc)
+                               return xc, err
+                       }
+                       cStreams[i] = tmp
                }
-               cStreams[i] = tmp
        }
        return xc, nil
 }
@@ -2035,12 +2071,14 @@ func (x *DeviceVsnd) fromC(xc *C.libxl_device_vsnd) 
error {
        if err := x.Params.fromC(&xc.params); err != nil {
                return err
        }
-       numVsndPcms := int(xc.num_vsnd_pcms)
-       cPcms := (*[1 << 
28]C.libxl_vsnd_pcm)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
-       x.Pcms = make([]VsndPcm, numVsndPcms)
-       for i, v := range cPcms {
-               if err := x.Pcms[i].fromC(&v); err != nil {
-                       return err
+       x.Pcms = nil
+       if numVsndPcms := int(xc.num_vsnd_pcms); numVsndPcms > 0 {
+               cPcms := (*[1 << 
28]C.libxl_vsnd_pcm)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
+               x.Pcms = make([]VsndPcm, numVsndPcms)
+               for i, v := range cPcms {
+                       if err := x.Pcms[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -2059,17 +2097,18 @@ func (x *DeviceVsnd) toC() (xc C.libxl_device_vsnd, err 
error) {
                C.libxl_device_vsnd_dispose(&xc)
                return xc, err
        }
-       numVsndPcms := len(x.Pcms)
-       xc.pcms = (*C.libxl_vsnd_pcm)(C.malloc(C.ulong(numVsndPcms) * 
C.sizeof_libxl_vsnd_pcm))
-       xc.num_vsnd_pcms = C.int(numVsndPcms)
-       cPcms := (*[1 << 
28]C.libxl_vsnd_pcm)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
-       for i, v := range x.Pcms {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_device_vsnd_dispose(&xc)
-                       return xc, err
+       if numVsndPcms := len(x.Pcms); numVsndPcms > 0 {
+               xc.pcms = (*C.libxl_vsnd_pcm)(C.malloc(C.ulong(numVsndPcms) * 
C.sizeof_libxl_vsnd_pcm))
+               xc.num_vsnd_pcms = C.int(numVsndPcms)
+               cPcms := (*[1 << 
28]C.libxl_vsnd_pcm)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
+               for i, v := range x.Pcms {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_device_vsnd_dispose(&xc)
+                               return xc, err
+                       }
+                       cPcms[i] = tmp
                }
-               cPcms[i] = tmp
        }
        return xc, nil
 }
@@ -2081,124 +2120,154 @@ func (x *DomainConfig) fromC(xc 
*C.libxl_domain_config) error {
        if err := x.BInfo.fromC(&xc.b_info); err != nil {
                return err
        }
-       numDisks := int(xc.num_disks)
-       cDisks := (*[1 << 
28]C.libxl_device_disk)(unsafe.Pointer(xc.disks))[:numDisks:numDisks]
-       x.Disks = make([]DeviceDisk, numDisks)
-       for i, v := range cDisks {
-               if err := x.Disks[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numNics := int(xc.num_nics)
-       cNics := (*[1 << 
28]C.libxl_device_nic)(unsafe.Pointer(xc.nics))[:numNics:numNics]
-       x.Nics = make([]DeviceNic, numNics)
-       for i, v := range cNics {
-               if err := x.Nics[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numPcidevs := int(xc.num_pcidevs)
-       cPcidevs := (*[1 << 
28]C.libxl_device_pci)(unsafe.Pointer(xc.pcidevs))[:numPcidevs:numPcidevs]
-       x.Pcidevs = make([]DevicePci, numPcidevs)
-       for i, v := range cPcidevs {
-               if err := x.Pcidevs[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numRdms := int(xc.num_rdms)
-       cRdms := (*[1 << 
28]C.libxl_device_rdm)(unsafe.Pointer(xc.rdms))[:numRdms:numRdms]
-       x.Rdms = make([]DeviceRdm, numRdms)
-       for i, v := range cRdms {
-               if err := x.Rdms[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numDtdevs := int(xc.num_dtdevs)
-       cDtdevs := (*[1 << 
28]C.libxl_device_dtdev)(unsafe.Pointer(xc.dtdevs))[:numDtdevs:numDtdevs]
-       x.Dtdevs = make([]DeviceDtdev, numDtdevs)
-       for i, v := range cDtdevs {
-               if err := x.Dtdevs[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numVfbs := int(xc.num_vfbs)
-       cVfbs := (*[1 << 
28]C.libxl_device_vfb)(unsafe.Pointer(xc.vfbs))[:numVfbs:numVfbs]
-       x.Vfbs = make([]DeviceVfb, numVfbs)
-       for i, v := range cVfbs {
-               if err := x.Vfbs[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numVkbs := int(xc.num_vkbs)
-       cVkbs := (*[1 << 
28]C.libxl_device_vkb)(unsafe.Pointer(xc.vkbs))[:numVkbs:numVkbs]
-       x.Vkbs = make([]DeviceVkb, numVkbs)
-       for i, v := range cVkbs {
-               if err := x.Vkbs[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numVtpms := int(xc.num_vtpms)
-       cVtpms := (*[1 << 
28]C.libxl_device_vtpm)(unsafe.Pointer(xc.vtpms))[:numVtpms:numVtpms]
-       x.Vtpms = make([]DeviceVtpm, numVtpms)
-       for i, v := range cVtpms {
-               if err := x.Vtpms[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numP9S := int(xc.num_p9s)
-       cP9S := (*[1 << 
28]C.libxl_device_p9)(unsafe.Pointer(xc.p9s))[:numP9S:numP9S]
-       x.P9S = make([]DeviceP9, numP9S)
-       for i, v := range cP9S {
-               if err := x.P9S[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numPvcallsifs := int(xc.num_pvcallsifs)
-       cPvcallsifs := (*[1 << 
28]C.libxl_device_pvcallsif)(unsafe.Pointer(xc.pvcallsifs))[:numPvcallsifs:numPvcallsifs]
-       x.Pvcallsifs = make([]DevicePvcallsif, numPvcallsifs)
-       for i, v := range cPvcallsifs {
-               if err := x.Pvcallsifs[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numVdispls := int(xc.num_vdispls)
-       cVdispls := (*[1 << 
28]C.libxl_device_vdispl)(unsafe.Pointer(xc.vdispls))[:numVdispls:numVdispls]
-       x.Vdispls = make([]DeviceVdispl, numVdispls)
-       for i, v := range cVdispls {
-               if err := x.Vdispls[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numVsnds := int(xc.num_vsnds)
-       cVsnds := (*[1 << 
28]C.libxl_device_vsnd)(unsafe.Pointer(xc.vsnds))[:numVsnds:numVsnds]
-       x.Vsnds = make([]DeviceVsnd, numVsnds)
-       for i, v := range cVsnds {
-               if err := x.Vsnds[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numChannels := int(xc.num_channels)
-       cChannels := (*[1 << 
28]C.libxl_device_channel)(unsafe.Pointer(xc.channels))[:numChannels:numChannels]
-       x.Channels = make([]DeviceChannel, numChannels)
-       for i, v := range cChannels {
-               if err := x.Channels[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numUsbctrls := int(xc.num_usbctrls)
-       cUsbctrls := (*[1 << 
28]C.libxl_device_usbctrl)(unsafe.Pointer(xc.usbctrls))[:numUsbctrls:numUsbctrls]
-       x.Usbctrls = make([]DeviceUsbctrl, numUsbctrls)
-       for i, v := range cUsbctrls {
-               if err := x.Usbctrls[i].fromC(&v); err != nil {
-                       return err
-               }
-       }
-       numUsbdevs := int(xc.num_usbdevs)
-       cUsbdevs := (*[1 << 
28]C.libxl_device_usbdev)(unsafe.Pointer(xc.usbdevs))[:numUsbdevs:numUsbdevs]
-       x.Usbdevs = make([]DeviceUsbdev, numUsbdevs)
-       for i, v := range cUsbdevs {
-               if err := x.Usbdevs[i].fromC(&v); err != nil {
-                       return err
+       x.Disks = nil
+       if numDisks := int(xc.num_disks); numDisks > 0 {
+               cDisks := (*[1 << 
28]C.libxl_device_disk)(unsafe.Pointer(xc.disks))[:numDisks:numDisks]
+               x.Disks = make([]DeviceDisk, numDisks)
+               for i, v := range cDisks {
+                       if err := x.Disks[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Nics = nil
+       if numNics := int(xc.num_nics); numNics > 0 {
+               cNics := (*[1 << 
28]C.libxl_device_nic)(unsafe.Pointer(xc.nics))[:numNics:numNics]
+               x.Nics = make([]DeviceNic, numNics)
+               for i, v := range cNics {
+                       if err := x.Nics[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Pcidevs = nil
+       if numPcidevs := int(xc.num_pcidevs); numPcidevs > 0 {
+               cPcidevs := (*[1 << 
28]C.libxl_device_pci)(unsafe.Pointer(xc.pcidevs))[:numPcidevs:numPcidevs]
+               x.Pcidevs = make([]DevicePci, numPcidevs)
+               for i, v := range cPcidevs {
+                       if err := x.Pcidevs[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Rdms = nil
+       if numRdms := int(xc.num_rdms); numRdms > 0 {
+               cRdms := (*[1 << 
28]C.libxl_device_rdm)(unsafe.Pointer(xc.rdms))[:numRdms:numRdms]
+               x.Rdms = make([]DeviceRdm, numRdms)
+               for i, v := range cRdms {
+                       if err := x.Rdms[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Dtdevs = nil
+       if numDtdevs := int(xc.num_dtdevs); numDtdevs > 0 {
+               cDtdevs := (*[1 << 
28]C.libxl_device_dtdev)(unsafe.Pointer(xc.dtdevs))[:numDtdevs:numDtdevs]
+               x.Dtdevs = make([]DeviceDtdev, numDtdevs)
+               for i, v := range cDtdevs {
+                       if err := x.Dtdevs[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Vfbs = nil
+       if numVfbs := int(xc.num_vfbs); numVfbs > 0 {
+               cVfbs := (*[1 << 
28]C.libxl_device_vfb)(unsafe.Pointer(xc.vfbs))[:numVfbs:numVfbs]
+               x.Vfbs = make([]DeviceVfb, numVfbs)
+               for i, v := range cVfbs {
+                       if err := x.Vfbs[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Vkbs = nil
+       if numVkbs := int(xc.num_vkbs); numVkbs > 0 {
+               cVkbs := (*[1 << 
28]C.libxl_device_vkb)(unsafe.Pointer(xc.vkbs))[:numVkbs:numVkbs]
+               x.Vkbs = make([]DeviceVkb, numVkbs)
+               for i, v := range cVkbs {
+                       if err := x.Vkbs[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Vtpms = nil
+       if numVtpms := int(xc.num_vtpms); numVtpms > 0 {
+               cVtpms := (*[1 << 
28]C.libxl_device_vtpm)(unsafe.Pointer(xc.vtpms))[:numVtpms:numVtpms]
+               x.Vtpms = make([]DeviceVtpm, numVtpms)
+               for i, v := range cVtpms {
+                       if err := x.Vtpms[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.P9S = nil
+       if numP9S := int(xc.num_p9s); numP9S > 0 {
+               cP9S := (*[1 << 
28]C.libxl_device_p9)(unsafe.Pointer(xc.p9s))[:numP9S:numP9S]
+               x.P9S = make([]DeviceP9, numP9S)
+               for i, v := range cP9S {
+                       if err := x.P9S[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Pvcallsifs = nil
+       if numPvcallsifs := int(xc.num_pvcallsifs); numPvcallsifs > 0 {
+               cPvcallsifs := (*[1 << 
28]C.libxl_device_pvcallsif)(unsafe.Pointer(xc.pvcallsifs))[:numPvcallsifs:numPvcallsifs]
+               x.Pvcallsifs = make([]DevicePvcallsif, numPvcallsifs)
+               for i, v := range cPvcallsifs {
+                       if err := x.Pvcallsifs[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Vdispls = nil
+       if numVdispls := int(xc.num_vdispls); numVdispls > 0 {
+               cVdispls := (*[1 << 
28]C.libxl_device_vdispl)(unsafe.Pointer(xc.vdispls))[:numVdispls:numVdispls]
+               x.Vdispls = make([]DeviceVdispl, numVdispls)
+               for i, v := range cVdispls {
+                       if err := x.Vdispls[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Vsnds = nil
+       if numVsnds := int(xc.num_vsnds); numVsnds > 0 {
+               cVsnds := (*[1 << 
28]C.libxl_device_vsnd)(unsafe.Pointer(xc.vsnds))[:numVsnds:numVsnds]
+               x.Vsnds = make([]DeviceVsnd, numVsnds)
+               for i, v := range cVsnds {
+                       if err := x.Vsnds[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Channels = nil
+       if numChannels := int(xc.num_channels); numChannels > 0 {
+               cChannels := (*[1 << 
28]C.libxl_device_channel)(unsafe.Pointer(xc.channels))[:numChannels:numChannels]
+               x.Channels = make([]DeviceChannel, numChannels)
+               for i, v := range cChannels {
+                       if err := x.Channels[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Usbctrls = nil
+       if numUsbctrls := int(xc.num_usbctrls); numUsbctrls > 0 {
+               cUsbctrls := (*[1 << 
28]C.libxl_device_usbctrl)(unsafe.Pointer(xc.usbctrls))[:numUsbctrls:numUsbctrls]
+               x.Usbctrls = make([]DeviceUsbctrl, numUsbctrls)
+               for i, v := range cUsbctrls {
+                       if err := x.Usbctrls[i].fromC(&v); err != nil {
+                               return err
+                       }
+               }
+       }
+       x.Usbdevs = nil
+       if numUsbdevs := int(xc.num_usbdevs); numUsbdevs > 0 {
+               cUsbdevs := (*[1 << 
28]C.libxl_device_usbdev)(unsafe.Pointer(xc.usbdevs))[:numUsbdevs:numUsbdevs]
+               x.Usbdevs = make([]DeviceUsbdev, numUsbdevs)
+               for i, v := range cUsbdevs {
+                       if err := x.Usbdevs[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
        x.OnPoweroff = ActionOnShutdown(xc.on_poweroff)
@@ -2222,185 +2291,200 @@ func (x *DomainConfig) toC() (xc 
C.libxl_domain_config, err error) {
                C.libxl_domain_config_dispose(&xc)
                return xc, err
        }
-       numDisks := len(x.Disks)
-       xc.disks = (*C.libxl_device_disk)(C.malloc(C.ulong(numDisks) * 
C.sizeof_libxl_device_disk))
-       xc.num_disks = C.int(numDisks)
-       cDisks := (*[1 << 
28]C.libxl_device_disk)(unsafe.Pointer(xc.disks))[:numDisks:numDisks]
-       for i, v := range x.Disks {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cDisks[i] = tmp
-       }
-       numNics := len(x.Nics)
-       xc.nics = (*C.libxl_device_nic)(C.malloc(C.ulong(numNics) * 
C.sizeof_libxl_device_nic))
-       xc.num_nics = C.int(numNics)
-       cNics := (*[1 << 
28]C.libxl_device_nic)(unsafe.Pointer(xc.nics))[:numNics:numNics]
-       for i, v := range x.Nics {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cNics[i] = tmp
-       }
-       numPcidevs := len(x.Pcidevs)
-       xc.pcidevs = (*C.libxl_device_pci)(C.malloc(C.ulong(numPcidevs) * 
C.sizeof_libxl_device_pci))
-       xc.num_pcidevs = C.int(numPcidevs)
-       cPcidevs := (*[1 << 
28]C.libxl_device_pci)(unsafe.Pointer(xc.pcidevs))[:numPcidevs:numPcidevs]
-       for i, v := range x.Pcidevs {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cPcidevs[i] = tmp
-       }
-       numRdms := len(x.Rdms)
-       xc.rdms = (*C.libxl_device_rdm)(C.malloc(C.ulong(numRdms) * 
C.sizeof_libxl_device_rdm))
-       xc.num_rdms = C.int(numRdms)
-       cRdms := (*[1 << 
28]C.libxl_device_rdm)(unsafe.Pointer(xc.rdms))[:numRdms:numRdms]
-       for i, v := range x.Rdms {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cRdms[i] = tmp
-       }
-       numDtdevs := len(x.Dtdevs)
-       xc.dtdevs = (*C.libxl_device_dtdev)(C.malloc(C.ulong(numDtdevs) * 
C.sizeof_libxl_device_dtdev))
-       xc.num_dtdevs = C.int(numDtdevs)
-       cDtdevs := (*[1 << 
28]C.libxl_device_dtdev)(unsafe.Pointer(xc.dtdevs))[:numDtdevs:numDtdevs]
-       for i, v := range x.Dtdevs {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cDtdevs[i] = tmp
-       }
-       numVfbs := len(x.Vfbs)
-       xc.vfbs = (*C.libxl_device_vfb)(C.malloc(C.ulong(numVfbs) * 
C.sizeof_libxl_device_vfb))
-       xc.num_vfbs = C.int(numVfbs)
-       cVfbs := (*[1 << 
28]C.libxl_device_vfb)(unsafe.Pointer(xc.vfbs))[:numVfbs:numVfbs]
-       for i, v := range x.Vfbs {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cVfbs[i] = tmp
-       }
-       numVkbs := len(x.Vkbs)
-       xc.vkbs = (*C.libxl_device_vkb)(C.malloc(C.ulong(numVkbs) * 
C.sizeof_libxl_device_vkb))
-       xc.num_vkbs = C.int(numVkbs)
-       cVkbs := (*[1 << 
28]C.libxl_device_vkb)(unsafe.Pointer(xc.vkbs))[:numVkbs:numVkbs]
-       for i, v := range x.Vkbs {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cVkbs[i] = tmp
-       }
-       numVtpms := len(x.Vtpms)
-       xc.vtpms = (*C.libxl_device_vtpm)(C.malloc(C.ulong(numVtpms) * 
C.sizeof_libxl_device_vtpm))
-       xc.num_vtpms = C.int(numVtpms)
-       cVtpms := (*[1 << 
28]C.libxl_device_vtpm)(unsafe.Pointer(xc.vtpms))[:numVtpms:numVtpms]
-       for i, v := range x.Vtpms {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cVtpms[i] = tmp
-       }
-       numP9S := len(x.P9S)
-       xc.p9s = (*C.libxl_device_p9)(C.malloc(C.ulong(numP9S) * 
C.sizeof_libxl_device_p9))
-       xc.num_p9s = C.int(numP9S)
-       cP9S := (*[1 << 
28]C.libxl_device_p9)(unsafe.Pointer(xc.p9s))[:numP9S:numP9S]
-       for i, v := range x.P9S {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cP9S[i] = tmp
-       }
-       numPvcallsifs := len(x.Pvcallsifs)
-       xc.pvcallsifs = 
(*C.libxl_device_pvcallsif)(C.malloc(C.ulong(numPvcallsifs) * 
C.sizeof_libxl_device_pvcallsif))
-       xc.num_pvcallsifs = C.int(numPvcallsifs)
-       cPvcallsifs := (*[1 << 
28]C.libxl_device_pvcallsif)(unsafe.Pointer(xc.pvcallsifs))[:numPvcallsifs:numPvcallsifs]
-       for i, v := range x.Pvcallsifs {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cPvcallsifs[i] = tmp
-       }
-       numVdispls := len(x.Vdispls)
-       xc.vdispls = (*C.libxl_device_vdispl)(C.malloc(C.ulong(numVdispls) * 
C.sizeof_libxl_device_vdispl))
-       xc.num_vdispls = C.int(numVdispls)
-       cVdispls := (*[1 << 
28]C.libxl_device_vdispl)(unsafe.Pointer(xc.vdispls))[:numVdispls:numVdispls]
-       for i, v := range x.Vdispls {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cVdispls[i] = tmp
-       }
-       numVsnds := len(x.Vsnds)
-       xc.vsnds = (*C.libxl_device_vsnd)(C.malloc(C.ulong(numVsnds) * 
C.sizeof_libxl_device_vsnd))
-       xc.num_vsnds = C.int(numVsnds)
-       cVsnds := (*[1 << 
28]C.libxl_device_vsnd)(unsafe.Pointer(xc.vsnds))[:numVsnds:numVsnds]
-       for i, v := range x.Vsnds {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cVsnds[i] = tmp
-       }
-       numChannels := len(x.Channels)
-       xc.channels = (*C.libxl_device_channel)(C.malloc(C.ulong(numChannels) * 
C.sizeof_libxl_device_channel))
-       xc.num_channels = C.int(numChannels)
-       cChannels := (*[1 << 
28]C.libxl_device_channel)(unsafe.Pointer(xc.channels))[:numChannels:numChannels]
-       for i, v := range x.Channels {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cChannels[i] = tmp
-       }
-       numUsbctrls := len(x.Usbctrls)
-       xc.usbctrls = (*C.libxl_device_usbctrl)(C.malloc(C.ulong(numUsbctrls) * 
C.sizeof_libxl_device_usbctrl))
-       xc.num_usbctrls = C.int(numUsbctrls)
-       cUsbctrls := (*[1 << 
28]C.libxl_device_usbctrl)(unsafe.Pointer(xc.usbctrls))[:numUsbctrls:numUsbctrls]
-       for i, v := range x.Usbctrls {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
-               }
-               cUsbctrls[i] = tmp
-       }
-       numUsbdevs := len(x.Usbdevs)
-       xc.usbdevs = (*C.libxl_device_usbdev)(C.malloc(C.ulong(numUsbdevs) * 
C.sizeof_libxl_device_usbdev))
-       xc.num_usbdevs = C.int(numUsbdevs)
-       cUsbdevs := (*[1 << 
28]C.libxl_device_usbdev)(unsafe.Pointer(xc.usbdevs))[:numUsbdevs:numUsbdevs]
-       for i, v := range x.Usbdevs {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_domain_config_dispose(&xc)
-                       return xc, err
+       if numDisks := len(x.Disks); numDisks > 0 {
+               xc.disks = (*C.libxl_device_disk)(C.malloc(C.ulong(numDisks) * 
C.sizeof_libxl_device_disk))
+               xc.num_disks = C.int(numDisks)
+               cDisks := (*[1 << 
28]C.libxl_device_disk)(unsafe.Pointer(xc.disks))[:numDisks:numDisks]
+               for i, v := range x.Disks {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cDisks[i] = tmp
+               }
+       }
+       if numNics := len(x.Nics); numNics > 0 {
+               xc.nics = (*C.libxl_device_nic)(C.malloc(C.ulong(numNics) * 
C.sizeof_libxl_device_nic))
+               xc.num_nics = C.int(numNics)
+               cNics := (*[1 << 
28]C.libxl_device_nic)(unsafe.Pointer(xc.nics))[:numNics:numNics]
+               for i, v := range x.Nics {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cNics[i] = tmp
+               }
+       }
+       if numPcidevs := len(x.Pcidevs); numPcidevs > 0 {
+               xc.pcidevs = (*C.libxl_device_pci)(C.malloc(C.ulong(numPcidevs) 
* C.sizeof_libxl_device_pci))
+               xc.num_pcidevs = C.int(numPcidevs)
+               cPcidevs := (*[1 << 
28]C.libxl_device_pci)(unsafe.Pointer(xc.pcidevs))[:numPcidevs:numPcidevs]
+               for i, v := range x.Pcidevs {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cPcidevs[i] = tmp
+               }
+       }
+       if numRdms := len(x.Rdms); numRdms > 0 {
+               xc.rdms = (*C.libxl_device_rdm)(C.malloc(C.ulong(numRdms) * 
C.sizeof_libxl_device_rdm))
+               xc.num_rdms = C.int(numRdms)
+               cRdms := (*[1 << 
28]C.libxl_device_rdm)(unsafe.Pointer(xc.rdms))[:numRdms:numRdms]
+               for i, v := range x.Rdms {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cRdms[i] = tmp
+               }
+       }
+       if numDtdevs := len(x.Dtdevs); numDtdevs > 0 {
+               xc.dtdevs = (*C.libxl_device_dtdev)(C.malloc(C.ulong(numDtdevs) 
* C.sizeof_libxl_device_dtdev))
+               xc.num_dtdevs = C.int(numDtdevs)
+               cDtdevs := (*[1 << 
28]C.libxl_device_dtdev)(unsafe.Pointer(xc.dtdevs))[:numDtdevs:numDtdevs]
+               for i, v := range x.Dtdevs {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cDtdevs[i] = tmp
+               }
+       }
+       if numVfbs := len(x.Vfbs); numVfbs > 0 {
+               xc.vfbs = (*C.libxl_device_vfb)(C.malloc(C.ulong(numVfbs) * 
C.sizeof_libxl_device_vfb))
+               xc.num_vfbs = C.int(numVfbs)
+               cVfbs := (*[1 << 
28]C.libxl_device_vfb)(unsafe.Pointer(xc.vfbs))[:numVfbs:numVfbs]
+               for i, v := range x.Vfbs {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cVfbs[i] = tmp
+               }
+       }
+       if numVkbs := len(x.Vkbs); numVkbs > 0 {
+               xc.vkbs = (*C.libxl_device_vkb)(C.malloc(C.ulong(numVkbs) * 
C.sizeof_libxl_device_vkb))
+               xc.num_vkbs = C.int(numVkbs)
+               cVkbs := (*[1 << 
28]C.libxl_device_vkb)(unsafe.Pointer(xc.vkbs))[:numVkbs:numVkbs]
+               for i, v := range x.Vkbs {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cVkbs[i] = tmp
+               }
+       }
+       if numVtpms := len(x.Vtpms); numVtpms > 0 {
+               xc.vtpms = (*C.libxl_device_vtpm)(C.malloc(C.ulong(numVtpms) * 
C.sizeof_libxl_device_vtpm))
+               xc.num_vtpms = C.int(numVtpms)
+               cVtpms := (*[1 << 
28]C.libxl_device_vtpm)(unsafe.Pointer(xc.vtpms))[:numVtpms:numVtpms]
+               for i, v := range x.Vtpms {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cVtpms[i] = tmp
+               }
+       }
+       if numP9S := len(x.P9S); numP9S > 0 {
+               xc.p9s = (*C.libxl_device_p9)(C.malloc(C.ulong(numP9S) * 
C.sizeof_libxl_device_p9))
+               xc.num_p9s = C.int(numP9S)
+               cP9S := (*[1 << 
28]C.libxl_device_p9)(unsafe.Pointer(xc.p9s))[:numP9S:numP9S]
+               for i, v := range x.P9S {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cP9S[i] = tmp
+               }
+       }
+       if numPvcallsifs := len(x.Pvcallsifs); numPvcallsifs > 0 {
+               xc.pvcallsifs = 
(*C.libxl_device_pvcallsif)(C.malloc(C.ulong(numPvcallsifs) * 
C.sizeof_libxl_device_pvcallsif))
+               xc.num_pvcallsifs = C.int(numPvcallsifs)
+               cPvcallsifs := (*[1 << 
28]C.libxl_device_pvcallsif)(unsafe.Pointer(xc.pvcallsifs))[:numPvcallsifs:numPvcallsifs]
+               for i, v := range x.Pvcallsifs {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cPvcallsifs[i] = tmp
+               }
+       }
+       if numVdispls := len(x.Vdispls); numVdispls > 0 {
+               xc.vdispls = 
(*C.libxl_device_vdispl)(C.malloc(C.ulong(numVdispls) * 
C.sizeof_libxl_device_vdispl))
+               xc.num_vdispls = C.int(numVdispls)
+               cVdispls := (*[1 << 
28]C.libxl_device_vdispl)(unsafe.Pointer(xc.vdispls))[:numVdispls:numVdispls]
+               for i, v := range x.Vdispls {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cVdispls[i] = tmp
+               }
+       }
+       if numVsnds := len(x.Vsnds); numVsnds > 0 {
+               xc.vsnds = (*C.libxl_device_vsnd)(C.malloc(C.ulong(numVsnds) * 
C.sizeof_libxl_device_vsnd))
+               xc.num_vsnds = C.int(numVsnds)
+               cVsnds := (*[1 << 
28]C.libxl_device_vsnd)(unsafe.Pointer(xc.vsnds))[:numVsnds:numVsnds]
+               for i, v := range x.Vsnds {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cVsnds[i] = tmp
+               }
+       }
+       if numChannels := len(x.Channels); numChannels > 0 {
+               xc.channels = 
(*C.libxl_device_channel)(C.malloc(C.ulong(numChannels) * 
C.sizeof_libxl_device_channel))
+               xc.num_channels = C.int(numChannels)
+               cChannels := (*[1 << 
28]C.libxl_device_channel)(unsafe.Pointer(xc.channels))[:numChannels:numChannels]
+               for i, v := range x.Channels {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cChannels[i] = tmp
+               }
+       }
+       if numUsbctrls := len(x.Usbctrls); numUsbctrls > 0 {
+               xc.usbctrls = 
(*C.libxl_device_usbctrl)(C.malloc(C.ulong(numUsbctrls) * 
C.sizeof_libxl_device_usbctrl))
+               xc.num_usbctrls = C.int(numUsbctrls)
+               cUsbctrls := (*[1 << 
28]C.libxl_device_usbctrl)(unsafe.Pointer(xc.usbctrls))[:numUsbctrls:numUsbctrls]
+               for i, v := range x.Usbctrls {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cUsbctrls[i] = tmp
+               }
+       }
+       if numUsbdevs := len(x.Usbdevs); numUsbdevs > 0 {
+               xc.usbdevs = 
(*C.libxl_device_usbdev)(C.malloc(C.ulong(numUsbdevs) * 
C.sizeof_libxl_device_usbdev))
+               xc.num_usbdevs = C.int(numUsbdevs)
+               cUsbdevs := (*[1 << 
28]C.libxl_device_usbdev)(unsafe.Pointer(xc.usbdevs))[:numUsbdevs:numUsbdevs]
+               for i, v := range x.Usbdevs {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_domain_config_dispose(&xc)
+                               return xc, err
+                       }
+                       cUsbdevs[i] = tmp
                }
-               cUsbdevs[i] = tmp
        }
        xc.on_poweroff = C.libxl_action_on_shutdown(x.OnPoweroff)
        xc.on_reboot = C.libxl_action_on_shutdown(x.OnReboot)
@@ -2658,12 +2742,14 @@ func (x *Vdisplinfo) fromC(xc *C.libxl_vdisplinfo) 
error {
        x.Devid = Devid(xc.devid)
        x.State = int(xc.state)
        x.BeAlloc = bool(xc.be_alloc)
-       numConnectors := int(xc.num_connectors)
-       cConnectors := (*[1 << 
28]C.libxl_connectorinfo)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
-       x.Connectors = make([]Connectorinfo, numConnectors)
-       for i, v := range cConnectors {
-               if err := x.Connectors[i].fromC(&v); err != nil {
-                       return err
+       x.Connectors = nil
+       if numConnectors := int(xc.num_connectors); numConnectors > 0 {
+               cConnectors := (*[1 << 
28]C.libxl_connectorinfo)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
+               x.Connectors = make([]Connectorinfo, numConnectors)
+               for i, v := range cConnectors {
+                       if err := x.Connectors[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -2679,17 +2765,18 @@ func (x *Vdisplinfo) toC() (xc C.libxl_vdisplinfo, err 
error) {
        xc.devid = C.libxl_devid(x.Devid)
        xc.state = C.int(x.State)
        xc.be_alloc = C.bool(x.BeAlloc)
-       numConnectors := len(x.Connectors)
-       xc.connectors = 
(*C.libxl_connectorinfo)(C.malloc(C.ulong(numConnectors) * 
C.sizeof_libxl_connectorinfo))
-       xc.num_connectors = C.int(numConnectors)
-       cConnectors := (*[1 << 
28]C.libxl_connectorinfo)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
-       for i, v := range x.Connectors {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_vdisplinfo_dispose(&xc)
-                       return xc, err
+       if numConnectors := len(x.Connectors); numConnectors > 0 {
+               xc.connectors = 
(*C.libxl_connectorinfo)(C.malloc(C.ulong(numConnectors) * 
C.sizeof_libxl_connectorinfo))
+               xc.num_connectors = C.int(numConnectors)
+               cConnectors := (*[1 << 
28]C.libxl_connectorinfo)(unsafe.Pointer(xc.connectors))[:numConnectors:numConnectors]
+               for i, v := range x.Connectors {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_vdisplinfo_dispose(&xc)
+                               return xc, err
+                       }
+                       cConnectors[i] = tmp
                }
-               cConnectors[i] = tmp
        }
        return xc, nil
 }
@@ -2709,12 +2796,14 @@ func (x *Streaminfo) toC() (xc C.libxl_streaminfo, err 
error) {
 }
 
 func (x *Pcminfo) fromC(xc *C.libxl_pcminfo) error {
-       numVsndStreams := int(xc.num_vsnd_streams)
-       cStreams := (*[1 << 
28]C.libxl_streaminfo)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
-       x.Streams = make([]Streaminfo, numVsndStreams)
-       for i, v := range cStreams {
-               if err := x.Streams[i].fromC(&v); err != nil {
-                       return err
+       x.Streams = nil
+       if numVsndStreams := int(xc.num_vsnd_streams); numVsndStreams > 0 {
+               cStreams := (*[1 << 
28]C.libxl_streaminfo)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
+               x.Streams = make([]Streaminfo, numVsndStreams)
+               for i, v := range cStreams {
+                       if err := x.Streams[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -2723,17 +2812,18 @@ func (x *Pcminfo) fromC(xc *C.libxl_pcminfo) error {
 
 func (x *Pcminfo) toC() (xc C.libxl_pcminfo, err error) {
        C.libxl_pcminfo_init(&xc)
-       numVsndStreams := len(x.Streams)
-       xc.streams = (*C.libxl_streaminfo)(C.malloc(C.ulong(numVsndStreams) * 
C.sizeof_libxl_streaminfo))
-       xc.num_vsnd_streams = C.int(numVsndStreams)
-       cStreams := (*[1 << 
28]C.libxl_streaminfo)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
-       for i, v := range x.Streams {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_pcminfo_dispose(&xc)
-                       return xc, err
+       if numVsndStreams := len(x.Streams); numVsndStreams > 0 {
+               xc.streams = 
(*C.libxl_streaminfo)(C.malloc(C.ulong(numVsndStreams) * 
C.sizeof_libxl_streaminfo))
+               xc.num_vsnd_streams = C.int(numVsndStreams)
+               cStreams := (*[1 << 
28]C.libxl_streaminfo)(unsafe.Pointer(xc.streams))[:numVsndStreams:numVsndStreams]
+               for i, v := range x.Streams {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_pcminfo_dispose(&xc)
+                               return xc, err
+                       }
+                       cStreams[i] = tmp
                }
-               cStreams[i] = tmp
        }
        return xc, nil
 }
@@ -2745,12 +2835,14 @@ func (x *Vsndinfo) fromC(xc *C.libxl_vsndinfo) error {
        x.FrontendId = uint32(xc.frontend_id)
        x.Devid = Devid(xc.devid)
        x.State = int(xc.state)
-       numVsndPcms := int(xc.num_vsnd_pcms)
-       cPcms := (*[1 << 
28]C.libxl_pcminfo)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
-       x.Pcms = make([]Pcminfo, numVsndPcms)
-       for i, v := range cPcms {
-               if err := x.Pcms[i].fromC(&v); err != nil {
-                       return err
+       x.Pcms = nil
+       if numVsndPcms := int(xc.num_vsnd_pcms); numVsndPcms > 0 {
+               cPcms := (*[1 << 
28]C.libxl_pcminfo)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
+               x.Pcms = make([]Pcminfo, numVsndPcms)
+               for i, v := range cPcms {
+                       if err := x.Pcms[i].fromC(&v); err != nil {
+                               return err
+                       }
                }
        }
 
@@ -2765,17 +2857,18 @@ func (x *Vsndinfo) toC() (xc C.libxl_vsndinfo, err 
error) {
        xc.frontend_id = C.uint32_t(x.FrontendId)
        xc.devid = C.libxl_devid(x.Devid)
        xc.state = C.int(x.State)
-       numVsndPcms := len(x.Pcms)
-       xc.pcms = (*C.libxl_pcminfo)(C.malloc(C.ulong(numVsndPcms) * 
C.sizeof_libxl_pcminfo))
-       xc.num_vsnd_pcms = C.int(numVsndPcms)
-       cPcms := (*[1 << 
28]C.libxl_pcminfo)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
-       for i, v := range x.Pcms {
-               tmp, err := v.toC()
-               if err != nil {
-                       C.libxl_vsndinfo_dispose(&xc)
-                       return xc, err
+       if numVsndPcms := len(x.Pcms); numVsndPcms > 0 {
+               xc.pcms = (*C.libxl_pcminfo)(C.malloc(C.ulong(numVsndPcms) * 
C.sizeof_libxl_pcminfo))
+               xc.num_vsnd_pcms = C.int(numVsndPcms)
+               cPcms := (*[1 << 
28]C.libxl_pcminfo)(unsafe.Pointer(xc.pcms))[:numVsndPcms:numVsndPcms]
+               for i, v := range x.Pcms {
+                       tmp, err := v.toC()
+                       if err != nil {
+                               C.libxl_vsndinfo_dispose(&xc)
+                               return xc, err
+                       }
+                       cPcms[i] = tmp
                }
-               cPcms[i] = tmp
        }
        return xc, nil
 }
@@ -2809,11 +2902,13 @@ func (x *Vkbinfo) toC() (xc C.libxl_vkbinfo, err error) 
{
 func (x *Numainfo) fromC(xc *C.libxl_numainfo) error {
        x.Size = uint64(xc.size)
        x.Free = uint64(xc.free)
-       numDists := int(xc.num_dists)
-       cDists := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.dists))[:numDists:numDists]
-       x.Dists = make([]uint32, numDists)
-       for i, v := range cDists {
-               x.Dists[i] = uint32(v)
+       x.Dists = nil
+       if numDists := int(xc.num_dists); numDists > 0 {
+               cDists := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.dists))[:numDists:numDists]
+               x.Dists = make([]uint32, numDists)
+               for i, v := range cDists {
+                       x.Dists[i] = uint32(v)
+               }
        }
 
        return nil
@@ -2823,12 +2918,13 @@ func (x *Numainfo) toC() (xc C.libxl_numainfo, err 
error) {
        C.libxl_numainfo_init(&xc)
        xc.size = C.uint64_t(x.Size)
        xc.free = C.uint64_t(x.Free)
-       numDists := len(x.Dists)
-       xc.dists = (*C.uint32_t)(C.malloc(C.size_t(numDists * numDists)))
-       xc.num_dists = C.int(numDists)
-       cDists := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.dists))[:numDists:numDists]
-       for i, v := range x.Dists {
-               cDists[i] = C.uint32_t(v)
+       if numDists := len(x.Dists); numDists > 0 {
+               xc.dists = (*C.uint32_t)(C.malloc(C.size_t(numDists * 
numDists)))
+               xc.num_dists = C.int(numDists)
+               cDists := (*[1 << 
28]C.uint32_t)(unsafe.Pointer(xc.dists))[:numDists:numDists]
+               for i, v := range x.Dists {
+                       cDists[i] = C.uint32_t(v)
+               }
        }
        return xc, nil
 }
@@ -2976,12 +3072,6 @@ func (x *Event) fromC(xc *C.libxl_event) error {
        x.ForUser = uint64(xc.for_user)
        x.Type = EventType(xc._type)
        switch x.Type {
-       case EventTypeOperationComplete:
-               var typeOperationComplete EventTypeUnionOperationComplete
-               if err := typeOperationComplete.fromC(xc); err != nil {
-                       return err
-               }
-               x.TypeUnion = typeOperationComplete
        case EventTypeDomainShutdown:
                var typeDomainShutdown EventTypeUnionDomainShutdown
                if err := typeDomainShutdown.fromC(xc); err != nil {
@@ -2994,6 +3084,12 @@ func (x *Event) fromC(xc *C.libxl_event) error {
                        return err
                }
                x.TypeUnion = typeDiskEject
+       case EventTypeOperationComplete:
+               var typeOperationComplete EventTypeUnionOperationComplete
+               if err := typeOperationComplete.fromC(xc); err != nil {
+                       return err
+               }
+               x.TypeUnion = typeOperationComplete
        default:
                return fmt.Errorf("invalid union key '%v'", x.Type)
        }
@@ -3113,18 +3209,18 @@ func (x *PsrHwInfo) fromC(xc *C.libxl_psr_hw_info) 
error {
        x.Id = uint32(xc.id)
        x.Type = PsrFeatType(xc._type)
        switch x.Type {
-       case PsrFeatTypeMba:
-               var typeMba PsrHwInfoTypeUnionMba
-               if err := typeMba.fromC(xc); err != nil {
-                       return err
-               }
-               x.TypeUnion = typeMba
        case PsrFeatTypeCat:
                var typeCat PsrHwInfoTypeUnionCat
                if err := typeCat.fromC(xc); err != nil {
                        return err
                }
                x.TypeUnion = typeCat
+       case PsrFeatTypeMba:
+               var typeMba PsrHwInfoTypeUnionMba
+               if err := typeMba.fromC(xc); err != nil {
+                       return err
+               }
+               x.TypeUnion = typeMba
        default:
                return fmt.Errorf("invalid union key '%v'", x.Type)
        }
-- 
2.24.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.