* libdw/dwarf_end.c (cu_free): Free str_off_base_lock.
* libdw/libdwP.h (struct Dwarf_CU): Add str_off_base_lock member.
(str_offsets_base_off): Add locking.
* libdw/libdw_findcu.c (__libdw_intern_next_unit): Initialize
str_off_base_lock.
Signed-off-by: Aaron Merey <[email protected]>
---
v3 changes:
This patch replaces v2 04/10. 04/10 added a lock to dwarf_offdie that
was unnecessary but happened to prevent the reporting of a race condition
in str_offsets_base_off. This patch addresses the source of the race
condition.
libdw/dwarf_end.c | 1 +
libdw/libdwP.h | 20 ++++++++++++++++++--
libdw/libdw_findcu.c | 1 +
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 92389c07..d8830823 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -70,6 +70,7 @@ cu_free (void *arg)
Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
rwlock_fini (p->abbrev_lock);
rwlock_fini (p->split_lock);
+ mutex_fini (p->str_off_base_lock);
/* Free split dwarf one way (from skeleton to split). */
if (p->unit_type == DW_UT_skeleton
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index d121914d..27e968ae 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -461,6 +461,10 @@ struct Dwarf_CU
Covers __libdw_find_split_unit. */
rwlock_define(, split_lock);
+ /* Synchronize access to the str_off_base of this Dwarf_CU.
+ Covers __libdw_str_offsets_base_off. */
+ mutex_define(, str_off_base_lock);
+
/* Memory boundaries of this CU. */
void *startp;
void *endp;
@@ -1202,6 +1206,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
Dwarf_Off off = 0;
if (cu != NULL)
{
+ mutex_lock (cu->str_off_base_lock);
if (cu->str_off_base == (Dwarf_Off) -1)
{
Dwarf_Off dwp_offset;
@@ -1216,6 +1221,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
if (dwarf_formudata (&attr, &base) == 0)
{
cu->str_off_base = off + base;
+ mutex_unlock (cu->str_off_base_lock);
return cu->str_off_base;
}
}
@@ -1223,6 +1229,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
if (cu->version < 5)
{
cu->str_off_base = off;
+ mutex_unlock (cu->str_off_base_lock);
return cu->str_off_base;
}
@@ -1230,7 +1237,12 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
dbg = cu->dbg;
}
else
- return cu->str_off_base;
+ {
+ mutex_unlock (cu->str_off_base_lock);
+ return cu->str_off_base;
+ }
+
+ mutex_unlock (cu->str_off_base_lock);
}
/* No str_offsets_base attribute, we have to assume "zero".
@@ -1280,7 +1292,11 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
no_header:
if (cu != NULL)
- cu->str_off_base = off;
+ {
+ mutex_lock (cu->str_off_base_lock);
+ cu->str_off_base = off;
+ mutex_unlock (cu->str_off_base_lock);
+ }
return off;
}
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 613f61c8..1e96110b 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -179,6 +179,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
eu_search_tree_init (&newp->locs_tree);
rwlock_init (newp->abbrev_lock);
rwlock_init (newp->split_lock);
+ mutex_init (newp->str_off_base_lock);
/* v4 debug type units have version == 4 and unit_type == DW_UT_type. */
if (debug_types)
--
2.48.1