\glibc-2.34\elf\rtld.c
#ifdef RTLD_START
RTLD_START
#else
# error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START"
#endif
\glibc-2.34\sysdeps\aarch64\dl-machine.h
#ifdef __LP64__
# define RTLD_START RTLD_START_1 ("x", "3", "sp")
#else
# define RTLD_START RTLD_START_1 ("w", "2", "wsp")
#endif
#define RTLD_START_1(PTR, PTR_SIZE_LOG, PTR_SP) asm ("\
.text \n\
.globl _start \n\
.type _start, %function \n\
.globl _dl_start_user \n\
.type _dl_start_user, %function \n\
_start: \n\
// bti c \n\
hint 34 \n\
mov " PTR "0, " PTR_SP " \n\
bl _dl_start \n\
// returns user entry point in x0 \n\
mov x21, x0 \n\
_dl_start_user: \n\
// get the original arg count \n\
ldr " PTR "1, [sp] \n\
// get the argv address \n\
add " PTR "2, " PTR_SP ", #(1<<" PTR_SIZE_LOG ") \n\
// get _dl_skip_args to see if we were \n\
// invoked as an executable \n\
adrp x4, _dl_skip_args \n\
ldr w4, [x4, #:lo12:_dl_skip_args] \n\
// do we need to adjust argc/argv \n\
cmp w4, 0 \n\
beq .L_done_stack_adjust \n\
// subtract _dl_skip_args from original arg count \n\
sub " PTR "1, " PTR "1, " PTR "4 \n\
// store adjusted argc back to stack \n\
str " PTR "1, [sp] \n\
// find the first unskipped argument \n\
mov " PTR "3, " PTR "2 \n\
add " PTR "4, " PTR "2, " PTR "4, lsl #" PTR_SIZE_LOG " \n\
// shuffle argv down \n\
1: ldr " PTR "5, [x4], #(1<<" PTR_SIZE_LOG ") \n\
str " PTR "5, [x3], #(1<<" PTR_SIZE_LOG ") \n\
cmp " PTR "5, #0 \n\
bne 1b \n\
// shuffle envp down \n\
1: ldr " PTR "5, [x4], #(1<<" PTR_SIZE_LOG ") \n\
str " PTR "5, [x3], #(1<<" PTR_SIZE_LOG ") \n\
cmp " PTR "5, #0 \n\
bne 1b \n\
// shuffle auxv down \n\
1: ldp " PTR "0, " PTR "5, [x4, #(2<<" PTR_SIZE_LOG ")]! \n\
stp " PTR "0, " PTR "5, [x3], #(2<<" PTR_SIZE_LOG ") \n\
cmp " PTR "0, #0 \n\
bne 1b \n\
// Update _dl_argv \n\
adrp x3, __GI__dl_argv \n\
str " PTR "2, [x3, #:lo12:__GI__dl_argv] \n\
.L_done_stack_adjust: \n\
// compute envp \n\
add " PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG " \n\
add " PTR "3, " PTR "3, #(1<<" PTR_SIZE_LOG ") \n\
adrp x16, _rtld_local \n\
add " PTR "16, " PTR "16, #:lo12:_rtld_local \n\
ldr " PTR "0, [x16] \n\
bl _dl_init \n\
// load the finalizer function \n\
adrp x0, _dl_fini \n\
add " PTR "0, " PTR "0, #:lo12:_dl_fini \n\
// jump to the user_s entry point \n\
mov x16, x21 \n\
br x16 \n\
");
\glibc-2.34\elf\rtld.c
static ElfW(Addr) __attribute_used__
_dl_start (void *arg)
{
...code...
#ifdef DONT_USE_BOOTSTRAP_MAP
ElfW(Addr) entry = _dl_start_final (arg);
#else
ElfW(Addr) entry = _dl_start_final (arg, &info);
#endif
#ifndef ELF_MACHINE_START_ADDRESS
# define ELF_MACHINE_START_ADDRESS(map, start) (start)
#endif
return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry);
}
}
\glibc-2.34\elf\rtld.c
#ifdef DONT_USE_BOOTSTRAP_MAP
static inline ElfW(Addr) __attribute__ ((always_inline))
_dl_start_final (void *arg)
#else
static ElfW(Addr) __attribute__ ((noinline))
_dl_start_final (void *arg, struct dl_start_final_info *info)
#endif
{
...code...
/* Call the OS-dependent function to set up life so we can do things like
file access. It will call `dl_main' (below) to do all the real work
of the dynamic linker, and then unwind our frame and run the user
entry point on the same stack we entered on. */
start_addr = _dl_sysdep_start (arg, &dl_main);
...code...
return start_addr;
}
\glibc-2.34\elf\dl-sysdep.c
ElfW(Addr)
_dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
{
...code...
DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ,
GLRO(dl_auxv));
...code...
for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
switch (av->a_type)
{
case AT_PHDR:
phdr = (void *) av->a_un.a_val;
break;
case AT_PHNUM:
phnum = av->a_un.a_val;
break;
case AT_PAGESZ:
GLRO(dl_pagesize) = av->a_un.a_val;
break;
case AT_ENTRY:
user_entry = av->a_un.a_val;
break;
...code...
(*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
return user_entry;
}
\glibc-2.34\elf\dl-sysdep.c
#ifndef DL_FIND_ARG_COMPONENTS
# define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
do { \
void **_tmp; \
(argc) = *(long int *) cookie; \
(argv) = (char **) ((long int *) cookie + 1); \
(envp) = (argv) + (argc) + 1; \
for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
continue; \
(auxp) = (void *) ++_tmp; \
} while (0)
#endif
博客展示了glibc-2.34中多个文件的代码,包括rtld.c、dl-machine.h、dl-sysdep.c等。代码围绕RTLD_START的定义和使用,涉及条件编译、汇编代码编写,以及动态链接器相关函数如_dl_start、_dl_start_final、_dl_sysdep_start等的实现。
1658





