This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto][patch] Split archives
- From: "Rafael Espindola" <espindola at google dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Cc: "Diego Novillo" <dnovillo at google dot com>
- Date: Thu, 11 Sep 2008 09:28:56 +0100
- Subject: [lto][patch] Split archives
With the attached patch the plugin now splits archives and writes them
to a temporary directory. The file with the resolution points to the
individual object files.
This is less efficient than adding support for archives in lto1, but easier.
2008-09-11 Rafael Avila de Espindola <espindola@google.com>
* lto-plugin.c: Include sys/stat.h, unistd.h anad fcntl.h
(plugin_file_info): Remove file. Add name, fd and handle.
(temp_obj_dir_name): New.
(register_cleanup): New.
(free_1): Close fd.
(free_2): Free name.
(all_symbols_read_handler): Update to work with new plugin_file_info.
(cleanup_handler): New.
(claim_file_handler): Split archives.
(onload): Handle LDPT_REGISTER_CLEANUP_HOOK. Create temporary directory.
* lto-symtab.c (cleanup_handler): New.
(register_cleanup): New.
(tv): Add LDPT_REGISTER_CLEANUP_HOOK entry.
(main): Call cleanup_handler.
Cheers,
--
Rafael Avila de Espindola
Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index 0493b37..1db0363 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -33,6 +33,9 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#include <stdio.h>
#include <inttypes.h>
#include <ar.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
#ifdef HAVE_GELF_H
# include <gelf.h>
@@ -62,16 +65,20 @@ struct plugin_symtab
struct plugin_file_info
{
+ char *name;
+ int fd;
+ void *handle;
Elf *elf;
- struct ld_plugin_input_file file;
struct plugin_symtab symtab;
};
+#define temp_obj_dir_name "tmp_objects"
static ld_plugin_register_claim_file register_claim_file;
static ld_plugin_add_symbols add_symbols;
static ld_plugin_register_all_symbols_read register_all_symbols_read;
static ld_plugin_get_symbols get_symbols;
+static ld_plugin_register_cleanup register_cleanup;
static struct plugin_file_info *claimed_files = NULL;
static unsigned int num_claimed_files = 0;
@@ -212,6 +219,8 @@ free_1 (void)
{
struct plugin_file_info *info = &claimed_files[i];
struct plugin_symtab *symtab = &info->symtab;
+ int t = close (info->fd);
+ assert (t == 0);
free (symtab->syms);
symtab->syms = NULL;
elf_end (info->elf);
@@ -230,6 +239,7 @@ free_2 (void)
struct plugin_file_info *info = &claimed_files[i];
struct plugin_symtab *symtab = &info->symtab;
free (symtab->slots);
+ free (info->name);
}
free (claimed_files);
claimed_files = NULL;
@@ -251,21 +261,19 @@ all_symbols_read_handler (void)
{
struct plugin_file_info *info = &claimed_files[i];
struct plugin_symtab *symtab = &info->symtab;
- struct ld_plugin_input_file *file = &info->file;
struct ld_plugin_symbol *syms = calloc (symtab->nsyms,
sizeof (struct ld_plugin_symbol));
unsigned j;
assert (syms);
- get_symbols (file->handle, symtab->nsyms, syms);
+ get_symbols (info->handle, symtab->nsyms, syms);
for (j = 0; j < info->symtab.nsyms; j++)
{
uint32_t slot = symtab->slots[j];
unsigned int resolution = syms[j].resolution;
- fprintf(f, "%s\n%" PRId64 " %" PRId64 " %d %s\n",
- file->name, (int64_t) file->offset, (int64_t) file->filesize,
- slot, lto_resolution_str[resolution]);
+ fprintf(f, "%s\n%d %s\n",
+ info->name, slot, lto_resolution_str[resolution]);
}
free (syms);
}
@@ -274,6 +282,16 @@ all_symbols_read_handler (void)
return LDPS_OK;
}
+/* Remove temporary files at the end of the link. */
+
+static enum ld_plugin_status
+cleanup_handler (void)
+{
+ int t = system ("rm -rf " temp_obj_dir_name);
+ assert (t == 0);
+ return LDPS_OK;
+}
+
/* Callback used by gold to check if the plugin will claim FILE. Writes
the result in CLAIMED. */
@@ -281,17 +299,50 @@ 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);
+ Elf *elf;
struct plugin_file_info lto_file;
Elf_Data *symtab;
if (file->offset != 0)
{
- elf_rand (elf, file->offset - sizeof (struct ar_hdr));
- Elf *member = elf_begin (file->fd, ELF_C_READ, elf);
- elf_end (elf);
- elf = member;
+ int fd;
+ off_t size = file->filesize;
+ off_t offset;
+
+ static int objnum = 0;
+ const int name_size = 20;
+ char *objname = malloc (name_size);
+ int t = snprintf (objname, name_size, "%s/obj%d.o",
+ temp_obj_dir_name, objnum);
+ assert (t >= 0 && t < name_size);
+ objnum++;
+
+ fd = open(objname, O_RDWR | O_CREAT, 0666);
+ assert (fd > 0);
+ offset = lseek (file->fd, file->offset, SEEK_SET);
+ assert (offset == file->offset);
+ while (size > 0)
+ {
+ ssize_t r, written;
+ char buf[1000];
+ off_t s = sizeof (buf) < size ? sizeof (buf) : size;
+ r = read (file->fd, buf, s);
+ written = write (fd, buf, r);
+ assert (written = r);
+ size -= r;
+ }
+ lto_file.name = objname;
+ lto_file.fd = fd;
+ lto_file.handle = file->handle;
+ }
+ else
+ {
+ lto_file.name = strdup (file->name);
+ lto_file.fd = file->fd;
+ lto_file.handle = file->handle;
}
+ lto_file.elf = elf_begin (lto_file.fd, ELF_C_READ, NULL);
+ elf = lto_file.elf;
*claimed = 0;
@@ -303,8 +354,6 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
return LDPS_OK;
translate (symtab, <o_file.symtab);
- lto_file.file = *file;
- lto_file.elf = elf;
status = add_symbols (file->handle, lto_file.symtab.nsyms,
lto_file.symtab.syms);
@@ -327,6 +376,7 @@ onload (struct ld_plugin_tv *tv)
{
struct ld_plugin_tv *p;
enum ld_plugin_status status;
+ int t;
unsigned version = elf_version (EV_CURRENT);
assert (version != EV_NONE);
@@ -348,21 +398,31 @@ onload (struct ld_plugin_tv *tv)
case LDPT_GET_SYMBOLS:
get_symbols = p->tv_u.tv_get_symbols;
break;
+ case LDPT_REGISTER_CLEANUP_HOOK:
+ register_cleanup = p->tv_u.tv_register_cleanup;
+ break;
default:
break;
}
p++;
}
+ assert (register_cleanup);
assert (register_claim_file);
assert (add_symbols);
status = register_claim_file (claim_file_handler);
assert (status == LDPS_OK);
+ status = register_cleanup (cleanup_handler);
+ assert (status == LDPS_OK);
+
if (register_all_symbols_read)
{
assert (get_symbols);
status = register_all_symbols_read (all_symbols_read_handler);
assert (status == LDPS_OK);
}
+
+ t = mkdir (temp_obj_dir_name, 0777);
+ assert (t == 0);
}
diff --git a/lto-plugin/lto-symtab.c b/lto-plugin/lto-symtab.c
index 0b2116d..4c3cfb1 100644
--- a/lto-plugin/lto-symtab.c
+++ b/lto-plugin/lto-symtab.c
@@ -39,6 +39,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
static ld_plugin_claim_file_handler claim_file_handler;
static ld_plugin_all_symbols_read_handler all_symbols_read_handler;
+static ld_plugin_cleanup_handler cleanup_handler;
static void *plugin_handle;
struct file_handle {
@@ -83,6 +84,15 @@ register_claim_file(ld_plugin_claim_file_handler handler)
return LDPS_OK;
}
+/* Register HANDLER as the callback to removing temporary files. */
+
+static enum ld_plugin_status
+register_cleanup (ld_plugin_cleanup_handler handler)
+{
+ cleanup_handler = handler;
+ return LDPS_OK;
+}
+
/* For a file identified by HANDLE, add NSYMS symbols from SYMS. */
static enum ld_plugin_status
@@ -122,7 +132,9 @@ struct ld_plugin_tv tv[] = {
{LDPT_GET_SYMBOLS,
{.tv_get_symbols = get_symbols}
},
-
+ {LDPT_REGISTER_CLEANUP_HOOK,
+ {.tv_register_cleanup = register_cleanup}
+ },
{0, {0}}
};
@@ -346,6 +358,8 @@ main(int argc, char *argv[])
free_all ();
+ cleanup_handler ();
+
unload_plugin ();
return 0;