Commit 7208f4b6 authored by pcc's avatar pcc Committed by Commit bot

Gold: Patch linker to fix LTO related bugs.

Also ship the LTO plugin header so we can build LLVM against it.

BUG=453195
R=thakis@chromium.org
CC=thestig@chromium.org

Review URL: https://codereview.chromium.org/899783003

Cr-Commit-Position: refs/heads/master@{#314741}
parent c7c37ff3
fd80d8d02666517d0781d3039499b4131e5d3e4e e73c227c9cfacfc5fecaa22ee3555b90925f96c2
\ No newline at end of file \ No newline at end of file
905e9e6eb9b0e11f0587177cfbaf9f7822736f34 05497e34b29c01dd82df76d2fbdf017d4a2c4214
\ No newline at end of file \ No newline at end of file
...@@ -19,5 +19,11 @@ Local patches: ...@@ -19,5 +19,11 @@ Local patches:
* ehframe-race.patch for http://crbug.com/161942 from upstream change * ehframe-race.patch for http://crbug.com/161942 from upstream change
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=635aa30e3ae9735e362cfd1cda2be9f7b65b32a2 https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=635aa30e3ae9735e362cfd1cda2be9f7b65b32a2
* unlock-thin.patch for http://crbug.com/453195 from upstream change
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=2cfbf2fece582c29df348104b28677c38a8301f4
* plugin-dso-fix.patch for http://crbug.com/453195 from upstream change
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
* (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils * (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils
binaries and uploading them to Google storage. binaries and uploading them to Google storage.
...@@ -44,6 +44,8 @@ if [ ! -d binutils-$VERSION ]; then ...@@ -44,6 +44,8 @@ if [ ! -d binutils-$VERSION ]; then
( (
cd binutils-$VERSION cd binutils-$VERSION
patch -p1 < ../ehframe-race.patch patch -p1 < ../ehframe-race.patch
patch -p1 < ../unlock-thin.patch
patch -p1 < ../plugin-dso-fix.patch
) )
fi fi
...@@ -106,6 +108,10 @@ for ARCH in i386 amd64; do ...@@ -106,6 +108,10 @@ for ARCH in i386 amd64; do
# Copy them out of the chroot # Copy them out of the chroot
cp -a "$BUILDDIR/output/$ARCHNAME" "$OUTPUTDIR" cp -a "$BUILDDIR/output/$ARCHNAME" "$OUTPUTDIR"
# Copy plugin header out of the chroot
mkdir "$OUTPUTDIR/$ARCHNAME/include"
cp "$BUILDDIR/binutils-$VERSION/include/plugin-api.h" "$OUTPUTDIR/$ARCHNAME/include/"
# Clean up chroot # Clean up chroot
sudo rm -rf "$BUILDDIR" sudo rm -rf "$BUILDDIR"
done done
......
commit 3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
Author: Peter Collingbourne <pcc@google.com>
Date: Wed Feb 4 09:47:28 2015 -0800
Resolve forwarding symbols in plugins.
2015-02-04 Peter Collingbourne <pcc@google.com>
* plugin.cc (Pluginobj::get_symbol_resolution_info): Resolve
forwarding symbols when computing symbol resolution info for plugins.
diff --git a/gold/plugin.cc b/gold/plugin.cc
index bde8c78..68da8e3 100644
--- a/gold/plugin.cc
+++ b/gold/plugin.cc
@@ -914,7 +914,8 @@ is_visible_from_outside(Symbol* lsym)
// Get symbol resolution info.
ld_plugin_status
-Pluginobj::get_symbol_resolution_info(int nsyms,
+Pluginobj::get_symbol_resolution_info(Symbol_table* symtab,
+ int nsyms,
ld_plugin_symbol* syms,
int version) const
{
@@ -943,6 +944,8 @@ Pluginobj::get_symbol_resolution_info(int nsyms,
{
ld_plugin_symbol* isym = &syms[i];
Symbol* lsym = this->symbols_[i];
+ if (lsym->is_forwarder())
+ lsym = symtab->resolve_forwards(lsym);
ld_plugin_symbol_resolution res = LDPR_UNKNOWN;
if (lsym->is_undefined())
@@ -1511,14 +1514,16 @@ static enum ld_plugin_status
get_symbols(const void* handle, int nsyms, ld_plugin_symbol* syms)
{
gold_assert(parameters->options().has_plugins());
- Object* obj = parameters->options().plugins()->object(
+ Plugin_manager* plugins = parameters->options().plugins();
+ Object* obj = plugins->object(
static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
if (obj == NULL)
return LDPS_ERR;
Pluginobj* plugin_obj = obj->pluginobj();
if (plugin_obj == NULL)
return LDPS_ERR;
- return plugin_obj->get_symbol_resolution_info(nsyms, syms, 1);
+ Symbol_table* symtab = plugins->symtab();
+ return plugin_obj->get_symbol_resolution_info(symtab, nsyms, syms, 1);
}
// Version 2 of the above. The only difference is that this version
@@ -1528,14 +1533,16 @@ static enum ld_plugin_status
get_symbols_v2(const void* handle, int nsyms, ld_plugin_symbol* syms)
{
gold_assert(parameters->options().has_plugins());
- Object* obj = parameters->options().plugins()->object(
+ Plugin_manager* plugins = parameters->options().plugins();
+ Object* obj = plugins->object(
static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
if (obj == NULL)
return LDPS_ERR;
Pluginobj* plugin_obj = obj->pluginobj();
if (plugin_obj == NULL)
return LDPS_ERR;
- return plugin_obj->get_symbol_resolution_info(nsyms, syms, 2);
+ Symbol_table* symtab = plugins->symtab();
+ return plugin_obj->get_symbol_resolution_info(symtab, nsyms, syms, 2);
}
// Add a new (real) input file generated by a plugin.
diff --git a/gold/plugin.h b/gold/plugin.h
index ef78b84..f926879 100644
--- a/gold/plugin.h
+++ b/gold/plugin.h
@@ -282,6 +282,10 @@ class Plugin_manager
input_objects() const
{ return this->input_objects_; }
+ Symbol_table*
+ symtab()
+ { return this->symtab_; }
+
Layout*
layout()
{ return this->layout_; }
@@ -396,7 +400,8 @@ class Pluginobj : public Object
// Fill in the symbol resolution status for the given plugin symbols.
ld_plugin_status
- get_symbol_resolution_info(int nsyms,
+ get_symbol_resolution_info(Symbol_table* symtab,
+ int nsyms,
ld_plugin_symbol* syms,
int version) const;
commit 2cfbf2fece582c29df348104b28677c38a8301f4
Author: Cary Coutant <ccoutant@google.com>
Date: Tue Feb 3 19:54:57 2015 -0800
Fix a file descriptor leak in gold.
When an LTO linker plugin claims an external member of a thin archive, gold
does not properly unlock the file and make its file descriptor available for
reuse. This patch fixes the problem by modifying Archive::include_member to
unlock the object file via an RAII class instance, ensuring that it will be
unlocked no matter what path is taken through the function.
gold/
PR gold/15660
* archive.cc (Thin_archive_object_unlocker): New class.
(Archive::include_member): Unlock external members of thin archives.
* testsuite/Makefile.am (plugin_test_1): Rename .syms files.
(plugin_test_2): Likewise.
(plugin_test_3): Likewise.
(plugin_test_4): Likewise.
(plugin_test_5): Likewise.
(plugin_test_6): Likewise.
(plugin_test_7): Likewise.
(plugin_test_8): Likewise.
(plugin_test_9): Likewise.
(plugin_test_10): Likewise.
(plugin_test_11): New test case.
* testsuite/Makefile.in: Regenerate.
* testsuite/plugin_test.c (claim_file_hook): Check for parallel .syms
file to decide whether to claim file.
(all_symbols_read_hook): Likewise.
* testsuite/plugin_test_1.sh: Adjust expected output.
* testsuite/plugin_test_2.sh: Likewise.
* testsuite/plugin_test_3.sh: Likewise.
* testsuite/plugin_test_6.sh: Likewise.
* testsuite/plugin_test_tls.sh: Likewise.
* testsuite/plugin_test_11.sh: New testcase.
diff --git a/gold/archive.cc b/gold/archive.cc
index 69107f5..6d25980 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -930,6 +930,32 @@ Archive::count_members()
return ret;
}
+// RAII class to ensure we unlock the object if it's a member of a
+// thin archive. We can't use Task_lock_obj in Archive::include_member
+// because the object file is already locked when it's opened by
+// get_elf_object_for_member.
+
+class Thin_archive_object_unlocker
+{
+ public:
+ Thin_archive_object_unlocker(const Task *task, Object* obj)
+ : task_(task), obj_(obj)
+ { }
+
+ ~Thin_archive_object_unlocker()
+ {
+ if (this->obj_->offset() == 0)
+ this->obj_->unlock(this->task_);
+ }
+
+ private:
+ Thin_archive_object_unlocker(const Thin_archive_object_unlocker&);
+ Thin_archive_object_unlocker& operator=(const Thin_archive_object_unlocker&);
+
+ const Task* task_;
+ Object* obj_;
+};
+
// Include an archive member in the link. OFF is the file offset of
// the member header. WHY is the reason we are including this member.
// Return true if we added the member or if we had an error, return
@@ -978,6 +1004,10 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
return unconfigured ? false : true;
}
+ // If the object is an external member of a thin archive,
+ // unlock it when we're done here.
+ Thin_archive_object_unlocker unlocker(this->task_, obj);
+
if (mapfile != NULL)
mapfile->report_include_archive_member(obj->name(), sym, why);
@@ -991,31 +1021,21 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
if (!input_objects->add_object(obj))
{
- // If this is an external member of a thin archive, unlock the
- // file.
- if (obj->offset() == 0)
- obj->unlock(this->task_);
delete obj;
+ return true;
}
- else
- {
- {
- if (layout->incremental_inputs() != NULL)
- layout->incremental_inputs()->report_object(obj, 0, this, NULL);
- Read_symbols_data sd;
- obj->read_symbols(&sd);
- obj->layout(symtab, layout, &sd);
- obj->add_symbols(symtab, &sd, layout);
- }
-
- // If this is an external member of a thin archive, unlock the file
- // for the next task.
- if (obj->offset() == 0)
- obj->unlock(this->task_);
- this->included_member_ = true;
- }
+ if (layout->incremental_inputs() != NULL)
+ layout->incremental_inputs()->report_object(obj, 0, this, NULL);
+
+ {
+ Read_symbols_data sd;
+ obj->read_symbols(&sd);
+ obj->layout(symtab, layout, &sd);
+ obj->add_symbols(symtab, &sd, layout);
+ }
+ this->included_member_ = true;
return true;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment