2 * @brief C file implementing IO logging
4 /* Compile the profiler by running `make`.
6 * Run using the xapian-io-profile script, which expects profiler.so to be in the same directory as the script:
8 * ./xapian-io-profile --log=log_file_name ./executable
10 * The resulting log can be analysed with strace-analyse:
12 * ./strace-analyse log_file_name
25 /* Work out the appropriate printf specifier for off_t. */
26 #if SIZEOF_OFF_T == SIZEOF_INT
27 # define FORMAT_OFF_T "d"
28 #elif SIZEOF_OFF_T == SIZEOF_LONG
29 # define FORMAT_OFF_T "ld"
30 #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
31 # define FORMAT_OFF_T "lld"
34 /* Pick a suitable `off64_t` type to use for pread64(), etc. */
36 # define OFF64_T off_t
37 # define FORMAT_OFF64_T FORMAT_OFF_T
38 #elif SIZEOF_LONG == 8
40 # define FORMAT_OFF64_T "ld"
41 #elif SIZEOF_LONG_LONG == 8
42 # define OFF64_T long long
43 # define FORMAT_OFF64_T "lld"
46 // function for logging calls
48 void logcall(const char *format
, ...)
50 static FILE *file_ptr
= NULL
;
51 int saved_errno
= errno
;
52 if (file_ptr
== NULL
) {
53 char *fd_str
= getenv("XAPIAN_IO_PROFILE_LOG_FD");
55 int fd
= atoi(fd_str
);
56 file_ptr
= fdopen(fd
, "w");
62 va_start(args_ptr
, format
);
63 vfprintf(file_ptr
, format
, args_ptr
);
70 typedef int (*real_open_t
)(const char *, int, mode_t
);
72 int open(const char *pathname
, int flags
, mode_t mode
)
74 static real_open_t real_open
= NULL
;
76 real_open
= (real_open_t
)dlsym(RTLD_NEXT
, "open");
78 int fd
= real_open(pathname
, flags
, mode
);
79 // realpath can set errno
80 int saved_errno
= errno
;
81 char *abspath
= realpath(pathname
, NULL
);
83 logcall("open(\"%s\",,) = %d\n", abspath
, fd
);
86 // display pathname in case realpath fails
87 logcall("open(\"%s\",,) = %d\n", pathname
, fd
);
94 // wrapper for open64()
96 typedef int (*real_open64_t
)(const char *, int, mode_t
);
98 int open64(const char *pathname
, int flags
, mode_t mode
)
100 static real_open64_t real_open64
= NULL
;
102 real_open64
= (real_open64_t
)dlsym(RTLD_NEXT
, "open64");
104 int fd
= real_open64(pathname
, flags
, mode
);
105 // realpath can set errno
106 int saved_errno
= errno
;
107 char *abspath
= realpath(pathname
, NULL
);
109 logcall("open(\"%s\",,) = %d\n", abspath
, fd
);
112 // display pathname in case realpath fails
113 logcall("open(\"%s\",,) = %d\n", pathname
, fd
);
120 // wrapper for close()
122 typedef int (*real_close_t
)(int);
126 static real_close_t real_close
= NULL
;
128 real_close
= (real_close_t
)dlsym(RTLD_NEXT
, "close");
130 int return_val
= real_close(fd
);
131 logcall("close(%d) = %d\n", fd
, return_val
);
135 #ifdef HAVE_FDATASYNC
136 // wrapper for fdatasync()
138 typedef ssize_t (*real_fdatasync_t
)(int);
140 ssize_t
fdatasync(int fd
)
142 static real_fdatasync_t real_fdatasync
= NULL
;
143 if (!real_fdatasync
) {
144 real_fdatasync
= (real_fdatasync_t
)dlsym(RTLD_NEXT
, "fdatasync");
146 ssize_t return_val
= real_fdatasync(fd
);
147 logcall("fdatasync(%d) = %ld\n", fd
, return_val
);
153 // wrapper for fsync()
155 typedef ssize_t (*real_fsync_t
)(int);
157 ssize_t
fsync(int fd
)
159 static real_fsync_t real_fsync
= NULL
;
161 real_fsync
= (real_fsync_t
)dlsym(RTLD_NEXT
, "fsync");
163 ssize_t return_val
= real_fsync(fd
);
164 logcall("fsync(%d) = %ld\n", fd
, return_val
);
169 // wrapper for pread()
171 typedef ssize_t (*real_pread_t
)(int, void *, size_t, off_t
);
173 ssize_t
pread(int fd
, void *buf
, size_t count
, off_t offset
)
175 static real_pread_t real_pread
= NULL
;
177 real_pread
= (real_pread_t
)dlsym(RTLD_NEXT
, "pread");
179 ssize_t return_val
= real_pread(fd
, buf
, count
, offset
);
180 logcall("pread(%d, \"\", %zu, %" FORMAT_OFF_T
") = %zd\n",
181 fd
, count
, offset
, return_val
);
186 // wrapper for pread64()
188 typedef ssize_t (*real_pread64_t
)(int, void *, size_t, OFF64_T
);
190 ssize_t
pread64(int fd
, void *buf
, size_t count
, OFF64_T offset
)
192 static real_pread64_t real_pread64
= NULL
;
194 real_pread64
= (real_pread64_t
)dlsym(RTLD_NEXT
, "pread64");
196 ssize_t return_val
= real_pread64(fd
, buf
, count
, offset
);
197 logcall("pread(%d, \"\", %zu, %" FORMAT_OFF64_T
") = %zd\n",
198 fd
, count
, offset
, return_val
);
203 // wrapper for pwrite()
205 typedef ssize_t (*real_pwrite_t
)(int, const void *, size_t, off_t
);
207 ssize_t
pwrite(int fd
, const void *buf
, size_t count
, off_t offset
)
209 static real_pwrite_t real_pwrite
= NULL
;
211 real_pwrite
= (real_pwrite_t
)dlsym(RTLD_NEXT
, "pwrite");
213 ssize_t return_val
= real_pwrite(fd
, buf
, count
, offset
);
214 logcall("pwrite(%d, \"\", %zu, %" FORMAT_OFF_T
") = %zd\n",
215 fd
, count
, offset
, return_val
);
220 // wrapper for pwrite64()
222 typedef ssize_t (*real_pwrite64_t
)(int, const void *, size_t, OFF64_T
);
224 ssize_t
pwrite64(int fd
, const void *buf
, size_t count
, OFF64_T offset
)
226 static real_pwrite64_t real_pwrite64
= NULL
;
227 if (!real_pwrite64
) {
228 real_pwrite64
= (real_pwrite64_t
)dlsym(RTLD_NEXT
, "pwrite64");
230 ssize_t return_val
= real_pwrite64(fd
, buf
, count
, offset
);
231 logcall("pwrite(%d, \"\", %zu, %" FORMAT_OFF64_T
") = %zd\n",
232 fd
, count
, offset
, return_val
);