Update year range in copyright notice of all files.
[deliverable/binutils-gdb.git] / bfd / peicode.h
index e36568aa2070ab5fa5282c0ddcf19f934d039a2e..2dffb12072b60adb3a4b4005743462b922a8a236 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for the generic parts of PE/PEI, for BFD.
-   Copyright (C) 1995-2015 Free Software Foundation, Inc.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
    Written by Cygnus Solutions.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -631,6 +631,20 @@ pe_ILF_make_a_section (pe_ILF_vars * vars,
   if (size & 1)
     vars->data --;
 
+# if (GCC_VERSION >= 3000)
+  /* PR 18758: See note in pe_ILF_buid_a_bfd.  We must make sure that we
+     preserve host alignment requirements.  We test 'size' rather than
+     vars.data as we cannot perform binary arithmetic on pointers.  We assume
+     that vars.data was sufficiently aligned upon entry to this function.
+     The BFD_ASSERTs in this functions will warn us if we run out of room,
+     but we should already have enough padding built in to ILF_DATA_SIZE.  */
+  {
+    unsigned int alignment = __alignof__ (struct coff_section_tdata);
+
+    if (size & (alignment - 1))
+      vars->data += alignment - (size & (alignment - 1));
+  }
+#endif
   /* Create a coff_section_tdata structure for our use.  */
   sec->used_by_bfd = (struct coff_section_tdata *) vars->data;
   vars->data += sizeof (struct coff_section_tdata);
@@ -757,11 +771,13 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
     case IMPORT_CONST:
       /* XXX code yet to be written.  */
+      /* xgettext:c-format */
       _bfd_error_handler (_("%B: Unhandled import type; %x"),
                          abfd, import_type);
       return FALSE;
 
     default:
+      /* xgettext:c-format */
       _bfd_error_handler (_("%B: Unrecognised import type; %x"),
                          abfd, import_type);
       return FALSE;
@@ -776,6 +792,7 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       break;
 
     default:
+      /* xgettext:c-format */
       _bfd_error_handler (_("%B: Unrecognised import name type; %x"),
                          abfd, import_name_type);
       return FALSE;
@@ -836,6 +853,24 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
   /* The remaining space in bim->buffer is used
      by the pe_ILF_make_a_section() function.  */
+# if (GCC_VERSION >= 3000)
+  /* PR 18758: Make sure that the data area is sufficiently aligned for
+     pointers on the host.  __alignof__ is a gcc extension, hence the test
+     above.  For other compilers we will have to assume that the alignment is
+     unimportant, or else extra code can be added here and in
+     pe_ILF_make_a_section.
+
+     Note - we cannot test 'ptr' directly as it is illegal to perform binary
+     arithmetic on pointers, but we know that the strings section is the only
+     one that might end on an unaligned boundary.  */
+  {
+    unsigned int alignment = __alignof__ (char *);
+
+    if (SIZEOF_ILF_STRINGS & (alignment - 1))
+      ptr += alignment - (SIZEOF_ILF_STRINGS & (alignment - 1));
+  }
+#endif
+
   vars.data = ptr;
   vars.abfd = abfd;
   vars.sec_index = 0;
@@ -857,8 +892,8 @@ pe_ILF_build_a_bfd (bfd *           abfd,
   if (import_name_type == IMPORT_ORDINAL)
     {
       if (ordinal == 0)
-       /* XXX - treat as IMPORT_NAME ??? */
-       abort ();
+       /* See PR 20907 for a reproducer.  */
+       goto error_return;
 
 #ifdef COFF_WITH_pex64
       ((unsigned int *) id4->contents)[0] = ordinal;
@@ -927,13 +962,19 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       pe_ILF_save_relocs (&vars, id5);
     }
 
+  /* Create an import symbol.  */
+  pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
+  imp_sym   = vars.sym_ptr_ptr - 1;
+  imp_index = vars.sym_index - 1;
+
   /* Create extra sections depending upon the type of import we are dealing with.  */
   switch (import_type)
     {
       int i;
 
     case IMPORT_CODE:
-      /* Create a .text section.
+      /* CODE functions are special, in that they get a trampoline that
+         jumps to the main import symbol.  Create a .text section to hold it.
         First we need to look up its contents in the jump table.  */
       for (i = NUM_ENTRIES (jtab); i--;)
        {
@@ -954,11 +995,6 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       /* Copy in the jump code.  */
       memcpy (text->contents, jtab[i].data, jtab[i].size);
 
-      /* Create an import symbol.  */
-      pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
-      imp_sym   = vars.sym_ptr_ptr - 1;
-      imp_index = vars.sym_index - 1;
-
       /* Create a reloc for the data in the text section.  */
 #ifdef MIPS_ARCH_MAGIC_WINCE
       if (magic == MIPS_ARCH_MAGIC_WINCE)
@@ -972,6 +1008,15 @@ pe_ILF_build_a_bfd (bfd *           abfd,
                                      imp_index);
        }
       else
+#endif
+#ifdef AMD64MAGIC
+      if (magic == AMD64MAGIC)
+       {
+         pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
+                                     BFD_RELOC_32_PCREL, (asymbol **) imp_sym,
+                                     imp_index);
+       }
+      else
 #endif
        pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
                                    BFD_RELOC_32, (asymbol **) imp_sym,
@@ -1027,14 +1072,6 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       pe_ILF_make_a_symbol (& vars, "", symbol_name, text,
                            BSF_NOT_AT_END | BSF_FUNCTION);
 
-      /* Create an import symbol for the DLL, without the
-       .dll suffix.  */
-      ptr = (bfd_byte *) strrchr (source_dll, '.');
-      if (ptr)
-       * ptr = 0;
-      pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
-      if (ptr)
-       * ptr = '.';
       break;
 
     case IMPORT_DATA:
@@ -1046,6 +1083,14 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       abort ();
     }
 
+  /* Create an import symbol for the DLL, without the .dll suffix.  */
+  ptr = (bfd_byte *) strrchr (source_dll, '.');
+  if (ptr)
+    * ptr = 0;
+  pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
+  if (ptr)
+    * ptr = '.';
+
   /* Point the bfd at the symbol table.  */
   obj_symbols (abfd) = vars.sym_cache;
   bfd_get_symcount (abfd) = vars.sym_index;
@@ -1168,6 +1213,7 @@ pe_ILF_object_p (bfd * abfd)
       /* We no longer support PowerPC.  */
     default:
       _bfd_error_handler
+       /* xgettext:c-format */
        (_("%B: Unrecognised machine type (0x%x)"
           " in Import Library Format archive"),
         abfd, machine);
@@ -1180,6 +1226,7 @@ pe_ILF_object_p (bfd * abfd)
   if (magic == 0)
     {
       _bfd_error_handler
+       /* xgettext:c-format */
        (_("%B: Recognised but unhandled machine type (0x%x)"
           " in Import Library Format archive"),
         abfd, machine);
@@ -1222,7 +1269,8 @@ pe_ILF_object_p (bfd * abfd)
     }
 
   symbol_name = (char *) ptr;
-  source_dll  = symbol_name + strlen (symbol_name) + 1;
+  /* See PR 20905 for an example of where the strnlen is necessary.  */
+  source_dll  = symbol_name + strnlen (symbol_name, size - 1) + 1;
 
   /* Verify that the strings are null terminated.  */
   if (ptr[size - 1] != 0
@@ -1246,6 +1294,92 @@ pe_ILF_object_p (bfd * abfd)
   return abfd->xvec;
 }
 
+static void
+pe_bfd_read_buildid (bfd *abfd)
+{
+  pe_data_type *pe = pe_data (abfd);
+  struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+  asection *section;
+  bfd_byte *data = 0;
+  bfd_size_type dataoff;
+  unsigned int i;
+
+  bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
+  bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
+
+  if (size == 0)
+    return;
+
+  addr += extra->ImageBase;
+
+  /* Search for the section containing the DebugDirectory.  */
+  for (section = abfd->sections; section != NULL; section = section->next)
+    {
+      if ((addr >= section->vma) && (addr < (section->vma + section->size)))
+        break;
+    }
+
+  if (section == NULL)
+    return;
+
+  if (!(section->flags & SEC_HAS_CONTENTS))
+    return;
+
+  dataoff = addr - section->vma;
+
+  /* PR 20605: Make sure that the data is really there.  */
+  if (dataoff + size > section->size)
+    {
+      _bfd_error_handler (_("%B: Error: Debug Data ends beyond end of debug directory."),
+                         abfd);
+      return;
+    }
+  
+  /* Read the whole section. */
+  if (!bfd_malloc_and_get_section (abfd, section, &data))
+    {
+      if (data != NULL)
+       free (data);
+      return;
+    }
+
+  /* Search for a CodeView entry in the DebugDirectory */
+  for (i = 0; i < size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
+    {
+      struct external_IMAGE_DEBUG_DIRECTORY *ext
+       = &((struct external_IMAGE_DEBUG_DIRECTORY *)(data + dataoff))[i];
+      struct internal_IMAGE_DEBUG_DIRECTORY idd;
+
+      _bfd_XXi_swap_debugdir_in (abfd, ext, &idd);
+
+      if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW)
+        {
+          char buffer[256 + 1];
+          CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
+
+          /*
+            The debug entry doesn't have to have to be in a section, in which
+            case AddressOfRawData is 0, so always use PointerToRawData.
+          */
+          if (_bfd_XXi_slurp_codeview_record (abfd,
+                                              (file_ptr) idd.PointerToRawData,
+                                              idd.SizeOfData, cvinfo))
+            {
+              struct bfd_build_id* build_id = bfd_alloc (abfd,
+                         sizeof (struct bfd_build_id) + cvinfo->SignatureLength);
+              if (build_id)
+                {
+                  build_id->size = cvinfo->SignatureLength;
+                  memcpy(build_id->data,  cvinfo->Signature,
+                         cvinfo->SignatureLength);
+                  abfd->build_id = build_id;
+                }
+            }
+          break;
+        }
+    }
+}
+
 static const bfd_target *
 pe_bfd_object_p (bfd * abfd)
 {
@@ -1256,6 +1390,7 @@ pe_bfd_object_p (bfd * abfd)
   struct internal_aouthdr internal_a;
   file_ptr opt_hdr_size;
   file_ptr offset;
+  const bfd_target *result;
 
   /* Detect if this a Microsoft Import Library Format element.  */
   /* First read the beginning of the header.  */
@@ -1349,10 +1484,20 @@ pe_bfd_object_p (bfd * abfd)
        return NULL;
     }
 
-  return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
-                            (opt_hdr_size != 0
-                             ? &internal_a
-                             : (struct internal_aouthdr *) NULL));
+
+  result = coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
+                               (opt_hdr_size != 0
+                                ? &internal_a
+                                : (struct internal_aouthdr *) NULL));
+
+
+  if (result)
+    {
+      /* Now the whole header has been processed, see if there is a build-id */
+      pe_bfd_read_buildid(abfd);
+    }
+
+  return result;
 }
 
 #define coff_object_p pe_bfd_object_p
This page took 0.059103 seconds and 4 git commands to generate.