rust-osdev / cargo-xbuild

Automatically cross-compiles the sysroot crates core, compiler_builtins, and alloc.
Apache License 2.0
260 stars 25 forks source link

".got" linker section emitted in debug mode despite disabling dynamic linking/PIE #80

Open Earlz opened 4 years ago

Earlz commented 4 years ago

I'm getting this error " = note: rust-lld: error: no memory region specified for section '.got'" which is unexpected because my target does not support the .got section at all. It is allowed in the linker script just to trigger a compiler error. This was working as of the .29 release, but is now broken with .33. With .29 I had the error with LTO code when using release mode, but with .33 that error went away. This .got error only occurs with debug builds.

The target file I'm using:

{
  "arch": "x86",
  "cpu": "i486",
  "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128",
  "dynamic-linking": false,
  "executables": true,
  "has-elf-tls": false,
  "has-rpath": false,
  "is-builtin": false,
  "linker": "rust-lld",
  "linker-flavor": "ld.lld",
  "linker-is-gnu": false,
  "llvm-target": "i486-unknown-none",
  "max-atomic-width": 64,
  "os": "neutron",
  "position-independent-executables": false,
  "target-c-int-width": "32",
  "target-endian": "little",
  "target-family": "unix",
  "target-pointer-width": "32",
  "vendor": "qtum",
  "features": "-mmx,-sse,+soft-float",
  "panic-strategy": "abort"
}

The linker script:

ENTRY(__start)

EXTERN(__sheap)
EXTERN(__start)

MEMORY
{
    CODEMEM : ORIGIN = 0x10000, LENGTH = 63K
    CODEMEMAUX1 : ORIGIN = 0x20000, LENGTH = 63K
    CODEMEMAUX2 : ORIGIN = 0x30000, LENGTH = 63K
    CODEMEMAUX3 : ORIGIN = 0x40000, LENGTH = 63K
    CODEMEMAUX4 : ORIGIN = 0x50000, LENGTH = 63K
    CODEMEMAUX5 : ORIGIN = 0x60000, LENGTH = 63K
    CODEMEMAUX6 : ORIGIN = 0x70000, LENGTH = 63K
    CODEMEMAUX7 : ORIGIN = 0x80000, LENGTH = 63K
    DATAMEM : ORIGIN = 0x80020000, LENGTH = 63K
}
/* # Sections */
SECTIONS
{
  /* ### .text */
  .text :
  {
    *(__start_text);
    *(.text .text.*);
    *(.rodata .rodata.*);
  } > CODEMEM
  /* # aux code sections */
  .textaux1 :
  {
    *(.textaux1 .textaux1.*);
  } > CODEMEMAUX1
  .textaux2 :
  {
    *(.textaux2 .textaux2.*);
  } > CODEMEMAUX2
  .textaux3 :
  {
    *(.textaux3 .textaux3.*);
  } > CODEMEMAUX3
  .textaux4 :
  {
    *(.textaux4 .textaux4.*);
  } > CODEMEMAUX4
  .textaux5 :
  {
    *(.textaux5 .textaux5.*);
  } > CODEMEMAUX5
  .textaux6 :
  {
    *(.textaux6 .textaux6.*);
  } > CODEMEMAUX6
  .textaux7 :
  {
    *(.textaux7 .textaux7.*);
  } > CODEMEMAUX7

  /* ## Sections in RAM */
  /* ### .data */
  .data : ALIGN(4)
  {
    . = ALIGN(4);
    __sdata = .;
    *(.data .data.*);
    . = ALIGN(4); /* 4-byte align the end (VMA) of this section */
    __edata = .;
  } > DATAMEM AT > CODEMEM

  /* LMA of .data */
  __sidata = LOADADDR(.data);

  /* ### .bss */
  .bss : ALIGN(4)
  {
    . = ALIGN(4);
    __sbss = .;
    *(.bss .bss.*);
    . = ALIGN(4); /* 4-byte align the end (VMA) of this section */
    __ebss = .;
  } > DATAMEM

  /* ### .uninit */
  .uninit (NOLOAD) : ALIGN(4)
  {
    . = ALIGN(4);
    *(.uninit .uninit.*);
    . = ALIGN(4);
  } > DATAMEM

  /* Place the heap right after `.uninit` */
  . = ALIGN(4);
  __sheap = .;

  /* ## .got */
  /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in
     the input files and raise an error if relocatable code is found */
  .got  :
  {
    KEEP(*(.got .got.*));
  }

  /* ## Discarded sections */
  /DISCARD/ :
  {
    /* Unused exception related info that only wastes space */
    *(.ARM.exidx);
    *(.ARM.exidx.*);
    *(.ARM.extab.*);
    *(.debug*);
    *(.comment*);
    *(.eh_frame*);

  }
}
/*
ASSERT(SIZEOF(.got) == 0, "
ERROR(cortex-m-rt): .got section detected in the input object files
Dynamic relocations are not supported. If you are linking to C code compiled using
the 'cc' crate then modify your build script to compile the C code _without_
the -fPIC flag. See the documentation of the `cc::Build.pic` method for details.");
*/

And the .cargo/config file:

[target.i686-neutron]
rustflags = [
  "-C", "link-arg=-Tlink.x",
  "-C", "relocation-model=static"
]
[target.i486-neutron]
rustflags = [
  "-C", "link-arg=-Tlink.x",
  "-C", "relocation-model=static"
]
runner = "neutron-testbench"

[build]
target = "i486-neutron"

I'm building it using cargo xbuild --target i486-neutron.json --verbose

I have a few other targeted crates that I'm using, as well as some common ones like serde, alloc, etc

phil-opp commented 4 years ago

I think this is a bug of rust itself. Have you tried building this with cargo's built-in -Zbuild-std=core,alloc flag instead of cargo-xbuild? You probably need to add a dependency on rlibc and an extern crate rlibc statement when trying this to resolve memset etc.

If the problem still occurs with -Zbuild-std, we know that it's not a problem in cargo-xbuild. In that case, we should report it in the rust-lang/rust repository directly.

Earlz commented 4 years ago

It seems to slightly be a bug in cargo-xbuild. Specifically, the .cargo/config Rust flags aren't used for building the core etc crate. The target file is however used, so the solution I found is to add "relocation-model": "static" to the target file

phil-opp commented 4 years ago

Ah yeah, we deliberately set a RUSTFLAGS environment variable to override any rustflags keys in .cargo/config files: https://github.com/rust-osdev/cargo-xbuild/blob/a779803ab1062ce3e3f864f242b6c45aa02a0332/src/sysroot.rs#L93

Apart from passing -Cembed-bitcode=yes, the reason for this is that most of the time you don't want to apply your rustflags to the sysroot build. For example, you probably don't want that the sysroot crates are built with "-C", "link-arg=-Tlink.x" in your case.

So setting it in the target file is currently the only option I think. I would also recommend trying the -Zbuild-std flag, which builds the sysroot crates as normal dependencies and thus shouldn't have this problem.