Skip to content

Commit

Permalink
support -ffat-lto-objects for GCC compiler
Browse files Browse the repository at this point in the history
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 <mliska@suse.cz>
  • Loading branch information
marxin committed Nov 28, 2022
1 parent d2cfffc commit 804b843
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
19 changes: 17 additions & 2 deletions filetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,26 @@ inline bool is_gcc_lto_obj(MappedFile<C> *mf) {

const char *data = mf->get_contents().data();
ElfEhdr<E> &ehdr = *(ElfEhdr<E> *)data;
ElfShdr<E> *sh_begin = (ElfShdr<E> *)(data + ehdr.e_shoff);
std::span<ElfShdr<E>> shdrs{(ElfShdr<E> *)(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<E> &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;

Expand All @@ -49,8 +66,6 @@ inline bool is_gcc_lto_obj(MappedFile<C> *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++;
Expand Down
9 changes: 9 additions & 0 deletions test/elf/lto-gcc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<EOF | $GCC -flto -ffat-lto-objects -c -o $t/a.o -xc -
#include <stdio.h>
int main() {
printf("Hello world\n");
}
EOF
$GCC -B. -o $t/exe $t/a.o --verbose 2>&1 | grep -- -fwpa

0 comments on commit 804b843

Please sign in to comment.