This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

--build-id use of elf_obj_tdata


This started life as a simple change to bfd_alloc struct build_id_info
in gld${EMULATION_NAME}_after_open so as to free the memory on closing
the output bfd.  It grew a little..

What I'm doing here as well is tidying the build_id usage of
elf_obj_tdata, a struct added to all ELF BFDs.  In particular,
elf_obj_tdata now doesn't contain fields used by the build_id code
only for the linker output BFD.  Fields used only by the linker output
BFD are a problem since they increase memory for input BFDs, of which
there may be many.  Not that the build_id code is particularly bad in
this respect, it just happened to be where I was looking.

Since this touches gdb, is that part OK to apply?

include/
	* bfdlink.h (struct bfd_link_info): Delete emit_note_gnu_build_id.
bfd/
	* configure.in: Bump version to 2.23.52.
	* elf-bfd.h (struct elf_build_id_info): New.
	(struct elf_obj_tdata): Delete after_write_object_contents,
	after_write_object_contents_info and build_id_size.  Make build_id
	a pointer to struct elf_build_id_info.
	* elf.c (_bfd_elf_write_object_contents): Style.  Update
	after_write_ibject_contents invocation.
	(elfobj_grok_gnu_build_id): Update for new build_id struct.  Don't
	allow zero size notes.
	* configure: Regenerate.
gdb/
	* elfread.c (struct build_id): Delete.  Use struct elf_build_id
	throughout file instead.
	(build_id_bfd_get): Update to use new elf_tdata build_id field.
	Don't xmalloc return value.
	(build_id_verify): Similarly.  Don't xfree.
	(build_id_to_debug_filename): Update.
	(find_separate_debug_file_by_buildid): Update, don't xfree.
ld/
	* emultempl/elf32.em (emit_note_gnu_build_id): New static var.
	Replace all info->emit_note_gnu_build_id refs.
	(id_note_section_size): Rename from
	gld${EMULATION_NAME}_id_note_section_size.
	(struct build_id_info): Delete.
	(write_build_id): Rename from
	gld${EMULATION_NAME}_write_build_id_section.
	Update elf_tdata usage.  Style, formatting.
	(setup_build_id): New function.
	(gld${EMULATION_NAME}_after_open): Use setup_build_id.

Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.98
diff -u -p -r1.98 bfdlink.h
--- include/bfdlink.h	24 Oct 2012 11:09:28 -0000	1.98
+++ include/bfdlink.h	12 Feb 2013 03:23:12 -0000
@@ -469,9 +469,6 @@ struct bfd_link_info
   bfd *input_bfds;
   bfd **input_bfds_tail;
 
-  /* Non-NULL if .note.gnu.build-id section should be created.  */
-  char *emit_note_gnu_build_id;
-
   /* If a symbol should be created for each input BFD, this is section
      where those symbols should be placed.  It must be a section in
      the output BFD.  It may be NULL, in which case no such symbols
Index: bfd/configure.in
===================================================================
RCS file: /cvs/src/src/bfd/configure.in,v
retrieving revision 1.328
diff -u -p -r1.328 configure.in
--- bfd/configure.in	6 Feb 2013 23:22:08 -0000	1.328
+++ bfd/configure.in	12 Feb 2013 03:23:09 -0000
@@ -18,7 +18,7 @@ dnl <http://www.gnu.org/licenses/>.
 dnl
 
 AC_PREREQ(2.59)
-AC_INIT([bfd], [2.23.51])
+AC_INIT([bfd], [2.23.52])
 AC_CONFIG_SRCDIR([libbfd.c])
 
 AC_CANONICAL_TARGET
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.359
diff -u -p -r1.359 elf-bfd.h
--- bfd/elf-bfd.h	11 Feb 2013 05:30:53 -0000	1.359
+++ bfd/elf-bfd.h	12 Feb 2013 03:23:09 -0000
@@ -1512,6 +1512,28 @@ struct sdt_note
   bfd_byte data[1];
 };
 
+/* NT_GNU_BUILD_ID note type info.  */
+struct elf_build_id_info
+{
+  union
+  {
+    /* Used on output bfd by linker.  */
+    struct elf_build_id_out
+    {
+      size_t zero;       /* Always zero */
+      bfd_boolean (*after_write_object_contents) (bfd *);
+      const char *style;
+      asection *sec;
+    } o;
+    /* Used for input bfd.  */
+    struct elf_build_id
+    {
+      size_t size;       /* Always non-zero */
+      bfd_byte data[1];
+    } i;
+  } u;
+};
+
 /* Some private data is stashed away for future use using the tdata pointer
    in the bfd structure.  */
 
@@ -1664,13 +1686,8 @@ struct elf_obj_tdata
   obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES];
   obj_attribute_list *other_obj_attributes[2];
 
-  /* Called at the end of _bfd_elf_write_object_contents if not NULL.  */
-  bfd_boolean (*after_write_object_contents) (bfd *);
-  void *after_write_object_contents_info;
-
   /* NT_GNU_BUILD_ID note type.  */
-  bfd_size_type build_id_size;
-  bfd_byte *build_id;
+  struct elf_build_id_info *build_id;
 
   /* Linked-list containing information about every Systemtap section
      found in the object file.  Each section corresponds to one entry
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.584
diff -u -p -r1.584 elf.c
--- bfd/elf.c	8 Feb 2013 07:04:50 -0000	1.584
+++ bfd/elf.c	12 Feb 2013 03:23:10 -0000
@@ -5292,6 +5292,7 @@ _bfd_elf_write_object_contents (bfd *abf
   Elf_Internal_Shdr **i_shdrp;
   bfd_boolean failed;
   unsigned int count, num_sec;
+  struct elf_obj_tdata *t;
 
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
@@ -5323,21 +5324,22 @@ _bfd_elf_write_object_contents (bfd *abf
     }
 
   /* Write out the section header names.  */
+  t = elf_tdata (abfd);
   if (elf_shstrtab (abfd) != NULL
-      && (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
+      && (bfd_seek (abfd, t->shstrtab_hdr.sh_offset, SEEK_SET) != 0
 	  || !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))))
     return FALSE;
 
   if (bed->elf_backend_final_write_processing)
-    (*bed->elf_backend_final_write_processing) (abfd,
-						elf_tdata (abfd)->linker);
+    (*bed->elf_backend_final_write_processing) (abfd, t->linker);
 
   if (!bed->s->write_shdrs_and_ehdr (abfd))
     return FALSE;
 
   /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0].  */
-  if (elf_tdata (abfd)->after_write_object_contents)
-    return (*elf_tdata (abfd)->after_write_object_contents) (abfd);
+  if (t->build_id != NULL
+      && t->build_id->u.o.zero == 0)
+    return (*t->build_id->u.o.after_write_object_contents) (abfd);
 
   return TRUE;
 }
@@ -8692,12 +8694,18 @@ elfcore_grok_note (bfd *abfd, Elf_Intern
 static bfd_boolean
 elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
 {
-  elf_tdata (abfd)->build_id_size = note->descsz;
-  elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz);
-  if (elf_tdata (abfd)->build_id == NULL)
+  struct elf_obj_tdata *t;
+
+  if (note->descsz == 0)
+    return FALSE;
+
+  t = elf_tdata (abfd);
+  t->build_id = bfd_alloc (abfd, sizeof (t->build_id->u.i) - 1 + note->descsz);
+  if (t->build_id == NULL)
     return FALSE;
 
-  memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz);
+  t->build_id->u.i.size = note->descsz;
+  memcpy (t->build_id->u.i.data, note->descdata, note->descsz);
 
   return TRUE;
 }
Index: gdb/elfread.c
===================================================================
RCS file: /cvs/src/src/gdb/elfread.c,v
retrieving revision 1.143
diff -u -p -r1.143 elfread.c
--- gdb/elfread.c	1 Feb 2013 19:39:03 -0000	1.143
+++ gdb/elfread.c	12 Feb 2013 03:23:11 -0000
@@ -1074,38 +1074,27 @@ elf_gnu_ifunc_resolver_return_stop (stru
   update_breakpoint_locations (b, sals, sals_end);
 }
 
-struct build_id
-  {
-    size_t size;
-    gdb_byte data[1];
-  };
-
 /* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
 
-static struct build_id *
+static struct elf_build_id *
 build_id_bfd_get (bfd *abfd)
 {
-  struct build_id *retval;
-
   if (!bfd_check_format (abfd, bfd_object)
       || bfd_get_flavour (abfd) != bfd_target_elf_flavour
-      || elf_tdata (abfd)->build_id == NULL)
+      || elf_tdata (abfd)->build_id == NULL
+      || elf_tdata (abfd)->build_id->u.i.size == 0)
     return NULL;
 
-  retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size);
-  retval->size = elf_tdata (abfd)->build_id_size;
-  memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size);
-
-  return retval;
+  return &elf_tdata (abfd)->build_id->u.i;
 }
 
 /* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value.  */
 
 static int
-build_id_verify (const char *filename, struct build_id *check)
+build_id_verify (const char *filename, struct elf_build_id *check)
 {
   bfd *abfd;
-  struct build_id *found = NULL;
+  struct elf_build_id *found;
   int retval = 0;
 
   /* We expect to be silent on the non-existing files.  */
@@ -1126,13 +1115,11 @@ build_id_verify (const char *filename, s
 
   gdb_bfd_unref (abfd);
 
-  xfree (found);
-
   return retval;
 }
 
 static char *
-build_id_to_debug_filename (struct build_id *build_id)
+build_id_to_debug_filename (struct elf_build_id *build_id)
 {
   char *link, *debugdir, *retval = NULL;
   VEC (char_ptr) *debugdir_vec;
@@ -1191,7 +1178,7 @@ build_id_to_debug_filename (struct build
 static char *
 find_separate_debug_file_by_buildid (struct objfile *objfile)
 {
-  struct build_id *build_id;
+  struct elf_build_id *build_id;
 
   build_id = build_id_bfd_get (objfile->obfd);
   if (build_id != NULL)
@@ -1199,7 +1186,6 @@ find_separate_debug_file_by_buildid (str
       char *build_id_name;
 
       build_id_name = build_id_to_debug_filename (build_id);
-      xfree (build_id);
       /* Prevent looping on a stripped .debug file.  */
       if (build_id_name != NULL
 	  && filename_cmp (build_id_name, objfile->name) == 0)
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.239
diff -u -p -r1.239 elf32.em
--- ld/emultempl/elf32.em	5 Feb 2013 21:47:32 -0000	1.239
+++ ld/emultempl/elf32.em	12 Feb 2013 05:30:54 -0000
@@ -165,6 +165,9 @@ static bfd_boolean global_vercheck_faile
 static char *audit; /* colon (typically) separated list of libs */
 static char *depaudit; /* colon (typically) separated list of libs */
 
+/* Style of .note.gnu.build-id section.  */
+static const char *emit_note_gnu_build_id;
+
 /* On Linux, it's possible to have different versions of the same
    shared library linked against different versions of libc.  The
    dynamic linker somehow tags which libc version to use in
@@ -890,10 +893,9 @@ if test x"$LDEMUL_AFTER_OPEN" != xgld"$E
 fragment <<EOF
 
 static bfd_size_type
-gld${EMULATION_NAME}_id_note_section_size (bfd *abfd,
-					   struct bfd_link_info *linfo)
+id_note_section_size (bfd *abfd)
 {
-  const char *style = linfo->emit_note_gnu_build_id;
+  const char *style = emit_note_gnu_build_id;
   bfd_size_type size;
 
   abfd = abfd;
@@ -944,25 +946,22 @@ read_hex (const char xdigit)
   return 0;
 }
 
-struct build_id_info
-{
-  const char *style;
-  asection *sec;
-};
-
 static bfd_boolean
-gld${EMULATION_NAME}_write_build_id_section (bfd *abfd)
+write_build_id (bfd *abfd)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  struct build_id_info *info = (struct build_id_info *)
-    elf_tdata (abfd)->after_write_object_contents_info;
+  struct elf_obj_tdata *t = elf_tdata (abfd);
+  const char *style;
   asection *asec;
   Elf_Internal_Shdr *i_shdr;
   unsigned char *contents, *id_bits;
   bfd_size_type size;
+  file_ptr position;
   Elf_External_Note *e_note;
+  typedef void (*sum_fn) (const void *, size_t, void *);
 
-  asec = info->sec;
+  style = t->build_id->u.o.style;
+  asec = t->build_id->u.o.sec;
   if (bfd_is_abs_section (asec->output_section))
     {
       einfo (_("%P: warning: .note.gnu.build-id section discarded,"
@@ -991,31 +990,25 @@ gld${EMULATION_NAME}_write_build_id_sect
   bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
   memcpy (e_note->name, "GNU", sizeof "GNU");
 
-  if (!strcmp (info->style, "md5"))
+  if (strcmp (style, "md5") == 0)
     {
       struct md5_ctx ctx;
+
       md5_init_ctx (&ctx);
-      if (bed->s->checksum_contents (abfd,
-				     (void (*) (const void *, size_t, void *))
-				     &md5_process_bytes,
-				     &ctx))
-	md5_finish_ctx (&ctx, id_bits);
-      else
+      if (!bed->s->checksum_contents (abfd, (sum_fn) &md5_process_bytes, &ctx))
 	return FALSE;
+      md5_finish_ctx (&ctx, id_bits);
     }
-  else if (!strcmp (info->style, "sha1"))
+  else if (strcmp (style, "sha1") == 0)
     {
       struct sha1_ctx ctx;
+
       sha1_init_ctx (&ctx);
-      if (bed->s->checksum_contents (abfd,
-				     (void (*) (const void *, size_t, void *))
-				     &sha1_process_bytes,
-				     &ctx))
-	sha1_finish_ctx (&ctx, id_bits);
-      else
+      if (!bed->s->checksum_contents (abfd, (sum_fn) &sha1_process_bytes, &ctx))
 	return FALSE;
+      sha1_finish_ctx (&ctx, id_bits);
     }
-  else if (!strcmp (info->style, "uuid"))
+  else if (strcmp (style, "uuid") == 0)
     {
       int n;
       int fd = open ("/dev/urandom", O_RDONLY);
@@ -1026,10 +1019,10 @@ gld${EMULATION_NAME}_write_build_id_sect
       if (n < (int) size)
 	return FALSE;
     }
-  else if (!strncmp (info->style, "0x", 2))
+  else if (strncmp (style, "0x", 2) == 0)
     {
       /* ID is in string form (hex).  Convert to bits.  */
-      const char *id = info->style + 2;
+      const char *id = style + 2;
       size_t n = 0;
       do
 	{
@@ -1047,12 +1040,51 @@ gld${EMULATION_NAME}_write_build_id_sect
   else
     abort ();			/* Should have been validated earlier.  */
 
+  position = i_shdr->sh_offset + asec->output_offset;
   size = asec->size;
-  return (bfd_seek (abfd,
-		    i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0
+  return (bfd_seek (abfd, position, SEEK_SET) == 0
 	  && bfd_bwrite (contents, size, abfd) == size);
 }
 
+/* Make .note.gnu.build-id section, and set up elf_tdata->build_id.  */
+
+static bfd_boolean
+setup_build_id (bfd *ibfd)
+{
+  asection *s;
+  bfd_size_type size;
+  flagword flags;
+
+  size = id_note_section_size (ibfd);
+  if (size == 0)
+    {
+      einfo ("%P: warning: unrecognized --build-id style ignored.\n");
+      return FALSE;
+    }
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
+	   | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA);
+  s = bfd_make_section_with_flags (ibfd, ".note.gnu.build-id", flags);
+  if (s != NULL && bfd_set_section_alignment (ibfd, s, 2))
+    {
+      struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
+      t->build_id = bfd_alloc (link_info.output_bfd, sizeof (t->build_id->u.o));
+      if (t->build_id != NULL)
+	{
+	  t->build_id->u.o.zero = 0;
+	  t->build_id->u.o.after_write_object_contents = &write_build_id;
+	  t->build_id->u.o.style = emit_note_gnu_build_id;
+	  t->build_id->u.o.sec = s;
+	  elf_section_type (s) = SHT_NOTE;
+	  s->size = size;
+	  return TRUE;
+	}
+    }
+
+  einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
+	 " --build-id ignored.\n");
+  return FALSE;
+}
 
 /* This is called after all the input files have been opened.  */
 
@@ -1068,11 +1101,9 @@ gld${EMULATION_NAME}_after_open (void)
   if (!is_elf_hash_table (htab))
     return;
 
-  if (link_info.emit_note_gnu_build_id)
+  if (emit_note_gnu_build_id != NULL)
     {
       bfd *abfd;
-      asection *s;
-      bfd_size_type size;
 
       /* Find an ELF input.  */
       for (abfd = link_info.input_bfds;
@@ -1080,50 +1111,13 @@ gld${EMULATION_NAME}_after_open (void)
 	if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
 	  break;
 
-      if (abfd == NULL)
-	{
-	  /* PR 10555: If there are no input files do not
-	     try to create a .note.gnu-build-id section.  */
-	  free (link_info.emit_note_gnu_build_id);
-	  link_info.emit_note_gnu_build_id = NULL;
-	}
-      else
+      /* PR 10555: If there are no ELF input files do not try to
+	 create a .note.gnu-build-id section.  */
+      if (abfd == NULL
+	  || !setup_build_id (abfd))
 	{
-	  size = gld${EMULATION_NAME}_id_note_section_size (abfd, &link_info);
-	  if (size == 0)
-	    {
-	      einfo ("%P: warning: unrecognized --build-id style ignored.\n");
-	      free (link_info.emit_note_gnu_build_id);
-	      link_info.emit_note_gnu_build_id = NULL;
-	    }
-	  else
-	    {
-	      s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id",
-					       SEC_ALLOC | SEC_LOAD
-					       | SEC_IN_MEMORY | SEC_LINKER_CREATED
-					       | SEC_READONLY | SEC_DATA);
-	      if (s != NULL && bfd_set_section_alignment (abfd, s, 2))
-		{
-		  struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
-		  struct build_id_info *b =
-		      (struct build_id_info *) xmalloc (sizeof *b);
-
-		  b->style = link_info.emit_note_gnu_build_id;
-		  b->sec = s;
-		  elf_section_type (s) = SHT_NOTE;
-		  s->size = size;
-		  t->after_write_object_contents
-		    = &gld${EMULATION_NAME}_write_build_id_section;
-		  t->after_write_object_contents_info = b;
-		}
-	      else
-		{
-		  einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
-			 " --build-id ignored.\n");
-		  free (link_info.emit_note_gnu_build_id);
-		  link_info.emit_note_gnu_build_id = NULL;
-		}
-	    }
+	  free ((char *) emit_note_gnu_build_id);
+	  emit_note_gnu_build_id = NULL;
 	}
     }
 
@@ -2192,15 +2186,15 @@ gld${EMULATION_NAME}_handle_option (int 
       return FALSE;
 
     case OPTION_BUILD_ID:
-      if (link_info.emit_note_gnu_build_id != NULL)
+      if (emit_note_gnu_build_id != NULL)
 	{
-	  free (link_info.emit_note_gnu_build_id);
-	  link_info.emit_note_gnu_build_id = NULL;
+	  free ((char *) emit_note_gnu_build_id);
+	  emit_note_gnu_build_id = NULL;
 	}
       if (optarg == NULL)
 	optarg = DEFAULT_BUILD_ID_STYLE;
       if (strcmp (optarg, "none"))
-	link_info.emit_note_gnu_build_id = xstrdup (optarg);
+	emit_note_gnu_build_id = xstrdup (optarg);
       break;
 
 EOF

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]