Tools: Add a workaround for the GCC_ARM & LTO bug

This is a workaround for the GCC not using the strong symbols from
C files to override the weak symbols from ASM files. This GCC bug is only
present when building with the link-time optimizer (LTO) enabled. For
more details please see:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967

This can be fixed by changing the order of object files in the linker
command; objects providing the weak symbols and compiled from assembly
must be listed before the objects providing the strong symbols.
To keep things simple, ALL object files from ASM are listed before
other object files.
pull/11856/head
Filip Jagodzinski 2020-02-13 17:47:40 +01:00
parent b03f974d03
commit 56255adb9f
1 changed files with 38 additions and 2 deletions

View File

@ -17,7 +17,7 @@ limitations under the License.
import re
import fnmatch
from os.path import join, basename, splitext, dirname, exists
from os import getenv
from os import getcwd, getenv
from distutils.spawn import find_executable
from distutils.version import LooseVersion
@ -35,6 +35,7 @@ class GCC(mbedToolchain):
GCC_RANGE = (LooseVersion("9.0.0"), LooseVersion("10.0.0"))
GCC_VERSION_RE = re.compile(b"\d+\.\d+\.\d+")
DWARF_PRODUCER_RE = re.compile(r'(DW_AT_producer)(.*:\s*)(?P<producer>.*)')
def __init__(self, target, notify=None, macros=None, build_profile=None,
build_dir=None, coverage_patterns=None):
@ -156,6 +157,7 @@ class GCC(mbedToolchain):
self.ar = join(tool_path, "arm-none-eabi-ar")
self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
self.objdump = join(tool_path, "arm-none-eabi-objdump")
self.use_distcc = (bool(getenv("DISTCC_POTENTIAL_HOSTS", False))
and not getenv("MBED_DISABLE_DISTCC", False))
@ -306,12 +308,31 @@ class GCC(mbedToolchain):
self.default_cmd(cmd)
mem_map = preproc_output
# NOTE: GCC_ARM_LTO_WORKAROUND
# This is a workaround for the GCC not using the strong symbols from
# C files to override the weak symbols from ASM files. This GCC bug is only
# present when building with the link-time optimizer (LTO) enabled. For
# more details please see:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967
#
# This can be fixed by changing the order of object files in the linker
# command; objects providing the weak symbols and compiled from assembly
# must be listed before the objects providing the strong symbols.
# To keep things simple, ALL object files from ASM are listed before
# other object files.
asm_objects = []
if '-flto' in self.ld:
asm_objects = self.get_asm_objects(objects)
reorg_objects = (
[o for o in objects if o in asm_objects] +
[o for o in objects if o not in asm_objects]
)
# Build linker command
map_file = splitext(output)[0] + ".map"
cmd = (
(self.coverage_ld if self.coverage_patterns else self.ld) +
["-o", output, "-Wl,-Map=%s" % map_file] +
objects +
reorg_objects +
["-Wl,--start-group"] +
libs +
["-Wl,--end-group"]
@ -383,6 +404,21 @@ class GCC(mbedToolchain):
exec_name = join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-gcc')
return exists(exec_name) or exists(exec_name + '.exe')
def check_if_obj_from_asm(self, obj_file):
"""Check if obj_file was build by the GNU Assembler."""
dw_producer = ''
cmd = [self.objdump, '--dwarf=info', obj_file]
stdout, stderr, rc = run_cmd(cmd, work_dir=getcwd(), chroot=self.CHROOT)
if rc != 0:
return False
match = self.DWARF_PRODUCER_RE.search(stdout.encode('utf-8'))
if match:
dw_producer = match.group('producer')
return 'GNU AS' in dw_producer
def get_asm_objects(self, objects):
"""Return a list of object files built from ASM."""
return [o for o in objects if self.check_if_obj_from_asm(o)]
class GCC_ARM(GCC):
pass