【问题标题】:Changing source code at compilation time (using LLVM)在编译时更改源代码(使用 LLVM)
【发布时间】:2013-11-24 23:47:34
【问题描述】:
#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;
     }
    }

现在,假设在编写 LLVM 通行证时,我想确保不是调用 sprintf,而是调用 printf(使用相同的参数)。我该怎么做呢?

【问题讨论】:

  • 这没有任何意义。 sprintfprintf 的原型不同。在您的示例中,您没有向 sprintf 传递足够的参数。你到底想完成什么?
  • 已修复。我宁愿用一个 printf() 替换 {sprintf()+puts()} 通过 LLVM 传递。我是第一次尝试 LLVM,想知道如何去做。

标签: llvm llvm-clang llvm-ir


【解决方案1】:

简而言之,

  1. 查看函数中的所有指令。
  2. 如果指令是CallInst,请检查它是否是对sprintf 的调用(您可以只检查它的名称)。
  3. 创建一个新的CallInstvia CallInst::Create) 调用printf 而不是sprintf。我认为获得printf 声明的Value 的最简单方法是使用Module::getOrCreate 之一方法。printf 的类型应与sprintf 的类型相同,但减去第一个参数。
  4. 将新调用指令的操作数设置为与sprintf 相同,减去第一个参数。
  5. 用新调用替换旧调用 - replaceInstWithInst (in BasicBlockUtils.h) 可能是最方便的方法。
  6. 最后,您可能想要跟踪旧的第一个参数的使用情况,将它们全部删除,然后将其删除 - 这样您就可以摆脱 puts 调用。

【讨论】:

    【解决方案2】:
    #ifdef USE_BUFFER
    #define my_printf(...) sprintf(buffer, __VA_ARGS__)
    #else
    #define my_printf(...) printf(__VA_ARGS__)
    #endif
    

    现在你可以使用my_printf("My name is %s.", "Bozo");,它会像默认printf("My name is %s.", "Bozo")一样编译。

    如果您在标题前包含#define USE_BUFFER,它将在编译时将这些行转换为sprintf(buffer, "My name is %s.", "Bozo")。当然,变量buffer 必须存在于上下文中。

    【讨论】:

    • 这需要在编译之前修改源代码,在我看来这不像 OP 所要求的(尽管这已被接受)。
    猜你喜欢
    • 1970-01-01
    • 2014-12-21
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 2018-11-26
    相关资源
    最近更新 更多