--build-id use of elf_obj_tdata
Alan Modra
amodra@gmail.com
Mon Feb 18 00:19:00 GMT 2013
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
More information about the Binutils
mailing list