This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[lto] PATCH: map/unmap LTO sections, + bug fixes


Here's the patch to implement the map/unmap functions for the LTO information. I've also attempted to fix some bugs in the DIE readers for parameters and subroutines, so that it can read a file containing the identity function without croaking. (I've been configuring with --enable-checking=all for my debugging and testing work.) I dunno, maybe lto_read_variable_formal_parameter_const should just return PARM_DECLs and CONST_DECLs immediately after the call to build_decl, instead of trying to make the rest of the stuff not barf on them?

Anyway, it will now at least read the .o file produced from compiling the identify function:

int f (int x)
{
  return x;
}

-Sandra

2006-09-14  Sandra Loosemore  <sandra@codesourcery.com>

	* gcc/lto/lto.c (lto_read_variable_formal_parameter_const): Don't
	pass PARM_DECLs or CONST_DECLs to rest_of_decl_compilation.
	(lto_read_subroutine_type_subprogram_DIE): Fix precedence problem
	in computing parameter array length.  Make body const.  Initialize
	name_str before using it.

	* gcc/lto/Make-lang.in (lto/lto-elf.o): Add dependency on lto-tags.h.

	* gcc/lto/lto-elf.c: Include lto-tags.h.
	(struct lto_elf_file): Add bits and string_table_section_index, to
	cache info needed by lto_elf_find_section_data.
	(lto_elf_find_section_data): New.
	(lto_elf_file_open): Refactored to use lto_elf_find_section_data
	to look up the .debug_info and .debug_abbrev sections.
	(lto_elf_map_fn_body): Make return type const.  Use
	lto_elf_find_section_data to find the data.
	(lto_elf_unmap_fn_body): Make data parameter const.

	* gcc/lto/lto.h (struct lto_file_vtable): Make return type of
	map_fn_body and data parameter to unmap_fn_body const.

	* gcc/lto/lto-symtab.c (lto_symtab_merge_var): Don't complain if
	it gets a PARM_DECL or CONST_DECL instead of a VAR_DECL.
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c	(revision 116922)
--- gcc/lto/lto.c	(working copy)
*************** lto_read_variable_formal_parameter_const
*** 1743,1749 ****
       declarations.  */
    decl = lto_symtab_merge_var (decl);
    /* Let the middle end know about the new entity.  */
!   if (decl != error_mark_node)
      rest_of_decl_compilation (decl,
  			      /*top_level=*/1,
  			      /*at_end=*/0);
--- 1743,1755 ----
       declarations.  */
    decl = lto_symtab_merge_var (decl);
    /* Let the middle end know about the new entity.  */
!   if (decl != error_mark_node
!       && TREE_CODE (decl) == VAR_DECL)
!     /* rest_of_decl_compilation won't handle PARM_DECLs or CONST_DECLs.
!        PARM_DECLs ought to be handled with their respective FUNCTION_DECL.
!        GCC never generates DW_TAG_constant, and otherwise uses CONST_DECL
!        only for enumeration constants, which are stored in the DWARF file
!        in a completely different way.  */
      rest_of_decl_compilation (decl,
  			      /*top_level=*/1,
  			      /*at_end=*/0);
*************** lto_read_subroutine_type_subprogram_DIE 
*** 1842,1848 ****
  
    parms = lto_collect_child_DIEs (fd, abbrev, context);
    n_parms = VEC_length (tree, parms);
!   arg_types = make_tree_vec (n_parms + prototyped ? 1 : 0);
    for (i = 0; i < n_parms; ++i)
      {
        tree parm = VEC_index (tree, parms, i);
--- 1848,1854 ----
  
    parms = lto_collect_child_DIEs (fd, abbrev, context);
    n_parms = VEC_length (tree, parms);
!   arg_types = make_tree_vec (n_parms + (prototyped ? 1 : 0));
    for (i = 0; i < n_parms; ++i)
      {
        tree parm = VEC_index (tree, parms, i);
*************** lto_read_subroutine_type_subprogram_DIE 
*** 1860,1866 ****
      result = type;
    else
      {
!       void *body;
        lto_file *file;
        const char *name_str;
  
--- 1866,1872 ----
      result = type;
    else
      {
!       const void *body;
        lto_file *file;
        const char *name_str;
  
*************** lto_read_subroutine_type_subprogram_DIE 
*** 1871,1876 ****
--- 1877,1883 ----
        TREE_PUBLIC (result) = external;
        /* Load the body of the function.  */
        file = fd->base.file;
+       name_str = IDENTIFIER_POINTER (name);
        body = file->vtable->map_fn_body (file, name_str);
        if (body)
  	{
Index: gcc/lto/Make-lang.in
===================================================================
*** gcc/lto/Make-lang.in	(revision 116922)
--- gcc/lto/Make-lang.in	(working copy)
*************** lto/lto-lang.o: lto/lto-lang.c $(CONFIG_
*** 82,88 ****
  lto/lto.o: lto/lto.c $(CONFIG_H) $(CGRAPH_H) coretypes.h dwarf2.h \
  	$(GGC_H) opts.h $(SYSTEM_H) toplev.h $(TM_H) $(LTO_H)
  lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
! 	toplev.h $(LTO_H) 
  lto/lto-symtab.o: lto/lto-symtab.c $(CONFIG_H) coretypes.h \
  	$(SYSTEM_H) toplev.h $(TREE_H) $(LTO_H) lto/lto-tree.h
  lto-read.o : lto-read.c $(CONFIG_H) $(SYSTEM_H) \
--- 82,88 ----
  lto/lto.o: lto/lto.c $(CONFIG_H) $(CGRAPH_H) coretypes.h dwarf2.h \
  	$(GGC_H) opts.h $(SYSTEM_H) toplev.h $(TM_H) $(LTO_H)
  lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
! 	toplev.h $(LTO_H) $(LTO_TAGS_H)
  lto/lto-symtab.o: lto/lto-symtab.c $(CONFIG_H) coretypes.h \
  	$(SYSTEM_H) toplev.h $(TREE_H) $(LTO_H) lto/lto-tree.h
  lto-read.o : lto-read.c $(CONFIG_H) $(SYSTEM_H) \
Index: gcc/lto/lto-elf.c
===================================================================
*** gcc/lto/lto-elf.c	(revision 116922)
--- gcc/lto/lto-elf.c	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 25,30 ****
--- 25,31 ----
  #include "toplev.h"
  #include "lto.h"
  #include "libelf.h"
+ #include "lto-tags.h"
  
  /* An ELF input file.  */
  struct lto_elf_file 
*************** struct lto_elf_file 
*** 35,50 ****
    int fd;
    /* The libelf descriptor for the file.  */
    Elf *elf;
  };
  typedef struct lto_elf_file lto_elf_file;
  
  /* Forward Declarations */
  
! static void *
  lto_elf_map_fn_body (lto_file *file, const char *fn);
  
  static void
! lto_elf_unmap_fn_body (lto_file *file, const char *fn, void *data);
  
  /* The vtable for ELF input files.  */
  static const lto_file_vtable lto_elf_file_vtable = {
--- 36,55 ----
    int fd;
    /* The libelf descriptor for the file.  */
    Elf *elf;
+   /* 32 or 64 bits? */
+   size_t bits;
+   /* Offset of string table used for section names.  */
+   size_t string_table_section_index;
  };
  typedef struct lto_elf_file lto_elf_file;
  
  /* Forward Declarations */
  
! static const void *
  lto_elf_map_fn_body (lto_file *file, const char *fn);
  
  static void
! lto_elf_unmap_fn_body (lto_file *file, const char *fn, const void *data);
  
  /* The vtable for ELF input files.  */
  static const lto_file_vtable lto_elf_file_vtable = {
*************** static const lto_file_vtable lto_elf_fil
*** 52,67 ****
    lto_elf_unmap_fn_body
  };
  
  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 = XNEW (lto_elf_file);
--- 57,160 ----
    lto_elf_unmap_fn_body
  };
  
+ /* A helper function to find the section named SECTION_NAME in ELF_FILE, and
+    return its data.  Emits an appropriate error message and returns NULL
+    if a unique section with that name is not found.  */
+ 
+ static Elf_Data *
+ lto_elf_find_section_data (lto_elf_file *elf_file, const char *section_name)
+ {
+   Elf_Scn *section, *result;
+   Elf_Data *data;
+   size_t bits = elf_file->bits;
+ 
+   result = NULL;
+   for (section = elf_getscn (elf_file->elf, 0);
+        section;
+        section = elf_nextscn (elf_file->elf, section)) 
+     {
+       size_t offset;
+       const char *name;
+ 
+       if (!section)
+ 	{
+ 	  error ("could not read section information: %s", elf_errmsg (0));
+ 	  return NULL;
+ 	}
+ 
+ #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)); \
+ 	    return NULL;						 \
+ 	  }								 \
+ 	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, elf_file->string_table_section_index, 
+ 			 offset);
+       if (!name)
+ 	{
+ 	  error ("could not read section name: %s", elf_errmsg (0));
+ 	  return NULL;
+ 	}
+       
+       /* Check to see if this is the section of interest.  */
+       if (strcmp (name, section_name) == 0)
+ 	{
+ 	  /* There should not be two debugging sections with the same
+ 	     name.  */
+ 	  if (result)
+ 	    {
+ 	      error ("duplicate %qs section", section_name);
+ 	      return NULL;
+ 	    }
+ 	  result = section;
+ 	}
+     }
+   if (! result)
+     {
+       error ("missing %qs section", section_name);
+       return NULL;
+     }
+ 
+   data = elf_getdata (result, NULL);
+   if (!data)
+     {
+       error ("could not read data: %s", elf_errmsg (0));
+       return NULL;
+     }
+   return data;
+ }
+ 
  lto_file *
  lto_elf_file_open (const char *filename)
  {
    lto_elf_file *elf_file;
    size_t bits;
    const char *elf_ident;
    Elf_Scn *string_table_section;
!   Elf_Data *data;
    lto_file *result;
+   lto_fd *fd;
  
    /* Set up.  */
    elf_file = XNEW (lto_elf_file);
*************** lto_elf_file_open (const char *filename)
*** 116,121 ****
--- 209,215 ----
        error ("unsupported ELF file class");
        goto fail;
      }
+   elf_file->bits = bits;
  
    /* Check that the input file is a relocatable object file.  */
  #define ELF_CHECK_FILE_TYPE(N)						\
*************** lto_elf_file_open (const char *filename)
*** 149,246 ****
  #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: %s", 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;
!       lto_fd *fd;
!       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)
! 	fd = (lto_fd *) &result->debug_info;
!       else if (strcmp (name, ".debug_abbrev") == 0)
! 	fd = (lto_fd *) &result->debug_abbrev;
!       else
! 	continue;
! 
!       /* There should not be two debugging sections with the same
! 	 name.  */
!       if (fd->start)
! 	{
! 	  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: %s", elf_errmsg (0));
! 	  goto fail;
! 	}
!       fd->start = (const char *) data->d_buf;
!       fd->end = fd->start + data->d_size;
!     }
! 
!   if (!((lto_fd *) (&result->debug_info))->start
!       || !((lto_fd *) (&result->debug_abbrev))->start)
!     {
!       error ("could not read DWARF debugging information");
!       goto fail;
!     }
  
    return result;
  
--- 243,270 ----
  #undef ELF_CHECK_FILE_TYPE
  
    /* Read the string table used for section header names.  */
!   if (elf_getshstrndx (elf_file->elf, &elf_file->string_table_section_index) == -1)
      {
        error ("could not locate ELF string table: %s", elf_errmsg (0));
        goto fail;
      }
    string_table_section = elf_getscn (elf_file->elf, 
! 				     elf_file->string_table_section_index);
  
    /* Find the .debug_info and .debug_abbrev sections.  */
!   data = lto_elf_find_section_data (elf_file, ".debug_info");
!   if (!data)
!     goto fail;
!   fd = (lto_fd *) &result->debug_info;
!   fd->start = (const char *) data->d_buf;
!   fd->end = fd->start + data->d_size;
! 
!   data = lto_elf_find_section_data (elf_file, ".debug_abbrev");
!   if (!data)
!     goto fail;
!   fd = (lto_fd *) &result->debug_abbrev;
!   fd->start = (const char *) data->d_buf;
!   fd->end = fd->start + data->d_size;
  
    return result;
  
*************** lto_elf_file_close (lto_file *file)
*** 260,278 ****
    lto_file_close (file);
  }
  
! void *
! lto_elf_map_fn_body (lto_file *file ATTRIBUTE_UNUSED, 
! 		     const char *fn ATTRIBUTE_UNUSED)
  {
!   /* ??? Look in the ELF file to find the actual data, which should be
       in the section named LTO_SECTION_NAME_PREFIX || "the function name".  */
!   return (void *)0x1;
  }
  
  void
  lto_elf_unmap_fn_body (lto_file *file ATTRIBUTE_UNUSED, 
  		       const char *fn ATTRIBUTE_UNUSED, 
! 		       void *data ATTRIBUTE_UNUSED)
  {
    return;
  }
--- 284,308 ----
    lto_file_close (file);
  }
  
! const void *
! lto_elf_map_fn_body (lto_file *file,
! 		     const char *fn)
  {
!   /* Look in the ELF file to find the actual data, which should be
       in the section named LTO_SECTION_NAME_PREFIX || "the function name".  */
!   const char *name = concat (LTO_SECTION_NAME_PREFIX, fn, NULL);
!   Elf_Data *data = lto_elf_find_section_data ((lto_elf_file *)file, name);
! 
!   if (! data)
!     return NULL;
!   else
!     return (const void *)(data->d_buf);
  }
  
  void
  lto_elf_unmap_fn_body (lto_file *file ATTRIBUTE_UNUSED, 
  		       const char *fn ATTRIBUTE_UNUSED, 
! 		       const void *data ATTRIBUTE_UNUSED)
  {
    return;
  }
Index: gcc/lto/lto.h
===================================================================
*** gcc/lto/lto.h	(revision 116922)
--- gcc/lto/lto.h	(working copy)
*************** typedef struct lto_file_vtable
*** 84,94 ****
  {
    /* Return the address of the function-body data for the function
       named FN, or NULL if the data is not available.  */
!   void *(*map_fn_body)(lto_file *file, const char *fn);
    /* DATA is the non-NULL address returned by a previous call to
       MAP_FN_BODY, with the same value of FN.  Release any resources
       allocated by MAP_FN_BODY.  */
!   void (*unmap_fn_body)(lto_file *file, const char *fn, void *data);
  } lto_file_vtable;
  
  /* An input file.  */
--- 84,94 ----
  {
    /* Return the address of the function-body data for the function
       named FN, or NULL if the data is not available.  */
!   const void *(*map_fn_body)(lto_file *file, const char *fn);
    /* DATA is the non-NULL address returned by a previous call to
       MAP_FN_BODY, with the same value of FN.  Release any resources
       allocated by MAP_FN_BODY.  */
!   void (*unmap_fn_body)(lto_file *file, const char *fn, const void *data);
  } lto_file_vtable;
  
  /* An input file.  */
Index: gcc/lto/lto-symtab.c
===================================================================
*** gcc/lto/lto-symtab.c	(revision 116922)
--- gcc/lto/lto-symtab.c	(working copy)
*************** lto_symtab_merge_var (tree new_var) 
*** 56,62 ****
    tree old_var;
    tree name;
  
!   gcc_assert (TREE_CODE (new_var) == VAR_DECL);
    /* Variables with internal linkage do not need to be merged.  */
    if (!TREE_PUBLIC (new_var))
      return new_var;
--- 56,64 ----
    tree old_var;
    tree name;
  
!   gcc_assert (TREE_CODE (new_var) == VAR_DECL
! 	      || TREE_CODE (new_var) == PARM_DECL
! 	      || TREE_CODE (new_var) == CONST_DECL);
    /* Variables with internal linkage do not need to be merged.  */
    if (!TREE_PUBLIC (new_var))
      return new_var;

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