我使用一些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);
问题是它没有被转发(如果我在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 }
如何将输出重定向到我的文件?
3条答案
按热度按时间brjng4g31#
我意识到这是一个老问题,然而,我在查找llvm的outs()流的一些简单信息时遇到了这个问题,我找到了here。
llvm“BrainF”附带的一个示例是这样使用的:
所以它似乎表明你可以安全地重新定向。
注意:在本例中,OutputFilename/InputFilename是使用llvm的Support Library CommandLine创建的std::string类型。
mefy6pfw2#
似乎没有一个简单的方法可以做到这一点:在
llvm::raw_fd_ostream
和llvm::raw_ostream
中都没有复制/赋值构造函数。freopen
技巧也不起作用,因为文件描述器整数用于初始化llvm::outs()
返回的对象。我看到的唯一方法是使用LD_PRELOAD动态地更改
llvm::outs()
的实现,或者类似的链接器技巧,但这对我来说听起来非常古怪。也许把原始符号标记为弱符号,然后在你的库中覆盖它?6bc51xsx3#
如果你愿意容忍一些未定义的行为,你可以这样做:
这是通过劫持vtable指针来挂钩
write_impl
,current_pos
和preferred_buffer_size
函数。这些行被累加并传递给hijack_log_line
函数。这取决于
llvm::outs()
在内部使用static raw_fd_ostream S;
的实现细节。我们从这个类继承来确保内存布局是兼容的,但是如果这个实现改变,它可能会中断。