This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] PATCH: map/unmap LTO sections, + bug fixes
- From: Sandra Loosemore <sandra at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Mark Mitchell <mark at codesourcery dot com>, Kenneth Zadeck <zadeck at naturalbridge dot com>
- Date: Wed, 13 Sep 2006 23:44:28 -0400
- Subject: [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;