fopen

2021. 2. 17. 00:10?

▶ fopen

extern _IO_FILE *_IO_new_fopen (const char*, const char*);
#   define fopen(fname, mode) _IO_new_fopen (fname, mode)

fopen(fname, mode) → _IO_new_fopen(fname, mode)


▶ _IO_new_fopen

_IO_FILE *
_IO_new_fopen (const char *filename, const char *mode)
{
  return __fopen_internal (filename, mode, 1);
}

_IO_new_fopen(fname, mode) → __fopen_internal(fname, mode, 1)


▶ __fopen_internal

_IO_FILE *
__fopen_internal (const char *filename, const char *mode, int is32)
{
  struct locked_FILE
  {
    struct _IO_FILE_plus fp;
#ifdef _IO_MTSAFE_IO
    _IO_lock_t lock;
#endif
    struct _IO_wide_data wd;
  } *new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));

  if (new_f == NULL)
    return NULL;
#ifdef _IO_MTSAFE_IO
  new_f->fp.file._lock = &new_f->lock;
#endif
  _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps);
  _IO_JUMPS (&new_f->fp) = &_IO_file_jumps;
  _IO_new_file_init_internal (&new_f->fp);
#if  !_IO_UNIFIED_JUMPTABLES
  new_f->fp.vtable = NULL;
#endif
  if (_IO_file_fopen ((_IO_FILE *) new_f, filename, mode, is32) != NULL)
    return __fopen_maybe_mmap (&new_f->fp.file);

  _IO_un_link (&new_f->fp);
  free (new_f);
  return NULL;
}

struct locked_FILE *new_f;  // _IO_FILE_plus + lock + _IO_wide_data

new_f = malloc(sizeof(struct locked_FILE));

→ locked_FILE 구조체 malloc

 

_IO_no_init(&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps);

→ fp.file (_IO_FILE 구조체) 초기화, fp->_wide_data 초기화

더보기

▶ _IO_no_init

void
_IO_no_init (_IO_FILE *fp, int flags, int orientation,
	     struct _IO_wide_data *wd, const struct _IO_jump_t *jmp)
{
  _IO_old_init (fp, flags);
  fp->_mode = orientation;
  if (orientation >= 0)
    {
      fp->_wide_data = wd;
      fp->_wide_data->_IO_buf_base = NULL;
      fp->_wide_data->_IO_buf_end = NULL;
      fp->_wide_data->_IO_read_base = NULL;
      fp->_wide_data->_IO_read_ptr = NULL;
      fp->_wide_data->_IO_read_end = NULL;
      fp->_wide_data->_IO_write_base = NULL;
      fp->_wide_data->_IO_write_ptr = NULL;
      fp->_wide_data->_IO_write_end = NULL;
      fp->_wide_data->_IO_save_base = NULL;
      fp->_wide_data->_IO_backup_base = NULL;
      fp->_wide_data->_IO_save_end = NULL;

      fp->_wide_data->_wide_vtable = jmp;
    }
  else
    /* Cause predictable crash when a wide function is called on a byte
       stream.  */
    fp->_wide_data = (struct _IO_wide_data *) -1L;
  fp->_freeres_list = NULL;
}

fp->_wide_data 초기화

fp->_mode = orientation; // 0

fp->_wide_data = wd; // &new_f->wd

fp->_wide_data->_wide_vtable = jmp; // &_IO_wfile_jumps

 

▶ _IO_old_init

void
_IO_old_init (_IO_FILE *fp, int flags)
{
  fp->_flags = _IO_MAGIC|flags;
  fp->_flags2 = 0;
  if (stdio_needs_locking)
    fp->_flags2 |= _IO_FLAGS2_NEED_LOCK;
  fp->_IO_buf_base = NULL;
  fp->_IO_buf_end = NULL;
  fp->_IO_read_base = NULL;
  fp->_IO_read_ptr = NULL;
  fp->_IO_read_end = NULL;
  fp->_IO_write_base = NULL;
  fp->_IO_write_ptr = NULL;
  fp->_IO_write_end = NULL;
  fp->_chain = NULL; /* Not necessary. */

  fp->_IO_save_base = NULL;
  fp->_IO_backup_base = NULL;
  fp->_IO_save_end = NULL;
  fp->_markers = NULL;
  fp->_cur_column = 0;
#if _IO_JUMPS_OFFSET
  fp->_vtable_offset = 0;
#endif
#ifdef _IO_MTSAFE_IO
  if (fp->_lock != NULL)
    _IO_lock_init (*fp->_lock);
#endif
}

fp 초기화

fp->_flags 설정 // 0xfbad0000

fp-> lock ?

[-------------------------------------code-------------------------------------]
   0x7ffff7e46ad3 <_IO_new_fopen+67>:	mov    rdi,rbx
   0x7ffff7e46ad6 <_IO_new_fopen+70>:	mov    r12,rbx
   0x7ffff7e46ad9 <_IO_new_fopen+73>:	lea    r8,[rip+0x167480]        # 0x7ffff7fadf60 <_IO_wfile_jumps>
=> 0x7ffff7e46ae0 <_IO_new_fopen+80>:	call   0x7ffff7e56920 <_IO_no_init>
   0x7ffff7e46ae5 <_IO_new_fopen+85>:	lea    rax,[rip+0x1679b4]        # 0x7ffff7fae4a0 <_IO_file_jumps>
   0x7ffff7e46aec <_IO_new_fopen+92>:	mov    rdi,rbx
   0x7ffff7e46aef <_IO_new_fopen+95>:	mov    QWORD PTR [rbx+0xd8],rax
   0x7ffff7e46af6 <_IO_new_fopen+102>:	call   0x7ffff7e53ef0 <_IO_new_file_init_internal>
Guessed arguments:
arg[0]: 0x4052a0 --> 0x0 // &new_f->fp.file
arg[1]: 0x0
arg[2]: 0x0 
arg[3]: 0x405390 --> 0x0 // &new_f->wd 
arg[4]: 0x7ffff7fadf60 --> 0x0 // &_IO_wfile_jumps

_IO_no_init 후 상황

0x4052a0:	0x00000000fbad0000	0x0000000000000000
0x4052b0:	0x0000000000000000	0x0000000000000000
0x4052c0:	0x0000000000000000	0x0000000000000000
0x4052d0:	0x0000000000000000	0x0000000000000000
0x4052e0:	0x0000000000000000	0x0000000000000000
0x4052f0:	0x0000000000000000	0x0000000000000000
0x405300:	0x0000000000000000	0x0000000000000000
0x405310:	0x0000000000000000	0x0000000000000000
0x405320:	0x0000000000000000	0x0000000000405380
0x405330:	0x0000000000000000	0x0000000000000000
0x405340:	0x0000000000405390	0x0000000000000000
0x405350:	0x0000000000000000	0x0000000000000000
0x405360:	0x0000000000000000	0x0000000000000000
0x405370:	0x0000000000000000	0x0000000000000000
0x405380:	0x0000000000000000	0x0000000000000000
0x405390:	0x0000000000000000	0x0000000000000000
0x4053a0:	0x0000000000000000	0x0000000000000000
0x4053b0:	0x0000000000000000	0x0000000000000000
0x4053c0:	0x0000000000000000	0x0000000000000000
0x4053d0:	0x0000000000000000	0x0000000000000000
0x4053e0:	0x0000000000000000	0x0000000000000000
0x4053f0:	0x0000000000000000	0x0000000000000000
0x405400:	0x0000000000000000	0x0000000000000000
0x405410:	0x0000000000000000	0x0000000000000000
0x405420:	0x0000000000000000	0x0000000000000000
0x405430:	0x0000000000000000	0x0000000000000000
0x405440:	0x0000000000000000	0x0000000000000000
0x405450:	0x0000000000000000	0x0000000000000000
0x405460:	0x0000000000000000	0x0000000000000000
0x405470:	0x00007ffff7fadf60	0x0000000000020b91
gdb-peda$ x/x 0x00007ffff7fadf60
0x7ffff7fadf60 <_IO_wfile_jumps>:	0x0000000000000000

_flags = 0xfbad0000

_lock = fp+0xe0

_wide_data = fp+0xf0 (_IO_wide_data 시작 주소)

fp->_wide_data->_wide_vtable = _IO_wfile_jumps

더보기
gdb-peda$ p *(struct _IO_FILE_plus *)0x4052a0
$2 = {
  file = {
    _flags = 0xfbad0000,
    _IO_read_ptr = 0x0,
    _IO_read_end = 0x0,
    _IO_read_base = 0x0,
    _IO_write_base = 0x0,
    _IO_write_ptr = 0x0,
    _IO_write_end = 0x0,
    _IO_buf_base = 0x0,
    _IO_buf_end = 0x0,
    _IO_save_base = 0x0,
    _IO_backup_base = 0x0,
    _IO_save_end = 0x0,
    _markers = 0x0,
    _chain = 0x0,
    _fileno = 0x0,
    _flags2 = 0x0,
    _old_offset = 0x0,
    _cur_column = 0x0,
    _vtable_offset = 0x0,
    _shortbuf = "",
    _lock = 0x405380,
    _offset = 0x0,
    _codecvt = 0x0,
    _wide_data = 0x405390,
    _freeres_list = 0x0,
    _freeres_buf = 0x0,
    __pad5 = 0x0,
    _mode = 0x0,
    _unused2 = '\000' <repeats 19 times>
  },
  vtable = 0x0
}

이게되네

 

_IO_JUMPS (&new_f->fp) = &_IO_file_jumps;

#define _IO_JUMPS(THIS) (THIS)->vtable

fp->vtable = _IO_file_jumps


_IO_new_file_init_internal (&new_f->fp);

void
_IO_new_file_init_internal (struct _IO_FILE_plus *fp)
{
  /* POSIX.1 allows another file handle to be used to change the position
     of our file descriptor.  Hence we actually don't know the actual
     position before we do the first fseek (and until a following fflush). */
  fp->file._offset = _IO_pos_BAD;
  fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;

  _IO_link_in (fp);
  fp->file._fileno = -1;
}
gdb-peda$ pd _IO_new_file_init_internal
Dump of assembler code for function _IO_new_file_init_internal:
   0x00007ffff7e53ef0 <+0>:	endbr64 
   0x00007ffff7e53ef4 <+4>:	or     DWORD PTR [rdi],0x240c
   0x00007ffff7e53efa <+10>:	push   rbx
   0x00007ffff7e53efb <+11>:	mov    rbx,rdi
   0x00007ffff7e53efe <+14>:	mov    QWORD PTR [rdi+0x90],0xffffffffffffffff
=> 0x00007ffff7e53f09 <+25>:	call   0x7ffff7e55560 <__GI__IO_link_in>
   0x00007ffff7e53f0e <+30>:	mov    DWORD PTR [rbx+0x70],0xffffffff
   0x00007ffff7e53f15 <+37>:	pop    rbx
   0x00007ffff7e53f16 <+38>:	ret 

_offset = 0xffffffffffffffff

_flags |= 0x240c

더보기

▶ _IO_link_in

void
_IO_link_in (struct _IO_FILE_plus *fp)
{
  if ((fp->file._flags & _IO_LINKED) == 0)
    {
      fp->file._flags |= _IO_LINKED;
#ifdef _IO_MTSAFE_IO
      _IO_cleanup_region_start_noarg (flush_cleanup);
      _IO_lock_lock (list_all_lock);
      run_fp = (_IO_FILE *) fp;
      _IO_flockfile ((_IO_FILE *) fp);
#endif
      fp->file._chain = (_IO_FILE *) _IO_list_all;
      _IO_list_all = fp;
#ifdef _IO_MTSAFE_IO
      _IO_funlockfile ((_IO_FILE *) fp);
      run_fp = NULL;
      _IO_lock_unlock (list_all_lock);
      _IO_cleanup_region_end (0);
#endif
    }
}

if ((fp->file._flags & _IO_LINKED) == 0)

#define _IO_LINKED 0x80 /* Set if linked (using _chain) to streambuf::_list_all.*/

flag & 0x80 == 0 이 아니면 그냥 ret

#ifdef _IO_MTSAFE_IO
      _IO_cleanup_region_start_noarg (flush_cleanup);
      _IO_lock_lock (list_all_lock);
      run_fp = (_IO_FILE *) fp;
      _IO_flockfile ((_IO_FILE *) fp);

→ ?? new_f lock이 설정되는 것 같다

#ifdef _IO_MTSAFE_IO
      _IO_funlockfile ((_IO_FILE *) fp);
      run_fp = NULL;
      _IO_lock_unlock (list_all_lock);
      _IO_cleanup_region_end (0);

lock 영역을 썼다가 뒤에서 다시 초기화함

fp->file._flags |= _IO_LINKED; // _IO_LINKED 설정

fp->file._chain = (_IO_FILE *) _IO_list_all; // single linked list로 관리

gdb-peda$ p *(struct _IO_FILE_plus *)0x4052a0
$57 = {
  file = {
...
    _chain = 0x7ffff7fad5c0 <_IO_2_1_stderr_>,
...
gdb-peda$ p *(struct _IO_FILE_plus *)0x7ffff7fad5c0 // stderr
$58 = {
  file = {
...
    _chain = 0x7ffff7fad6a0 <_IO_2_1_stdout_>,
...
gdb-peda$ p *(struct _IO_FILE_plus *)0x7ffff7fad6a0 // stdout
$59 = {
  file = {
...
    _chain = 0x7ffff7fac980 <_IO_2_1_stdin_>,
...
gdb-peda$ p *(struct _IO_FILE_plus *)0x7ffff7fac980 //stdin
$60 = {
  file = {
...
    _chain = 0x0,
...

FILE 구조체들을 _chain을 이용해서 single linked list로 관리한다

_IO_new_file_init_internal (&new_f->fp) 실행 후

 

_flags = 0xfbad248c 

_chain = stderr

_offset = 0xffffffffffffffff

 

if (_IO_file_fopen ((_IO_FILE *) new_f, filename, mode, is32) != NULL)

[-------------------------------------code-------------------------------------]
   0x7ffff7e46b00 <_IO_new_fopen+112>:	mov    rdx,r13
   0x7ffff7e46b03 <_IO_new_fopen+115>:	mov    rsi,rbp
   0x7ffff7e46b06 <_IO_new_fopen+118>:	mov    rdi,rbx
=> 0x7ffff7e46b09 <_IO_new_fopen+121>:	call   0x7ffff7e54260 <_IO_new_file_fopen>
   0x7ffff7e46b0e <_IO_new_fopen+126>:	test   rax,rax
   0x7ffff7e46b11 <_IO_new_fopen+129>:	je     0x7ffff7e46b60 <_IO_new_fopen+208>
   0x7ffff7e46b13 <_IO_new_fopen+131>:	test   BYTE PTR [rbx+0x74],0x1
   0x7ffff7e46b17 <_IO_new_fopen+135>:	je     0x7ffff7e46b4d <_IO_new_fopen+189>
Guessed arguments:
arg[0]: 0x4052a0 --> 0xfbad248c 
arg[1]: filename
arg[2]: mode
arg[3]: 0x1 (?)

is32가 뭔지 모르겠는데 그냥 mov ecx,0x1로 1을 넣는다.

코드엔 _IO_file_fopen이라고 써있는데 _IO_new_file_fopen 함수 실행함

 

▶ _IO_new_file_fopen

_IO_FILE *
_IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode,
		    int is32not64)
{
  int oflags = 0, omode;
  int read_write;
  int oprot = 0666;
  int i;
  _IO_FILE *result;
  const char *cs;
  const char *last_recognized;

  if (_IO_file_is_open (fp))
    return 0;
  switch (*mode)
    {
    case 'r':
      omode = O_RDONLY;
      read_write = _IO_NO_WRITES;
      break;
    case 'w':
      omode = O_WRONLY;
      oflags = O_CREAT|O_TRUNC;
      read_write = _IO_NO_READS;
      break;
    case 'a':
      omode = O_WRONLY;
      oflags = O_CREAT|O_APPEND;
      read_write = _IO_NO_READS|_IO_IS_APPENDING;
      break;
    default:
      __set_errno (EINVAL);
      return NULL;
    }
  last_recognized = mode;
  for (i = 1; i < 7; ++i)
    {
      switch (*++mode)
	{
	case '\0':
	  break;
	case '+':
	  omode = O_RDWR;
	  read_write &= _IO_IS_APPENDING;
	  last_recognized = mode;
	  continue;
	case 'x':
	  oflags |= O_EXCL;
	  last_recognized = mode;
	  continue;
	case 'b':
	  last_recognized = mode;
	  continue;
	case 'm':
	  fp->_flags2 |= _IO_FLAGS2_MMAP;
	  continue;
	case 'c':
	  fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
	  continue;
	case 'e':
	  oflags |= O_CLOEXEC;
	  fp->_flags2 |= _IO_FLAGS2_CLOEXEC;
	  continue;
	default:
	  /* Ignore.  */
	  continue;
	}
      break;
    }

  result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
			  is32not64);

  if (result != NULL)
    {
      /* Test whether the mode string specifies the conversion.  */
      cs = strstr (last_recognized + 1, ",ccs=");
      if (cs != NULL)
	{
	  /* Yep.  Load the appropriate conversions and set the orientation
	     to wide.  */
	  struct gconv_fcts fcts;
	  struct _IO_codecvt *cc;
	  char *endp = __strchrnul (cs + 5, ',');
	  char *ccs = malloc (endp - (cs + 5) + 3);

	  if (ccs == NULL)
	    {
	      int malloc_err = errno;  /* Whatever malloc failed with.  */
	      (void) _IO_file_close_it (fp);
	      __set_errno (malloc_err);
	      return NULL;
	    }

	  *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
	  strip (ccs, ccs);

	  if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
				   ? upstr (ccs, cs + 5) : ccs) != 0)
	    {
	      /* Something went wrong, we cannot load the conversion modules.
		 This means we cannot proceed since the user explicitly asked
		 for these.  */
	      (void) _IO_file_close_it (fp);
	      free (ccs);
	      __set_errno (EINVAL);
	      return NULL;
	    }

	  free (ccs);

	  assert (fcts.towc_nsteps == 1);
	  assert (fcts.tomb_nsteps == 1);

	  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
	  fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;

	  /* Clear the state.  We start all over again.  */
	  memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
	  memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));

	  cc = fp->_codecvt = &fp->_wide_data->_codecvt;

	  /* The functions are always the same.  */
	  *cc = __libio_codecvt;

	  cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
	  cc->__cd_in.__cd.__steps = fcts.towc;

	  cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
	  cc->__cd_in.__cd.__data[0].__internal_use = 1;
	  cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
	  cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;

	  cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
	  cc->__cd_out.__cd.__steps = fcts.tomb;

	  cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
	  cc->__cd_out.__cd.__data[0].__internal_use = 1;
	  cc->__cd_out.__cd.__data[0].__flags
	    = __GCONV_IS_LAST | __GCONV_TRANSLIT;
	  cc->__cd_out.__cd.__data[0].__statep =
	    &result->_wide_data->_IO_state;

	  /* From now on use the wide character callback functions.  */
	  _IO_JUMPS_FILE_plus (fp) = fp->_wide_data->_wide_vtable;

	  /* Set the mode now.  */
	  result->_mode = 1;
	}
    }

  return result;
}

 

if (_IO_file_is_open (fp))
  return 0;
#define _IO_file_is_open(__fp) ((__fp)->_fileno != -1)

fp->_fileno가 -1이 아니면 return 0

 

switch case로 mode에 따라 oflags, omode를 설정

result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write, is32not64);
더보기

▶ _IO_file_open

_IO_FILE *
_IO_file_open (_IO_FILE *fp, const char *filename, int posix_mode, int prot,
	       int read_write, int is32not64)
{
  int fdesc;
  if (__glibc_unlikely (fp->_flags2 & _IO_FLAGS2_NOTCANCEL))
    fdesc = __open_nocancel (filename,
			     posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
  else
    fdesc = __open (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
  if (fdesc < 0)
    return NULL;
  fp->_fileno = fdesc;
  _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
  /* For append mode, send the file offset to the end of the file.  Don't
     update the offset cache though, since the file handle is not active.  */
  if ((read_write & (_IO_IS_APPENDING | _IO_NO_READS))
      == (_IO_IS_APPENDING | _IO_NO_READS))
    {
      _IO_off64_t new_pos = _IO_SYSSEEK (fp, 0, _IO_seek_end);
      if (new_pos == _IO_pos_BAD && errno != ESPIPE)
	{
	  __close_nocancel (fdesc);
	  return NULL;
	}
    }
  _IO_link_in ((struct _IO_FILE_plus *) fp);
  return fp;
}
if (__glibc_unlikely (fp->_flags2 & _IO_FLAGS2_NOTCANCEL))
  fdesc = __open_nocancel (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
else
  fdesc = __open (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
#define _IO_FLAGS2_NOTCANCEL 2

_flags2 == 0x2 면 __open_nocancel

아니면 __open으로 파일을 연다.

 

▶ __open

int
__libc_open64 (const char *file, int oflag, ...)
{
  int mode = 0;

  if (__OPEN_NEEDS_MODE (oflag))
    {
      va_list arg;
      va_start (arg, oflag);
      mode = va_arg (arg, int);
      va_end (arg);
    }

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

 

/* Detect if open needs mode as a third argument (or for openat as a fourth
   argument).  */
#ifdef __O_TMPFILE
# define __OPEN_NEEDS_MODE(oflag) \
  (((oflag) & O_CREAT) != 0 || ((oflag) & __O_TMPFILE) == __O_TMPFILE)
#else
# define __OPEN_NEEDS_MODE(oflag) (((oflag) & O_CREAT) != 0)
#endif

w나 a가 들어가면 oflag에 O_CREAT가 설정되어 if문이 수행된다.

__O_TMPFILE 은 잘 모르겠음

[----------------------------------registers-----------------------------------]
RAX: 0x101 
...
[-------------------------------------code-------------------------------------]
   0x7ffff7ed1e9c <__libc_open64+76>:	mov    rsi,rbp
   0x7ffff7ed1e9f <__libc_open64+79>:	mov    edi,0xffffff9c
   0x7ffff7ed1ea4 <__libc_open64+84>:	mov    eax,0x101
=> 0x7ffff7ed1ea9 <__libc_open64+89>:	syscall 
   0x7ffff7ed1eab <__libc_open64+91>:	cmp    rax,0xfffffffffffff000
   0x7ffff7ed1eb1 <__libc_open64+97>:	ja     0x7ffff7ed1f48 <__libc_open64+248>
   0x7ffff7ed1eb7 <__libc_open64+103>:	mov    rcx,QWORD PTR [rsp+0x28]
   0x7ffff7ed1ebc <__libc_open64+108>:	xor    rcx,QWORD PTR fs:0x28
Guessed arguments:
arg[0]: dirfd
arg[1]: filename
arg[2]: oflag

SYSCALL_CANCEL 부분도 잘 모르겠는데

openat(dirfd, filename, oflag)가 실행되고 파일 디스크립터가 리턴된다.

 

결과적으로 fdesc = openat(dirfd, filename, oflag); 이 됨

 

if (fdesc < 0)
  return NULL;

fdesc가 0보다 작으면 return NULL

 

fp->_fileno = fdesc;
_IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
#define _IO_mask_flags(fp, f, mask) \
       ((fp)->_flags = ((fp)->_flags & ~(mask)) | ((f) & (mask)))

fp->_fileno, fp->_flags 설정

_IO_link_in ((struct _IO_FILE_plus *) fp);
return fp;

얘도 single linked list로 관리하고 fp 리턴

fp _fileno, _flags 설정됨

result = fp

 

  result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write, is32not64);

  if (result != NULL)
    {
    ...
    }
    
  return result;
}
fopen 은 유니코드 파일 스트림을 지원 합니다. 유니코드 파일을 열려면 다음과 같이 fopen 에 원하는 인코딩을 지정 하는 ccs 플래그를 전달 합니다.
FILE * fp = fopen ("newfile.txt", "rt +, ccs =encoding");

// https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-160

다음과 같이 fopen에 인코딩이 지정된 경우를 처리하고 result(==fp)를 리턴

 

[----------------------------------registers-----------------------------------]
RAX: 0x4052a0 --> 0xfbad2484 
...
[-------------------------------------code-------------------------------------]
   0x7ffff7e46b0e <_IO_new_fopen+126>:	test   rax,rax
   0x7ffff7e46b11 <_IO_new_fopen+129>:	je     0x7ffff7e46b60 <_IO_new_fopen+208>
   0x7ffff7e46b13 <_IO_new_fopen+131>:	test   BYTE PTR [rbx+0x74],0x1
=> 0x7ffff7e46b17 <_IO_new_fopen+135>:	je     0x7ffff7e46b4d <_IO_new_fopen+189>
 | 0x7ffff7e46b19 <_IO_new_fopen+137>:	test   BYTE PTR [rbx],0x8
 | 0x7ffff7e46b1c <_IO_new_fopen+140>:	je     0x7ffff7e46b4d <_IO_new_fopen+189>
 | 0x7ffff7e46b1e <_IO_new_fopen+142>:	mov    ecx,DWORD PTR [rbx+0xc0]
 | 0x7ffff7e46b24 <_IO_new_fopen+148>:	lea    rdx,[rip+0x1672b5]        # 0x7ffff7fadde0 <_IO_wfile_jumps_maybe_mmap>
 |->   0x7ffff7e46b4d <_IO_new_fopen+189>:	add    rsp,0x8
       0x7ffff7e46b51 <_IO_new_fopen+193>:	mov    rax,r12
       0x7ffff7e46b54 <_IO_new_fopen+196>:	pop    rbx
       0x7ffff7e46b55 <_IO_new_fopen+197>:	pop    rbp
0x00007ffff7e46b13 <+131>:	test   BYTE PTR [rbx+0x74],0x1
0x00007ffff7e46b17 <+135>:	je     0x7ffff7e46b4d <_IO_new_fopen+189>
0x00007ffff7e46b19 <+137>:	test   BYTE PTR [rbx],0x8
0x00007ffff7e46b1c <+140>:	je     0x7ffff7e46b4d <_IO_new_fopen+189>
0x00007ffff7e46b1e <+142>:	mov    ecx,DWORD PTR [rbx+0xc0]
0x00007ffff7e46b24 <+148>:	lea    rdx,[rip+0x1672b5]        # 0x7ffff7fadde0 <_IO_wfile_jumps_maybe_mmap>
0x00007ffff7e46b2b <+155>:	lea    rax,[rip+0x1677ee]        # 0x7ffff7fae320 <_IO_file_jumps_maybe_mmap>
0x00007ffff7e46b32 <+162>:	test   ecx,ecx
0x00007ffff7e46b34 <+164>:	cmovg  rax,rdx
0x00007ffff7e46b38 <+168>:	mov    QWORD PTR [rbx+0xd8],rax
0x00007ffff7e46b3f <+175>:	mov    rax,QWORD PTR [rbx+0xa0]
0x00007ffff7e46b46 <+182>:	mov    QWORD PTR [rax+0xe0],rdx
0x00007ffff7e46b4d <+189>:	add    rsp,0x8
0x00007ffff7e46b51 <+193>:	mov    rax,r12
0x00007ffff7e46b54 <+196>:	pop    rbx
0x00007ffff7e46b55 <+197>:	pop    rbp
0x00007ffff7e46b56 <+198>:	pop    r12
0x00007ffff7e46b58 <+200>:	pop    r13
0x00007ffff7e46b5a <+202>:	ret  
#define _IO_NO_WRITES 8 /* Writing not allowd */
...
#define _IO_FLAGS2_MMAP 1

fp->_flags2에 _IO_FLAGS2_MMAP이 설정되어있고

fp->_flags에 _IO_NO_WRITES가 설정되어있으면 _IO_new_fopen+142 부분이 실행됨

 

뭔지는 잘 모르겠음

'?' 카테고리의 다른 글

부동소수점  (0) 2021.08.14
docker 실행  (0) 2021.06.23
apt-get update... 404 not found  (0) 2021.06.23
glibc 2.31 free  (0) 2021.03.01
glibc 2.31 malloc  (0) 2021.02.21