研究了一下bss段上为什么会有stdin,stdout,stderr, 根据经验观察似乎在使用setvbuf时会出现这种情况, 经过控制变量测试, 发现只要setvbuf这三个变量的一个, 就会使该变量出现在bss段中. setvbuf使用了这三个stdio.h中的extern变量

/* Standard streams.  */
extern FILE *stdin;		/* Standard input stream.  */
extern FILE *stdout;		/* Standard output stream.  */
extern FILE *stderr;		/* Standard error output stream.  */
/* C89/C99 say they're macros.  Make them happy.  */
#define stdin stdin
#define stdout stdout
#define stderr stderr

他们定义在stdio.c中, 不过右边的仍然是extern变量

#include "libioP.h"
#include "stdio.h"

#undef stdin
#undef stdout
#undef stderr
FILE *stdin = (FILE *) &_IO_2_1_stdin_;
FILE *stdout = (FILE *) &_IO_2_1_stdout_;
FILE *stderr = (FILE *) &_IO_2_1_stderr_;

他们最初的定义在stdfile.c中

DEF_STDFILE(_IO_2_1_stdin_, 0, 0, _IO_NO_WRITES);
DEF_STDFILE(_IO_2_1_stdout_, 1, &_IO_2_1_stdin_, _IO_NO_READS);
DEF_STDFILE(_IO_2_1_stderr_, 2, &_IO_2_1_stdout_, _IO_NO_READS+_IO_UNBUFFERED);

struct _IO_FILE_plus *_IO_list_all = &_IO_2_1_stderr_;
libc_hidden_data_def (_IO_list_all)

因为stdin等三个变量是未初始化的全局变量, 所以他们被分配到bss段. 在执行setvbuf时, 经过两次重定位将libc地址填入其中.
如果不setvbuf, 这三个符号就不会被用到, 也就不会被解析.

问题

发现似乎在使用setbuf时, 它们会作为libc里的变量出现在got表里, 这又是为什么呢?

P198 P194

![[279a9d0da6d999a174b5d072d63afc92.png]]

![[d2dfc527da1909ca844b92495861ce84_720.png]]