diff mbox series

[v2,15/22] golang/xenlight: begin C to Go type marshaling

Message ID 472334f58bc435e505ad6bc392426960630fb060.1573840474.git.rosbrookn@ainfosec.com (mailing list archive)
State Superseded
Headers show
Series generated Go libxl bindings using IDL | expand

Commit Message

Nick Rosbrook Nov. 15, 2019, 7:44 p.m. UTC
From: Nick Rosbrook <rosbrookn@ainfosec.com>

Implement basic type conversion in fromC functions such as strings and
integer types. Also, remove existing toGo functions from xenlight.go in
favor of the new generated functions.

Signed-off-by: Nick Rosbrook <rosbrookn@ainfosec.com>
---
Changes in v2:
- Add Makefile changes for helpers.gen.go.
- Re-generate helpers.gen.go to include libxl changes after rebase.

 tools/golang/xenlight/Makefile       |   2 +
 tools/golang/xenlight/gengotypes.py  | 120 ++++
 tools/golang/xenlight/helpers.gen.go | 969 +++++++++++++++++++++++++++
 tools/golang/xenlight/xenlight.go    | 111 +--
 4 files changed, 1102 insertions(+), 100 deletions(-)
 create mode 100644 tools/golang/xenlight/helpers.gen.go

Comments

George Dunlap Dec. 4, 2019, 6:07 p.m. UTC | #1
On 11/15/19 7:44 PM, Nick Rosbrook wrote:
> From: Nick Rosbrook <rosbrookn@ainfosec.com>
> 
> Implement basic type conversion in fromC functions such as strings and
> integer types. Also, remove existing toGo functions from xenlight.go in
> favor of the new generated functions.

You should probably say here explicitly what kinds of elements you're
supporting and not supporting in this patch; specifically:

- You're converting built-ins (or is this any struct-like type?)
- You handle nested anonymous structs
- But you're not handling keyed unions or arrays (anything else)?


> +func (x *VncInfo) fromC(xc *C.libxl_vnc_info) error {
> +	var defboolEnable Defbool
> +	if err := defboolEnable.fromC(&xc.enable); err != nil {
> +		return err
> +	}

Is there a reason in these cases that we don't simply call .fromC on the
elemet itself?

i.e., why not just:

> +	x.Enable = defboolEnable

    x.Enable.fromC(&xc.enable)

?


Everything else looks good, thanks

 -George
Nick Rosbrook Dec. 5, 2019, 4:38 p.m. UTC | #2
> You should probably say here explicitly what kinds of elements you're
> supporting and not supporting in this patch; specifically:
>
> - You're converting built-ins (or is this any struct-like type?)

Any struct-like type, since the fromC functions are all defined in
this patch (excluding array fields and keyed unions as you said
below).

> - You handle nested anonymous structs
> - But you're not handling keyed unions or arrays (anything else)?

I think this covers it, thanks.

> > +func (x *VncInfo) fromC(xc *C.libxl_vnc_info) error {
> > +     var defboolEnable Defbool
> > +     if err := defboolEnable.fromC(&xc.enable); err != nil {
> > +             return err
> > +     }
>
> Is there a reason in these cases that we don't simply call .fromC on the
> elemet itself?

This ensures that when we call fromC, we have an initialized variable.
This might be overkill here, as this would matter more if we had
structs with a nested struct pointer. E.g., [1] will panic since only
the outer struct is initialized.

-NR

[1]  https://play.golang.org/p/1gDVjbXgWd-
George Dunlap Dec. 5, 2019, 6 p.m. UTC | #3
On 12/5/19 4:38 PM, Nick Rosbrook wrote:
>> You should probably say here explicitly what kinds of elements you're
>> supporting and not supporting in this patch; specifically:
>>
>> - You're converting built-ins (or is this any struct-like type?)
> 
> Any struct-like type, since the fromC functions are all defined in
> this patch (excluding array fields and keyed unions as you said
> below).
> 
>> - You handle nested anonymous structs
>> - But you're not handling keyed unions or arrays (anything else)?
> 
> I think this covers it, thanks.
> 
>>> +func (x *VncInfo) fromC(xc *C.libxl_vnc_info) error {
>>> +     var defboolEnable Defbool
>>> +     if err := defboolEnable.fromC(&xc.enable); err != nil {
>>> +             return err
>>> +     }
>>
>> Is there a reason in these cases that we don't simply call .fromC on the
>> elemet itself?
> 
> This ensures that when we call fromC, we have an initialized variable.
> This might be overkill here, as this would matter more if we had
> structs with a nested struct pointer. E.g., [1] will panic since only
> the outer struct is initialized.

So first of all, I noticed that the marshalling code for Union structs
does what I suggest. :-)

I can see how such a construct would be needed when there was a pointer
type.  But if there was a pointer type, you'd have to special-case
things anyway.  Take the following code that has a non-pointer element:

	var defboolEnable Defbool // The same type as x.Enable
	if err := defboolEnable.fromC(&xc.enable); err != nil {
		return err
	}
	x.Enable = defboolEnable

Now suppose you had a pointer element instead; what would it look like?

	var defboolEnable Defbool // NOT the same type as x.Enable!
	if err := defboolEnable.fromC(&xc.enable); err != nil {
		return err
	}
	x.Enable = &defboolEnable

The generation code would have to replace the type of "Enable", which is
a pointer, with the actual instance of the thing; and then assign the
reference, rather than the value.  So if we run across something like
that, we can sort that out when we come to it.

I'm not super-strong on this, so I don't want to bike-shed.  But I think
the way you generate the marshalling code for the union structs is better:

	if err := x.Pae.fromC(&tmp.pae); err != nil {
		return err
	}

Thanks,
 -George
Nick Rosbrook Dec. 5, 2019, 6:32 p.m. UTC | #4
> So first of all, I noticed that the marshalling code for Union structs
> does what I suggest. :-)

Yeah I realized that. I must have figured out that my previous way
wasn't necessary, but forgot to go back and change it.

> I'm not super-strong on this, so I don't want to bike-shed.  But I think
> the way you generate the marshalling code for the union structs is better:
>
>         if err := x.Pae.fromC(&tmp.pae); err != nil {
>                 return err
>         }

I'll change it. I'd prefer not to have those inconsistencies in the
code generation.

Thanks,
-NR
diff mbox series

Patch

diff --git a/tools/golang/xenlight/Makefile b/tools/golang/xenlight/Makefile
index 681f32c234..07b8896e5b 100644
--- a/tools/golang/xenlight/Makefile
+++ b/tools/golang/xenlight/Makefile
@@ -19,6 +19,7 @@  $(XEN_GOPATH)/src/$(XEN_GOCODE_URL)/xenlight/: %.gen.go
 	$(INSTALL_DIR) $(XEN_GOPATH)$(GOXL_PKG_DIR)
 	$(INSTALL_DATA) xenlight.go $(XEN_GOPATH)$(GOXL_PKG_DIR)
 	$(INSTALL_DATA) types.gen.go $(XEN_GOPATH)$(GOXL_PKG_DIR)
+	$(INSTALL_DATA) helpers.gen.go $(XEN_GOPATH)$(GOXL_PKG_DIR)
 
 %.gen.go: gengotypes.py $(XEN_ROOT)/tools/libxl/libxl_types.idl $(XEN_ROOT)/tools/libxl/idl.py
 	XEN_ROOT=$(XEN_ROOT) $(PYTHON) gengotypes.py ../../libxl/libxl_types.idl
@@ -39,6 +40,7 @@  install: build
 	$(INSTALL_DIR) $(DESTDIR)$(GOXL_INSTALL_DIR)
 	$(INSTALL_DATA) $(XEN_GOPATH)$(GOXL_PKG_DIR)xenlight.go $(DESTDIR)$(GOXL_INSTALL_DIR)
 	$(INSTALL_DATA) $(XEN_GOPATH)$(GOXL_PKG_DIR)types.gen.go $(DESTDIR)$(GOXL_INSTALL_DIR)
+	$(INSTALL_DATA) $(XEN_GOPATH)$(GOXL_PKG_DIR)helpers.gen.go $(DESTDIR)$(GOXL_INSTALL_DIR)
 
 .PHONY: uninstall
 	rm -rf $(DESTDIR)$(GOXL_INSTALL_DIR)
diff --git a/tools/golang/xenlight/gengotypes.py b/tools/golang/xenlight/gengotypes.py
index 8963b14eee..0c8a1327a1 100644
--- a/tools/golang/xenlight/gengotypes.py
+++ b/tools/golang/xenlight/gengotypes.py
@@ -18,6 +18,12 @@  builtin_type_names = {
     idl.uint64.typename: 'uint64',
 }
 
+# Some go keywords that conflict with field names in libxl structs.
+go_keywords = ['type', 'func']
+
+go_builtin_types = ['bool', 'string', 'int', 'byte',
+                    'uint16', 'uint32', 'uint64']
+
 def xenlight_golang_generate_types(path = None, types = None, comment = None):
     """
     Generate a .go file (types.gen.go by default)
@@ -176,6 +182,118 @@  def xenlight_golang_define_union(ty = None, structname = ''):
 
     return (s,extras)
 
+def xenlight_golang_generate_helpers(path = None, types = None, comment = None):
+    """
+    Generate a .go file (helpers.gen.go by default)
+    that contains helper functions for marshaling between
+    C and Go types.
+    """
+    if path is None:
+        path = 'helpers.gen.go'
+
+    with open(path, 'w') as f:
+        if comment is not None:
+            f.write(comment)
+        f.write('package xenlight\n')
+
+        # Cgo preamble
+        f.write('/*\n')
+        f.write('#cgo LDFLAGS: -lxenlight\n')
+        f.write('#include <stdlib.h>\n')
+        f.write('#include <libxl.h>\n')
+        f.write('\n')
+
+        f.write('*/\nimport "C"\n')
+
+        for ty in types:
+            if not isinstance(ty, idl.Struct):
+                continue
+
+            f.write(xenlight_golang_define_from_C(ty))
+            f.write('\n')
+
+    go_fmt(path)
+
+def xenlight_golang_define_from_C(ty = None, typename = None, nested = False):
+    s = ''
+
+    gotypename = ctypename = ''
+
+    if typename is not None:
+        gotypename = xenlight_golang_fmt_name(typename)
+        ctypename  = typename
+    else:
+        gotypename = xenlight_golang_fmt_name(ty.typename)
+        ctypename  = ty.typename
+
+    if not nested:
+        s += 'func (x *{}) fromC(xc *C.{}) error {{\n'.format(gotypename,ctypename)
+
+    for f in ty.fields:
+        if f.type.typename is not None:
+            if isinstance(f.type, idl.Array):
+                # TODO
+                continue
+
+            gotypename = xenlight_golang_fmt_name(f.type.typename)
+            gofname    = xenlight_golang_fmt_name(f.name)
+            cfname     = f.name
+
+            # In cgo, C names that conflict with Go keywords can be
+            # accessed by prepending an underscore to the name.
+            if cfname in go_keywords:
+                cfname = '_' + cfname
+
+            # If this is nested, we need the outer name too.
+            if nested and typename is not None:
+                goname = xenlight_golang_fmt_name(typename)
+                goname = '{}.{}'.format(goname, gofname)
+                cname  = '{}.{}'.format(typename, cfname)
+
+            else:
+                goname = gofname
+                cname  = cfname
+
+            # Types that satisfy this condition can be easily casted or
+            # converted to a Go builtin type.
+            is_castable = (f.type.json_parse_type == 'JSON_INTEGER' or
+                           isinstance(f.type, idl.Enumeration) or
+                           gotypename in go_builtin_types)
+
+            if is_castable:
+                # Use the cgo helper for converting C strings.
+                if gotypename == 'string':
+                    s += 'x.{} = C.GoString(xc.{})\n'.format(goname, cname)
+                    continue
+
+                s += 'x.{} = {}(xc.{})\n'.format(goname, gotypename, cname)
+
+            else:
+                # If the type is not castable, we need to call its fromC
+                # function.
+                varname = '{}_{}'.format(f.type.typename,f.name)
+                varname = xenlight_golang_fmt_name(varname, exported=False)
+
+                s += 'var {} {}\n'.format(varname, gotypename)
+                s += 'if err := {}.fromC(&xc.{});'.format(varname, cname)
+                s += 'err != nil {\n return err\n}\n'
+                s += 'x.{} = {}\n'.format(goname, varname)
+
+        elif isinstance(f.type, idl.Struct):
+            s += xenlight_golang_define_from_C(f.type, typename=f.name, nested=True)
+
+        elif isinstance(f.type, idl.KeyedUnion):
+            pass
+
+        else:
+            raise Exception('type {} not supported'.format(f.type))
+
+    if not nested:
+        s += 'return nil'
+        s += '}\n'
+
+    return s
+
 def xenlight_golang_fmt_name(name, exported = True):
     """
     Take a given type name and return an
@@ -218,3 +336,5 @@  if __name__ == '__main__':
 
     xenlight_golang_generate_types(types=types,
                                    comment=header_comment)
+    xenlight_golang_generate_helpers(types=types,
+                                     comment=header_comment)
diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go
new file mode 100644
index 0000000000..0de42eaa6b
--- /dev/null
+++ b/tools/golang/xenlight/helpers.gen.go
@@ -0,0 +1,969 @@ 
+// DO NOT EDIT.
+//
+// This file is generated by:
+// gengotypes.py ../../libxl/libxl_types.idl
+//
+package xenlight
+
+/*
+#cgo LDFLAGS: -lxenlight
+#include <stdlib.h>
+#include <libxl.h>
+
+*/
+import "C"
+
+func (x *IoportRange) fromC(xc *C.libxl_ioport_range) error {
+	x.First = uint32(xc.first)
+	x.Number = uint32(xc.number)
+	return nil
+}
+
+func (x *IomemRange) fromC(xc *C.libxl_iomem_range) error {
+	x.Start = uint64(xc.start)
+	x.Number = uint64(xc.number)
+	x.Gfn = uint64(xc.gfn)
+	return nil
+}
+
+func (x *VgaInterfaceInfo) fromC(xc *C.libxl_vga_interface_info) error {
+	x.Kind = VgaInterfaceType(xc.kind)
+	return nil
+}
+
+func (x *VncInfo) fromC(xc *C.libxl_vnc_info) error {
+	var defboolEnable Defbool
+	if err := defboolEnable.fromC(&xc.enable); err != nil {
+		return err
+	}
+	x.Enable = defboolEnable
+	x.Listen = C.GoString(xc.listen)
+	x.Passwd = C.GoString(xc.passwd)
+	x.Display = int(xc.display)
+	var defboolFindunused Defbool
+	if err := defboolFindunused.fromC(&xc.findunused); err != nil {
+		return err
+	}
+	x.Findunused = defboolFindunused
+	return nil
+}
+
+func (x *SpiceInfo) fromC(xc *C.libxl_spice_info) error {
+	var defboolEnable Defbool
+	if err := defboolEnable.fromC(&xc.enable); err != nil {
+		return err
+	}
+	x.Enable = defboolEnable
+	x.Port = int(xc.port)
+	x.TlsPort = int(xc.tls_port)
+	x.Host = C.GoString(xc.host)
+	var defboolDisableTicketing Defbool
+	if err := defboolDisableTicketing.fromC(&xc.disable_ticketing); err != nil {
+		return err
+	}
+	x.DisableTicketing = defboolDisableTicketing
+	x.Passwd = C.GoString(xc.passwd)
+	var defboolAgentMouse Defbool
+	if err := defboolAgentMouse.fromC(&xc.agent_mouse); err != nil {
+		return err
+	}
+	x.AgentMouse = defboolAgentMouse
+	var defboolVdagent Defbool
+	if err := defboolVdagent.fromC(&xc.vdagent); err != nil {
+		return err
+	}
+	x.Vdagent = defboolVdagent
+	var defboolClipboardSharing Defbool
+	if err := defboolClipboardSharing.fromC(&xc.clipboard_sharing); err != nil {
+		return err
+	}
+	x.ClipboardSharing = defboolClipboardSharing
+	x.Usbredirection = int(xc.usbredirection)
+	x.ImageCompression = C.GoString(xc.image_compression)
+	x.StreamingVideo = C.GoString(xc.streaming_video)
+	return nil
+}
+
+func (x *SdlInfo) fromC(xc *C.libxl_sdl_info) error {
+	var defboolEnable Defbool
+	if err := defboolEnable.fromC(&xc.enable); err != nil {
+		return err
+	}
+	x.Enable = defboolEnable
+	var defboolOpengl Defbool
+	if err := defboolOpengl.fromC(&xc.opengl); err != nil {
+		return err
+	}
+	x.Opengl = defboolOpengl
+	x.Display = C.GoString(xc.display)
+	x.Xauthority = C.GoString(xc.xauthority)
+	return nil
+}
+
+func (x *Dominfo) fromC(xc *C.libxl_dominfo) error {
+	var uuidUuid Uuid
+	if err := uuidUuid.fromC(&xc.uuid); err != nil {
+		return err
+	}
+	x.Uuid = uuidUuid
+	x.Domid = Domid(xc.domid)
+	x.Ssidref = uint32(xc.ssidref)
+	x.SsidLabel = C.GoString(xc.ssid_label)
+	x.Running = bool(xc.running)
+	x.Blocked = bool(xc.blocked)
+	x.Paused = bool(xc.paused)
+	x.Shutdown = bool(xc.shutdown)
+	x.Dying = bool(xc.dying)
+	x.NeverStop = bool(xc.never_stop)
+	x.ShutdownReason = ShutdownReason(xc.shutdown_reason)
+	x.OutstandingMemkb = uint64(xc.outstanding_memkb)
+	x.CurrentMemkb = uint64(xc.current_memkb)
+	x.SharedMemkb = uint64(xc.shared_memkb)
+	x.PagedMemkb = uint64(xc.paged_memkb)
+	x.MaxMemkb = uint64(xc.max_memkb)
+	x.CpuTime = uint64(xc.cpu_time)
+	x.VcpuMaxId = uint32(xc.vcpu_max_id)
+	x.VcpuOnline = uint32(xc.vcpu_online)
+	x.Cpupool = uint32(xc.cpupool)
+	x.DomainType = DomainType(xc.domain_type)
+	return nil
+}
+
+func (x *Cpupoolinfo) fromC(xc *C.libxl_cpupoolinfo) error {
+	x.Poolid = uint32(xc.poolid)
+	x.PoolName = C.GoString(xc.pool_name)
+	x.Sched = Scheduler(xc.sched)
+	x.NDom = uint32(xc.n_dom)
+	var bitmapCpumap Bitmap
+	if err := bitmapCpumap.fromC(&xc.cpumap); err != nil {
+		return err
+	}
+	x.Cpumap = bitmapCpumap
+	return nil
+}
+
+func (x *Channelinfo) fromC(xc *C.libxl_channelinfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	x.Evtch = int(xc.evtch)
+	x.Rref = int(xc.rref)
+	return nil
+}
+
+func (x *Vminfo) fromC(xc *C.libxl_vminfo) error {
+	var uuidUuid Uuid
+	if err := uuidUuid.fromC(&xc.uuid); err != nil {
+		return err
+	}
+	x.Uuid = uuidUuid
+	x.Domid = Domid(xc.domid)
+	return nil
+}
+
+func (x *VersionInfo) fromC(xc *C.libxl_version_info) error {
+	x.XenVersionMajor = int(xc.xen_version_major)
+	x.XenVersionMinor = int(xc.xen_version_minor)
+	x.XenVersionExtra = C.GoString(xc.xen_version_extra)
+	x.Compiler = C.GoString(xc.compiler)
+	x.CompileBy = C.GoString(xc.compile_by)
+	x.CompileDomain = C.GoString(xc.compile_domain)
+	x.CompileDate = C.GoString(xc.compile_date)
+	x.Capabilities = C.GoString(xc.capabilities)
+	x.Changeset = C.GoString(xc.changeset)
+	x.VirtStart = uint64(xc.virt_start)
+	x.Pagesize = int(xc.pagesize)
+	x.Commandline = C.GoString(xc.commandline)
+	x.BuildId = C.GoString(xc.build_id)
+	return nil
+}
+
+func (x *DomainCreateInfo) fromC(xc *C.libxl_domain_create_info) error {
+	x.Type = DomainType(xc._type)
+	var defboolHap Defbool
+	if err := defboolHap.fromC(&xc.hap); err != nil {
+		return err
+	}
+	x.Hap = defboolHap
+	var defboolOos Defbool
+	if err := defboolOos.fromC(&xc.oos); err != nil {
+		return err
+	}
+	x.Oos = defboolOos
+	x.Ssidref = uint32(xc.ssidref)
+	x.SsidLabel = C.GoString(xc.ssid_label)
+	x.Name = C.GoString(xc.name)
+	var uuidUuid Uuid
+	if err := uuidUuid.fromC(&xc.uuid); err != nil {
+		return err
+	}
+	x.Uuid = uuidUuid
+	var keyValueListXsdata KeyValueList
+	if err := keyValueListXsdata.fromC(&xc.xsdata); err != nil {
+		return err
+	}
+	x.Xsdata = keyValueListXsdata
+	var keyValueListPlatformdata KeyValueList
+	if err := keyValueListPlatformdata.fromC(&xc.platformdata); err != nil {
+		return err
+	}
+	x.Platformdata = keyValueListPlatformdata
+	x.Poolid = uint32(xc.poolid)
+	x.PoolName = C.GoString(xc.pool_name)
+	var defboolRunHotplugScripts Defbool
+	if err := defboolRunHotplugScripts.fromC(&xc.run_hotplug_scripts); err != nil {
+		return err
+	}
+	x.RunHotplugScripts = defboolRunHotplugScripts
+	var defboolDriverDomain Defbool
+	if err := defboolDriverDomain.fromC(&xc.driver_domain); err != nil {
+		return err
+	}
+	x.DriverDomain = defboolDriverDomain
+	x.Passthrough = Passthrough(xc.passthrough)
+	return nil
+}
+
+func (x *DomainRestoreParams) fromC(xc *C.libxl_domain_restore_params) error {
+	x.CheckpointedStream = int(xc.checkpointed_stream)
+	x.StreamVersion = uint32(xc.stream_version)
+	x.ColoProxyScript = C.GoString(xc.colo_proxy_script)
+	var defboolUserspaceColoProxy Defbool
+	if err := defboolUserspaceColoProxy.fromC(&xc.userspace_colo_proxy); err != nil {
+		return err
+	}
+	x.UserspaceColoProxy = defboolUserspaceColoProxy
+	return nil
+}
+
+func (x *SchedParams) fromC(xc *C.libxl_sched_params) error {
+	x.Vcpuid = int(xc.vcpuid)
+	x.Weight = int(xc.weight)
+	x.Cap = int(xc.cap)
+	x.Period = int(xc.period)
+	x.Extratime = int(xc.extratime)
+	x.Budget = int(xc.budget)
+	return nil
+}
+
+func (x *VcpuSchedParams) fromC(xc *C.libxl_vcpu_sched_params) error {
+	x.Sched = Scheduler(xc.sched)
+	return nil
+}
+
+func (x *DomainSchedParams) fromC(xc *C.libxl_domain_sched_params) error {
+	x.Sched = Scheduler(xc.sched)
+	x.Weight = int(xc.weight)
+	x.Cap = int(xc.cap)
+	x.Period = int(xc.period)
+	x.Budget = int(xc.budget)
+	x.Extratime = int(xc.extratime)
+	x.Slice = int(xc.slice)
+	x.Latency = int(xc.latency)
+	return nil
+}
+
+func (x *VnodeInfo) fromC(xc *C.libxl_vnode_info) error {
+	x.Memkb = uint64(xc.memkb)
+	x.Pnode = uint32(xc.pnode)
+	var bitmapVcpus Bitmap
+	if err := bitmapVcpus.fromC(&xc.vcpus); err != nil {
+		return err
+	}
+	x.Vcpus = bitmapVcpus
+	return nil
+}
+
+func (x *RdmReserve) fromC(xc *C.libxl_rdm_reserve) error {
+	x.Strategy = RdmReserveStrategy(xc.strategy)
+	x.Policy = RdmReservePolicy(xc.policy)
+	return nil
+}
+
+func (x *DomainBuildInfo) fromC(xc *C.libxl_domain_build_info) error {
+	x.MaxVcpus = int(xc.max_vcpus)
+	var bitmapAvailVcpus Bitmap
+	if err := bitmapAvailVcpus.fromC(&xc.avail_vcpus); err != nil {
+		return err
+	}
+	x.AvailVcpus = bitmapAvailVcpus
+	var bitmapCpumap Bitmap
+	if err := bitmapCpumap.fromC(&xc.cpumap); err != nil {
+		return err
+	}
+	x.Cpumap = bitmapCpumap
+	var bitmapNodemap Bitmap
+	if err := bitmapNodemap.fromC(&xc.nodemap); err != nil {
+		return err
+	}
+	x.Nodemap = bitmapNodemap
+	var defboolNumaPlacement Defbool
+	if err := defboolNumaPlacement.fromC(&xc.numa_placement); err != nil {
+		return err
+	}
+	x.NumaPlacement = defboolNumaPlacement
+	x.TscMode = TscMode(xc.tsc_mode)
+	x.MaxMemkb = uint64(xc.max_memkb)
+	x.TargetMemkb = uint64(xc.target_memkb)
+	x.VideoMemkb = uint64(xc.video_memkb)
+	x.ShadowMemkb = uint64(xc.shadow_memkb)
+	x.IommuMemkb = uint64(xc.iommu_memkb)
+	x.RtcTimeoffset = uint32(xc.rtc_timeoffset)
+	x.ExecSsidref = uint32(xc.exec_ssidref)
+	x.ExecSsidLabel = C.GoString(xc.exec_ssid_label)
+	var defboolLocaltime Defbool
+	if err := defboolLocaltime.fromC(&xc.localtime); err != nil {
+		return err
+	}
+	x.Localtime = defboolLocaltime
+	var defboolDisableMigrate Defbool
+	if err := defboolDisableMigrate.fromC(&xc.disable_migrate); err != nil {
+		return err
+	}
+	x.DisableMigrate = defboolDisableMigrate
+	var cpuidPolicyListCpuid CpuidPolicyList
+	if err := cpuidPolicyListCpuid.fromC(&xc.cpuid); err != nil {
+		return err
+	}
+	x.Cpuid = cpuidPolicyListCpuid
+	x.BlkdevStart = C.GoString(xc.blkdev_start)
+	x.MaxGrantFrames = uint32(xc.max_grant_frames)
+	x.MaxMaptrackFrames = uint32(xc.max_maptrack_frames)
+	x.DeviceModelVersion = DeviceModelVersion(xc.device_model_version)
+	var defboolDeviceModelStubdomain Defbool
+	if err := defboolDeviceModelStubdomain.fromC(&xc.device_model_stubdomain); err != nil {
+		return err
+	}
+	x.DeviceModelStubdomain = defboolDeviceModelStubdomain
+	x.DeviceModel = C.GoString(xc.device_model)
+	x.DeviceModelSsidref = uint32(xc.device_model_ssidref)
+	x.DeviceModelSsidLabel = C.GoString(xc.device_model_ssid_label)
+	x.DeviceModelUser = C.GoString(xc.device_model_user)
+	var stringListExtra StringList
+	if err := stringListExtra.fromC(&xc.extra); err != nil {
+		return err
+	}
+	x.Extra = stringListExtra
+	var stringListExtraPv StringList
+	if err := stringListExtraPv.fromC(&xc.extra_pv); err != nil {
+		return err
+	}
+	x.ExtraPv = stringListExtraPv
+	var stringListExtraHvm StringList
+	if err := stringListExtraHvm.fromC(&xc.extra_hvm); err != nil {
+		return err
+	}
+	x.ExtraHvm = stringListExtraHvm
+	var domainSchedParamsSchedParams DomainSchedParams
+	if err := domainSchedParamsSchedParams.fromC(&xc.sched_params); err != nil {
+		return err
+	}
+	x.SchedParams = domainSchedParamsSchedParams
+	var defboolClaimMode Defbool
+	if err := defboolClaimMode.fromC(&xc.claim_mode); err != nil {
+		return err
+	}
+	x.ClaimMode = defboolClaimMode
+	x.EventChannels = uint32(xc.event_channels)
+	x.Kernel = C.GoString(xc.kernel)
+	x.Cmdline = C.GoString(xc.cmdline)
+	x.Ramdisk = C.GoString(xc.ramdisk)
+	x.DeviceTree = C.GoString(xc.device_tree)
+	var defboolAcpi Defbool
+	if err := defboolAcpi.fromC(&xc.acpi); err != nil {
+		return err
+	}
+	x.Acpi = defboolAcpi
+	x.Bootloader = C.GoString(xc.bootloader)
+	var stringListBootloaderArgs StringList
+	if err := stringListBootloaderArgs.fromC(&xc.bootloader_args); err != nil {
+		return err
+	}
+	x.BootloaderArgs = stringListBootloaderArgs
+	x.TimerMode = TimerMode(xc.timer_mode)
+	var defboolNestedHvm Defbool
+	if err := defboolNestedHvm.fromC(&xc.nested_hvm); err != nil {
+		return err
+	}
+	x.NestedHvm = defboolNestedHvm
+	var defboolApic Defbool
+	if err := defboolApic.fromC(&xc.apic); err != nil {
+		return err
+	}
+	x.Apic = defboolApic
+	var defboolDmRestrict Defbool
+	if err := defboolDmRestrict.fromC(&xc.dm_restrict); err != nil {
+		return err
+	}
+	x.DmRestrict = defboolDmRestrict
+	x.Tee = TeeType(xc.tee)
+	x.ArchArm.GicVersion = GicVersion(xc.arch_arm.gic_version)
+	x.ArchArm.Vuart = VuartType(xc.arch_arm.vuart)
+	x.Altp2M = Altp2MMode(xc.altp2m)
+	return nil
+}
+
+func (x *DeviceVfb) fromC(xc *C.libxl_device_vfb) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	var vncInfoVnc VncInfo
+	if err := vncInfoVnc.fromC(&xc.vnc); err != nil {
+		return err
+	}
+	x.Vnc = vncInfoVnc
+	var sdlInfoSdl SdlInfo
+	if err := sdlInfoSdl.fromC(&xc.sdl); err != nil {
+		return err
+	}
+	x.Sdl = sdlInfoSdl
+	x.Keymap = C.GoString(xc.keymap)
+	return nil
+}
+
+func (x *DeviceVkb) fromC(xc *C.libxl_device_vkb) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	x.BackendType = VkbBackend(xc.backend_type)
+	x.UniqueId = C.GoString(xc.unique_id)
+	x.FeatureDisableKeyboard = bool(xc.feature_disable_keyboard)
+	x.FeatureDisablePointer = bool(xc.feature_disable_pointer)
+	x.FeatureAbsPointer = bool(xc.feature_abs_pointer)
+	x.FeatureRawPointer = bool(xc.feature_raw_pointer)
+	x.FeatureMultiTouch = bool(xc.feature_multi_touch)
+	x.Width = uint32(xc.width)
+	x.Height = uint32(xc.height)
+	x.MultiTouchWidth = uint32(xc.multi_touch_width)
+	x.MultiTouchHeight = uint32(xc.multi_touch_height)
+	x.MultiTouchNumContacts = uint32(xc.multi_touch_num_contacts)
+	return nil
+}
+
+func (x *DeviceDisk) fromC(xc *C.libxl_device_disk) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.PdevPath = C.GoString(xc.pdev_path)
+	x.Vdev = C.GoString(xc.vdev)
+	x.Backend = DiskBackend(xc.backend)
+	x.Format = DiskFormat(xc.format)
+	x.Script = C.GoString(xc.script)
+	x.Removable = int(xc.removable)
+	x.Readwrite = int(xc.readwrite)
+	x.IsCdrom = int(xc.is_cdrom)
+	x.DirectIoSafe = bool(xc.direct_io_safe)
+	var defboolDiscardEnable Defbool
+	if err := defboolDiscardEnable.fromC(&xc.discard_enable); err != nil {
+		return err
+	}
+	x.DiscardEnable = defboolDiscardEnable
+	var defboolColoEnable Defbool
+	if err := defboolColoEnable.fromC(&xc.colo_enable); err != nil {
+		return err
+	}
+	x.ColoEnable = defboolColoEnable
+	var defboolColoRestoreEnable Defbool
+	if err := defboolColoRestoreEnable.fromC(&xc.colo_restore_enable); err != nil {
+		return err
+	}
+	x.ColoRestoreEnable = defboolColoRestoreEnable
+	x.ColoHost = C.GoString(xc.colo_host)
+	x.ColoPort = int(xc.colo_port)
+	x.ColoExport = C.GoString(xc.colo_export)
+	x.ActiveDisk = C.GoString(xc.active_disk)
+	x.HiddenDisk = C.GoString(xc.hidden_disk)
+	return nil
+}
+
+func (x *DeviceNic) fromC(xc *C.libxl_device_nic) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	x.Mtu = int(xc.mtu)
+	x.Model = C.GoString(xc.model)
+	var macMac Mac
+	if err := macMac.fromC(&xc.mac); err != nil {
+		return err
+	}
+	x.Mac = macMac
+	x.Ip = C.GoString(xc.ip)
+	x.Bridge = C.GoString(xc.bridge)
+	x.Ifname = C.GoString(xc.ifname)
+	x.Script = C.GoString(xc.script)
+	x.Nictype = NicType(xc.nictype)
+	x.RateBytesPerInterval = uint64(xc.rate_bytes_per_interval)
+	x.RateIntervalUsecs = uint32(xc.rate_interval_usecs)
+	x.Gatewaydev = C.GoString(xc.gatewaydev)
+	x.ColoftForwarddev = C.GoString(xc.coloft_forwarddev)
+	x.ColoSockMirrorId = C.GoString(xc.colo_sock_mirror_id)
+	x.ColoSockMirrorIp = C.GoString(xc.colo_sock_mirror_ip)
+	x.ColoSockMirrorPort = C.GoString(xc.colo_sock_mirror_port)
+	x.ColoSockComparePriInId = C.GoString(xc.colo_sock_compare_pri_in_id)
+	x.ColoSockComparePriInIp = C.GoString(xc.colo_sock_compare_pri_in_ip)
+	x.ColoSockComparePriInPort = C.GoString(xc.colo_sock_compare_pri_in_port)
+	x.ColoSockCompareSecInId = C.GoString(xc.colo_sock_compare_sec_in_id)
+	x.ColoSockCompareSecInIp = C.GoString(xc.colo_sock_compare_sec_in_ip)
+	x.ColoSockCompareSecInPort = C.GoString(xc.colo_sock_compare_sec_in_port)
+	x.ColoSockCompareNotifyId = C.GoString(xc.colo_sock_compare_notify_id)
+	x.ColoSockCompareNotifyIp = C.GoString(xc.colo_sock_compare_notify_ip)
+	x.ColoSockCompareNotifyPort = C.GoString(xc.colo_sock_compare_notify_port)
+	x.ColoSockRedirector0Id = C.GoString(xc.colo_sock_redirector0_id)
+	x.ColoSockRedirector0Ip = C.GoString(xc.colo_sock_redirector0_ip)
+	x.ColoSockRedirector0Port = C.GoString(xc.colo_sock_redirector0_port)
+	x.ColoSockRedirector1Id = C.GoString(xc.colo_sock_redirector1_id)
+	x.ColoSockRedirector1Ip = C.GoString(xc.colo_sock_redirector1_ip)
+	x.ColoSockRedirector1Port = C.GoString(xc.colo_sock_redirector1_port)
+	x.ColoSockRedirector2Id = C.GoString(xc.colo_sock_redirector2_id)
+	x.ColoSockRedirector2Ip = C.GoString(xc.colo_sock_redirector2_ip)
+	x.ColoSockRedirector2Port = C.GoString(xc.colo_sock_redirector2_port)
+	x.ColoFilterMirrorQueue = C.GoString(xc.colo_filter_mirror_queue)
+	x.ColoFilterMirrorOutdev = C.GoString(xc.colo_filter_mirror_outdev)
+	x.ColoFilterRedirector0Queue = C.GoString(xc.colo_filter_redirector0_queue)
+	x.ColoFilterRedirector0Indev = C.GoString(xc.colo_filter_redirector0_indev)
+	x.ColoFilterRedirector0Outdev = C.GoString(xc.colo_filter_redirector0_outdev)
+	x.ColoFilterRedirector1Queue = C.GoString(xc.colo_filter_redirector1_queue)
+	x.ColoFilterRedirector1Indev = C.GoString(xc.colo_filter_redirector1_indev)
+	x.ColoFilterRedirector1Outdev = C.GoString(xc.colo_filter_redirector1_outdev)
+	x.ColoComparePriIn = C.GoString(xc.colo_compare_pri_in)
+	x.ColoCompareSecIn = C.GoString(xc.colo_compare_sec_in)
+	x.ColoCompareOut = C.GoString(xc.colo_compare_out)
+	x.ColoCompareNotifyDev = C.GoString(xc.colo_compare_notify_dev)
+	x.ColoSockSecRedirector0Id = C.GoString(xc.colo_sock_sec_redirector0_id)
+	x.ColoSockSecRedirector0Ip = C.GoString(xc.colo_sock_sec_redirector0_ip)
+	x.ColoSockSecRedirector0Port = C.GoString(xc.colo_sock_sec_redirector0_port)
+	x.ColoSockSecRedirector1Id = C.GoString(xc.colo_sock_sec_redirector1_id)
+	x.ColoSockSecRedirector1Ip = C.GoString(xc.colo_sock_sec_redirector1_ip)
+	x.ColoSockSecRedirector1Port = C.GoString(xc.colo_sock_sec_redirector1_port)
+	x.ColoFilterSecRedirector0Queue = C.GoString(xc.colo_filter_sec_redirector0_queue)
+	x.ColoFilterSecRedirector0Indev = C.GoString(xc.colo_filter_sec_redirector0_indev)
+	x.ColoFilterSecRedirector0Outdev = C.GoString(xc.colo_filter_sec_redirector0_outdev)
+	x.ColoFilterSecRedirector1Queue = C.GoString(xc.colo_filter_sec_redirector1_queue)
+	x.ColoFilterSecRedirector1Indev = C.GoString(xc.colo_filter_sec_redirector1_indev)
+	x.ColoFilterSecRedirector1Outdev = C.GoString(xc.colo_filter_sec_redirector1_outdev)
+	x.ColoFilterSecRewriter0Queue = C.GoString(xc.colo_filter_sec_rewriter0_queue)
+	x.ColoCheckpointHost = C.GoString(xc.colo_checkpoint_host)
+	x.ColoCheckpointPort = C.GoString(xc.colo_checkpoint_port)
+	return nil
+}
+
+func (x *DevicePci) fromC(xc *C.libxl_device_pci) error {
+	x.Func = byte(xc._func)
+	x.Dev = byte(xc.dev)
+	x.Bus = byte(xc.bus)
+	x.Domain = int(xc.domain)
+	x.Vdevfn = uint32(xc.vdevfn)
+	x.VfuncMask = uint32(xc.vfunc_mask)
+	x.Msitranslate = bool(xc.msitranslate)
+	x.PowerMgmt = bool(xc.power_mgmt)
+	x.Permissive = bool(xc.permissive)
+	x.Seize = bool(xc.seize)
+	x.RdmPolicy = RdmReservePolicy(xc.rdm_policy)
+	return nil
+}
+
+func (x *DeviceRdm) fromC(xc *C.libxl_device_rdm) error {
+	x.Start = uint64(xc.start)
+	x.Size = uint64(xc.size)
+	x.Policy = RdmReservePolicy(xc.policy)
+	return nil
+}
+
+func (x *DeviceUsbctrl) fromC(xc *C.libxl_device_usbctrl) error {
+	x.Type = UsbctrlType(xc._type)
+	x.Devid = Devid(xc.devid)
+	x.Version = int(xc.version)
+	x.Ports = int(xc.ports)
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	return nil
+}
+
+func (x *DeviceUsbdev) fromC(xc *C.libxl_device_usbdev) error {
+	x.Ctrl = Devid(xc.ctrl)
+	x.Port = int(xc.port)
+	return nil
+}
+
+func (x *DeviceDtdev) fromC(xc *C.libxl_device_dtdev) error {
+	x.Path = C.GoString(xc.path)
+	return nil
+}
+
+func (x *DeviceVtpm) fromC(xc *C.libxl_device_vtpm) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	var uuidUuid Uuid
+	if err := uuidUuid.fromC(&xc.uuid); err != nil {
+		return err
+	}
+	x.Uuid = uuidUuid
+	return nil
+}
+
+func (x *DeviceP9) fromC(xc *C.libxl_device_p9) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Tag = C.GoString(xc.tag)
+	x.Path = C.GoString(xc.path)
+	x.SecurityModel = C.GoString(xc.security_model)
+	x.Devid = Devid(xc.devid)
+	return nil
+}
+
+func (x *DevicePvcallsif) fromC(xc *C.libxl_device_pvcallsif) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	return nil
+}
+
+func (x *DeviceChannel) fromC(xc *C.libxl_device_channel) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	x.Name = C.GoString(xc.name)
+	return nil
+}
+
+func (x *ConnectorParam) fromC(xc *C.libxl_connector_param) error {
+	x.UniqueId = C.GoString(xc.unique_id)
+	x.Width = uint32(xc.width)
+	x.Height = uint32(xc.height)
+	return nil
+}
+
+func (x *DeviceVdispl) fromC(xc *C.libxl_device_vdispl) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	x.BeAlloc = bool(xc.be_alloc)
+	return nil
+}
+
+func (x *VsndParams) fromC(xc *C.libxl_vsnd_params) error {
+	x.ChannelsMin = uint32(xc.channels_min)
+	x.ChannelsMax = uint32(xc.channels_max)
+	x.BufferSize = uint32(xc.buffer_size)
+	return nil
+}
+
+func (x *VsndStream) fromC(xc *C.libxl_vsnd_stream) error {
+	x.UniqueId = C.GoString(xc.unique_id)
+	x.Type = VsndStreamType(xc._type)
+	var vsndParamsParams VsndParams
+	if err := vsndParamsParams.fromC(&xc.params); err != nil {
+		return err
+	}
+	x.Params = vsndParamsParams
+	return nil
+}
+
+func (x *VsndPcm) fromC(xc *C.libxl_vsnd_pcm) error {
+	x.Name = C.GoString(xc.name)
+	var vsndParamsParams VsndParams
+	if err := vsndParamsParams.fromC(&xc.params); err != nil {
+		return err
+	}
+	x.Params = vsndParamsParams
+	return nil
+}
+
+func (x *DeviceVsnd) fromC(xc *C.libxl_device_vsnd) error {
+	x.BackendDomid = Domid(xc.backend_domid)
+	x.BackendDomname = C.GoString(xc.backend_domname)
+	x.Devid = Devid(xc.devid)
+	x.ShortName = C.GoString(xc.short_name)
+	x.LongName = C.GoString(xc.long_name)
+	var vsndParamsParams VsndParams
+	if err := vsndParamsParams.fromC(&xc.params); err != nil {
+		return err
+	}
+	x.Params = vsndParamsParams
+	return nil
+}
+
+func (x *DomainConfig) fromC(xc *C.libxl_domain_config) error {
+	var domainCreateInfoCInfo DomainCreateInfo
+	if err := domainCreateInfoCInfo.fromC(&xc.c_info); err != nil {
+		return err
+	}
+	x.CInfo = domainCreateInfoCInfo
+	var domainBuildInfoBInfo DomainBuildInfo
+	if err := domainBuildInfoBInfo.fromC(&xc.b_info); err != nil {
+		return err
+	}
+	x.BInfo = domainBuildInfoBInfo
+	x.OnPoweroff = ActionOnShutdown(xc.on_poweroff)
+	x.OnReboot = ActionOnShutdown(xc.on_reboot)
+	x.OnWatchdog = ActionOnShutdown(xc.on_watchdog)
+	x.OnCrash = ActionOnShutdown(xc.on_crash)
+	x.OnSoftReset = ActionOnShutdown(xc.on_soft_reset)
+	return nil
+}
+
+func (x *Diskinfo) fromC(xc *C.libxl_diskinfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	x.Evtch = int(xc.evtch)
+	x.Rref = int(xc.rref)
+	return nil
+}
+
+func (x *Nicinfo) fromC(xc *C.libxl_nicinfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	x.Evtch = int(xc.evtch)
+	x.RrefTx = int(xc.rref_tx)
+	x.RrefRx = int(xc.rref_rx)
+	return nil
+}
+
+func (x *Vtpminfo) fromC(xc *C.libxl_vtpminfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	x.Evtch = int(xc.evtch)
+	x.Rref = int(xc.rref)
+	var uuidUuid Uuid
+	if err := uuidUuid.fromC(&xc.uuid); err != nil {
+		return err
+	}
+	x.Uuid = uuidUuid
+	return nil
+}
+
+func (x *Usbctrlinfo) fromC(xc *C.libxl_usbctrlinfo) error {
+	x.Type = UsbctrlType(xc._type)
+	x.Devid = Devid(xc.devid)
+	x.Version = int(xc.version)
+	x.Ports = int(xc.ports)
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.State = int(xc.state)
+	x.Evtch = int(xc.evtch)
+	x.RefUrb = int(xc.ref_urb)
+	x.RefConn = int(xc.ref_conn)
+	return nil
+}
+
+func (x *Vcpuinfo) fromC(xc *C.libxl_vcpuinfo) error {
+	x.Vcpuid = uint32(xc.vcpuid)
+	x.Cpu = uint32(xc.cpu)
+	x.Online = bool(xc.online)
+	x.Blocked = bool(xc.blocked)
+	x.Running = bool(xc.running)
+	x.VcpuTime = uint64(xc.vcpu_time)
+	var bitmapCpumap Bitmap
+	if err := bitmapCpumap.fromC(&xc.cpumap); err != nil {
+		return err
+	}
+	x.Cpumap = bitmapCpumap
+	var bitmapCpumapSoft Bitmap
+	if err := bitmapCpumapSoft.fromC(&xc.cpumap_soft); err != nil {
+		return err
+	}
+	x.CpumapSoft = bitmapCpumapSoft
+	return nil
+}
+
+func (x *Physinfo) fromC(xc *C.libxl_physinfo) error {
+	x.ThreadsPerCore = uint32(xc.threads_per_core)
+	x.CoresPerSocket = uint32(xc.cores_per_socket)
+	x.MaxCpuId = uint32(xc.max_cpu_id)
+	x.NrCpus = uint32(xc.nr_cpus)
+	x.CpuKhz = uint32(xc.cpu_khz)
+	x.TotalPages = uint64(xc.total_pages)
+	x.FreePages = uint64(xc.free_pages)
+	x.ScrubPages = uint64(xc.scrub_pages)
+	x.OutstandingPages = uint64(xc.outstanding_pages)
+	x.SharingFreedPages = uint64(xc.sharing_freed_pages)
+	x.SharingUsedFrames = uint64(xc.sharing_used_frames)
+	x.MaxPossibleMfn = uint64(xc.max_possible_mfn)
+	x.NrNodes = uint32(xc.nr_nodes)
+	var hwcapHwCap Hwcap
+	if err := hwcapHwCap.fromC(&xc.hw_cap); err != nil {
+		return err
+	}
+	x.HwCap = hwcapHwCap
+	x.CapHvm = bool(xc.cap_hvm)
+	x.CapPv = bool(xc.cap_pv)
+	x.CapHvmDirectio = bool(xc.cap_hvm_directio)
+	x.CapHap = bool(xc.cap_hap)
+	x.CapShadow = bool(xc.cap_shadow)
+	x.CapIommuHapPtShare = bool(xc.cap_iommu_hap_pt_share)
+	return nil
+}
+
+func (x *Connectorinfo) fromC(xc *C.libxl_connectorinfo) error {
+	x.UniqueId = C.GoString(xc.unique_id)
+	x.Width = uint32(xc.width)
+	x.Height = uint32(xc.height)
+	x.ReqEvtch = int(xc.req_evtch)
+	x.ReqRref = int(xc.req_rref)
+	x.EvtEvtch = int(xc.evt_evtch)
+	x.EvtRref = int(xc.evt_rref)
+	return nil
+}
+
+func (x *Vdisplinfo) fromC(xc *C.libxl_vdisplinfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	x.BeAlloc = bool(xc.be_alloc)
+	return nil
+}
+
+func (x *Streaminfo) fromC(xc *C.libxl_streaminfo) error {
+	x.ReqEvtch = int(xc.req_evtch)
+	x.ReqRref = int(xc.req_rref)
+	return nil
+}
+
+func (x *Pcminfo) fromC(xc *C.libxl_pcminfo) error {
+	return nil
+}
+
+func (x *Vsndinfo) fromC(xc *C.libxl_vsndinfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	return nil
+}
+
+func (x *Vkbinfo) fromC(xc *C.libxl_vkbinfo) error {
+	x.Backend = C.GoString(xc.backend)
+	x.BackendId = uint32(xc.backend_id)
+	x.Frontend = C.GoString(xc.frontend)
+	x.FrontendId = uint32(xc.frontend_id)
+	x.Devid = Devid(xc.devid)
+	x.State = int(xc.state)
+	x.Evtch = int(xc.evtch)
+	x.Rref = int(xc.rref)
+	return nil
+}
+
+func (x *Numainfo) fromC(xc *C.libxl_numainfo) error {
+	x.Size = uint64(xc.size)
+	x.Free = uint64(xc.free)
+	return nil
+}
+
+func (x *Cputopology) fromC(xc *C.libxl_cputopology) error {
+	x.Core = uint32(xc.core)
+	x.Socket = uint32(xc.socket)
+	x.Node = uint32(xc.node)
+	return nil
+}
+
+func (x *Pcitopology) fromC(xc *C.libxl_pcitopology) error {
+	x.Seg = uint16(xc.seg)
+	x.Bus = byte(xc.bus)
+	x.Devfn = byte(xc.devfn)
+	x.Node = uint32(xc.node)
+	return nil
+}
+
+func (x *SchedCreditParams) fromC(xc *C.libxl_sched_credit_params) error {
+	x.TsliceMs = int(xc.tslice_ms)
+	x.RatelimitUs = int(xc.ratelimit_us)
+	x.VcpuMigrDelayUs = int(xc.vcpu_migr_delay_us)
+	return nil
+}
+
+func (x *SchedCredit2Params) fromC(xc *C.libxl_sched_credit2_params) error {
+	x.RatelimitUs = int(xc.ratelimit_us)
+	return nil
+}
+
+func (x *DomainRemusInfo) fromC(xc *C.libxl_domain_remus_info) error {
+	x.Interval = int(xc.interval)
+	var defboolAllowUnsafe Defbool
+	if err := defboolAllowUnsafe.fromC(&xc.allow_unsafe); err != nil {
+		return err
+	}
+	x.AllowUnsafe = defboolAllowUnsafe
+	var defboolBlackhole Defbool
+	if err := defboolBlackhole.fromC(&xc.blackhole); err != nil {
+		return err
+	}
+	x.Blackhole = defboolBlackhole
+	var defboolCompression Defbool
+	if err := defboolCompression.fromC(&xc.compression); err != nil {
+		return err
+	}
+	x.Compression = defboolCompression
+	var defboolNetbuf Defbool
+	if err := defboolNetbuf.fromC(&xc.netbuf); err != nil {
+		return err
+	}
+	x.Netbuf = defboolNetbuf
+	x.Netbufscript = C.GoString(xc.netbufscript)
+	var defboolDiskbuf Defbool
+	if err := defboolDiskbuf.fromC(&xc.diskbuf); err != nil {
+		return err
+	}
+	x.Diskbuf = defboolDiskbuf
+	var defboolColo Defbool
+	if err := defboolColo.fromC(&xc.colo); err != nil {
+		return err
+	}
+	x.Colo = defboolColo
+	var defboolUserspaceColoProxy Defbool
+	if err := defboolUserspaceColoProxy.fromC(&xc.userspace_colo_proxy); err != nil {
+		return err
+	}
+	x.UserspaceColoProxy = defboolUserspaceColoProxy
+	return nil
+}
+
+func (x *Event) fromC(xc *C.libxl_event) error {
+	var evLinkLink EvLink
+	if err := evLinkLink.fromC(&xc.link); err != nil {
+		return err
+	}
+	x.Link = evLinkLink
+	x.Domid = Domid(xc.domid)
+	var uuidDomuuid Uuid
+	if err := uuidDomuuid.fromC(&xc.domuuid); err != nil {
+		return err
+	}
+	x.Domuuid = uuidDomuuid
+	x.ForUser = uint64(xc.for_user)
+	return nil
+}
+
+func (x *PsrCatInfo) fromC(xc *C.libxl_psr_cat_info) error {
+	x.Id = uint32(xc.id)
+	x.CosMax = uint32(xc.cos_max)
+	x.CbmLen = uint32(xc.cbm_len)
+	x.CdpEnabled = bool(xc.cdp_enabled)
+	return nil
+}
+
+func (x *PsrHwInfo) fromC(xc *C.libxl_psr_hw_info) error {
+	x.Id = uint32(xc.id)
+	return nil
+}
diff --git a/tools/golang/xenlight/xenlight.go b/tools/golang/xenlight/xenlight.go
index 9420197bfb..210a418c02 100644
--- a/tools/golang/xenlight/xenlight.go
+++ b/tools/golang/xenlight/xenlight.go
@@ -415,47 +415,6 @@  func (bm *Bitmap) toC() (C.libxl_bitmap, error) {
 	return cbm, nil
 }
 
-func (cphys *C.libxl_physinfo) toGo() (physinfo *Physinfo) {
-
-	physinfo = &Physinfo{}
-	physinfo.ThreadsPerCore = uint32(cphys.threads_per_core)
-	physinfo.CoresPerSocket = uint32(cphys.cores_per_socket)
-	physinfo.MaxCpuId = uint32(cphys.max_cpu_id)
-	physinfo.NrCpus = uint32(cphys.nr_cpus)
-	physinfo.CpuKhz = uint32(cphys.cpu_khz)
-	physinfo.TotalPages = uint64(cphys.total_pages)
-	physinfo.FreePages = uint64(cphys.free_pages)
-	physinfo.ScrubPages = uint64(cphys.scrub_pages)
-	physinfo.ScrubPages = uint64(cphys.scrub_pages)
-	physinfo.SharingFreedPages = uint64(cphys.sharing_freed_pages)
-	physinfo.SharingUsedFrames = uint64(cphys.sharing_used_frames)
-	physinfo.NrNodes = uint32(cphys.nr_nodes)
-	physinfo.HwCap.fromC(&cphys.hw_cap)
-	physinfo.CapHvm = bool(cphys.cap_hvm)
-	physinfo.CapHvmDirectio = bool(cphys.cap_hvm_directio)
-
-	return
-}
-
-func (cinfo *C.libxl_version_info) toGo() (info *VersionInfo) {
-	info = &VersionInfo{}
-	info.XenVersionMajor = int(cinfo.xen_version_major)
-	info.XenVersionMinor = int(cinfo.xen_version_minor)
-	info.XenVersionExtra = C.GoString(cinfo.xen_version_extra)
-	info.Compiler = C.GoString(cinfo.compiler)
-	info.CompileBy = C.GoString(cinfo.compile_by)
-	info.CompileDomain = C.GoString(cinfo.compile_domain)
-	info.CompileDate = C.GoString(cinfo.compile_date)
-	info.Capabilities = C.GoString(cinfo.capabilities)
-	info.Changeset = C.GoString(cinfo.changeset)
-	info.VirtStart = uint64(cinfo.virt_start)
-	info.Pagesize = int(cinfo.pagesize)
-	info.Commandline = C.GoString(cinfo.commandline)
-	info.BuildId = C.GoString(cinfo.build_id)
-
-	return
-}
-
 func (sr ShutdownReason) String() (str string) {
 	cstr := C.libxl_shutdown_reason_to_string(C.libxl_shutdown_reason(sr))
 	str = C.GoString(cstr)
@@ -470,34 +429,6 @@  func (dt DomainType) String() (str string) {
 	return
 }
 
-func (cdi *C.libxl_dominfo) toGo() (di *Dominfo) {
-
-	di = &Dominfo{}
-	di.Uuid.fromC(&cdi.uuid)
-	di.Domid = Domid(cdi.domid)
-	di.Ssidref = uint32(cdi.ssidref)
-	di.SsidLabel = C.GoString(cdi.ssid_label)
-	di.Running = bool(cdi.running)
-	di.Blocked = bool(cdi.blocked)
-	di.Paused = bool(cdi.paused)
-	di.Shutdown = bool(cdi.shutdown)
-	di.Dying = bool(cdi.dying)
-	di.NeverStop = bool(cdi.never_stop)
-	di.ShutdownReason = ShutdownReason(cdi.shutdown_reason)
-	di.OutstandingMemkb = uint64(cdi.outstanding_memkb)
-	di.CurrentMemkb = uint64(cdi.current_memkb)
-	di.SharedMemkb = uint64(cdi.shared_memkb)
-	di.PagedMemkb = uint64(cdi.paged_memkb)
-	di.MaxMemkb = uint64(cdi.max_memkb)
-	di.CpuTime = uint64(cdi.cpu_time)
-	di.VcpuMaxId = uint32(cdi.vcpu_max_id)
-	di.VcpuOnline = uint32(cdi.vcpu_online)
-	di.Cpupool = uint32(cdi.cpupool)
-	di.DomainType = DomainType(cdi.domain_type)
-
-	return
-}
-
 // const char *libxl_scheduler_to_string(libxl_scheduler p);
 func (s Scheduler) String() string {
 	cs := C.libxl_scheduler_to_string(C.libxl_scheduler(s))
@@ -529,16 +460,6 @@  func SchedulerFromString(name string) (s Scheduler, err error) {
 	return
 }
 
-func (cci C.libxl_cpupoolinfo) toGo() (gci Cpupoolinfo) {
-	gci.Poolid = uint32(cci.poolid)
-	gci.PoolName = C.GoString(cci.pool_name)
-	gci.Sched = Scheduler(cci.sched)
-	gci.NDom = uint32(cci.n_dom)
-	gci.Cpumap.fromC(&cci.cpumap)
-
-	return
-}
-
 // libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx*, int *nb_pool_out);
 // void libxl_cpupoolinfo_list_free(libxl_cpupoolinfo *list, int nb_pool);
 func (Ctx *Context) ListCpupool() (list []Cpupoolinfo) {
@@ -560,7 +481,8 @@  func (Ctx *Context) ListCpupool() (list []Cpupoolinfo) {
 	// Magic
 	cpupoolListSlice := (*[1 << 30]C.libxl_cpupoolinfo)(unsafe.Pointer(c_cpupool_list))[:nbPool:nbPool]
 	for i := range cpupoolListSlice {
-		info := cpupoolListSlice[i].toGo()
+		var info Cpupoolinfo
+		_ = info.fromC(&cpupoolListSlice[i])
 		list = append(list, info)
 	}
 
@@ -583,7 +505,7 @@  func (Ctx *Context) CpupoolInfo(Poolid uint32) (pool Cpupoolinfo) {
 	}
 	defer C.libxl_cpupoolinfo_dispose(&c_cpupool)
 
-	pool = c_cpupool.toGo()
+	_ = pool.fromC(&c_cpupool)
 
 	return
 }
@@ -1074,7 +996,7 @@  func (Ctx *Context) GetPhysinfo() (physinfo *Physinfo, err error) {
 		err = Error(ret)
 		return
 	}
-	physinfo = cphys.toGo()
+	err = physinfo.fromC(&cphys)
 
 	return
 }
@@ -1090,7 +1012,7 @@  func (Ctx *Context) GetVersionInfo() (info *VersionInfo, err error) {
 
 	cinfo = C.libxl_get_version_info(Ctx.ctx)
 
-	info = cinfo.toGo()
+	err = info.fromC(cinfo)
 
 	return
 }
@@ -1112,7 +1034,7 @@  func (Ctx *Context) DomainInfo(Id Domid) (di *Dominfo, err error) {
 		return
 	}
 
-	di = cdi.toGo()
+	err = di.fromC(&cdi)
 
 	return
 }
@@ -1194,26 +1116,14 @@  func (Ctx *Context) ListDomain() (glist []Dominfo) {
 
 	gslice := (*[1 << 30]C.libxl_dominfo)(unsafe.Pointer(clist))[:nbDomain:nbDomain]
 	for i := range gslice {
-		info := gslice[i].toGo()
-		glist = append(glist, *info)
+		var info Dominfo
+		_ = info.fromC(&gslice[i])
+		glist = append(glist, info)
 	}
 
 	return
 }
 
-func (cvci C.libxl_vcpuinfo) toGo() (gvci Vcpuinfo) {
-	gvci.Vcpuid = uint32(cvci.vcpuid)
-	gvci.Cpu = uint32(cvci.cpu)
-	gvci.Online = bool(cvci.online)
-	gvci.Blocked = bool(cvci.blocked)
-	gvci.Running = bool(cvci.running)
-	gvci.VcpuTime = uint64(cvci.vcpu_time)
-	gvci.Cpumap.fromC(&cvci.cpumap)
-	gvci.CpumapSoft.fromC(&cvci.cpumap_soft)
-
-	return
-}
-
 //libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
 //				int *nb_vcpu, int *nr_cpus_out);
 //void libxl_vcpuinfo_list_free(libxl_vcpuinfo *, int nr_vcpus);
@@ -1235,7 +1145,8 @@  func (Ctx *Context) ListVcpu(id Domid) (glist []Vcpuinfo) {
 
 	gslice := (*[1 << 30]C.libxl_vcpuinfo)(unsafe.Pointer(clist))[:nbVcpu:nbVcpu]
 	for i := range gslice {
-		info := gslice[i].toGo()
+		var info Vcpuinfo
+		_ = info.fromC(&gslice[i])
 		glist = append(glist, info)
 	}