Added script generating additions to libgcc_compat.c from linker errors

bug: 12234455
Change-Id: Icac35237f06e75745da5a91d9c4c941d7df4f84d
This commit is contained in:
Dmitriy Ivanov 2014-02-19 17:23:24 -08:00
parent 44ef37c1b4
commit adab51aefd
2 changed files with 224 additions and 166 deletions

View File

@ -1,176 +1,90 @@
/*
* Copyright (C) 2008 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.
*/
/* This file contains dummy references to libgcc.a functions to force the
* dynamic linker to copy their definition into the final libc.so binary.
*
* They are required to ensure backwards binary compatibility with
* libc.so provided by the platform and binaries built with the NDK or
* different versions/configurations of toolchains.
*
* Now, for a more elaborate description of the issue:
*
* libgcc.a is a compiler-specific library containing various helper
* functions used to implement certain operations that are not necessarily
* supported by the target CPU. For example, integer division doesn't have a
* corresponding CPU instruction on ARMv5, and is instead implemented in the
* compiler-generated machine code as a call to an __idiv helper function.
*
* Normally, one has to place libgcc.a in the link command used to generate
* target binaries (shared libraries and executables) after all objects and
* static libraries, but before dependent shared libraries, i.e. something
* like:
* gcc <options> -o libfoo.so foo.a libgcc.a -lc -lm
*
* This ensures that any helper function needed by the code in foo.a is copied
* into the final libfoo.so. However, doing so will link a bunch of other __cxa
* functions from libgcc.a into each .so and executable, causing 4k+ increase
* in every binary. Therefore the Android platform build system has been
* using this instead:
*
* gcc <options> -o libfoo.so foo.a -lc -lm libgcc.a
*
* The problem with this is that if one helper function needed by foo.a has
* already been copied into libc.so or libm.so, then nothing will be copied
* into libfoo.so. Instead, a symbol import definition will be added to it
* so libfoo.so can directly call the one in libc.so at runtime.
*
* When refreshing toolchains for new versions or using different architecture
* flags, the set of helper functions copied to libc.so may change, which
* resulted in some native shared libraries generated with the NDK or prebuilts
* from vendors to fail to load properly.
*
* The NDK has been fixed after 1.6_r1 to use the correct link command, so
* any native shared library generated with it should now be safe from that
* problem. On the other hand, existing shared libraries distributed with
* applications that were generated with a previous version of the NDK
* still need all 1.5/1.6 helper functions in libc.so and libm.so
*
* After 3.2, the toolchain was updated again, adding __aeabi_f2uiz to the
* list of requirements. Technically, this is due to mis-linked NDK libraries
* but it is easier to add a single function here than asking several app
* developers to fix their build.
*
* The __aeabi_idiv function is added to the list since cortex-a15 supports
* HW idiv instructions so the system libc.so doesn't pull in the reference to
* __aeabi_idiv but legacy libraries built against cortex-a9 targets still need
* it.
*
* Final note: some of the functions below should really be in libm.so to
* completely reflect the state of 1.5/1.6 system images. However,
* since libm.so depends on libc.so, it's easier to put all of
* these in libc.so instead, since the dynamic linker will always
* search in libc.so before libm.so for dependencies.
*/
/* Generated by genlibgcc_compat.py */
#define COMPAT_FUNCTIONS_LIST \
XX(__adddf3) \
XX(__addsf3) \
XX(__aeabi_cdcmpeq) \
XX(__aeabi_cdcmple) \
XX(__aeabi_cdrcmple) \
XX(__aeabi_d2f) \
XX(__aeabi_d2iz) \
XX(__aeabi_dadd) \
XX(__aeabi_dcmpeq) \
XX(__aeabi_dcmpge) \
XX(__aeabi_dcmpgt) \
XX(__aeabi_dcmple) \
XX(__aeabi_dcmplt) \
XX(__aeabi_dcmpun) \
XX(__aeabi_ddiv) \
XX(__aeabi_dmul) \
XX(__aeabi_drsub) \
XX(__aeabi_dsub) \
XX(__aeabi_f2d) \
XX(__aeabi_f2iz) \
XX(__aeabi_f2uiz) \
XX(__aeabi_fadd) \
XX(__aeabi_fcmpun) \
XX(__aeabi_fdiv) \
XX(__aeabi_fmul) \
XX(__aeabi_frsub) \
XX(__aeabi_fsub) \
XX(__aeabi_i2d) \
XX(__aeabi_i2f) \
XX(__aeabi_idiv) \
XX(__aeabi_idivmod) \
XX(__aeabi_l2d) \
XX(__aeabi_l2f) \
XX(__aeabi_lasr) \
XX(__aeabi_ldivmod) \
XX(__aeabi_llsl) \
XX(__aeabi_llsr) \
XX(__aeabi_lmul) \
XX(__aeabi_ui2d) \
XX(__aeabi_ui2f) \
XX(__aeabi_uidiv) \
XX(__aeabi_uidivmod) \
XX(__aeabi_ul2d) \
XX(__aeabi_ul2f) \
XX(__aeabi_uldivmod) \
XX(__cmpdf2) \
XX(__divdf3) \
XX(__divsf3) \
XX(__eqdf2) \
XX(__extendsfdf2) \
XX(__fixdfsi) \
XX(__fixsfsi) \
XX(__floatdidf) \
XX(__floatdisf) \
XX(__floatsidf) \
XX(__floatsisf) \
XX(__floatundidf) \
XX(__floatundisf) \
XX(__floatunsidf) \
XX(__floatunsisf) \
XX(__gedf2) \
XX(__gtdf2) \
XX(__ledf2) \
XX(__ltdf2) \
XX(__muldf3) \
XX(__muldi3) \
XX(__mulsf3) \
XX(__nedf2) \
XX(__popcountsi2) \
XX(__popcount_tab) \
XX(__subdf3) \
XX(__subsf3) \
XX(__truncdfsf2) \
XX(__unorddf2) \
XX(__unordsf2) \
XX(__adddf3) \
XX(__addsf3) \
XX(__aeabi_cdcmpeq) \
XX(__aeabi_cdcmple) \
XX(__aeabi_cdrcmple) \
XX(__aeabi_d2f) \
XX(__aeabi_d2iz) \
XX(__aeabi_dadd) \
XX(__aeabi_dcmpeq) \
XX(__aeabi_dcmpge) \
XX(__aeabi_dcmpgt) \
XX(__aeabi_dcmple) \
XX(__aeabi_dcmplt) \
XX(__aeabi_dcmpun) \
XX(__aeabi_ddiv) \
XX(__aeabi_dmul) \
XX(__aeabi_drsub) \
XX(__aeabi_dsub) \
XX(__aeabi_f2d) \
XX(__aeabi_f2iz) \
XX(__aeabi_f2uiz) \
XX(__aeabi_fadd) \
XX(__aeabi_fcmpun) \
XX(__aeabi_fdiv) \
XX(__aeabi_fmul) \
XX(__aeabi_frsub) \
XX(__aeabi_fsub) \
XX(__aeabi_i2d) \
XX(__aeabi_i2f) \
XX(__aeabi_idiv) \
XX(__aeabi_idivmod) \
XX(__aeabi_l2d) \
XX(__aeabi_l2f) \
XX(__aeabi_lasr) \
XX(__aeabi_ldivmod) \
XX(__aeabi_llsl) \
XX(__aeabi_llsr) \
XX(__aeabi_lmul) \
XX(__aeabi_ui2d) \
XX(__aeabi_ui2f) \
XX(__aeabi_uidiv) \
XX(__aeabi_uidivmod) \
XX(__aeabi_ul2d) \
XX(__aeabi_ul2f) \
XX(__aeabi_uldivmod) \
XX(__aeabi_unwind_cpp_pr0) \
XX(__aeabi_unwind_cpp_pr1) \
XX(__cmpdf2) \
XX(__divdf3) \
XX(__divsf3) \
XX(__eqdf2) \
XX(__extendsfdf2) \
XX(__fixdfsi) \
XX(__fixsfsi) \
XX(__floatdidf) \
XX(__floatdisf) \
XX(__floatsidf) \
XX(__floatsisf) \
XX(__floatundidf) \
XX(__floatundisf) \
XX(__floatunsidf) \
XX(__floatunsisf) \
XX(__gedf2) \
XX(__gtdf2) \
XX(__ledf2) \
XX(__ltdf2) \
XX(__muldf3) \
XX(__muldi3) \
XX(__mulsf3) \
XX(__nedf2) \
XX(__popcount_tab) \
XX(__popcountsi2) \
XX(__subdf3) \
XX(__subsf3) \
XX(__truncdfsf2) \
XX(__unorddf2) \
XX(__unordsf2) \
#define XX(f) extern void f(void);
COMPAT_FUNCTIONS_LIST
#undef XX
void __bionic_libgcc_compat_hooks(void)
{
void __bionic_libgcc_compat_hooks(void) {
#define XX(f) f();
COMPAT_FUNCTIONS_LIST
#undef XX

144
libc/tools/genlibgcc_compat.py Executable file
View File

@ -0,0 +1,144 @@
#!/usr/bin/python
'''
/* This file generates libgcc_compat.c file that contains dummy
* references to libgcc.a functions to force the dynamic linker
* to copy their definition into the final libc.so binary.
*
* They are required to ensure backwards binary compatibility with
* libc.so provided by the platform and binaries built with the NDK or
* different versions/configurations of toolchains.
*
* Now, for a more elaborate description of the issue:
*
* libgcc.a is a compiler-specific library containing various helper
* functions used to implement certain operations that are not necessarily
* supported by the target CPU. For example, integer division doesn't have a
* corresponding CPU instruction on ARMv5, and is instead implemented in the
* compiler-generated machine code as a call to an __idiv helper function.
*
* Normally, one has to place libgcc.a in the link command used to generate
* target binaries (shared libraries and executables) after all objects and
* static libraries, but before dependent shared libraries, i.e. something
* like:
* gcc <options> -o libfoo.so foo.a libgcc.a -lc -lm
*
* This ensures that any helper function needed by the code in foo.a is copied
* into the final libfoo.so. However, doing so will link a bunch of other __cxa
* functions from libgcc.a into each .so and executable, causing 4k+ increase
* in every binary. Therefore the Android platform build system has been
* using this instead:
*
* gcc <options> -o libfoo.so foo.a -lc -lm libgcc.a
*
* The problem with this is that if one helper function needed by foo.a has
* already been copied into libc.so or libm.so, then nothing will be copied
* into libfoo.so. Instead, a symbol import definition will be added to it
* so libfoo.so can directly call the one in libc.so at runtime.
*
* When refreshing toolchains for new versions or using different architecture
* flags, the set of helper functions copied to libc.so may change, which
* resulted in some native shared libraries generated with the NDK or prebuilts
* from vendors to fail to load properly.
*
* The NDK has been fixed after 1.6_r1 to use the correct link command, so
* any native shared library generated with it should now be safe from that
* problem. On the other hand, existing shared libraries distributed with
* applications that were generated with a previous version of the NDK
* still need all 1.5/1.6 helper functions in libc.so and libm.so
*
* After 3.2, the toolchain was updated again, adding __aeabi_f2uiz to the
* list of requirements. Technically, this is due to mis-linked NDK libraries
* but it is easier to add a single function here than asking several app
* developers to fix their build.
*
* The __aeabi_idiv function is added to the list since cortex-a15 supports
* HW idiv instructions so the system libc.so doesn't pull in the reference to
* __aeabi_idiv but legacy libraries built against cortex-a9 targets still need
* it.
*
* Final note: some of the functions below should really be in libm.so to
* completely reflect the state of 1.5/1.6 system images. However,
* since libm.so depends on libc.so, it's easier to put all of
* these in libc.so instead, since the dynamic linker will always
* search in libc.so before libm.so for dependencies.
*/
'''
import os
import sys
import subprocess
import tempfile
import re
libgcc_compat_header = "/* Generated by genlibgcc_compat.py */\n" + \
"""
#define COMPAT_FUNCTIONS_LIST \\
"""
libgcc_compat_footer = """
#define XX(f) extern void f(void);
COMPAT_FUNCTIONS_LIST
#undef XX
void __bionic_libgcc_compat_hooks(void) {
#define XX(f) f();
COMPAT_FUNCTIONS_LIST
#undef XX
}
"""
class Generator:
def process(self):
android_build_top_path = os.environ["ANDROID_BUILD_TOP"]
build_path = android_build_top_path + "/bionic/libc"
file_name = "libgcc_compat.c"
file_path = build_path + "/arch-arm/bionic/" + file_name
print "* ANDROID_BUILD_TOP=" + android_build_top_path
# Check TARGET_ARCH
arch = subprocess.check_output(["CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make --no-print-directory -f build/core/config.mk dumpvar-TARGET_ARCH"],
cwd=android_build_top_path, shell=True).strip()
if arch != 'arm':
sys.exit("Error: Invalid TARGET_ARCH='" + arch + "' expecting 'arm'")
build_output_file_path = tempfile.mkstemp()[1]
p = subprocess.Popen(["ONE_SHOT_MAKEFILE=bionic/libc/Android.mk make -C " + android_build_top_path
+ " -f build/core/main.mk all_modules TARGET_LIBGCC= -j20 -B 2>&1 | tee " + build_output_file_path],
cwd=build_path, shell=True)
p.wait()
print "* Build complete, logfile: " + build_output_file_path
func_set = set()
prog=re.compile("(?<=undefined reference to ')\w+")
fd = open(build_output_file_path, 'r')
for line in fd:
m = prog.search(line)
if m:
func_set.add(m.group(0))
fd.close()
func_list = sorted(func_set)
print "* Found " + repr(len(func_list)) + " referenced functions: " + repr(func_list)
if 0 == len(func_list):
sys.exit("Error: function list is empty, please check the build log: " + build_output_file_path)
print "* Generating " + file_path
fres = open(file_path, 'w')
fres.write(libgcc_compat_header)
for func_name in func_list:
fres.write(" XX("+func_name+") \\\n")
fres.write(libgcc_compat_footer)
fres.close()
generator = Generator()
generator.process()