I was able to extract string from basic_string pointer. And now, I am trying to print the content of a shared pointer. In following code snipet, you can see the output of a simple cpp file, where I am passing a string to a function strr() and I was able to retrieve the value of that string at runtime which is
Going to Strr function.
It's a new line.
You can see the content of this string in arg_values
.
Provide 2 inputs => a,b.
If a is greater than 10 then subtract(string) function will be called. Otherwise str(string) will be called
455
65
User: main is calling _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_ is called from this callInst invoke void @_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_(%"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %agg.tmp, i8* noundef getelementptr inbounds ([42 x i8], [42 x i8]* @.str.4, i64 0, i64 0), %"class.std::allocator"* noundef nonnull align 1 dereferenceable(1) %ref.tmp)
to label %invoke.cont unwind label %lpad, !dbg !871
a is greater than 10
User: main is calling _Z4strrNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_Z4strrNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE is called from this callInst %call5 = invoke noundef i32 @_Z4strrNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE(%"class.std::__cxx11::basic_string"* noundef %agg.tmp)
to label %invoke.cont4 unwind label %lpad3, !dbg !872
Wed Mar 15 20:15:07 2023
Unix time: 1678932907
arguments: _Z4strrNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_Z4strrNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE %"class.std::__cxx11::basic_string"* %s
arg_values: Going to Strr function.
It's a new line.
Total Process time:0.000010
It's a string
User: main is calling _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev is called from this callInst call void @_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev(%"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %agg.tmp) #3, !dbg !872
The function in IR looks like this,
define dso_local noundef i32 @_Z4strrNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE(%"class.std::__cxx11::basic_string"* noundef %0) #5 {
%calltmp = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @str.3, i32 0, i32 0))
%calltmp1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @str.4, i32 0, i32 0))
%calltmp2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @9, i32 0, i32 0), i8* getelementptr inbounds ([61 x i8], [61 x i8]* @10, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @11, i32 0, i32 0))
%2 = load %"class.std::__cxx11::basic_string", %"class.std::__cxx11::basic_string"* %0, align 8
%calltmp3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @12, i32 0, i32 0), %"class.std::__cxx11::basic_string" %2)
%calltmp4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @str.5, i32 0, i32 0))
%3 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i64 0, i64 0))
ret i32 0
}
I am able to retrieve the content simply by loading the pointer to a load inst,
%2 = load %"class.std::__cxx11::basic_string", %"class.std::__cxx11::basic_string"* %0, align 8
Using following piece of code,
for (auto &v : arg_values) {
if(v->getType()->isPointerTy()){
//String is loaded here
llvm::Value *loadedValue = builder.CreateLoad(v->getType()->getPointerElementType(),v);
argsV.push_back(loadedValue);
continue;
}
argsV.push_back(v);
}
Now, if I try to print this function arguments at runtime,
define linkonce_odr dso_local void @_ZN13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE(%class.mqtt_callback* noundef nonnull align 8 dereferenceable(8) %0, %"class.std::shared_ptr.12"* noundef %1) unnamed_addr #7 comdat align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
%calltmp = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @str.3, i32 0, i32 0))
%calltmp1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @str.4, i32 0, i32 0))
%calltmp2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @9, i32 0, i32 0), i8* getelementptr inbounds ([70 x i8], [70 x i8]* @10, i32 0, i32 0), i8* getelementptr inbounds ([94 x i8], [94 x i8]* @11, i32 0, i32 0), i8* getelementptr inbounds ([125 x i8], [125 x i8]* @12, i32 0, i32 0))
%calltmp3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @13, i32 0, i32 0))
%calltmp4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @str.5, i32 0, i32 0))
%3 = alloca %class.mqtt_callback*, align 8
%4 = alloca %"class.std::__cxx11::basic_string", align 8
%5 = alloca i8*, align 8
%6 = alloca i32, align 4
store %class.mqtt_callback* %0, %class.mqtt_callback** %3, align 8
%7 = load %class.mqtt_callback*, %class.mqtt_callback** %3, align 8
%8 = call noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i8* noundef getelementptr inbounds ([28 x i8], [28 x i8]* @.str.18, i64 0, i64 0))
%9 = bitcast %"class.std::shared_ptr.12"* %1 to %"class.std::__shared_ptr_access.14"*
%10 = call noundef %"class.mqtt::message"* @_ZNKSt19__shared_ptr_accessIKN4mqtt7messageELN9__gnu_cxx12_Lock_policyE2ELb0ELb0EEptEv(%"class.std::__shared_ptr_access.14"* noundef nonnull align 1 dereferenceable(1) %9) #3
%11 = call noundef nonnull align 8 dereferenceable(32) %"class.std::__cxx11::basic_string"* @_ZNK4mqtt7message9get_topicB5cxx11Ev(%"class.mqtt::message"* noundef nonnull align 8 dereferenceable(120) %10)
%12 = call noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) %8, %"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %11)
%13 = call noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) %12, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* noundef @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
%14 = call noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) @_ZSt4cout, i8* noundef getelementptr inbounds ([18 x i8], [18 x i8]* @.str.19, i64 0, i64 0))
%15 = bitcast %"class.std::shared_ptr.12"* %1 to %"class.std::__shared_ptr_access.14"*
%16 = call noundef %"class.mqtt::message"* @_ZNKSt19__shared_ptr_accessIKN4mqtt7messageELN9__gnu_cxx12_Lock_policyE2ELb0ELb0EEptEv(%"class.std::__shared_ptr_access.14"* noundef nonnull align 1 dereferenceable(1) %15) #3
call void @_ZNK4mqtt7message9to_stringB5cxx11Ev(%"class.std::__cxx11::basic_string"* sret(%"class.std::__cxx11::basic_string") align 8 %4, %"class.mqtt::message"* noundef nonnull align 8 dereferenceable(120) %16)
%17 = invoke noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) %14, %"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %4)
to label %18 unwind label %21
18: ; preds = %2
%19 = invoke noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) %17, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* noundef @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
to label %20 unwind label %21
20: ; preds = %18
call void @_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev(%"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %4) #3
ret void
21: ; preds = %18, %2
%22 = landingpad { i8*, i32 }
cleanup
%23 = extractvalue { i8*, i32 } %22, 0
store i8* %23, i8** %5, align 8
%24 = extractvalue { i8*, i32 } %22, 1
store i32 %24, i32* %6, align 4
call void @_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev(%"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %4) #3
br label %25
25: ; preds = %21
%26 = load i8*, i8** %5, align 8
%27 = load i32, i32* %6, align 4
%28 = insertvalue { i8*, i32 } undef, i8* %26, 0
%29 = insertvalue { i8*, i32 } %28, i32 %27, 1
resume { i8*, i32 } %29
}
Which takes these arguments and 2nd one of those arguments is a shared pointer,
define linkonce_odr dso_local void @_ZN13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE(%class.mqtt_callback* noundef nonnull align 8 dereferenceable(8) %0, %"class.std::shared_ptr.12"* noundef %1) unnamed_addr #7 comdat align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
...
}
How do I extract the content of this function arguments? I tried following,
- putting a check for the shared pointer.
for (auto &v : arg_values) {
if(v->getType()->isPointerTy()){
llvm::Type *elementType = v->getType()->getPointerElementType();
if (auto *ptrType = llvm::dyn_cast<llvm::PointerType>(elementType)) {
llvm::Type *pointedType = ptrType->getPointerElementType();
if (pointedType->isIntegerTy(8)) {
llvm::Type *sharedPtrType = llvm::Type::getInt8PtrTy(context); // modify for actual shared pointer type
if (ptrType == sharedPtrType) {
// Pointer to a shared pointer of a string
llvm::Value *sharedPtrValue = builder.CreateLoad(elementType, v);
llvm::Value *loadedValue = builder.CreateLoad(sharedPtrValue->getType()->getPointerElementType(), sharedPtrValue);
argsV.push_back(loadedValue);
}
}
}
continue;
}
argsV.push_back(v);
}
But it is reading some wrong registers, I think,
Connecting to MQTT server: 'tcp://localhost:1883'...OK
Subscribing to topic: my/topic...OK
Wed Mar 15 16:56:30 2023
Unix time: 1678920990
arguments: _ZN13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE
_ZN13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE %class.mqtt_callback* %this
_ZN13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE %class.mqtt_callback* %this%"class.std::shared_ptr.12"* %msg
arg_values: (null)
^�F�
Total Process time:0.000006
Message received on topic: my/topic
Message content: Hello, MQTT!
^Z
[2]+ Stopped ./subscriber
- Dereferencing the shared pointer
for (auto &v : arg_values) {
if(v->getType()->isPointerTy()){
v->dump();
llvm::Value* sharedPtrValue = builder.CreateLoad(v->getType()->getPointerElementType(),v);
llvm::Value* ptrValue = builder.CreateExtractValue(sharedPtrValue, {0});
llvm::Value* loadedValue = CreateLoad(ptrValue->getType()->getPointerElementType(),ptrValue,"");
argsV.push_back(loadedValue);
argsV.push_back(builder.CreateGlobalStringPtr("pointer"));
continue;
}
argsV.push_back(v);
}
I am getting this error,
make: Warning: File 'Makefile' has modification time 12506 s in the future
clang++-14 -o client.ll -S -emit-llvm client_subscriber.cpp
clang++-14 -I/usr/lib/llvm-14/include -std=c++14 -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Wl,-znodelete -fno-rtti -fpic -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DVERSION=1 -Wno-variadic-macros -g -shared stringExtractPass.cpp -o instrument.so
#clang++-14 -o subscriber -lpaho-mqttpp3 -lpaho-mqtt3c -lpaho-mqtt3a -lmosquitto client_subscriber.cpp
clang++-14 -o subscriber -lpaho-mqttpp3 -lpaho-mqtt3c -lpaho-mqtt3a -lmosquitto -fno-discard-value-names -flegacy-pass-manager -g -Xclang -load -Xclang ./instrument.so client_subscriber.cpp
%class.mqtt_callback* %this
clang: /usr/lib/llvm-14/include/llvm/IR/Type.h:379: llvm::Type *llvm::Type::getNonOpaquePointerElementType() const: Assertion `getTypeID() == PointerTyID' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: /usr/lib/llvm-14/bin/clang -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend -disable-llvm-verifier -main-file-name client_subscriber.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -mllvm -treat-scalable-fixed-error-as-warning -debug-info-kind=constructor -dwarf-version=5 -debugger-tuning=gdb -fcoverage-compilation-dir=/home/u18new/LLVM_PASSES/LogPasses-new/messagePublishFunc/TopicExtraction/mqtt -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -fdebug-compilation-dir=/home/u18new/LLVM_PASSES/LogPasses-new/messagePublishFunc/TopicExtraction/mqtt -ferror-limit 19 -fgnuc-version=4.2.1 -flegacy-pass-manager -fcxx-exceptions -fexceptions -fcolor-diagnostics -load ./instrument.so -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/client_subscriber-a31ad4.o -x c++ client_subscriber.cpp
1. <eof> parser at end of file
2. Per-module optimization passes
3. Running pass 'CPSTracker Pass' on module 'client_subscriber.cpp'.
#0 0x00007f168612a6a1 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4e6a1)
#1 0x00007f16861283ee llvm::sys::RunSignalHandlers() (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4c3ee)
#2 0x00007f168612abdb (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4ebdb)
#3 0x00007f168f400980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
#4 0x00007f1684566e87 raise /build/glibc-CVJwZb/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0
#5 0x00007f16845687f1 abort /build/glibc-CVJwZb/glibc-2.27/stdlib/abort.c:81:0
#6 0x00007f16845583fa __assert_fail_base /build/glibc-CVJwZb/glibc-2.27/assert/assert.c:89:0
#7 0x00007f1684558472 (/lib/x86_64-linux-gnu/libc.so.6+0x30472)
#8 0x00007f168114a923 (anonymous namespace)::CPSTracker::runOnModule(llvm::Module&) /home/u18new/LLVM_PASSES/LogPasses-new/messagePublishFunc/TopicExtraction/mqtt/stringExtractPass.cpp:0:0
#9 0x00007f16862657c6 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xf897c6)
#10 0x00007f168d45b69b clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x186569b)
#11 0x00007f168d77fc01 (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x1b89c01)
#12 0x00007f168c5fb054 clang::ParseAST(clang::Sema&, bool, bool) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0xa05054)
#13 0x00007f168d77bf51 clang::CodeGenAction::ExecuteAction() (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x1b85f51)
#14 0x00007f168e11d727 clang::FrontendAction::Execute() (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x2527727)
#15 0x00007f168e074d86 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x247ed86)
#16 0x00007f168e196e8b clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x25a0e8b)
#17 0x000000000041329f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/lib/llvm-14/bin/clang+0x41329f)
#18 0x00000000004114dc (/usr/lib/llvm-14/bin/clang+0x4114dc)
#19 0x0000000000411327 main (/usr/lib/llvm-14/bin/clang+0x411327)
#20 0x00007f1684549c87 __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:344:0
#21 0x000000000040e3da _start (/usr/lib/llvm-14/bin/clang+0x40e3da)
clang: error: unable to execute command: Aborted (core dumped)
clang: error: clang frontend command failed due to signal (use -v to see invocation)
Ubuntu clang version 14.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
clang: note: diagnostic msg:
********************
PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/client_subscriber-3e96d3.cpp
clang: note: diagnostic msg: /tmp/client_subscriber-3e96d3.sh
clang: note: diagnostic msg:
********************
Makefile:28: recipe for target 'subscriber' failed
make: *** [subscriber] Error 254
probably need to bitcast again, but don’t want to do that again.
Any suggestions on how to extract the value of this mqtt function parameters at runtime.