glibc源码解读——malloc

时间:2022-09-29 03:18:08

通过宏定义的展开,找到malloc的函数地址:

# define C_SYMBOL_NAME(name) name
# define ASM_LINE_SEP ;

void *__libc_malloc (size_t bytes);

libc_hidden_def (__libc_malloc)

# define libc_hidden_def(name) hidden_def (name)

# define hidden_def(name)  strong_alias (name, __GI_##name)

# define strong_alias(original, alias)             \
  .globl C_SYMBOL_NAME (alias) ASM_LINE_SEP     \
  C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original)

strong_alias (__libc_malloc, __malloc) strong_alias (__libc_malloc, malloc)

以下是展开后的结果:

libc_hidden_def (__libc_malloc) -----> 展开
strong_alias(__libc_malloc, __GI___libc_malloc) -----> 展开
.globl __GI___libc_malloc ;     __GI___libc_malloc = __libc_malloc

strong_alias (__libc_malloc, __malloc) -----> 展开
.globl __malloc ;     __malloc = __libc_malloc

strong_alias (__libc_malloc, malloc) -----> 展开
.globl malloc ;     malloc = __libc_malloc

可以看出: __libc_malloc是malloc函数的实现

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

其中介绍一下.global:

  .text 部分是处理器开始执行代码的地方,指定了后续编译出来的内容放在代码段【可执行】,是arm-gcc编译器的关键词。

     .global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用;告诉编译器后续跟的是一个全局可见的名字【可能是变量,也可以是函数名】

     .global _start 让 _start 符号成为可见的标识符,这样链接器就知道跳转到程序中的什么地方并开始执行

    _start是一个函数的起始地址,也是编译、链接后程序的起始地址。由于程序是通过加载器来加载的,必须要找到 _start名字的函数,因此_start必须定义成全局的,以便存在于编译后的全局符合表中,供其它程序【如加载器】寻找到。

       linux寻找这个 _start 标签作为程序的默认进入点。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面看 __libc_malloc 的实现:

/*------------------------ Public wrappers. --------------------------------*/

void *
__libc_malloc (size_t bytes)
{
  mstate ar_ptr;
  void *victim;

  void *(*hook) (size_t, const void *)
    = atomic_forced_read (__malloc_hook);
  if (__builtin_expect (hook != NULL, 0))
    return (*hook)(bytes, RETURN_ADDRESS (0));

  arena_get (ar_ptr, bytes);

  victim = _int_malloc (ar_ptr, bytes);
  /* Retry with another arena only if we were able to find a usable arena
     before.  */
  if (!victim && ar_ptr != NULL)
    {
      LIBC_PROBE (memory_malloc_retry, 1, bytes);
      ar_ptr = arena_get_retry (ar_ptr, bytes);
      victim = _int_malloc (ar_ptr, bytes);
    }

  if (ar_ptr != NULL)
    __libc_lock_unlock (ar_ptr->mutex);

  assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
          ar_ptr == arena_for_chunk (mem2chunk (victim)));
  return victim;
}
libc_hidden_def (__libc_malloc)

其中 _int_malloc 是内存申请的实现: