diff mbox series

[2/2] contrib/elf2dmp: elf2dmp for Windows hosts

Message ID 20181102002818.8568-3-viktor.prutyanov@phystech.edu (mailing list archive)
State New, archived
Headers show
Series [1/2] contrib/elf2dmp: use GLib file mapping | expand

Commit Message

Viktor Prutyanov Nov. 2, 2018, 12:28 a.m. UTC
After this patch elf2dmp can be built by mingw64 for Windows hosts.

Signed-off-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
---
 Makefile               |  4 ++--
 contrib/elf2dmp/kdbg.h | 12 ++++++++----
 contrib/elf2dmp/main.c | 27 +++++++++++++++------------
 contrib/elf2dmp/pdb.c  |  4 +++-
 contrib/elf2dmp/pdb.h  |  2 ++
 contrib/elf2dmp/pe.h   |  6 ++++--
 6 files changed, 34 insertions(+), 21 deletions(-)

Comments

Roman Kagan Nov. 21, 2018, 10:25 a.m. UTC | #1
On Fri, Nov 02, 2018 at 03:28:18AM +0300, Viktor Prutyanov wrote:
> After this patch elf2dmp can be built by mingw64 for Windows hosts.

What prevents building it with mingw32?  (I realize that since the tool
uses mmaped access to the dump data it's limited to dumps under a couple
of gigs but it's still not totally useless).

> Signed-off-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
> ---
>  Makefile               |  4 ++--
>  contrib/elf2dmp/kdbg.h | 12 ++++++++----
>  contrib/elf2dmp/main.c | 27 +++++++++++++++------------
>  contrib/elf2dmp/pdb.c  |  4 +++-
>  contrib/elf2dmp/pdb.h  |  2 ++
>  contrib/elf2dmp/pe.h   |  6 ++++--
>  6 files changed, 34 insertions(+), 21 deletions(-)

Isn't there a configure check that needs to be removed?

> 
> diff --git a/Makefile b/Makefile
> index ef53dd2a97..73adb02b41 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -711,8 +711,8 @@ ifneq ($(EXESUF),)
>  qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
>  endif
>  
> -elf2dmp: LIBS += $(CURL_LIBS)
> -elf2dmp: $(elf2dmp-obj-y)
> +elf2dmp$(EXESUF): LIBS += $(CURL_LIBS)
> +elf2dmp$(EXESUF): $(elf2dmp-obj-y)
>  	$(call LINK, $^)
>  
>  ifdef CONFIG_IVSHMEM
> diff --git a/contrib/elf2dmp/kdbg.h b/contrib/elf2dmp/kdbg.h
> index 851b57c321..d3936994a0 100644
> --- a/contrib/elf2dmp/kdbg.h
> +++ b/contrib/elf2dmp/kdbg.h
> @@ -25,11 +25,15 @@ typedef struct DBGKD_GET_VERSION64 {
>      uint64_t DebuggerDataList;
>  } DBGKD_GET_VERSION64;
>  
> +#ifndef _WIN64

So this may be better _WIN32

> +typedef struct LIST_ENTRY64 {
> +    struct LIST_ENTRY64 *Flink;
> +    struct LIST_ENTRY64 *Blink;
> +} LIST_ENTRY64;
> +#endif
> +
>  typedef struct DBGKD_DEBUG_DATA_HEADER64 {
> -    struct LIST_ENTRY64 {
> -       struct LIST_ENTRY64 *Flink;
> -       struct LIST_ENTRY64 *Blink;
> -    } List;
> +    LIST_ENTRY64    List;
>      uint32_t           OwnerTag;
>      uint32_t           Size;
>  } DBGKD_DEBUG_DATA_HEADER64;
> diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
> index 9b93dab662..fdafb54900 100644
> --- a/contrib/elf2dmp/main.c
> +++ b/contrib/elf2dmp/main.c
> @@ -5,6 +5,8 @@
>   *
>   */
>  
> +#include <inttypes.h>
> +
>  #include "qemu/osdep.h"
>  #include "err.h"
>  #include "addrspace.h"
> @@ -41,7 +43,8 @@ static const uint64_t SharedUserData = 0xfffff78000000000;
>  #define KUSD_OFFSET_PRODUCT_TYPE 0x264
>  
>  #define SYM_RESOLVE(base, r, s) ((s = pdb_resolve(base, r, #s)),\
> -    s ? printf(#s" = 0x%016lx\n", s) : eprintf("Failed to resolve "#s"\n"), s)
> +    s ? printf(#s" = 0x%016"PRIx64"\n", s) :\

I'd rather split the fixes to printf specifiers into a separate patch,
as they have nothing to do with Windows support.

Thanks,
Roman.

> +    eprintf("Failed to resolve "#s"\n"), s)
>  
>  static uint64_t rol(uint64_t x, uint64_t y)
>  {
> @@ -98,8 +101,8 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb,
>              return NULL;
>          }
>  
> -        printf("[KiWaitNever] = 0x%016lx\n", kwn);
> -        printf("[KiWaitAlways] = 0x%016lx\n", kwa);
> +        printf("[KiWaitNever] = 0x%016"PRIx64"\n", kwn);
> +        printf("[KiWaitAlways] = 0x%016"PRIx64"\n", kwa);
>  
>          /*
>           * If KDBG header can be decoded, KDBG size is available
> @@ -202,7 +205,7 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
>  
>          if (is_system(s)) {
>              va_space_set_dtb(vs, s->cr[3]);
> -            printf("DTB 0x%016lx has been found from CPU #%zu"
> +            printf("DTB 0x%016"PRIx64" has been found from CPU #%zu"
>                      " as system task CR3\n", vs->dtb, i);
>              return !(va_space_resolve(vs, SharedUserData));
>          }
> @@ -222,7 +225,7 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
>          }
>  
>          va_space_set_dtb(vs, *cr3);
> -        printf("DirectoryTableBase = 0x%016lx has been found from CPU #0"
> +        printf("DirectoryTableBase = 0x%016"PRIx64" has been found from CPU #0"
>                  " as interrupt handling CR3\n", vs->dtb);
>          return !(va_space_resolve(vs, SharedUserData));
>      }
> @@ -393,8 +396,8 @@ static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr,
>          return 1;
>      }
>  
> -    printf("Debug Directory RVA = 0x%016x\n",
> -            data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
> +    printf("Debug Directory RVA = 0x%08"PRIx32"\n",
> +            (uint32_t)data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
>  
>      if (va_space_rw(vs,
>                  base + data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress,
> @@ -488,7 +491,7 @@ int main(int argc, char *argv[])
>      }
>  
>      state = qemu_elf.state[0];
> -    printf("CPU #0 CR3 is 0x%016lx\n", state->cr[3]);
> +    printf("CPU #0 CR3 is 0x%016"PRIx64"\n", state->cr[3]);
>  
>      va_space_create(&vs, &ps, state->cr[3]);
>      if (fix_dtb(&vs, &qemu_elf)) {
> @@ -497,7 +500,7 @@ int main(int argc, char *argv[])
>          goto out_elf;
>      }
>  
> -    printf("CPU #0 IDT is at 0x%016lx\n", state->idt.base);
> +    printf("CPU #0 IDT is at 0x%016"PRIx64"\n", state->idt.base);
>  
>      if (va_space_rw(&vs, state->idt.base,
>                  &first_idt_desc, sizeof(first_idt_desc), 0)) {
> @@ -505,10 +508,10 @@ int main(int argc, char *argv[])
>          err = 1;
>          goto out_ps;
>      }
> -    printf("CPU #0 IDT[0] -> 0x%016lx\n", idt_desc_addr(first_idt_desc));
> +    printf("CPU #0 IDT[0] -> 0x%016"PRIx64"\n", idt_desc_addr(first_idt_desc));
>  
>      KernBase = idt_desc_addr(first_idt_desc) & ~(PAGE_SIZE - 1);
> -    printf("Searching kernel downwards from 0x%16lx...\n", KernBase);
> +    printf("Searching kernel downwards from 0x%016"PRIx64"...\n", KernBase);
>  
>      for (; KernBase >= 0xfffff78000000000; KernBase -= PAGE_SIZE) {
>          nt_start_addr = va_space_resolve(&vs, KernBase);
> @@ -521,7 +524,7 @@ int main(int argc, char *argv[])
>          }
>      }
>  
> -    printf("KernBase = 0x%16lx, signature is \'%.2s\'\n", KernBase,
> +    printf("KernBase = 0x%016"PRIx64", signature is \'%.2s\'\n", KernBase,
>              (char *)nt_start_addr);
>  
>      if (pe_get_pdb_symstore_hash(KernBase, nt_start_addr, pdb_hash, &vs)) {
> diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
> index 8fa5d71c66..0c5a6fbb9e 100644
> --- a/contrib/elf2dmp/pdb.c
> +++ b/contrib/elf2dmp/pdb.c
> @@ -18,6 +18,8 @@
>   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
>   */
>  
> +#include <inttypes.h>
> +
>  #include "qemu/osdep.h"
>  #include "pdb.h"
>  #include "err.h"
> @@ -66,7 +68,7 @@ uint64_t pdb_find_public_v3_symbol(struct pdb_reader *r, const char *name)
>              uint32_t sect_rva = segment->dword[1];
>              uint64_t rva = sect_rva + sym->public_v3.offset;
>  
> -            printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09lx\n", name,
> +            printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09"PRIx64"\n", name,
>                      sect_rva, sym->public_v3.segment,
>                      ((char *)segment - 8), sym->public_v3.offset, rva);
>              return rva;
> diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h
> index 21c0a0e833..fe189f0ecc 100644
> --- a/contrib/elf2dmp/pdb.h
> +++ b/contrib/elf2dmp/pdb.h
> @@ -13,12 +13,14 @@
>  
>  #include "file_map.h"
>  
> +#ifndef _WIN64
>  typedef struct GUID {
>      unsigned int Data1;
>      unsigned short Data2;
>      unsigned short Data3;
>      unsigned char Data4[8];
>  } GUID;
> +#endif
>  
>  struct PDB_FILE {
>      uint32_t size;
> diff --git a/contrib/elf2dmp/pe.h b/contrib/elf2dmp/pe.h
> index 374e06a9c5..7b60849713 100644
> --- a/contrib/elf2dmp/pe.h
> +++ b/contrib/elf2dmp/pe.h
> @@ -10,6 +10,7 @@
>  
>  #include <stdint.h>
>  
> +#ifndef _WIN64
>  typedef struct IMAGE_DOS_HEADER {
>      uint16_t  e_magic;      /* 0x00: MZ Header signature */
>      uint16_t  e_cblp;       /* 0x02: Bytes on last page of file */
> @@ -88,8 +89,6 @@ typedef struct IMAGE_NT_HEADERS64 {
>    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
>  } __attribute__ ((packed)) IMAGE_NT_HEADERS64;
>  
> -#define IMAGE_FILE_DEBUG_DIRECTORY  6
> -
>  typedef struct IMAGE_DEBUG_DIRECTORY {
>    uint32_t Characteristics;
>    uint32_t TimeDateStamp;
> @@ -102,6 +101,9 @@ typedef struct IMAGE_DEBUG_DIRECTORY {
>  } __attribute__ ((packed)) IMAGE_DEBUG_DIRECTORY;
>  
>  #define IMAGE_DEBUG_TYPE_CODEVIEW   2
> +#endif
> +
> +#define IMAGE_FILE_DEBUG_DIRECTORY  6
>  
>  typedef struct guid_t {
>      uint32_t a;
> -- 
> 2.17.2
>
Eric Blake Nov. 21, 2018, 4:54 p.m. UTC | #2
On 11/21/18 4:25 AM, Roman Kagan wrote:
> On Fri, Nov 02, 2018 at 03:28:18AM +0300, Viktor Prutyanov wrote:
>> After this patch elf2dmp can be built by mingw64 for Windows hosts.
> 
> What prevents building it with mingw32?  (I realize that since the tool
> uses mmaped access to the dump data it's limited to dumps under a couple
> of gigs but it's still not totally useless).

Careful. The original (32-bit) mingw project is obsolete, and its 
replacement, the mingw64 project, provides both 32- and 64-bit 
environments.  Even more confusingly, Fedora ships the mingw64 
cross-compilers under the names i686-w64-mingw32-gcc (build for a 32-bit 
environment) and x86_64-w64-mingw32-gcc (build for a 64-bit 
environment).  Historical naming causes confusion.

So your question may not be relevant, especially given that 
tests/docker/test-mingw builds both 32- and 64-bit mingw builds.
Roman Kagan Nov. 22, 2018, 9:04 a.m. UTC | #3
On Wed, Nov 21, 2018 at 10:54:15AM -0600, Eric Blake wrote:
> On 11/21/18 4:25 AM, Roman Kagan wrote:
> > On Fri, Nov 02, 2018 at 03:28:18AM +0300, Viktor Prutyanov wrote:
> > > After this patch elf2dmp can be built by mingw64 for Windows hosts.
> > 
> > What prevents building it with mingw32?  (I realize that since the tool
> > uses mmaped access to the dump data it's limited to dumps under a couple
> > of gigs but it's still not totally useless).
> 
> Careful. The original (32-bit) mingw project is obsolete, and its
> replacement, the mingw64 project, provides both 32- and 64-bit environments.
> Even more confusingly, Fedora ships the mingw64 cross-compilers under the
> names i686-w64-mingw32-gcc (build for a 32-bit environment) and
> x86_64-w64-mingw32-gcc (build for a 64-bit environment).  Historical naming
> causes confusion.

Indeed.

> So your question may not be relevant, especially given that
> tests/docker/test-mingw builds both 32- and 64-bit mingw builds.

I think it still is :)

The patch protects certain parts with #ifdef _WIN64, so it looks like it
won't build against 32-bit mingw.  Hence my question.

Roman.
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index ef53dd2a97..73adb02b41 100644
--- a/Makefile
+++ b/Makefile
@@ -711,8 +711,8 @@  ifneq ($(EXESUF),)
 qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
 endif
 
-elf2dmp: LIBS += $(CURL_LIBS)
-elf2dmp: $(elf2dmp-obj-y)
+elf2dmp$(EXESUF): LIBS += $(CURL_LIBS)
+elf2dmp$(EXESUF): $(elf2dmp-obj-y)
 	$(call LINK, $^)
 
 ifdef CONFIG_IVSHMEM
diff --git a/contrib/elf2dmp/kdbg.h b/contrib/elf2dmp/kdbg.h
index 851b57c321..d3936994a0 100644
--- a/contrib/elf2dmp/kdbg.h
+++ b/contrib/elf2dmp/kdbg.h
@@ -25,11 +25,15 @@  typedef struct DBGKD_GET_VERSION64 {
     uint64_t DebuggerDataList;
 } DBGKD_GET_VERSION64;
 
+#ifndef _WIN64
+typedef struct LIST_ENTRY64 {
+    struct LIST_ENTRY64 *Flink;
+    struct LIST_ENTRY64 *Blink;
+} LIST_ENTRY64;
+#endif
+
 typedef struct DBGKD_DEBUG_DATA_HEADER64 {
-    struct LIST_ENTRY64 {
-       struct LIST_ENTRY64 *Flink;
-       struct LIST_ENTRY64 *Blink;
-    } List;
+    LIST_ENTRY64    List;
     uint32_t           OwnerTag;
     uint32_t           Size;
 } DBGKD_DEBUG_DATA_HEADER64;
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 9b93dab662..fdafb54900 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -5,6 +5,8 @@ 
  *
  */
 
+#include <inttypes.h>
+
 #include "qemu/osdep.h"
 #include "err.h"
 #include "addrspace.h"
@@ -41,7 +43,8 @@  static const uint64_t SharedUserData = 0xfffff78000000000;
 #define KUSD_OFFSET_PRODUCT_TYPE 0x264
 
 #define SYM_RESOLVE(base, r, s) ((s = pdb_resolve(base, r, #s)),\
-    s ? printf(#s" = 0x%016lx\n", s) : eprintf("Failed to resolve "#s"\n"), s)
+    s ? printf(#s" = 0x%016"PRIx64"\n", s) :\
+    eprintf("Failed to resolve "#s"\n"), s)
 
 static uint64_t rol(uint64_t x, uint64_t y)
 {
@@ -98,8 +101,8 @@  static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb,
             return NULL;
         }
 
-        printf("[KiWaitNever] = 0x%016lx\n", kwn);
-        printf("[KiWaitAlways] = 0x%016lx\n", kwa);
+        printf("[KiWaitNever] = 0x%016"PRIx64"\n", kwn);
+        printf("[KiWaitAlways] = 0x%016"PRIx64"\n", kwa);
 
         /*
          * If KDBG header can be decoded, KDBG size is available
@@ -202,7 +205,7 @@  static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
 
         if (is_system(s)) {
             va_space_set_dtb(vs, s->cr[3]);
-            printf("DTB 0x%016lx has been found from CPU #%zu"
+            printf("DTB 0x%016"PRIx64" has been found from CPU #%zu"
                     " as system task CR3\n", vs->dtb, i);
             return !(va_space_resolve(vs, SharedUserData));
         }
@@ -222,7 +225,7 @@  static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
         }
 
         va_space_set_dtb(vs, *cr3);
-        printf("DirectoryTableBase = 0x%016lx has been found from CPU #0"
+        printf("DirectoryTableBase = 0x%016"PRIx64" has been found from CPU #0"
                 " as interrupt handling CR3\n", vs->dtb);
         return !(va_space_resolve(vs, SharedUserData));
     }
@@ -393,8 +396,8 @@  static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr,
         return 1;
     }
 
-    printf("Debug Directory RVA = 0x%016x\n",
-            data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
+    printf("Debug Directory RVA = 0x%08"PRIx32"\n",
+            (uint32_t)data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
 
     if (va_space_rw(vs,
                 base + data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress,
@@ -488,7 +491,7 @@  int main(int argc, char *argv[])
     }
 
     state = qemu_elf.state[0];
-    printf("CPU #0 CR3 is 0x%016lx\n", state->cr[3]);
+    printf("CPU #0 CR3 is 0x%016"PRIx64"\n", state->cr[3]);
 
     va_space_create(&vs, &ps, state->cr[3]);
     if (fix_dtb(&vs, &qemu_elf)) {
@@ -497,7 +500,7 @@  int main(int argc, char *argv[])
         goto out_elf;
     }
 
-    printf("CPU #0 IDT is at 0x%016lx\n", state->idt.base);
+    printf("CPU #0 IDT is at 0x%016"PRIx64"\n", state->idt.base);
 
     if (va_space_rw(&vs, state->idt.base,
                 &first_idt_desc, sizeof(first_idt_desc), 0)) {
@@ -505,10 +508,10 @@  int main(int argc, char *argv[])
         err = 1;
         goto out_ps;
     }
-    printf("CPU #0 IDT[0] -> 0x%016lx\n", idt_desc_addr(first_idt_desc));
+    printf("CPU #0 IDT[0] -> 0x%016"PRIx64"\n", idt_desc_addr(first_idt_desc));
 
     KernBase = idt_desc_addr(first_idt_desc) & ~(PAGE_SIZE - 1);
-    printf("Searching kernel downwards from 0x%16lx...\n", KernBase);
+    printf("Searching kernel downwards from 0x%016"PRIx64"...\n", KernBase);
 
     for (; KernBase >= 0xfffff78000000000; KernBase -= PAGE_SIZE) {
         nt_start_addr = va_space_resolve(&vs, KernBase);
@@ -521,7 +524,7 @@  int main(int argc, char *argv[])
         }
     }
 
-    printf("KernBase = 0x%16lx, signature is \'%.2s\'\n", KernBase,
+    printf("KernBase = 0x%016"PRIx64", signature is \'%.2s\'\n", KernBase,
             (char *)nt_start_addr);
 
     if (pe_get_pdb_symstore_hash(KernBase, nt_start_addr, pdb_hash, &vs)) {
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
index 8fa5d71c66..0c5a6fbb9e 100644
--- a/contrib/elf2dmp/pdb.c
+++ b/contrib/elf2dmp/pdb.c
@@ -18,6 +18,8 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <inttypes.h>
+
 #include "qemu/osdep.h"
 #include "pdb.h"
 #include "err.h"
@@ -66,7 +68,7 @@  uint64_t pdb_find_public_v3_symbol(struct pdb_reader *r, const char *name)
             uint32_t sect_rva = segment->dword[1];
             uint64_t rva = sect_rva + sym->public_v3.offset;
 
-            printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09lx\n", name,
+            printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09"PRIx64"\n", name,
                     sect_rva, sym->public_v3.segment,
                     ((char *)segment - 8), sym->public_v3.offset, rva);
             return rva;
diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h
index 21c0a0e833..fe189f0ecc 100644
--- a/contrib/elf2dmp/pdb.h
+++ b/contrib/elf2dmp/pdb.h
@@ -13,12 +13,14 @@ 
 
 #include "file_map.h"
 
+#ifndef _WIN64
 typedef struct GUID {
     unsigned int Data1;
     unsigned short Data2;
     unsigned short Data3;
     unsigned char Data4[8];
 } GUID;
+#endif
 
 struct PDB_FILE {
     uint32_t size;
diff --git a/contrib/elf2dmp/pe.h b/contrib/elf2dmp/pe.h
index 374e06a9c5..7b60849713 100644
--- a/contrib/elf2dmp/pe.h
+++ b/contrib/elf2dmp/pe.h
@@ -10,6 +10,7 @@ 
 
 #include <stdint.h>
 
+#ifndef _WIN64
 typedef struct IMAGE_DOS_HEADER {
     uint16_t  e_magic;      /* 0x00: MZ Header signature */
     uint16_t  e_cblp;       /* 0x02: Bytes on last page of file */
@@ -88,8 +89,6 @@  typedef struct IMAGE_NT_HEADERS64 {
   IMAGE_OPTIONAL_HEADER64 OptionalHeader;
 } __attribute__ ((packed)) IMAGE_NT_HEADERS64;
 
-#define IMAGE_FILE_DEBUG_DIRECTORY  6
-
 typedef struct IMAGE_DEBUG_DIRECTORY {
   uint32_t Characteristics;
   uint32_t TimeDateStamp;
@@ -102,6 +101,9 @@  typedef struct IMAGE_DEBUG_DIRECTORY {
 } __attribute__ ((packed)) IMAGE_DEBUG_DIRECTORY;
 
 #define IMAGE_DEBUG_TYPE_CODEVIEW   2
+#endif
+
+#define IMAGE_FILE_DEBUG_DIRECTORY  6
 
 typedef struct guid_t {
     uint32_t a;