【问题标题】:How to redirect llvm::outs() to file?如何将 llvm::outs() 重定向到文件?
【发布时间】:2014-12-06 16:06:51
【问题描述】:

我正在使用一些 LLVM 工具(如 llvm-nm)作为静态库。 IE。我复制了源 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); 

问题是它没有被转发(如果我在 nm 源代码中添加 printf() 但不适用于 nm 输出)。我查看了源代码,我可以看到输出是使用 llvm::outs() 流完成的:

outs() << "Archive map" << "\n";

还有it's implemented下一条路:

/// 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 }

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

【问题讨论】:

    标签: c++ stream llvm nm


    【解决方案1】:

    我意识到这是一个老问题,但是,我在查找 llvm 的 outs() 流的一些简单信息时遇到了它,我发现了 here

    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;
    
      ...
    

    所以它似乎表明你可以安全地重定向。

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2014-09-30
        • 2013-04-12
        • 1970-01-01
        • 2015-03-10
        • 1970-01-01
        • 2023-03-03
        • 2023-03-06
        • 2019-01-05
        • 2017-03-26
        相关资源
        最近更新 更多