1f08c3bdfSopenharmony_ci#!/usr/bin/gvpr -f 2f08c3bdfSopenharmony_ci// Compute the reverse partition of the chosen function 3f08c3bdfSopenharmony_ci// 4f08c3bdfSopenharmony_ci// Run with graph ... | return-paths | subg-rev -a functionname 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ciBEGIN { 8f08c3bdfSopenharmony_ci // Find the immediate parent subgraph of this object 9f08c3bdfSopenharmony_ci graph_t find_owner(obj_t o, graph_t g) 10f08c3bdfSopenharmony_ci { 11f08c3bdfSopenharmony_ci graph_t g1; 12f08c3bdfSopenharmony_ci for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1)) 13f08c3bdfSopenharmony_ci if(isIn(g1,o)) return g1; 14f08c3bdfSopenharmony_ci return NULL; 15f08c3bdfSopenharmony_ci } 16f08c3bdfSopenharmony_ci} 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ciBEG_G { 19f08c3bdfSopenharmony_ci graph_t calls[]; // Crude hash table for tracking who calls what 20f08c3bdfSopenharmony_ci graph_t sg = subg ($, "reachable"); 21f08c3bdfSopenharmony_ci graph_t target, g, g2; 22f08c3bdfSopenharmony_ci edge_t e; 23f08c3bdfSopenharmony_ci int i; 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci $tvtype = TV_rev; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci // find the ep corresponding to ARG[0] 28f08c3bdfSopenharmony_ci for (g = fstsubg($G); g; g = nxtsubg(g)) { 29f08c3bdfSopenharmony_ci if(g.fun == ARGV[0]) { 30f08c3bdfSopenharmony_ci node_t n; 31f08c3bdfSopenharmony_ci n = node($,g.ep); 32f08c3bdfSopenharmony_ci $tvroot = n; 33f08c3bdfSopenharmony_ci n.style = "filled"; 34f08c3bdfSopenharmony_ci target = g; 35f08c3bdfSopenharmony_ci break; 36f08c3bdfSopenharmony_ci } 37f08c3bdfSopenharmony_ci } 38f08c3bdfSopenharmony_ci if(!target) { 39f08c3bdfSopenharmony_ci printf(2, "Function %s not found\n", ARGV[0]); 40f08c3bdfSopenharmony_ci exit(1); 41f08c3bdfSopenharmony_ci } 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci // Add the incoming call edges to the allowed call list 44f08c3bdfSopenharmony_ci i = 0; 45f08c3bdfSopenharmony_ci for(e = fstin(n); e; e = nxtin(e)) { 46f08c3bdfSopenharmony_ci if (e.op = "call") { 47f08c3bdfSopenharmony_ci g2 = find_owner(e.tail, $G); 48f08c3bdfSopenharmony_ci calls[sprintf("%s%d", g2.name, ++i)] = g; 49f08c3bdfSopenharmony_ci } 50f08c3bdfSopenharmony_ci } 51f08c3bdfSopenharmony_ci} 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ciE [op == "ret"] { 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci // This is a return edge. Allow the corresponding call 57f08c3bdfSopenharmony_ci g = find_owner(head, $G); 58f08c3bdfSopenharmony_ci i = 0; 59f08c3bdfSopenharmony_ci while(calls[sprintf("%s%d", g.name, ++i)]) { 60f08c3bdfSopenharmony_ci } 61f08c3bdfSopenharmony_ci calls[sprintf("%s%d", g.name, i)] = find_owner(tail, $G); 62f08c3bdfSopenharmony_ci g2 = find_owner(tail, $G); 63f08c3bdfSopenharmony_ci} 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ciN [split == 1] { 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci // Ignore returns back to the target function 69f08c3bdfSopenharmony_ci for (e = fstin($); e; e = nxtin(e)) 70f08c3bdfSopenharmony_ci if (e.op == "ret" && isIn(target,e.tail)) 71f08c3bdfSopenharmony_ci delete($G,e); 72f08c3bdfSopenharmony_ci} 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ciN { 75f08c3bdfSopenharmony_ci $tvroot = NULL; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci for (e = fstin($); e; e = nxtin(e)) { 78f08c3bdfSopenharmony_ci if (e.op == "call") { 79f08c3bdfSopenharmony_ci int found = 0; 80f08c3bdfSopenharmony_ci g = find_owner(e.tail, $G); 81f08c3bdfSopenharmony_ci i = 0; 82f08c3bdfSopenharmony_ci while(calls[sprintf("%s%d", g.name, ++i)]) { 83f08c3bdfSopenharmony_ci if (isIn(calls[sprintf("%s%d", g.name, i)],e.head)) 84f08c3bdfSopenharmony_ci found = 1; 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci g2 = find_owner(e.head, $G); 87f08c3bdfSopenharmony_ci if (!found) delete($G, e); 88f08c3bdfSopenharmony_ci } 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci for (g = fstsubg($G); g; g = nxtsubg(g)) { 92f08c3bdfSopenharmony_ci if(isIn(g,$) && g != sg) { 93f08c3bdfSopenharmony_ci subnode (copy(sg, g), $); 94f08c3bdfSopenharmony_ci } 95f08c3bdfSopenharmony_ci } 96f08c3bdfSopenharmony_ci} 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ciEND_G { 99f08c3bdfSopenharmony_ci induce(sg); 100f08c3bdfSopenharmony_ci write(sg); 101f08c3bdfSopenharmony_ci} 102