[PATCH][GOLD] Fix dangling pointer bug due to premature unlock.
Doug Kwan (關振德)
dougkwan@google.com
Tue Jan 25 09:20:00 GMT 2011
Hi
This fixes a bug in which an object is released too early, causing
a pointer to point to unmapped memory. My fix is to move the locking
code to the caller of get_section_contents() and replace the original
locking code with a check. This has been tested on x86_64.
-Doug
2011-01-25 Doug Kwan <dougkwan@google.com>
* gold/icf.cc (get_section_contents): Instead of locking object in
two places, ask caller to lock it before calling. Add an assert
to check that object is locked in the first iteration.
(match_sections): Lock object before calling get_section_contents()
in the first iteration.
-------------- next part --------------
Index: gold/icf.cc
===================================================================
RCS file: /cvs/src/src/gold/icf.cc,v
retrieving revision 1.17
diff -u -u -p -r1.17 icf.cc
--- gold/icf.cc 14 Dec 2010 19:03:30 -0000 1.17
+++ gold/icf.cc 25 Jan 2011 08:36:15 -0000
@@ -221,6 +221,8 @@ preprocess_for_unique_sections(const std
// Parameters :
// FIRST_ITERATION : true if it is the first invocation.
// SECN : Section for which contents are desired.
+// For the first iteration, caller needs to
+// lock the section's object.
// SECTION_NUM : Unique section number of this section.
// NUM_TRACKED_RELOCS : Vector reference to store the number of relocs
// to ICF sections.
@@ -240,13 +242,13 @@ get_section_contents(bool first_iteratio
section_size_type plen;
const unsigned char* contents = NULL;
+ // We access the section's object in the first iteration and that requires
+ // locking. Instead of locking and unlocking in two places here, we require
+ // a caller to lock the object before calling this for the first iteration.
+ gold_assert(!first_iteration || secn.first->is_locked());
+
if (first_iteration)
{
- // Lock the object so we can read from it. This is only called
- // single-threaded from queue_middle_tasks, so it is OK to lock.
- // Unfortunately we have no way to pass in a Task token.
- const Task* dummy_task = reinterpret_cast<const Task*>(-1);
- Task_lock_obj<Object> tl(dummy_task, secn.first);
contents = secn.first->section_contents(secn.second,
&plen,
false);
@@ -373,12 +375,6 @@ get_section_contents(bool first_iteratio
if (!first_iteration)
continue;
- // Lock the object so we can read from it. This is only called
- // single-threaded from queue_middle_tasks, so it is OK to lock.
- // Unfortunately we have no way to pass in a Task token.
- const Task* dummy_task = reinterpret_cast<const Task*>(-1);
- Task_lock_obj<Object> tl(dummy_task, it_v->first);
-
uint64_t secn_flags = (it_v->first)->section_flags(it_v->second);
// This reloc points to a merge section. Hash the
// contents of this section.
@@ -591,6 +587,12 @@ match_sections(unsigned int iteration_nu
if (iteration_num == 1)
{
unsigned int num_relocs = 0;
+
+ // Lock the object so we can read from it. This is only called
+ // single-threaded from queue_middle_tasks, so it is OK to lock.
+ // Unfortunately we have no way to pass in a Task token.
+ const Task* dummy_task = reinterpret_cast<const Task*>(-1);
+ Task_lock_obj<Object> tl(dummy_task, secn.first);
this_secn_contents = get_section_contents(true, secn, i, &num_relocs,
symtab, (*kept_section_id),
section_contents);
More information about the Binutils
mailing list