[lto] PATCH: Locate DWARF information in ELF files
Mark Mitchell
mark@codesourcery.com
Sun Jun 18 20:47:00 GMT 2006
This patch makes the LTO front end open ELF files and locate the DWARF
sections required for building LTO information. The ELF-specific bits
are segreated into a separate file so that platforms using other
object file formats can be supported in future. We will probably also
need some autoconf bits to detect libelf; for now, we'll just assume
its available.
The next step is to begin reading the DWARF information and generating
trees.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2006-06-18 Mark Mitchell <mark@codesourcery.com>
* lto.h: New file.
* lto.c: New file.
* lto-elf.c: New file.
* lto-lang.c (flags.h): Include it.
(lto.h): Likewise.
(lto_init): New function.
(lto_write_globals): Remove.
(LANG_HOOKS_WRITE_GLOBALS): Define to lhd_do_nothing.
(LANG_HOOKS_INIT): Define.
(LANG_HOOKS_PARSE_FILE): Likewise.
* Make-lang.in (LTO_OBJS): Add lto.o and lto-elf.o.
(LTO_EXE): Link with libelf.
(lto/lto-lang.o): Update dependencies.
(lto/lto.o): New target.
(lto/lto-elf.o): Likewise.
Index: lto.c
===================================================================
--- lto.c (revision 0)
+++ lto.c (revision 0)
@@ -0,0 +1,62 @@
+/* Top-level LTO routines.
+ Copyright 2006 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "opts.h"
+#include "lto.h"
+
+void
+lto_file_init (lto_file *file, const char *filename)
+{
+ file->debug_info = NULL;
+ file->debug_info_length = 0;
+ file->debug_abbrev = NULL;
+ file->debug_abbrev_length = 0;
+ file->filename = filename;
+}
+
+bool
+lto_file_read (lto_file *file)
+{
+ return true;
+}
+
+void
+lto_main (int debug_p ATTRIBUTE_UNUSED)
+{
+ unsigned i;
+
+ /* Read all of the object files specified on the command line. */
+ for (i = 0; i < num_in_fnames; ++i)
+ {
+ lto_file *file;
+
+ file = lto_elf_file_open (in_fnames[i]);
+ if (!file)
+ break;
+ gcc_assert (file->debug_info);
+ gcc_assert (file->debug_abbrev);
+ if (!lto_file_read (file))
+ return;
+ lto_elf_file_close (file);
+ }
+}
Index: Make-lang.in
===================================================================
--- Make-lang.in (revision 114758)
+++ Make-lang.in (working copy)
@@ -26,7 +26,7 @@
# The name of the LTO compiler.
LTO_EXE = lto1$(exeext)
# The LTO-specific object files inclued in $(LTO_EXE).
-LTO_OBJS = lto/lto-lang.o
+LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-elf.o
########################################################################
# Rules
@@ -68,12 +68,15 @@ lto.stagefeedback:
$(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- $(LTO_OBJS) $(BACKEND) $(LIBS)
+ $(LTO_OBJS) $(BACKEND) $(LIBS) -lelf
########################################################################
# Dependencies
########################################################################
lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
- $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
- lto/lto-tree.h gtype-lto.h
+ flags.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
+ $(TM_H) lto/lto-tree.h lto/lto.h gtype-lto.h
+lto/lto.o: lto/lto.c $(CONFIG_H) opts.h $(SYSTEM_H) lto/lto.h
+lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H)\
+ toplev.h lto/lto.h
Index: lto-elf.c
===================================================================
--- lto-elf.c (revision 0)
+++ lto-elf.c (revision 0)
@@ -0,0 +1,253 @@
+/* LTO routines for ELF object files.
+ Copyright 2006 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "toplev.h"
+#include "lto.h"
+#include "libelf.h"
+
+/* An ELF input file. */
+struct lto_elf_file
+{
+ /* The base information. */
+ lto_file base;
+ /* The system file descriptor for the file. */
+ int fd;
+ /* The libelf descriptor for the file. */
+ Elf *elf;
+};
+typedef struct lto_elf_file lto_elf_file;
+
+lto_file *
+lto_elf_file_open (const char *filename)
+{
+ lto_elf_file *elf_file;
+ size_t bits;
+ const char *elf_ident;
+ size_t string_table_section_index;
+ Elf_Scn *string_table_section;
+ Elf_Scn *section;
+ lto_file *result;
+
+ /* Set up. */
+ elf_file = (lto_elf_file *) xmalloc (sizeof (lto_elf_file));
+ result = &elf_file->base;
+ lto_file_init (result, filename);
+ elf_file->fd = -1;
+ elf_file->elf = NULL;
+
+ /* Open the file. */
+ elf_file->fd = open (filename, O_RDONLY);
+ if (elf_file->fd == -1)
+ {
+ error ("could not open");
+ goto fail;
+ }
+
+ /* Initialize the ELF library. */
+ if (elf_version (EV_CURRENT) == EV_NONE)
+ {
+ error ("ELF library is older than that used when building GCC");
+ goto fail;
+ }
+
+ /* Open the ELF file descriptor. */
+ elf_file->elf = elf_begin (elf_file->fd, ELF_C_READ, NULL);
+ if (!elf_file->elf)
+ {
+ error ("could not open ELF file: %s", elf_errmsg (0));
+ goto fail;
+ }
+
+ /* Some aspects of the libelf API are dependent on whether the
+ object file is a 32-bit or 64-bit file. Determine which kind of
+ file this is now. */
+ elf_ident = elf_getident (elf_file->elf, NULL);
+ if (!elf_ident)
+ {
+ error ("could not read ELF identification information: %s",
+ elf_errmsg (0));
+ goto fail;
+
+ }
+ switch (elf_ident[EI_CLASS])
+ {
+ case ELFCLASS32:
+ bits = 32;
+ break;
+ case ELFCLASS64:
+ bits = 64;
+ break;
+ default:
+ error ("unsupported ELF file class");
+ goto fail;
+ }
+
+ /* Check that the input file is a relocatable object file. */
+#define ELF_CHECK_FILE_TYPE(N) \
+ do { \
+ Elf##N##_Ehdr *elf_header; \
+ elf_header = elf##N##_getehdr (elf_file->elf); \
+ if (!elf_header) \
+ { \
+ error ("could not read ELF header: %s", elf_errmsg (0)); \
+ goto fail; \
+ } \
+ if (elf_header->e_type != ET_REL) \
+ { \
+ error ("not a relocatable ELF object file"); \
+ goto fail; \
+ } \
+ } while (false)
+
+ switch (bits)
+ {
+ case 32:
+ ELF_CHECK_FILE_TYPE (32);
+ break;
+ case 64:
+ ELF_CHECK_FILE_TYPE (64);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+#undef ELF_CHECK_FILE_TYPE
+
+ /* Read the string table used for section header names. */
+ if (elf_getshstrndx (elf_file->elf, &string_table_section_index) == -1)
+ {
+ error ("could not locate ELF string table", elf_errmsg (0));
+ goto fail;
+ }
+ string_table_section = elf_getscn (elf_file->elf,
+ string_table_section_index);
+
+ /* Find the .debug_info and .debug_abbrev sections. */
+ for (section = elf_getscn (elf_file->elf, 0);
+ section;
+ section = elf_nextscn (elf_file->elf, section))
+ {
+ size_t offset;
+ const char *name;
+ const void **datap;
+ size_t *lengthp;
+ Elf_Data *data;
+
+ if (!section)
+ {
+ error ("could not read section information: %s", elf_errmsg (0));
+ goto fail;
+ }
+
+#define ELF_GET_SECTION_HEADER_NAME(N) \
+ do { \
+ Elf##N##_Shdr *section_header; \
+ section_header = elf##N##_getshdr (section); \
+ if (!section_header) \
+ { \
+ error ("could not read section header: %s", elf_errmsg (0)); \
+ goto fail; \
+ } \
+ offset = section_header->sh_name; \
+ } while (false)
+
+ switch (bits)
+ {
+ case 32:
+ ELF_GET_SECTION_HEADER_NAME(32);
+ break;
+ case 64:
+ ELF_GET_SECTION_HEADER_NAME(64);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+#undef ELF_GET_SECTION_HEADER_NAME
+
+ /* Get the name of this section. */
+ name = elf_strptr (elf_file->elf, string_table_section_index,
+ offset);
+ if (!name)
+ {
+ error ("could not read section name: %s", elf_errmsg (0));
+ goto fail;
+ }
+
+ /* Check to see if this is one of the sections of interest. */
+ if (strcmp (name, ".debug_info") == 0)
+ {
+ datap = &result->debug_info;
+ lengthp = &result->debug_info_length;
+ }
+ else if (strcmp (name, ".debug_abbrev") == 0)
+ {
+ datap = &result->debug_abbrev;
+ lengthp = &result->debug_abbrev_length;
+ }
+ else
+ continue;
+
+ /* There should not be two debugging sections with the same
+ name. */
+ if (*datap)
+ {
+ error ("duplicate %qs section", name);
+ goto fail;
+ }
+
+ /* Read the data from the section. */
+ data = elf_getdata (section, NULL);
+ if (!data)
+ {
+ error ("could not read data", elf_errmsg (0));
+ goto fail;
+ }
+ *datap = data->d_buf;
+ *lengthp = data->d_size;
+ }
+
+ if (!result->debug_info || !result->debug_abbrev)
+ {
+ error ("could not read DWARF debugging information");
+ goto fail;
+ }
+
+ return result;
+
+ fail:
+ lto_elf_file_close (result);
+ return NULL;
+}
+
+void
+lto_elf_file_close (lto_file *file)
+{
+ lto_elf_file *elf_file = (lto_elf_file *) file;
+ if (elf_file->elf)
+ elf_end (elf_file->elf);
+ if (elf_file->fd != -1)
+ close (elf_file->fd);
+ free (file);
+}
Index: lto.h
===================================================================
--- lto.h (revision 0)
+++ lto.h (revision 0)
@@ -0,0 +1,65 @@
+/* LTO declarations.
+ Copyright 2006 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef LTO_H
+#define LTO_H
+
+/* An input file. */
+typedef struct lto_file
+{
+ /* The name of the file. */
+ const char *filename;
+ /* The contents of the .debug_info section. */
+ const void *debug_info;
+ /* The number of bytes pointed to by DEBUG_INFO. */
+ size_t debug_info_length;
+ /* The contents of the .debug_abbrev section. */
+ const void *debug_abbrev;
+ /* The number of bytes pointed to by DEBUG_ABBREV. */
+ size_t debug_abbrev_length;
+} lto_file;
+
+/* lto.c */
+
+/* Read all of the input object files, generate a TREE representation
+ of the combined program, and provide that combined representation
+ to the middle end. */
+extern void lto_main (int debug_p);
+
+/* Initialize the newly allocated FILE, which corresponds to
+ FILENAME. */
+extern void lto_file_init (lto_file *file, const char *filename);
+
+/* Generate a TREE representation for all entities in FILE. If an
+ entity in FILE has already been read (from another object file),
+ merge the two entities. Returns TRUE iff FILE was successfully
+ processed. */
+extern bool lto_file_read (lto_file *file);
+
+/* lto-elf.c */
+
+/* Open the ELF input file indicated by FILENAME. Return */
+extern lto_file *lto_elf_file_open (const char *filename);
+
+/* Close an ELF input file. */
+extern void lto_elf_file_close (lto_file *file);
+
+#endif /* LTO_H */
Index: lto-lang.c
===================================================================
--- lto-lang.c (revision 114758)
+++ lto-lang.c (working copy)
@@ -22,11 +22,14 @@ Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "flags.h"
+#include "tm.h"
#include "tree.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "debug.h"
#include "lto-tree.h"
+#include "lto.h"
/* Tables of information about tree codes. */
@@ -113,12 +116,6 @@ lto_getdecls (void)
gcc_unreachable ();
}
-static void
-lto_write_globals (void)
-{
- gcc_unreachable ();
-}
-
static tree
lto_builtin_function (const char *name ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
@@ -130,6 +127,27 @@ lto_builtin_function (const char *name A
gcc_unreachable ();
}
+/* Perform LTO-specific initialization. */
+
+static bool
+lto_init (void)
+{
+ /* Create the basic integer types. */
+ build_common_tree_nodes (flag_signed_char,
+ /*signed_sizetype=*/false);
+ /* Tell the middle end what type to use for the size of objects. */
+ if (strcmp (SIZE_TYPE, "unsigned int") == 0)
+ set_sizetype (unsigned_type_node);
+ else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
+ set_sizetype (long_unsigned_type_node);
+ else
+ gcc_unreachable();
+ /* Create other basic types. */
+ build_common_tree_nodes_2 (/*short_double=*/false);
+
+ return true;
+}
+
#define LANG_HOOKS_MARK_ADDRESSABLE lto_mark_addressable
#define LANG_HOOKS_TYPE_FOR_MODE lto_type_for_mode
#define LANG_HOOKS_TYPE_FOR_SIZE lto_type_for_size
@@ -145,9 +163,13 @@ lto_builtin_function (const char *name A
#undef LANG_HOOKS_GETDECLS
#define LANG_HOOKS_GETDECLS lto_getdecls
#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS lto_write_globals
+#define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing
#undef LANG_HOOKS_BUILTIN_FUNCTION
#define LANG_HOOKS_BUILTIN_FUNCTION lto_builtin_function
+#undef LANG_HOOKS_INIT
+#define LANG_HOOKS_INIT lto_init
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE lto_main
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
More information about the Gcc-patches
mailing list