Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
executable file
·
121 lines (111 loc) · 4.25 KB

File metadata and controls

executable file
·
121 lines (111 loc) · 4.25 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python3
#
# Author: cbdev <cb@cbcdn.com>
# Reference: https://github.com/cbdevnet/rtl2dot
#
#This program is free software. It comes without any warranty, to
#the extent permitted by applicable law. You can redistribute it
#and/or modify it under the terms of the Do What The Fuck You Want
#To Public License, Version 2, as published by Sam Hocevar and
#reproduced below.
#
#DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
#Version 2, December 2004
#
#Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
#
# Everyone is permitted to copy and distribute verbatim or modified
# copies of this license document, and changing it is allowed as long
# as the name is changed.
#
#DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
#TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHAT THE FUCK YOU WANT TO.
#
import fileinput
import re
import sys
root = "main"
ignore = None
infiles = []
local = False
indirects = False
i = 1
# There probably should be sanity checks here, but lets face it: If you cant pass arguments right, this isnt for you
while i < len(sys.argv):
if sys.argv[i] == "--ignore":
ignore = re.compile(sys.argv[i + 1])
i += 1
elif sys.argv[i] == "--root":
root = sys.argv[i + 1]
i += 1
elif sys.argv[i] == "--local":
local = True
elif sys.argv[i] == "--indirect":
indirects = True
elif sys.argv[i] == "--help" or sys.argv[i] == "-h":
print("Generate call graphs of C programs from gcc rtldumps")
print("Options:")
print("\t--ignore <regex>\t\tFunctions to omit from the resulting graph")
print("\t--root <function>\t\tWhich function to use as root node (default: main)")
print("\t--local\t\t\t\tOmit functions not defined in the dump (eg. library calls)")
print("\t--indirect\t\t\tDraw a dashed line when the address of a function is taken")
sys.exit(0)
else:
infiles.append(sys.argv[i])
i += 1
current = ""
calls = {}
func_old = re.compile("^;; Function (?P<func>\S+)\s*$")
func_new = re.compile("^;; Function (?P<mangle>.*)\s+\((?P<func>\S+)(,.*)?\).*$")
funcall = re.compile("^.*\(call.*\"(?P<target>.*)\".*$")
symref = re.compile("^.*\(symbol_ref.*\"(?P<target>.*)\".*$")
def enter(func):
global current, calls
current = func
if calls.get(current, None) is not None:
print("Ambiguous function name " + current, file=sys.stderr)
else:
calls[current] = {}
def call(func, facility):
global calls
if calls[current].get(func, None) is not None and calls[current][func] != facility:
print("Ambiguous calling reference to " + func, file=sys.stderr)
calls[current][func] = facility
def dump(func):
global calls
if calls.get(func, None) is None:
# edge node
return
for ref in calls[func].keys():
if calls[func][ref] is not None:
style = "" if calls[func][ref] == "call" else ' [style="dashed"]'
if local and calls.get(ref, None) is None:
# non-local function
continue
if not indirects and calls[func][ref] == "ref":
# indirect reference, but not requested
continue
if ignore is None or re.match(ignore, ref) is None:
# Invalidate the reference to avoid loops
calls[func][ref] = None
print('"' + func + '" -> "' + ref + '"' + style + ';')
dump(ref)
# Scan the rtl dump into the dict
for line in fileinput.input(infiles):
if re.match(func_old, line) is not None:
# print "OLD", re.match(func_old, line).group("func")
enter(re.match(func_old, line).group("func"))
elif re.match(func_new, line) is not None:
# print "NEW", re.match(func_new, line).group("func"), "Mangled:", re.match(func_new, line).group("mangle")
enter(re.match(func_new, line).group("func"))
elif re.match(funcall, line) is not None:
# print "CALL", re.match(funcall, line).group("target")
call(re.match(funcall, line).group("target"), "call")
elif re.match(symref, line) is not None:
# print "REF", re.match(symref, line).group("target")
call(re.match(symref, line).group("target"), "ref")
print("digraph callgraph {")
dump(root)
print("}")
Morty Proxy This is a proxified and sanitized view of the page, visit original site.