Turn on more linker optimisation.

Discard more unused sections, identical code folding and link time
optimisation. These are things that we will likely want to use when
building out final image so turning them on now will help us catch any
issues they might cause as we're going.

Change-Id: Ibe6e26d0feb1fb899c2050a4b00f36d2b408d647
diff --git a/Makefile b/Makefile
index d6f537f..4c2476c 100644
--- a/Makefile
+++ b/Makefile
@@ -48,7 +48,7 @@
 	@find src/ -name *.c -o -name *.h | xargs clang-format -style file -i
 	@find inc/ -name *.c -o -name *.h | xargs clang-format -style file -i
 	@find test/ -name *.c -o -name *.h | xargs clang-format -style file -i
-	@find . -name *.gn -o -name *.gni -exec $(GN) format {} \;
+	@find . \( -name *.gn -o -name *.gni \) -exec $(GN) format {} \;
 
 # see .clang-tidy.
 .PHONY: tidy
diff --git a/build/BUILD.gn b/build/BUILD.gn
index 8ef2258..01c7a40 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -1,32 +1,25 @@
 import("//build/arch/common.gni")
-import("//build/arch/aarch64.gni") # TODO: remove when no dependency on arch_aarch64_pl011_base_address
+import("//build/arch/aarch64.gni")  # TODO: remove when no dependency on arch_aarch64_pl011_base_address
 
 config("compiler_defaults") {
   cflags = [
     "-g",
     "-O2",
     "-Wall",
+
     #"-Wextra",
     "-Wpedantic",
     "-Werror",
   ]
 
-  cflags_c = [
-    "-std=c11",
-  ]
+  cflags_c = [ "-std=c11" ]
 
-  cflags_cc = [
-    "-std=c++14",
-  ]
+  cflags_cc = [ "-std=c++14" ]
 
   if (is_debug) {
-    defines = [
-      "DEBUG=1",
-    ]
+    defines = [ "DEBUG=1" ]
   } else {
-    defines = [
-      "DEBUG=0",
-    ]
+    defines = [ "DEBUG=0" ]
   }
 
   # Configuration specific for the bare metal images
@@ -56,17 +49,17 @@
     # TODO: this should be arch specific but it is currenly used by the
     # platform generic code to map the memory
     if (arch_aarch64_use_pl011) {
-      defines += [
-        "PL011_BASE=${arch_aarch64_pl011_base_address}",
-      ]
+      defines += [ "PL011_BASE=${arch_aarch64_pl011_base_address}" ]
     }
   }
 }
 
 config("executable_ldconfig") {
   if (current_toolchain == arch_toolchain) {
-    ldflags = [
-      "--gc-sections"
-    ]
+    ldflags = [ "--gc-sections" ]
   }
 }
+
+config("lto") {
+  cflags = [ "-flto" ]
+}
diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn
index b330ffb..c211f2c 100644
--- a/build/BUILDCONFIG.gn
+++ b/build/BUILDCONFIG.gn
@@ -51,7 +51,10 @@
 assert(target_cpu == host_cpu, "Cross compiles not yet supported")
 
 # All binary targets will get this list of configs by default
-_shared_binary_target_configs = [ "//build:compiler_defaults" ]
+_shared_binary_target_configs = [
+  "//build:compiler_defaults",
+  "//build:lto",
+]
 
 # Apply that default list to the binary target types.
 set_defaults("executable") {
diff --git a/build/image/generate_offsets.gni b/build/image/generate_offsets.gni
index 7116f87..267eb6c 100644
--- a/build/image/generate_offsets.gni
+++ b/build/image/generate_offsets.gni
@@ -21,6 +21,9 @@
                              "sources",
                              "testonly",
                            ])
+
+    # Disable LTO so we get an object file.
+    configs -= [ "//build:lto" ]
     defines = [ "GEN_OFFSETS" ]
     visibility = [ ":${header_target}" ]
   }
diff --git a/build/image/image.ld b/build/image/image.ld
index ba5a626..9973954 100644
--- a/build/image/image.ld
+++ b/build/image/image.ld
@@ -64,6 +64,11 @@
 	.data : {
 		*(.data)
 	}
+	/* Global offset table used for relocations. This is where relocation
+	 * fix-ups are applied. */
+	.got : {
+		*(.got.*)
+	}
 	/* The entry point code assumes that .bss is 16-byte aligned. */
 	. = ALIGN(16);
 	bss_begin = .;
@@ -76,6 +81,21 @@
 	data_end = .;
 
 	/*
+	 * Remove unused sections from the image.
+	 */
+	/DISCARD/ : {
+		/* The image loads itself so doesn't need these sections. */
+		/* ld.lld doesn't allow these to be discarded.
+		*(.dynsym)
+		*(.dynstr)
+		*(.dynamic)
+		*/
+		*(.gnu.hash)
+		*(.hash)
+		*(.interp)
+	}
+
+	/*
 	 * Make note of some useful values.
 	 */
 
diff --git a/build/toolchain/arch/BUILD.gn b/build/toolchain/arch/BUILD.gn
index 2975cd3..8bfb538 100644
--- a/build/toolchain/arch/BUILD.gn
+++ b/build/toolchain/arch/BUILD.gn
@@ -71,13 +71,15 @@
 
 # Specialize for clang or gcc
 template("clang_toolchain") {
-  assert(defined(invoker.target), "clang_toolchain() must specify a \"target\" value")
-  assert(defined(invoker.arch_tool_prefix), "gcc_toolchain() must specify a \"arch_tool_prefix\" value")
+  assert(defined(invoker.target),
+         "clang_toolchain() must specify a \"target\" value")
+  assert(defined(invoker.arch_tool_prefix),
+         "gcc_toolchain() must specify a \"arch_tool_prefix\" value")
 
   cc_toolchain(target_name) {
     cc = "clang"
     cflags = "-target ${invoker.target} -fcolor-diagnostics"
-    ld = "ld.lld --color-diagnostics"
+    ld = "ld.lld --color-diagnostics -O2 -lto-O2 --icf=all --fatal-warnings"
 
     toolchain_args = {
       arch_tool_prefix = invoker.arch_tool_prefix
@@ -86,7 +88,8 @@
 }
 
 template("gcc_toolchain") {
-  assert(defined(invoker.arch_tool_prefix), "gcc_toolchain() must specify a \"arch_tool_prefix\" value")
+  assert(defined(invoker.arch_tool_prefix),
+         "gcc_toolchain() must specify a \"arch_tool_prefix\" value")
 
   cc_toolchain(target_name) {
     cc = "${invoker.arch_tool_prefix}gcc"
@@ -103,6 +106,7 @@
 
 clang_toolchain("clang_aarch64") {
   target = "aarch64-none-eabi"
+
   # TODO: below isn't right for bare metal code, but it works fine
   arch_tool_prefix = "aarch64-linux-gnu-"
 }
diff --git a/build/toolchain/host/BUILD.gn b/build/toolchain/host/BUILD.gn
index 4532e0d..8ab38e5 100644
--- a/build/toolchain/host/BUILD.gn
+++ b/build/toolchain/host/BUILD.gn
@@ -60,7 +60,8 @@
       sofile = "{{output_dir}}/$soname"
       rspfile = soname + ".rsp"
 
-      command = "${cxx} -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
+      command =
+          "${cxx} -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
       rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
 
       description = "SOLINK $soname"
diff --git a/src/BUILD.gn b/src/BUILD.gn
index be4a8ba..3f54988 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -19,9 +19,7 @@
   ]
 
   if (is_debug) {
-    deps += [
-      ":common_debug",
-    ]
+    deps += [ ":common_debug" ]
   }
 }
 
diff --git a/src/arch/aarch64/BUILD.gn b/src/arch/aarch64/BUILD.gn
index 93d887d..00f0553 100644
--- a/src/arch/aarch64/BUILD.gn
+++ b/src/arch/aarch64/BUILD.gn
@@ -4,8 +4,8 @@
 # Hypervisor specific code.
 source_set("aarch64") {
   sources = [
-    "exceptions.S",
     "cpu_entry.S",
+    "exceptions.S",
     "hypervisor_entry.S",
     "smc.S",
   ]
diff --git a/test/vm/primary_with_secondary/BUILD.gn b/test/vm/primary_with_secondary/BUILD.gn
index 9d9aff1..512ccfd 100644
--- a/test/vm/primary_with_secondary/BUILD.gn
+++ b/test/vm/primary_with_secondary/BUILD.gn
@@ -27,7 +27,10 @@
 initrd("primary_with_secondary_test") {
   testonly = true
   primary_vm = ":primary_with_secondary_test_primary_vm"
-  secondary_vms = [
-    ["1048576", "1", "secondary", ":primary_with_secondary_test_secondary_vm"],
-  ]
+  secondary_vms = [ [
+        "1048576",
+        "1",
+        "secondary",
+        ":primary_with_secondary_test_secondary_vm",
+      ] ]
 }