关于 glibc 中 _IO_sputn 到 _IO_file_jumps 的作品
About works of _IO_sputn through _IO_file_jumps in glibc
感谢您阅读我的问题。
当我在 glibc 中调试 puts
函数时,我发现了一些无法理解的东西。
// glibc-2.27/libio/ioputs.c
int
_IO_puts (const char *str)
{
int result = EOF;
size_t len = strlen (str);
_IO_acquire_lock (stdout);
if ((_IO_vtable_offset (stdout) != 0
|| _IO_fwide (stdout, -1) == -1)
&& _IO_sputn (stdout, str, len) == len
&& _IO_putc_unlocked ('\n', stdout) != EOF)
result = MIN (INT_MAX, len + 1);
_IO_release_lock (stdout);
return result;
}
weak_alias (_IO_puts, puts)
(gdb中调用_IO_sputn
函数的一部分)
如您所见,_IO_puts
调用了 _IO_sputn
函数。
但是当我在 gdb 中检查 [r13+0x38] 时,有一个不同的值。
(不同值)
为什么_IO_sputn
函数是通过_IO_file_jumps
调用的?
_IO_file_jumps
在 glibc 中的作用是什么?
_IO_sputn
函数如何最终调用_IO_new_file_xsputn
?
<加法>
// glibc-2.27/libio/libioP.h
#define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n)
// glibc-2.27/libio/libioP.h
typedef size_t (*_IO_xsputn_t) (FILE *FP, const void *DATA,
size_t N);
#define _IO_XSPUTN(FP, DATA, N) JUMP2 (__xsputn, FP, DATA, N)
#define _IO_WXSPUTN(FP, DATA, N) WJUMP2 (__xsputn, FP, DATA, N)
// glibc-2.27/libio/libioP.h
struct _IO_jump_t
{
JUMP_FIELD(size_t, __dummy);
JUMP_FIELD(size_t, __dummy2);
JUMP_FIELD(_IO_finish_t, __finish);
JUMP_FIELD(_IO_overflow_t, __overflow);
JUMP_FIELD(_IO_underflow_t, __underflow);
JUMP_FIELD(_IO_underflow_t, __uflow);
JUMP_FIELD(_IO_pbackfail_t, __pbackfail);
/* showmany */
JUMP_FIELD(_IO_xsputn_t, __xsputn);
JUMP_FIELD(_IO_xsgetn_t, __xsgetn);
JUMP_FIELD(_IO_seekoff_t, __seekoff);
JUMP_FIELD(_IO_seekpos_t, __seekpos);
JUMP_FIELD(_IO_setbuf_t, __setbuf);
JUMP_FIELD(_IO_sync_t, __sync);
JUMP_FIELD(_IO_doallocate_t, __doallocate);
JUMP_FIELD(_IO_read_t, __read);
JUMP_FIELD(_IO_write_t, __write);
JUMP_FIELD(_IO_seek_t, __seek);
JUMP_FIELD(_IO_close_t, __close);
JUMP_FIELD(_IO_stat_t, __stat);
JUMP_FIELD(_IO_showmanyc_t, __showmanyc);
JUMP_FIELD(_IO_imbue_t, __imbue);
};
这是我可以通过 ctags 和 cscope.
找到的关于 _IO_sputn
的所有信息
Why _IO_sputn function is called through _IO_file_jumps ?
因为一个文件(“文件”作为一个对象)可能会以不同的方式实现放置字符,所以使用调度 table。
And what is _IO_file_jumps's role in glibc?
它是一个 dispatch table - 函数指针数组。它用于指定一个通用的 stable 虚拟接口,由不同的文件以不同的方式实现,这些文件需要对请求的操作进行不同的实现和抽象。
How can _IO_sputn function calls _IO_new_file_xsputn finally ?
一个function pointer is part of C language, that allows to call another function via a pointer that points to a function. _IO_sputn
is a macro that expands to a function call on that function pointer。宏的存在是为了简化将指向对象数据本身的指针传递给函数的过程——它不是特别漂亮,但简化了代码的编写。
感谢您阅读我的问题。
当我在 glibc 中调试 puts
函数时,我发现了一些无法理解的东西。
// glibc-2.27/libio/ioputs.c
int
_IO_puts (const char *str)
{
int result = EOF;
size_t len = strlen (str);
_IO_acquire_lock (stdout);
if ((_IO_vtable_offset (stdout) != 0
|| _IO_fwide (stdout, -1) == -1)
&& _IO_sputn (stdout, str, len) == len
&& _IO_putc_unlocked ('\n', stdout) != EOF)
result = MIN (INT_MAX, len + 1);
_IO_release_lock (stdout);
return result;
}
weak_alias (_IO_puts, puts)
(gdb中调用_IO_sputn
函数的一部分)
如您所见,_IO_puts
调用了 _IO_sputn
函数。
但是当我在 gdb 中检查 [r13+0x38] 时,有一个不同的值。
(不同值)
为什么
_IO_sputn
函数是通过_IO_file_jumps
调用的?_IO_file_jumps
在 glibc 中的作用是什么?_IO_sputn
函数如何最终调用_IO_new_file_xsputn
?
<加法>
// glibc-2.27/libio/libioP.h
#define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n)
// glibc-2.27/libio/libioP.h
typedef size_t (*_IO_xsputn_t) (FILE *FP, const void *DATA,
size_t N);
#define _IO_XSPUTN(FP, DATA, N) JUMP2 (__xsputn, FP, DATA, N)
#define _IO_WXSPUTN(FP, DATA, N) WJUMP2 (__xsputn, FP, DATA, N)
// glibc-2.27/libio/libioP.h
struct _IO_jump_t
{
JUMP_FIELD(size_t, __dummy);
JUMP_FIELD(size_t, __dummy2);
JUMP_FIELD(_IO_finish_t, __finish);
JUMP_FIELD(_IO_overflow_t, __overflow);
JUMP_FIELD(_IO_underflow_t, __underflow);
JUMP_FIELD(_IO_underflow_t, __uflow);
JUMP_FIELD(_IO_pbackfail_t, __pbackfail);
/* showmany */
JUMP_FIELD(_IO_xsputn_t, __xsputn);
JUMP_FIELD(_IO_xsgetn_t, __xsgetn);
JUMP_FIELD(_IO_seekoff_t, __seekoff);
JUMP_FIELD(_IO_seekpos_t, __seekpos);
JUMP_FIELD(_IO_setbuf_t, __setbuf);
JUMP_FIELD(_IO_sync_t, __sync);
JUMP_FIELD(_IO_doallocate_t, __doallocate);
JUMP_FIELD(_IO_read_t, __read);
JUMP_FIELD(_IO_write_t, __write);
JUMP_FIELD(_IO_seek_t, __seek);
JUMP_FIELD(_IO_close_t, __close);
JUMP_FIELD(_IO_stat_t, __stat);
JUMP_FIELD(_IO_showmanyc_t, __showmanyc);
JUMP_FIELD(_IO_imbue_t, __imbue);
};
这是我可以通过 ctags 和 cscope.
找到的关于_IO_sputn
的所有信息
Why _IO_sputn function is called through _IO_file_jumps ?
因为一个文件(“文件”作为一个对象)可能会以不同的方式实现放置字符,所以使用调度 table。
And what is _IO_file_jumps's role in glibc?
它是一个 dispatch table - 函数指针数组。它用于指定一个通用的 stable 虚拟接口,由不同的文件以不同的方式实现,这些文件需要对请求的操作进行不同的实现和抽象。
How can _IO_sputn function calls _IO_new_file_xsputn finally ?
一个function pointer is part of C language, that allows to call another function via a pointer that points to a function. _IO_sputn
is a macro that expands to a function call on that function pointer。宏的存在是为了简化将指向对象数据本身的指针传递给函数的过程——它不是特别漂亮,但简化了代码的编写。