Skip to content

Commit 56255ad

Browse files
author
Filip Jagodzinski
committed
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.
1 parent b03f974 commit 56255ad

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

tools/toolchains/gcc.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import re
1818
import fnmatch
1919
from os.path import join, basename, splitext, dirname, exists
20-
from os import getenv
20+
from os import getcwd, getenv
2121
from distutils.spawn import find_executable
2222
from distutils.version import LooseVersion
2323

@@ -35,6 +35,7 @@ class GCC(mbedToolchain):
3535

3636
GCC_RANGE = (LooseVersion("9.0.0"), LooseVersion("10.0.0"))
3737
GCC_VERSION_RE = re.compile(b"\d+\.\d+\.\d+")
38+
DWARF_PRODUCER_RE = re.compile(r'(DW_AT_producer)(.*:\s*)(?P<producer>.*)')
3839

3940
def __init__(self, target, notify=None, macros=None, build_profile=None,
4041
build_dir=None, coverage_patterns=None):
@@ -156,6 +157,7 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
156157

157158
self.ar = join(tool_path, "arm-none-eabi-ar")
158159
self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
160+
self.objdump = join(tool_path, "arm-none-eabi-objdump")
159161

160162
self.use_distcc = (bool(getenv("DISTCC_POTENTIAL_HOSTS", False))
161163
and not getenv("MBED_DISABLE_DISTCC", False))
@@ -306,12 +308,31 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
306308
self.default_cmd(cmd)
307309
mem_map = preproc_output
308310

311+
# NOTE: GCC_ARM_LTO_WORKAROUND
312+
# This is a workaround for the GCC not using the strong symbols from
313+
# C files to override the weak symbols from ASM files. This GCC bug is only
314+
# present when building with the link-time optimizer (LTO) enabled. For
315+
# more details please see:
316+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967
317+
#
318+
# This can be fixed by changing the order of object files in the linker
319+
# command; objects providing the weak symbols and compiled from assembly
320+
# must be listed before the objects providing the strong symbols.
321+
# To keep things simple, ALL object files from ASM are listed before
322+
# other object files.
323+
asm_objects = []
324+
if '-flto' in self.ld:
325+
asm_objects = self.get_asm_objects(objects)
326+
reorg_objects = (
327+
[o for o in objects if o in asm_objects] +
328+
[o for o in objects if o not in asm_objects]
329+
)
309330
# Build linker command
310331
map_file = splitext(output)[0] + ".map"
311332
cmd = (
312333
(self.coverage_ld if self.coverage_patterns else self.ld) +
313334
["-o", output, "-Wl,-Map=%s" % map_file] +
314-
objects +
335+
reorg_objects +
315336
["-Wl,--start-group"] +
316337
libs +
317338
["-Wl,--end-group"]
@@ -383,6 +404,21 @@ def check_executable():
383404
exec_name = join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-gcc')
384405
return exists(exec_name) or exists(exec_name + '.exe')
385406

407+
def check_if_obj_from_asm(self, obj_file):
408+
"""Check if obj_file was build by the GNU Assembler."""
409+
dw_producer = ''
410+
cmd = [self.objdump, '--dwarf=info', obj_file]
411+
stdout, stderr, rc = run_cmd(cmd, work_dir=getcwd(), chroot=self.CHROOT)
412+
if rc != 0:
413+
return False
414+
match = self.DWARF_PRODUCER_RE.search(stdout.encode('utf-8'))
415+
if match:
416+
dw_producer = match.group('producer')
417+
return 'GNU AS' in dw_producer
418+
419+
def get_asm_objects(self, objects):
420+
"""Return a list of object files built from ASM."""
421+
return [o for o in objects if self.check_if_obj_from_asm(o)]
386422

387423
class GCC_ARM(GCC):
388424
pass

0 commit comments

Comments
 (0)