Linux: cannot find entry symbol _start

Created on 15 Oct 2018  路  11Comments  路  Source: ClangBuiltLinux/linux

  LD      arch/x86/realmode/rm/realmode.elf
ld.lld: warning: cannot find entry symbol _start; defaulting to 0x1000

This is with a few workarounds in place to link with LLD, so I wouldn't be surprise if once they're fixed, this quickly becomes unreproducible.

Needs Backport [ARCH] x86_64 [BUG] linux [FIXED][LINUX] 5.5 [TOOL] lld

All 11 comments

lld/ELF/Writer.cpp:

// The entry point address is chosen in the following ways.
//
// 1. the '-e' entry command-line option;
// 2. the ENTRY(symbol) command in a linker control script;
// 3. the value of the symbol _start, if present;
// 4. the number represented by the entry symbol, if it is a number;
// 5. the address of the first byte of the .text section, if present;
// 6. the address 0.
static uint64_t getEntryAddr() {
  // Case 1, 2 or 3
  if (Symbol *B = Symtab->find(Config->Entry))
    return B->getVA();

  // Case 4
  uint64_t Addr;
  if (to_integer(Config->Entry, Addr))
    return Addr;

  // Case 5
  if (OutputSection *Sec = findSection(".text")) {
    if (Config->WarnMissingEntry)
      warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +
           utohexstr(Sec->Addr));
    return Sec->Addr;
  }

  // Case 6
  if (Config->WarnMissingEntry)
    warn("cannot find entry symbol " + Config->Entry +
         "; not setting start address");
  return 0;
}

So I assume the kernel does one of the above for arm64, which is why we don't see this warning there. Maybe we just need to do that for x86_64 as well?

Or just disable the warning if the resulting code is still correct.

$ nm vmlinux | grep 'T _start$'
$ readelf -t vmlinux | grep text
  [ 1] .text
       PROGBITS               PROGBITS         ffffffff81000000  0000000000200000  0
       0000000000e01941 0000000000000000  0                 4096
       [0000000000000006]: ALLOC, EXEC

So maybe just best to disable the warning?

lld/ELF/Driver.cpp has:

  Config->WarnMissingEntry =
      (!Config->Entry.empty() || (!Config->Shared && !Config->Relocatable));

but I'm not sure how to set Config->Entry.empty(). -e '' just presents the error:

ld.lld: error: cannot find linker script -e

cc @rui314 @GeorgiiR

Is it possible to get the LLD --reproduce file for this?

(Actually, we use the getEntryAddr() value for ELF file header:
https://github.com/llvm-mirror/lld/blob/master/ELF/Writer.cpp#L2348
I wonder what is the GNU linkers behavior is, I would expect to see a warning too).

I guess this needs an addition of -z max-page-size=4096 (Hex for 0x1000) in LDFLAGS_realmode.elf line in arch/x86/realmode/rm/Makefile.

UPDATE: This did not work.

By the way, I can still reproduce this warning with -O2, linux-next-next-20190730, clang version 10.0.0 (366783) and lld.

For the config and buildlog see #623

Still occurs with kernel 5.3.1 and LLVM/clang-9.0.0 on x86_64

BUILDSTDERR: ld.lld: warning: -r and --gc-sections may not be used together, disabling --gc-sections
BUILDSTDERR: ld.lld: warning: -r and --icf may not be used together, disabling --icf
  LD      arch/x86/realmode/rm/realmode.elf
BUILDSTDERR: ld.lld: warning: cannot find entry symbol _start; defaulting to 0x1000
  RELOCS  arch/x86/realmode/rm/realmode.relocs

arch/x86/realmode/rm/Makefile:

 49 LDFLAGS_realmode.elf := -m elf_i386 --emit-relocs -T                
 50 CPPFLAGS_realmode.lds += -P -C -I$(objtree)/$(obj)                              

Sounds like maybe an ENTRY(<symbol>) in arch/x86/realmode/rm/realmode.lds.S would help?

$ make CC=clang -j71 defconfig
$ make CC=clang -j71
$ readelf -h arch/x86/realmode/rm/realmode.elf | grep Entry
  Entry point address:               0x1000

https://lkml.org/lkml/2019/9/23/913

I suspect this needs to be backported to 5.4, and 4.19 at least.

Was this page helpful?
0 / 5 - 0 ratings