gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / libiberty / simple-object.c
index c9bd82f271416b5bf270fd31bddded4a9f9d8cf8..92f5698d0a6490bc1364812af61c1a402523eab9 100644 (file)
@@ -1,5 +1,5 @@
 /* simple-object.c -- simple routines to read and write object files.
-   Copyright 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 This program is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA.  */
 #include "simple-object.h"
 
 #include <errno.h>
+#include <fcntl.h>
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -43,6 +44,10 @@ Boston, MA 02110-1301, USA.  */
 #define SEEK_SET 0
 #endif
 
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
 #include "simple-object-common.h"
 
 /* The known object file formats.  */
@@ -51,7 +56,8 @@ static const struct simple_object_functions * const format_functions[] =
 {
   &simple_object_elf_functions,
   &simple_object_mach_o_functions,
-  &simple_object_coff_functions
+  &simple_object_coff_functions,
+  &simple_object_xcoff_functions
 };
 
 /* Read data from a file using the simple_object error reporting
@@ -62,8 +68,6 @@ simple_object_internal_read (int descriptor, off_t offset,
                             unsigned char *buffer, size_t size,
                             const char **errmsg, int *err)
 {
-  ssize_t got;
-
   if (lseek (descriptor, offset, SEEK_SET) < 0)
     {
       *errmsg = "lseek";
@@ -71,15 +75,26 @@ simple_object_internal_read (int descriptor, off_t offset,
       return 0;
     }
 
-  got = read (descriptor, buffer, size);
-  if (got < 0)
+  do
     {
-      *errmsg = "read";
-      *err = errno;
-      return 0;
+      ssize_t got = read (descriptor, buffer, size);
+      if (got == 0)
+       break;
+      else if (got > 0)
+       {
+         buffer += got;
+         size -= got;
+       }
+      else if (errno != EINTR)
+       {
+         *errmsg = "read";
+         *err = errno;
+         return 0;
+       }
     }
+  while (size > 0);
 
-  if ((size_t) got < size)
+  if (size > 0)
     {
       *errmsg = "file too short";
       *err = 0;
@@ -97,8 +112,6 @@ simple_object_internal_write (int descriptor, off_t offset,
                              const unsigned char *buffer, size_t size,
                              const char **errmsg, int *err)
 {
-  ssize_t wrote;
-
   if (lseek (descriptor, offset, SEEK_SET) < 0)
     {
       *errmsg = "lseek";
@@ -106,15 +119,26 @@ simple_object_internal_write (int descriptor, off_t offset,
       return 0;
     }
 
-  wrote = write (descriptor, buffer, size);
-  if (wrote < 0)
+  do
     {
-      *errmsg = "write";
-      *err = errno;
-      return 0;
+      ssize_t wrote = write (descriptor, buffer, size);
+      if (wrote == 0)
+       break;
+      else if (wrote > 0)
+       {
+         buffer += wrote;
+         size -= wrote;
+       }
+      else if (errno != EINTR)
+       {
+         *errmsg = "write";
+         *err = errno;
+         return 0;
+       }
     }
+  while (size > 0);
 
-  if ((size_t) wrote < size)
+  if (size > 0)
     {
       *errmsg = "short write";
       *err = 0;
@@ -230,6 +254,131 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
   return 1;
 }
 
+/* Callback to identify and rename LTO debug sections by name.
+   Returns non-NULL if NAME is a LTO debug section, NULL if not.
+   If RENAME is true it will rename LTO debug sections to non-LTO
+   ones.  */
+
+static char *
+handle_lto_debug_sections (const char *name, int rename)
+{
+  char *newname = rename ? XCNEWVEC (char, strlen (name) + 1)
+                        : xstrdup (name);
+
+  /* ???  So we can't use .gnu.lto_ prefixed sections as the assembler
+     complains about bogus section flags.  Which means we need to arrange
+     for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
+     fat lto object tooling work for the fat part).  */
+  /* Also include corresponding reloc sections.  */
+  if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
+    {
+      if (rename)
+        strncpy (newname, name, sizeof (".rela") - 1);
+      name += sizeof (".rela") - 1;
+    }
+  else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
+    {
+      if (rename)
+        strncpy (newname, name, sizeof (".rel") - 1);
+      name += sizeof (".rel") - 1;
+    }
+  /* ???  For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
+     sections.  */
+  /* Copy LTO debug sections and rename them to their non-LTO name.  */
+  if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
+    return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname;
+  else if (strncmp (name, ".gnu.lto_.debug_",
+                   sizeof (".gnu.lto_.debug_") -1) == 0)
+    return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname;
+  /* Copy over .note.GNU-stack section under the same name if present.  */
+  else if (strcmp (name, ".note.GNU-stack") == 0)
+    return strcpy (newname, name);
+  /* Copy over .note.gnu.property section under the same name if present.  */
+  else if (strcmp (name, ".note.gnu.property") == 0)
+    return strcpy (newname, name);
+  /* Copy over .comment section under the same name if present.  Solaris
+     ld uses them to relax its checking of ELF gABI access rules for
+     COMDAT sections in objects produced by GCC.  */
+  else if (strcmp (name, ".comment") == 0)
+    return strcpy (newname, name);
+  /* Copy over .GCC.command.line section under the same name if present.  */
+  else if (strcmp (name, ".GCC.command.line") == 0)
+    return strcpy (newname, name);
+  free (newname);
+  return NULL;
+}
+
+/* Wrapper for handle_lto_debug_sections.  */
+
+static char *
+handle_lto_debug_sections_rename (const char *name)
+{
+  return handle_lto_debug_sections (name, 1);
+}
+
+/* Wrapper for handle_lto_debug_sections.  */
+
+static char *
+handle_lto_debug_sections_norename (const char *name)
+{
+  return handle_lto_debug_sections (name, 0);
+}
+
+/* Copy LTO debug sections.  */
+
+const char *
+simple_object_copy_lto_debug_sections (simple_object_read *sobj,
+                                      const char *dest, int *err, int rename)
+{
+  const char *errmsg;
+  simple_object_write *dest_sobj;
+  simple_object_attributes *attrs;
+  int outfd;
+
+  if (! sobj->functions->copy_lto_debug_sections)
+    {
+      *err = EINVAL;
+      return "simple_object_copy_lto_debug_sections not implemented";
+    }
+
+  attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
+  if (! attrs)
+    return errmsg;
+  dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
+  simple_object_release_attributes (attrs);
+  if (! dest_sobj)
+    return errmsg;
+
+  errmsg = sobj->functions->copy_lto_debug_sections
+                (sobj, dest_sobj,
+                 rename ? handle_lto_debug_sections_rename
+                        : handle_lto_debug_sections_norename,  err);
+  if (errmsg)
+    {
+      simple_object_release_write (dest_sobj);
+      return errmsg;
+    }
+
+  outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777);
+  if (outfd == -1)
+    {
+      *err = errno;
+      simple_object_release_write (dest_sobj);
+      return "open failed";
+    }
+
+  errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
+  close (outfd);
+  if (errmsg)
+    {
+      simple_object_release_write (dest_sobj);
+      return errmsg;
+    }
+
+  simple_object_release_write (dest_sobj);
+  return NULL;
+}
+
 /* Fetch attributes.  */
 
 simple_object_attributes *
@@ -257,20 +406,19 @@ simple_object_release_read (simple_object_read *sobj)
   XDELETE (sobj);
 }
 
-/* Compare attributes.  */
+/* Merge attributes.  */
 
 const char *
-simple_object_attributes_compare (simple_object_attributes *attrs1,
-                                 simple_object_attributes *attrs2,
-                                 int *err)
+simple_object_attributes_merge (simple_object_attributes *to,
+                               simple_object_attributes *from,
+                               int *err)
 {
-  if (attrs1->functions != attrs2->functions)
+  if (to->functions != from->functions)
     {
       *err = 0;
       return "different object file format";
     }
-  return attrs1->functions->attributes_compare (attrs1->data, attrs2->data,
-                                               err);
+  return to->functions->attributes_merge (to->data, from->data, err);
 }
 
 /* Release an attributes structure.  */
@@ -297,7 +445,7 @@ simple_object_start_write (simple_object_attributes *attrs,
     return NULL;
   ret = XNEW (simple_object_write);
   ret->functions = attrs->functions;
-  ret->segment_name = xstrdup (segment_name);
+  ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
   ret->sections = NULL;
   ret->last_section = NULL;
   ret->data = data;
This page took 0.026379 seconds and 4 git commands to generate.