public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [lto][patch] Add initial gold plugin
@ 2008-08-28 12:09 Rafael Espindola
  2008-08-28 17:36 ` Diego Novillo
  2008-08-28 20:03 ` Joseph S. Myers
  0 siblings, 2 replies; 9+ messages in thread
From: Rafael Espindola @ 2008-08-28 12:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Cary Coutant, Diego Novillo

[-- Attachment #1: Type: text/plain, Size: 1052 bytes --]

The attached patch adds the first version of the lto plugin for gold.
I has only the functionality needed to print the symbol table.

Since the plugin support is still in development, I have included a
copy of the header that contains the API. This will be removed once it
is included in gold.

2008-08-27  Rafael Avila de Espindola  <espindola@google.com>

	* Makefile.am (AM_CFLAGS): New.
	(ltosymtab_LDADD): Remove -lelf. Add -ldl.
	(lib_LTLIBRARIES): New.
	(liblto_plugin_la_SOURCES): New.
	(liblto_plugin_la_LIBADD): New.
	* Makefile.in: Regenerate.
	* acinclude.m4: Don't include ../config/acx.m4 and
	../config/no-executables.m4.
	Include ../ltsugar.m4, ../ltoptions.m4, ../ltversion.m4 and
	../libtool.m4.
	* aclocal.m4: Regenerate.
	* configure: Regenerate.
	* configure.ac: Use AM_PROG_LIBTOOL.
	* lto-plugin.c: New.
	* lto-symtab.c: Rewrite to use the plugin.
	* plugin-api.h: New.

Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: plugin.patch --]
[-- Type: text/x-diff; name=plugin.patch, Size: 19170 bytes --]

diff --git a/lto-plugin/Makefile.am b/lto-plugin/Makefile.am
index db159bd..acc0565 100644
--- a/lto-plugin/Makefile.am
+++ b/lto-plugin/Makefile.am
@@ -1,4 +1,13 @@
 AM_CPPFLAGS = -I$(top_srcdir)/../include
+
+AM_CFLAGS = -Wall -Werror
+
 bin_PROGRAMS = ltosymtab
+
 ltosymtab_SOURCES = lto-symtab.c
-ltosymtab_LDADD = -lelf
+ltosymtab_LDADD = -ldl
+
+lib_LTLIBRARIES = liblto_plugin.la
+
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = -lelf
diff --git a/lto-plugin/acinclude.m4 b/lto-plugin/acinclude.m4
index 9302f26..655ba7a 100644
--- a/lto-plugin/acinclude.m4
+++ b/lto-plugin/acinclude.m4
@@ -1,3 +1,6 @@
-m4_include(../config/acx.m4)
-m4_include(../config/no-executables.m4)
 m4_include([../config/libelf.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltversion.m4])
+
+sinclude(../libtool.m4)
diff --git a/lto-plugin/configure.ac b/lto-plugin/configure.ac
index e967a22..c2c9ea5 100644
--- a/lto-plugin/configure.ac
+++ b/lto-plugin/configure.ac
@@ -4,5 +4,6 @@ GCC_TOPLEV_SUBDIRS
 AM_INIT_AUTOMAKE([foreign])
 AC_PROG_CC
 AC_CHECK_GELF
+AM_PROG_LIBTOOL
 AC_CONFIG_FILES(Makefile)
 AC_OUTPUT
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
new file mode 100644
index 0000000..3c65f95
--- /dev/null
+++ b/lto-plugin/lto-plugin.c
@@ -0,0 +1,216 @@
+/* LTO plugin for gold.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Contributed by Rafael Avila de Espindola (espindola@google.com).
+
+This program 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 3 of the License, or
+(at your option) any later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_GELF_H
+# include <gelf.h>
+#else
+# if defined(HAVE_LIBELF_GELF_H)
+#   include <libelf/gelf.h>
+# else
+#  error "gelf.h not available"
+# endif
+#endif
+
+#include "plugin-api.h"
+
+static ld_plugin_register_claim_file register_claim_file;
+static ld_plugin_add_symbols add_symbols;
+
+/* Parse an entry of the IL symbol table. The data to be parsed is pointed
+   by P and the result is written in ENTRY. The slot number is stored in SLOT.
+   Returns the address of the next entry. */
+
+char *
+parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
+{
+  unsigned char t;
+  enum ld_plugin_symbol_kind translate_kind[] =
+    {
+      LDPK_DEF,
+      LDPK_WEAKDEF,
+      LDPK_UNDEF,
+      LDPK_WEAKUNDEF,
+      LDPK_COMMON
+    };
+
+  enum ld_plugin_symbol_visibility translate_visibility[] =
+    {
+      LDPV_DEFAULT,
+      LDPV_PROTECTED,
+      LDPV_INTERNAL,
+      LDPV_HIDDEN
+    };
+
+  entry->name = p;
+  while (*p)
+    p++;
+  p++;
+
+  entry->version = NULL;
+
+  entry->comdat_key = p;
+  while (*p)
+    p++;
+  p++;
+
+  if (strcmp (entry->comdat_key, "") == 0)
+    entry->comdat_key = NULL;
+
+  t = *p;
+  assert (t <= 4);
+  entry->def = translate_kind[t];
+  p++;
+
+  t = *p;
+  assert (t <= 3);
+  entry->visibility = translate_visibility[t];
+  p++;
+
+  entry->size = *(uint64_t *) p;
+  p += 8;
+
+  *slot = *(uint32_t *) p;
+  p += 4;
+
+  entry->resolution = LDPR_UNKNOWN;
+
+  return p;
+}
+
+/* Returns the string table of file ELF. */
+
+const char *
+get_string_table (Elf *elf)
+{
+  GElf_Ehdr header;
+  GElf_Ehdr *t = gelf_getehdr (elf, &header);
+  assert (t == &header);
+  Elf_Scn *section = elf_getscn (elf, header.e_shstrndx);
+  assert (section);
+  Elf_Data *data = 0;
+  data = elf_getdata (section, data);
+  assert (data);
+  assert (data->d_buf);
+  return (const char *) data->d_buf;
+}
+
+
+/* Return the section in ELF that is named NAME. */
+
+Elf_Scn *
+get_section (Elf *elf, const char *name)
+{
+  const char *string_table = get_string_table (elf);
+  Elf_Scn *section = 0;
+  while ((section = elf_nextscn(elf, section)) != 0)
+    {
+      GElf_Shdr shdr;
+      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
+      const char *t;
+      assert (tshdr == &shdr);
+      t = string_table + shdr.sh_name;
+      if (strcmp (t, name) == 0)
+	return section;
+    }
+  return NULL;
+}
+
+/* Returns the IL symbol table of file ELF. */
+
+Elf_Data *
+get_symtab (Elf *elf)
+{
+  Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
+  assert (section);
+  Elf_Data *data = 0;
+  data = elf_getdata (section, data);
+  assert (data);
+  return data;
+}
+
+static struct ld_plugin_symbol *
+translate (Elf_Data *symtab, int *num)
+{
+  char *data = symtab->d_buf;
+  char *end = data + symtab->d_size;
+  struct ld_plugin_symbol *ret = NULL;
+  int n = 0;
+  while (data < end)
+    {
+      uint32_t slot;
+      n++;
+      ret = realloc (ret, n * sizeof (struct ld_plugin_symbol));
+      assert (ret);
+      data = parse_table_entry (data, &ret[n - 1], &slot);
+    }
+  *num = n;
+  return ret;
+}
+
+static enum ld_plugin_status
+claim_file_handler(const struct ld_plugin_input_file *file, int *claimed)
+{
+  enum ld_plugin_status status;
+  Elf *elf = elf_begin(file->fd, ELF_C_READ, NULL);
+  assert (elf);
+
+  Elf_Data *symtab = get_symtab (elf);
+  int num;
+  struct ld_plugin_symbol *syms = translate (symtab, &num);
+
+  status = add_symbols (file->handle, num, syms);
+  assert (status == LDPS_OK);
+
+  return LDPS_OK;
+}
+
+void
+onload(struct ld_plugin_tv *tv)
+{
+  struct ld_plugin_tv *p;
+  enum ld_plugin_status status;
+
+  unsigned version = elf_version(EV_CURRENT);
+  assert (version != EV_NONE);
+
+  p = tv;
+  while (p->tv_tag)
+    {
+      switch (p->tv_tag)
+	{
+	case LDPT_REGISTER_CLAIM_FILE_HOOK:
+	  register_claim_file = p->tv_u.tv_register_claim_file;
+	  break;
+	case LDPT_ADD_SYMBOLS:
+	  add_symbols = p->tv_u.tv_add_symbols;
+	  break;
+	default:
+	  break;
+	}
+      p++;
+    }
+
+  assert (register_claim_file);
+  assert (add_symbols);
+  status = register_claim_file (claim_file_handler);
+  assert (status == LDPS_OK);
+}
diff --git a/lto-plugin/lto-symtab.c b/lto-plugin/lto-symtab.c
index 82253f2..126c563 100644
--- a/lto-plugin/lto-symtab.c
+++ b/lto-plugin/lto-symtab.c
@@ -1,10 +1,10 @@
 /* Program to read the IL symbol table.
-   Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
-   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Contributed by Rafael Avila de Espindola (espindola@google.com).
 
 This program 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 of the License, or
+the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
@@ -18,146 +18,126 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
 #include <fcntl.h>
 #include <assert.h>
-#ifdef HAVE_GELF_H
-# include <gelf.h>
-#else
-# if defined(HAVE_LIBELF_GELF_H)
-#   include <libelf/gelf.h>
-# else
-#  error "gelf.h not available"
-# endif
-#endif
+#include <dlfcn.h>
 #include <stdio.h>
-#include <string.h>
-#include "lto-symtab.h"
+#include <inttypes.h>
 
-/* Return the string table of ELF. */
 
-const char *
-get_string_table (Elf *elf)
+
+#include "plugin-api.h"
+
+ld_plugin_claim_file_handler claim_file_handler;
+void *current_file_handle;
+
+/* Register HANDLER as the callback for claiming a file. */
+
+enum ld_plugin_status
+register_claim_file(ld_plugin_claim_file_handler handler)
 {
-  GElf_Ehdr header;
-  GElf_Ehdr *t = gelf_getehdr (elf, &header);
-  assert (t == &header);
-  Elf_Scn *section = elf_getscn (elf, header.e_shstrndx);
-  assert (section);
-  Elf_Data *data = 0;
-  data = elf_getdata (section, data);
-  assert (data);
-  assert (data->d_buf);
-  return (const char *) data->d_buf;
+  claim_file_handler = handler;
+  return LDPS_OK;
 }
 
-/* Return the section in ELF that is named NAME. */
+/* For a file identified by HANDLE, add NSYMS symbols from SYMS. */
 
-Elf_Scn *
-get_section (Elf *elf, const char *name)
+static enum ld_plugin_status
+add_symbols (const void *handle, int nsyms,
+	     const struct ld_plugin_symbol *syms)
 {
-  const char *string_table = get_string_table (elf);
-  Elf_Scn *section = 0;
-  while ((section = elf_nextscn(elf, section)) != 0)
+  const char *kind_str[] = {"DEF", "WEAKDEF", "UNDEF",
+			    "WEAKUNDEF", "COMMON"};
+  const char *visibility_str[] = {"DEFAULT", "PROTECTED",
+				  "INTERNAL", "HIDDEN"};
+  const char *resolution_str[] = {"UNKNOWN", "UNDEF",
+				  "PREVAILING_DEF",
+				  "PREVAILING_DEF_IRONLY",
+				  "PREEMPTED_REG",
+				  "PREEMPTED_IR",
+				  "RESOLVED_IR",
+				  "RESOLVED_EXEC",
+				  "RESOLVED_DYN"};
+
+  int i;
+  assert (handle == current_file_handle);
+
+  for (i = 0; i < nsyms; i++)
     {
-      GElf_Shdr shdr;
-      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
-      const char *t;
-      assert (tshdr == &shdr);
-      t = string_table + shdr.sh_name;
-      if (strcmp (t, name) == 0)
-	return section;
+      printf("name: %s; ", syms[i].name);
+      if (syms[i].version)
+	printf("version: %s;", syms[i].version);
+      else
+	printf("not versioned; ");
+      printf("kind: %s; ", kind_str[syms[i].def]);
+      printf("visibility: %s; ", visibility_str[syms[i].visibility]);
+      printf("size: %" PRId64 "; ", syms[i].size);
+      if (syms[i].comdat_key)
+	printf("comdat_key: %s; ", syms[i].comdat_key);
+      else
+	printf("no comdat_key; ");
+      printf ("resolution: %s\n", resolution_str[syms[i].resolution]);
     }
-  return NULL;
+  return LDPS_OK;
 }
 
-/* Return the IL symbol table of ELF. */
+struct ld_plugin_tv tv[] = {
+  {LDPT_REGISTER_CLAIM_FILE_HOOK,
+   {.tv_register_claim_file = register_claim_file}
+  },
+  {LDPT_ADD_SYMBOLS,
+   {.tv_add_symbols = add_symbols}
+  },
 
-Elf_Data *
-get_symtab (Elf *elf)
-{
-  Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
-  assert (section);
-  Elf_Data *data = 0;
-  data = elf_getdata (section, data);
-  assert (data);
-  return data;
-}
-
-struct table_entry
-{
-  char *name;
-  char *comdat;
-  enum gcc_plugin_symbol_kind kind;
-  enum gcc_plugin_symbol_visibility visibility;
-  uint64_t size;
-  uint32_t slot_num;
+  {0, {0}}
 };
 
-/* Parse an entry of the IL symbol table. The data to be parsed is pointed
-   by P and the result is written in ENTRY. Returs the address of the next
-   entry. */
+/* Load a plugin from a file named NAME. */
 
-char *parse_table_entry (char *p, struct table_entry *entry)
+static void
+load_plugin (const char *name)
 {
-  entry->name = p;
-  while (*p)
-    p++;
-  p++;
-
-  entry->comdat = p;
-  while (*p)
-    p++;
-  p++;
+  ld_plugin_onload onload;
+  void *lib = dlopen (name, RTLD_LAZY);
+
+  assert (lib != NULL);
+  onload = dlsym (lib, "onload");
+  assert (onload);
+  onload (tv);
+  assert (claim_file_handler);
+}
 
-  entry->kind = *p;
-  assert (entry->kind <= 4);
-  p++;
+/* Send file named NAME to the plugin. */
 
-  entry->visibility = *p;
-  assert (entry->visibility <= 3);
-  p++;
+static void
+register_file (const char *name)
+{
+ int claimed;
+ struct ld_plugin_input_file file;
+ int fd = open (name, O_RDONLY);
+ assert (fd >= 0);
 
-  entry->size = *(uint64_t *) p;
-  p += 8;
+ file.name = (char *) name;
+ file.fd = fd;
+ file.offset = 0; /* Used only in archives. */
+ file.filesize = 0; /* Used only in archives. */
 
-  entry->slot_num = *(uint32_t *) p;
-  p += 4;
+ /* Just to check that the plugin keeps it. */
+ file.handle = &file;
+ current_file_handle = file.handle;
 
-  return p;
+ claim_file_handler (&file, &claimed);
 }
 
-/* Print the symbol table SYMTAB to stdout. */
-
-void printTable (Elf_Data *symtab)
+int
+main(int argc, char *argv[])
 {
-  char *data = symtab->d_buf;
-  char *end = data + symtab->d_size;
-  while (data < end)
-    {
-      struct table_entry entry;
-      const char *kind_str[] = {"GCCPK_DEF", "GCCPK_WEAKDEF", "GCCPK_UNDEF",
-				"GCCPK_WEAKUNDEF", "GCCPK_COMMON"};
-      const char *visibility_str[] = {"GCCPV_DEFAULT", "GCCPV_PROTECTED",
-				      "GCCPV_INTERNAL", "GCCPV_HIDDEN"};
-      data = parse_table_entry (data, &entry);
-
-      printf("%s %s %s %s %lld %d\n", entry.name, entry.comdat,
-	     kind_str[entry.kind], visibility_str[entry.visibility],
-	     entry.size, entry.slot_num);
-    }
-}
+  const char *plugin;
+  const char *obj;
+  assert (argc == 3);
+  plugin = argv[1];
+  obj = argv[2];
+
+  load_plugin (plugin);
+  register_file (obj);
 
-int main (int argc,  char *argv[])
-{
-  unsigned version = elf_version(EV_CURRENT);
-  assert (version != EV_NONE);
-  assert (argc == 2);
-  int fd = open (argv[1], O_RDONLY);
-  assert (fd >= 0);
-  Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
-  assert (elf);
-
-  Elf_Data *symtab = get_symtab (elf);
-  printTable (symtab);
-
-  elf_end(elf);
   return 0;
 }
diff --git a/lto-plugin/plugin-api.h b/lto-plugin/plugin-api.h
new file mode 100644
index 0000000..7f96bbd
--- /dev/null
+++ b/lto-plugin/plugin-api.h
@@ -0,0 +1,237 @@
+/* plugin-api.h -- External plugin API for gold.  */
+
+/* Copyright 2008 Free Software Foundation, Inc.
+   Written by Cary Coutant <ccoutant@google.com>.
+
+   This file is part of gold.
+
+   This program 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 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* This file defines the interface for writing a linker plugin, which is
+   described at < http://gcc.gnu.org/wiki/whopr/driver >.  */
+
+#ifndef GOLD_PLUGIN_API_H
+#define GOLD_PLUGIN_API_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Status code returned by most API routines.  */
+
+enum ld_plugin_status {
+  LDPS_OK = 0,
+  LDPS_ERR,
+  /* Additional Error codes TBD.  */
+};
+
+/* The version of the API specification.  */
+
+enum ld_plugin_api_version
+{
+  LD_PLUGIN_API_VERSION = 1,
+};
+
+/* The type of output file being generated by the linker.  */
+
+enum ld_plugin_output_file_type
+{
+  LDPO_REL,
+  LDPO_EXEC,
+  LDPO_DYN,
+};
+
+/* An input file managed by the plugin library.  */
+
+struct ld_plugin_input_file
+{
+  const char *name;
+  int fd;
+  off_t offset;
+  off_t filesize;
+  void *handle;
+};
+
+/* A symbol belonging to an input file managed by the plugin library.  */
+
+struct ld_plugin_symbol
+{
+  char *name;
+  char *version;
+  int def;
+  int visibility;
+  uint64_t size;
+  char *comdat_key;
+  int resolution;
+};
+
+/* Whether the symbol is a definition, reference, or common, weak or not.  */
+
+enum ld_plugin_symbol_kind
+{
+  LDPK_DEF,
+  LDPK_WEAKDEF,
+  LDPK_UNDEF,
+  LDPK_WEAKUNDEF,
+  LDPK_COMMON,
+};
+
+/* The visibility of the symbol.  */
+
+enum ld_plugin_symbol_visibility
+{
+  LDPV_DEFAULT,
+  LDPV_PROTECTED,
+  LDPV_INTERNAL,
+  LDPV_HIDDEN,
+};
+
+/* How a symbol is resolved.  */
+
+enum ld_plugin_symbol_resolution
+{
+  LDPR_UNKNOWN = 0,
+  LDPR_UNDEF,
+  LDPR_PREVAILING_DEF,
+  LDPR_PREVAILING_DEF_IRONLY,
+  LDPR_PREEMPTED_REG,
+  LDPR_PREEMPTED_IR,
+  LDPR_RESOLVED_IR,
+  LDPR_RESOLVED_EXEC,
+  LDPR_RESOLVED_DYN,
+};
+
+/* The plugin library's "claim file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_claim_file_handler) (
+  const struct ld_plugin_input_file *file, int *claimed);
+
+/* The plugin library's "all symbols read" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_all_symbols_read_handler) ();
+
+/* The plugin library's cleanup handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_cleanup_handler) ();
+
+/* The linker's interface for registering the "claim file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
+
+/* The linker's interface for registering the "all symbols read" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_all_symbols_read) (
+  ld_plugin_all_symbols_read_handler handler);
+
+/* The linker's interface for registering the cleanup handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_cleanup) (ld_plugin_cleanup_handler handler);
+
+/* The linker's interface for adding symbols from a claimed input file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_add_symbols) (const void *handle, int nsyms,
+                          const struct ld_plugin_symbol *syms);
+
+/* The linker's interface for retrieving symbol resolution information.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_symbols) (void *handle, int nsyms,
+                          struct ld_plugin_symbol *syms);
+
+/* The linker's interface for adding a compiled input file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_add_input_file) (char *pathname);
+
+/* The linker's interface for issuing a warning or error message.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_message) (int level, char *format, ...);
+
+enum ld_plugin_level
+{
+  LDPL_INFO,
+  LDPL_WARNING,
+  LDPL_ERROR,
+  LDPL_FATAL,
+};
+
+/* Values for the tv_tag field of the transfer vector.  */
+
+enum ld_plugin_tag
+{
+  LDPT_NULL = 0,
+  LDPT_API_VERSION,
+  LDPT_GOLD_VERSION,
+  LDPT_LINKER_OUTPUT,
+  LDPT_OPTION,
+  LDPT_REGISTER_CLAIM_FILE_HOOK,
+  LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
+  LDPT_REGISTER_CLEANUP_HOOK,
+  LDPT_ADD_SYMBOLS,
+  LDPT_GET_SYMBOLS,
+  LDPT_ADD_INPUT_FILE,
+  LDPT_MESSAGE,
+};
+
+/* The plugin transfer vector.  */
+
+struct ld_plugin_tv
+{
+  enum ld_plugin_tag tv_tag;
+  union
+  {
+    int tv_val;
+    const char *tv_string;
+    ld_plugin_register_claim_file tv_register_claim_file;
+    ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
+    ld_plugin_register_cleanup tv_register_cleanup;
+    ld_plugin_add_symbols tv_add_symbols;
+    ld_plugin_get_symbols tv_get_symbols;
+    ld_plugin_add_input_file tv_add_input_file;
+    ld_plugin_message tv_message;
+  } tv_u;
+};
+
+/* The plugin library's "onload" entry point.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_onload) (struct ld_plugin_tv *tv);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* !defined(GOLD_PLUGIN_API_H) */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-08-28 12:09 [lto][patch] Add initial gold plugin Rafael Espindola
@ 2008-08-28 17:36 ` Diego Novillo
  2008-09-01 14:35   ` Rafael Espindola
  2008-08-28 20:03 ` Joseph S. Myers
  1 sibling, 1 reply; 9+ messages in thread
From: Diego Novillo @ 2008-08-28 17:36 UTC (permalink / raw)
  To: Rafael Espindola; +Cc: gcc-patches, Cary Coutant

Rafael Espindola wrote:

> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 3 of the License, or
> +(at your option) any later version.
> +
> +This program 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 this program; if not, write to the Free Software
> +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
> +

Could you add a file level comment explaining at a high level how the 
plugin operates?  Some of it will need to refer to the documentation in 
gold, which for now is mostly what we have in the LTO wiki, I suspect.

> +/* Returns the IL symbol table of file ELF. */
> +
> +Elf_Data *
> +get_symtab (Elf *elf)
> +{
> +  Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
> +  assert (section);

Do we really want to assert here?  Maybe return an error code so the 
caller can emit a diagnostic?

> +  Elf_Data *data = 0;
> +  data = elf_getdata (section, data);
> +  assert (data);
> +  return data;
> +}
> +
> +static struct ld_plugin_symbol *
> +translate (Elf_Data *symtab, int *num)

Needs documentation.  Applies to most new functions in the file.

> +
> +static enum ld_plugin_status
> +claim_file_handler(const struct ld_plugin_input_file *file, int *claimed)
> +{
> +  enum ld_plugin_status status;
> +  Elf *elf = elf_begin(file->fd, ELF_C_READ, NULL);

Space before '('.  There are a few occurrences of this throughout.

>  
> -Elf_Scn *
> -get_section (Elf *elf, const char *name)
> +static enum ld_plugin_status
> +add_symbols (const void *handle, int nsyms,
> +	     const struct ld_plugin_symbol *syms)
>  {
> -  const char *string_table = get_string_table (elf);
> -  Elf_Scn *section = 0;
> -  while ((section = elf_nextscn(elf, section)) != 0)
> +  const char *kind_str[] = {"DEF", "WEAKDEF", "UNDEF",
> +			    "WEAKUNDEF", "COMMON"};
> +  const char *visibility_str[] = {"DEFAULT", "PROTECTED",
> +				  "INTERNAL", "HIDDEN"};
> +  const char *resolution_str[] = {"UNKNOWN", "UNDEF",
> +				  "PREVAILING_DEF",
> +				  "PREVAILING_DEF_IRONLY",
> +				  "PREEMPTED_REG",
> +				  "PREEMPTED_IR",
> +				  "RESOLVED_IR",
> +				  "RESOLVED_EXEC",
> +				  "RESOLVED_DYN"};

Move to a header file?

The rest looks fine.


Thanks.  Diego.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-08-28 12:09 [lto][patch] Add initial gold plugin Rafael Espindola
  2008-08-28 17:36 ` Diego Novillo
@ 2008-08-28 20:03 ` Joseph S. Myers
  2008-08-29  8:29   ` Rafael Espindola
  1 sibling, 1 reply; 9+ messages in thread
From: Joseph S. Myers @ 2008-08-28 20:03 UTC (permalink / raw)
  To: Rafael Espindola; +Cc: gcc-patches, Cary Coutant, Diego Novillo

On Wed, 27 Aug 2008, Rafael Espindola wrote:

> The attached patch adds the first version of the lto plugin for gold.
> I has only the functionality needed to print the symbol table.
> 
> Since the plugin support is still in development, I have included a
> copy of the header that contains the API. This will be removed once it
> is included in gold.
> 
> 2008-08-27  Rafael Avila de Espindola  <espindola@google.com>
> 
> 	* Makefile.am (AM_CFLAGS): New.
> 	(ltosymtab_LDADD): Remove -lelf. Add -ldl.

Since you are making other use of libtool here, I suggest using its 
support for dynamic loading (with libltdl when necessary) rather than 
hardcoding -ldl and so restricting the supported hosts arbitrarily.  (I 
have not looked at the details of how or why -ldl is being used.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-08-28 20:03 ` Joseph S. Myers
@ 2008-08-29  8:29   ` Rafael Espindola
  2008-12-17 23:11     ` Andrew Pinski
  0 siblings, 1 reply; 9+ messages in thread
From: Rafael Espindola @ 2008-08-29  8:29 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, Cary Coutant, Diego Novillo

> Since you are making other use of libtool here, I suggest using its
> support for dynamic loading (with libltdl when necessary) rather than
> hardcoding -ldl and so restricting the supported hosts arbitrarily.  (I
> have not looked at the details of how or why -ldl is being used.)

This is a lto plugin for Gold. I don't think using -ldl is limiting
the supported platforms. I can change that in the future, but get it
working is a bigger priority.

> --
> Joseph S. Myers
> joseph@codesourcery.com
>


Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-08-28 17:36 ` Diego Novillo
@ 2008-09-01 14:35   ` Rafael Espindola
  2008-09-01 14:36     ` Rafael Espindola
  0 siblings, 1 reply; 9+ messages in thread
From: Rafael Espindola @ 2008-09-01 14:35 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc-patches, Cary Coutant

>> -get_section (Elf *elf, const char *name)
>> +static enum ld_plugin_status
>> +add_symbols (const void *handle, int nsyms,
>> +            const struct ld_plugin_symbol *syms)
>>  {
>> -  const char *string_table = get_string_table (elf);
>> -  Elf_Scn *section = 0;
>> -  while ((section = elf_nextscn(elf, section)) != 0)
>> +  const char *kind_str[] = {"DEF", "WEAKDEF", "UNDEF",
>> +                           "WEAKUNDEF", "COMMON"};
>> +  const char *visibility_str[] = {"DEFAULT", "PROTECTED",
>> +                                 "INTERNAL", "HIDDEN"};
>> +  const char *resolution_str[] = {"UNKNOWN", "UNDEF",
>> +                                 "PREVAILING_DEF",
>> +                                 "PREVAILING_DEF_IRONLY",
>> +                                 "PREEMPTED_REG",
>> +                                 "PREEMPTED_IR",
>> +                                 "RESOLVED_IR",
>> +                                 "RESOLVED_EXEC",
>> +                                 "RESOLVED_DYN"};
>
> Move to a header file?

Cary, what do you think. Should this be it plugin-api.h? These arrays
are indexed with enums defined there.

> The rest looks fine.
An updated version is attached. Could you please take another look?


>
> Thanks.  Diego.
>


Thanks,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-09-01 14:35   ` Rafael Espindola
@ 2008-09-01 14:36     ` Rafael Espindola
  2008-09-02 22:07       ` Diego Novillo
  0 siblings, 1 reply; 9+ messages in thread
From: Rafael Espindola @ 2008-09-01 14:36 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc-patches, Cary Coutant

[-- Attachment #1: Type: text/plain, Size: 244 bytes --]

> An updated version is attached. Could you please take another look?

Now it is ...

Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: plugin.patch --]
[-- Type: text/x-diff; name=plugin.patch, Size: 20139 bytes --]

diff --git a/lto-plugin/Makefile.am b/lto-plugin/Makefile.am
index db159bd..acc0565 100644
--- a/lto-plugin/Makefile.am
+++ b/lto-plugin/Makefile.am
@@ -1,4 +1,13 @@
 AM_CPPFLAGS = -I$(top_srcdir)/../include
+
+AM_CFLAGS = -Wall -Werror
+
 bin_PROGRAMS = ltosymtab
+
 ltosymtab_SOURCES = lto-symtab.c
-ltosymtab_LDADD = -lelf
+ltosymtab_LDADD = -ldl
+
+lib_LTLIBRARIES = liblto_plugin.la
+
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = -lelf
diff --git a/lto-plugin/acinclude.m4 b/lto-plugin/acinclude.m4
index 9302f26..655ba7a 100644
--- a/lto-plugin/acinclude.m4
+++ b/lto-plugin/acinclude.m4
@@ -1,3 +1,6 @@
-m4_include(../config/acx.m4)
-m4_include(../config/no-executables.m4)
 m4_include([../config/libelf.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltversion.m4])
+
+sinclude(../libtool.m4)
diff --git a/lto-plugin/configure.ac b/lto-plugin/configure.ac
index e967a22..c2c9ea5 100644
--- a/lto-plugin/configure.ac
+++ b/lto-plugin/configure.ac
@@ -4,5 +4,6 @@ GCC_TOPLEV_SUBDIRS
 AM_INIT_AUTOMAKE([foreign])
 AC_PROG_CC
 AC_CHECK_GELF
+AM_PROG_LIBTOOL
 AC_CONFIG_FILES(Makefile)
 AC_OUTPUT
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
new file mode 100644
index 0000000..bd4b2f4
--- /dev/null
+++ b/lto-plugin/lto-plugin.c
@@ -0,0 +1,247 @@
+/* LTO plugin for gold.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Contributed by Rafael Avila de Espindola (espindola@google.com).
+
+This program 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 3 of the License, or
+(at your option) any later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* The plugin has only one external function: onload. Gold passes it an array of
+   function that the plugin uses to communicate back to gold.
+
+   With the functions provided by gold, the plugin can be notified when
+   gold first analyzes a file and pass a symbol table back to gold. The plugin
+   is also notified when all symbols have been read and it is time to generate
+   machine code for the necessary symbols.
+
+   More information at http://gcc.gnu.org/wiki/whopr/driver.
+*/
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_GELF_H
+# include <gelf.h>
+#else
+# if defined(HAVE_LIBELF_GELF_H)
+#   include <libelf/gelf.h>
+# else
+#  error "gelf.h not available"
+# endif
+#endif
+
+#include "plugin-api.h"
+
+static ld_plugin_register_claim_file register_claim_file;
+static ld_plugin_add_symbols add_symbols;
+
+/* Parse an entry of the IL symbol table. The data to be parsed is pointed
+   by P and the result is written in ENTRY. The slot number is stored in SLOT.
+   Returns the address of the next entry. */
+
+static char *
+parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
+{
+  unsigned char t;
+  enum ld_plugin_symbol_kind translate_kind[] =
+    {
+      LDPK_DEF,
+      LDPK_WEAKDEF,
+      LDPK_UNDEF,
+      LDPK_WEAKUNDEF,
+      LDPK_COMMON
+    };
+
+  enum ld_plugin_symbol_visibility translate_visibility[] =
+    {
+      LDPV_DEFAULT,
+      LDPV_PROTECTED,
+      LDPV_INTERNAL,
+      LDPV_HIDDEN
+    };
+
+  entry->name = p;
+  while (*p)
+    p++;
+  p++;
+
+  entry->version = NULL;
+
+  entry->comdat_key = p;
+  while (*p)
+    p++;
+  p++;
+
+  if (strcmp (entry->comdat_key, "") == 0)
+    entry->comdat_key = NULL;
+
+  t = *p;
+  assert (t <= 4);
+  entry->def = translate_kind[t];
+  p++;
+
+  t = *p;
+  assert (t <= 3);
+  entry->visibility = translate_visibility[t];
+  p++;
+
+  entry->size = *(uint64_t *) p;
+  p += 8;
+
+  *slot = *(uint32_t *) p;
+  p += 4;
+
+  entry->resolution = LDPR_UNKNOWN;
+
+  return p;
+}
+
+/* Returns the string table of file ELF. */
+
+static const char *
+get_string_table (Elf *elf)
+{
+  GElf_Ehdr header;
+  GElf_Ehdr *t = gelf_getehdr (elf, &header);
+  assert (t == &header);
+  Elf_Scn *section = elf_getscn (elf, header.e_shstrndx);
+  assert (section);
+  Elf_Data *data = 0;
+  data = elf_getdata (section, data);
+  assert (data);
+  assert (data->d_buf);
+  return (const char *) data->d_buf;
+}
+
+
+/* Return the section in ELF that is named NAME. */
+
+static Elf_Scn *
+get_section (Elf *elf, const char *name)
+{
+  const char *string_table = get_string_table (elf);
+  Elf_Scn *section = 0;
+  while ((section = elf_nextscn(elf, section)) != 0)
+    {
+      GElf_Shdr shdr;
+      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
+      const char *t;
+      assert (tshdr == &shdr);
+      t = string_table + shdr.sh_name;
+      if (strcmp (t, name) == 0)
+	return section;
+    }
+  return NULL;
+}
+
+/* Returns the IL symbol table of file ELF. */
+
+static Elf_Data *
+get_symtab (Elf *elf)
+{
+  Elf_Data *data = 0;
+  Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
+  if (!section)
+    return NULL;
+
+  data = elf_getdata (section, data);
+  assert (data);
+  return data;
+}
+
+/* Translate the IL symbol tabel SYMTAB into an array of ld_plugin_symbol
+   and return it. Write the array size in SIZE. */
+
+static struct ld_plugin_symbol *
+translate (Elf_Data *symtab, int *size)
+{
+  char *data = symtab->d_buf;
+  char *end = data + symtab->d_size;
+  struct ld_plugin_symbol *ret = NULL;
+  int n = 0;
+  while (data < end)
+    {
+      uint32_t slot;
+      n++;
+      ret = realloc (ret, n * sizeof (struct ld_plugin_symbol));
+      assert (ret);
+      data = parse_table_entry (data, &ret[n - 1], &slot);
+    }
+  *size = n;
+  return ret;
+}
+
+/* Callback used by gold to check if the plugin will claim FILE. Writes
+   the result in CLAIMED. */
+
+static enum ld_plugin_status
+claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+{
+  enum ld_plugin_status status;
+  Elf *elf = elf_begin (file->fd, ELF_C_READ, NULL);
+  int num;
+  Elf_Data *symtab;
+  struct ld_plugin_symbol *syms;
+
+  *claimed = 0;
+
+  if (!elf)
+    return LDPS_OK;
+
+  symtab = get_symtab (elf);
+  if (!symtab)
+    return LDPS_OK;
+
+  syms = translate (symtab, &num);
+
+  status = add_symbols (file->handle, num, syms);
+  assert (status == LDPS_OK);
+
+  *claimed = 1;
+  return LDPS_OK;
+}
+
+/* Called by gold after loading the plugin. TV is the transfer vector. */
+
+void
+onload (struct ld_plugin_tv *tv)
+{
+  struct ld_plugin_tv *p;
+  enum ld_plugin_status status;
+
+  unsigned version = elf_version (EV_CURRENT);
+  assert (version != EV_NONE);
+
+  p = tv;
+  while (p->tv_tag)
+    {
+      switch (p->tv_tag)
+	{
+	case LDPT_REGISTER_CLAIM_FILE_HOOK:
+	  register_claim_file = p->tv_u.tv_register_claim_file;
+	  break;
+	case LDPT_ADD_SYMBOLS:
+	  add_symbols = p->tv_u.tv_add_symbols;
+	  break;
+	default:
+	  break;
+	}
+      p++;
+    }
+
+  assert (register_claim_file);
+  assert (add_symbols);
+  status = register_claim_file (claim_file_handler);
+  assert (status == LDPS_OK);
+}
diff --git a/lto-plugin/lto-symtab.c b/lto-plugin/lto-symtab.c
index 82253f2..126c563 100644
--- a/lto-plugin/lto-symtab.c
+++ b/lto-plugin/lto-symtab.c
@@ -1,10 +1,10 @@
 /* Program to read the IL symbol table.
-   Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
-   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Contributed by Rafael Avila de Espindola (espindola@google.com).
 
 This program 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 of the License, or
+the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
@@ -18,146 +18,126 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
 #include <fcntl.h>
 #include <assert.h>
-#ifdef HAVE_GELF_H
-# include <gelf.h>
-#else
-# if defined(HAVE_LIBELF_GELF_H)
-#   include <libelf/gelf.h>
-# else
-#  error "gelf.h not available"
-# endif
-#endif
+#include <dlfcn.h>
 #include <stdio.h>
-#include <string.h>
-#include "lto-symtab.h"
+#include <inttypes.h>
 
-/* Return the string table of ELF. */
 
-const char *
-get_string_table (Elf *elf)
+
+#include "plugin-api.h"
+
+ld_plugin_claim_file_handler claim_file_handler;
+void *current_file_handle;
+
+/* Register HANDLER as the callback for claiming a file. */
+
+enum ld_plugin_status
+register_claim_file(ld_plugin_claim_file_handler handler)
 {
-  GElf_Ehdr header;
-  GElf_Ehdr *t = gelf_getehdr (elf, &header);
-  assert (t == &header);
-  Elf_Scn *section = elf_getscn (elf, header.e_shstrndx);
-  assert (section);
-  Elf_Data *data = 0;
-  data = elf_getdata (section, data);
-  assert (data);
-  assert (data->d_buf);
-  return (const char *) data->d_buf;
+  claim_file_handler = handler;
+  return LDPS_OK;
 }
 
-/* Return the section in ELF that is named NAME. */
+/* For a file identified by HANDLE, add NSYMS symbols from SYMS. */
 
-Elf_Scn *
-get_section (Elf *elf, const char *name)
+static enum ld_plugin_status
+add_symbols (const void *handle, int nsyms,
+	     const struct ld_plugin_symbol *syms)
 {
-  const char *string_table = get_string_table (elf);
-  Elf_Scn *section = 0;
-  while ((section = elf_nextscn(elf, section)) != 0)
+  const char *kind_str[] = {"DEF", "WEAKDEF", "UNDEF",
+			    "WEAKUNDEF", "COMMON"};
+  const char *visibility_str[] = {"DEFAULT", "PROTECTED",
+				  "INTERNAL", "HIDDEN"};
+  const char *resolution_str[] = {"UNKNOWN", "UNDEF",
+				  "PREVAILING_DEF",
+				  "PREVAILING_DEF_IRONLY",
+				  "PREEMPTED_REG",
+				  "PREEMPTED_IR",
+				  "RESOLVED_IR",
+				  "RESOLVED_EXEC",
+				  "RESOLVED_DYN"};
+
+  int i;
+  assert (handle == current_file_handle);
+
+  for (i = 0; i < nsyms; i++)
     {
-      GElf_Shdr shdr;
-      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
-      const char *t;
-      assert (tshdr == &shdr);
-      t = string_table + shdr.sh_name;
-      if (strcmp (t, name) == 0)
-	return section;
+      printf("name: %s; ", syms[i].name);
+      if (syms[i].version)
+	printf("version: %s;", syms[i].version);
+      else
+	printf("not versioned; ");
+      printf("kind: %s; ", kind_str[syms[i].def]);
+      printf("visibility: %s; ", visibility_str[syms[i].visibility]);
+      printf("size: %" PRId64 "; ", syms[i].size);
+      if (syms[i].comdat_key)
+	printf("comdat_key: %s; ", syms[i].comdat_key);
+      else
+	printf("no comdat_key; ");
+      printf ("resolution: %s\n", resolution_str[syms[i].resolution]);
     }
-  return NULL;
+  return LDPS_OK;
 }
 
-/* Return the IL symbol table of ELF. */
+struct ld_plugin_tv tv[] = {
+  {LDPT_REGISTER_CLAIM_FILE_HOOK,
+   {.tv_register_claim_file = register_claim_file}
+  },
+  {LDPT_ADD_SYMBOLS,
+   {.tv_add_symbols = add_symbols}
+  },
 
-Elf_Data *
-get_symtab (Elf *elf)
-{
-  Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
-  assert (section);
-  Elf_Data *data = 0;
-  data = elf_getdata (section, data);
-  assert (data);
-  return data;
-}
-
-struct table_entry
-{
-  char *name;
-  char *comdat;
-  enum gcc_plugin_symbol_kind kind;
-  enum gcc_plugin_symbol_visibility visibility;
-  uint64_t size;
-  uint32_t slot_num;
+  {0, {0}}
 };
 
-/* Parse an entry of the IL symbol table. The data to be parsed is pointed
-   by P and the result is written in ENTRY. Returs the address of the next
-   entry. */
+/* Load a plugin from a file named NAME. */
 
-char *parse_table_entry (char *p, struct table_entry *entry)
+static void
+load_plugin (const char *name)
 {
-  entry->name = p;
-  while (*p)
-    p++;
-  p++;
-
-  entry->comdat = p;
-  while (*p)
-    p++;
-  p++;
+  ld_plugin_onload onload;
+  void *lib = dlopen (name, RTLD_LAZY);
+
+  assert (lib != NULL);
+  onload = dlsym (lib, "onload");
+  assert (onload);
+  onload (tv);
+  assert (claim_file_handler);
+}
 
-  entry->kind = *p;
-  assert (entry->kind <= 4);
-  p++;
+/* Send file named NAME to the plugin. */
 
-  entry->visibility = *p;
-  assert (entry->visibility <= 3);
-  p++;
+static void
+register_file (const char *name)
+{
+ int claimed;
+ struct ld_plugin_input_file file;
+ int fd = open (name, O_RDONLY);
+ assert (fd >= 0);
 
-  entry->size = *(uint64_t *) p;
-  p += 8;
+ file.name = (char *) name;
+ file.fd = fd;
+ file.offset = 0; /* Used only in archives. */
+ file.filesize = 0; /* Used only in archives. */
 
-  entry->slot_num = *(uint32_t *) p;
-  p += 4;
+ /* Just to check that the plugin keeps it. */
+ file.handle = &file;
+ current_file_handle = file.handle;
 
-  return p;
+ claim_file_handler (&file, &claimed);
 }
 
-/* Print the symbol table SYMTAB to stdout. */
-
-void printTable (Elf_Data *symtab)
+int
+main(int argc, char *argv[])
 {
-  char *data = symtab->d_buf;
-  char *end = data + symtab->d_size;
-  while (data < end)
-    {
-      struct table_entry entry;
-      const char *kind_str[] = {"GCCPK_DEF", "GCCPK_WEAKDEF", "GCCPK_UNDEF",
-				"GCCPK_WEAKUNDEF", "GCCPK_COMMON"};
-      const char *visibility_str[] = {"GCCPV_DEFAULT", "GCCPV_PROTECTED",
-				      "GCCPV_INTERNAL", "GCCPV_HIDDEN"};
-      data = parse_table_entry (data, &entry);
-
-      printf("%s %s %s %s %lld %d\n", entry.name, entry.comdat,
-	     kind_str[entry.kind], visibility_str[entry.visibility],
-	     entry.size, entry.slot_num);
-    }
-}
+  const char *plugin;
+  const char *obj;
+  assert (argc == 3);
+  plugin = argv[1];
+  obj = argv[2];
+
+  load_plugin (plugin);
+  register_file (obj);
 
-int main (int argc,  char *argv[])
-{
-  unsigned version = elf_version(EV_CURRENT);
-  assert (version != EV_NONE);
-  assert (argc == 2);
-  int fd = open (argv[1], O_RDONLY);
-  assert (fd >= 0);
-  Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
-  assert (elf);
-
-  Elf_Data *symtab = get_symtab (elf);
-  printTable (symtab);
-
-  elf_end(elf);
   return 0;
 }
diff --git a/lto-plugin/plugin-api.h b/lto-plugin/plugin-api.h
new file mode 100644
index 0000000..7f96bbd
--- /dev/null
+++ b/lto-plugin/plugin-api.h
@@ -0,0 +1,237 @@
+/* plugin-api.h -- External plugin API for gold.  */
+
+/* Copyright 2008 Free Software Foundation, Inc.
+   Written by Cary Coutant <ccoutant@google.com>.
+
+   This file is part of gold.
+
+   This program 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 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* This file defines the interface for writing a linker plugin, which is
+   described at < http://gcc.gnu.org/wiki/whopr/driver >.  */
+
+#ifndef GOLD_PLUGIN_API_H
+#define GOLD_PLUGIN_API_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Status code returned by most API routines.  */
+
+enum ld_plugin_status {
+  LDPS_OK = 0,
+  LDPS_ERR,
+  /* Additional Error codes TBD.  */
+};
+
+/* The version of the API specification.  */
+
+enum ld_plugin_api_version
+{
+  LD_PLUGIN_API_VERSION = 1,
+};
+
+/* The type of output file being generated by the linker.  */
+
+enum ld_plugin_output_file_type
+{
+  LDPO_REL,
+  LDPO_EXEC,
+  LDPO_DYN,
+};
+
+/* An input file managed by the plugin library.  */
+
+struct ld_plugin_input_file
+{
+  const char *name;
+  int fd;
+  off_t offset;
+  off_t filesize;
+  void *handle;
+};
+
+/* A symbol belonging to an input file managed by the plugin library.  */
+
+struct ld_plugin_symbol
+{
+  char *name;
+  char *version;
+  int def;
+  int visibility;
+  uint64_t size;
+  char *comdat_key;
+  int resolution;
+};
+
+/* Whether the symbol is a definition, reference, or common, weak or not.  */
+
+enum ld_plugin_symbol_kind
+{
+  LDPK_DEF,
+  LDPK_WEAKDEF,
+  LDPK_UNDEF,
+  LDPK_WEAKUNDEF,
+  LDPK_COMMON,
+};
+
+/* The visibility of the symbol.  */
+
+enum ld_plugin_symbol_visibility
+{
+  LDPV_DEFAULT,
+  LDPV_PROTECTED,
+  LDPV_INTERNAL,
+  LDPV_HIDDEN,
+};
+
+/* How a symbol is resolved.  */
+
+enum ld_plugin_symbol_resolution
+{
+  LDPR_UNKNOWN = 0,
+  LDPR_UNDEF,
+  LDPR_PREVAILING_DEF,
+  LDPR_PREVAILING_DEF_IRONLY,
+  LDPR_PREEMPTED_REG,
+  LDPR_PREEMPTED_IR,
+  LDPR_RESOLVED_IR,
+  LDPR_RESOLVED_EXEC,
+  LDPR_RESOLVED_DYN,
+};
+
+/* The plugin library's "claim file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_claim_file_handler) (
+  const struct ld_plugin_input_file *file, int *claimed);
+
+/* The plugin library's "all symbols read" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_all_symbols_read_handler) ();
+
+/* The plugin library's cleanup handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_cleanup_handler) ();
+
+/* The linker's interface for registering the "claim file" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
+
+/* The linker's interface for registering the "all symbols read" handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_all_symbols_read) (
+  ld_plugin_all_symbols_read_handler handler);
+
+/* The linker's interface for registering the cleanup handler.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_cleanup) (ld_plugin_cleanup_handler handler);
+
+/* The linker's interface for adding symbols from a claimed input file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_add_symbols) (const void *handle, int nsyms,
+                          const struct ld_plugin_symbol *syms);
+
+/* The linker's interface for retrieving symbol resolution information.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_symbols) (void *handle, int nsyms,
+                          struct ld_plugin_symbol *syms);
+
+/* The linker's interface for adding a compiled input file.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_add_input_file) (char *pathname);
+
+/* The linker's interface for issuing a warning or error message.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_message) (int level, char *format, ...);
+
+enum ld_plugin_level
+{
+  LDPL_INFO,
+  LDPL_WARNING,
+  LDPL_ERROR,
+  LDPL_FATAL,
+};
+
+/* Values for the tv_tag field of the transfer vector.  */
+
+enum ld_plugin_tag
+{
+  LDPT_NULL = 0,
+  LDPT_API_VERSION,
+  LDPT_GOLD_VERSION,
+  LDPT_LINKER_OUTPUT,
+  LDPT_OPTION,
+  LDPT_REGISTER_CLAIM_FILE_HOOK,
+  LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
+  LDPT_REGISTER_CLEANUP_HOOK,
+  LDPT_ADD_SYMBOLS,
+  LDPT_GET_SYMBOLS,
+  LDPT_ADD_INPUT_FILE,
+  LDPT_MESSAGE,
+};
+
+/* The plugin transfer vector.  */
+
+struct ld_plugin_tv
+{
+  enum ld_plugin_tag tv_tag;
+  union
+  {
+    int tv_val;
+    const char *tv_string;
+    ld_plugin_register_claim_file tv_register_claim_file;
+    ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
+    ld_plugin_register_cleanup tv_register_cleanup;
+    ld_plugin_add_symbols tv_add_symbols;
+    ld_plugin_get_symbols tv_get_symbols;
+    ld_plugin_add_input_file tv_add_input_file;
+    ld_plugin_message tv_message;
+  } tv_u;
+};
+
+/* The plugin library's "onload" entry point.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_onload) (struct ld_plugin_tv *tv);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* !defined(GOLD_PLUGIN_API_H) */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-09-01 14:36     ` Rafael Espindola
@ 2008-09-02 22:07       ` Diego Novillo
  0 siblings, 0 replies; 9+ messages in thread
From: Diego Novillo @ 2008-09-02 22:07 UTC (permalink / raw)
  To: Rafael Espindola; +Cc: gcc-patches, Cary Coutant

On Mon, Sep 1, 2008 at 10:34, Rafael Espindola <espindola@google.com> wrote:
>> An updated version is attached. Could you please take another look?
>
> Now it is ...

Looks fine.


Thanks.  Diego.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-08-29  8:29   ` Rafael Espindola
@ 2008-12-17 23:11     ` Andrew Pinski
  2008-12-17 23:16       ` Rafael Espindola
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Pinski @ 2008-12-17 23:11 UTC (permalink / raw)
  To: Rafael Espindola
  Cc: Joseph S. Myers, gcc-patches, Cary Coutant, Diego Novillo

On Thu, Aug 28, 2008 at 1:15 AM, Rafael Espindola <espindola@google.com> wrote:
>> Since you are making other use of libtool here, I suggest using its
>> support for dynamic loading (with libltdl when necessary) rather than
>> hardcoding -ldl and so restricting the supported hosts arbitrarily.  (I
>> have not looked at the details of how or why -ldl is being used.)
>
> This is a lto plugin for Gold. I don't think using -ldl is limiting
> the supported platforms. I can change that in the future, but get it
> working is a bigger priority.

More to the point, there could be Windows cross compilers that could
target elf targets.  Think embedded targets where many people use
windows as the host machine.

Thanks,
Andrew Pinski

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [lto][patch] Add initial gold plugin
  2008-12-17 23:11     ` Andrew Pinski
@ 2008-12-17 23:16       ` Rafael Espindola
  0 siblings, 0 replies; 9+ messages in thread
From: Rafael Espindola @ 2008-12-17 23:16 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Joseph S. Myers, gcc-patches, Cary Coutant, Diego Novillo

> More to the point, there could be Windows cross compilers that could
> target elf targets.  Think embedded targets where many people use
> windows as the host machine.

The library is used in a demo program to load the plugin, but is not
used in the plugin.

> Thanks,
> Andrew Pinski
>


Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-12-17 23:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-28 12:09 [lto][patch] Add initial gold plugin Rafael Espindola
2008-08-28 17:36 ` Diego Novillo
2008-09-01 14:35   ` Rafael Espindola
2008-09-01 14:36     ` Rafael Espindola
2008-09-02 22:07       ` Diego Novillo
2008-08-28 20:03 ` Joseph S. Myers
2008-08-29  8:29   ` Rafael Espindola
2008-12-17 23:11     ` Andrew Pinski
2008-12-17 23:16       ` Rafael Espindola

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).