2016-05-17 13 views
2

我有以下的C程序:我的编译器如何查找stat(文件状态)函数?

#include <sys/stat.h> 

int main(int argc, char **argv) { 
    struct stat fileStat; 
    if(stat(argv[1],&fileStat) < 0)  
     return 1; 
} 

当我它编译使用锵LLVM IR到,我可以看到stat被声明为以下:

declare i32 @stat(i8*, %struct.stat*) 

通常,这样的外部呼叫到系统函数直接映射到C标准库函数。例如,我可以找到malloc有以下几点:

nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep malloc 

然而,stat功能似乎要区别对待。当grepping为stat时,我可以找到相关函数,如__xstat,但不是stat函数本身。

当我通过ltrace跟踪到外部库的调用时,我看到以下调用:__xstat(1, ".", 0x7fff7928c6f0)。此外,可执行文件中的代码还确认,不是调用stat函数,而是调用__xstat函数。

我没有观察到C标准库的其他函数调用的名称与C程序中声明的名称不同。为什么在标准库中没有直接的等价物,我的编译器如何发现它应该调用__xstat而不是stat

+1

这可能会帮助你很多http://stackoverflow.com/questions/8237294/intercepting-stat –

回答

4

部首sys/stat.hstat定义为,在glibc的调用__xstat宏:

#define stat(fname, buf) __xstat (_STAT_VER, fname, buf) 
+1

但是,如果'stat'是一个宏,那么这个宏应该已经被Clang解决了,并且在LLVM位代码中的调用文件应该去'__xstat'或不? – box

1

我发现在/usr/include/x86_64-linux-gnu/sys/stat.h以下注释:

/* To allow the `struct stat' structure and the file type `mode_t' 
    bits to vary without changing shared library major version number, 
    the `stat' family of functions and `mknod' are in fact inline 
    wrappers around calls to `xstat', `fxstat', `lxstat', and `xmknod', 
    which all take a leading version-number argument designating the 
    data structure and bits used. <bits/stat.h> defines _STAT_VER with 
    the version number corresponding to `struct stat' as defined in 
    that file; and _MKNOD_VER with the version number corresponding to 
    the S_IF* macros defined therein. It is arranged that when not 
    inlined these function are always statically linked; that way a 
    dynamically-linked executable always encodes the version number 
    corresponding to the data structures it uses, so the `x' functions 
    in the shared library can adapt without needing to recompile all 
    callers. */ 

# ifdef __REDIRECT_NTH 
extern int __REDIRECT_NTH (stat, (const char *__restrict __file, 
        struct stat *__restrict __buf), stat64) 
    __nonnull ((1, 2)); 
# endif 

__REDIRECT_NTH/usr/include/x86_64-linux-gnu/sys/cdefs.h定义:

/* __asm__ ("xyz") is used throughout the headers to rename functions 
    at the assembly language level. This is wrapped by the __REDIRECT 
    macro, in order to support compilers that can do this some other 
    way. When compilers don't support asm-names at all, we have to do 
    preprocessor tricks instead (which don't have exactly the right 
    semantics, but it's the best we can do). 

    Example: 
    int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ 

#if defined __GNUC__ && __GNUC__ >= 2 

# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) 
# ifdef __cplusplus 
# define __REDIRECT_NTH(name, proto, alias) \ 
    name proto __THROW __asm__ (__ASMNAME (#alias)) 
# define __REDIRECT_NTHNL(name, proto, alias) \ 
    name proto __THROWNL __asm__ (__ASMNAME (#alias)) 
# else 
# define __REDIRECT_NTH(name, proto, alias) \ 
    name proto __asm__ (__ASMNAME (#alias)) __THROW 
# define __REDIRECT_NTHNL(name, proto, alias) \ 
    name proto __asm__ (__ASMNAME (#alias)) __THROWNL 
# endif 
# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) 
# define __ASMNAME2(prefix, cname) __STRING (prefix) cname 

从注释和宏定义看来,别名是在内联汇编程序中指定的。