-
lock값에 왜 저 값이 들어가는지 의문(fp+0x80)
-
vtable다음에 쉘 함수가 있어도 어떻게 fp->_s.allocate_buffer가 이 위치를 알 수 있나
즉, fp->_s.allocate_buffer함수가 쉘 함수(?)의 위치를 어떻게 특정하나?
lock값은 어따 쓰는지 저도 코드 찾아보다가 포기했고(멀티스레드 환경에서 쓰이는 값이니까 아마 그런 관련 헤더파일에 있지 않을까는 싶은데..)
두 번째 질문에 대한 답은 해드리겠습니다.
코드 확인
코드 확인해보시면 이렇게 되어있습니다.
int
_IO_str_overflow (_IO_FILE *fp, int c)
{
...
new_buf = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
...
}
fp는 저희가 봤던 _IO_FILE
의 포인터인데 지금 강제형변환으로 _IO_strfile
포인터라고 해석하게 해놨습니다.
그럼 기존에 각 오프셋 별로 해석되던게 어떻게 바뀌었는지만 확인하면 도대체 _s._allocate_buffer
가 뭔지 알 수 있습니다.
_IO_strfile 구조체
glibc-2.27/source/libio/strfile.h에 다음과 같이 정의되어 있습니다.
struct _IO_str_fields
{
_IO_alloc_type _allocate_buffer;
_IO_free_type _free_buffer;
};
struct _IO_streambuf
{
struct _IO_FILE _f;
const struct _IO_jump_t *vtable;
};
typedef struct _IO_strfile_
{
struct _IO_streambuf _sbf;
struct _IO_str_fields _s;
} _IO_strfile;
_IO_strfile
내부에 또다시 _IO_streambuf
, _IO_str_fields
구조체가 있습니다.
바로 위에 있는 _IO_streambuf
구조체를 보면 생김새가 어디서 많이 본 구조체 아닙니까?
네 바로 _IO_FILE_plus
와 그냥 같습니다. (앞에 struct, const 붙은거 제외하면 같음. 결국 틀은 같음)
그렇다면 이제 살펴볼 건 바로 밑에 있는 _IO_str_fields
구조체 밖에 없습니다.
마침 이름도 _s
라 저희가 찾던 녀석 중 하나입니다.
멤버를 보면 저희가 유심히 살펴봐야 할 _allocate_buffer
이 보입니다.
이 녀석의 타입이 뭐냐하면 같은 헤더 파일 내부에 정의되어 있는 void *
입니다.
typedef void *(*_IO_alloc_type) (_IO_size_t);
typedef void (*_IO_free_type) (void*);
결국 이 구조체가 지닌 구조는 알기 쉽게 풀면 이렇습니다.
_IO_FILE_plus
-----------------------------
void * (_s._allocate_buffer)
그러니까 그냥 구조체에서 전달한 버퍼(new_size) 조작해준 다음에 마지막에 하나(system) 붙이면 system(new_size)
가 호출되었던 겁니다.