Blob Blame History Raw
commit 7cb54ca93cffc949b16611d5b6c66844524143d8
Author: Josh Stone <jistone@redhat.com>
Date:   Thu Oct 17 16:05:25 2013 -0700

    Fix DYNINST_index_lock state and ppc64 writeFunctionPtr
    
    There are two fixes in this patch to resolve hangs that we've seen on
    ppc64 tests, most notably in test_thread_5.
    
    The first is that DYNINST_index_lock may be left in a locked state from
    DYNINSTthreadIndexSLOW when DYNINST_thread_hash_size is 0.  This simply
    needs an unlock in that error path.
    
    The second resolves *why* DYNINST_thread_hash_size is 0, even after it
    was correctly initialized to 40.  This turned out to be corruption when
    the mutator writeFunctionPtr sets DYNINST_pthread_self.  Those symbols
    in libdyninstAPI_RT.so happen to be arranged like so:
    
        0000000000031180 B DYNINST_pthread_self
        0000000000031188 B DYNINST_sysEntry
        0000000000031190 B DYNINST_thread_hash_size
    
    So writeFunctionPtr was sending three longs: the function descriptor
    correctly in DYNINST_pthread_self; the toc in DYNINST_sysEntry, a dead
    variable; and the guilty 0x0 in DYNINST_thread_hash_size.  The only
    thing a function pointer actually needs is the function descriptor.
    
    For comparison, on EL5 and EL6 our build has the symbols like so:
    
        000000000002c400 B DYNINST_pthread_self
        000000000002c408 B DYNINSTlinkSave
        000000000002c410 B DYNINSTtocSave
        000000000002c418 B DYNINST_sysEntry
        000000000002c420 B DYNINST_thread_hash_tids
        000000000002c428 B DYNINST_thread_hash_size
    
    So that still clobbered data, but DYNINSTlinkSave and DYNINSTtocSave are
    both unused variables -- no harm done.
    
    Signed-off-by: Josh Stone <jistone@redhat.com>

diff --git a/dyninstAPI/src/inst-power.C b/dyninstAPI/src/inst-power.C
index c2accaf..74436ec 100644
--- a/dyninstAPI/src/inst-power.C
+++ b/dyninstAPI/src/inst-power.C
@@ -2589,20 +2589,11 @@ bool writeFunctionPtr(AddressSpace *p, Address addr, func_instance *f)
 #else
     // 64-bit ELF PowerPC Linux uses r2 (same as AIX) for TOC base register
     if (p->getAddressWidth() == sizeof(uint64_t)) {
-        Address buffer[3];
         Address val_to_write = f->addr();
         // Use function descriptor address, if available.
         if (f->getPtrAddress()) val_to_write = f->getPtrAddress();
-        assert(p->proc());
-        Address toc = p->proc()->getTOCoffsetInfo(f);
-        buffer[0] = val_to_write;
-        buffer[1] = toc;
-        buffer[2] = 0x0;
-
-        if (!p->writeDataSpace((void *) addr, sizeof(buffer), buffer))
-            fprintf(stderr, "%s[%d]:  writeDataSpace failed\n",
-                            FILE__, __LINE__);
-        return true;
+        return p->writeDataSpace((void *) addr,
+                                 sizeof(val_to_write), &val_to_write);
     }
     else {
         // Originally copied from inst-x86.C
diff --git a/dyninstAPI_RT/src/RTthread.c b/dyninstAPI_RT/src/RTthread.c
index 9897563..2a80f58 100644
--- a/dyninstAPI_RT/src/RTthread.c
+++ b/dyninstAPI_RT/src/RTthread.c
@@ -119,6 +119,7 @@ unsigned DYNINSTthreadIndexSLOW(dyntid_t tid) {
      **/
     if (!DYNINST_thread_hash_size) {
         //Uninitialized tramp guard.
+        tc_lock_unlock(&DYNINST_index_lock);
         return DYNINST_max_num_threads;
     }