OUTPUT_ARCH(aarch64)
ENTRY(_start)

PHDRS
{
    main PT_LOAD;
}

SECTIONS
{
    PROVIDE(__start__ = ORIGIN(main));
    . = __start__;

    .text :
    {
        . = ALIGN(8);
        KEEP(*(.crt0*));
        *(.text.unlikely .text.*_unlikely .text.unlikely.*)
        *(.text.exit .text.exit.*)
        *(.text.startup .text.startup.*)
        *(.text.hot .text.hot.*)
        *(.text .stub .text.* .gnu.linkonce.t.*)
        . = ALIGN(0x800);
        __vectors_start__ = ABSOLUTE(.);
        KEEP(*(.vectors*));
        __vectors_end__   = ABSOLUTE(.);
        ASSERT(__vectors_end__ - __vectors_start__ <= 0x800, "Exception vectors section should be max 0x800 in size!");
        . = ALIGN(8);
    } >main :main

    .init :
    {
        KEEP( *(.init) )
        . = ALIGN(8);
    } >main :main

    .plt :
    {
        *(.plt)
        *(.iplt)
        . = ALIGN(8);
    } >main :main


    .fini :
    {
        KEEP( *(.fini) )
        . = ALIGN(8);
    } >main :main

    .rodata :
    {
        *(.rodata .rodata.* .gnu.linkonce.r.*)
        SORT(CONSTRUCTORS)
        . = ALIGN(8);
    } >main :main

    .got            : { __got_start__ = ABSOLUTE(.); *(.got) *(.igot) } >main :main
    .got.plt        : { *(.got.plt)  *(.igot.plt)  __got_end__ = ABSOLUTE(.);} >main :main

    .preinit_array :
    {
        . = ALIGN(8);
        PROVIDE (__preinit_array_start = ABSOLUTE(.));
        KEEP (*(.preinit_array))
        PROVIDE (__preinit_array_end = ABSOLUTE(.));
        . = ALIGN(8);
    } >main :main

    .init_array :
    {
        PROVIDE (__init_array_start = ABSOLUTE(.));
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        PROVIDE (__init_array_end = ABSOLUTE(.));
    } >main :main

    .fini_array :
    {
        . = ALIGN(8);
        PROVIDE (__fini_array_start = ABSOLUTE(.));
        KEEP (*(.fini_array))
        KEEP (*(SORT(.fini_array.*)))
        PROVIDE (__fini_array_end = ABSOLUTE(.));
        . = ALIGN(8);
    } >main :main

    .ctors :
    {
        . = ALIGN(8);
        KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
        KEEP (*(SORT(.ctors.*)))
        KEEP (*(.ctors))
        . = ALIGN(8);
    } >main :main

    .dtors ALIGN(8) :
    {
        . = ALIGN(8);
        KEEP (*crtbegin.o(.dtors))
        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
        KEEP (*(SORT(.dtors.*)))
        KEEP (*(.dtors))
        . = ALIGN(8);
    } >main :main

    .data ALIGN(8) :
    {
        *(.data .data.* .gnu.linkonce.d.*)
        CONSTRUCTORS
        . = ALIGN(8);
    } >main :main


    .eh_frame_hdr     : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } >main :main
    .eh_frame         : { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main :main
    .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } >main :main
    .gnu_extab        : { *(.gnu_extab*) } >main :main
    .exception_ranges : { *(.exception_ranges .exception_ranges*) } >main :main

    .dynamic           : { *(.dynamic) } >main :main
    .interp            : { *(.interp) } >main :main
    .note.gnu.build-id : { *(.note.gnu.build-id) } >main :main
    .hash              : { *(.hash) } >main :main
    .gnu.hash          : { *(.gnu.hash) } >main :main
    .gnu.version       : { *(.gnu.version) } >main :main
    .gnu.version_d     : { *(.gnu.version_d) } >main :main
    .gnu.version_r     : { *(.gnu.version_r) } >main :main
    .dynsym            : { *(.dynsym) } >main :main
    .dynstr            : { *(.dynstr) } >main :main
    .rela.dyn          : { *(.rela.*); __main_end__ = ABSOLUTE(.);} >main :main

    .bss (NOLOAD) :
    {
        . = ALIGN(8);
        __bss_start__  = ABSOLUTE(.);
        *(.dynbss)
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(COMMON)
        . = ALIGN(8);
        __end__ = ABSOLUTE(.);
    } >main :NONE

    .temp (NOLOAD) :
    {
        . = ALIGN(0x1000);
        __stacks_top__       = ABSOLUTE(. + 0x2000);
        __crash_stacks_top__ = ABSOLUTE(. + 0x3000);
        . += 0x3000;
        __temp_bss_start__ = ABSOLUTE(.);
        *(.tempbss .tempbss.*)
        __temp_bss_end__ = ABSOLUTE(.);
        . = ALIGN(0x1000);
    } >temp :NONE



    . = ALIGN(8);

    /* ==================
       ==== Metadata ====
       ================== */

    /* Discard sections that difficult post-processing */
    /DISCARD/ : { *(.group .comment .note) }

    /* Stabs debugging sections. */
    .stab          0 : { *(.stab) }
    .stabstr       0 : { *(.stabstr) }
    .stab.excl     0 : { *(.stab.excl) }
    .stab.exclstr  0 : { *(.stab.exclstr) }
    .stab.index    0 : { *(.stab.index) }
    .stab.indexstr 0 : { *(.stab.indexstr) }

    /* DWARF debug sections.
       Symbols in the DWARF debugging sections are relative to the beginning
       of the section so we begin them at 0. */

    /* DWARF 1 */
    .debug          0 : { *(.debug) }
    .line           0 : { *(.line) }

    /* GNU DWARF 1 extensions */
    .debug_srcinfo  0 : { *(.debug_srcinfo) }
    .debug_sfnames  0 : { *(.debug_sfnames) }

    /* DWARF 1.1 and DWARF 2 */
    .debug_aranges  0 : { *(.debug_aranges) }
    .debug_pubnames 0 : { *(.debug_pubnames) }

    /* DWARF 2 */
    .debug_info     0 : { *(.debug_info) }
    .debug_abbrev   0 : { *(.debug_abbrev) }
    .debug_line     0 : { *(.debug_line) }
    .debug_frame    0 : { *(.debug_frame) }
    .debug_str      0 : { *(.debug_str) }
    .debug_loc      0 : { *(.debug_loc) }
    .debug_macinfo  0 : { *(.debug_macinfo) }
}