Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Caren Kresse
callgraph
Commits
7885386d
Commit
7885386d
authored
May 15, 2021
by
Carsten Emde
Browse files
Added option (-x) to force output of symbols in use, unused symbols are
suppressed
parent
012b3ccd
Changes
4
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
7885386d
cypherdir
gexfdir
gvdir
testdir
textdir
README.md
View file @
7885386d
...
...
@@ -58,6 +58,8 @@ Copyright 2021 - Open Source Automation Development Lab (OSADL) eG, author Carst
-t FILE, --targets FILE
only examine file or comma-separated list of files
-x, --symbols include symbols and their relations (default when format is 'cypher')
-v, --verbose be more verbose about what the program is actually doing
# Scope
...
...
@@ -89,6 +91,26 @@ line options, e.g.
dot -Nfontname=Korolev -Nfontsize=16 -Tpdf callgraph-output.gv >/tmp/gv-display.pdf
There is also a Graphviz live visual editor
# Getting the Graphviz live visual editor from
https://github.com/magjac/graphviz-visual-editor
and follow the installations instructions
1 git clone https://github.com/magjac/graphviz-visual-editor
2.
cd graphviz-visual-editor
3.
npm install
4.
make
5.
npm run start
You may then access the Graphviz visual editor by entering
https://localhost:3000
into your browser of choice.
# Getting Neo4J (tested with version 3.4.9 community edition)
Get the community edition at:
...
...
generatecypher.py
View file @
7885386d
...
...
@@ -64,7 +64,7 @@ def notarget(filename, limitsearch):
def
createoutput
(
outputdir
,
outputformat
,
machine_to_binary
,
linked_libraries
,
filename_to_full_path
,
elf_to_exported_symbols
,
elf_to_imported_symbols
,
symlink_to_target
,
targets
):
elf_to_imported_symbols
,
symlink_to_target
,
targets
,
forcesymbols
):
'''Create an output file for each set of ELF files that belongs together'''
# create an output file for each architecture/operating system
...
...
@@ -90,7 +90,11 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
if
limit
not
in
linked_libraries
:
continue
for
lib
in
linked_libraries
[
limit
]:
fullfilenames
=
filename_to_full_path
[
lib
]
try
:
fullfilenames
=
filename_to_full_path
[
lib
]
except
:
print
(
"Warning: '%s' not found in file system"
%
(
lib
))
continue
for
fullfilename
in
fullfilenames
:
if
fullfilename
in
symlink_to_target
:
fullfilename
=
symlink_to_target
[
fullfilename
]
...
...
@@ -154,7 +158,7 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
outputfileopen
.
write
(
"<graph defaultedgetype=
\"
directed
\"
idtype=
\"
string
\"
type=
\"
static
\"
>
\n
"
)
outputfileopen
.
write
(
"<nodes>
\n
"
)
elif
outputformat
==
'gv'
:
outputfileopen
.
write
(
"digraph "
+
os
.
path
.
basename
(
limitsearch
[
0
])
+
" {
\n
ratio=0.562
\n
"
)
outputfileopen
.
write
(
"digraph "
+
os
.
path
.
basename
(
limitsearch
[
0
])
+
" {
\n
ratio=0.562
;
\n
"
)
seenfirst
=
False
...
...
@@ -206,14 +210,20 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
print
(
"Warning: Library '%s' of file '%s' not found in file system"
%
(
l
,
filename
))
continue
#pass
outputfileopen
.
write
(
newline
)
if
seenfirst
:
outputfileopen
.
write
(
newline
)
else
:
seenfirst
=
True
if
outputformat
==
'cypher'
:
outputfileopen
.
write
(
"(%s)-[:LINKSWITH]->(%s)"
%
(
elf_to_placeholder
[
filename
],
elf_to_placeholder
[
fl
]))
elif
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"<edge id=
\"
%s
\"
source=
\"
%s
\"
target=
\"
%s
\"
label=
\"
links with
\"
/>"
%
(
elf_to_placeholder
[
filename
]
+
elf_to_placeholder
[
fl
],
elf_to_placeholder
[
filename
],
elf_to_placeholder
[
fl
]))
elif
outputformat
==
'gv'
:
outputfileopen
.
write
(
" %s -> %s;"
%
(
elf_to_placeholder
[
filename
],
elf_to_placeholder
[
fl
]))
if
forcesymbols
:
outputfileopen
.
write
(
" %s -> %s [label=
\"
links with
\"
];"
%
(
elf_to_placeholder
[
filename
],
elf_to_placeholder
[
fl
]))
else
:
outputfileopen
.
write
(
" %s -> %s;"
%
(
elf_to_placeholder
[
filename
],
elf_to_placeholder
[
fl
]))
elif
outputformat
==
'text'
:
outputfileopen
.
write
(
"%s LINKSWITH %s"
%
(
filename
,
fl
))
if
fl
not
in
linked_from
:
...
...
@@ -225,9 +235,12 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
if
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"
\n
</edges>"
)
if
outputformat
!=
'cypher'
:
if
outputformat
!=
'cypher'
and
not
forcesymbols
:
continue
;
if
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"
\n
<nodes>"
)
# then add all the exported symbols just once
tmpexportsymbols
=
set
()
...
...
@@ -242,6 +255,18 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
continue
if
exp
[
'type'
]
==
'DATA'
:
continue
symbolinuse
=
False
for
otherfilename
in
machine_to_binary
[
architecture
][
o
][
endian
][
elfclass
]:
if
otherfilename
==
filename
or
notarget
(
otherfilename
,
limitsearch
):
continue
for
imp
in
elf_to_imported_symbols
[
otherfilename
]:
if
imp
[
'bind'
]
!=
'LOCAL'
and
imp
[
'bind'
]
!=
'WEAK'
and
exp
[
'name'
]
==
imp
[
'name'
]:
symbolinuse
=
True
break
if
symbolinuse
:
break
if
not
symbolinuse
:
continue
if
'name'
in
exp
and
'type'
in
exp
and
'bind'
in
exp
:
tmpexportsymbols
.
add
((
exp
[
'name'
],
exp
[
'type'
],
exp
[
'bind'
]))
else
:
...
...
@@ -260,8 +285,18 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
break
symbol_to_placeholder
[(
symbolname
,
symboltype
)]
=
placeholdername
all_placeholder_names
.
add
(
placeholdername
)
outputfileopen
.
write
(
newline
)
outputfileopen
.
write
(
"(%s:SYMBOL {name: '%s', type: '%s'})"
%
(
symbol_to_placeholder
[(
symbolname
,
symboltype
)],
symbolname
,
symboltype
))
if
outputformat
!=
'text'
:
outputfileopen
.
write
(
newline
)
if
outputformat
==
'cypher'
:
outputfileopen
.
write
(
"(%s:SYMBOL {name: '%s', type: '%s'})"
%
(
symbol_to_placeholder
[(
symbolname
,
symboltype
)],
symbolname
,
symboltype
))
elif
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"<node id=
\"
%s
\"
label=
\"
%s
\"
/>"
%
(
symbol_to_placeholder
[(
symbolname
,
symboltype
)],
symbolname
))
elif
outputformat
==
'gv'
:
outputfileopen
.
write
(
" %s [label=
\"
%s
\"
tooltip=
\"
%s
\"
];"
%
(
symbol_to_placeholder
[(
symbolname
,
symboltype
)],
symbolname
,
symboltype
))
if
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"
\n
</nodes>"
)
outputfileopen
.
write
(
"
\n
<edges>"
)
# then declare for all the symbols which are exported
for
filename
in
machine_to_binary
[
architecture
][
o
][
endian
][
elfclass
]:
...
...
@@ -289,7 +324,17 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
if
not
symbolinuse
:
continue
outputfileopen
.
write
(
newline
)
outputfileopen
.
write
(
"(%s)-[:EXPORTS]->(%s)"
%
(
elf_to_placeholder
[
filename
],
symbol_to_placeholder
[(
exp
[
'name'
],
exp
[
'type'
])]))
if
outputformat
==
'cypher'
:
outputfileopen
.
write
(
"(%s)-[:EXPORTS]->(%s)"
%
(
elf_to_placeholder
[
filename
],
symbol_to_placeholder
[(
exp
[
'name'
],
exp
[
'type'
])]))
elif
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"<edge source=
\"
%s
\"
target=
\"
%s
\"
label=
\"
exports
\"
/>"
%
(
elf_to_placeholder
[
filename
],
symbol_to_placeholder
[(
exp
[
'name'
],
exp
[
'type'
])]))
elif
outputformat
==
'gv'
:
outputfileopen
.
write
(
" %s -> %s [label=
\"
exports
\"
];"
%
(
elf_to_placeholder
[
filename
],
symbol_to_placeholder
[(
exp
[
'name'
],
exp
[
'type'
])]))
elif
outputformat
==
'text'
:
outputfileopen
.
write
(
"%s EXPORTS %s"
%
(
filename
,
exp
[
'name'
]))
exportedsymbols
+=
1
if
exportedsymbols
==
0
and
targets
!=
[]
and
filename
not
in
targets
:
files_without_exports
.
add
(
filename
)
...
...
@@ -321,10 +366,24 @@ def createoutput(outputdir, outputformat, machine_to_binary, linked_libraries,
usage
=
"UNUSES"
else
:
usage
=
"USES"
outputfileopen
.
write
(
"(%s)-[:%s]->(%s)"
%
(
elf_to_placeholder
[
filename
],
usage
,
symbol_to_placeholder
[(
imp
[
'name'
],
imp
[
'type'
])]))
else
:
# something is horribly wrong here
pass
if
outputformat
==
'cypher'
:
outputfileopen
.
write
(
"(%s)-[:%s]->(%s)"
%
(
elf_to_placeholder
[
filename
],
usage
,
symbol_to_placeholder
[(
imp
[
'name'
],
imp
[
'type'
])]))
elif
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"<edge source=
\"
%s
\"
target=
\"
%s
\"
label=
\"
%s
\"
/>"
%
(
elf_to_placeholder
[
filename
],
symbol_to_placeholder
[(
imp
[
'name'
],
imp
[
'type'
])],
usage
.
lower
()))
elif
outputformat
==
'gv'
:
outputfileopen
.
write
(
" %s -> %s [label=
\"
%s
\"
];"
%
(
elf_to_placeholder
[
filename
],
symbol_to_placeholder
[(
imp
[
'name'
],
imp
[
'type'
])],
usage
.
lower
()))
elif
outputformat
==
'text'
:
outputfileopen
.
write
(
"%s %s %s"
%
(
filename
,
usage
,
imp
[
'name'
]))
else
:
# something is horribly wrong here
pass
if
outputformat
==
'gexf'
:
outputfileopen
.
write
(
"
\n
</edges>"
)
if
outputformat
==
'cypher'
:
outputfileopen
.
write
(
";
\n
"
)
elif
outputformat
==
'text'
:
...
...
@@ -357,6 +416,9 @@ def main(argv):
parser
.
add_argument
(
"-t"
,
"--targets"
,
action
=
"store"
,
dest
=
"targets"
,
help
=
"only examine file or comma-separated list of files"
,
metavar
=
"FILE"
)
parser
.
add_argument
(
"-x"
,
"--symbols"
,
action
=
"store_true"
,
dest
=
"forcesymbols"
,
default
=
False
,
help
=
"include symbols and their relations (default when format is 'cypher')"
)
parser
.
add_argument
(
"-v"
,
"--verbose"
,
action
=
"store_true"
,
dest
=
"verbose"
,
default
=
False
,
help
=
"be more verbose about what the program is actually doing"
)
...
...
@@ -709,7 +771,7 @@ def main(argv):
createoutput
(
outputdir
,
outputformat
,
machine_to_binary
,
linked_libraries
,
filename_to_full_path
,
elf_to_exported_symbols
,
elf_to_imported_symbols
,
symlink_to_target
,
args
.
targets
)
args
.
targets
,
args
.
forcesymbols
)
if
__name__
==
"__main__"
:
main
(
sys
.
argv
)
graph.config
View file @
7885386d
...
...
@@ -6,9 +6,9 @@ cypherdir = cypherdir
textdir
=
textdir
[
gexf
]
gexfdir
=
gexfdir
gexfdir
=
gexfdir
[
gv
]
gvdir
=
gvdir
gvdir
=
gvdir
[
neo4j
]
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment