Skip to content

Commit ac5ae5c

Browse files
tautschnigDaniel Kroening
authored and
Daniel Kroening
committed
Hack to make CPAchecker parse graphml concurrency witnesses
This does likely need more work, but at least got us some points in the past.
1 parent 3713490 commit ac5ae5c

File tree

4 files changed

+80
-25
lines changed

4 files changed

+80
-25
lines changed

regression/cbmc/graphml_witness1/test.desc

-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ main.c
1616
<key attr.name="enterLoopHead" attr.type="boolean" for="edge" id="enterLoopHead">
1717
<default>false</default>
1818
</key>
19-
<key attr.name="threadNumber" attr.type="int" for="node" id="thread">
20-
<default>0</default>
21-
</key>
2219
<key attr.name="sourcecodeLanguage" attr.type="string" for="graph" id="sourcecodelang"/>
2320
<key attr.name="programFile" attr.type="string" for="graph" id="programfile"/>
2421
<key attr.name="programHash" attr.type="string" for="graph" id="programhash"/>

src/goto-programs/graphml_witness.cpp

+65-7
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,61 @@ static bool contains_symbol_prefix(const exprt &expr, const std::string &prefix)
278278
/// counterexample witness
279279
void graphml_witnesst::operator()(const goto_tracet &goto_trace)
280280
{
281+
unsigned int max_thread_idx = 0;
282+
bool trace_has_violation = false;
283+
for(goto_tracet::stepst::const_iterator it = goto_trace.steps.begin();
284+
it != goto_trace.steps.end();
285+
++it)
286+
{
287+
if(it->thread_nr > max_thread_idx)
288+
max_thread_idx = it->thread_nr;
289+
if(it->is_assert() && !it->cond_value)
290+
trace_has_violation = true;
291+
}
292+
281293
graphml.key_values["sourcecodelang"]="C";
282294

283295
const graphmlt::node_indext sink=graphml.add_node();
284296
graphml[sink].node_name="sink";
285-
graphml[sink].thread_nr=0;
286297
graphml[sink].is_violation=false;
287298
graphml[sink].has_invariant=false;
288299

300+
if(max_thread_idx > 0 && trace_has_violation)
301+
{
302+
std::vector<graphmlt::node_indext> nodes;
303+
304+
for(unsigned int i = 0; i <= max_thread_idx + 1; ++i)
305+
{
306+
nodes.push_back(graphml.add_node());
307+
graphml[nodes.back()].node_name = "N" + std::to_string(i);
308+
graphml[nodes.back()].is_violation = i == max_thread_idx + 1;
309+
graphml[nodes.back()].has_invariant = false;
310+
}
311+
312+
for(auto it = nodes.cbegin(); std::next(it) != nodes.cend(); ++it)
313+
{
314+
xmlt edge("edge");
315+
edge.set_attribute("source", graphml[*it].node_name);
316+
edge.set_attribute("target", graphml[*std::next(it)].node_name);
317+
const auto thread_id = std::distance(nodes.cbegin(), it);
318+
xmlt &data = edge.new_element("data");
319+
data.set_attribute("key", "createThread");
320+
data.data = std::to_string(thread_id);
321+
if(thread_id == 0)
322+
{
323+
xmlt &data = edge.new_element("data");
324+
data.set_attribute("key", "enterFunction");
325+
data.data = "main";
326+
}
327+
graphml[*std::next(it)].in[*it].xml_node = edge;
328+
graphml[*it].out[*std::next(it)].xml_node = edge;
329+
}
330+
331+
// we do not provide any further details as CPAchecker does not seem to
332+
// handle more detailed concurrency witnesses
333+
return;
334+
}
335+
289336
// step numbers start at 1
290337
std::vector<std::size_t> step_to_node(goto_trace.steps.size()+1, 0);
291338

@@ -324,14 +371,15 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
324371
std::to_string(it->pc->location_number)+"."+std::to_string(it->step_nr);
325372
graphml[node].file=source_location.get_file();
326373
graphml[node].line=source_location.get_line();
327-
graphml[node].thread_nr=it->thread_nr;
328374
graphml[node].is_violation=
329375
it->type==goto_trace_stept::typet::ASSERT && !it->cond_value;
330376
graphml[node].has_invariant=false;
331377

332378
step_to_node[it->step_nr]=node;
333379
}
334380

381+
unsigned thread_id = 0;
382+
335383
// build edges
336384
for(goto_tracet::stepst::const_iterator
337385
it=goto_trace.steps.begin();
@@ -364,6 +412,7 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
364412
case goto_trace_stept::typet::ASSIGNMENT:
365413
case goto_trace_stept::typet::ASSERT:
366414
case goto_trace_stept::typet::GOTO:
415+
case goto_trace_stept::typet::SPAWN:
367416
{
368417
xmlt edge(
369418
"edge",
@@ -379,6 +428,10 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
379428
xmlt &data_l=edge.new_element("data");
380429
data_l.set_attribute("key", "startline");
381430
data_l.data=id2string(graphml[from].line);
431+
432+
xmlt &data_t=edge.new_element("data");
433+
data_t.set_attribute("key", "threadId");
434+
data_t.data=std::to_string(it->thread_nr);
382435
}
383436

384437
const auto lhs_object = it->get_lhs_object();
@@ -387,11 +440,19 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
387440
lhs_object.has_value())
388441
{
389442
const std::string &lhs_id = id2string(lhs_object->get_identifier());
390-
if(
443+
if(lhs_id.find("pthread_create::thread") != std::string::npos)
444+
{
445+
xmlt &data_t = edge.new_element("data");
446+
data_t.set_attribute("key", "createThread");
447+
data_t.data = std::to_string(++thread_id);
448+
}
449+
else if(
391450
!contains_symbol_prefix(
392451
it->full_lhs_value, SYMEX_DYNAMIC_PREFIX "dynamic_object") &&
393452
!contains_symbol_prefix(
394453
it->full_lhs, SYMEX_DYNAMIC_PREFIX "dynamic_object") &&
454+
lhs_id.find("thread") == std::string::npos &&
455+
lhs_id.find("mutex") == std::string::npos &&
395456
(!it->full_lhs_value.is_constant() ||
396457
!it->full_lhs_value.has_operands() ||
397458
!has_prefix(
@@ -434,7 +495,6 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
434495
case goto_trace_stept::typet::OUTPUT:
435496
case goto_trace_stept::typet::SHARED_READ:
436497
case goto_trace_stept::typet::SHARED_WRITE:
437-
case goto_trace_stept::typet::SPAWN:
438498
case goto_trace_stept::typet::MEMORY_BARRIER:
439499
case goto_trace_stept::typet::ATOMIC_BEGIN:
440500
case goto_trace_stept::typet::ATOMIC_END:
@@ -456,7 +516,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
456516

457517
const graphmlt::node_indext sink=graphml.add_node();
458518
graphml[sink].node_name="sink";
459-
graphml[sink].thread_nr=0;
460519
graphml[sink].is_violation=false;
461520
graphml[sink].has_invariant=false;
462521

@@ -502,7 +561,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
502561
std::to_string(step_nr);
503562
graphml[node].file=source_location.get_file();
504563
graphml[node].line=source_location.get_line();
505-
graphml[node].thread_nr=it->source.thread_nr;
506564
graphml[node].is_violation=false;
507565
graphml[node].has_invariant=false;
508566

@@ -543,6 +601,7 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
543601
case goto_trace_stept::typet::ASSIGNMENT:
544602
case goto_trace_stept::typet::ASSERT:
545603
case goto_trace_stept::typet::GOTO:
604+
case goto_trace_stept::typet::SPAWN:
546605
{
547606
xmlt edge(
548607
"edge",
@@ -587,7 +646,6 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
587646
case goto_trace_stept::typet::OUTPUT:
588647
case goto_trace_stept::typet::SHARED_READ:
589648
case goto_trace_stept::typet::SHARED_WRITE:
590-
case goto_trace_stept::typet::SPAWN:
591649
case goto_trace_stept::typet::MEMORY_BARRIER:
592650
case goto_trace_stept::typet::ATOMIC_BEGIN:
593651
case goto_trace_stept::typet::ATOMIC_END:

src/xmllang/graphml.cpp

+15-14
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ static bool build_graph_rec(
5454
node.node_name=node_name;
5555
node.is_violation=false;
5656
node.has_invariant=false;
57-
node.thread_nr=0;
5857

5958
for(xmlt::elementst::const_iterator
6059
e_it=xml.elements.begin();
@@ -66,8 +65,6 @@ static bool build_graph_rec(
6665
if(e_it->get_attribute("key")=="violation" &&
6766
e_it->data=="true")
6867
node.is_violation=e_it->data=="true";
69-
else if(e_it->get_attribute("key")=="threadNumber")
70-
node.thread_nr=safe_string2unsigned(e_it->data);
7168
else if(e_it->get_attribute("key")=="entry" &&
7269
e_it->data=="true")
7370
entrynode=node_name;
@@ -324,13 +321,24 @@ bool write_graphml(const graphmlt &src, std::ostream &os)
324321
}
325322

326323
// <key attr.name="threadId" attr.type="string" for="edge" id="threadId"/>
327-
// TODO: format for multi-threaded programs not defined yet
328324
{
329325
xmlt &key=graphml.new_element("key");
330-
key.set_attribute("attr.name", "threadNumber");
326+
key.set_attribute("attr.name", "threadId");
331327
key.set_attribute("attr.type", "int");
332-
key.set_attribute("for", "node");
333-
key.set_attribute("id", "thread");
328+
key.set_attribute("for", "edge");
329+
key.set_attribute("id", "threadId");
330+
331+
key.new_element("default").data = "0";
332+
}
333+
334+
// <key attr.name="createThread" attr.type="string"
335+
// for="edge" id="createThread"/>
336+
{
337+
xmlt &key = graphml.new_element("key");
338+
key.set_attribute("attr.name", "createThread");
339+
key.set_attribute("attr.type", "int");
340+
key.set_attribute("for", "edge");
341+
key.set_attribute("id", "createThread");
334342

335343
key.new_element("default").data="0";
336344
}
@@ -503,13 +511,6 @@ bool write_graphml(const graphmlt &src, std::ostream &os)
503511
entry_done=true;
504512
}
505513

506-
if(n.thread_nr!=0)
507-
{
508-
xmlt &entry=node.new_element("data");
509-
entry.set_attribute("key", "threadNumber");
510-
entry.data=std::to_string(n.thread_nr);
511-
}
512-
513514
// <node id="A14">
514515
// <data key="violation">true</data>
515516
// </node>

src/xmllang/graphml.h

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ struct xml_graph_nodet:public graph_nodet<xml_edget>
3232
std::string node_name;
3333
irep_idt file;
3434
irep_idt line;
35-
unsigned thread_nr;
3635
bool is_violation;
3736
bool has_invariant;
3837
std::string invariant;

0 commit comments

Comments
 (0)