EEVblog® Electronics Community Forum
Electronics => Microcontrollers => Topic started by: dobsonr741 on March 13, 2024, 02:17:28 pm
-
What tools are you using visualizing C/C++ codebase? For dependency analysis for C, extracting UML class diagrams for C++.
-
Hi,
I used Doxygen. See link:
https://github.com/nullromo/doxygen-example
Best Regards
-
An abandoned (but excellent) software was sourcetrails:
https://github.com/CoatiSoftware/Sourcetrail
this work fine on my PC from AppImage package but is non maintained software...
-
Yes Doxygen will create call graphs for you. Handy. (Using it for documentation purposes is itself more questionable and you'll find many strong opinions against it, but for analyzing source code and creating call graphs, it's fine.)
Note that if you want more control and don't want to deal with Doxygen altogether, clang can do that for you. You can pair it with Graphviz to get the graphics. More details there: https://stackoverflow.com/questions/5373714/how-to-generate-a-call-graph-for-c-code (https://stackoverflow.com/questions/5373714/how-to-generate-a-call-graph-for-c-code)
You also have CppDepend, but it's not free: https://www.cppdepend.com/ (https://www.cppdepend.com/)
-
How well do those work with function pointers?
Do they presume some coding convention in their use, e.g. FSMs implemented as 2d arrays of function pointers (i.e. event+state=>action)
-
How well do those work with function pointers?
I've described in another thread I like to use ELF tools for this, specifically -fdata-sections -ffunction-sections when compiling source to object files, followed by objdump -tr on the object files to obtain full call graphs, including initialized/immutable data structures with function pointers. This works even when the data structures have only local visibility, and requires no specific coding conventions.
The reason for using per-section data and functions, is that on some architectures, multiple symbols in the same section need additional processing to map correctly. With per-section data objects and functions, no offset calculations are needed, as the section itself yields the source/target name at sufficient precision. Also, run-time modifications to the structures, for example changing a function pointer, cannot be automatically resolved.
I prefer this approach over source-level examination, because I can compile my sources normally (with just the two additional options), with all optimizations I prefer enabled, and observe the actual dependencies from the object code; specifically, the ELF relocation records.
You might wish to try the above with a codebase you already have, to see what the end result looks like. (I recommend explicitly setting LANG=C LC_ALL=C in the environment to ensure no translation, and remembering that the symbol table output is mixed delimited/fixed-width format. The developers recommend against automatically parsing the output –– one can parse the ELF object files directly to do that ––, but for something like this, with an output parser that complains if the input format does not conform to its expectations, it is absolutely fine.)