【问题标题】:About works of _IO_sputn through _IO_file_jumps in glibc关于glibc中_IO_sputn到_IO_file_jumps的工作
【发布时间】:2023-03-29 21:04:01
【问题描述】:

感谢您阅读我的问题。

当我在 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] 时,会有不同的值。

(不同的值)

  1. 为什么通过_IO_file_jumps调用_IO_sputn函数?

  2. _IO_file_jumps 在 glibc 中的作用是什么?

  3. _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);
};

这是我可以找到的关于 _IO_sputn 的所有信息,带有 ctagscscope

【问题讨论】:

  • 请勿张贴文字图片。请将文本作为文本复制到问题中。

标签: c gdb glibc puts


【解决方案1】:

为什么通过_IO_file_jumps调用_IO_sputn函数?

因为文件(“文件”作为对象)可能以不同的方式实现放置字符,所以使用了调度表。

而 _IO_file_jumps 在 glibc 中的作用是什么?

这是一个dispatch table - 一个函数指针数组。它可以指定一个通用的稳定虚拟接口,由不同的文件以不同的方式实现,这些文件需要对所请求的操作进行不同的实现和抽象。

_IO_sputn 函数最终如何调用 _IO_new_file_xsputn ?

function pointer 是 C 语言的一部分,它允许通过指向函数的指针调用另一个函数。 _IO_sputn 是一个 macro,即 expandsthat function pointer 的函数调用。宏的存在是为了简化将指向对象数据本身的指针传递给函数——它不是特别漂亮,但简化了代码的编写。

【讨论】:

  • 感谢您回答我的问题 :) 我想知道 __xsputn 是如何连接到 __IO_new_file_xsputn 函数的。 __IO_new_file_xsputn_IO_file_jump 表中吗?如果是这样,我可以在哪里找到源代码?
  • how __xsputn is connected to __IO_new_file_xsputn function 这里的某处github.com/lattera/glibc/blob/master/libio/iofopen.c#L73 用于文件。 Is __IO_new_file_xsputn in _IO_file_jump table? 是的,_IO_file_jump类型,该类型的实例化定义为here。请注意上面的versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
  • where is the source code which I can find?github很适合浏览,主要是google对github的索引很高,所以我用google搜索。但是code.woboq.org/userspace/glibc 更好,因为它有一些简单的浏览器内标签浏览(在谷歌中也很高)。
最近更新 更多