better cfg

This commit is contained in:
Jean-Marie Mineau 2025-04-23 15:52:19 +02:00
parent 5a4504592c
commit 110f0c0215
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 59 additions and 14 deletions

View file

@ -2750,7 +2750,9 @@ impl Apk {
if let Some(try_) = tries.remove(&addr) { if let Some(try_) = tries.remove(&addr) {
insns.push(try_); insns.push(try_);
} }
if let Some(label_l) = labels.remove(&addr) { if let Some(mut label_l) = labels.remove(&addr) {
label_l.sort();
label_l.dedup();
for label in label_l.into_iter() { for label in label_l.into_iter() {
insns.push(Instruction::Label { name: label }); insns.push(Instruction::Label { name: label });
} }

View file

@ -271,8 +271,10 @@ impl<'a> MethodCFG<'a> {
format!("block {i}") format!("block {i}")
}; };
let label = if node.code_block.is_empty() { let label = if node.code_block.is_empty() {
format!("{{\\< {block_name} \\>}}") //format!("{{\\< {block_name} \\>}}")
format!("<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\"><TR><TD><B> {block_name} </B></TD></TR></TABLE>")
} else { } else {
/*
let mut label = format!("{{\\< {block_name} \\>:\\l\\\n"); let mut label = format!("{{\\< {block_name} \\>:\\l\\\n");
for (i, ins) in node.code_block.iter().enumerate() { for (i, ins) in node.code_block.iter().enumerate() {
label += &format!("|<i{i}>"); label += &format!("|<i{i}>");
@ -284,17 +286,38 @@ impl<'a> MethodCFG<'a> {
.replace("\"", "\\\"") .replace("\"", "\\\"")
.replace("{", "\\{") .replace("{", "\\{")
.replace("}", "\\}") .replace("}", "\\}")
//.replace("[", "\\[")
.as_str(); .as_str();
label += "\\l\\\n"; label += "\\l\\\n";
} }
label += "}"; label += "}";
*/
let mut label = format!("<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n <TR><TD PORT=\"blkname\"><B> {block_name} </B></TD></TR>\n");
for (i, ins) in node.code_block.iter().enumerate() {
label += &format!(
" <TR><TD PORT=\"i{i}\">{}</TD></TR>\n",
ins.__str__()
//.replace(" ", "\\ ")
.replace("&", "&amp;")
.replace(">", "&gt;")
.replace("<", "&lt;")
.replace("\"", "&quot;")
//.replace("{", "\\{")
//.replace("}", "\\}")
//.replace("[", "\\[")
.as_str()
);
}
label += " </TABLE>";
label label
}; };
dot_string += &format!( dot_string += &format!(
" node_{i} [shape=record,style=filled,fillcolor=lightgrey,label=\"{label}\"];\n\n" //" node_{i} [shape=record,style=filled,fillcolor=lightgrey,label=\"{label}\"];\n\n"
" node_{i} [shape=plaintext,style=filled,fillcolor=lightgrey,label=<{label}>];\n\n"
); );
} }
dot_string += " node_end [shape=record,style=filled,fillcolor=lightgrey,label=\"{\\< EXIT \\>}\"];\n\n"; //dot_string += " node_end [shape=record,style=filled,fillcolor=lightgrey,label=\"{\\< EXIT \\>}\"];\n\n";
dot_string += " node_end [shape=plaintext,style=filled,fillcolor=lightgrey,label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\"><TR><TD><B> EXIT </B></TD></TR></TABLE>>];\n\n";
for (i, node) in self.nodes.iter().enumerate() { for (i, node) in self.nodes.iter().enumerate() {
for j in &node.next_nodes { for j in &node.next_nodes {

View file

@ -112,20 +112,40 @@ impl MethodCFG<'_> {
dot_string += " color=\"black\";\n"; dot_string += " color=\"black\";\n";
dot_string += " rankdir=\"TB\";\n"; dot_string += " rankdir=\"TB\";\n";
dot_string += &format!( dot_string += &format!(
" label=\"Register Types{}\";\n", " label=\"Register Types for {}\";\n",
self.method.descriptor.__str__() self.method.descriptor.__str__()
); );
for (label, regs) in &types { let mut labels: Vec<_> = types.keys().collect();
labels.sort(); // Order more or less by addresses, good enought
let mut prev = None;
for label in labels.into_iter() {
let regs = types.get(label).unwrap();
let mut node_label = String::new(); let mut node_label = String::new();
for reg in regs { node_label += "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n";
node_label += "|"; node_label += &format!(
node_label += reg.to_str(); " <TR><TD COLSPAN=\"{}\"><B>register types at {label}</B></TD></TR>\n <TR>", regs.len(),
}
node_label += "|";
dot_string += &format!(
" node_{label} [shape=record,style=filled,fillcolor=lightgrey,label=\"{node_label}\"];\n"
); );
for i in 0..regs.len() {
node_label += &format!(" <TD>{i}</TD>\n");
}
node_label += " </TR><TR>\n";
for reg in regs {
//node_label += "|";
//node_label += reg.to_str();
node_label += &format!(" <TD>{}</TD>\n", reg.to_str());
}
//node_label += "|";
node_label += " </TR></TABLE>";
dot_string += &format!(
//" node_{label} [shape=record,style=filled,fillcolor=lightgrey,label=\"{node_label}\"];\n"
" node_{label} [shape=plaintext,style=filled,fillcolor=lightgrey,label=<{node_label}>];\n"
);
if let Some(prev) = prev {
// Add invisible edge to ensure the nodes are verticals
dot_string += &format!(" {prev}:s -> node_{label}:n [style=\"invis\"];\n");
}
prev = Some(format!("node_{label}"));
} }
dot_string += "}\n"; dot_string += "}\n";
@ -135,7 +155,7 @@ impl MethodCFG<'_> {
if let Instruction::Label { name } = ins { if let Instruction::Label { name } = ins {
let mid = self.dot_sanitized_method_dscr(); let mid = self.dot_sanitized_method_dscr();
dot_string += &format!( dot_string += &format!(
" node_{i}:i{j}:e -> node_{name}:w \ " node_{i}:i{j}:e -> node_{name} \
[ltail=cluster_{mid},lhead=cluster_reg_types_{mid},style=\"solid,bold\",color=grey,weight=10,constraint=true];\n", [ltail=cluster_{mid},lhead=cluster_reg_types_{mid},style=\"solid,bold\",color=grey,weight=10,constraint=true];\n",
); );
} }