Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using C++ files for rtlib #8

Closed
ghost opened this issue Mar 29, 2016 · 11 comments
Closed

Using C++ files for rtlib #8

ghost opened this issue Mar 29, 2016 · 11 comments

Comments

@ghost
Copy link

ghost commented Mar 29, 2016

Did you ever attempt to use C++ for calling a runtime library, or was the mangling too big of an issue to overcome?

@sampsyo
Copy link
Owner

sampsyo commented Mar 29, 2016

I've never done it, but if I did, I would probably use extern "C" to avoid mangling in the run-time hooks. (You can of course still call into general C++ from there.)

@ghost
Copy link
Author

ghost commented Mar 29, 2016

Well I'll give that a try.

@ghost
Copy link
Author

ghost commented Mar 29, 2016

It worked! Thank you.

@sampsyo
Copy link
Owner

sampsyo commented Mar 29, 2016

Woohoo!

@sampsyo sampsyo closed this as completed Mar 29, 2016
@LuoRongLuoRong
Copy link

LuoRongLuoRong commented Apr 15, 2022

And I world like to share my experiment.
I changed content of rtlib.c and example.c from c to cpp.
Then I run:

(base) fdse@ubuntu:~/luorong/LLVM/test/llvm-pass-skeleton$ ls
build  CMakeLists.txt  example.cpp  LICENSE  README.md  rtlib.cpp  skeleton
(base) fdse@ubuntu:~/luorong/LLVM/test/llvm-pass-skeleton$ g++ -c rtlib.cpp 
(base) fdse@ubuntu:~/luorong/LLVM/test/llvm-pass-skeleton$ clang++  -flegacy-pass-manager  -Xclang -load -Xclang build/skeleton/libSkeletonPass.so -c example.cpp
(base) fdse@ubuntu:~/luorong/LLVM/test/llvm-pass-skeleton$ ls
build           example.cpp  LICENSE    rtlib.cpp  skeleton
CMakeLists.txt  example.o    README.md  rtlib.o
(base) fdse@ubuntu:~/luorong/LLVM/test/llvm-pass-skeleton$ g++ example.o rtlib.o
example.o: In function `main':
example.cpp:(.text+0x35): undefined reference to `logop'
collect2: error: ld returned 1 exit status

Yes, it cannot find logop. So I check the difference between the ll file of rtlib.c and that of rtlib.cpp.

rtlib.c 's  ll
define dso_local void @logop(i32 %0) #0 !dbg !9

rtlib.cpp 's  ll
define dso_local void @_Z5logopi(i32 %0) #0 !dbg !9

So I changed the Skeleton.cpp from F.getParent()->getOrInsertFunction("logop", logFuncType); to F.getParent()->getOrInsertFunction("_Z5logopi", logFuncType);. And then it worked.

Hope it's helpful.

@sampsyo
Copy link
Owner

sampsyo commented Apr 15, 2022

If I were writing a run-time library in C++, I would use extern "C" to export a non-mangled name.

@LuoRongLuoRong
Copy link

If I were writing a run-time library in C++, I would use extern "C" to export a non-mangled name.

Thank you for your reply! I don't understand export a non-mangled name. What is a non-mangled name? My translator told me it means 'an unchanged name'. Does it mean that if I use extern C, the name of functions in LLVM IR won't change? For example, in rtlib.cpp's ll file, the function name logop is still logop?

And another problem: My application is to analyse C++ by using LLVM pass. So, will extern "c" destroy other functions of C++?

Thank you!😉

@sampsyo
Copy link
Owner

sampsyo commented Apr 16, 2022

I unfortunately can't help walk through the mechanics here, but the relevant term to Google is "C++ name mangling".

An extern "C" runtime function should not prevent you from instrumenting C++ programs.

@LuoRongLuoRong
Copy link

Thank you, sir! 😁😁 Today, I finnally understand what you told me.

image

(Because I am a green hand in C and C++, so I didn't understand what extern "C" means the other day.)

Hope it will help other students like me :)

@LuoRongLuoRong
Copy link

LuoRongLuoRong commented Apr 25, 2022

Hi, I still have some primary problems about using string in llvm pass.
I wanna use string as argument, like that:

extern "C" void logvar(int i, char* name) {
    std::cout << "Num: " << i << "; Name: " << name << std::endl;
}

And pass.cpp

// Get the function to call from our runtime library.
LLVMContext &Ctx = F.getContext();
std::vector<Type*> paramTypes = {  // Param Types
  Type::getInt32Ty(Ctx),
  Type::getInt8PtrTy(Ctx) 
};
Type *retType = Type::getVoidTy(Ctx);
FunctionType *logFuncType = FunctionType::get(retType, paramTypes, false);
FunctionCallee logFunc = F.getParent()->getOrInsertFunction("logvar", logFuncType);

Insert logvar in pass.cpp
for store instruction such as store i32 0, i32* %retval, align 4

// for store instruction
void insertLogvar(StoreInst *inst, BasicBlock &B, FunctionCallee logFunc, LLVMContext &Ctx) {
  IRBuilder<> builder(inst);
  builder.SetInsertPoint(&B, ++builder.GetInsertPoint());

  Value *argi = inst->getOperand(0);  // integer
  if (auto constant_int = dyn_cast<ConstantInt>(argi)) {
    Value* argstr = ???   // HERE
    Value* args[] = {argi, argstr}; 
    builder.CreateCall(logFunc, args);
  } else {
    errs() << "store inst has no instance number" << "\n";
  }
}

My question is how to accomplish argstr? To match string type.

Best wishes!

@LuoRongLuoRong
Copy link

I found the solution Value *argstr = builder.CreateGlobalString(arg2ins->getName()); 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants