How to print a shared pointer value at runtime

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.

The error is likely because you called getPointerElementType on a non-ptr type. I’d suggest assertions before such calls.

Thanks for your reply. I just want to add this line inside the message_arrived function of mqtt,

printf("Message Topic from printf: %s\n", msg->get_topic().c_str());

here is the function,

    void message_arrived(mqtt::const_message_ptr msg) override {
	//std::cout << "msg: " << msg << std::endl;
	printf("Message Content Length: %lu\n", msg->get_payload().length());        
	std::cout << "Message received on topic: " << msg->get_topic() << std::endl;
        std::cout << "Message content: " << msg->to_string() << std::endl;
    }

Here is the pass,

for(auto i = F.arg_begin();i!=F.arg_end();++i){
	rso << *i <<"\n";
	arg_strings.push_back(rso.str());
	arg_values.push_back(i);
}

//if(F.getName().contains("message_arrived") || F.getName().contains("publish") || F.getName().contains("connection_lost") || F.getName().contains("delivery_complete")){
if(F.getName().contains("message_arrived")){
	// If a function is declared then it will not have basic blocks in them. So, if a function is not delcared then it will have basic block, which I need to insert printf
	if(!F.isDeclaration()){
		auto &BB = F.getEntryBlock();        
		std::vector<std::string> arguments; // This vector will be used to store functions arguments name
		BasicBlock::iterator IP = BB.getFirstInsertionPt();
		IRBuilder<> builder(&(*IP));
		
		{
			// using the format specifier for printing the values
			std::string format("arg_values: ");
			for (size_t i = 0; i < arg_values.size(); ++i) {
				format += "%s\n";
			}
			Value *str = builder.CreateGlobalStringPtr(format, "");
			std::vector<Value *> argsV({str});

			outs()<<"\nFunction name:"<<F.getName()<<"\n";
		
			for (auto &v : arg_values) {
				if(v->getType()->isPointerTy()){
					outs()<<"Pointer type:"<< *v->getType() <<"\n";
					auto containedType = v->getType()->getContainedType(0);
					outs()<<"Contained type(0): "<<*v->getType()->getContainedType(0)<<"\n";
					outs()<<"Contained contained type: "<<containedType->getContainedType(0)->isStructTy()<<"\n";
					if (containedType->getStructName().startswith("class.std::shared_ptr")) {
					   { // This part checks if v is an actual object, not necessarily required here, but yet given to ensure the type of v
						outs()<<"Struct name: "<<containedType->getContainedType(0)->getStructName()<<"\n";
						// trying to print the pointer shared pointer is pointing to 
						assert(containedType->getContainedType(0));
						// Now getting the contained types and it's shared pointers like following,
						// Contained Pointer Type:%"class.std::__shared_ptr.113" = type { %"class.mqtt::delivery_token"*, %"class.std::__shared_count" }
						Type *containedPointerType = containedType->getContainedType(0);
						outs()<< "Contained Pointer Type:" << *containedPointerType <<"\n";
						assert(containedType->isStructTy());
						outs()<<"First type: "<< *containedPointerType->getContainedType(0)<<"\n";
						// So, the 1st type of 1st pointer is extracted, looks like -  %"class.mqtt::delivery_token"*
						Type *firstType = containedPointerType->getContainedType(0);
						assert(firstType->isPointerTy());
					   }
					   { // This part calls the get_topic() function with the object `v`
					        // Get the function named "_ZNK4mqtt7message9get_topicB5cxx11Ev" from the parent module of F
						llvm::Function* getTopicFn = F.getParent()->getFunction("_ZNK4mqtt7message9get_topicB5cxx11Ev");
						// Ensuring that the LLVM function pointer getTopicFn is not null
						assert(getTopicFn);
						
						// Call the function with the argument v and get the returned value, which is a pointer to a string
						Value *topicStrPtr = builder.CreateCall(getTopicFn, v);
						
						// Print the type of the returned value
						outs()<<"topicStrPtr type: "<<*topicStrPtr->getType()<<"\n";
						
						// Load the string from the pointer
						Value *loadedTopicStrPtr = builder.CreateLoad(topicStrPtr->getType()->getPointerElementType(),topicStrPtr);
						
						// Convert the loaded string pointer to a char pointer
						Value *topicCharPtr = builder.CreatePointerCast(loadedTopicStrPtr, builder.getInt8PtrTy());
						
						// Add the char pointer to argsV, which is a vector of arguments for another function call
						argsV.push_back(topicCharPtr);
					   }
					}
					else{
						llvm::Value *loadedValue = builder.CreateLoad(v->getType()->getPointerElementType(),v);
						outs()<<"loadedValue: "<<*loadedValue<<"\n";
			                	//argsV.push_back(loadedValue);
						argsV.push_back(builder.CreateGlobalStringPtr("This is msg part 2", ""));
					}
					continue;
			        }
				argsV.push_back(v);

			}
			builder.CreateCall(printfFunc, argsV, "calltmp"); 
		}
	}
}

I am calling the get_topic() with v here after confirming it’s an object with this if (containedType->getStructName().startswith("class.std::shared_ptr")) {
And then pushing it to argsV,

{ // This part calls the get_topic() function with the object `v`
     // Get the function named "_ZNK4mqtt7message9get_topicB5cxx11Ev" from the parent module of F
     llvm::Function* getTopicFn = F.getParent()->getFunction("_ZNK4mqtt7message9get_topicB5cxx11Ev");
     // Ensuring that the LLVM function pointer getTopicFn is not null
     assert(getTopicFn);
     
     // Call the function with the argument v and get the returned value, which is a pointer to a string
     Value *topicStrPtr = builder.CreateCall(getTopicFn, v);
     
     // Print the type of the returned value
     outs()<<"topicStrPtr type: "<<*topicStrPtr->getType()<<"\n";
     
     // Load the string from the pointer
     Value *loadedTopicStrPtr = builder.CreateLoad(topicStrPtr->getType()->getPointerElementType(),topicStrPtr);
     
     // Convert the loaded string pointer to a char pointer
     Value *topicCharPtr = builder.CreatePointerCast(loadedTopicStrPtr, builder.getInt8PtrTy());
     
     // Add the char pointer to argsV, which is a vector of arguments for another function call
     argsV.push_back(topicCharPtr);
}

Am I doing any mistakes here, because I don’t see the topic in the output,

Output at runtime:

$ ./subscriber 
Connecting to MQTT server: 'tcp://localhost:1883'...OK

Subscribing to topic: my/topic...OK

arg_values: This is msg part 2
P�\�9
Message Content Length: 12
Message received on topic: my/topic
Message content: Hello, MQTT!

It should print the topic except this P|��.

Output at compile time:

Function name:_ZTv0_n48_N13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE
Pointer type:%class.mqtt_callback*
Contained type(0): %class.mqtt_callback = type { %"class.mqtt::callback" }
Contained contained type: 1
loadedValue:   %3 = load %class.mqtt_callback, %class.mqtt_callback* %0, align 8
Pointer type:%"class.std::shared_ptr.12"*
Contained type(0): %"class.std::shared_ptr.12" = type { %"class.std::__shared_ptr.13" }
Contained contained type: 1
Struct name: class.std::__shared_ptr.13
Contained Pointer Type:%"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
First type: %"class.mqtt::message"*
topicStrPtr type: %"class.std::__cxx11::basic_string"*

My guess: the function is inlined before you change it. Try __attribute__((noinline)). That said, it is hard to tell and you should inspect the final IR etc.

Here is the definition of get_topic(): paho.mqtt.cpp/will_options.h at 2ff3d155dcd10564f1816675789284b4efd79eb7 · eclipse/paho.mqtt.cpp · GitHub

It is defined like this,

	string get_topic() const { return topic_ ? topic_.to_string() : string(); }

Though it’s not marked with the inline keyword, but it’s still possible for the compiler to inline it if it wants to do so. So, I checked if it is inline then I am making it noinline,

if (getTopicFn->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
        getTopicFn->addFnAttr(llvm::Attribute::NoInline);
}

I think the main problem is, I am not passing the 1st element to the get_topic() function like in IR, suppose, when I calling the get_topic() from source code, then it takes this class.mqtt::message

%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)

But the get_topic() I am instrumenting, it’s taking class.std::shared_ptr.12.

  %4 = call %"class.std::__cxx11::basic_string"* @_ZNK4mqtt7message9get_topicB5cxx11Ev(%"class.std::shared_ptr.12"* %1)

Here is the IR,

; Function Attrs: mustprogress noinline optnone uwtable
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 {
// I instrumented this printf 
  %3 = load %class.mqtt_callback, %class.mqtt_callback* %0, align 8
  %4 = call %"class.std::__cxx11::basic_string"* @_ZNK4mqtt7message9get_topicB5cxx11Ev(%"class.std::shared_ptr.12"* %1)
  %5 = load %"class.std::__cxx11::basic_string", %"class.std::__cxx11::basic_string"* %4, align 8
  %6 = addrspacecast %"class.std::__cxx11::basic_string" %5 to i8*
  %calltmp = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @0, i32 0, i32 0), i8* getelementptr inbounds ([19 x i8], [19 x i8]* @1, i32 0, i32 0), i8* %6)

// Following IR is generated from source code
  %7 = alloca %class.mqtt_callback*, align 8
  store %class.mqtt_callback* %0, %class.mqtt_callback** %7, align 8
  %8 = load %class.mqtt_callback*, %class.mqtt_callback** %7, align 8
  %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 i8* @_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5c_strEv(%"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %11) #3
  %13 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([11 x i8], [11 x i8]* @.str.18, i64 0, i64 0), i8* noundef %12)
  ret void
}

So, I tried to get the pointer reference to this value class.mqtt::message. At first v is a shared pointer type,

Pointer type:%"class.std::shared_ptr.12"*
// contained type is also a shared pointer type
Contained type(0): %"class.std::shared_ptr.12" = type { %"class.std::__shared_ptr.13" }
// Contained pointer type is a struct type with 2 different elements
Contained contained type: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
Contained contained type struct: 1
  1. I got the pointer ref to the value of contained type from v,
llvm::Value* containedValue = builder.CreateLoad(containedType, builder.CreateGEP(containedType, v, {builder.getInt32(0) , builder.getInt32(0)})); 
outs()<<"containedValue: "<<*containedValue<<"\n";
outs()<<"containedValue type: "<<*containedValue->getType()->getContainedType(0)<<"\n";

Output of above code,

containedValue:   %5 = load %"class.std::shared_ptr.12", %"class.std::__shared_ptr.13"* %4, align 8
containedValue type: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
  1. Now, I need to get the ref to the 1st element class.mqtt::message. As this is a struct type, I can not call CreateGEP directly. I have to get the element pointer first,

The Value *CreateStructGEP (Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="") should give me the pointer to 1st value,

// got the type, which I already have but retrieve it again just to ignore a mismatch
auto containedStructPtrType = containedValue->getType()->getContainedType(0); // Get the pointer to the struct
// Now, passing it to CreateStructGEP to get the pointer of the 1st element
llvm::Value *firstFieldPtr = builder.CreateStructGEP(containedStructPtrType, containedValue, 0);

But I got this,

containedValue:   %2 = load %"class.std::shared_ptr.12", %"class.std::__shared_ptr.13"* %1, align 8
containedValue type: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
clang: /usr/lib/llvm-14/include/llvm/IR/Instructions.h:923: llvm::Type *llvm::checkGEPType(llvm::Type *): Assertion `Ty && "Invalid GetElementPtrInst indices for type!"' 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-07d5a5.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 0x00007ff4e72b96a1 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4e6a1)
 #1 0x00007ff4e72b73ee llvm::sys::RunSignalHandlers() (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4c3ee)
 #2 0x00007ff4e72b9bdb (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4ebdb)
 #3 0x00007ff4f058f980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
 #4 0x00007ff4e56f5e87 raise /build/glibc-CVJwZb/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0
 #5 0x00007ff4e56f77f1 abort /build/glibc-CVJwZb/glibc-2.27/stdlib/abort.c:81:0
 #6 0x00007ff4e56e73fa __assert_fail_base /build/glibc-CVJwZb/glibc-2.27/assert/assert.c:89:0
 #7 0x00007ff4e56e7472 (/lib/x86_64-linux-gnu/libc.so.6+0x30472)
 #8 0x00007ff4e22d97a9 (./instrument.so+0x67a9)

Also, tried doing this way,

// got the type, which I already have but retrieve it again just to ignore a mismatch
auto containedStructPtrType = containedValue->getType()->getContainedType(0); // Get the pointer to the struct
// Creating an LLVM IR instruction to extract the first field of a struct pointed to by `containedValue`.
auto containedStructPtr = builder.CreateExtractValue(containedValue, {0});
// Now, passing it to CreateStructGEP to get the pointer of the 1st element
llvm::Value *firstFieldPtr = builder.CreateStructGEP(containedStructPtrType, containedStructPtr, 0);

But I am getting this error,

containedValue:   %2 = load %"class.std::shared_ptr.12", %"class.std::__shared_ptr.13"* %1, align 8
containedValue type: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
clang: /usr/lib/llvm-14/include/llvm/Support/Casting.h:269: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = llvm::PointerType, Y = llvm::Type]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' 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-6f4477.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 0x00007f94321c76a1 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4e6a1)
 #1 0x00007f94321c53ee llvm::sys::RunSignalHandlers() (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4c3ee)
 #2 0x00007f94321c7bdb (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4ebdb)
 #3 0x00007f943b49d980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
 #4 0x00007f9430603e87 raise /build/glibc-CVJwZb/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0
 #5 0x00007f94306057f1 abort /build/glibc-CVJwZb/glibc-2.27/stdlib/abort.c:81:0
 #6 0x00007f94305f53fa __assert_fail_base /build/glibc-CVJwZb/glibc-2.27/assert/assert.c:89:0
 #7 0x00007f94305f5472 (/lib/x86_64-linux-gnu/libc.so.6+0x30472)
 #8 0x00007f942d1e72e6 llvm::GetElementPtrInst::Create(llvm::Type*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::Twine const&, llvm::Instruction*) /usr/lib/llvm-14/include/llvm/IR/Instructions.h:962:5
 #9 0x00007f942d1e5ec5 llvm::GetElementPtrInst::CreateInBounds(llvm::Type*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::Twine const&, llvm::Instruction*) /usr/lib/llvm-14/include/llvm/IR/Instructions.h:987:9
#10 0x00007f942d1e5ec5 llvm::IRBuilderBase::CreateConstInBoundsGEP2_32(llvm::Type*, llvm::Value*, unsigned int, unsigned int, llvm::Twine const&) /usr/lib/llvm-14/include/llvm/IR/IRBuilder.h:1805:19
#11 0x00007f942d1e5ec5 llvm::IRBuilderBase::CreateStructGEP(llvm::Type*, llvm::Value*, unsigned int, llvm::Twine const&) /usr/lib/llvm-14/include/llvm/IR/IRBuilder.h:1856:12
#12 0x00007f942d1e5ec5 (anonymous namespace)::CPSTracker::runOnModule(llvm::Module&) /home/u18new/LLVM_PASSES/LogPasses-new/messagePublishFunc/TopicExtraction/mqtt/copyValueTypeExtractionPass.cpp:129:38
#13 0x00007f94323027c6 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xf897c6)
#14 0x00007f94394f869b 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)
#15 0x00007f943981cc01 (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x1b89c01)
#16 0x00007f9438698054 clang::ParseAST(clang::Sema&, bool, bool) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0xa05054)
#17 0x00007f9439818f51 clang::CodeGenAction::ExecuteAction() (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x1b85f51)
#18 0x00007f943a1ba727 clang::FrontendAction::Execute() (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x2527727)
#19 0x00007f943a111d86 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x247ed86)
#20 0x00007f943a233e8b clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/usr/lib/x86_64-linux-gnu/libclang-cpp.so.14+0x25a0e8b)
#21 0x000000000041329f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/lib/llvm-14/bin/clang+0x41329f)
#22 0x00000000004114dc (/usr/lib/llvm-14/bin/clang+0x4114dc)
#23 0x0000000000411327 main (/usr/lib/llvm-14/bin/clang+0x411327)
#24 0x00007f94305e6c87 __libc_start_main /build/glibc-CVJwZb/glibc-2.27/csu/../csu/libc-start.c:344:0
#25 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-e39471.cpp
clang: note: diagnostic msg: /tmp/client_subscriber-e39471.sh
clang: note: diagnostic msg: 

********************
Makefile:32: recipe for target 'subscriber' failed
make: *** [subscriber] Error 254

Here is the code,

if (containedType->getStructName().startswith("class.std::shared_ptr")) {
   { // This part checks if v is an actual object, not necessarily required here, but yet given to ensure the type of v
	outs()<<"Contained Pointer Struct name: "<<containedType->getContainedType(0)->getStructName()<<"\n";
	// trying to print the pointer shared pointer is pointing to 
	assert(containedType->getContainedType(0));
	// Now getting the contained types and it's shared pointers like following,
	// Contained Pointer Type:%"class.std::__shared_ptr.113" = type { %"class.mqtt::delivery_token"*, %"class.std::__shared_count" }
	Type *containedPointerType = containedType->getContainedType(0);
	outs()<< "Contained Pointer Type:" << *containedPointerType <<"\n";
	assert(containedPointerType->isStructTy());
	outs()<<"First type: "<< *containedPointerType->getContainedType(0)<<"\n";
	// So, the 1st type of 1st pointer is extracted, looks like -  %"class.mqtt::delivery_token"*
	Type *firstType = containedPointerType->getContainedType(0);
	assert(firstType->isPointerTy());

	// Now, getting the pointer to the %"class.mqtt::message"*
	outs()<<"v type to pointerElement type:"<<*v->getType()->getPointerElementType()<<"\n";
	outs()<<"firstType pointer element type: "<<*firstType->getPointerElementType()<<"\n";

	llvm::Value* containedValue = builder.CreateLoad(containedType, builder.CreateGEP(containedType, v, {builder.getInt32(0) , builder.getInt32(0)}));
        outs()<<"containedValue: "<<*containedValue<<"\n";
        outs()<<"containedValue type: "<<*containedValue->getType()->getContainedType(0)<<"\n";

	//llvm::Value* containedPointerValue = builder.CreateLoad(firstType, builder.CreateGEP(firstType, containedValue, {builder.getInt32(0) , builder.getInt32(0)}));
   	//outs()<<"containedPointerValue: "<<*containedPointerValue<<"\n";
	
	auto containedStructPtrType = containedValue->getType()->getContainedType(0); // Get the pointer to the struct
	auto containedStructPtr = builder.CreateExtractValue(containedValue, {1});
	llvm::Value *firstFieldPtr = builder.CreateStructGEP(containedValue->getType()->getContainedType(0), containedValue, 0);
	//llvm::Value *firstFieldPtr = builder.CreateStructGEP(containedValue->getType(), containedValue, 0);
	//for(auto it: containedType->element_begin(); it!= element_end(); ++it){
	//	outs()<<*it<<"\n";
	//}

   }
   { // This part calls the get_topic() function with the object `v`
        // Get the function named "_ZNK4mqtt7message9get_topicB5cxx11Ev" from the parent module of F
	llvm::Function* getTopicFn = F.getParent()->getFunction("_ZNK4mqtt7message9get_topicB5cxx11Ev");
	// Ensuring that the LLVM function pointer getTopicFn is not null
	assert(getTopicFn);
	//outs()<<*containedType->getPointerElementType()<<"\n";
	if (getTopicFn->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
		getTopicFn->addFnAttr(llvm::Attribute::NoInline);
	}
	
	// Call the function with the argument v and get the returned value, which is a pointer to a string
	//Value *topicStrPtr = builder.CreateCall(getTopicFn, v);
	Value *topicStrPtr = builder.CreateCall(getTopicFn, v);
	
	// Print the type of the returned value
	outs()<<"topicStrPtr type: "<<*topicStrPtr->getType()<<"\n";
	
	// Load the string from the pointer
	Value *loadedTopicStrPtr = builder.CreateLoad(topicStrPtr->getType()->getPointerElementType(),topicStrPtr);
	
	// Convert the loaded string pointer to a char pointer
	Value *topicCharPtr = builder.CreatePointerCast(loadedTopicStrPtr, builder.getInt8PtrTy());
	
	// Add the char pointer to argsV, which is a vector of arguments for another function call
	argsV.push_back(topicCharPtr);
   }
}

I have bit cast the shared pointer to another pointer and then retrieved the address of the class.mqtt::message, which is passed to get_topic(), following is the code,

if(v->getType()->isPointerTy()){
	outs()<<"Just v:"<< *v <<"\n";
	outs()<<"Pointer type:"<< *v->getType() <<"\n";
	auto containedType = v->getType()->getContainedType(0);
	outs()<<"Contained type(0): "<<*v->getType()->getContainedType(0)<<"\n";
	outs()<<"Contained type is struct type: "<<containedType->isStructTy()<<"\n";
	outs()<<"Contained contained type: "<<*containedType->getContainedType(0)<<"\n";
	outs()<<"Contained contained type struct: "<<containedType->getContainedType(0)->isStructTy()<<"\n";
	if (containedType->getStructName().startswith("class.std::shared_ptr")) {
	   { // This part checks if v is an actual object, not necessarily required here, but yet given to ensure the type of v
		outs()<<"Contained Pointer Struct name: "<<containedType->getContainedType(0)->getStructName()<<"\n";
		// trying to print the pointer shared pointer is pointing to 
		assert(containedType->getContainedType(0));
		// Now getting the contained types and it's shared pointers like following,
		// Contained Pointer Type:%"class.std::__shared_ptr.113" = type { %"class.mqtt::delivery_token"*, %"class.std::__shared_count" }
		Type *containedPointerType = containedType->getContainedType(0);
		outs()<< "Contained Pointer Type:" << *containedPointerType <<"\n";
		assert(containedPointerType->isStructTy());
		outs()<<"First type: "<< *containedPointerType->getContainedType(0)<<"\n";
		// So, the 1st type of 1st pointer is extracted, looks like -  %"class.mqtt::delivery_token"*
		Type *firstType = containedPointerType->getContainedType(0);
		assert(firstType->isPointerTy());

		// Now, getting the pointer to the %"class.mqtt::message"*
		outs()<<"v type to pointerElement type:"<<*v->getType()->getPointerElementType()<<"\n";
		outs()<<"firstType pointer element type: "<<*firstType->getPointerElementType()<<"\n";

		llvm::Value* containedValue = builder.CreateLoad(containedType, builder.CreateGEP(containedType, v, {builder.getInt32(0) , builder.getInt32(0)}));
                outs()<<"containedValue: "<<*containedValue<<"\n";
                outs()<<"containedValue type: "<<*containedValue->getType()->getContainedType(0)<<"\n";

		// Probably need the hell bitcast
		auto* newPointerType = llvm::PointerType::getUnqual(containedPointerType);
		auto* bitcast = builder.CreateBitCast(v, newPointerType, "bitcast");
		outs()<<" Just v: "<<v<<" "<<"just bitcast: "<<bitcast<<"\n";
		outs()<<*bitcast<<"\n";
		outs()<<"bitcast 1st pointer value: "<<*bitcast->getType()->getPointerElementType()<<"\n";

		// GETTING CLASS.MQTT::MESSAGE VALUE BY GETTING POINTERS TO THE MESSAGE BODY 
		llvm::Value* containedPointerValue = builder.CreateGEP(containedPointerType, bitcast, {builder.getInt32(0) , builder.getInt32(0)});
		outs()<<"ConatainerPointerValue: "<<*containedPointerValue<<"\n";
		//llvm::Value* firstValue= builder.CreateStructGEP(containedPointerValue->getType()->getContainedType(0), containedPointerValue, 0);
		llvm::Value *loadedValue = builder.CreateLoad(containedPointerValue->getType()->getPointerElementType(),bitcast);
		outs()<<"loadedValue addr:"<<loadedValue<<"\n";
                outs()<<"loadedValue: "<<*loadedValue<<"\n";
                //argsV.push_back(loadedValue);
		
		
		// JUST CALLING SAME FUNCTIONS LIKE MQTT DOES
		llvm::Function* mqttMsgFn = F.getParent()->getFunction("_ZNKSt19__shared_ptr_accessIKN4mqtt7messageELN9__gnu_cxx12_Lock_policyE2ELb0ELb0EEptEv");
		assert(mqttMsgFn);
		Value *msgClass = builder.CreateCall(mqttMsgFn, bitcast);
		outs()<<"class.mqtt::msg: "<< *msgClass <<"\n";

		llvm::Function* getTopicFn = F.getParent()->getFunction("_ZNK4mqtt7message9get_topicB5cxx11Ev");
		Value *topicStrPtr = builder.CreateCall(getTopicFn, loadedValue);
		outs()<<"msg address: "<<loadedValue<<"\n";
		outs()<<"topic from msg:"<< *topicStrPtr <<"\n";
		argsV.push_back(topicStrPtr);

	   }
	}
	else{
		llvm::Value *loadedValue = builder.CreateLoad(v->getType()->getPointerElementType(),v);
		outs()<<"loadedValue: "<<*loadedValue<<"\n";
        	//argsV.push_back(loadedValue);
		argsV.push_back(builder.CreateGlobalStringPtr("This is msg part 1", ""));
	}
	continue;
}
argsV.push_back(v);

But I don’t know why I am not getting the topic, it prints nothing. I have print the address of both msg at compile time and runtime though I am not sure if those will be similar or not.
Compile time output,

Function name:_ZTv0_n48_N13mqtt_callback15message_arrivedESt10shared_ptrIKN4mqtt7messageEE
Just v:%class.mqtt_callback* %0
Pointer type:%class.mqtt_callback*
Contained type(0): %class.mqtt_callback = type { %"class.mqtt::callback" }
Contained type is struct type: 1
Contained contained type: %"class.mqtt::callback" = type { i32 (...)** }
Contained contained type struct: 1
loadedValue:   %3 = load %class.mqtt_callback, %class.mqtt_callback* %0, align 8
Just v:%"class.std::shared_ptr.12"* %1
Pointer type:%"class.std::shared_ptr.12"*
Contained type(0): %"class.std::shared_ptr.12" = type { %"class.std::__shared_ptr.13" }
Contained type is struct type: 1
Contained contained type: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
Contained contained type struct: 1
Contained Pointer Struct name: class.std::__shared_ptr.13
Contained Pointer Type:%"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
First type: %"class.mqtt::message"*
v type to pointerElement type:%"class.std::shared_ptr.12" = type { %"class.std::__shared_ptr.13" }
firstType pointer element type: %"class.mqtt::message" = type { %struct.MQTTAsync_message, %"class.mqtt::buffer_ref", %"class.mqtt::buffer_ref", %"class.mqtt::properties" }
containedValue:   %5 = load %"class.std::shared_ptr.12", %"class.std::__shared_ptr.13"* %4, align 8
containedValue type: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
 Just v: 0x1596618 just bitcast: 0x15b99b0
  %bitcast = bitcast %"class.std::shared_ptr.12"* %1 to %"class.std::__shared_ptr.13"*
bitcast 1st pointer value: %"class.std::__shared_ptr.13" = type { %"class.mqtt::message"*, %"class.std::__shared_count" }
ConatainerPointerValue:   %6 = getelementptr %"class.std::__shared_ptr.13", %"class.std::__shared_ptr.13"* %bitcast, i32 0, i32 0
loadedValue addr:0x15b9b00
loadedValue:   %7 = load %"class.mqtt::message"*, %"class.std::__shared_ptr.13"* %bitcast, align 8
class.mqtt::msg:   %8 = call %"class.mqtt::message"* @_ZNKSt19__shared_ptr_accessIKN4mqtt7messageELN9__gnu_cxx12_Lock_policyE2ELb0ELb0EEptEv(%"class.std::__shared_ptr.13"* %bitcast)
msg address: 0x15b9b00
topic from msg:  %9 = call %"class.std::__cxx11::basic_string"* @_ZNK4mqtt7message9get_topicB5cxx11Ev(%"class.mqtt::message"* %7)

msg address msg address: 0x15b9b00

Runtime output:

$ ./subscriber 
Connecting to MQTT server: 'tcp://localhost:1883'...OK

Subscribing to topic: my/topic...OK

arg_values: This is msg part 1

msg: 0x7fc8359599f0
Topic: my/topic
^Z
[8]+  Stopped                 ./subscriber

This msg address is different msg: 0x7fc8359599f0

Here is the IR,

; Function Attrs: mustprogress noinline optnone uwtable
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 {
// instruments starts
  %3 = load %class.mqtt_callback, %class.mqtt_callback* %0, align 8
  %4 = getelementptr %"class.std::shared_ptr.12", %"class.std::shared_ptr.12"* %1, i32 0, i32 0
  %5 = load %"class.std::shared_ptr.12", %"class.std::__shared_ptr.13"* %4, align 8
  %bitcast = bitcast %"class.std::shared_ptr.12"* %1 to %"class.std::__shared_ptr.13"*
  %6 = getelementptr %"class.std::__shared_ptr.13", %"class.std::__shared_ptr.13"* %bitcast, i32 0, i32 0
  %7 = load %"class.mqtt::message"*, %"class.std::__shared_ptr.13"* %bitcast, align 8
  %8 = call %"class.mqtt::message"* @_ZNKSt19__shared_ptr_accessIKN4mqtt7messageELN9__gnu_cxx12_Lock_policyE2ELb0ELb0EEptEv(%"class.std::__shared_ptr.13"* %bitcast)
  %9 = call %"class.std::__cxx11::basic_string"* @_ZNK4mqtt7message9get_topicB5cxx11Ev(%"class.mqtt::message"* %7)
  %calltmp = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @3, i32 0, i32 0), i8* getelementptr inbounds ([19 x i8], [19 x i8]* @4, i32 0, i32 0), %"class.std::__cxx11::basic_string"* %9)
 // instrumented part ends
  %10 = alloca %class.mqtt_callback*, align 8
  store %class.mqtt_callback* %0, %class.mqtt_callback** %10, align 8
  %11 = load %class.mqtt_callback*, %class.mqtt_callback** %10, align 8
  %12 = 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 ([6 x i8], [6 x i8]* @.str.18, i64 0, i64 0))
  %13 = bitcast %"class.std::shared_ptr.12"* %1 to i8*
  %14 = call noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEPKv(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) %12, i8* noundef %13)
  %15 = call noundef nonnull align 8 dereferenceable(8) %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* noundef nonnull align 8 dereferenceable(8) %14, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* noundef @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
  %16 = bitcast %"class.std::shared_ptr.12"* %1 to %"class.std::__shared_ptr_access.14"*
  %17 = 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) %16) #3
  %18 = call noundef nonnull align 8 dereferenceable(32) %"class.std::__cxx11::basic_string"* @_ZNK4mqtt7message9get_topicB5cxx11Ev(%"class.mqtt::message"* noundef nonnull align 8 dereferenceable(120) %17)
  %19 = call noundef i8* @_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5c_strEv(%"class.std::__cxx11::basic_string"* noundef nonnull align 8 dereferenceable(32) %18) #3
  %20 = call i32 (i8*, ...) @printf(i8* noundef getelementptr inbounds ([11 x i8], [11 x i8]* @.str.19, i64 0, i64 0), i8* noundef %19)
  ret void
}

Any suggestions on this, I am not sure if I am getting the right address.

@jdoerfert bro, did it by using some predefined functions.