summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2018-04-24 15:27:16 +0200
committerMilian Wolff <mail@milianw.de>2018-05-04 23:13:26 +0200
commit2bb51aa4fd46a61c4702f05a5c93e811a5e112ef (patch)
tree410e93c2f7856d2307398066b48c8bbb44019596
parentfba2ae7b2c43d3e706849c8098930683cbd0e322 (diff)
downloadlibunwind-2bb51aa4fd46a61c4702f05a5c93e811a5e112ef.tar.gz
Fix data race on cache hints in find_reg_state
This can be reproduced by using libunwind from multiple threads with UNW_CACHE_GLOBAL cache policy, as e.g. happens by default or when libunwind wasn't build with --enable-per-thread-cache. The call to put_rs_cache unlocks the cache, but we used to access data that needs to be guarded still. So move the call to put_rs_cache down to protect the data properly. Fixes the following data race reported by TSAN: WARNING: ThreadSanitizer: data race (pid=16551) Read of size 2 at 0x7f7dda69ed7a by thread T2: #0 find_reg_state ../../src/dwarf/Gparser.c:939 (libunwind.so. 8+0x000000037254) #1 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:958 (libunwind.so. 8+0x000000037543) #2 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so. 8+0x000000021fdd) #3 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so. 8+0x0000000246cc) #4 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so. 8+0x000000024be7) #5 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so. 8+0x000000025058) #6 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so. 8+0x00000001a6e7) Previous write of size 2 at 0x7f7dda69ed7a by thread T3: #0 find_reg_state ../../src/dwarf/Gparser.c:940 (libunwind.so. 8+0x000000037383) #1 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:958 (libunwind.so. 8+0x000000037543) #2 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so. 8+0x000000021fdd) #3 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so. 8+0x0000000246cc) #4 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so. 8+0x000000024be7) #5 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so. 8+0x000000025058) #6 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so. 8+0x00000001a6e7) Location is global 'local_addr_space' of size 26296 at 0x7f7dda698c60 (libunwind.so.8+0x000000268d7a)
-rw-r--r--src/dwarf/Gparser.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c
index 7ddd8ded..3f79ed4c 100644
--- a/src/dwarf/Gparser.c
+++ b/src/dwarf/Gparser.c
@@ -932,7 +932,6 @@ find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
unsigned short index = -1;
if (cache)
{
- put_rs_cache (c->as, cache, &saved_mask);
if (rs)
{
index = rs - cache->buckets;
@@ -940,6 +939,7 @@ find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
cache->links[c->prev_rs].hint = index + 1;
c->prev_rs = index;
}
+ put_rs_cache (c->as, cache, &saved_mask);
}
if (ret < 0)
return ret;