diff --git a/apps/Makefile b/apps/Makefile index cdfb257..6ebd438 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -63,7 +63,8 @@ TARGET_APPS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi \ printenv.efi t7.efi t8.efi tcc.efi modelist.efi \ route80h.efi drv0_use.efi AllocPages.efi exit.efi \ FreePages.efi setjmp.efi debughook.efi debughook.efi.debug \ - bltgrid.efi lfbgrid.efi setdbg.efi unsetdbg.efi + bltgrid.efi lfbgrid.efi setdbg.efi unsetdbg.efi \ + ctors_test.efi TARGET_BSDRIVERS = drv0.efi TARGET_RTDRIVERS = @@ -88,6 +89,8 @@ TARGETS = $(TARGET_APPS) $(TARGET_BSDRIVERS) $(TARGET_RTDRIVERS) all: $(TARGETS) +ctors_test.so : ctors_fns.o ctors_test.o + clean: rm -f $(TARGETS) *~ *.o *.so diff --git a/apps/ctors_fns.c b/apps/ctors_fns.c new file mode 100644 index 0000000..6241904 --- /dev/null +++ b/apps/ctors_fns.c @@ -0,0 +1,26 @@ +/* + * ctors.c + * Copyright 2019 Peter Jones + * + */ + +#include +#include + +int constructed_value = 0; + +static void __attribute__((__constructor__)) ctor(void) +{ + Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value); + constructed_value = 1; + Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value); +} + +static void __attribute__((__destructor__)) dtor(void) +{ + Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value); + constructed_value = 0; + Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value); +} + +// vim:fenc=utf-8:tw=75:noet diff --git a/apps/ctors_test.c b/apps/ctors_test.c new file mode 100644 index 0000000..7e48da8 --- /dev/null +++ b/apps/ctors_test.c @@ -0,0 +1,20 @@ +/* + * ctors_test.c + * Copyright 2019 Peter Jones + * + */ + +#include +#include + +extern int constructed_value; + +EFI_STATUS +efi_main (EFI_HANDLE image EFI_UNUSED, EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value); + + return EFI_SUCCESS; +} + +// vim:fenc=utf-8:tw=75:noet diff --git a/gnuefi/crt0-efi-aarch64.S b/gnuefi/crt0-efi-aarch64.S index a9eda65..6016698 100644 --- a/gnuefi/crt0-efi-aarch64.S +++ b/gnuefi/crt0-efi-aarch64.S @@ -34,7 +34,7 @@ _start: cbnz x0, 0f ldp x0, x1, [sp, #16] - bl efi_main + bl _entry 0: ldp x29, x30, [sp], #32 ret diff --git a/gnuefi/crt0-efi-arm.S b/gnuefi/crt0-efi-arm.S index ea3bbc4..716699b 100644 --- a/gnuefi/crt0-efi-arm.S +++ b/gnuefi/crt0-efi-arm.S @@ -136,7 +136,7 @@ _start: bne 0f ldmfd sp, {r0-r1} - bl efi_main + bl _entry 0: add sp, sp, #12 ldr pc, [sp], #4 diff --git a/gnuefi/crt0-efi-ia32.S b/gnuefi/crt0-efi-ia32.S index 9e9c865..df3340a 100644 --- a/gnuefi/crt0-efi-ia32.S +++ b/gnuefi/crt0-efi-ia32.S @@ -56,13 +56,13 @@ _start: call _relocate popl %ebx popl %ebx - testl %eax,%eax - jne .exit + testl %eax,%eax + jne .exit - call efi_main # call app with "image" and "systab" argument + call _entry # call app with "image" and "systab" argument .exit: leave - ret + ret // hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: diff --git a/gnuefi/crt0-efi-ia64.S b/gnuefi/crt0-efi-ia64.S index 38af615..30714d3 100644 --- a/gnuefi/crt0-efi-ia64.S +++ b/gnuefi/crt0-efi-ia64.S @@ -56,7 +56,7 @@ _start: mov out0=in0 // image handle mov out1=in1 // systab - br.call.sptk.few rp=efi_main + br.call.sptk.few rp=_entry .Lret2: .exit: mov ar.pfs=loc0 diff --git a/gnuefi/crt0-efi-mips64el.S b/gnuefi/crt0-efi-mips64el.S index 4b2c1b2..cecabfb 100644 --- a/gnuefi/crt0-efi-mips64el.S +++ b/gnuefi/crt0-efi-mips64el.S @@ -172,8 +172,8 @@ _pc: // a0: ImageHandle ld $a0, 16($sp) - // call efi_main - dla $t9, efi_main + // call _start + dla $t9, _entry jalr $t9 // a1: SystemTable ld $a1, 24($sp) diff --git a/gnuefi/crt0-efi-x86_64.S b/gnuefi/crt0-efi-x86_64.S index 49f0a0d..5179439 100644 --- a/gnuefi/crt0-efi-x86_64.S +++ b/gnuefi/crt0-efi-x86_64.S @@ -56,7 +56,7 @@ _start: popq %rdi popq %rsi - call efi_main + call _entry addq $8, %rsp .exit: diff --git a/gnuefi/elf_aarch64_efi.lds b/gnuefi/elf_aarch64_efi.lds index 775133c..563e22d 100644 --- a/gnuefi/elf_aarch64_efi.lds +++ b/gnuefi/elf_aarch64_efi.lds @@ -41,6 +41,26 @@ SECTIONS *(.got.plt) *(.got) + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); @@ -52,6 +72,7 @@ SECTIONS *(COMMON) *(.rel.local) . = ALIGN(16); + _bss_end = .; } diff --git a/gnuefi/elf_arm_efi.lds b/gnuefi/elf_arm_efi.lds index 62ebb50..3023ebc 100644 --- a/gnuefi/elf_arm_efi.lds +++ b/gnuefi/elf_arm_efi.lds @@ -28,6 +28,26 @@ SECTIONS *(.got.plt) *(.got) + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); diff --git a/gnuefi/elf_ia32_efi.lds b/gnuefi/elf_ia32_efi.lds index 98fa6a5..23261c1 100644 --- a/gnuefi/elf_ia32_efi.lds +++ b/gnuefi/elf_ia32_efi.lds @@ -42,6 +42,27 @@ SECTIONS *(.sdata) *(.got.plt) *(.got) + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.sbss) diff --git a/gnuefi/elf_ia32_fbsd_efi.lds b/gnuefi/elf_ia32_fbsd_efi.lds index cd309e2..9e9baec 100644 --- a/gnuefi/elf_ia32_fbsd_efi.lds +++ b/gnuefi/elf_ia32_fbsd_efi.lds @@ -40,6 +40,27 @@ SECTIONS *(.sdata) *(.got.plt) *(.got) + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.sbss) diff --git a/gnuefi/elf_ia64_efi.lds b/gnuefi/elf_ia64_efi.lds index 0d6996b..e45799c 100644 --- a/gnuefi/elf_ia64_efi.lds +++ b/gnuefi/elf_ia64_efi.lds @@ -41,6 +41,27 @@ SECTIONS *(.data*) *(.gnu.linkonce.d*) *(.plabel) /* data whose relocs we want to ignore */ + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.dynbss) diff --git a/gnuefi/elf_mips64el_efi.lds b/gnuefi/elf_mips64el_efi.lds index 1b2943a..bf96841 100644 --- a/gnuefi/elf_mips64el_efi.lds +++ b/gnuefi/elf_mips64el_efi.lds @@ -29,6 +29,26 @@ SECTIONS HIDDEN (_gp = ALIGN (16) + 0x7ff0); *(.got) + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); diff --git a/gnuefi/elf_x86_64_efi.lds b/gnuefi/elf_x86_64_efi.lds index 9ec9cc1..2e0e0cb 100644 --- a/gnuefi/elf_x86_64_efi.lds +++ b/gnuefi/elf_x86_64_efi.lds @@ -28,6 +28,7 @@ SECTIONS { KEEP (*(.reloc)) } + . = ALIGN(4096); .data : { @@ -37,6 +38,27 @@ SECTIONS *(.got) *(.data*) *(.sdata) + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.sbss) diff --git a/gnuefi/elf_x86_64_fbsd_efi.lds b/gnuefi/elf_x86_64_fbsd_efi.lds index fe1f334..721ce9a 100644 --- a/gnuefi/elf_x86_64_fbsd_efi.lds +++ b/gnuefi/elf_x86_64_fbsd_efi.lds @@ -36,6 +36,27 @@ SECTIONS *(.got) *(.data*) *(.sdata) + + /* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + . = ALIGN(16); + _init_array = .; + *(SORT_BY_NAME(.init_array)) + _init_array_end = .; + __CTOR_LIST__ = .; + *(SORT_BY_NAME(.ctors)) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + *(SORT_BY_NAME(.dtors)) + __DTOR_END__ = .; + _fini_array = .; + *(SORT_BY_NAME(.fini_array)) + _fini_array_end = .; + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.sbss) diff --git a/lib/Makefile b/lib/Makefile index db0ab2e..3643b4d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -43,8 +43,8 @@ include $(SRCDIR)/../Make.defaults TOPDIR = $(SRCDIR)/.. CDIR = $(TOPDIR)/.. -FILES = boxdraw smbios console crc data debug dpath \ - error event exit guid hand hw init lock \ +FILES = boxdraw smbios console crc data debug dpath \ + entry error event exit guid hand hw init lock \ misc pause print sread str cmdline\ runtime/rtlock runtime/efirtlib runtime/rtstr runtime/vm runtime/rtdata \ $(ARCH)/initplat $(ARCH)/math $(ARCH)/setjmp @@ -62,7 +62,7 @@ FILES += $(ARCH)/uldiv $(ARCH)/ldivmod $(ARCH)/div $(ARCH)/llsl $(ARCH)/llsr \ $(ARCH)/mullu endif -OBJS = $(FILES:%=%.o) +OBJS = $(FILES:%=%.o) ctors.o SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 loongarch64 runtime diff --git a/lib/ctors.S b/lib/ctors.S new file mode 100644 index 0000000..4a0c6ab --- /dev/null +++ b/lib/ctors.S @@ -0,0 +1,47 @@ +/* + * Try to define the minimal empty init/ctor/dtor/fini_arrays so building with + * older or out-of-tree linker scripts will still work. + */ +/* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ + .section .init_array, "aM", @init_array + .p2align 3, 0 + .globl _init_array +_init_array: + .p2align 3, 0 + .globl _init_array_end +_init_array_end: + .long 0 + .section .ctors, "aM", @init_array + .p2align 3, 0 + .globl __CTOR_LIST__ +__CTOR_LIST__: + .p2align 3, 0 + .globl __CTOR_END__ +__CTOR_END__: + .long 0 + .section .dtors, "aM", @fini_array + .p2align 3, 0 + .globl __DTOR_LIST__ +__DTOR_LIST__: + .p2align 3, 0 + .globl __DTOR_END__ +__DTOR_END__: + .long 0 + .section .fini_array, "aM", @fini_array + .p2align 3, 0 + .globl _fini_array +_fini_array: + .p2align 3, 0 + .globl _fini_array_end +_fini_array_end: + .long 0 + +#if defined(__ELF__) && defined(__linux__) + .section .note.GNU-stack,"",%progbits +#endif + diff --git a/lib/entry.c b/lib/entry.c new file mode 100644 index 0000000..d852608 --- /dev/null +++ b/lib/entry.c @@ -0,0 +1,67 @@ +/* + * ctors.c + * Copyright 2019 Peter Jones + * + */ + +#include +#include + +/* + * Note that these aren't the using the GNU "CONSTRUCTOR" output section + * command, so they don't start with a size. Because of p2align and the + * end/END definitions, and the fact that they're mergeable, they can also + * have NULLs which aren't guaranteed to be at the end. + */ +extern UINTN _init_array, _init_array_end; +extern UINTN __CTOR_LIST__, __CTOR_END__; +extern UINTN _fini_array, _fini_array_end; +extern UINTN __DTOR_LIST__, __DTOR_END__; + +typedef void (*funcp)(void); + +static void ctors(void) +{ + for (funcp *location = (void *)&_init_array; location < (funcp *)&_init_array_end; location++) { + funcp func = *location; + if (location != NULL) + func(); + } + + for (funcp *location = (void *)&__CTOR_LIST__; location < (funcp *)&__CTOR_END__; location++) { + funcp func = *location; + if (location != NULL) + func(); + } +} + +static void dtors(void) +{ + for (funcp *location = (void *)&__DTOR_LIST__; location < (funcp *)&__DTOR_END__; location++) { + funcp func = *location; + if (location != NULL) + func(); + } + + for (funcp *location = (void *)&_fini_array; location < (funcp *)&_fini_array_end; location++) { + funcp func = *location; + if (location != NULL) + func(); + } +} + +extern EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab); + +EFI_STATUS _entry(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS status; + InitializeLib(image, systab); + + ctors(); + status = efi_main(image, systab); + dtors(); + + return status; +} + +// vim:fenc=utf-8:tw=75:noet diff --git a/lib/init.c b/lib/init.c index 4f238c0..726e493 100644 --- a/lib/init.c +++ b/lib/init.c @@ -46,57 +46,52 @@ Returns: EFI_STATUS Status; CHAR8 *LangCode; - if (!LibInitialized) { - LibInitialized = TRUE; - LibFwInstance = FALSE; - LibImageHandle = ImageHandle; + if (LibInitialized) + return; + LibInitialized = TRUE; + LibFwInstance = FALSE; + LibImageHandle = ImageHandle; - // - // Set up global pointer to the system table, boot services table, - // and runtime services table - // + // + // Set up global pointer to the system table, boot services table, + // and runtime services table + // - ST = SystemTable; - BS = SystemTable->BootServices; - RT = SystemTable->RuntimeServices; -// ASSERT (CheckCrc(0, &ST->Hdr)); -// ASSERT (CheckCrc(0, &BS->Hdr)); -// ASSERT (CheckCrc(0, &RT->Hdr)); + ST = SystemTable; + BS = SystemTable->BootServices; + RT = SystemTable->RuntimeServices; + // ASSERT (CheckCrc(0, &ST->Hdr)); + // ASSERT (CheckCrc(0, &BS->Hdr)); + // ASSERT (CheckCrc(0, &RT->Hdr)); + // + // Initialize pool allocation type + // - // - // Initialize pool allocation type - // + if (ImageHandle) { + Status = uefi_call_wrapper( + BS->HandleProtocol, + 3, + ImageHandle, + &LoadedImageProtocol, + (VOID*)&LoadedImage + ); - if (ImageHandle) { - Status = uefi_call_wrapper( - BS->HandleProtocol, - 3, - ImageHandle, - &LoadedImageProtocol, - (VOID*)&LoadedImage - ); - - if (!EFI_ERROR(Status)) { - PoolAllocationType = LoadedImage->ImageDataType; - } - EFIDebugVariable (); - } - - // - // Initialize Guid table - // - - InitializeGuid(); - - InitializeLibPlatform(ImageHandle,SystemTable); + if (!EFI_ERROR(Status)) { + PoolAllocationType = LoadedImage->ImageDataType; + } + EFIDebugVariable (); } // - // + // Initialize Guid table // + InitializeGuid(); + + InitializeLibPlatform(ImageHandle,SystemTable); + if (ImageHandle && UnicodeInterface == &LibStubUnicodeInterface) { LangCode = LibGetVariable (VarLanguage, &EfiGlobalVariable); InitializeUnicodeSupport (LangCode);