running a module pass via opt on multiple bitcode files

Hi,

I’m trying to implement a module pass as a share object to process an entire program as a unit. The target program is built from multiple object files, hence multiple bitcode files. However, it seems that opt does not take the whole program, but just one bitcode file, “test.bc” in the example run shown below.

$ opt -load mypass.dylib -mymodulepass < test.bc > /dev/null

How do I run my module pass in a library on a whole program?

Thanks.

Hi,

I’m trying to implement a module pass as a share object to process an entire program as a unit. The target program is built from multiple object files, hence multiple bitcode files. However, it seems that opt does not take the whole program, but just one bitcode file, “test.bc” in the example run shown below.

$ opt -load mypass.dylib -mymodulepass < test.bc > /dev/null

How do I run my module pass in a library on a whole program?

Link the bitcode files together into a single bitcode file with llvm-ld. You can
then run the single bitcode file through opt.

I think it would be better to link them with the (simpler) llvm-link.

Ciao, Duncan.

Thanks John. Your approach worked fine for my small toy program. Now, I would like to run my module pass on a huge project (still a single executable) consisting of a few thousand bit code files scattered in many different directories. And some of them are static libraries. Do you still think it’s a good idea to manually gather and link them with llvm-ld? I’ve seen other module pass implementations where they directly patch a specific version of LLVM or clang, instead of running a shared object implementation with opt. Which would be the ideal approach to analyze a program with a module pass? Thanks.

Thanks John. Your approach worked fine for my small toy program. Now, I would like to run my module pass on a huge project (still a single executable) consisting of a few thousand bit code files scattered in many different directories. And some of them are static libraries. Do you still think it’s a good idea to manually gather and link them with llvm-ld? I’ve seen other module pass implementations where they directly patch a specific version of LLVM or clang, instead of running a shared object implementation with opt. Which would be the ideal approach to analyze a program with a module pass? Thanks.

Thanks John. Your approach worked fine for my small toy program. Now, I would like to run my module pass on a huge project (still a single executable) consisting of a few thousand bit code files scattered in many different directories. And some of them are static libraries. Do you still think it’s a good idea to manually gather and link them with llvm-ld? I’ve seen other module pass implementations where they directly patch a specific version of LLVM or clang, instead of running a shared object implementation with opt. Which would be the ideal approach to analyze a program with a module pass? Thanks.

Thanks John. I appreciate your help.

De nada.

I have taken the libLTO approach and it worked like a charm :slight_smile: For those who wanted to achieve the same thing, below are the steps I’ve taken.

John – a small question: I thought I wouldn’t need to touch Makefiles at all, but that wasn’t the case. Could you take a look at Step 4) and tell me what you think? Thanks!

A properly written project will allow the person compiling the software to easily change the compiler and the compiler/linker flags used.

For example, autoconf-based configure scripts usually use the following environment variables:

CC - C compiler
CXX - C++ compiler
CFLAGS - compiler flags
LDFLAGS - linker flags

So, you would do the following in sh/ksh syntax:

CC=llvm-gcc
CXX=llvm-g++
CFLAGS="-emit-llvm"
export CC
export CXX
export CFLAGS
./configure

  1. Create your own libLTO and add your pass to it. Do a code diff between /safecode/tools/LTO/LTOCodeGenerator.cpp and /llvm/tools/lto/LTOCodeGenerator.cpp to figure out what changes are needed to do this.
  2. Make a backup copy of the original linker /usr/lib/libLTO.dylib.
  3. Copy your libLTO.dylib to /usr/lib.
  4. Open Makefiles in your target project and change CC and CFLAGS as follows:

CC=llvm-gcc
CFLAGS=-emit-llvm …

  1. Build the project with LLVM.

– John T.

Ah, I just tried with a properly written project and everything worked smoothly. Thanks John.