2016-05-17 16 views
2

Ich habe folgende C-Programm:Wie findet mein Compiler die Stat (File Status) -Funktion?

#include <sys/stat.h> 

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

Als ich es LLVM IR mit Clang kompiliert, kann ich sehen, dass stat wie folgt erklärt:

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

Normalerweise sind solche, einen externen Anruf an Eine Systemfunktion wird direkt einer C-Standardbibliotheksfunktion zugeordnet. Zum Beispiel kann ich malloc mit dem folgenden:

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

jedoch die stat Funktion anders behandelt zu werden scheint. Wenn ich für stat greife, kann ich verwandte Funktionen wie __xstat aber nicht die stat Funktion selbst finden.

Wenn ich den Aufruf an die externe Bibliothek mit ltrace verfolgen, sehe ich den folgenden Aufruf: __xstat(1, ".", 0x7fff7928c6f0). Auch der Code in der ausführbaren Datei bestätigt, dass anstelle des Aufrufs der stat Funktion die __xstat Funktion aufgerufen wird.

Ich habe andere Funktionsaufrufe an die C-Standardbibliothek nicht beobachtet, die andere als die im C-Programm deklarierten Namen haben. Warum gibt es kein direktes Äquivalent in der Standardbibliothek und wie findet mein Compiler heraus, dass es einen Aufruf an __xstat und nicht an stat erzeugen sollte?

+1

Dies kann Ihnen eine Menge helfen http://stackoverflow.com/questions/8237294/intercepting-stat –

Antwort

4

Kopf sys/stat.h definiert stat als Makro, das __xstat in glibc ruft:

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

Aber wenn "stat" ein Makro ist, sollte das Makro bereits durch Clang und den Aufruf in der LLVM-Bitcode aufgelöst werden Datei sollte zu "__xstat" gehen oder nicht? – box

1

ich den folgenden Kommentar in /usr/include/x86_64-linux-gnu/sys/stat.h gefunden:

/* 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 definiert in /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 

Aus den Kommentaren und Makrodefinitionen scheint der Alias ​​in Inline-Assembler angegeben zu sein.