---
# System prepended metadata

title: uClibc ld.so source code 解析
tags: [uClibc]

---

---
title: uClibc ld.so source code 解析
tags: uClibc
lang: zh_tw
---

# uClibc `ld.so` source code 解析
* 版本: 0.9.33.2
* binary 是從 NETGEAR R9000 Firmware 中取出
* source code 從網路下載

## Start
* 先上 IDA 畫面

![](https://i.imgur.com/gltqgtY.png)

* 對應 source code 位於 `ldso/ldso/arm/dl-startup.h`

```c
#if !defined(__thumb__)
__asm__(
    "	.text\n"
    "	.globl	_start\n"
    "	.type	_start,%function\n"
	"_start:\n"
	"	@ at start time, all the args are on the stack\n"
	"	mov	r0, sp\n"
	"	bl	_dl_start\n"
	"	@ returns user entry point in r0\n"
	"	mov	r6, r0\n"
	"	@ we are PIC code, so get global offset table\n"
	"	ldr	sl, .L_GET_GOT\n"
	"	add	sl, pc, sl\n"
	".L_GOT_GOT:\n"
	"	@ See if we were run as a command with the executable file\n"
	"	@ name as an extra leading argument.\n"
	"	ldr	r4, .L_SKIP_ARGS\n"
	"	ldr	r4, [sl, r4]\n"
	"	@ get the original arg count\n"
	"	ldr	r1, [sp]\n"
	"	@ subtract _dl_skip_args from it\n"
	"	sub	r1, r1, r4\n"
	"	@ adjust the stack pointer to skip them\n"
	"	add	sp, sp, r4, lsl #2\n"
	"	@ get the argv address\n"
	"	add	r2, sp, #4\n"
	"	@ store the new argc in the new stack location\n"
	"	str	r1, [sp]\n"
	"	@ compute envp\n"
	"	add	r3, r2, r1, lsl #2\n"
	"	add	r3, r3, #4\n"
	"\n\n"
	"	@ load the finalizer function\n"
	"	ldr	r0, .L_FINI_PROC\n"
	"	ldr	r0, [sl, r0]\n"
	"	@ jump to the user_s entry point\n"
#if defined(__USE_BX__)
	"	bx	r6\n"
#else
	"	mov	pc, r6\n"
#endif
	".L_GET_GOT:\n"
	"	.word	_GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
	".L_SKIP_ARGS:\n"
	"	.word	_dl_skip_args(GOTOFF)\n"
	".L_FINI_PROC:\n"
	"	.word	_dl_fini(GOT)\n"
	"\n\n"
    "	.size	_start,.-_start\n"
	".previous\n"
);
#else
```

* 從註解可以看出來最後一行是移動到 user entry point




