0
#include <stdio.h>
#include <string.h>    
int foo(char* a)
    { char str[10];
      if (strlen(a)<10) 
     { 
       sprintf(str,"Yes");
       puts(str);
       return 0;
     }
     else
     {
       sprintf(str,"No");
       puts(str);
       return 1;
     }
    }

Now, lets say while writing a LLVM pass, I want to ensure that instead of calling sprintf, printf is called instead (with the same arguments). How could I go about doing that?

t7t0t0t7t
  • 362
  • 3
  • 5
  • 1
    This doesn't make any sense. The prototypes for `sprintf` and `printf` are different. And you're not passing enough arguments to `sprintf` in your example. What exactly are you trying to accomplish? – Jonathon Reinhart Nov 24 '13 at 23:49
  • 1
    Fixed it. I would rather have a single printf() replace {sprintf()+puts()} through LLVM pass. I'm trying out LLVM for the first time, was wondering how could one go about doing that. – t7t0t0t7t Nov 24 '13 at 23:56

2 Answers2

2

In a nutshell,

  1. Go over all instructions in the function.
  2. If the instruction is a CallInst, check if it's a call to sprintf (you can just check its name).
  3. Create a new CallInst (via CallInst::Create) that calls printf instead of sprintf. I think the easiest way to get the Value of the printf declaration is to use one of the Module::getOrCreate methods. The type of printf should be the same as the one for sprintf minus the first parameter.
  4. Set the operands of the new call instructions to be the same as for sprintf, minus the first parameter.
  5. Replace the old call with the new call - replaceInstWithInst (in BasicBlockUtils.h) is probably the most convenient way.
  6. Finally, you might want to track the usages of the old first parameter, remove them all and then remove it - so you'd get rid of that puts call.
Oak
  • 26,231
  • 8
  • 93
  • 152
0
#ifdef USE_BUFFER
#define my_printf(...) sprintf(buffer, __VA_ARGS__)
#else
#define my_printf(...) printf(__VA_ARGS__)
#endif

Now you can use for instance my_printf("My name is %s.", "Bozo"); and it will compile as if it was printf("My name is %s.", "Bozo") by default.

If you include #define USE_BUFFER before the headers, it will instead convert those lines to sprintf(buffer, "My name is %s.", "Bozo") at compile time. Of course the variable buffer must exist in the context.

Havenard
  • 27,022
  • 5
  • 36
  • 62
  • 1
    This requires modification of the source code before compilation, which doesn't seem to me like what the OP was asking for (although this was accepted). – Oak Nov 25 '13 at 07:26