Bladeren bron

add support for init/finit (constructors and destructors)

this is mainly in hopes of supporting c++ (not yet possible for other
reasons) but will also help applications/libraries which use (and more
often, abuse) the gcc __attribute__((__constructor__)) feature in "C"
code.

x86_64 and arm versions of the new startup asm are untested and may
have minor problems.
Rich Felker 13 jaren geleden
bovenliggende
commit
4ce3cb5cdd
10 gewijzigde bestanden met toevoegingen van 75 en 7 verwijderingen
  1. 5 2
      crt/arm/crt1.s
  2. 7 0
      crt/arm/crti.s
  3. 9 0
      crt/arm/crtn.s
  4. 6 2
      crt/i386/crt1.s
  5. 7 0
      crt/i386/crti.s
  6. 5 0
      crt/i386/crtn.s
  7. 5 3
      crt/x86_64/crt1.s
  8. 7 0
      crt/x86_64/crti.s
  9. 5 0
      crt/x86_64/crtn.s
  10. 19 0
      src/ldso/dynlink.c

+ 5 - 2
crt/arm/crt1.s

@@ -1,13 +1,16 @@
+.weak _init
+.weak _fini
 .global _start
 _start:
 	mov fp,#0
 	mov lr,#0
 	ldr a2,[sp],#4
 	mov a3,sp
-	mov a4,#0
+	ldr a4,=_fini
 	str fp,[sp,#-4]!
 	str a1,[sp,#-4]!
-	str fp,[sp,#-4]!
+	str a4,[sp,#-4]!
+	ldr a4,=_init
 	ldr a1,=main
 	bl __libc_start_main
 1:	b 1b

+ 7 - 0
crt/arm/crti.s

@@ -0,0 +1,7 @@
+.section .init
+.global _init
+_init:
+
+.section .fini
+.global _fini
+_fini:

+ 9 - 0
crt/arm/crtn.s

@@ -0,0 +1,9 @@
+.section .init
+	tst lr,#1
+	moveq pc,lr
+	bx lr
+
+.section .fini
+	tst lr,#1
+	moveq pc,lr
+	bx lr

+ 6 - 2
crt/i386/crt1.s

@@ -1,3 +1,5 @@
+.weak _init
+.weak _fini
 .text
 .global _start
 _start:
@@ -8,8 +10,10 @@ _start:
 	pushl %esp
 	pushl %esp
 	pushl %edx
-	pushl %ebp
-	pushl %ebp
+	call 1f
+1:	addl $[_fini-.],(%esp)
+	call 1f
+1:	addl $[_init-.],(%esp)
 	pushl %eax
 	pushl %ecx
 	call 1f

+ 7 - 0
crt/i386/crti.s

@@ -0,0 +1,7 @@
+.section .init
+.global _init
+_init:
+
+.section .fini
+.global _fini
+_fini:

+ 5 - 0
crt/i386/crtn.s

@@ -0,0 +1,5 @@
+.section .init
+	ret
+
+.section .fini
+	ret

+ 5 - 3
crt/x86_64/crt1.s

@@ -1,4 +1,6 @@
 /* Written 2011 Nicholas J. Kain, released as Public Domain */
+.weak _init
+.weak _fini
 .text
 .global _start
 _start:
@@ -9,8 +11,8 @@ _start:
 	andq $-16,%rsp  /* align stack pointer */
 	push %rax       /* 8th arg: glibc ABI compatible */
 	push %rsp       /* 7th arg: glibc ABI compatible */
-	xor %r8,%r8     /* 5th arg: always 0 */
-	xor %rcx,%rcx   /* 4th arg: always 0 */
+	mov $_fini,%r8  /* 5th arg: fini/dtors function */
+	mov $_init,%rcx /* 4th arg: init/ctors function */
 	mov $main,%rdi  /* 1st arg: application entry ip */
 	call __libc_start_main /* musl init will run the program */
-.L0:	jmp .L0
+1:	jmp 1b

+ 7 - 0
crt/x86_64/crti.s

@@ -0,0 +1,7 @@
+.section .init
+.global _init
+_init:
+
+.section .fini
+.global _fini
+_fini:

+ 5 - 0
crt/x86_64/crtn.s

@@ -0,0 +1,5 @@
+.section .init
+	ret
+
+.section .fini
+	ret

+ 19 - 0
src/ldso/dynlink.c

@@ -49,6 +49,7 @@ struct dso
 	ino_t ino;
 	int global;
 	int relocated;
+	int constructed;
 	struct dso **deps;
 	char *name;
 	char buf[];
@@ -471,6 +472,20 @@ static size_t find_dyn(Phdr *ph, size_t cnt, size_t stride)
 	return 0;
 }
 
+static void do_init_fini(struct dso *p)
+{
+	size_t dyn[DYN_CNT] = {0};
+	for (; p; p=p->prev) {
+		if (p->constructed) return;
+		decode_vec(p->dynv, dyn, DYN_CNT);
+		if (dyn[0] & (1<<DT_FINI))
+			atexit((void (*)(void))(p->base + dyn[DT_FINI]));
+		if (dyn[0] & (1<<DT_INIT))
+			((void (*)(void))(p->base + dyn[DT_INIT]))();
+		p->constructed = 1;
+	}
+}
+
 void *__dynlink(int argc, char **argv)
 {
 	size_t *auxv, aux[AUX_CNT] = {0};
@@ -520,6 +535,7 @@ void *__dynlink(int argc, char **argv)
 	}
 	app->name = argv[0];
 	app->global = 1;
+	app->constructed = 1;
 	app->dynv = (void *)(app->base + find_dyn(
 		(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
 	decode_dyn(app);
@@ -577,6 +593,9 @@ void *__dynlink(int argc, char **argv)
 	 * error. If the dynamic loader (dlopen) will not be used, free
 	 * all memory used by the dynamic linker. */
 	runtime = 1;
+
+	do_init_fini(tail);
+
 	if (!rtld_used) {
 		free_all(head);
 		free(sys_path);