Compare commits
14 Commits
2ae2ede0b2
...
6affef76b1
Author | SHA1 | Date |
---|---|---|
Bananymous | 6affef76b1 | |
Bananymous | 32ba4d07e2 | |
Bananymous | ddaaf89c87 | |
Bananymous | 9aed8dbe6b | |
Bananymous | aa7e92b275 | |
Bananymous | f30947336a | |
Bananymous | 0bb44d7b75 | |
Bananymous | 1138ec77ca | |
Bananymous | c4dadd27ac | |
Bananymous | 04c715d314 | |
Bananymous | 35743cc8e6 | |
Bananymous | 5f92807fdd | |
Bananymous | 700c3444f5 | |
Bananymous | ddf1babfe1 |
|
@ -6,7 +6,10 @@ set(BAN_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(ban ${BAN_SOURCES})
|
add_library(ban ${BAN_SOURCES})
|
||||||
|
target_link_options(ban PRIVATE -nolibc)
|
||||||
banan_link_library(ban libc)
|
banan_link_library(ban libc)
|
||||||
|
|
||||||
|
set_target_properties(ban PROPERTIES OUTPUT_NAME libban)
|
||||||
|
|
||||||
banan_install_headers(ban)
|
banan_install_headers(ban)
|
||||||
install(TARGETS ban OPTIONAL)
|
install(TARGETS ban OPTIONAL)
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
namespace BAN
|
namespace BAN
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T> struct remove_refenrece { using type = T; };
|
template<typename T> struct remove_reference { using type = T; };
|
||||||
template<typename T> struct remove_refenrece<T&> { using type = T; };
|
template<typename T> struct remove_reference<T&> { using type = T; };
|
||||||
template<typename T> struct remove_refenrece<T&&> { using type = T; };
|
template<typename T> struct remove_reference<T&&> { using type = T; };
|
||||||
template<typename T> using remove_reference_t = typename remove_refenrece<T>::type;
|
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
|
||||||
|
|
||||||
template<typename T> struct remove_const { using type = T; };
|
template<typename T> struct remove_const { using type = T; };
|
||||||
template<typename T> struct remove_const<const T> { using type = T; };
|
template<typename T> struct remove_const<const T> { using type = T; };
|
||||||
|
|
|
@ -25,6 +25,13 @@ set(CMAKE_INSTALL_SYSCONF ${BANAN_ETC})
|
||||||
set(CMAKE_INSTALL_MESSAGE NEVER)
|
set(CMAKE_INSTALL_MESSAGE NEVER)
|
||||||
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY True)
|
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY True)
|
||||||
|
|
||||||
|
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||||
|
set(BUILD_SHARED_LIBS True)
|
||||||
|
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||||
|
|
||||||
# include headers of ${library} to ${target}
|
# include headers of ${library} to ${target}
|
||||||
function(banan_include_headers target library)
|
function(banan_include_headers target library)
|
||||||
target_include_directories(${target} PRIVATE $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
target_include_directories(${target} PRIVATE $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
||||||
|
|
|
@ -23,7 +23,7 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||||
- [ ] Task bar
|
- [ ] Task bar
|
||||||
- [ ] Program launcher
|
- [ ] Program launcher
|
||||||
- [ ] Some nice apps
|
- [ ] Some nice apps
|
||||||
- [ ] ELF dynamic linking
|
- [x] ELF dynamic linking
|
||||||
- [ ] copy-on-write memory
|
- [ ] copy-on-write memory
|
||||||
|
|
||||||
#### Drivers
|
#### Drivers
|
||||||
|
|
|
@ -191,12 +191,12 @@ target_compile_options(kernel PRIVATE
|
||||||
-Wall -Wextra -Werror -Wstack-usage=1024
|
-Wall -Wextra -Werror -Wstack-usage=1024
|
||||||
)
|
)
|
||||||
|
|
||||||
# This might not work with other toolchains
|
# C++ specific
|
||||||
target_compile_options(kernel PRIVATE $<$<COMPILE_LANGUAGE:CXX>:
|
target_compile_options(kernel PRIVATE
|
||||||
-Wno-literal-suffix
|
-Wno-literal-suffix
|
||||||
-Wno-invalid-offsetof
|
-Wno-invalid-offsetof
|
||||||
-fno-rtti
|
-fno-rtti
|
||||||
-fno-exceptions>
|
-fno-exceptions
|
||||||
)
|
)
|
||||||
|
|
||||||
if(ENABLE_KERNEL_UBSAN)
|
if(ENABLE_KERNEL_UBSAN)
|
||||||
|
@ -213,8 +213,9 @@ endif()
|
||||||
|
|
||||||
target_link_options(kernel PRIVATE -ffreestanding -nostdlib -orphan-handling=error)
|
target_link_options(kernel PRIVATE -ffreestanding -nostdlib -orphan-handling=error)
|
||||||
|
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN OUTPUT_STRIP_TRAILING_WHITESPACE)
|
get_target_property(KERNEL_COMPILE_OPTIONS kernel COMPILE_OPTIONS)
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND OUTPUT_STRIP_TRAILING_WHITESPACE)
|
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${KERNEL_COMPILE_OPTIONS} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${KERNEL_COMPILE_OPTIONS} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET kernel PRE_LINK
|
TARGET kernel PRE_LINK
|
||||||
|
|
|
@ -216,12 +216,11 @@ higher_half:
|
||||||
# call global constuctors
|
# call global constuctors
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
movl $__init_array_start, %ebx
|
movl $g_init_array_start, %ebx
|
||||||
jmp 2f
|
jmp 2f
|
||||||
1: movl (%ebx), %eax
|
1: call *(%ebx)
|
||||||
call *%eax
|
|
||||||
addl $4, %ebx
|
addl $4, %ebx
|
||||||
2: cmpl $__init_array_end, %ebx
|
2: cmpl $g_init_array_end, %ebx
|
||||||
jne 1b
|
jne 1b
|
||||||
|
|
||||||
# call to the kernel itself (clear ebp for stacktrace)
|
# call to the kernel itself (clear ebp for stacktrace)
|
||||||
|
|
|
@ -14,11 +14,3 @@ _fini:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||||
|
|
||||||
.section .init_array
|
|
||||||
.global __init_array_start
|
|
||||||
__init_array_start:
|
|
||||||
|
|
||||||
.section .fini_array
|
|
||||||
.global __fini_array_start
|
|
||||||
__fini_array_start:
|
|
||||||
|
|
|
@ -8,11 +8,3 @@
|
||||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.section .init_array
|
|
||||||
.global __init_array_end
|
|
||||||
__init_array_end:
|
|
||||||
|
|
||||||
.section .fini_array
|
|
||||||
.global __fini_array_end
|
|
||||||
__fini_array_end:
|
|
||||||
|
|
|
@ -30,6 +30,12 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.rodata.*)
|
*(.rodata.*)
|
||||||
}
|
}
|
||||||
|
.init_array ALIGN(4K) : AT(ADDR(.init_array) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
g_init_array_start = .;
|
||||||
|
*(.init_array)
|
||||||
|
g_init_array_end = .;
|
||||||
|
}
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
g_kernel_writable_start = .;
|
g_kernel_writable_start = .;
|
||||||
|
|
|
@ -216,12 +216,11 @@ higher_half:
|
||||||
# call global constuctors
|
# call global constuctors
|
||||||
call _init
|
call _init
|
||||||
|
|
||||||
movq $__init_array_start, %rbx
|
movq $g_init_array_start, %rbx
|
||||||
jmp 2f
|
jmp 2f
|
||||||
1: movq (%rbx), %rax
|
1: call *(%rbx)
|
||||||
call *%rax
|
|
||||||
addq $8, %rbx
|
addq $8, %rbx
|
||||||
2: cmpq $__init_array_end, %rbx
|
2: cmpq $g_init_array_end, %rbx
|
||||||
jne 1b
|
jne 1b
|
||||||
|
|
||||||
# call to the kernel itself (clear rbp for stacktrace)
|
# call to the kernel itself (clear rbp for stacktrace)
|
||||||
|
|
|
@ -14,11 +14,3 @@ _fini:
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||||
|
|
||||||
.section .init_array
|
|
||||||
.global __init_array_start
|
|
||||||
__init_array_start:
|
|
||||||
|
|
||||||
.section .fini_array
|
|
||||||
.global __fini_array_start
|
|
||||||
__fini_array_start:
|
|
||||||
|
|
|
@ -8,11 +8,3 @@
|
||||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||||
popq %rbp
|
popq %rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.section .init_array
|
|
||||||
.global __init_array_end
|
|
||||||
__init_array_end:
|
|
||||||
|
|
||||||
.section .fini_array
|
|
||||||
.global __fini_array_end
|
|
||||||
__fini_array_end:
|
|
||||||
|
|
|
@ -30,6 +30,12 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.rodata.*)
|
*(.rodata.*)
|
||||||
}
|
}
|
||||||
|
.init_array ALIGN(4K) : AT(ADDR(.init_array) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
g_init_array_start = .;
|
||||||
|
*(.init_array)
|
||||||
|
g_init_array_end = .;
|
||||||
|
}
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
g_kernel_writable_start = .;
|
g_kernel_writable_start = .;
|
||||||
|
|
|
@ -67,14 +67,16 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
ASSERT(&PageTable::current() == &m_page_table);
|
ASSERT(&PageTable::current() == &m_page_table);
|
||||||
|
|
||||||
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + m_size }, m_type, m_flags));
|
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
|
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
|
||||||
|
|
||||||
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
|
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
|
||||||
{
|
{
|
||||||
paddr_t paddr = m_page_table.physical_address_of(m_vaddr + offset);
|
paddr_t paddr = m_page_table.physical_address_of(m_vaddr + offset);
|
||||||
if (paddr == 0)
|
if (paddr == 0)
|
||||||
continue;
|
continue;
|
||||||
TRY(result->copy_data_to_region(offset, (const uint8_t*)(m_vaddr + offset), PAGE_SIZE));
|
const size_t to_copy = BAN::Math::min<size_t>(PAGE_SIZE, m_size - offset);
|
||||||
|
TRY(result->copy_data_to_region(offset, (const uint8_t*)(m_vaddr + offset), to_copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
|
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
|
||||||
|
|
|
@ -61,12 +61,6 @@ if [[ -z ${MAKE_JOBS:x} ]]; then
|
||||||
MAKE_JOBS="-j$(nproc)"
|
MAKE_JOBS="-j$(nproc)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $BANAN_ARCH = "x86_64" ]; then
|
|
||||||
XCFLAGS="-g -O2 -mcmodel=large -mno-red-zone"
|
|
||||||
else
|
|
||||||
XCFLAGS="-g -O2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
enter_clean_build () {
|
enter_clean_build () {
|
||||||
rm -rf build-$BANAN_ARCH
|
rm -rf build-$BANAN_ARCH
|
||||||
mkdir build-$BANAN_ARCH
|
mkdir build-$BANAN_ARCH
|
||||||
|
@ -129,6 +123,11 @@ build_gcc () {
|
||||||
--disable-nls \
|
--disable-nls \
|
||||||
--enable-languages=c,c++
|
--enable-languages=c,c++
|
||||||
|
|
||||||
|
XCFLAGS=""
|
||||||
|
if [ $BANAN_ARCH = "x86_64" ]; then
|
||||||
|
XCFLAGS="-mcmodel=large -mno-red-zone"
|
||||||
|
fi
|
||||||
|
|
||||||
make $MAKE_JOBS all-gcc
|
make $MAKE_JOBS all-gcc
|
||||||
make $MAKE_JOBS all-target-libgcc CFLAGS_FOR_TARGET="$XCFLAGS"
|
make $MAKE_JOBS all-target-libgcc CFLAGS_FOR_TARGET="$XCFLAGS"
|
||||||
make install-gcc
|
make install-gcc
|
||||||
|
@ -142,7 +141,7 @@ build_libstdcpp () {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd $BANAN_BUILD_DIR/toolchain/$GCC_VERSION/build-$BANAN_ARCH
|
cd $BANAN_BUILD_DIR/toolchain/$GCC_VERSION/build-$BANAN_ARCH
|
||||||
make $MAKE_JOBS all-target-libstdc++-v3 CFLAGS_FOR_TARGET="$XCFLAGS"
|
make $MAKE_JOBS all-target-libstdc++-v3
|
||||||
make install-target-libstdc++-v3
|
make install-target-libstdc++-v3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +267,8 @@ fi
|
||||||
if (($BUILD_LIBSTDCPP)); then
|
if (($BUILD_LIBSTDCPP)); then
|
||||||
# delete sysroot and install libc
|
# delete sysroot and install libc
|
||||||
rm -r $BANAN_SYSROOT
|
rm -r $BANAN_SYSROOT
|
||||||
$BANAN_SCRIPT_DIR/build.sh libc
|
$BANAN_SCRIPT_DIR/build.sh libc-static
|
||||||
|
$BANAN_SCRIPT_DIR/build.sh libc-shared
|
||||||
$BANAN_SCRIPT_DIR/build.sh install
|
$BANAN_SCRIPT_DIR/build.sh install
|
||||||
|
|
||||||
build_libstdcpp
|
build_libstdcpp
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
diff -ruN gcc-12.2.0/config.sub gcc-12.2.0-banan_os/config.sub
|
diff -ruN gcc-12.2.0/config.sub gcc-12.2.0-banan_os/config.sub
|
||||||
--- gcc-12.2.0/config.sub 2022-08-19 11:09:52.128656687 +0300
|
--- gcc-12.2.0/config.sub 2022-08-19 11:09:52.128656687 +0300
|
||||||
+++ gcc-12.2.0-banan_os/config.sub 2024-08-26 16:10:21.057075425 +0300
|
+++ gcc-12.2.0-banan_os/config.sub 2024-09-03 23:09:34.347772496 +0300
|
||||||
@@ -1749,7 +1749,7 @@
|
@@ -1749,7 +1749,7 @@
|
||||||
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
|
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
|
||||||
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
|
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
|
||||||
|
@ -12,7 +12,7 @@ diff -ruN gcc-12.2.0/config.sub gcc-12.2.0-banan_os/config.sub
|
||||||
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
|
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
|
||||||
diff -ruN gcc-12.2.0/fixincludes/mkfixinc.sh gcc-12.2.0-banan_os/fixincludes/mkfixinc.sh
|
diff -ruN gcc-12.2.0/fixincludes/mkfixinc.sh gcc-12.2.0-banan_os/fixincludes/mkfixinc.sh
|
||||||
--- gcc-12.2.0/fixincludes/mkfixinc.sh 2022-08-19 11:09:52.160657095 +0300
|
--- gcc-12.2.0/fixincludes/mkfixinc.sh 2022-08-19 11:09:52.160657095 +0300
|
||||||
+++ gcc-12.2.0-banan_os/fixincludes/mkfixinc.sh 2024-08-26 16:26:29.728558199 +0300
|
+++ gcc-12.2.0-banan_os/fixincludes/mkfixinc.sh 2024-09-03 23:09:34.461106020 +0300
|
||||||
@@ -11,6 +11,7 @@
|
@@ -11,6 +11,7 @@
|
||||||
|
|
||||||
# Check for special fix rules for particular targets
|
# Check for special fix rules for particular targets
|
||||||
|
@ -23,7 +23,7 @@ diff -ruN gcc-12.2.0/fixincludes/mkfixinc.sh gcc-12.2.0-banan_os/fixincludes/mkf
|
||||||
x86_64-*-mingw32* | \
|
x86_64-*-mingw32* | \
|
||||||
diff -ruN gcc-12.2.0/gcc/config/banan_os.h gcc-12.2.0-banan_os/gcc/config/banan_os.h
|
diff -ruN gcc-12.2.0/gcc/config/banan_os.h gcc-12.2.0-banan_os/gcc/config/banan_os.h
|
||||||
--- gcc-12.2.0/gcc/config/banan_os.h 1970-01-01 02:00:00.000000000 +0200
|
--- gcc-12.2.0/gcc/config/banan_os.h 1970-01-01 02:00:00.000000000 +0200
|
||||||
+++ gcc-12.2.0-banan_os/gcc/config/banan_os.h 2024-08-26 16:20:51.429017406 +0300
|
+++ gcc-12.2.0-banan_os/gcc/config/banan_os.h 2024-09-03 23:09:34.461106020 +0300
|
||||||
@@ -0,0 +1,35 @@
|
@@ -0,0 +1,35 @@
|
||||||
+/* Useful if you wish to make target-specific GCC changes. */
|
+/* Useful if you wish to make target-specific GCC changes. */
|
||||||
+#undef TARGET_BANAN_OS
|
+#undef TARGET_BANAN_OS
|
||||||
|
@ -37,11 +37,11 @@ diff -ruN gcc-12.2.0/gcc/config/banan_os.h gcc-12.2.0-banan_os/gcc/config/banan_
|
||||||
+/* Files that are linked before user code.
|
+/* Files that are linked before user code.
|
||||||
+ The %s tells GCC to look for these files in the library directory. */
|
+ The %s tells GCC to look for these files in the library directory. */
|
||||||
+#undef STARTFILE_SPEC
|
+#undef STARTFILE_SPEC
|
||||||
+#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti.o%s crtbegin.o%s"
|
+#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti.o%s %{shared|static-pie|!no-pie:crtbeginS.o%s; :crtbegin.o%s}"
|
||||||
+
|
+
|
||||||
+/* Files that are linked after user code. */
|
+/* Files that are linked after user code. */
|
||||||
+#undef ENDFILE_SPEC
|
+#undef ENDFILE_SPEC
|
||||||
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
|
+#define ENDFILE_SPEC "%{shared|static-pie|!no-pie:crtendS.o%s; :crtend.o%s} crtn.o%s"
|
||||||
+
|
+
|
||||||
+#undef LINK_SPEC
|
+#undef LINK_SPEC
|
||||||
+#define LINK_SPEC "%{shared:-shared} %{static:-static} %{!shared: %{!static: %{rdynamic:-export-dynamic}}}"
|
+#define LINK_SPEC "%{shared:-shared} %{static:-static} %{!shared: %{!static: %{rdynamic:-export-dynamic}}}"
|
||||||
|
@ -62,8 +62,8 @@ diff -ruN gcc-12.2.0/gcc/config/banan_os.h gcc-12.2.0-banan_os/gcc/config/banan_
|
||||||
+ } while(0);
|
+ } while(0);
|
||||||
diff -ruN gcc-12.2.0/gcc/config.gcc gcc-12.2.0-banan_os/gcc/config.gcc
|
diff -ruN gcc-12.2.0/gcc/config.gcc gcc-12.2.0-banan_os/gcc/config.gcc
|
||||||
--- gcc-12.2.0/gcc/config.gcc 2022-08-19 11:09:52.552662114 +0300
|
--- gcc-12.2.0/gcc/config.gcc 2022-08-19 11:09:52.552662114 +0300
|
||||||
+++ gcc-12.2.0-banan_os/gcc/config.gcc 2024-08-26 16:12:58.904718171 +0300
|
+++ gcc-12.2.0-banan_os/gcc/config.gcc 2024-09-03 23:09:34.461106020 +0300
|
||||||
@@ -673,6 +673,12 @@
|
@@ -673,6 +673,13 @@
|
||||||
|
|
||||||
# Common parts for widely ported systems.
|
# Common parts for widely ported systems.
|
||||||
case ${target} in
|
case ${target} in
|
||||||
|
@ -72,6 +72,7 @@ diff -ruN gcc-12.2.0/gcc/config.gcc gcc-12.2.0-banan_os/gcc/config.gcc
|
||||||
+ gnu_ld=yes
|
+ gnu_ld=yes
|
||||||
+ default_use_cxa_atexit=yes
|
+ default_use_cxa_atexit=yes
|
||||||
+ use_gcc_stdint=provide
|
+ use_gcc_stdint=provide
|
||||||
|
+ tmake_file="t-slibgcc"
|
||||||
+ ;;
|
+ ;;
|
||||||
*-*-darwin*)
|
*-*-darwin*)
|
||||||
tmake_file="t-darwin "
|
tmake_file="t-darwin "
|
||||||
|
@ -91,25 +92,36 @@ diff -ruN gcc-12.2.0/gcc/config.gcc gcc-12.2.0-banan_os/gcc/config.gcc
|
||||||
;;
|
;;
|
||||||
diff -ruN gcc-12.2.0/libgcc/config.host gcc-12.2.0-banan_os/libgcc/config.host
|
diff -ruN gcc-12.2.0/libgcc/config.host gcc-12.2.0-banan_os/libgcc/config.host
|
||||||
--- gcc-12.2.0/libgcc/config.host 2022-08-19 11:09:54.664689148 +0300
|
--- gcc-12.2.0/libgcc/config.host 2022-08-19 11:09:54.664689148 +0300
|
||||||
+++ gcc-12.2.0-banan_os/libgcc/config.host 2024-08-26 16:25:09.397768608 +0300
|
+++ gcc-12.2.0-banan_os/libgcc/config.host 2024-09-03 23:09:34.474439376 +0300
|
||||||
@@ -698,6 +698,14 @@
|
@@ -698,6 +698,14 @@
|
||||||
hppa*-*-netbsd*)
|
hppa*-*-netbsd*)
|
||||||
tmake_file="$tmake_file pa/t-netbsd"
|
tmake_file="$tmake_file pa/t-netbsd"
|
||||||
;;
|
;;
|
||||||
+i[34567]86-*-banan_os*)
|
+i[34567]86-*-banan_os*)
|
||||||
+ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
|
+ extra_parts="$extra_parts crti.o crtbegin.o crtbeginS.o crtend.o crtendS.o crtn.o"
|
||||||
+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
|
+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic t-slibgcc"
|
||||||
+ ;;
|
+ ;;
|
||||||
+x86_64-*-banan_os*)
|
+x86_64-*-banan_os*)
|
||||||
+ extra_parts="$extra_parts crti.o crtbegin.o crtend.o crtn.o"
|
+ extra_parts="$extra_parts crti.o crtbegin.o crtbeginS.o crtend.o crtendS.o crtn.o"
|
||||||
+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
|
+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic t-slibgcc"
|
||||||
+ ;;
|
+ ;;
|
||||||
i[34567]86-*-darwin*)
|
i[34567]86-*-darwin*)
|
||||||
tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
|
tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
|
||||||
tm_file="$tm_file i386/darwin-lib.h"
|
tm_file="$tm_file i386/darwin-lib.h"
|
||||||
|
diff -ruN gcc-12.2.0/libgcc/config/t-slibgcc gcc-12.2.0-banan_os/libgcc/config/t-slibgcc
|
||||||
|
--- gcc-12.2.0/libgcc/config/t-slibgcc 2022-08-19 11:09:54.724689916 +0300
|
||||||
|
+++ gcc-12.2.0-banan_os/libgcc/config/t-slibgcc 2024-09-04 23:06:14.275389818 +0300
|
||||||
|
@@ -26,7 +26,6 @@
|
||||||
|
SHLIB_OBJS = @shlib_objs@
|
||||||
|
SHLIB_DIR = @multilib_dir@
|
||||||
|
SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
|
||||||
|
-SHLIB_LC = -lc
|
||||||
|
SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
|
||||||
|
SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \
|
||||||
|
$(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
|
||||||
diff -ruN gcc-12.2.0/libstdc++-v3/acinclude.m4 gcc-12.2.0-banan_os/libstdc++-v3/acinclude.m4
|
diff -ruN gcc-12.2.0/libstdc++-v3/acinclude.m4 gcc-12.2.0-banan_os/libstdc++-v3/acinclude.m4
|
||||||
--- gcc-12.2.0/libstdc++-v3/acinclude.m4 2022-08-19 11:09:55.380698313 +0300
|
--- gcc-12.2.0/libstdc++-v3/acinclude.m4 2022-08-19 11:09:55.380698313 +0300
|
||||||
+++ gcc-12.2.0-banan_os/libstdc++-v3/acinclude.m4 2024-08-26 19:03:18.261183636 +0300
|
+++ gcc-12.2.0-banan_os/libstdc++-v3/acinclude.m4 2024-09-03 23:09:34.477772715 +0300
|
||||||
@@ -1380,7 +1380,7 @@
|
@@ -1380,7 +1380,7 @@
|
||||||
ac_has_nanosleep=yes
|
ac_has_nanosleep=yes
|
||||||
ac_has_sched_yield=yes
|
ac_has_sched_yield=yes
|
||||||
|
@ -121,7 +133,7 @@ diff -ruN gcc-12.2.0/libstdc++-v3/acinclude.m4 gcc-12.2.0-banan_os/libstdc++-v3/
|
||||||
ac_has_nanosleep=yes
|
ac_has_nanosleep=yes
|
||||||
diff -ruN gcc-12.2.0/libstdc++-v3/configure gcc-12.2.0-banan_os/libstdc++-v3/configure
|
diff -ruN gcc-12.2.0/libstdc++-v3/configure gcc-12.2.0-banan_os/libstdc++-v3/configure
|
||||||
--- gcc-12.2.0/libstdc++-v3/configure 2022-08-19 11:09:55.416698774 +0300
|
--- gcc-12.2.0/libstdc++-v3/configure 2022-08-19 11:09:55.416698774 +0300
|
||||||
+++ gcc-12.2.0-banan_os/libstdc++-v3/configure 2024-08-26 19:09:19.671026813 +0300
|
+++ gcc-12.2.0-banan_os/libstdc++-v3/configure 2024-09-03 23:09:34.487772732 +0300
|
||||||
@@ -11904,6 +11904,11 @@
|
@@ -11904,6 +11904,11 @@
|
||||||
lt_cv_dlopen_self=yes
|
lt_cv_dlopen_self=yes
|
||||||
;;
|
;;
|
||||||
|
@ -134,6 +146,17 @@ diff -ruN gcc-12.2.0/libstdc++-v3/configure gcc-12.2.0-banan_os/libstdc++-v3/con
|
||||||
mingw* | pw32* | cegcc*)
|
mingw* | pw32* | cegcc*)
|
||||||
lt_cv_dlopen="LoadLibrary"
|
lt_cv_dlopen="LoadLibrary"
|
||||||
lt_cv_dlopen_libs=
|
lt_cv_dlopen_libs=
|
||||||
|
@@ -15603,8 +15608,8 @@
|
||||||
|
glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
|
||||||
|
|
||||||
|
else
|
||||||
|
- glibcxx_lt_pic_flag=
|
||||||
|
- glibcxx_compiler_pic_flag=
|
||||||
|
+ glibcxx_lt_pic_flag="-prefer-pic"
|
||||||
|
+ glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
|
||||||
|
glibcxx_compiler_shared_flag=
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -20575,7 +20580,7 @@
|
@@ -20575,7 +20580,7 @@
|
||||||
ac_has_nanosleep=yes
|
ac_has_nanosleep=yes
|
||||||
ac_has_sched_yield=yes
|
ac_has_sched_yield=yes
|
||||||
|
@ -154,7 +177,7 @@ diff -ruN gcc-12.2.0/libstdc++-v3/configure gcc-12.2.0-banan_os/libstdc++-v3/con
|
||||||
$as_echo "#define HAVE_ASINF 1" >>confdefs.h
|
$as_echo "#define HAVE_ASINF 1" >>confdefs.h
|
||||||
diff -ruN gcc-12.2.0/libstdc++-v3/crossconfig.m4 gcc-12.2.0-banan_os/libstdc++-v3/crossconfig.m4
|
diff -ruN gcc-12.2.0/libstdc++-v3/crossconfig.m4 gcc-12.2.0-banan_os/libstdc++-v3/crossconfig.m4
|
||||||
--- gcc-12.2.0/libstdc++-v3/crossconfig.m4 2022-08-19 11:09:55.420698825 +0300
|
--- gcc-12.2.0/libstdc++-v3/crossconfig.m4 2022-08-19 11:09:55.420698825 +0300
|
||||||
+++ gcc-12.2.0-banan_os/libstdc++-v3/crossconfig.m4 2024-08-26 18:53:31.865865576 +0300
|
+++ gcc-12.2.0-banan_os/libstdc++-v3/crossconfig.m4 2024-09-03 23:09:34.531106138 +0300
|
||||||
@@ -9,7 +9,7 @@
|
@@ -9,7 +9,7 @@
|
||||||
# This is a freestanding configuration; there is nothing to do here.
|
# This is a freestanding configuration; there is nothing to do here.
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -15,9 +15,14 @@ add_custom_target(libraries)
|
||||||
|
|
||||||
foreach(library ${USERSPACE_LIBRARIES})
|
foreach(library ${USERSPACE_LIBRARIES})
|
||||||
string(TOLOWER ${library} library_lower)
|
string(TOLOWER ${library} library_lower)
|
||||||
if (TARGET ${library_lower})
|
if (TARGET ${library_lower} AND NOT ${library_lower} STREQUAL "libc")
|
||||||
add_dependencies(libraries ${library_lower})
|
add_dependencies(libraries ${library_lower})
|
||||||
# This is to allow cmake to link when libc updates
|
# This is to allow cmake to link when libc updates
|
||||||
target_link_options(${library_lower} PRIVATE -nolibc)
|
target_link_options(${library_lower} PRIVATE -nolibc)
|
||||||
|
|
||||||
|
target_compile_definitions(${library_lower} PRIVATE __enable_sse=${BANAN_ENABLE_SSE})
|
||||||
|
if (NOT BANAN_ENABLE_SSE)
|
||||||
|
target_compile_options(${library_lower} PRIVATE -mno-sse -mno-sse2)
|
||||||
|
endif ()
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
@ -4,6 +4,7 @@ set(LIBC_SOURCES
|
||||||
ctype.cpp
|
ctype.cpp
|
||||||
dirent.cpp
|
dirent.cpp
|
||||||
dlfcn.cpp
|
dlfcn.cpp
|
||||||
|
errno.cpp
|
||||||
fcntl.cpp
|
fcntl.cpp
|
||||||
ftw.cpp
|
ftw.cpp
|
||||||
grp.cpp
|
grp.cpp
|
||||||
|
@ -72,16 +73,25 @@ banan_include_headers(objlibc kernel)
|
||||||
|
|
||||||
banan_install_headers(objlibc)
|
banan_install_headers(objlibc)
|
||||||
|
|
||||||
add_library(libc STATIC $<TARGET_OBJECTS:objlibc>)
|
add_library(libc-static STATIC $<TARGET_OBJECTS:objlibc>)
|
||||||
add_library(libc-shared SHARED $<TARGET_OBJECTS:objlibc>)
|
add_library(libc-shared SHARED $<TARGET_OBJECTS:objlibc>)
|
||||||
|
|
||||||
target_link_options(libc PRIVATE -nolibc)
|
target_link_options(libc-static PRIVATE -nostdlib)
|
||||||
target_link_options(libc-shared PRIVATE -nolibc)
|
target_link_options(libc-shared PRIVATE -nostdlib)
|
||||||
|
|
||||||
install(TARGETS libc OPTIONAL)
|
install(TARGETS libc-static OPTIONAL)
|
||||||
install(TARGETS libc-shared OPTIONAL)
|
install(TARGETS libc-shared OPTIONAL)
|
||||||
|
|
||||||
|
set_target_properties(libc-static PROPERTIES OUTPUT_NAME libc)
|
||||||
set_target_properties(libc-shared PROPERTIES OUTPUT_NAME libc)
|
set_target_properties(libc-shared PROPERTIES OUTPUT_NAME libc)
|
||||||
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
add_library(libc ALIAS libc-shared)
|
||||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
|
||||||
|
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libgcc_s.so OUTPUT_VARIABLE LIBGCC_S_LINK OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
file(REAL_PATH ${LIBGCC_S_LINK} LIBGCC_S)
|
||||||
|
install(FILES ${LIBGCC_S} DESTINATION ${CMAKE_INSTALL_LIBDIR} RENAME libgcc_s.so
|
||||||
|
PERMISSIONS
|
||||||
|
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||||
|
GROUP_READ GROUP_EXECUTE
|
||||||
|
WORLD_READ WORLD_EXECUTE
|
||||||
|
)
|
||||||
|
|
|
@ -23,8 +23,7 @@ _start:
|
||||||
|
|
||||||
movl $__init_array_start, %ebx
|
movl $__init_array_start, %ebx
|
||||||
jmp 2f
|
jmp 2f
|
||||||
1: movl (%ebx), %eax
|
1: call *(%ebx)
|
||||||
call *%eax
|
|
||||||
addl $4, %ebx
|
addl $4, %ebx
|
||||||
2: cmpl $__init_array_end, %ebx
|
2: cmpl $__init_array_end, %ebx
|
||||||
jne 1b
|
jne 1b
|
||||||
|
|
|
@ -24,8 +24,7 @@ _start:
|
||||||
|
|
||||||
movq $__init_array_start, %rbx
|
movq $__init_array_start, %rbx
|
||||||
jmp 2f
|
jmp 2f
|
||||||
1: movq (%rbx), %rax
|
1: call *(%rbx)
|
||||||
call *%rax
|
|
||||||
addq $8, %rbx
|
addq $8, %rbx
|
||||||
2: cmpq $__init_array_end, %rbx
|
2: cmpq $__init_array_end, %rbx
|
||||||
jne 1b
|
jne 1b
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static int s_errno = 0;
|
||||||
|
|
||||||
|
int* __errno_location()
|
||||||
|
{
|
||||||
|
return &s_errno;
|
||||||
|
}
|
|
@ -93,9 +93,9 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
#define EUNKNOWN 0xFF
|
#define EUNKNOWN 0xFF
|
||||||
|
|
||||||
#define errno __errno
|
#define errno (*__errno_location())
|
||||||
|
|
||||||
extern int __errno;
|
int* __errno_location(void);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#if __enable_sse
|
||||||
BUILTINS1(acos)
|
BUILTINS1(acos)
|
||||||
BUILTINS1(acosh)
|
BUILTINS1(acosh)
|
||||||
BUILTINS1(asin)
|
BUILTINS1(asin)
|
||||||
|
@ -65,5 +66,6 @@ BUILTINS1(tgamma)
|
||||||
BUILTINS1(trunc)
|
BUILTINS1(trunc)
|
||||||
BUILTINS1(y0)
|
BUILTINS1(y0)
|
||||||
BUILTINS1(y1)
|
BUILTINS1(y1)
|
||||||
|
#endif
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
|
@ -262,6 +262,7 @@ int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(void*),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if __enable_sse
|
||||||
auto parse_floating_point_internal =
|
auto parse_floating_point_internal =
|
||||||
[&parse_integer_internal, &get_input, &in]<int BASE, typename T>(BASE_TYPE<BASE>, bool negative, int width, T* out, bool require_start = true) -> ConversionResult
|
[&parse_integer_internal, &get_input, &in]<int BASE, typename T>(BASE_TYPE<BASE>, bool negative, int width, T* out, bool require_start = true) -> ConversionResult
|
||||||
{
|
{
|
||||||
|
@ -436,6 +437,7 @@ int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(void*),
|
||||||
return ConversionResult::MATCH_FAILURE;
|
return ConversionResult::MATCH_FAILURE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
auto parse_string =
|
auto parse_string =
|
||||||
[&arguments, &get_input, &in](uint8_t* mask, bool exclude, bool suppress, bool allocate, int min_len, int max_len, bool terminate) -> ConversionResult
|
[&arguments, &get_input, &in](uint8_t* mask, bool exclude, bool suppress, bool allocate, int min_len, int max_len, bool terminate) -> ConversionResult
|
||||||
|
@ -520,9 +522,11 @@ int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(void*),
|
||||||
case 'x': result = parse_integer(BASE_TYPE<16>{}, IS_UNSIGNED<true> {}, conversion.suppress, conversion.field_width, conversion.length); break;
|
case 'x': result = parse_integer(BASE_TYPE<16>{}, IS_UNSIGNED<true> {}, conversion.suppress, conversion.field_width, conversion.length); break;
|
||||||
case 'X': result = parse_integer(BASE_TYPE<16>{}, IS_UNSIGNED<true> {}, conversion.suppress, conversion.field_width, conversion.length); break;
|
case 'X': result = parse_integer(BASE_TYPE<16>{}, IS_UNSIGNED<true> {}, conversion.suppress, conversion.field_width, conversion.length); break;
|
||||||
case 'p': result = parse_integer(BASE_TYPE<16>{}, IS_UNSIGNED<true> {}, conversion.suppress, conversion.field_width, LengthModifier::j); break;
|
case 'p': result = parse_integer(BASE_TYPE<16>{}, IS_UNSIGNED<true> {}, conversion.suppress, conversion.field_width, LengthModifier::j); break;
|
||||||
|
#if __enable_sse
|
||||||
case 'a': case 'e': case 'f': case 'g':
|
case 'a': case 'e': case 'f': case 'g':
|
||||||
result = parse_floating_point(conversion.suppress, conversion.field_width, conversion.length);
|
result = parse_floating_point(conversion.suppress, conversion.field_width, conversion.length);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 'S':
|
case 'S':
|
||||||
conversion.length = LengthModifier::l;
|
conversion.length = LengthModifier::l;
|
||||||
// fall through
|
// fall through
|
||||||
|
|
|
@ -158,6 +158,7 @@ static T strtoT(const char* str, char** endp, int base, int& error)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __enable_sse
|
||||||
template<BAN::floating_point T>
|
template<BAN::floating_point T>
|
||||||
static T strtoT(const char* str, char** endp, int& error)
|
static T strtoT(const char* str, char** endp, int& error)
|
||||||
{
|
{
|
||||||
|
@ -303,11 +304,14 @@ static T strtoT(const char* str, char** endp, int& error)
|
||||||
result *= BAN::Math::pow<T>((base == 10) ? 10 : 2, exponent);
|
result *= BAN::Math::pow<T>((base == 10) ? 10 : 2, exponent);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __enable_sse
|
||||||
double atof(const char* str)
|
double atof(const char* str)
|
||||||
{
|
{
|
||||||
return strtod(str, nullptr);
|
return strtod(str, nullptr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int atoi(const char* str)
|
int atoi(const char* str)
|
||||||
{
|
{
|
||||||
|
@ -324,6 +328,7 @@ long long atoll(const char* str)
|
||||||
return strtoll(str, nullptr, 10);
|
return strtoll(str, nullptr, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __enable_sse
|
||||||
float strtof(const char* __restrict str, char** __restrict endp)
|
float strtof(const char* __restrict str, char** __restrict endp)
|
||||||
{
|
{
|
||||||
return strtoT<float>(str, endp, errno);
|
return strtoT<float>(str, endp, errno);
|
||||||
|
@ -338,6 +343,7 @@ long double strtold(const char* __restrict str, char** __restrict endp)
|
||||||
{
|
{
|
||||||
return strtoT<long double>(str, endp, errno);
|
return strtoT<long double>(str, endp, errno);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
long strtol(const char* __restrict str, char** __restrict endp, int base)
|
long strtol(const char* __restrict str, char** __restrict endp, int base)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int errno = 0;
|
|
||||||
|
|
||||||
void* memccpy(void* __restrict s1, const void* __restrict s2, int c, size_t n)
|
void* memccpy(void* __restrict s1, const void* __restrict s2, int c, size_t n)
|
||||||
{
|
{
|
||||||
unsigned char* dst = static_cast<unsigned char*>(s1);
|
unsigned char* dst = static_cast<unsigned char*>(s1);
|
||||||
|
|
|
@ -89,6 +89,7 @@ namespace LibELF
|
||||||
SHN_COMMON = 0xFFF2,
|
SHN_COMMON = 0xFFF2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ELF_ST_BIND(i) ((i) >> 4)
|
||||||
enum ELF_STB
|
enum ELF_STB
|
||||||
{
|
{
|
||||||
STB_LOCAL = 0,
|
STB_LOCAL = 0,
|
||||||
|
@ -100,6 +101,7 @@ namespace LibELF
|
||||||
STB_HIPROC = 15,
|
STB_HIPROC = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ELF_ST_TYPE(i) ((i) & 0xF)
|
||||||
enum ELF_STT
|
enum ELF_STT
|
||||||
{
|
{
|
||||||
STT_NOTYPE = 0,
|
STT_NOTYPE = 0,
|
||||||
|
@ -174,4 +176,60 @@ namespace LibELF
|
||||||
DT_HIPROC = 0x7FFFFFFF,
|
DT_HIPROC = 0x7FFFFFFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||||
|
#define ELF32_R_TYPE(i) ((i) & 0xFF)
|
||||||
|
enum ELF_R_386
|
||||||
|
{
|
||||||
|
R_386_NONE = 0,
|
||||||
|
R_386_32 = 1,
|
||||||
|
R_386_PC32 = 2,
|
||||||
|
R_386_GOT32 = 3,
|
||||||
|
R_386_PLT32 = 4,
|
||||||
|
R_386_COPY = 5,
|
||||||
|
R_386_GLOB_DAT = 6,
|
||||||
|
R_386_JMP_SLOT = 7,
|
||||||
|
R_386_RELATIVE = 8,
|
||||||
|
R_386_GOTOFF = 9,
|
||||||
|
R_386_GOTPC = 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||||
|
#define ELF64_R_TYPE(i) ((i) & 0xFFFFFFFF)
|
||||||
|
enum ELF_R_X86_64
|
||||||
|
{
|
||||||
|
R_X86_64_NONE = 0,
|
||||||
|
R_X86_64_64 = 1,
|
||||||
|
R_X86_64_PC32 = 2,
|
||||||
|
R_X86_64_GOT32 = 3,
|
||||||
|
R_X86_64_PLT32 = 4,
|
||||||
|
R_X86_64_COPY = 5,
|
||||||
|
R_X86_64_GLOB_DAT = 6,
|
||||||
|
R_X86_64_JUMP_SLOT = 7,
|
||||||
|
R_X86_64_RELATIVE = 8,
|
||||||
|
R_X86_64_GOTPCREL = 9,
|
||||||
|
R_X86_64_32 = 10,
|
||||||
|
R_X86_64_32S = 11,
|
||||||
|
R_X86_64_16 = 12,
|
||||||
|
R_X86_64_PC16 = 13,
|
||||||
|
R_X86_64_8 = 14,
|
||||||
|
R_X86_64_PC8 = 15,
|
||||||
|
R_X86_64_DTPMOD64 = 16,
|
||||||
|
R_X86_64_DTPOFF64 = 17,
|
||||||
|
R_X86_64_TPOFF64 = 18,
|
||||||
|
R_X86_64_TLSGD = 19,
|
||||||
|
R_X86_64_TLSLD = 20,
|
||||||
|
R_X86_64_DTPOFF32 = 21,
|
||||||
|
R_X86_64_GOTTPOFF = 22,
|
||||||
|
R_X86_64_TPOFF32 = 23,
|
||||||
|
R_X86_64_PC64 = 24,
|
||||||
|
R_X86_64_GOTOFF64 = 25,
|
||||||
|
R_X86_64_GOTPC32 = 26,
|
||||||
|
R_X86_64_SIZE32 = 32,
|
||||||
|
R_X86_64_SIZE64 = 33,
|
||||||
|
R_X86_64_GOTPC32_TLSDESC = 34,
|
||||||
|
R_X86_64_TLSDESC_CALL = 35,
|
||||||
|
R_X86_64_TLSDESC = 36,
|
||||||
|
R_X86_64_IRELATIVE = 37,
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,5 +9,3 @@ banan_link_library(libfont ban)
|
||||||
|
|
||||||
banan_install_headers(libfont)
|
banan_install_headers(libfont)
|
||||||
install(TARGETS libfont OPTIONAL)
|
install(TARGETS libfont OPTIONAL)
|
||||||
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
|
||||||
|
|
|
@ -10,5 +10,3 @@ banan_link_library(libgui libc)
|
||||||
|
|
||||||
banan_install_headers(libgui)
|
banan_install_headers(libgui)
|
||||||
install(TARGETS libgui OPTIONAL)
|
install(TARGETS libgui OPTIONAL)
|
||||||
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
|
||||||
|
|
|
@ -11,5 +11,3 @@ banan_link_library(libimage ban)
|
||||||
|
|
||||||
banan_install_headers(libimage)
|
banan_install_headers(libimage)
|
||||||
install(TARGETS libimage OPTIONAL)
|
install(TARGETS libimage OPTIONAL)
|
||||||
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
|
||||||
|
|
|
@ -87,10 +87,10 @@ namespace LibImage
|
||||||
constexpr Image::Color as_color() const
|
constexpr Image::Color as_color() const
|
||||||
{
|
{
|
||||||
return Image::Color {
|
return Image::Color {
|
||||||
.r = static_cast<uint8_t>(BAN::Math::clamp<double>(r, 0.0, 255.0)),
|
.r = static_cast<uint8_t>(r < 0.0 ? 0.0 : r > 255.0 ? 255.0 : r),
|
||||||
.g = static_cast<uint8_t>(BAN::Math::clamp<double>(g, 0.0, 255.0)),
|
.g = static_cast<uint8_t>(g < 0.0 ? 0.0 : g > 255.0 ? 255.0 : g),
|
||||||
.b = static_cast<uint8_t>(BAN::Math::clamp<double>(b, 0.0, 255.0)),
|
.b = static_cast<uint8_t>(b < 0.0 ? 0.0 : b > 255.0 ? 255.0 : b),
|
||||||
.a = static_cast<uint8_t>(BAN::Math::clamp<double>(a, 0.0, 255.0)),
|
.a = static_cast<uint8_t>(a < 0.0 ? 0.0 : a > 255.0 ? 255.0 : a),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -133,8 +133,13 @@ namespace LibImage
|
||||||
{
|
{
|
||||||
const double src_x = x * ratio_x;
|
const double src_x = x * ratio_x;
|
||||||
const double src_y = y * ratio_y;
|
const double src_y = y * ratio_y;
|
||||||
|
#if __enable_sse
|
||||||
const double weight_x = src_x - floor(src_x);
|
const double weight_x = src_x - floor(src_x);
|
||||||
const double weight_y = src_y - floor(src_y);
|
const double weight_y = src_y - floor(src_y);
|
||||||
|
#else
|
||||||
|
const double weight_x = src_x - (uint64_t)src_x;
|
||||||
|
const double weight_y = src_y - (uint64_t)src_y;
|
||||||
|
#endif
|
||||||
|
|
||||||
const Color avg_t = Color::average(
|
const Color avg_t = Color::average(
|
||||||
get_clamped_color(src_x + 0.0, src_y),
|
get_clamped_color(src_x + 0.0, src_y),
|
||||||
|
@ -173,8 +178,13 @@ namespace LibImage
|
||||||
{
|
{
|
||||||
const double src_x = x * ratio_x;
|
const double src_x = x * ratio_x;
|
||||||
const double src_y = y * ratio_y;
|
const double src_y = y * ratio_y;
|
||||||
|
#if __enable_sse
|
||||||
const double weight_x = src_x - floor(src_x);
|
const double weight_x = src_x - floor(src_x);
|
||||||
const double weight_y = src_y - floor(src_y);
|
const double weight_y = src_y - floor(src_y);
|
||||||
|
#else
|
||||||
|
const double weight_x = src_x - (uint64_t)src_x;
|
||||||
|
const double weight_y = src_y - (uint64_t)src_y;
|
||||||
|
#endif
|
||||||
|
|
||||||
FloatingColor values[4];
|
FloatingColor values[4];
|
||||||
for (int64_t m = -1; m <= 2; m++)
|
for (int64_t m = -1; m <= 2; m++)
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace LibImage
|
||||||
// weight of 0.0 returns a and weight of 1.0 returns b
|
// weight of 0.0 returns a and weight of 1.0 returns b
|
||||||
static Color average(Color a, Color b, double weight)
|
static Color average(Color a, Color b, double weight)
|
||||||
{
|
{
|
||||||
const double b_mult = BAN::Math::clamp(weight, 0.0, 1.0);
|
const double b_mult = weight < 0.0 ? 0.0 : weight > 1.0 ? 1.0 : weight;
|
||||||
const double a_mult = 1.0 - b_mult;
|
const double a_mult = 1.0 - b_mult;
|
||||||
return Color {
|
return Color {
|
||||||
.r = static_cast<uint8_t>(a.r * a_mult + b.r * b_mult),
|
.r = static_cast<uint8_t>(a.r * a_mult + b.r * b_mult),
|
||||||
|
|
|
@ -4,10 +4,8 @@ set(LIBINPUT_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(libinput ${LIBINPUT_SOURCES})
|
add_library(libinput ${LIBINPUT_SOURCES})
|
||||||
banan_include_headers(libinput ban)
|
banan_link_library(libinput ban)
|
||||||
banan_link_library(libinput libc)
|
banan_link_library(libinput libc)
|
||||||
|
|
||||||
banan_install_headers(libinput)
|
banan_install_headers(libinput)
|
||||||
install(TARGETS libinput OPTIONAL)
|
install(TARGETS libinput OPTIONAL)
|
||||||
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ set(USERSPACE_PROGRAMS
|
||||||
cp
|
cp
|
||||||
dd
|
dd
|
||||||
dhcp-client
|
dhcp-client
|
||||||
|
DynamicLoader
|
||||||
echo
|
echo
|
||||||
getopt
|
getopt
|
||||||
http-server
|
http-server
|
||||||
|
@ -43,4 +44,9 @@ foreach(project ${USERSPACE_PROGRAMS})
|
||||||
target_link_options(${project} PRIVATE -nolibc)
|
target_link_options(${project} PRIVATE -nolibc)
|
||||||
# Default compile options
|
# Default compile options
|
||||||
target_compile_options(${project} PRIVATE -g -O2)
|
target_compile_options(${project} PRIVATE -g -O2)
|
||||||
|
|
||||||
|
target_compile_definitions(${project} PRIVATE __enable_sse=${BANAN_ENABLE_SSE})
|
||||||
|
if (NOT BANAN_ENABLE_SSE)
|
||||||
|
target_compile_options(${project} PRIVATE -mno-sse -mno-sse2)
|
||||||
|
endif ()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
utils.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(DynamicLoader ${SOURCES})
|
||||||
|
target_compile_options(DynamicLoader PRIVATE -fno-tree-loop-distribute-patterns -fno-rtti -pie -fpie -ffunction-sections -fdata-sections -mgeneral-regs-only)
|
||||||
|
target_compile_options(DynamicLoader PRIVATE -Wall -Wextra -Werror)
|
||||||
|
target_compile_definitions(DynamicLoader PRIVATE __arch=${BANAN_ARCH})
|
||||||
|
target_link_options(DynamicLoader PRIVATE -nolibc -nostartfiles -static-libgcc -pie -fpie)
|
||||||
|
target_link_options(DynamicLoader PRIVATE LINKER:--no-dynamic-linker)
|
||||||
|
|
||||||
|
# DynamicLoader does not support relocating itself
|
||||||
|
add_custom_command(
|
||||||
|
TARGET DynamicLoader POST_BUILD
|
||||||
|
COMMAND readelf --relocs $<TARGET_FILE:DynamicLoader> | grep -q 'There are no relocations in this file'
|
||||||
|
)
|
||||||
|
|
||||||
|
banan_include_headers(DynamicLoader ban)
|
||||||
|
banan_include_headers(DynamicLoader kernel)
|
||||||
|
banan_include_headers(DynamicLoader libc)
|
||||||
|
banan_include_headers(DynamicLoader libelf)
|
||||||
|
|
||||||
|
set_target_properties(DynamicLoader PROPERTIES OUTPUT_NAME DynamicLoader.so)
|
||||||
|
install(TARGETS DynamicLoader DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL)
|
|
@ -0,0 +1,928 @@
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <LibELF/Types.h>
|
||||||
|
#include <LibELF/Values.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
__attribute__((naked))
|
||||||
|
void _start()
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
asm volatile(
|
||||||
|
"xorq %rbp, %rbp;"
|
||||||
|
"call _entry;"
|
||||||
|
"ud2;"
|
||||||
|
);
|
||||||
|
#elif defined(__i686__)
|
||||||
|
asm volatile(
|
||||||
|
"xorl %ebp, %ebp;"
|
||||||
|
"pushl %ecx;"
|
||||||
|
"pushl %edx;"
|
||||||
|
"pushl %esi;"
|
||||||
|
"pushl %edi;"
|
||||||
|
"call _entry;"
|
||||||
|
"ud2;"
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((naked, noreturn))
|
||||||
|
static void call_entry_point(int, char**, char**, uintptr_t)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
asm volatile(
|
||||||
|
"andq $-16, %rsp;"
|
||||||
|
"jmp *%rcx;"
|
||||||
|
);
|
||||||
|
#elif defined(__i686__)
|
||||||
|
asm volatile(
|
||||||
|
"addl $4, %esp;"
|
||||||
|
"popl %edi;"
|
||||||
|
"popl %esi;"
|
||||||
|
"popl %edx;"
|
||||||
|
"popl %ecx;"
|
||||||
|
"andl $-16, %esp;"
|
||||||
|
"jmp *%ecx;"
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace LibELF;
|
||||||
|
|
||||||
|
static void validate_program_header(const ElfNativeFileHeader& file_header)
|
||||||
|
{
|
||||||
|
if (file_header.e_ident[EI_MAG0] != ELFMAG0 ||
|
||||||
|
file_header.e_ident[EI_MAG1] != ELFMAG1 ||
|
||||||
|
file_header.e_ident[EI_MAG2] != ELFMAG2 ||
|
||||||
|
file_header.e_ident[EI_MAG3] != ELFMAG3)
|
||||||
|
{
|
||||||
|
print_error_and_exit("ELF has invalid magic in header", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_header.e_ident[EI_DATA] != ELFDATA2LSB)
|
||||||
|
print_error_and_exit("ELF is not little-endian", 0);
|
||||||
|
|
||||||
|
if (file_header.e_ident[EI_VERSION] != EV_CURRENT)
|
||||||
|
print_error_and_exit("ELF has invalid version", 0);
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
if (file_header.e_ident[EI_CLASS] != ELFCLASS64)
|
||||||
|
#elif defined(__i686__)
|
||||||
|
if (file_header.e_ident[EI_CLASS] != ELFCLASS32)
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
print_error_and_exit("ELF not in native format", 0);
|
||||||
|
|
||||||
|
if (file_header.e_type != ET_EXEC && file_header.e_type != ET_DYN)
|
||||||
|
print_error_and_exit("ELF has unsupported file header type", 0);
|
||||||
|
|
||||||
|
if (file_header.e_version != EV_CURRENT)
|
||||||
|
print_error_and_exit("ELF has unsupported version", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((naked))
|
||||||
|
static void resolve_symbol_trampoline()
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
asm volatile(
|
||||||
|
"pushq %rdi;"
|
||||||
|
"pushq %rsi;"
|
||||||
|
"pushq %rdx;"
|
||||||
|
"pushq %rcx;"
|
||||||
|
"pushq %r8;"
|
||||||
|
"pushq %r9;"
|
||||||
|
"pushq %r10;"
|
||||||
|
"pushq %r11;"
|
||||||
|
|
||||||
|
"movq 64(%rsp), %rdi;"
|
||||||
|
"movq 72(%rsp), %rsi;"
|
||||||
|
|
||||||
|
"call resolve_symbol;"
|
||||||
|
|
||||||
|
"popq %r11;"
|
||||||
|
"popq %r10;"
|
||||||
|
"popq %r9;"
|
||||||
|
"popq %r8;"
|
||||||
|
"popq %rcx;"
|
||||||
|
"popq %rdx;"
|
||||||
|
"popq %rsi;"
|
||||||
|
"popq %rdi;"
|
||||||
|
|
||||||
|
"addq $16, %rsp;"
|
||||||
|
"jmp *%rax;"
|
||||||
|
);
|
||||||
|
#elif defined(__i686__)
|
||||||
|
asm volatile(
|
||||||
|
"call resolve_symbol;"
|
||||||
|
"addl $8, %esp;"
|
||||||
|
"jmp *%eax;"
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoadedElf
|
||||||
|
{
|
||||||
|
ElfNativeFileHeader file_header;
|
||||||
|
ElfNativeDynamic* dynamics;
|
||||||
|
|
||||||
|
uintptr_t base;
|
||||||
|
|
||||||
|
uintptr_t hash;
|
||||||
|
|
||||||
|
uintptr_t strtab;
|
||||||
|
|
||||||
|
uintptr_t symtab;
|
||||||
|
size_t syment;
|
||||||
|
|
||||||
|
uintptr_t rel;
|
||||||
|
size_t relent;
|
||||||
|
size_t relsz;
|
||||||
|
|
||||||
|
uintptr_t rela;
|
||||||
|
size_t relaent;
|
||||||
|
size_t relasz;
|
||||||
|
|
||||||
|
uintptr_t jmprel;
|
||||||
|
size_t pltrel;
|
||||||
|
size_t pltrelsz;
|
||||||
|
|
||||||
|
uintptr_t init;
|
||||||
|
uintptr_t init_array;
|
||||||
|
size_t init_arraysz;
|
||||||
|
|
||||||
|
bool has_called_init;
|
||||||
|
bool is_relocated;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uintptr_t SYM_NOT_FOUND = -1;
|
||||||
|
|
||||||
|
static uint32_t elf_hash(const char* name)
|
||||||
|
{
|
||||||
|
uint32_t h = 0, g;
|
||||||
|
while (*name)
|
||||||
|
{
|
||||||
|
h = (h << 4) + *name++;
|
||||||
|
if ((g = h & 0xF0000000))
|
||||||
|
h ^= g >> 24;
|
||||||
|
h &= ~g;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ElfNativeSymbol* find_symbol(const LoadedElf& elf, const char* name)
|
||||||
|
{
|
||||||
|
const uint32_t* hash_table = reinterpret_cast<uint32_t*>(elf.hash);
|
||||||
|
const uint32_t nbucket = hash_table[0];
|
||||||
|
|
||||||
|
for (uint32_t entry = hash_table[2 + (elf_hash(name) % nbucket)]; entry; entry = hash_table[2 + nbucket + entry])
|
||||||
|
{
|
||||||
|
auto& symbol = *reinterpret_cast<ElfNativeSymbol*>(elf.symtab + entry * elf.syment);
|
||||||
|
if (symbol.st_shndx == 0)
|
||||||
|
continue;
|
||||||
|
const char* symbol_name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name);
|
||||||
|
if (strcmp(name, symbol_name))
|
||||||
|
continue;
|
||||||
|
return &symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintptr_t get_symbol_address(const LoadedElf& elf, const char* name)
|
||||||
|
{
|
||||||
|
auto* symbol = find_symbol(elf, name);
|
||||||
|
if (symbol == nullptr)
|
||||||
|
return SYM_NOT_FOUND;
|
||||||
|
return elf.base + symbol->st_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoadedElf* get_libc_elf();
|
||||||
|
static LoadedElf* get_libgcc_elf();
|
||||||
|
|
||||||
|
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
|
||||||
|
static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc)
|
||||||
|
{
|
||||||
|
uintptr_t symbol_address = 0;
|
||||||
|
size_t symbol_size = 0;
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
const bool is_copy = (ELF64_R_TYPE(reloc.r_info) == R_X86_64_COPY);
|
||||||
|
if (const uint32_t symbol_index = ELF64_R_SYM(reloc.r_info))
|
||||||
|
#elif defined(__i686__)
|
||||||
|
const bool is_copy = (ELF32_R_TYPE(reloc.r_info) == R_386_COPY);
|
||||||
|
if (const uint32_t symbol_index = ELF32_R_SYM(reloc.r_info))
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
const auto& symbol = *reinterpret_cast<ElfNativeSymbol*>(elf.symtab + symbol_index * elf.syment);
|
||||||
|
const char* symbol_name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name);
|
||||||
|
|
||||||
|
symbol_size = symbol.st_size;
|
||||||
|
|
||||||
|
if (!is_copy && symbol.st_shndx)
|
||||||
|
symbol_address = elf.base + symbol.st_value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// external symbol
|
||||||
|
symbol_address = SYM_NOT_FOUND;
|
||||||
|
for (size_t i = 0; symbol_address == SYM_NOT_FOUND; i++)
|
||||||
|
{
|
||||||
|
auto& dynamic = elf.dynamics[i];
|
||||||
|
if (dynamic.d_tag == DT_NULL)
|
||||||
|
break;
|
||||||
|
if (dynamic.d_tag != DT_NEEDED)
|
||||||
|
continue;
|
||||||
|
const auto& lib_elf = *reinterpret_cast<LoadedElf*>(dynamic.d_un.d_ptr);
|
||||||
|
symbol_address = get_symbol_address(lib_elf, symbol_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// libgcc_s.so needs symbols from libc, but we can't link it as toolchain
|
||||||
|
// has to be built before libc. This hack allows resolving symbols from
|
||||||
|
// libc even if its not specified as dependency, but is loaded
|
||||||
|
if (symbol_address == SYM_NOT_FOUND)
|
||||||
|
if (const auto* libc_elf = get_libc_elf())
|
||||||
|
symbol_address = get_symbol_address(*libc_elf, symbol_name);
|
||||||
|
if (symbol_address == SYM_NOT_FOUND)
|
||||||
|
if (const auto* libgcc_elf = get_libgcc_elf())
|
||||||
|
symbol_address = get_symbol_address(*libgcc_elf, symbol_name);
|
||||||
|
|
||||||
|
if (symbol_address == SYM_NOT_FOUND)
|
||||||
|
{
|
||||||
|
if (ELF_ST_BIND(symbol.st_info) != STB_WEAK)
|
||||||
|
{
|
||||||
|
print(STDERR_FILENO, elf.path);
|
||||||
|
print(STDERR_FILENO, ": could not find symbol \"");
|
||||||
|
print(STDERR_FILENO, symbol_name);
|
||||||
|
print_error_and_exit("\"", 0);
|
||||||
|
}
|
||||||
|
symbol_address = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
uintptr_t value = 0;
|
||||||
|
bool add_addend = false;
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
switch (ELF64_R_TYPE(reloc.r_info))
|
||||||
|
{
|
||||||
|
case R_X86_64_NONE:
|
||||||
|
break;
|
||||||
|
case R_X86_64_64:
|
||||||
|
size = 8;
|
||||||
|
value = symbol_address;
|
||||||
|
add_addend = true;
|
||||||
|
break;
|
||||||
|
case R_X86_64_COPY:
|
||||||
|
if (symbol_address == 0)
|
||||||
|
print_error_and_exit("copy undefined weak symbol?", 0);
|
||||||
|
memcpy(
|
||||||
|
reinterpret_cast<void*>(elf.base + reloc.r_offset),
|
||||||
|
reinterpret_cast<void*>(symbol_address),
|
||||||
|
symbol_size
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case R_X86_64_GLOB_DAT:
|
||||||
|
size = 8;
|
||||||
|
value = symbol_address;
|
||||||
|
break;
|
||||||
|
case R_X86_64_JUMP_SLOT:
|
||||||
|
size = 8;
|
||||||
|
value = symbol_address;
|
||||||
|
break;
|
||||||
|
case R_X86_64_RELATIVE:
|
||||||
|
size = 8;
|
||||||
|
value = elf.base;
|
||||||
|
add_addend = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print(STDERR_FILENO, "unsupported reloc type ");
|
||||||
|
print_uint(STDERR_FILENO, ELF64_R_TYPE(reloc.r_info));
|
||||||
|
print(STDERR_FILENO, " in ");
|
||||||
|
print(STDERR_FILENO, elf.path);
|
||||||
|
print_error_and_exit("", 0);
|
||||||
|
}
|
||||||
|
#elif defined(__i686__)
|
||||||
|
switch (ELF32_R_TYPE(reloc.r_info))
|
||||||
|
{
|
||||||
|
case R_386_NONE:
|
||||||
|
break;
|
||||||
|
case R_386_32:
|
||||||
|
size = 4;
|
||||||
|
value = symbol_address;
|
||||||
|
add_addend = true;
|
||||||
|
break;
|
||||||
|
case R_386_PC32:
|
||||||
|
size = 4;
|
||||||
|
value = symbol_address - reloc.r_offset;
|
||||||
|
add_addend = true;
|
||||||
|
break;
|
||||||
|
case R_386_COPY:
|
||||||
|
memcpy(
|
||||||
|
reinterpret_cast<void*>(elf.base + reloc.r_offset),
|
||||||
|
reinterpret_cast<void*>(symbol_address),
|
||||||
|
symbol_size
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case R_386_GLOB_DAT:
|
||||||
|
size = 4;
|
||||||
|
value = symbol_address;
|
||||||
|
break;
|
||||||
|
case R_386_JMP_SLOT:
|
||||||
|
size = 4;
|
||||||
|
value = symbol_address;
|
||||||
|
break;
|
||||||
|
case R_386_RELATIVE:
|
||||||
|
size = 4;
|
||||||
|
value = elf.base;
|
||||||
|
add_addend = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print(STDERR_FILENO, "unsupported reloc type ");
|
||||||
|
print_uint(STDERR_FILENO, ELF32_R_TYPE(reloc.r_info));
|
||||||
|
print_error_and_exit("", 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (add_addend)
|
||||||
|
{
|
||||||
|
if constexpr(BAN::is_same_v<RelocT, ElfNativeRelocationA>)
|
||||||
|
value += reloc.r_addend;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 1: value += *reinterpret_cast<uint8_t*> (elf.base + reloc.r_offset); break;
|
||||||
|
case 2: value += *reinterpret_cast<uint16_t*>(elf.base + reloc.r_offset); break;
|
||||||
|
case 4: value += *reinterpret_cast<uint32_t*>(elf.base + reloc.r_offset); break;
|
||||||
|
case 8: value += *reinterpret_cast<uint64_t*>(elf.base + reloc.r_offset); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 1: *reinterpret_cast<uint8_t*> (elf.base + reloc.r_offset) = value; break;
|
||||||
|
case 2: *reinterpret_cast<uint16_t*>(elf.base + reloc.r_offset) = value; break;
|
||||||
|
case 4: *reinterpret_cast<uint32_t*>(elf.base + reloc.r_offset) = value; break;
|
||||||
|
case 8: *reinterpret_cast<uint64_t*>(elf.base + reloc.r_offset) = value; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relocate_elf(LoadedElf& elf, bool lazy_load)
|
||||||
|
{
|
||||||
|
if (elf.is_relocated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// relocate libraries
|
||||||
|
for (size_t i = 0;; i++)
|
||||||
|
{
|
||||||
|
auto& dynamic = elf.dynamics[i];
|
||||||
|
if (dynamic.d_tag == DT_NULL)
|
||||||
|
break;
|
||||||
|
if (dynamic.d_tag != DT_NEEDED)
|
||||||
|
continue;
|
||||||
|
relocate_elf(*reinterpret_cast<LoadedElf*>(dynamic.d_un.d_ptr), lazy_load);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elf.is_relocated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// do "normal" relocations
|
||||||
|
if (elf.rel && elf.relent)
|
||||||
|
for (size_t i = 0; i < elf.relsz / elf.relent; i++)
|
||||||
|
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent));
|
||||||
|
if (elf.rela && elf.relaent)
|
||||||
|
for (size_t i = 0; i < elf.relasz / elf.relaent; i++)
|
||||||
|
handle_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent));
|
||||||
|
|
||||||
|
// do jumprel relocations
|
||||||
|
if (elf.jmprel && elf.pltrelsz)
|
||||||
|
{
|
||||||
|
if (elf.pltrel != DT_REL && elf.pltrel != DT_RELA)
|
||||||
|
print_error_and_exit("invalid value for DT_PLTREL", 0);
|
||||||
|
|
||||||
|
if (!lazy_load)
|
||||||
|
{
|
||||||
|
switch (elf.pltrel)
|
||||||
|
{
|
||||||
|
case DT_REL:
|
||||||
|
for (size_t i = 0; i < elf.pltrelsz / sizeof(ElfNativeRelocation); i++)
|
||||||
|
handle_relocation(elf, reinterpret_cast<ElfNativeRelocation*>(elf.jmprel)[i]);
|
||||||
|
break;
|
||||||
|
case DT_RELA:
|
||||||
|
for (size_t i = 0; i < elf.pltrelsz / sizeof(ElfNativeRelocationA); i++)
|
||||||
|
handle_relocation(elf, reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const size_t pltrelent = (elf.pltrel == DT_REL)
|
||||||
|
? sizeof(ElfNativeRelocation)
|
||||||
|
: sizeof(ElfNativeRelocationA);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < elf.pltrelsz / pltrelent; i++)
|
||||||
|
{
|
||||||
|
const auto info = (elf.pltrel == DT_REL)
|
||||||
|
? reinterpret_cast<ElfNativeRelocation*>(elf.jmprel)[i].r_info
|
||||||
|
: reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[i].r_info;
|
||||||
|
const auto offset = (elf.pltrel == DT_REL)
|
||||||
|
? reinterpret_cast<ElfNativeRelocation*>(elf.jmprel)[i].r_offset
|
||||||
|
: reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[i].r_offset;
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
if (ELF64_R_TYPE(info) != R_X86_64_JUMP_SLOT)
|
||||||
|
print_error_and_exit("jmprel relocation not R_X86_64_JUMP_SLOT", 0);
|
||||||
|
#elif defined(__i686__)
|
||||||
|
if (ELF32_R_TYPE(info) != R_386_JMP_SLOT)
|
||||||
|
print_error_and_exit("jmprel relocation not R_386_JMP_SLOT", 0);
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*reinterpret_cast<uintptr_t*>(elf.base + offset) += elf.base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elf.is_relocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
__attribute__((used))
|
||||||
|
uintptr_t resolve_symbol(const LoadedElf& elf, uintptr_t plt_entry)
|
||||||
|
{
|
||||||
|
if (elf.pltrel == DT_REL)
|
||||||
|
return handle_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.jmprel + plt_entry));
|
||||||
|
if (elf.pltrel == DT_RELA)
|
||||||
|
return handle_relocation(elf, reinterpret_cast<ElfNativeRelocationA*>(elf.jmprel)[plt_entry]);
|
||||||
|
print_error_and_exit("invalid value for DT_PLTREL", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoadedElf& load_elf(const char* path, int fd);
|
||||||
|
|
||||||
|
static void handle_dynamic(LoadedElf& elf)
|
||||||
|
{
|
||||||
|
uintptr_t pltgot = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0;; i++)
|
||||||
|
{
|
||||||
|
auto& dynamic = elf.dynamics[i];
|
||||||
|
if (dynamic.d_tag == DT_NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (dynamic.d_tag)
|
||||||
|
{
|
||||||
|
case DT_PLTGOT: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_HASH: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_STRTAB: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_SYMTAB: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_RELA: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_INIT: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_FINI: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_REL: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_JMPREL: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_INIT_ARRAY: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
case DT_FINI_ARRAY: dynamic.d_un.d_ptr += elf.base; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dynamic.d_tag)
|
||||||
|
{
|
||||||
|
case DT_PLTRELSZ: elf.pltrelsz = dynamic.d_un.d_val; break;
|
||||||
|
case DT_PLTGOT: pltgot = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_HASH: elf.hash = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_STRTAB: elf.strtab = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_SYMTAB: elf.symtab = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_RELA: elf.rela = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_RELASZ: elf.relasz = dynamic.d_un.d_val; break;
|
||||||
|
case DT_RELAENT: elf.relaent = dynamic.d_un.d_val; break;
|
||||||
|
case DT_SYMENT: elf.syment = dynamic.d_un.d_val; break;
|
||||||
|
case DT_REL: elf.rel = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_RELSZ: elf.relsz = dynamic.d_un.d_val; break;
|
||||||
|
case DT_RELENT: elf.relent = dynamic.d_un.d_val; break;
|
||||||
|
case DT_PLTREL: elf.pltrel = dynamic.d_un.d_val; break;
|
||||||
|
case DT_JMPREL: elf.jmprel = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_INIT: elf.init = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_INIT_ARRAY: elf.init_array = dynamic.d_un.d_ptr; break;
|
||||||
|
case DT_INIT_ARRAYSZ: elf.init_arraysz = dynamic.d_un.d_val; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0;; i++)
|
||||||
|
{
|
||||||
|
auto& dynamic = elf.dynamics[i];
|
||||||
|
if (dynamic.d_tag == DT_NULL)
|
||||||
|
break;
|
||||||
|
if (dynamic.d_tag != DT_NEEDED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char* library_dir = "/usr/lib/";
|
||||||
|
|
||||||
|
char path_buffer[PATH_MAX];
|
||||||
|
char* path_ptr = path_buffer;
|
||||||
|
|
||||||
|
const char* library_name = reinterpret_cast<const char*>(elf.strtab + dynamic.d_un.d_val);
|
||||||
|
if (library_name[0] != '/')
|
||||||
|
for (size_t i = 0; library_dir[i]; i++)
|
||||||
|
*path_ptr++ = library_dir[i];
|
||||||
|
for (size_t i = 0; library_name[i]; i++)
|
||||||
|
*path_ptr++ = library_name[i];
|
||||||
|
*path_ptr = '\0';
|
||||||
|
|
||||||
|
char realpath[PATH_MAX];
|
||||||
|
if (auto ret = syscall(SYS_REALPATH, path_buffer, realpath); ret < 0)
|
||||||
|
print_error_and_exit("realpath", ret);
|
||||||
|
|
||||||
|
int library_fd = syscall(SYS_OPEN, realpath, O_RDONLY);
|
||||||
|
if (library_fd < 0)
|
||||||
|
print_error_and_exit("could not open library", library_fd);
|
||||||
|
|
||||||
|
const auto& loaded_elf = load_elf(realpath, library_fd);
|
||||||
|
dynamic.d_un.d_ptr = reinterpret_cast<uintptr_t>(&loaded_elf);
|
||||||
|
|
||||||
|
syscall(SYS_CLOSE, library_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup required GOT entries
|
||||||
|
reinterpret_cast<uintptr_t*>(pltgot)[0] = reinterpret_cast<uintptr_t>(elf.dynamics);
|
||||||
|
reinterpret_cast<uintptr_t*>(pltgot)[1] = reinterpret_cast<uintptr_t>(&elf);
|
||||||
|
reinterpret_cast<uintptr_t*>(pltgot)[2] = reinterpret_cast<uintptr_t>(&resolve_symbol_trampoline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool can_load_elf(int fd, const ElfNativeFileHeader& file_header, uintptr_t base)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < file_header.e_phnum; i++)
|
||||||
|
{
|
||||||
|
ElfNativeProgramHeader program_header;
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, &program_header, sizeof(program_header), file_header.e_phoff + i * file_header.e_phentsize); ret != sizeof(program_header))
|
||||||
|
print_error_and_exit("could not read program header", ret);
|
||||||
|
program_header.p_vaddr += base;
|
||||||
|
|
||||||
|
uintptr_t page_alinged_vaddr = program_header.p_vaddr & ~(uintptr_t)0xFFF;
|
||||||
|
size_t mmap_length = (program_header.p_vaddr + program_header.p_memsz) - page_alinged_vaddr;
|
||||||
|
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = reinterpret_cast<void*>(page_alinged_vaddr);
|
||||||
|
mmap_args.fildes = -1;
|
||||||
|
mmap_args.flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE;
|
||||||
|
mmap_args.len = mmap_length;
|
||||||
|
mmap_args.off = 0;
|
||||||
|
mmap_args.prot = PROT_NONE;
|
||||||
|
|
||||||
|
auto ret = reinterpret_cast<void*>(syscall(SYS_MMAP, &mmap_args));
|
||||||
|
if (ret == MAP_FAILED)
|
||||||
|
return false;
|
||||||
|
syscall(SYS_MUNMAP, ret, mmap_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_program_header(const ElfNativeProgramHeader& program_header, int fd, bool needs_writable)
|
||||||
|
{
|
||||||
|
if (program_header.p_type != PT_LOAD)
|
||||||
|
print_error_and_exit("trying to load non PT_LOAD program header", 0);
|
||||||
|
if (program_header.p_memsz < program_header.p_filesz)
|
||||||
|
print_error_and_exit("invalid program header, memsz lower than filesz", 0);
|
||||||
|
|
||||||
|
const int prot =
|
||||||
|
[&program_header]() -> int
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (program_header.p_flags & PF_R)
|
||||||
|
result |= PROT_READ;
|
||||||
|
if (program_header.p_flags & PF_W)
|
||||||
|
result |= PROT_WRITE;
|
||||||
|
if (program_header.p_flags & PF_X)
|
||||||
|
result |= PROT_EXEC;
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
|
||||||
|
const uintptr_t aligned_vaddr = program_header.p_vaddr & ~(uintptr_t)0xFFF;
|
||||||
|
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = reinterpret_cast<void*>(aligned_vaddr);
|
||||||
|
mmap_args.fildes = -1;
|
||||||
|
mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
|
||||||
|
mmap_args.len = (program_header.p_vaddr + program_header.p_memsz) - aligned_vaddr;
|
||||||
|
mmap_args.off = 0;
|
||||||
|
mmap_args.prot = prot | PROT_WRITE;
|
||||||
|
|
||||||
|
if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(aligned_vaddr))
|
||||||
|
print_error_and_exit("could not load program header", ret);
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, program_header.p_vaddr, program_header.p_filesz, program_header.p_offset); ret != static_cast<long>(program_header.p_filesz))
|
||||||
|
print_error_and_exit("could not load program header", ret);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
uintptr_t filesz = program_header.p_filesz;
|
||||||
|
|
||||||
|
if (program_header.p_filesz != program_header.p_memsz)
|
||||||
|
{
|
||||||
|
const uintptr_t data_end_vaddr = program_header.p_vaddr + program_header.p_filesz;
|
||||||
|
const uintptr_t zero_end_vaddr = program_header.p_vaddr + program_header.p_memsz;
|
||||||
|
|
||||||
|
uintptr_t start_vaddr = data_end_vaddr & ~(uintptr_t)0xFFF;
|
||||||
|
if (program_header.p_vaddr & 0xFFF)
|
||||||
|
start_vaddr = program_header.p_vaddr & ~(uintptr_t)0xFFF;
|
||||||
|
|
||||||
|
if (start_vaddr != data_end_vaddr)
|
||||||
|
{
|
||||||
|
const uintptr_t end_vaddr = (data_end_vaddr + 4095) & ~(uintptr_t)0xFFF;
|
||||||
|
const ptrdiff_t length = min(end_vaddr - start_vaddr, zero_end_vaddr - start_vaddr);
|
||||||
|
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = reinterpret_cast<void*>(start_vaddr);
|
||||||
|
mmap_args.fildes = -1;
|
||||||
|
mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
|
||||||
|
mmap_args.len = length;
|
||||||
|
mmap_args.off = 0;
|
||||||
|
mmap_args.prot = prot | PROT_WRITE;
|
||||||
|
|
||||||
|
if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(start_vaddr))
|
||||||
|
print_error_and_exit("could not load program header", ret);
|
||||||
|
|
||||||
|
uintptr_t dummy_bytes = program_header.p_vaddr - start_vaddr;
|
||||||
|
if (program_header.p_vaddr & 0xFFF)
|
||||||
|
dummy_bytes = 0;
|
||||||
|
|
||||||
|
const uintptr_t data_vaddr = program_header.p_vaddr + dummy_bytes;
|
||||||
|
const ptrdiff_t data_bytes = data_end_vaddr - data_vaddr;
|
||||||
|
const uintptr_t data_offset = program_header.p_offset + dummy_bytes;
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, data_vaddr, data_bytes, data_offset); ret != data_bytes)
|
||||||
|
print_error_and_exit("could not load program header", ret);
|
||||||
|
|
||||||
|
if (!(prot & PROT_WRITE) && !needs_writable)
|
||||||
|
{
|
||||||
|
// FIXME: Implement mprotect so PROT_WRITE can be removed
|
||||||
|
//syscall(SYS_MPROTECT, start_vaddr, length, prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
filesz -= data_bytes;
|
||||||
|
start_vaddr += 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_vaddr < zero_end_vaddr)
|
||||||
|
{
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = reinterpret_cast<void*>(start_vaddr);
|
||||||
|
mmap_args.fildes = -1;
|
||||||
|
mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
|
||||||
|
mmap_args.len = zero_end_vaddr - start_vaddr;
|
||||||
|
mmap_args.off = 0;
|
||||||
|
mmap_args.prot = prot | (needs_writable ? PROT_WRITE : 0);
|
||||||
|
|
||||||
|
if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(start_vaddr))
|
||||||
|
print_error_and_exit("could not load program header", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filesz)
|
||||||
|
{
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = reinterpret_cast<void*>(program_header.p_vaddr);
|
||||||
|
mmap_args.fildes = fd;
|
||||||
|
mmap_args.flags = MAP_PRIVATE | MAP_FIXED;
|
||||||
|
mmap_args.len = filesz;
|
||||||
|
mmap_args.off = program_header.p_offset;
|
||||||
|
mmap_args.prot = prot | (needs_writable ? PROT_WRITE : 0);
|
||||||
|
|
||||||
|
if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(program_header.p_vaddr))
|
||||||
|
print_error_and_exit("could not load program header", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoadedElf s_loaded_files[128];
|
||||||
|
static size_t s_loaded_file_count = 0;
|
||||||
|
|
||||||
|
static LoadedElf* get_libc_elf()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
|
if (strcmp(s_loaded_files[i].path, "/usr/lib/libc.so") == 0)
|
||||||
|
return &s_loaded_files[i];
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoadedElf* get_libgcc_elf()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
|
if (strcmp(s_loaded_files[i].path, "/usr/lib/libgcc_s.so") == 0)
|
||||||
|
return &s_loaded_files[i];
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoadedElf& load_elf(const char* path, int fd)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
|
if (strcmp(s_loaded_files[i].path, path) == 0)
|
||||||
|
return s_loaded_files[i];
|
||||||
|
|
||||||
|
ElfNativeFileHeader file_header;
|
||||||
|
if (auto ret = syscall(SYS_READ, fd, &file_header, sizeof(file_header)); ret != sizeof(file_header))
|
||||||
|
print_error_and_exit("could not read file header", ret);
|
||||||
|
|
||||||
|
validate_program_header(file_header);
|
||||||
|
|
||||||
|
uintptr_t base = 0;
|
||||||
|
if (file_header.e_type == ET_DYN)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
constexpr uintptr_t base_mask = 0x7FFFFFFFF000;
|
||||||
|
#elif defined(__i686__)
|
||||||
|
constexpr uintptr_t base_mask = 0x7FFFF000;
|
||||||
|
#else
|
||||||
|
#error "unsupported architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// FIXME: This is very hacky :D
|
||||||
|
do {
|
||||||
|
base = (get_random_uptr() & base_mask) + 0x100000;
|
||||||
|
} while (!can_load_elf(fd, file_header, base));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needs_writable = false;
|
||||||
|
bool has_dynamic_pheader = false;
|
||||||
|
ElfNativeProgramHeader dynamic_pheader;
|
||||||
|
for (size_t i = 0; i < file_header.e_phnum; i++)
|
||||||
|
{
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, &dynamic_pheader, sizeof(dynamic_pheader), file_header.e_phoff + i * file_header.e_phentsize); ret != sizeof(dynamic_pheader))
|
||||||
|
print_error_and_exit("could not read program header", ret);
|
||||||
|
if (dynamic_pheader.p_type != PT_DYNAMIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = nullptr;
|
||||||
|
mmap_args.fildes = -1;
|
||||||
|
mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||||
|
mmap_args.len = dynamic_pheader.p_memsz;
|
||||||
|
mmap_args.off = 0;
|
||||||
|
mmap_args.prot = PROT_READ | PROT_WRITE;
|
||||||
|
|
||||||
|
const auto uaddr = syscall(SYS_MMAP, &mmap_args);
|
||||||
|
if (uaddr < 0)
|
||||||
|
print_error_and_exit("could not map dynamic header", uaddr);
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, uaddr, dynamic_pheader.p_filesz, dynamic_pheader.p_offset); ret != static_cast<long>(dynamic_pheader.p_filesz))
|
||||||
|
print_error_and_exit("could not read dynamic header", ret);
|
||||||
|
|
||||||
|
const auto* dynamics = reinterpret_cast<ElfNativeDynamic*>(uaddr);
|
||||||
|
for (size_t j = 0;; j++)
|
||||||
|
{
|
||||||
|
const auto& dynamic = dynamics[j];
|
||||||
|
if (dynamic.d_tag == DT_NULL)
|
||||||
|
break;
|
||||||
|
if (dynamic.d_tag != DT_TEXTREL)
|
||||||
|
continue;
|
||||||
|
needs_writable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall(SYS_MUNMAP, uaddr, dynamic_pheader.p_memsz);
|
||||||
|
|
||||||
|
has_dynamic_pheader = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < file_header.e_phnum; i++)
|
||||||
|
{
|
||||||
|
ElfNativeProgramHeader program_header;
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, &program_header, sizeof(program_header), file_header.e_phoff + i * file_header.e_phentsize); ret != sizeof(program_header))
|
||||||
|
print_error_and_exit("could not read program header", ret);
|
||||||
|
|
||||||
|
switch (program_header.p_type)
|
||||||
|
{
|
||||||
|
case PT_NULL:
|
||||||
|
case PT_DYNAMIC:
|
||||||
|
case PT_INTERP:
|
||||||
|
case PT_NOTE:
|
||||||
|
case PT_PHDR:
|
||||||
|
break;
|
||||||
|
case PT_LOAD:
|
||||||
|
program_header.p_vaddr += base;
|
||||||
|
load_program_header(program_header, fd, needs_writable);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print(STDERR_FILENO, "unsupported program header type ");
|
||||||
|
print_uint(STDERR_FILENO, program_header.p_type);
|
||||||
|
print_error_and_exit("", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& elf = s_loaded_files[s_loaded_file_count++];
|
||||||
|
elf.base = base;
|
||||||
|
elf.dynamics = nullptr;
|
||||||
|
memcpy(&elf.file_header, &file_header, sizeof(file_header));
|
||||||
|
strcpy(elf.path, path);
|
||||||
|
|
||||||
|
if (has_dynamic_pheader)
|
||||||
|
{
|
||||||
|
sys_mmap_t mmap_args;
|
||||||
|
mmap_args.addr = nullptr;
|
||||||
|
mmap_args.fildes = -1;
|
||||||
|
mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||||
|
mmap_args.len = dynamic_pheader.p_memsz;
|
||||||
|
mmap_args.off = 0;
|
||||||
|
mmap_args.prot = PROT_READ | PROT_WRITE;
|
||||||
|
|
||||||
|
const auto uaddr = syscall(SYS_MMAP, &mmap_args);
|
||||||
|
if (uaddr < 0)
|
||||||
|
print_error_and_exit("could not map dynamic header", uaddr);
|
||||||
|
if (auto ret = syscall(SYS_PREAD, fd, uaddr, dynamic_pheader.p_filesz, dynamic_pheader.p_offset); ret != static_cast<long>(dynamic_pheader.p_filesz))
|
||||||
|
print_error_and_exit("could not read dynamic header", ret);
|
||||||
|
|
||||||
|
elf.dynamics = reinterpret_cast<ElfNativeDynamic*>(uaddr);
|
||||||
|
handle_dynamic(elf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void call_init_funcs(LoadedElf& elf, char** envp, bool skip)
|
||||||
|
{
|
||||||
|
if (elf.has_called_init)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (elf.dynamics)
|
||||||
|
{
|
||||||
|
for (size_t i = 0;; i++)
|
||||||
|
{
|
||||||
|
const auto& dynamic = elf.dynamics[i];
|
||||||
|
if (dynamic.d_tag == DT_NULL)
|
||||||
|
break;
|
||||||
|
if (dynamic.d_tag == DT_NEEDED)
|
||||||
|
call_init_funcs(*reinterpret_cast<LoadedElf*>(dynamic.d_un.d_ptr), envp, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elf.has_called_init || skip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using init_t = void(*)();
|
||||||
|
if (elf.init)
|
||||||
|
reinterpret_cast<init_t>(elf.init)();
|
||||||
|
for (size_t i = 0; i < elf.init_arraysz / sizeof(init_t); i++)
|
||||||
|
reinterpret_cast<init_t*>(elf.init_array)[i]();
|
||||||
|
|
||||||
|
if (strcmp(elf.path, "/usr/lib/libc.so") == 0)
|
||||||
|
{
|
||||||
|
const uintptr_t init_libc = get_symbol_address(elf, "_init_libc");
|
||||||
|
if (init_libc != SYM_NOT_FOUND)
|
||||||
|
{
|
||||||
|
using init_libc_t = void(*)(char**);
|
||||||
|
reinterpret_cast<init_libc_t>(init_libc)(envp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elf.has_called_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
__attribute__((used, noreturn))
|
||||||
|
int _entry(int argc, char** argv, char** envp, int fd)
|
||||||
|
{
|
||||||
|
const bool invoked_directly = (fd < 0);
|
||||||
|
if (invoked_directly)
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
print_error_and_exit("missing program name", 0);
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
fd = syscall(SYS_OPEN, argv[0], O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
print_error_and_exit("could not open program", fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_random();
|
||||||
|
auto elf = load_elf(argv[0], fd);
|
||||||
|
syscall(SYS_CLOSE, fd);
|
||||||
|
fini_random();
|
||||||
|
|
||||||
|
relocate_elf(elf, true);
|
||||||
|
call_init_funcs(elf, envp, true);
|
||||||
|
call_entry_point(argc, argv, envp, elf.base + elf.file_header.e_entry);
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void print(int fd, const char* buffer)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (buffer[len])
|
||||||
|
len++;
|
||||||
|
syscall(SYS_WRITE, fd, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* errno_to_string(int error);
|
||||||
|
|
||||||
|
[[noreturn]] void print_error_and_exit(const char* message, int error)
|
||||||
|
{
|
||||||
|
print(STDERR_FILENO, message);
|
||||||
|
if (error < 0)
|
||||||
|
{
|
||||||
|
print(STDERR_FILENO, ": ");
|
||||||
|
print(STDERR_FILENO, errno_to_string(-error));
|
||||||
|
}
|
||||||
|
print(STDERR_FILENO, "\n");
|
||||||
|
|
||||||
|
syscall(SYS_EXIT, 1);
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
const unsigned char* u1 = reinterpret_cast<const unsigned char*>(s1);
|
||||||
|
const unsigned char* u2 = reinterpret_cast<const unsigned char*>(s2);
|
||||||
|
for (; *u1 && *u2; u1++, u2++)
|
||||||
|
if (*u1 != *u2)
|
||||||
|
break;
|
||||||
|
return *u1 - *u2;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* strcpy(char* __restrict s1, const char* __restrict s2)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
for (; s2[i]; i++)
|
||||||
|
s1[i] = s2[i];
|
||||||
|
s1[i] = '\0';
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* memcpy(void* __restrict dstp, const void* __restrict srcp, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char* dst = static_cast<unsigned char*>(dstp);
|
||||||
|
const unsigned char* src = static_cast<const unsigned char*>(srcp);
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
dst[i] = src[i];
|
||||||
|
return dstp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_random_fd;
|
||||||
|
|
||||||
|
void init_random()
|
||||||
|
{
|
||||||
|
s_random_fd = syscall(SYS_OPEN, "/dev/random", O_RDONLY);
|
||||||
|
if (s_random_fd < 0)
|
||||||
|
print_error_and_exit("could not open /dev/random", s_random_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fini_random()
|
||||||
|
{
|
||||||
|
auto ret = syscall(SYS_CLOSE, s_random_fd);
|
||||||
|
if (ret < 0)
|
||||||
|
print_error_and_exit("could not close /dev/random", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t get_random_uptr()
|
||||||
|
{
|
||||||
|
uintptr_t result;
|
||||||
|
if (auto ret = syscall(SYS_READ, s_random_fd, &result, sizeof(result)); ret != sizeof(result))
|
||||||
|
print_error_and_exit("could not read from /dev/random", ret);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* errno_to_string(int error)
|
||||||
|
{
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case 0: return "Success";
|
||||||
|
case E2BIG: return "Argument list too long.";
|
||||||
|
case EACCES: return "Permission denied.";
|
||||||
|
case EADDRINUSE: return "Address in use.";
|
||||||
|
case EADDRNOTAVAIL: return "Address not available.";
|
||||||
|
case EAFNOSUPPORT: return "Address family not supported.";
|
||||||
|
case EAGAIN: return "Resource unavailable, try again.";
|
||||||
|
case EALREADY: return "Connection already in progress.";
|
||||||
|
case EBADF: return "Bad file descriptor.";
|
||||||
|
case EBADMSG: return "Bad message.";
|
||||||
|
case EBUSY: return "Device or resource busy.";
|
||||||
|
case ECANCELED: return "Operation canceled.";
|
||||||
|
case ECHILD: return "No child processes.";
|
||||||
|
case ECONNABORTED: return "Connection aborted.";
|
||||||
|
case ECONNREFUSED: return "Connection refused.";
|
||||||
|
case ECONNRESET: return "Connection reset.";
|
||||||
|
case EDEADLK: return "Resource deadlock would occur.";
|
||||||
|
case EDESTADDRREQ: return "Destination address required.";
|
||||||
|
case EDOM: return "Mathematics argument out of domain of function.";
|
||||||
|
case EDQUOT: return "Reserved.";
|
||||||
|
case EEXIST: return "File exists.";
|
||||||
|
case EFAULT: return "Bad address.";
|
||||||
|
case EFBIG: return "File too large.";
|
||||||
|
case EHOSTUNREACH: return "Host is unreachable.";
|
||||||
|
case EIDRM: return "Identifier removed.";
|
||||||
|
case EILSEQ: return "Illegal byte sequence.";
|
||||||
|
case EINPROGRESS: return "Operation in progress.";
|
||||||
|
case EINTR: return "Interrupted function.";
|
||||||
|
case EINVAL: return "Invalid argument.";
|
||||||
|
case EIO: return "I/O error.";
|
||||||
|
case EISCONN: return "Socket is connected.";
|
||||||
|
case EISDIR: return "Is a directory.";
|
||||||
|
case ELOOP: return "Too many levels of symbolic links.";
|
||||||
|
case EMFILE: return "File descriptor value too large.";
|
||||||
|
case EMLINK: return "Too many links.";
|
||||||
|
case EMSGSIZE: return "Message too large.";
|
||||||
|
case EMULTIHOP: return "Reserved.";
|
||||||
|
case ENAMETOOLONG: return "Filename too long.";
|
||||||
|
case ENETDOWN: return "Network is down.";
|
||||||
|
case ENETRESET: return "Connection aborted by network.";
|
||||||
|
case ENETUNREACH: return "Network unreachable.";
|
||||||
|
case ENFILE: return "Too many files open in system.";
|
||||||
|
case ENOBUFS: return "No buffer space available.";
|
||||||
|
case ENODATA: return "No message is available on the STREAM head read queue.";
|
||||||
|
case ENODEV: return "No such device.";
|
||||||
|
case ENOENT: return "No such file or directory.";
|
||||||
|
case ENOEXEC: return "Executable file format error.";
|
||||||
|
case ENOLCK: return "No locks available.";
|
||||||
|
case ENOLINK: return "Reserved.";
|
||||||
|
case ENOMEM: return "Not enough space.";
|
||||||
|
case ENOMSG: return "No message of the desired type.";
|
||||||
|
case ENOPROTOOPT: return "Protocol not available.";
|
||||||
|
case ENOSPC: return "No space left on device.";
|
||||||
|
case ENOSR: return "No STREAM resources.";
|
||||||
|
case ENOSTR: return "Not a STREAM.";
|
||||||
|
case ENOSYS: return "Functionality not supported.";
|
||||||
|
case ENOTCONN: return "The socket is not connected.";
|
||||||
|
case ENOTDIR: return "Not a directory or a symbolic link to a directory.";
|
||||||
|
case ENOTEMPTY: return "Directory not empty.";
|
||||||
|
case ENOTRECOVERABLE: return "State not recoverable.";
|
||||||
|
case ENOTSOCK: return "Not a socket.";
|
||||||
|
case ENOTSUP: return "Not supported.";
|
||||||
|
case ENOTTY: return "Inappropriate I/O control operation.";
|
||||||
|
case ENXIO: return "No such device or address.";
|
||||||
|
case EOPNOTSUPP: return "Operation not supported on socket .";
|
||||||
|
case EOVERFLOW: return "Value too large to be stored in data type.";
|
||||||
|
case EOWNERDEAD: return "Previous owner died.";
|
||||||
|
case EPERM: return "Operation not permitted.";
|
||||||
|
case EPIPE: return "Broken pipe.";
|
||||||
|
case EPROTO: return "Protocol error.";
|
||||||
|
case EPROTONOSUPPORT: return "Protocol not supported.";
|
||||||
|
case EPROTOTYPE: return "Protocol wrong type for socket.";
|
||||||
|
case ERANGE: return "Result too large.";
|
||||||
|
case EROFS: return "Read-only file system.";
|
||||||
|
case ESPIPE: return "Invalid seek.";
|
||||||
|
case ESRCH: return "No such process.";
|
||||||
|
case ESTALE: return "Reserved.";
|
||||||
|
case ETIME: return "Stream ioctl() timeout.";
|
||||||
|
case ETIMEDOUT: return "Connection timed out.";
|
||||||
|
case ETXTBSY: return "Text file busy.";
|
||||||
|
case EWOULDBLOCK: return "Operation would block.";
|
||||||
|
case EXDEV: return "Cross-device link.";
|
||||||
|
case EEXISTS: return "File exists";
|
||||||
|
case ENOTBLK: return "Block device required";
|
||||||
|
case EUNKNOWN: return "Unknown error";
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Traits.h>
|
||||||
|
#include <kernel/Syscall.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr T min(T a, T b)
|
||||||
|
{
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr T max(T a, T b)
|
||||||
|
{
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Ts> requires (sizeof...(Ts) <= 5) && ((BAN::is_integral_v<Ts> || BAN::is_pointer_v<Ts>) && ...)
|
||||||
|
inline auto syscall(long syscall, Ts... args)
|
||||||
|
{
|
||||||
|
return Kernel::syscall(syscall, (uintptr_t)args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(int fd, const char* buffer);
|
||||||
|
|
||||||
|
[[noreturn]] void print_error_and_exit(const char* message, int error);
|
||||||
|
|
||||||
|
template<BAN::unsigned_integral T>
|
||||||
|
inline void print_uint(int fd, T val, uint8_t base = 10)
|
||||||
|
{
|
||||||
|
constexpr auto get_base_char = [](T val) { return ((val < 10) ? '0' : 'A' - 10) + val; };
|
||||||
|
|
||||||
|
char buffer[32];
|
||||||
|
char* ptr = buffer + sizeof(buffer);
|
||||||
|
*--ptr = '\0';
|
||||||
|
do { *--ptr = get_base_char(val % base); val /= base; } while (val);
|
||||||
|
print(fd, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(const char* s1, const char* s2);
|
||||||
|
char* strcpy(char* __restrict s1, const char* __restrict s2);
|
||||||
|
void* memcpy(void* __restrict s1, const void* __restrict s2, size_t n);
|
||||||
|
|
||||||
|
void init_random();
|
||||||
|
void fini_random();
|
||||||
|
uintptr_t get_random_uptr();
|
|
@ -499,6 +499,7 @@ BAN::Optional<int> execute_builtin(BAN::Vector<BAN::String>& args, int fd_in, in
|
||||||
TEST("ffffffffffffffff", 16);
|
TEST("ffffffffffffffff", 16);
|
||||||
TEST("10000000000000000", 16);
|
TEST("10000000000000000", 16);
|
||||||
#undef TEST
|
#undef TEST
|
||||||
|
#if __enable_sse
|
||||||
#define TEST(num) do { errno = 0; printf("strtod(\"" num "\", nullptr) = %e ", strtod(num, nullptr)); puts(errno ? strerrorname_np(errno) : ""); } while (false)
|
#define TEST(num) do { errno = 0; printf("strtod(\"" num "\", nullptr) = %e ", strtod(num, nullptr)); puts(errno ? strerrorname_np(errno) : ""); } while (false)
|
||||||
TEST("0");
|
TEST("0");
|
||||||
TEST(".1");
|
TEST(".1");
|
||||||
|
@ -531,6 +532,7 @@ BAN::Optional<int> execute_builtin(BAN::Vector<BAN::String>& args, int fd_in, in
|
||||||
TEST("-inf");
|
TEST("-inf");
|
||||||
TEST("nan");
|
TEST("nan");
|
||||||
#undef TEST
|
#undef TEST
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ set(SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(Terminal ${SOURCES})
|
add_executable(Terminal ${SOURCES})
|
||||||
banan_include_headers(Terminal ban)
|
banan_link_library(Terminal ban)
|
||||||
banan_link_library(Terminal libc)
|
banan_link_library(Terminal libc)
|
||||||
banan_link_library(Terminal libfont)
|
banan_link_library(Terminal libfont)
|
||||||
banan_link_library(Terminal libgui)
|
banan_link_library(Terminal libgui)
|
||||||
|
|
|
@ -6,8 +6,8 @@ set(SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(WindowServer ${SOURCES})
|
add_executable(WindowServer ${SOURCES})
|
||||||
banan_include_headers(WindowServer ban)
|
|
||||||
banan_include_headers(WindowServer libgui)
|
banan_include_headers(WindowServer libgui)
|
||||||
|
banan_link_library(WindowServer ban)
|
||||||
banan_link_library(WindowServer libc)
|
banan_link_library(WindowServer libc)
|
||||||
banan_link_library(WindowServer libfont)
|
banan_link_library(WindowServer libfont)
|
||||||
banan_link_library(WindowServer libimage)
|
banan_link_library(WindowServer libimage)
|
||||||
|
|
|
@ -4,6 +4,8 @@ set(SOURCES
|
||||||
|
|
||||||
add_executable(init ${SOURCES})
|
add_executable(init ${SOURCES})
|
||||||
banan_include_headers(init ban)
|
banan_include_headers(init ban)
|
||||||
banan_link_library(init libc)
|
banan_link_library(init libc-static)
|
||||||
|
|
||||||
|
target_link_options(init PRIVATE -static-libgcc)
|
||||||
|
|
||||||
install(TARGETS init OPTIONAL)
|
install(TARGETS init OPTIONAL)
|
||||||
|
|
|
@ -21,4 +21,9 @@ foreach(project ${USERSPACE_TESTS})
|
||||||
target_link_options(${project} PRIVATE -nolibc)
|
target_link_options(${project} PRIVATE -nolibc)
|
||||||
# Default compile options
|
# Default compile options
|
||||||
target_compile_options(${project} PRIVATE -g -O2)
|
target_compile_options(${project} PRIVATE -g -O2)
|
||||||
|
|
||||||
|
target_compile_definitions(${project} PRIVATE __enable_sse=${BANAN_ENABLE_SSE})
|
||||||
|
if (NOT BANAN_ENABLE_SSE)
|
||||||
|
target_compile_options(${project} PRIVATE -mno-sse -mno-sse2)
|
||||||
|
endif ()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
printf("printf works!\n");
|
printf("printf works\n");
|
||||||
|
fprintf(stdout, "fprintf(stdout) works!\n");
|
||||||
|
|
||||||
|
errno = ENOTSUP;
|
||||||
|
perror(nullptr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue