๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜๋ฉด์„œ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

 

 

_rtld_global ์‹ค์Šต ์˜ˆ์ œ

// Name: rtld.c
// Compile: gcc -o rtld rtld.c
int main() {
  return 0;
}

๋‹ค์Œ์˜ ์ฝ”๋“œ๋Š” ์ข…๋ฃŒํ•˜๋Š” ๊ณผ์ •์„ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•œ ์˜ˆ์ œ ์ฝ”๋“œ์ด๋‹ค.

 

 

 

_rtld_global

__Gl_exit

์•ž์„œ ์ปดํŒŒ์ผ ํ•œ ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋ณ„๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•œ๋‹ค.

๋””๋ฒ„๊น…์„ ํ†ตํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž.

 

main ํ•จ์ˆ˜ ๋‚ด์— ๋ฆฌํ„ดํ•˜๋Š” ๋ช…๋ น์–ด์— ๋ธŒ๋ ˆ์ดํฌ ํฌ์ธํŠธ๋ฅผ ์„ค์ •ํ•œ๋‹ค.

 

step into (si)๋ฅผ ํ†ตํ•ด ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•œ๋‹ค.

๋””๋ฒ„๊น… ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด, main ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ฆฌํ„ด ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ์Šคํƒ ์ตœ์ƒ๋‹จ์— ์žˆ๋Š” __libc_start_main+231 ์˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๋‚ด๋ถ€์—์„œ __GI_exit ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ __GI_exit ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ๋ชจ์Šต์ด๋‹ค.

๋˜ ๋‹ค๋ฅธ __run_exit_handlers ํ•จ์ˆ˜๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ฝ”๋“œ์˜ ํฌ๊ธฐ๊ฐ€ ํฌ๋ฏ€๋กœ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋ถ„์„ํ•ด๋ณด์ž.

 

 

 

 

__run_exit_handlers

๋‹ค์Œ์€ __run_exit_handlers ํ•จ์ˆ˜์˜ ์ฝ”๋“œ์ด๋‹ค.

void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
		     bool run_list_atexit, bool run_dtors)
{
	  const struct exit_function *const f = &cur->fns[--cur->idx];
	  switch (f->flavor)
	    {
	      void (*atfct) (void);
	      void (*onfct) (int status, void *arg);
	      void (*cxafct) (void *arg, int status);
	    case ef_free:
	    case ef_us:
	      break;
	    case ef_on:
	      onfct = f->func.on.fn;
#ifdef PTR_DEMANGLE
	      PTR_DEMANGLE (onfct);
#endif
	      onfct (status, f->func.on.arg);
	      break;
	    case ef_at:
	      atfct = f->func.at;
#ifdef PTR_DEMANGLE
	      PTR_DEMANGLE (atfct);
#endif
	      atfct ();
	      break;
	    case ef_cxa:
	      cxafct = f->func.cxa.fn;
#ifdef PTR_DEMANGLE
	      PTR_DEMANGLE (cxafct);
#endif
	      cxafct (f->func.cxa.arg, status);
	      break;
	    }
	}

 

exit_function ๊ตฌ์กฐ์ฒด์˜ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ๋”ฐ๋ฅธ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌํ„ด ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ด ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•œ๋‹ค๋ฉด _dl_fini ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

exit_function ๊ตฌ์กฐ์ฒด์˜ ๋ชจ์Šต์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

struct exit_function
{
/* `flavour' should be of type of the `enum' above but since we need
   this element in an atomic operation we have to use `long int'.  */
long int flavor;
union
  {
void (*at) (void);
struct
  {
    void (*fn) (int status, void *arg);
    void *arg;
  } on;
struct
{
    void (*fn) (void *arg, int status);
    void *arg;
    void *dso_handle;
  } cxa;
  } func;
};

 

 

 

 

_dl_fini

๋‹ค์Œ์€ ๋กœ๋”์— ์กด์žฌํ•˜๋Š” _dl_fini ํ•จ์ˆ˜ ์ฝ”๋“œ์˜ ์ผ๋ถ€์ด๋‹ค.

# define __rtld_lock_lock_recursive(NAME) \
  GL(dl_rtld_lock_recursive) (&(NAME).mutex)
  
void
_dl_fini (void)
{
#ifdef SHARED
  int do_audit = 0;
 again:
#endif
  for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
    {
      /* Protect against concurrent loads and unloads.  */
      __rtld_lock_lock_recursive (GL(dl_load_lock));

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, _dl_load_lock ์„ ์ธ์ž๋กœ __rtld_lock_lock_recursive ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งคํฌ๋กœ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด, ํ•ด๋‹น ํ•จ์ˆ˜๋Š” dl_rtld_lock_recursive๋ผ๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

ํ•ด๋‹น ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋Š” _rtld_global ๊ตฌ์กฐ์ฒด์˜ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์ด๋‹ค.

ํ•ด๋‹น ๊ตฌ์กฐ์ฒด๋Š” ๋งค์šฐ ๋ฐฉ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์™€ ์ „๋‹ฌ๋˜๋Š” ์ธ์ž์ธ dl_load_lock ๋งŒ์„ ์‚ดํŽด๋ณด์ž.

 

 

 

 

 

_rtld_global

๋‹ค์Œ์€ gdb์—์„œ _rtld_global ๊ตฌ์กฐ์ฒด๋ฅผ ์ถœ๋ ฅํ•œ ๋ชจ์Šต์ด๋‹ค. ๊ตฌ์กฐ์ฒด ๋‚ด _dl_rtld_lock_recursive ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์—๋Š” rtld_lock_default_lock_recursive ํ•จ์ˆ˜ ์ฃผ์†Œ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค.

๊ตฌ์กฐ์ฒด์˜ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๊ฐ€ ์ €์žฅ๋œ ์˜์—ญ์€ ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ ๊ถŒํ•œ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

 

 

 

 

_rtld_global ์ดˆ๊ธฐํ™”

๋‹ค์Œ์€ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋กœ๋“œํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” dl_main ์ฝ”๋“œ์˜ ์ผ๋ถ€์ด๋‹ค.

static void
dl_main (const ElfW(Phdr) *phdr,
	 ElfW(Word) phnum,
	 ElfW(Addr) *user_entry,
	 ElfW(auxv_t) *auxv)
{
  GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
#if defined SHARED && defined _LIBC_REENTRANT \
    && defined __rtld_lock_default_lock_recursive
  GL(dl_rtld_lock_recursive) = rtld_lock_default_lock_recursive;
  GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive;

_rtld_global ๊ตฌ์กฐ์ฒด์˜ dl_rtld_lock_recursive ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค!