fundamental / stoat Goto Github PK
View Code? Open in Web Editor NEWSTatic (LLVM) Object file Analysis Tool
License: GNU General Public License v3.0
STatic (LLVM) Object file Analysis Tool
License: GNU General Public License v3.0
This could make it easier to turn on and off annotations
Some typechecks and exception handling should be added to the YAML loading to provide clear errors and debugging information when the ruby layer reads in malformed files produced by the LLVM passes. See #38 as an example of one case where these improved errors would have helped.
The class which is not properly handled is calf_plugins::audio_module_iface
macOS uses Clang as the default compiler for the platform but omits LLVM tools required to build this project. The homebrew package manager provides LLVM with an option to use environment variables for programs like stoat which need to link to LLVM libraries. Building fails with the following output. My system details follow.
[lazzarello@strop build (master)]$ cmake ..
-- The C compiler identification is AppleClang 8.0.0.8000042
-- The CXX compiler identification is AppleClang 8.0.0.8000042
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found LLVM: -lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMSymbolize -lLLVMDebugInfoPDB -lLLVMDebugInfoDWARF -lLLVMMIRParser -lLLVMCoverage -lLLVMTableGen -lLLVMDlltoolDriver -lLLVMOrcJIT -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMXCoreAsmPrinter -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSystemZAsmPrinter -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMSparcAsmPrinter -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMPowerPCAsmPrinter -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMNVPTXAsmPrinter -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMLanaiDisassembler -lLLVMLanaiCodeGen -lLLVMLanaiAsmParser -lLLVMLanaiDesc -lLLVMLanaiAsmPrinter -lLLVMLanaiInfo -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen -lLLVMHexagonAsmParser -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMBPFDisassembler -lLLVMBPFCodeGen -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMBPFAsmPrinter -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMAMDGPUDisassembler -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo -lLLVMAMDGPUAsmPrinter -lLLVMAMDGPUUtils -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils -lLLVMObjectYAML -lLLVMLibDriver -lLLVMOption -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMLineEditor -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMCoroutines -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMLinker -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle;-L/usr/local/Cellar/llvm/5.0.0/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names (found version "5.0.0")
statusBuild Flags ' -I/usr/local/Cellar/llvm/5.0.0/include -DLLVM_BUILD_GLOBAL_ISEL -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fno-rtti -std=c++11'
-- Configuring done
CMake Warning (dev):
Policy CMP0042 is not set: MACOSX_RPATH is enabled by default. Run "cmake
--help-policy CMP0042" for policy details. Use the cmake_policy command to
set the policy and suppress this warning.
MACOSX_RPATH is not specified for the following targets:
stoat
This warning is for project developers. Use -Wno-dev to suppress it.
-- Generating done
-- Build files have been written to: /Users/lazzarello/src/stoat/build
[lazzarello@strop build (master)]$ make
Scanning dependencies of target stoat
[ 50%] Building CXX object CMakeFiles/stoat.dir/src/llvm-passes.cpp.o
/Users/lazzarello/src/stoat/src/llvm-passes.cpp:536:45: error: no member named 'getArgumentList' in
'llvm::Function'
std::string alias_type = Fn.getArgumentList().front().getType()->getPointerElementTyp...
~~ ^
1 error generated.
make[2]: *** [CMakeFiles/stoat.dir/src/llvm-passes.cpp.o] Error 1
make[1]: *** [CMakeFiles/stoat.dir/all] Error 2
make: *** [all] Error 2
[lazzarello@strop stoat (master)]$ llvm-config --version
5.0.0
[lazzarello@strop stoat (master)]$ clang --version
clang version 5.0.0 (tags/RELEASE_500/final)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin
[lazzarello@strop stoat (master)]$ cmake --version
cmake version 3.10.0
CMake suite maintained and supported by Kitware (kitware.com/cmake).
After running stoat on Ingen the following symbol calls no functions: Ingen::Server::PortImpl$vtable35
This is either a bug in vtable extraction or in the case of pure virtuals a bug in identifying subclasses.
In Carla I have a base class for a linked list which allocates on heap.
I override the allocation methods in a new rt-safe class with a memory pool.
The following code uses such class https://github.com/falkTX/Carla/blob/01b50d2f0ba44f4e98e2ae75082a0a465116d9ef/source/backend/plugin/CarlaPluginInternal.hpp#L253
stoat seems to be getting confused by this.
Reports the following error:
Error #26:
LinkedList<CarlaBackend::PluginPostRtEvent>::_allocate() _ZN10LinkedListIN12CarlaBackend17PluginPostRtEventEE9_allocateEv
##The Deduction Chain:
- LinkedList<CarlaBackend::PluginPostRtEvent>$vtable2 : Deduced Realtime
- AbstractLinkedList<CarlaBackend::PluginPostRtEvent>$vtable2 : Deduced Realtime
- AbstractLinkedList<CarlaBackend::PluginPostRtEvent>::_add(CarlaBackend::PluginPostRtEvent const&, bool, AbstractLinkedList<CarlaBackend::PluginPostRtEvent>::ListHead*) _ZN18AbstractLinkedListIN12CarlaBackend17PluginPostRtEventEE4_addERKS1_bPNS2_8ListHeadE : Deduced Realtime
- AbstractLinkedList<CarlaBackend::PluginPostRtEvent>::append(CarlaBackend::PluginPostRtEvent const&) _ZN18AbstractLinkedListIN12CarlaBackend17PluginPostRtEventEE6appendERKS1_ : Deduced Realtime
- CarlaBackend::CarlaPlugin::ProtectedData::PostRtEvents::appendRT(CarlaBackend::PluginPostRtEvent const&) _ZN12CarlaBackend11CarlaPlugin13ProtectedData12PostRtEvents8appendRTERKNS_17PluginPostRtEventE : Deduced Realtime
- CarlaBackend::CarlaPlugin::ProtectedData::postponeRtEvent(CarlaBackend::PluginPostRtEventType, int, int, float) _ZN12CarlaBackend11CarlaPlugin13ProtectedData15postponeRtEventENS_21PluginPostRtEventTypeEiif : Deduced Realtime
- CarlaBackend::CarlaPluginDSSI::process(float const**, float**, float const**, float**, unsigned int) _ZN12CarlaBackend15CarlaPluginDSSI7processEPPKfPPfS3_S5_j : Deduced Realtime
- CarlaBackend::CarlaPluginDSSI$vtable40 : Deduced Realtime
- CarlaBackend::CarlaPlugin$vtable40 : Deduced Realtime
- CarlaBackend::CarlaEngineJack::processPlugin(CarlaBackend::CarlaPlugin*, unsigned int) _ZN12CarlaBackend15CarlaEngineJack13processPluginEPNS_11CarlaPluginEj : Deduced Realtime
- CarlaBackend::CarlaEngineJack::handleJackProcessCallback(unsigned int) _ZN12CarlaBackend15CarlaEngineJack25handleJackProcessCallbackEj : Deduced Realtime
- CarlaBackend::CarlaEngineJack::carla_jack_process_callback(unsigned int, void*) _ZN12CarlaBackend15CarlaEngineJack27carla_jack_process_callbackEjPv : Realtime (Annotation)
##The Contradiction Reasons:
- malloc : NonRealtime (Blacklist)
I have some functions with the same name in multiple plugin-like .so files.
I annotated the first and it picked it up and reported a number of realtime functions, when the second was annotated that number did not change. Renaming the function caused the count to increase.
This may well be intentional (and my own fault for running across multiple targets), but I thought it might be worth asking about.
ExtractVtables::runOnModule in diamond confuse test case. I'd wager the crash is actually in handleVTable. Updating slackware should allow me to test this version. (currently tested with clang 3.7.0 and everything passes)
YAML (and Ruby's YAML parser) has a key length limit of 1024 characters. I hit this limit running stoat on mididings:
Parsing 'src/python_module.o.bc'...
/usr/lib/ruby/1.9.1/psych.rb:203:in `parse': (stoat_vtable.txt): could not find expected ':' while scanning a simple key at line 37 column 1 (Psych::SyntaxError)
from /usr/lib/ruby/1.9.1/psych.rb:203:in `parse_stream'
from /usr/lib/ruby/1.9.1/psych.rb:151:in `parse'
from /usr/lib/ruby/1.9.1/psych.rb:127:in `load'
from /usr/lib/ruby/1.9.1/psych.rb:297:in `block in load_file'
from /usr/lib/ruby/1.9.1/psych.rb:297:in `open'
from /usr/lib/ruby/1.9.1/psych.rb:297:in `load_file'
from /usr/local/share/stoat/load-callgraph.rb:52:in `block in load_callgraph'
from /usr/local/share/stoat/load-callgraph.rb:26:in `each'
from /usr/local/share/stoat/load-callgraph.rb:26:in `load_callgraph'
from /usr/local/bin/stoat:262:in `<main>'
The key is nothing fancy really, just a function taking a map<string, vector<string>>
, wrapped with Boost.Python...:
boost::python::objects::caller_py_function_impl<boost::python::detail::caller<void (mididings::backend::BackendBase::*)(std::map<std::string, std::vector<std::string, std::allocator<std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::vector<std::string, std::allocator<std::string> > > > > const&, std::map<std::string, std::vector<std::string, std::allocator<std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::vector<std::string, std::allocator<std::string> > > > > const&), boost::python::default_call_policies, boost::mpl::vector4<void, mididings::backend::BackendBase&, std::map<std::string, std::vector<std::string, std::allocator<std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::vector<std::string, std::allocator<std::string> > > > > const&, std::map<std::string, std::vector<std::string, std::allocator<std::string> >, std::less<std::string>, std::allocator<std::pair<std::string const, std::vector<std::string, std::allocator<std::string> > > > > const&> > >
My current workaround is to simply change ExtractVtables::handleVtable() to shorten names to 1024 characters (the function in question is not relevant to realtime-issues anyway). Is there a better solution, other than changing stoat's vtable file format?
might wanna fix hyperlink
http://log.fundamental-code.com/2014/08/15/stoat-tutorial-example
to working URI
http://log.fundamental-code.com/2014/08/15/stoat-tutorial-example.html
don't wanna fork+PR for such minimal edit
It looks like they've changed their API slightly for LLVM 5. Currently the LLVM pass has a chance to throw:
/usr/include/llvm-5.0/llvm/IR/Type.h:363: llvm::Type* llvm::Type::getArrayElementType() const: Assertion `getTypeID() == ArrayTyID' failed
A suppression file
a ==> A
b ==> B
will not only suppress calls from a to A and from b to B,
but will also suppress calls from a to B and from b to A
in the current implementation.
My default LLVM fails to build anything useful, I have multiple llvms but stoat fails to find them.
FindLLVM.cmake should have llvm-config-4.0, llvm-config-3.9 and llvm-config-3.8 added.
It is pretty idiotic, however it looks like the only way to establish any information about virtual method calls is to rebuild the vtable ourselves.
With a module pass it is possible to find all of the symbols that correspond to the vtable entries.
This should provide a function lookup scheme.
This however only takes care of part of the problem.
Knowing the vtables for "class B:public A" works fine when you are calling B's methods, but it fails hard when an A pointer is used.
This problem means that some hackery needs to be done within constructors to identify superclasses as well.
This seems reasonably easy to find as there are bitcast instructions which convert the "this" pointer from subclass type to superclass type within the subclass's constructor.
The only issue is identifying the constructor, which might need some understanding of the mangling functions.
Once the class hierarchy is known and the vtables are reconstructed, then a call to a function which cannot be resolved should be checkable against some relatively fixed patterns for vtable+offset .
Some extra caution will be needed to avoid any mistaken reports of calling __cxa_pure_virtual
As a rough idea as to what might get printed on the functioncall trace list
function trace:
- foobar
- A::vtable::0
vtable definitions
- A::vtable::0
- __cxa_pure_virtual
- A::vtable::1
- asdf
- B::vtable::0
- blam
Class Definition
- B :
- A
Oh boy is this going to be fun :p
There's yet another case that can result in a dangling $vtable in '[email protected]:JohannesLorenz/minimal.git'
This issue has to be investigated and then reclassified once the nature of the bug is known.
Note sure how to title this.
Take the following code:
https://github.com/falkTX/Carla/blob/01b50d2f0ba44f4e98e2ae75082a0a465116d9ef/source/backend/plugin/CarlaPlugin.cpp#L1306
There's 2 boolean arguments - sendOsc and sendCallback.
This function is called from RT side, but with those arguments as false.
For example here: https://github.com/falkTX/Carla/blob/01b50d2f0ba44f4e98e2ae75082a0a465116d9ef/source/backend/plugin/CarlaPluginLADSPA.cpp#L968
Hopefully it's possible to detect the cases where the code obviously is not being run, like calling a function with 'false' directly, as in the examples.
Carla's stoat output is 75% filled with stuff like this.
When building with -g clang produces information which should be mappable back to line numbers and whatnot.
MacOS 10.12.6 with Ruby 2.5.0
/usr/local/share/stoat/load-callgraph.rb:117:in `block in create_alias_map': undefined method `each' for #<String:0x007feafb873118> (NoMethodError)
from /usr/local/share/stoat/load-callgraph.rb:116:in `each'
from /usr/local/share/stoat/load-callgraph.rb:116:in `create_alias_map'
from /usr/local/share/stoat/load-callgraph.rb:55:in `block in load_callgraph'
from /usr/local/share/stoat/load-callgraph.rb:26:in `each'
from /usr/local/share/stoat/load-callgraph.rb:26:in `load_callgraph'
from /usr/local/bin/stoat:262:in `<main>'
Hi Mark, first of all it was very nice meeting you @ LAC!
As I already mentioned there thanks for this tool. I'm working on packaging it for gentoo and ran into the following issue when building it:
...
Install the project...
-- Install configuration: "Gentoo"
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/lib/libstoat.so
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/bin/stoat
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/bin/stoat-compile
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/bin/stoat-compile++
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/share/stoat/callgraph.rb
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/share/stoat/deductions.rb
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/share/stoat/graph.rb
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/share/stoat/load-callgraph.rb
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/share/stoat/whitelist.txt
-- Installing: /var/tmp/portage/dev-util/stoat-9999/image/usr/share/stoat/blacklist.txt
* ACCESS DENIED: open_wr: /etc/ld.so.cache~
CMake Warning at /var/tmp/portage/dev-util/stoat-9999/work/stoat-9999/cmake/InstallScript.cmake:8 (message):
Warning: ldconfig 1
Call Stack (most recent call first):
cmake_install.cmake:76 (include)
CMake Warning at /var/tmp/portage/dev-util/stoat-9999/work/stoat-9999/cmake/InstallScript.cmake:9 (message):
You may need to manually specify --llvm-passes
Call Stack (most recent call first):
cmake_install.cmake:76 (include)
>>> Completed installing stoat-9999 into /var/tmp/portage/dev-util/stoat-9999/image/
* Final size of build directory: 971 KiB
* Final size of installed tree: 10 KiB
* --------------------------- ACCESS VIOLATION SUMMARY ---------------------------
* LOG FILE: "/var/log/sandbox/sandbox-7282.log"
*
VERSION 1.0
FORMAT: F - Function called
FORMAT: S - Access Status
FORMAT: P - Path as passed to function
FORMAT: A - Absolute Path (not canonical)
FORMAT: R - Canonical Path
FORMAT: C - Command Line
F: open_wr
S: deny
P: /etc/ld.so.cache~
A: /etc/ld.so.cache~
R: /etc/ld.so.cache~
C: ldconfig
* --------------------------------------------------------------------------------
The error you're seeing is from the gentoo sandbox which is there to guarantee a clean build environment and ensure the build doesn't do anything with files it shouldn't have access to. In this case ldconfig
is trying to write to /etc/ld.so.cache
, which is not allowed in the sandbox.
This is caused by this script https://github.com/fundamental/stoat/blob/master/cmake/InstallScript.cmake
Was there any particular reason you added this? Normally the package manager would run ldconfig
if new libraries are installed, it's not something the build system normally does.
Hi,
I'm encountering an error on using the --graph-view switch, in a simple one file main.c
test using:
stoat -r . --graph-view graph.png
Error is as follows:
Error #1:
main
##The Deduction Chain:
##The Contradiction Reasons:
- printf : Assumed Unsafe
Total of 1 error(s)
Total Functions: 3
Total Realtime: 1
Total NonRealtime: 1
Parsing './main.bc'...
/usr/share/stoat/graph.rb:51:in `to_graph': uninitialized constant GraphRender::GraphViz (NameError)
from /usr/bin/stoat:312:in `<main>'
I'm on Arch linux with Graphviz current, and just ran gem install graphviz
.. perhaps there's a mismatch there? I'm no Ruby coder - so I'm not sure. Cheers, -Harry
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.