static void drd_report_data_race2(Error* const err, const DataRaceErrInfo* const dri) { AddrInfo ai; const unsigned descr_size = 256; Char* descr1 = VG_(malloc)(descr_size); Char* descr2 = VG_(malloc)(descr_size); tl_assert(dri); tl_assert(dri->addr); tl_assert(dri->size > 0); tl_assert(descr1); tl_assert(descr2); descr1[0] = 0; descr2[0] = 0; VG_(get_data_description)(descr1, descr2, descr_size, dri->addr); if (descr1[0] == 0) { describe_malloced_addr(dri->addr, dri->size, &ai); } VG_(message)(Vg_UserMsg, "Conflicting %s by thread %d/%d at 0x%08lx size %ld", dri->access_type == eStore ? "store" : "load", DrdThreadIdToVgThreadId(dri->tid), dri->tid, dri->addr, dri->size); VG_(pp_ExeContext)(VG_(get_error_where)(err)); if (descr1[0]) { VG_(message)(Vg_UserMsg, "%s", descr1); VG_(message)(Vg_UserMsg, "%s", descr2); } else if (ai.akind == eMallocd && ai.lastchange) { VG_(message)(Vg_UserMsg, "Address 0x%lx is at offset %ld from 0x%lx." " Allocation context:", dri->addr, ai.rwoffset, dri->addr - ai.rwoffset); VG_(pp_ExeContext)(ai.lastchange); } else { VG_(message)(Vg_UserMsg, "Allocation context: unknown."); } if (s_drd_show_conflicting_segments) { thread_report_conflicting_segments(dri->tid, dri->addr, dri->size, dri->access_type); } VG_(free)(descr2); VG_(free)(descr1); }
static void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri) { const Bool xml = VG_(clo_xml); const HChar* const what_prefix = xml ? " <what>" : ""; const HChar* const what_suffix = xml ? "</what>" : ""; const HChar* const auxwhat_prefix = xml ? " <auxwhat>" : ""; const HChar* const auxwhat_suffix = xml ? "</auxwhat>" : ""; const HChar* const indent = xml ? " " : ""; AddrInfo ai; XArray* /* of HChar */ descr1 = VG_(newXA)( VG_(malloc), "drd.error.drdr2.1", VG_(free), sizeof(HChar) ); XArray* /* of HChar */ descr2 = VG_(newXA)( VG_(malloc), "drd.error.drdr2.2", VG_(free), sizeof(HChar) ); tl_assert(dri); tl_assert(dri->addr); tl_assert(dri->size > 0); tl_assert(descr1); tl_assert(descr2); (void) VG_(get_data_description)(descr1, descr2, dri->addr); /* If there's nothing in descr1/2, free them. Why is it safe to to VG_(indexXA) at zero here? Because VG_(get_data_description) guarantees to zero terminate descr1/2 regardless of the outcome of the call. So there's always at least one element in each XA after the call. */ if (0 == VG_(strlen)( VG_(indexXA)( descr1, 0 ))) { VG_(deleteXA)( descr1 ); descr1 = NULL; } if (0 == VG_(strlen)( VG_(indexXA)( descr2, 0 ))) { VG_(deleteXA)( descr2 ); descr2 = NULL; } /* Assume (assert) that VG_(get_data_description) fills in descr1 before it fills in descr2 */ if (descr1 == NULL) tl_assert(descr2 == NULL); /* So anyway. Do we have something useful? */ if (descr1 == NULL) { /* No. Do Plan B. */ describe_malloced_addr(dri->addr, &ai); } print_err_detail("%sConflicting %s by thread %d at 0x%08lx size %ld%s\n", what_prefix, dri->access_type == eStore ? "store" : "load", dri->tid, dri->addr, dri->size, what_suffix); VG_(pp_ExeContext)(VG_(get_error_where)(err)); if (descr1 != NULL) { print_err_detail("%s%s\n", indent, (HChar*)VG_(indexXA)(descr1, 0)); if (descr2 != NULL) print_err_detail("%s%s\n", indent, (HChar*)VG_(indexXA)(descr2, 0)); } else if (ai.akind == eMallocd && ai.lastchange) { print_err_detail("%sAddress 0x%lx is at offset %ld from 0x%lx.%s%s", auxwhat_prefix, dri->addr, ai.rwoffset, dri->addr - ai.rwoffset, auxwhat_suffix, xml ? "\n" : ""); if (xml) print_err_detail(" <allocation_context>\n"); else print_err_detail(" Allocation context:\n"); VG_(pp_ExeContext)(ai.lastchange); if (xml) print_err_detail(" </allocation_context>\n"); } else { HChar sect_name[64]; VgSectKind sect_kind; sect_kind = VG_(DebugInfo_sect_kind)(sect_name, sizeof(sect_name), dri->addr); if (sect_kind != Vg_SectUnknown) { print_err_detail("%sAllocation context: %ps section of %ps%s\n", auxwhat_prefix, VG_(pp_SectKind)(sect_kind), sect_name, auxwhat_suffix); } else { print_err_detail("%sAllocation context: unknown.%s\n", auxwhat_prefix, auxwhat_suffix); } } if (s_show_conflicting_segments) { DRD_(thread_report_conflicting_segments)(dri->tid, dri->addr, dri->size, dri->access_type); } if (descr2) VG_(deleteXA)(descr2); if (descr1) VG_(deleteXA)(descr1); }
static void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri) { AddrInfo ai; XArray* /* of HChar */ descr1 = VG_(newXA)( VG_(malloc), "drd.error.drdr2.1", VG_(free), sizeof(HChar) ); XArray* /* of HChar */ descr2 = VG_(newXA)( VG_(malloc), "drd.error.drdr2.2", VG_(free), sizeof(HChar) ); tl_assert(dri); tl_assert(dri->addr); tl_assert(dri->size > 0); tl_assert(descr1); tl_assert(descr2); (void) VG_(get_data_description)(descr1, descr2, dri->addr); /* If there's nothing in descr1/2, free them. Why is it safe to to VG_(indexXA) at zero here? Because VG_(get_data_description) guarantees to zero terminate descr1/2 regardless of the outcome of the call. So there's always at least one element in each XA after the call. */ if (0 == VG_(strlen)( VG_(indexXA)( descr1, 0 ))) { VG_(deleteXA)( descr1 ); descr1 = NULL; } if (0 == VG_(strlen)( VG_(indexXA)( descr2, 0 ))) { VG_(deleteXA)( descr2 ); descr2 = NULL; } /* Assume (assert) that VG_(get_data_description) fills in descr1 before it fills in descr2 */ if (descr1 == NULL) tl_assert(descr2 == NULL); /* So anyway. Do we have something useful? */ if (descr1 == NULL) { /* No. Do Plan B. */ describe_malloced_addr(dri->addr, dri->size, &ai); } VG_(message)(Vg_UserMsg, "Conflicting %s by thread %d/%d at 0x%08lx size %ld\n", dri->access_type == eStore ? "store" : "load", DRD_(DrdThreadIdToVgThreadId)(dri->tid), dri->tid, dri->addr, dri->size); VG_(pp_ExeContext)(VG_(get_error_where)(err)); if (descr1 != NULL) { VG_(message)(Vg_UserMsg, "%s\n", (HChar*)VG_(indexXA)(descr1, 0)); if (descr2 != NULL) VG_(message)(Vg_UserMsg, "%s\n", (HChar*)VG_(indexXA)(descr2, 0)); } else if (ai.akind == eMallocd && ai.lastchange) { VG_(message)(Vg_UserMsg, "Address 0x%lx is at offset %ld from 0x%lx." " Allocation context:\n", dri->addr, ai.rwoffset, dri->addr - ai.rwoffset); VG_(pp_ExeContext)(ai.lastchange); } else { char sect_name[64]; VgSectKind sect_kind; sect_kind = VG_(seginfo_sect_kind)(sect_name, sizeof(sect_name), dri->addr); if (sect_kind != Vg_SectUnknown) { VG_(message)(Vg_UserMsg, "Allocation context: %s section of %s\n", VG_(pp_SectKind)(sect_kind), sect_name); } else { VG_(message)(Vg_UserMsg, "Allocation context: unknown.\n"); } } if (s_show_conflicting_segments) { DRD_(thread_report_conflicting_segments)(dri->tid, dri->addr, dri->size, dri->access_type); } if (descr2) VG_(deleteXA)(descr2); if (descr1) VG_(deleteXA)(descr1); }