#Linux system calls, glibc wrappers debugging

14 messages · Page 1 of 1 (latest)

pale forge
#

so, in C this snippet: int fd = open(/*etc...*/); according to Godbolt is directly running system call number, whatever it is, by firstly placing the necessary params in the correct registers, but manual testing shows that's not true, this snippet is actually a call to a custom made function in glibc (since I am running gcc to compile this snippet) which is declared according to the preprocessor as:

# 168 "/usr/include/fcntl.h" 3 4
extern int open (const char *__file, int __oflag, ...) __attribute__ ((__nonnull__ (1)));

but its implementation is not visible since glibc has no debug symbols, cause I have not recompiled gcc and therefore glibc with debug symbols, but the debugger does pinpoint to the nonexistent on my system file that does have the implementation:
https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/open64.c#L36
so... how did a call to open magically turn into a call to __libc_open64 (some linker symbol resolution magic maybe??? ),
and most importantly,

return SYSCALL_CANCEL (openat, AT_FDCWD, file, oflag | EXTRA_OPEN_FLAGS,
             mode);

what does this funky macro SYSCALL_CANCEL do?

GitHub

GNU Libc - Extremely old repo used for research purposes years ago. Please do not rely on this repo. - lattera/glibc

hardy sunBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

pale forge
#

Kay so I found that macro

#

!f

hardy sunBOT
#

91 ```cpp
#define SYSCALL_CANCEL(...)
92 ({
93 long int sc_ret;
94 if (SINGLE_THREAD_P)
95 sc_ret = INLINE_SYSCALL_CALL (VA_ARGS);
96 else
97 {
98 int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();
99 sc_ret = INLINE_SYSCALL_CALL (VA_ARGS);
100 LIBC_CANCEL_RESET (sc_cancel_oldtype);
101 }
102 sc_ret;
103 }

kolio_98
pale forge
#

sigh, now I gotta decrypt this thing too

#
 83 /* Issue a syscall defined by syscall number plus any other argument
 84    required.  Any error will be handled using arch defined macros and errno
 85    will be set accordingly.
 86    It is similar to INLINE_SYSCALL macro, but without the need to pass the
 87    expected argument number as second parameter.  */
 88 #define INLINE_SYSCALL_CALL(...) \
 89   __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)

pale forge
#

kay so after loads of macro tracking, I can see

sc_ret = INLINE_SYSCALL(openat, 4, AT_FDCWD, file, oflag | EXTRA_OPEN_FLAGS, mode)
#

and here, we get loads of differences for different CPU architectures

#

./sysdeps/unix/sysv/linux/x86_64/sysdep.h:193:# define INLINE_SYSCALL(name, nr, args...) \
this may be the snippet I need

#
193 # define INLINE_SYSCALL(name, nr, args...) \
194   ({                                                                          \
195     unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args);        \
196     if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, )))            \
197       {                                                                       \
198         __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                   \
199         resultvar = (unsigned long int) -1;                                   \
200       }                                                                       \
201     (long int) resultvar; })
202

#
298 #undef internal_syscall4
299 #define internal_syscall4(number, err, arg1, arg2, arg3, arg4)          \
300 ({                                                                      \
301     unsigned long int resultvar;                                        \
302     TYPEFY (arg4, __arg4) = ARGIFY (arg4);                              \
303     TYPEFY (arg3, __arg3) = ARGIFY (arg3);                              \
304     TYPEFY (arg2, __arg2) = ARGIFY (arg2);                              \
305     TYPEFY (arg1, __arg1) = ARGIFY (arg1);                              \
306     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;                   \
307     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;                   \
308     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;                   \
309     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;                   \
310     asm volatile (                                                      \
311     "syscall\n\t"                                                       \
312     : "=a" (resultvar)                                                  \
313     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)          \
314     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);                        \
315     (long int) resultvar;                                               \
316 })

hmmm, so this macro must be doing the register preparing and then syscall

#

if only I could just, skip the libc macros and just read the assembly with gdb directly

pale forge
#

!solved