intel: fix copying of create info

For XGL_STRUCTURE_TYPE_DEVICE_CREATE_INFO, we need to do a deep copy.  To
achieve, we need to derive the type of the create info from within
intel_base_dbg_create().

As usual, this is untested.
diff --git a/icd/intel/dev.c b/icd/intel/dev.c
index c8f6871..cb96022 100644
--- a/icd/intel/dev.c
+++ b/icd/intel/dev.c
@@ -31,7 +31,7 @@
 static struct intel_dev_dbg *dev_dbg_create(const XGL_DEVICE_CREATE_INFO *info)
 {
     return (struct intel_dev_dbg *)
-        intel_base_dbg_create(XGL_DBG_OBJECT_DEVICE, info, sizeof(*info),
+        intel_base_dbg_create(XGL_DBG_OBJECT_DEVICE, info,
                 sizeof(struct intel_dev_dbg));
 }
 
diff --git a/icd/intel/event.c b/icd/intel/event.c
index 54ae2a0..de64924 100644
--- a/icd/intel/event.c
+++ b/icd/intel/event.c
@@ -131,8 +131,8 @@
 
     event->obj.base.dispatch = dev->base.dispatch;
     if (dev->base.dbg) {
-        event->obj.base.dbg = intel_base_dbg_create(XGL_DBG_OBJECT_EVENT,
-                info, sizeof(*info), 0);
+        event->obj.base.dbg =
+            intel_base_dbg_create(XGL_DBG_OBJECT_EVENT, info, 0);
         if (!event->obj.base.dbg) {
             icd_free(event);
             return XGL_ERROR_OUT_OF_MEMORY;
diff --git a/icd/intel/fence.c b/icd/intel/fence.c
index f5c5a6f..842f134 100644
--- a/icd/intel/fence.c
+++ b/icd/intel/fence.c
@@ -49,8 +49,8 @@
 
     fence->obj.base.dispatch = dev->base.dispatch;
     if (dev->base.dbg) {
-        fence->obj.base.dbg = intel_base_dbg_create(XGL_DBG_OBJECT_FENCE,
-                info, sizeof(*info), 0);
+        fence->obj.base.dbg =
+            intel_base_dbg_create(XGL_DBG_OBJECT_FENCE, info, 0);
         if (!fence->obj.base.dbg) {
             icd_free(fence);
             return XGL_ERROR_OUT_OF_MEMORY;
diff --git a/icd/intel/mem.c b/icd/intel/mem.c
index c887a8e..7f1cc7f 100644
--- a/icd/intel/mem.c
+++ b/icd/intel/mem.c
@@ -43,8 +43,8 @@
 
     mem->base.dispatch = dev->base.dispatch;
     if (dev->base.dbg) {
-        mem->base.dbg = intel_base_dbg_create(XGL_DBG_OBJECT_GPU_MEMORY,
-                NULL, 0, 0);
+        mem->base.dbg =
+            intel_base_dbg_create(XGL_DBG_OBJECT_GPU_MEMORY, info, 0);
         if (!mem->base.dbg) {
             intel_mem_free(mem);
             return XGL_ERROR_OUT_OF_MEMORY;
diff --git a/icd/intel/obj.c b/icd/intel/obj.c
index 2ea35f4..f6b6e15 100644
--- a/icd/intel/obj.c
+++ b/icd/intel/obj.c
@@ -61,13 +61,103 @@
     return ret;
 }
 
+static bool base_dbg_copy_create_info(struct intel_base_dbg *dbg,
+                                      const void *create_info)
+{
+    const union {
+        const void *ptr;
+        const struct {
+            XGL_STRUCTURE_TYPE struct_type;
+            XGL_VOID *next;
+        } *header;
+    } info = { .ptr = create_info };
+    XGL_SIZE shallow_copy = 0;
+
+    if (!create_info)
+        return true;
+
+    switch (info.header->struct_type) {
+    case XGL_STRUCTURE_TYPE_DEVICE_CREATE_INFO:
+        assert(dbg->type == XGL_DBG_OBJECT_DEVICE);
+        break;
+    case XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO:
+        assert(dbg->type == XGL_DBG_OBJECT_GPU_MEMORY);
+        shallow_copy = sizeof(XGL_MEMORY_ALLOC_INFO);
+        break;
+    case XGL_STRUCTURE_TYPE_EVENT_CREATE_INFO:
+        assert(dbg->type == XGL_DBG_OBJECT_EVENT);
+        shallow_copy = sizeof(XGL_EVENT_CREATE_INFO);
+        break;
+    case XGL_STRUCTURE_TYPE_FENCE_CREATE_INFO:
+        assert(dbg->type == XGL_DBG_OBJECT_FENCE);
+        shallow_copy = sizeof(XGL_FENCE_CREATE_INFO);
+        break;
+    default:
+        return false;
+        break;
+    }
+
+    if (shallow_copy) {
+        assert(!info.header->next);
+
+        dbg->create_info = icd_alloc(shallow_copy, 0, XGL_SYSTEM_ALLOC_DEBUG);
+        if (!dbg->create_info)
+            return false;
+
+        memcpy(dbg->create_info, create_info, shallow_copy);
+    } else if (info.header->struct_type ==
+            XGL_STRUCTURE_TYPE_DEVICE_CREATE_INFO) {
+        const XGL_DEVICE_CREATE_INFO *src = info.ptr;
+        XGL_DEVICE_CREATE_INFO *dst;
+        uint8_t *d;
+        XGL_SIZE size;
+        XGL_UINT i;
+
+        size = sizeof(*src);
+        size += sizeof(src->pRequestedQueues[0]) * src->queueRecordCount;
+        size += sizeof(src->ppEnabledExtensionNames[0]) * src->extensionCount;
+        for (i = 0; i < src->extensionCount; i++) {
+            size += 1 +
+                strlen((const char *) src->ppEnabledExtensionNames[i]);
+        }
+
+        dst = icd_alloc(sizeof(size), 0, XGL_SYSTEM_ALLOC_DEBUG);
+        if (!dst)
+            return false;
+
+        memcpy(dst, src, sizeof(*src));
+
+        d = (uint8_t *) dst;
+        d += sizeof(*src);
+
+        size = sizeof(src->pRequestedQueues[0]) * src->queueRecordCount;
+        memcpy(d, src->pRequestedQueues, size);
+        dst->pRequestedQueues = (const XGL_DEVICE_QUEUE_CREATE_INFO *) d;
+        d += size;
+
+        size = sizeof(src->ppEnabledExtensionNames[0]) * src->extensionCount;
+        dst->ppEnabledExtensionNames = (const XGL_CHAR * const *) d;
+
+        for (i = 0; i < src->extensionCount; i++) {
+            const XGL_SIZE len =
+                strlen((const char *) src->ppEnabledExtensionNames[i]);
+
+            memcpy(d + size, src->ppEnabledExtensionNames[i], len + 1);
+            ((const XGL_CHAR **) d)[i] = (const XGL_CHAR *) (d + size);
+
+            size += len + 1;
+        }
+    }
+
+    return true;
+}
+
 /**
  * Create an intel_base_dbg.  When alloc_size is non-zero, a buffer of that
  * size is allocated and zeroed.
  */
 struct intel_base_dbg *intel_base_dbg_create(XGL_DBG_OBJECT_TYPE type,
                                              const void *create_info,
-                                             XGL_SIZE create_info_size,
                                              XGL_SIZE alloc_size)
 {
     struct intel_base_dbg *dbg;
@@ -86,15 +176,9 @@
     dbg->alloc_id = icd_get_allocator_id();
     dbg->type = type;
 
-    if (create_info_size) {
-        dbg->create_info =
-            icd_alloc(create_info_size, 0, XGL_SYSTEM_ALLOC_DEBUG);
-        if (!dbg->create_info) {
-            icd_free(dbg);
-            return NULL;
-        }
-
-        memcpy(dbg->create_info, create_info, create_info_size);
+    if (!base_dbg_copy_create_info(dbg, create_info)) {
+        icd_free(dbg);
+        return NULL;
     }
 
     return dbg;
diff --git a/icd/intel/obj.h b/icd/intel/obj.h
index acdedd8..b8f2f99 100644
--- a/icd/intel/obj.h
+++ b/icd/intel/obj.h
@@ -85,7 +85,6 @@
 
 struct intel_base_dbg *intel_base_dbg_create(XGL_DBG_OBJECT_TYPE type,
                                              const void *create_info,
-                                             XGL_SIZE create_info_size,
                                              XGL_SIZE alloc_size);
 void intel_base_dbg_destroy(struct intel_base_dbg *dbg);
 
diff --git a/icd/intel/queue.c b/icd/intel/queue.c
index 9dc23ab..a35449c 100644
--- a/icd/intel/queue.c
+++ b/icd/intel/queue.c
@@ -41,8 +41,8 @@
 
     queue->base.dispatch = dev->base.dispatch;
     if (dev->base.dbg) {
-        queue->base.dbg = intel_base_dbg_create(XGL_DBG_OBJECT_QUEUE,
-                NULL, 0, 0);
+        queue->base.dbg =
+            intel_base_dbg_create(XGL_DBG_OBJECT_QUEUE, NULL, 0);
         if (!queue->base.dbg) {
             icd_free(queue);
             return XGL_ERROR_OUT_OF_MEMORY;