Re:question about Insert callInst to call a function in library

Thanks Chris, but the method you mentioned is not what I want. Maybe I didn't make it clear.
As you said, /runtime/libprofile is runtime library for the following function.
    llvm_start_func_profiling
    llvm_start_block_profiling
    llvm_start_basic_block_tracing
    llvm_trace_basic_block

And those above functions can be inserted into basic block etc for getting profile. However, those functions are wroten by C/C++ which just statistic some data.
What I want is to write a Pass in external library. You know for the Pass, it will use LLVM methods. I can write a pass but I just don't know how to put the pass into external library and insert CallInst to call it like llvm_start_func_profiling. I mean I could insert a CallInst into *.bc to call function in the exernal library, but is it possible that the function in library will use LLVM method and will use itself bytecode file as input file?

for example: m.bc is orignal bytecode.
mutated bytecode is m1.bc. I would like to insert a CallInst to call decode function to recover original bytecode m.bc. Actually, I would to compile m1.bc and decode library to executed file, and once I run m1, at first the decode function at entry of main should be run before any code running. So now the decode part is llvm pass, could I do it like what I want? Thanks

Qiuyu

decode pass:

using namespace llvm;
#define endl "\n"
namespace {
  struct DecodeStr : public FunctionPass{
    virtual bool runOnFunction(Function &F);
  private:
    void DecodeString(Module *M);
    void get_randKey(Module *M);
    Constant *randKey;
  };
  RegisterOpt<DecodeStr> X("DecodeStr", "Decode to visible string");
}

bool DecodeStr::runOnFunction(Function &F){
  get_randKey(F.getParent());
  DecodeString(F.getParent());
  return true;
}
void DecodeStr::get_randKey(Module *M){
  for(Module::giterator gI=M->gbegin(),gE=M->gend();gI!=gE;++gI){
    std::string GVname = gI->getName();
    if(strcmp(GVname.c_str(),"Gvkey")==0){
      randKey =(gI->getInitializer());
    }
  }
}

void DecodeStr::DecodeString(Module *M){
  std::cerr<<"filename "<<M->getModuleIdentifier()<<endl;
  for(Module::giterator gI = M->gbegin(),gE=M->gend();gI!=gE;++gI){
    unsigned i=0;
    if(ConstantArray *Cstr = dyn_cast<ConstantArray>(gI->getInitializer())){
      if(Cstr->getType()->getElementType()->isInteger())
      {
std::vector<Constant*> HideString;
   Constant *Key=ConstantInt::get(Cstr->getType()->getElementType(),randKey);
  for(unsigned i=0;i<Cstr->getNumOperands();++i){
   HideString.push_back(ConstantExpr::getXor(Cstr->getOperand(i),randKey));
}
gI->setInitializer(ConstantArray::get(Cstr->getType(),HideString));
std::cerr<<"after set "<<*(gI->getInitializer())<<endl;
      }
    }
  }
}

Thanks Chris, but the method you mentioned is not what I want. Maybe I didn't make it clear.
As you said, /runtime/libprofile is runtime library for the following function.
    llvm_start_func_profiling
    llvm_start_block_profiling
    llvm_start_basic_block_tracing
    llvm_trace_basic_block

And those above functions can be inserted into basic block etc for getting profile. However, those functions are wroten by C/C++ which just statistic some data.
What I want is to write a Pass in external library. You know for the Pass, it will use LLVM methods. I can write a pass but I just don't know how to put the pass into external library and insert CallInst to call it like llvm_start_func_profiling. I mean I could insert a CallInst into *.bc to call function in the exernal library, but is it possible that the function in library will use LLVM method and will use itself bytecode file as input file?

for example: m.bc is orignal bytecode. mutated bytecode is m1.bc. I
would like to insert a CallInst to call decode function to recover
original bytecode m.bc. Actually, I would to compile m1.bc and decode
library to executed file, and once I run m1, at first the decode
function at entry of main should be run before any code running. So now
the decode part is llvm pass, could I do it like what I want? Thanks

It is no problem to insert an arbitrary function call to an arbitrary
chunk of code into a program. For exmaple, 'llvm_start_func_profiling'
gets inserted by the profiling code into a program's main, and is
implemented in a library.

Calling an LLVM pass is no different, but you have to remember what you're
getting. First of all, this would require all of the LLVM compiler to be
available at runtime and linked into the program (this is no small amount
of code). Second, if you mutated bytecode you got from somewhere, it
would not change the already compiled code.

I see two ways to get what you want here. First, instead of calling an
LLVM pass at runtime, just call a function. I do not see why this is so
hard. In particular, at compile time, encrypt your string so that the
program looks like this:

char yourstring[] = "fkasfalksfjalskdfj";

Then insert a call into main:

void main() {
  decrypt(yourstring, length);

}

There is no reason why 'decrypt' needs to be an llvm pass. It can just be
a simple for loop.

The second way to do this is to play funny games with the JIT, modifying
code before it gets code generated. This is entirely possible, but I
don't think you need to do this to achieve your goals.

I'm going to be out of town for several days, but hopefully this will
help.

-Chris

Qiuyu

decode pass:

using namespace llvm;
#define endl "\n"
namespace {
  struct DecodeStr : public FunctionPass{
    virtual bool runOnFunction(Function &F);
  private:
    void DecodeString(Module *M);
    void get_randKey(Module *M);
    Constant *randKey;
  };
  RegisterOpt<DecodeStr> X("DecodeStr", "Decode to visible string");
}

bool DecodeStr::runOnFunction(Function &F){
  get_randKey(F.getParent());
  DecodeString(F.getParent());
  return true;
}
void DecodeStr::get_randKey(Module *M){
  for(Module::giterator gI=M->gbegin(),gE=M->gend();gI!=gE;++gI){
    std::string GVname = gI->getName();
    if(strcmp(GVname.c_str(),"Gvkey")==0){
      randKey =(gI->getInitializer());
    }
  }
}

void DecodeStr::DecodeString(Module *M){
  std::cerr<<"filename "<<M->getModuleIdentifier()<<endl;
  for(Module::giterator gI = M->gbegin(),gE=M->gend();gI!=gE;++gI){
    unsigned i=0;
    if(ConstantArray *Cstr = dyn_cast<ConstantArray>(gI->getInitializer())){
      if(Cstr->getType()->getElementType()->isInteger())
      {
std::vector<Constant*> HideString;
   Constant *Key=ConstantInt::get(Cstr->getType()->getElementType(),randKey);
  for(unsigned i=0;i<Cstr->getNumOperands();++i){
   HideString.push_back(ConstantExpr::getXor(Cstr->getOperand(i),randKey));
}
gI->setInitializer(ConstantArray::get(Cstr->getType(),HideString));
std::cerr<<"after set "<<*(gI->getInitializer())<<endl;
      }
    }
  }
}

>
> > Hi,
> >
> > Thanks Chris. Following your suggestion, I wrote the code to hide the
> > visible string. Thanks again. Finially, I just realized my LLVM still is
> > 1.2, not 1.3. Now I update it to 1.3.
>
> ok.
>
> > > > > 5. Insert the for loop that translates the string when main runs.
> > > > >
> > > > > For #5, write the for loop you want, compile it with llvmgcc, then figure
> > > > > out how to generate it at compile time. Alternatively, you could put the
> > > > > 'decryption' routine in a library and just insert a call to the library.
> >
> > For decode part. I can write a pass to decode the hide-string bytecode(
> > after hide string pass, I create a globalvariable to store the Key for
> > decode routine. And on the decode pass, I use this Key to recover the
> > orignal bytecode.
>
> Sure.
>
> > It seems not good way to decode. The better way should be to embed the
> > decode routine into the bytecode in the entry of main. So the question
> > is how to do it?
>
> That's fine, take a look at how the profiling instrumentation code works
> in lib/Transforms/Instrumentation. That should give you examples of how
> to insert function calls. grep for 'new CallInst'.
>
> > What I can do is that,
> > I can create call instruction and insert it into entry BB of main.
> > And this call function is able to call the a function of the external
> > library which I could create as I want( just using C style). And I can
> > write decode pass, but I don't know how to build a library as the way
> > you mentioned. Actually, I was thinking the pass I wrote is a dynamic
> > library as libdecode.so. So could I use it? if not, how to build the
> > library you mentioned? I thought the library you mentioned should be
> > similar with the pass. However, I have no idea how combine them?
>
> Yes, this is no problem. The profiling instrumentation inserts function
> calls which get resolved to the llvm/runtime/libprofile library. Please
> look at how that works and you can pattern off of that.
>
> -Chris
>

_______________________________________________
LLVM Developers mailing list
LLVMdev@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev

-Chris