Hi!
My question has already been put on this forum quite a few times in
the past years. Still I feel an urge to ask it once more:
--> What is the easiest way to get a complete diagram of all the
relations caller/callee of all the subroutines (including the main
program) and functions in a program?
I am analyzing a program written by a third party. They provided the
sources (F90), but the style of the code is ... different than I would
have used ... (=irreadable). I would hope that there is a compiler
(pgf90? ifort? g95? gfortran?) that generates such a tree with just
one extra switch, but I didn't find any. I tried ftnchek, but wasn't
satisfied with the result. I read about some nice utility named
"pyramid", but that utility requires another utility (graphviz?
vizgraph?) that does not seem to be available for my platform in
binary form and I am too lazy to compile it myself (I fear more
dependencies and I have no root-privileges to install it). What is my
best option?
Arjan
|
|
0
|
|
|
|
Reply
|
arjan.van.dijk (248)
|
6/14/2010 7:28:39 AM |
|
Arjan <arjan.van.dijk@rivm.nl> wrote:
> I read about some nice utility named
> "pyramid", but that utility requires another utility (graphviz?
> vizgraph?) that does not seem to be available for my platform in
> binary form and I am too lazy to compile it myself (I fear more
> dependencies and I have no root-privileges to install it).
Everyone should have a copy of graphviz on their computer anyway ;) eg
http://www.graphviz.org/pub/graphviz/development/doxygen/html/structAgedge__t.htm
IIRC, you only need additional libraries to support particular output formats
eg libpng etc. I have compiled from source to make a personal version
of dot without any hassles.
Just 2c, David Duffy.
--
| David Duffy (MBBS PhD) ,-_|\
| email: davidD@qimr.edu.au ph: INT+61+7+3362-0217 fax: -0101 / *
| Epidemiology Unit, Queensland Institute of Medical Research \_,-._/
| 300 Herston Rd, Brisbane, Queensland 4029, Australia GPG 4D0B994A v
|
|
0
|
|
|
|
Reply
|
David
|
6/14/2010 11:24:59 AM
|
|
"Arjan" <arjan.van.dijk@rivm.nl> wrote in message
news:88efd67c-0bf5-4402-98bc-5d704bfa5a7a@r27g2000yqb.googlegroups.com...
> My question has already been put on this forum quite a few times in
> the past years. Still I feel an urge to ask it once more:
> --> What is the easiest way to get a complete diagram of all the
> relations caller/callee of all the subroutines (including the main
> program) and functions in a program?
In the general case this is impossible. For one thing, the call
graph need not be a tree, as RECURSIVE procedures are in the language
since F90. Since F03, a program unit could pass around arrays of
C_FUNPTRs around and then create procedure pointers from elements
indexed out of such arrays and then invoke the procedures. Since
F08 IIRC one can create procedure pointers to internal procedures
corresponding to different instances of their host procedure. How
do you express that in a call graph?
For that matter, a program may at runtime write code for a function,
link to a compiler in *.dll form, invoke the compiler to create a
*.dll file containing the compiled function, link to that *.dll file,
and then invoke the function that the program composed. This is a
real threat: FASM comes in also a *.dll format, although only in
32-bit form. I think that a program that attempts to generate a
call graph will miss such a function, not to mention all the
functions it may indirectly invoke.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
|
|
0
|
|
|
|
Reply
|
not_valid (1681)
|
6/14/2010 8:34:43 PM
|
|
James Van Buskirk <not_valid@comcast.net> wrote:
(snip, someone wrote)
>> --> What is the easiest way to get a complete diagram of all the
>> relations caller/callee of all the subroutines (including the main
>> program) and functions in a program?
> In the general case this is impossible. For one thing, the call
> graph need not be a tree, as RECURSIVE procedures are in the language
> since F90.
If I have it right, then it is a graph and not a tree.
Then I think a tree would be a directed acyclic graph.
> Since F03, a program unit could pass around arrays of
> C_FUNPTRs around and then create procedure pointers from elements
> indexed out of such arrays and then invoke the procedures. Since
> F08 IIRC one can create procedure pointers to internal procedures
> corresponding to different instances of their host procedure. How
> do you express that in a call graph?
Well, one that you usually want to know is where to look in
the program when something changes. So a link (I believe it is
edge in graph theory) would point the source of the C_FUNPTR.
Though I thought Fortran 2003 had its own procedure pointers,
in addition to C_FUNPTRs. (Mixing Fortran and C is likely
to complicate the generation of the graphical version.)
> For that matter, a program may at runtime write code for a function,
> link to a compiler in *.dll form, invoke the compiler to create a
> *.dll file containing the compiled function, link to that *.dll file,
> and then invoke the function that the program composed. This is a
> real threat: FASM comes in also a *.dll format, although only in
> 32-bit form. I think that a program that attempts to generate a
> call graph will miss such a function, not to mention all the
> functions it may indirectly invoke.
That is certainly possible. There are a lot of older programs,
though, likely back to Fortran 77 or even 66, which one might
try to understand. Having a graphical (printed) tree (or graph)
might help in visualizing the flow.
In most cases using C_FUNPTR or Fortran procedure pointers,
only a small fraction of the calls will use those, especially
in older code.
I believe that there are programs to do it for C and Fortran 77,
though I don't remember them by name.
-- glen
|
|
0
|
|
|
|
Reply
|
gah (12302)
|
6/14/2010 9:52:41 PM
|
|
Hi!
Arjan wrote:
> Hi!
>
> My question has already been put on this forum quite a few times in
> the past years. Still I feel an urge to ask it once more:
>
> --> What is the easiest way to get a complete diagram of all the
> relations caller/callee of all the subroutines (including the main
> program) and functions in a program?
>
Have you tried any of the call graph generators mentioned here?
http://en.wikipedia.org/wiki/Call_graph
I must confess that I've never used it on Fortran code, but on C the egypt
script gave very good results (but it uses Graphviz, though). It works with
the intermediate RTL files generated by gcc, so maybe it will also work with
gfortran generated output (honestly, I've never tried). Since quite some
time has passed since I used it the last time, I don't remember all
details... but if you'd like to try it, you need the compiler option -fdump-
rtl-expand (the -dr option mentioned in the egypt documentation doesn't work
anymore in recent compilers).
Another possibility would be using gprof and the GProf2Dot script
http://code.google.com/p/jrfonseca/wiki/Gprof2Dot
which also uses Graphviz. This one has the advantage to generate even
dynamic call graphs which are pretty sophisticated (color coding of "hot
spots" etc.)
Hope that helps!
Florian
|
|
0
|
|
|
|
Reply
|
fbuerzle (12)
|
6/15/2010 9:23:30 AM
|
|
Some F77 compilers optionally produced a list for each module
(program, function or subroutine) of what external modules were called
or invoked from within each module, in turn. These were also labelled
as being present in the overall compilation by module name, or not
found and so completely external.
I have written my own such source processor not roo long ago and still
use it occasionally.
My MS V3.31 compiler has a switch for doing this on an optional extra
pass, as well as machine code.
But when at IBM in 1961-64, I remember having written a flow diagram
genarator for Fortran source, (FI,II,"3",IV) with rectangles for
process blocks and diamonds for three-way branching decisions all
connected by mainly vertical parallel lines down the right side, or to
arrows with "other page" labels. Maybe someone has it. So it should
not be so hard to do today. Obviously, as pointed out earlier, any
recursive procedure would loop back to its own entry point, but it
would have at least one exit condition route. But I don't see that it
causes any impossibilities.
(I also wrote the program to play tunes on the 1403 print chain,
with a 4-character note code for letter, octave, flat/normal/sharp and
duration, between more useful products).
|
|
0
|
|
|
|
Reply
|
Terence
|
6/15/2010 12:13:05 PM
|
|
>
> Arjan wrote:
>
>> Hi!
>>
>> My question has already been put on this forum quite a few times in
>> the past years. Still I feel an urge to ask it once more:
>>
>> --> What is the easiest way to get a complete diagram of all the
>> relations caller/callee of all the subroutines (including the main
>> program) and functions in a program?
>>
>
I think it's impossible to do any kind of static source code tree
generation for any large program written in modern Fortran . The
only hope is to trap the subroutine entry code and build a dynamic
tree. My 4 reasons for saying this are:
1) With polymorphic variables and type bound procedures the
name of a called routine isn't available until run-time.
2) The rules for generic routine resolution are so intricate
that nobody will be able to write a stand-alone thing to
untangle them. However, since they are compile time resolvable,
you could recover them from some sort of compiler symbolic
output.
3) FORTRAN has allowed routines to be passed in as arguments and
then invoked via the dummy argument name since at least F77.
The same source code "name" can refer to different routines at
run time.
4) Fortran's procedure pointers are similar to 1) and 3).
Dick Hendrickson
|
|
0
|
|
|
|
Reply
|
Dick
|
6/15/2010 5:51:17 PM
|
|
Dick Hendrickson <dick.hendrickson@att.net> wrote:
(snip)
> I think it's impossible to do any kind of static source code tree
> generation for any large program written in modern Fortran .
There are many large old Fortran programs that one might want
to work on. (Maybe only make small changes, though.)
When you first start working with a large program, nothing
looks familiar. A printed tree (or graph) is helpful as you
get to know the program. Many old large programs have a fairly
small tree, if the subroutines are large. Also, with the
Fortran 66 limit of six characters for names, they are often less
descriptive than you would like.
> The only hope is to trap the subroutine entry code and build
> a dynamic tree. My 4 reasons for saying this are:
> 1) With polymorphic variables and type bound procedures the
> name of a called routine isn't available until run-time.
Probably still rare, but maybe not for long.
> 2) The rules for generic routine resolution are so intricate
> that nobody will be able to write a stand-alone thing to
> untangle them. However, since they are compile time resolvable,
> you could recover them from some sort of compiler symbolic
> output.
I would expect much of the generic routines to be leaf routines
(that don't call much else, though likely some system intrinsics).
> 3) FORTRAN has allowed routines to be passed in as arguments and
> then invoked via the dummy argument name since at least F77.
> The same source code "name" can refer to different routines at
> run time.
I believe back to Fortran II, it is, at least, in Fortran 66.
Usually only used once, or at least a small number of times,
even in large programs. If you link to the call using the
name, then one knows where to look.
> 4) Fortran's procedure pointers are similar to 1) and 3).
Yes.
-- glen
|
|
0
|
|
|
|
Reply
|
glen
|
6/15/2010 7:42:35 PM
|
|
"Dick Hendrickson" <dick.hendrickson@att.net> wrote in message
news:87pssnFno2U1@mid.individual.net...
> >
>> Arjan wrote:
>>
>>> Hi!
>>>
>>> My question has already been put on this forum quite a few times in
>>> the past years. Still I feel an urge to ask it once more:
>>>
>>> --> What is the easiest way to get a complete diagram of all the
>>> relations caller/callee of all the subroutines (including the main
>>> program) and functions in a program?
Dynamic call graph construction using a profiler, or a static
call graph analyzer or a tool that combines information from both.
There may not be a lot of tools lying around off-the-shelf that can do this,
especially for Fortran.
> I think it's impossible to do any kind of static source code tree
> generation for any large program written in modern Fortran .
I don't see why modern Fortran should be any different than modern
C in this regard, and we do this for C at the 10 million line scale.
See http://www.semanticdesigns.com/Products/DMS/FlowAnalysis.html
Fortran presents the details with different syntax but not different
problems.
> The only hope is to trap the subroutine entry code and build a dynamic
> tree. My 4 reasons for saying this are:
>
> 1) With polymorphic variables and type bound procedures the
> name of a called routine isn't available until run-time.
This in effect requires "points-to" analysis. The technology
to do this is well understood.
> 2) The rules for generic routine resolution are so intricate
> that nobody
Uh, even the compiler guys? So it isn't "nobody".
> will be able to write a stand-alone thing to
> untangle them. However, since they are compile time resolvable,
> you could recover them from some sort of compiler symbolic
> output.
> 3) FORTRAN has allowed routines to be passed in as arguments and
> then invoked via the dummy argument name since at least F77.
> The same source code "name" can refer to different routines at
> run time.
This is "points-to" analysis again.
> 4) Fortran's procedure pointers are similar to 1) and 3).
.... and again. OK, so it comes in several variants, but they aren't
really very different.
So we're back to, "possible to do". Just don't know if there are
any specific tools to do it.
These guys claim to do at least some this for Fortran:
http://www.scitools.com/
--
Ira Baxter, CTO
www.semanticdesigns.com
>
> Dick Hendrickson
|
|
0
|
|
|
|
Reply
|
Ira
|
6/15/2010 8:27:26 PM
|
|
Ira Baxter <idbaxter@semdesigns.com> wrote:
> "Dick Hendrickson" <dick.hendrickson@att.net> wrote in message
> news:87pssnFno2U1@mid.individual.net...
>> >
>>> Arjan wrote:
>>>
>>>> Hi!
>>>>
>>>> My question has already been put on this forum quite a few times in
>>>> the past years. Still I feel an urge to ask it once more:
>>>>
>>>> --> What is the easiest way to get a complete diagram of all the
>>>> relations caller/callee of all the subroutines (including the main
>>>> program) and functions in a program?
> Dynamic call graph construction using a profiler, or a static
> call graph analyzer or a tool that combines information from both.
> There may not be a lot of tools lying around off-the-shelf that can do this,
> especially for Fortran.
Perhaps
http://kcachegrind.sourceforge.net/
Though it too wants graphviz to be present
Cheers, David Duffy.
|
|
0
|
|
|
|
Reply
|
David
|
6/15/2010 10:23:40 PM
|
|
|
9 Replies
853 Views
(page loaded in 0.169 seconds)
|