如何将llvm :: outs()重定向到文件?

4nt*_*ine 9 c++ stream llvm nm

我正在使用一些LLVM工具(如llvm-nm)作为静态库.即我复制源LLVM-nm.cpp,改名main(..)llvm_nm(..)和它编译成静态库.我想将标准输出转发到我的文件.

我试过用下一种方法:

  int    out_fd, err_fd;
  fpos_t out_pos, err_pos;

  // redirect out
  fflush(stdout);
  fgetpos(stdout, &out_pos);
  out_fd = dup(fileno(stdout));
  freopen(outFilename, "w", stdout);

  // execute
  int ret = llvm_nm(argc_, argv_);

  // restore output
  fflush(stdout);
  dup2(out_fd, fileno(stdout));
  close(out_fd);
  clearerr(stdout);
  fsetpos(stdout, &out_pos); 
Run Code Online (Sandbox Code Playgroud)

问题是它没有被转发(如果我添加printf()nm源代码而不是nm输出,它可以工作).我已经浏览了源码,我可以看到输出是使用llvm::outs()流完成的:

outs() << "Archive map" << "\n";
Run Code Online (Sandbox Code Playgroud)

它的实现下一个方法:

/// outs() - This returns a reference to a raw_ostream for standard output.
00702 /// Use it like: outs() << "foo" << "bar";
00703 raw_ostream &llvm::outs() {
00704   // Set buffer settings to model stdout behavior.
00705   // Delete the file descriptor when the program exits, forcing error
00706   // detection. If you don't want this behavior, don't use outs().
00707   static raw_fd_ostream S(STDOUT_FILENO, true);
00708   return S;
00709 }
Run Code Online (Sandbox Code Playgroud)

如何将该输出重定向到我的文件?

Mat*_*ers 5

我意识到这是一个老问题,然而,我遇到它查找llvm的outs()流的一些简单信息,我在这里找到.

llvm"BrainF"附带的一个示例使用如下:

  ...

  raw_ostream *out = &outs();
  if (!JIT) {
    if (OutputFilename == "") {
      std::string base = InputFilename;
      if (InputFilename == "-") { base = "a"; }

      // Use default filename.
      OutputFilename = base+".bc";
    }
    if (OutputFilename != "-") {
      std::error_code EC;
      out = new raw_fd_ostream(OutputFilename, EC, sys::fs::F_None);
    }
  }

  ...

  if (out != &outs())
    delete out;

  ...
Run Code Online (Sandbox Code Playgroud)

因此,它似乎表明您可以安全地重定向.

注意:在此示例中,OutputFilename/InputFilename是使用llvm的支持库CommandLine创建的std :: string类型.


ser*_*lle 2

似乎没有一个简单的方法可以做到这一点:在llvm::raw_fd_ostream和 中都没有复制/赋值构造函数llvm::raw_ostream。而且这个freopen技巧也不起作用,因为文件描述符整数用于初始化 . 返回的对象llvm::outs()

我看到的唯一方法是使用LD_PRELOADllvm::outs()来更改动态的实现,或类似的链接器技巧,但这对我来说听起来很老套。也许将原始符号标记为弱,然后在您的库中覆盖它?