arm: rewrite crtbegin* as C files.

Rewrite
 crtbegin.S     -> crtbegin.c
 crtbegin_so.S  -> crtbegin_so.c

This change allows us to generate PIC code without relying
on text relocations.

As a consequence of this rewrite, also rewrite
  __dso_handle.S    -> __dso_handle.c
  __dso_handle_so.S -> __dso_handle_so.c
  atexit.S          -> atexit.c

In crtbegin.c _start, place the __PREINIT_ARRAY__, __INIT_ARRAY__,
__FINI_ARRAY__, and __CTOR_LIST__ variables onto the stack, instead of
passing a pointer to the text section of the binary.

This change appears sorta wonky, as I attempted to preserve,
as much as possible, the structure of the original assembly.
As a result, you have C files including other C files, and other
programming uglyness.

Result: This change reduces the number of files with text-relocations
from 315 to 19 on my Android build.

Before:
  $ scanelf -aR $OUT/system | grep TEXTREL | wc -l
  315

After:
  $ scanelf -aR $OUT/system | grep TEXTREL | wc -l
  19

Change-Id: Ib9f98107c0eeabcb606e1ddc7ed7fc4eba01c9c4
This commit is contained in:
Nick Kralevich 2012-05-31 11:40:10 -07:00
parent 857fc9eab9
commit 9d40326830
8 changed files with 154 additions and 127 deletions

View File

@ -515,8 +515,8 @@ else
libc_common_cflags += -DANDROID_SMP=0
endif
# Needed to access private/__dso_handle.S from
# crtbegin_xxx.S and crtend_xxx.S
# Needed to access private/__dso_handle.h from
# crtbegin_xxx.c and crtend_xxx.c
#
libc_crt_target_cflags += -I$(LOCAL_PATH)/private
@ -531,9 +531,8 @@ libc_common_c_includes := \
$(LOCAL_PATH)/string \
$(LOCAL_PATH)/stdio
# Needed to access private/__dso_handle.S from
# Needed to access private/__dso_handle.h from
# crtbegin_xxx.S and crtend_xxx.S
# and machine/asm.h
#
libc_crt_target_cflags += -I$(LOCAL_PATH)/private -I$(LOCAL_PATH)/arch-$(TARGET_ARCH)/include
@ -555,12 +554,16 @@ ifneq ($(filter arm x86,$(TARGET_ARCH)),)
#
libc_crt_target_so_cflags := $(libc_crt_target_cflags)
libc_crt_target_crtstart_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.c
libc_crt_target_crtstart_so_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.c
ifeq ($(TARGET_ARCH),x86)
# This flag must be added for x86 targets, but not for ARM
libc_crt_target_so_cflags += -fPIC
libc_crt_target_crtstart_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.S
libc_crt_target_crtstart_so_file := $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.S
endif
GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.S
$(GEN): $(libc_crt_target_crtstart_so_file)
@mkdir -p $(dir $@)
$(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
ALL_GENERATED_SOURCES += $(GEN)
@ -574,13 +577,13 @@ endif # TARGET_ARCH == x86 || TARGET_ARCH == arm
GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.S
$(GEN): $(libc_crt_target_crtstart_file)
@mkdir -p $(dir $@)
$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
ALL_GENERATED_SOURCES += $(GEN)
GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin.S
$(GEN): $(libc_crt_target_crtstart_file)
@mkdir -p $(dir $@)
$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
ALL_GENERATED_SOURCES += $(GEN)

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -25,61 +25,29 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
.text
.align 4
.type _start,#function
.globl _start
# this is the small startup code that is first run when
# any executable that is linked with Bionic runs.
#
# it's purpose is to call __libc_init with appropriate
# arguments, which are:
#
# - the address of the raw data block setup by the Linux
# kernel ELF loader
#
# - address of an "onexit" function, not used on any
# platform supported by Bionic
#
# - address of the "main" function of the program.
#
# - address of the constructor list
#
_start:
mov r0, sp
mov r1, #0
ldr r2, =main
adr r3, 1f
ldr r4, =__libc_init
blx r4
mov r0, #0
bx r0
/* CRT_LEGACY_WORKAROUND should only be defined when building
* this file as part of the platform's C library.
*
* The C library already defines a function named 'atexit()'
* for backwards compatibility with older NDK-generated binaries.
*
* For newer ones, 'atexit' is actually embedded in the C
* runtime objects that are linked into the final ELF
* binary (shared library or executable), and will call
* __cxa_atexit() in order to un-register any atexit()
* handler when a library is unloaded.
*
* This function must be global *and* hidden. Only the
* code inside the same ELF binary should be able to access it.
*/
1: .long __PREINIT_ARRAY__
.long __INIT_ARRAY__
.long __FINI_ARRAY__
.long __CTOR_LIST__
#ifndef CRT_LEGACY_WORKAROUND
extern void *__dso_handle;
.section .preinit_array, "aw"
.globl __PREINIT_ARRAY__
__PREINIT_ARRAY__:
.long -1
.section .init_array, "aw"
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
.section .fini_array, "aw"
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
.section .ctors, "aw"
.globl __CTOR_LIST__
__CTOR_LIST__:
.long -1
#include "__dso_handle.S"
#include "atexit.S"
__attribute__ ((visibility ("hidden")))
int atexit(void (*func)(void))
{
return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
}
#endif

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
typedef struct
{
void (**preinit_array)(void);
void (**init_array)(void);
void (**fini_array)(void);
void (**ctors_array)(void);
} structors_array_t;
extern int main(int argc, char **argv, char **env);
extern void __libc_init(
unsigned int *elfdata,
void (*onexit)(void),
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors
);
__attribute__ ((section (".preinit_array")))
void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".init_array")))
void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".fini_array")))
void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".ctors")))
void (*__CTOR_LIST__)(void) = (void (*)(void)) -1;
__attribute__((visbility("hidden")))
void _start() {
structors_array_t array;
void *elfdata;
array.preinit_array = &__PREINIT_ARRAY__;
array.init_array = &__INIT_ARRAY__;
array.fini_array = &__FINI_ARRAY__;
array.ctors_array = &__CTOR_LIST__;
elfdata = __builtin_frame_address(0) + sizeof(void *);
__libc_init(elfdata, (void *) 0, &main, &array);
}
#include "__dso_handle.h"
#include "atexit.h"

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,39 +26,18 @@
* SUCH DAMAGE.
*/
#include <machine/asm.h>
extern void __cxa_finalize(void *);
extern void *__dso_handle;
# Implement static C++ destructors when the shared
# library is unloaded through dlclose().
#
# A call to this function must be the first entry
# in the .fini_array. See 3.3.5.3.C of C++ ABI
# standard.
#
ENTRY(__on_dlclose)
adr r0, 0f
ldr r0, [r0]
b __cxa_finalize
END(__on_dlclose)
0:
.long __dso_handle
.section .init_array, "aw"
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
.section .fini_array, "aw"
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
.long __on_dlclose
__attribute__((visbility("hidden")))
void __on_dlclose() {
__cxa_finalize(&__dso_handle);
}
#ifdef CRT_LEGACY_WORKAROUND
#include "__dso_handle.S"
#include "__dso_handle.h"
#else
#include "__dso_handle_so.S"
#include "__dso_handle_so.h"
#endif
#include "atexit.S"
#include "atexit.h"

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011 The Android Open Source Project
* Copyright (C) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,37 +26,9 @@
* SUCH DAMAGE.
*/
#ifndef CRT_LEGACY_WORKAROUND
.arch armv5te
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 4
.eabi_attribute 18, 4
.hidden atexit
.code 16
.thumb_func
ENTRY(atexit)
.LFB0:
.save {r4, lr}
push {r4, lr}
.LCFI0:
ldr r3, .L3
mov r1, #0
@ sp needed for prologue
.LPIC0:
add r3, pc
ldr r2, [r3]
bl __cxa_atexit
pop {r4, pc}
.L4:
.align 2
.L3:
.word __dso_handle-(.LPIC0+4)
.LFE0:
END(atexit)
__attribute__ ((visibility ("hidden")))
#endif
__attribute__ ((section (".bss")))
void *__dso_handle = (void *) 0;

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
__attribute__ ((visibility ("hidden")))
__attribute__ ((section (".data")))
void *__dso_handle;