From 804b8439833604981a55d56346e5d1a86e43823c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 28 Nov 2022 17:00:13 +0100 Subject: [PATCH] support -ffat-lto-objects for GCC compiler FAT LTO objects are objects that contain both native assembly and LTO bytecode. Identify such files as GCC_LTO_OBJ. Signed-off-by: Martin Liska --- filetype.h | 19 +++++++++++++++++-- test/elf/lto-gcc.sh | 9 +++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/filetype.h b/filetype.h index 4683412c2..4ae906eb1 100644 --- a/filetype.h +++ b/filetype.h @@ -36,9 +36,26 @@ inline bool is_gcc_lto_obj(MappedFile *mf) { const char *data = mf->get_contents().data(); ElfEhdr &ehdr = *(ElfEhdr *)data; + ElfShdr *sh_begin = (ElfShdr *)(data + ehdr.e_shoff); std::span> shdrs{(ElfShdr *)(data + ehdr.e_shoff), ehdr.e_shnum}; + // e_shstrndx is a 16-bit field. If .shstrtab's section index is + // too large, the actual number is stored to sh_link field. + i64 shstrtab_idx = (ehdr.e_shstrndx == SHN_XINDEX) + ? sh_begin->sh_link : ehdr.e_shstrndx; + for (ElfShdr &sec : shdrs) { + // GCC LTO object contains only sections symbols followed by a common + // symbol whose name is `__gnu_lto_slim` (or `__gnu_lto_v1` for older + // GCC releases). + // + // However, FAT LTO objects don't have any of the above mentioned symbols + // and can identify LTO by `.gnu.lto_.symtab.` section, similarly + // to what lto-plugin does. + std::string_view name = data + shdrs[shstrtab_idx].sh_offset + sec.sh_name; + if (name.starts_with (".gnu.lto_.symtab.")) + return true; + if (sec.sh_type != SHT_SYMTAB) continue; @@ -49,8 +66,6 @@ inline bool is_gcc_lto_obj(MappedFile *mf) { return type == STT_NOTYPE || type == STT_FILE || type == STT_SECTION; }; - // GCC LTO object contains only sections symbols followed by a common - // symbol whose name is `__gnu_lto_v1` or `__gnu_lto_slim`. i64 i = 1; while (i < elf_syms.size() && skip(elf_syms[i].st_type)) i++; diff --git a/test/elf/lto-gcc.sh b/test/elf/lto-gcc.sh index 578021343..b28e98c12 100755 --- a/test/elf/lto-gcc.sh +++ b/test/elf/lto-gcc.sh @@ -13,3 +13,12 @@ EOF $GCC -B. -o $t/exe -flto $t/a.o $QEMU $t/exe | grep -q 'Hello world' + +# Test that LTO is used for FAT LTO objects +cat < +int main() { + printf("Hello world\n"); +} +EOF +$GCC -B. -o $t/exe $t/a.o --verbose 2>&1 | grep -- -fwpa