diff --git a/tools/profiles/debug.json b/tools/profiles/debug.json index 295211564d..d6c439eff6 100644 --- a/tools/profiles/debug.json +++ b/tools/profiles/debug.json @@ -1,15 +1,15 @@ { "GCC_ARM": { - "common": ["-c", "-Wall", "-Wextra", + "common": ["-Wall", "-Wextra", "-Wno-unused-parameter", "-Wno-missing-field-initializers", "-fmessage-length=0", "-fno-exceptions", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", - "-fomit-frame-pointer", "-Og", "-g3", "-DMBED_DEBUG", + "-fomit-frame-pointer", "-Og", "-DMBED_DEBUG", "-DMBED_TRAP_ERRORS_ENABLED=1"], - "asm": ["-x", "assembler-with-cpp"], - "c": ["-std=gnu11"], - "cxx": ["-std=gnu++14", "-fno-rtti", "-Wvla"], + "asm": ["-c", "-g3", "-x", "assembler-with-cpp"], + "c": ["-c", "-g3", "-std=gnu11"], + "cxx": ["-c", "-g3", "-std=gnu++14", "-fno-rtti", "-Wvla"], "ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r", "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r", "-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit", diff --git a/tools/profiles/develop.json b/tools/profiles/develop.json index f8626d86f9..ddd4585ef3 100644 --- a/tools/profiles/develop.json +++ b/tools/profiles/develop.json @@ -1,14 +1,14 @@ { "GCC_ARM": { - "common": ["-c", "-Wall", "-Wextra", + "common": ["-Wall", "-Wextra", "-Wno-unused-parameter", "-Wno-missing-field-initializers", "-fmessage-length=0", "-fno-exceptions", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fomit-frame-pointer", "-Os", "-g", "-DMBED_TRAP_ERRORS_ENABLED=1"], - "asm": ["-x", "assembler-with-cpp"], - "c": ["-std=gnu11"], - "cxx": ["-std=gnu++14", "-fno-rtti", "-Wvla"], + "asm": ["-c", "-x", "assembler-with-cpp"], + "c": ["-c", "-std=gnu11"], + "cxx": ["-c", "-std=gnu++14", "-fno-rtti", "-Wvla"], "ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r", "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r", "-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit", diff --git a/tools/profiles/extensions/lto.json b/tools/profiles/extensions/lto.json index 59366afb32..116b95e2c6 100644 --- a/tools/profiles/extensions/lto.json +++ b/tools/profiles/extensions/lto.json @@ -2,5 +2,9 @@ "ARMC6": { "common": ["-flto"], "ld": ["--lto", "--lto_level=Oz"] + }, + "GCC_ARM": { + "common": ["-flto"], + "ld": ["-u main"] } } diff --git a/tools/profiles/release.json b/tools/profiles/release.json index 5ab3a58d73..a4312a3c2e 100644 --- a/tools/profiles/release.json +++ b/tools/profiles/release.json @@ -1,14 +1,14 @@ { "GCC_ARM": { - "common": ["-c", "-Wall", "-Wextra", + "common": ["-Wall", "-Wextra", "-Wno-unused-parameter", "-Wno-missing-field-initializers", "-fmessage-length=0", "-fno-exceptions", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fomit-frame-pointer", "-Os", "-DNDEBUG", "-g"], - "asm": ["-x", "assembler-with-cpp"], - "c": ["-std=gnu11"], - "cxx": ["-std=gnu++14", "-fno-rtti", "-Wvla"], + "asm": ["-c", "-x", "assembler-with-cpp"], + "c": ["-c", "-std=gnu11"], + "cxx": ["-c", "-std=gnu++14", "-fno-rtti", "-Wvla"], "ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r", "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r", "-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit", diff --git a/tools/toolchains/gcc.py b/tools/toolchains/gcc.py index a55de6696a..5a40fbf859 100644 --- a/tools/toolchains/gcc.py +++ b/tools/toolchains/gcc.py @@ -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.*)') def __init__(self, target, notify=None, macros=None, build_profile=None, build_dir=None, coverage_patterns=None): @@ -149,12 +150,14 @@ class GCC(mbedToolchain): self.cppc += self.flags['cxx'] + self.flags['common'] self.flags['ld'] += self.cpu - self.ld = [join(tool_path, "arm-none-eabi-gcc")] + self.flags['ld'] + self.ld = [join(tool_path, "arm-none-eabi-gcc")] + self.ld += self.flags['ld'] + self.flags['common'] self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc", "nosys"] self.preproc = [join(tool_path, "arm-none-eabi-cpp"), "-E", "-P"] 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)) @@ -305,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"] @@ -382,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