Compare commits
18 Commits
9c8fbc72ac
...
10cf618834
| Author | SHA1 | Date | |
|---|---|---|---|
| 10cf618834 | |||
| 06760906b9 | |||
| 95bb04e866 | |||
| f1e71cafc4 | |||
| 75bd11d5cc | |||
| efad96ce63 | |||
| 1e6748b4fc | |||
| ff66c8d89f | |||
| ba455059ac | |||
| 9cc60cf3f1 | |||
| 281a3d5801 | |||
| ba8d6908fa | |||
| c426afce67 | |||
| f5daf972a8 | |||
| 2e6d7df38c | |||
| 0e562f6a79 | |||
| 3d28ed2cb8 | |||
| 0ca0bb39ca |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -185,7 +185,6 @@ dist/
|
|||||||
downloads/
|
downloads/
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
lib/
|
|
||||||
lib64/
|
lib64/
|
||||||
parts/
|
parts/
|
||||||
sdist/
|
sdist/
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(Rosetta C CXX ASM)
|
project(Rosetta C CXX ASM)
|
||||||
|
|
||||||
|
set(sys_dir ${CMAKE_CURRENT_BINARY_DIR}/sys)
|
||||||
|
|
||||||
set(kernel_name mango_kernel)
|
set(kernel_name mango_kernel)
|
||||||
set(bsp_name rosetta-system.bsp)
|
set(bsp_name rosetta-system.bsp)
|
||||||
|
|
||||||
@@ -15,16 +17,21 @@ bsp_reset()
|
|||||||
sysroot_reset()
|
sysroot_reset()
|
||||||
|
|
||||||
add_subdirectory(kernel)
|
add_subdirectory(kernel)
|
||||||
add_subdirectory(lib)
|
|
||||||
add_subdirectory(programs)
|
|
||||||
add_subdirectory(sys)
|
add_subdirectory(sys)
|
||||||
|
add_subdirectory(lib)
|
||||||
|
add_subdirectory(services)
|
||||||
|
add_subdirectory(programs)
|
||||||
|
|
||||||
sysroot_add_program(NAME ${kernel_name} BIN_DIR /boot)
|
sysroot_add_program(NAME ${kernel_name} BIN_DIR /boot)
|
||||||
|
|
||||||
bsp_finalise(BSP_NAME ${bsp_name})
|
bsp_finalise(
|
||||||
|
BSP_NAME ${bsp_name}
|
||||||
|
DEST_DIR ${sys_dir}
|
||||||
|
BOOTSTRAP_PROGRAM bootstrap)
|
||||||
|
|
||||||
sysroot_add_file(
|
sysroot_add_file(
|
||||||
ID bsp
|
ID bsp
|
||||||
SRC_PATH ${CMAKE_BINARY_DIR}/${bsp_name}
|
SRC_PATH ${CMAKE_BINARY_DIR}/sys/${bsp_name}
|
||||||
DEST_DIR /boot
|
DEST_DIR /boot
|
||||||
DEPENDS ${CMAKE_BINARY_DIR}/${bsp_name})
|
DEPENDS bsp)
|
||||||
sysroot_finalise()
|
sysroot_finalise()
|
||||||
|
|||||||
@@ -7,8 +7,15 @@ find_program(C_COMPILER x86_64-elf-gcc REQUIRED)
|
|||||||
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
||||||
find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
||||||
|
|
||||||
|
add_compile_definitions(__mango__=1)
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER ${C_COMPILER})
|
set(CMAKE_C_COMPILER ${C_COMPILER})
|
||||||
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})
|
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})
|
||||||
set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
|
set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
|
||||||
|
|
||||||
SET(CMAKE_C_FLAGS "-ffreestanding -nostdlib" CACHE STRING "" FORCE)
|
SET(CMAKE_C_FLAGS "-ffreestanding -nostdlib -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234" CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-shared" CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--dynamic-linker=/lib/ld64.so" CACHE STRING "" FORCE)
|
||||||
|
|
||||||
|
set(CMAKE_C_OUTPUT_EXTENSION .o)
|
||||||
|
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
||||||
|
|||||||
@@ -1,5 +1,24 @@
|
|||||||
find_program(QEMU qemu-system-${TARGET_ARCH} REQUIRED)
|
find_program(QEMU qemu-system-${TARGET_ARCH} REQUIRED)
|
||||||
|
find_program(LLDB lldb REQUIRED)
|
||||||
|
|
||||||
add_custom_target(run-kernel
|
add_custom_target(run-kernel
|
||||||
COMMAND ${QEMU} -kernel $<TARGET_FILE:${kernel_name}>
|
COMMAND
|
||||||
DEPENDS ${kernel_name} ${bsp_name})
|
${QEMU}
|
||||||
|
-kernel $<TARGET_FILE:${kernel_name}>
|
||||||
|
-initrd ${sys_dir}/${bsp_name}
|
||||||
|
-m 1G -serial stdio
|
||||||
|
--append kernel.early-console=ttyS0
|
||||||
|
USES_TERMINAL
|
||||||
|
DEPENDS ${kernel_name} bsp)
|
||||||
|
|
||||||
|
add_custom_target(debug-kernel
|
||||||
|
COMMAND
|
||||||
|
${QEMU}
|
||||||
|
-kernel $<TARGET_FILE:${kernel_name}>
|
||||||
|
-initrd ${sys_dir}/${bsp_name}
|
||||||
|
-m 1G -s -S &
|
||||||
|
${LLDB}
|
||||||
|
-o "file ${CMAKE_BINARY_DIR}/kernel/${kernel_name}.debug"
|
||||||
|
-o "gdb-remote localhost:1234"
|
||||||
|
USES_TERMINAL
|
||||||
|
DEPENDS ${kernel_name} bsp)
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ function(bsp_add_library)
|
|||||||
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
||||||
add-binary ${bsp_manifest} ${target_name}
|
add-binary ${bsp_manifest} ${target_name}
|
||||||
${arg_LIB_DIR} $<TARGET_FILE:${target_name}>
|
${arg_LIB_DIR} $<TARGET_FILE:${target_name}>
|
||||||
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
|
||||||
add-headers ${bsp_manifest} ${target_name}
|
|
||||||
${arg_HEADER_DIR} ${header_dirs}
|
|
||||||
COMMENT "Preparing bsp component: ${target_name}"
|
COMMENT "Preparing bsp component: ${target_name}"
|
||||||
DEPENDS ${target_name} ${serialiser})
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
|
||||||
@@ -75,7 +72,7 @@ endfunction(bsp_add_program)
|
|||||||
|
|
||||||
function(bsp_finalise)
|
function(bsp_finalise)
|
||||||
set(options)
|
set(options)
|
||||||
set(one_value_args BSP_NAME)
|
set(one_value_args BOOTSTRAP_PROGRAM DEST_DIR BSP_NAME)
|
||||||
set(multi_value_args)
|
set(multi_value_args)
|
||||||
|
|
||||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
@@ -83,13 +80,12 @@ function(bsp_finalise)
|
|||||||
"${one_value_args}"
|
"${one_value_args}"
|
||||||
"${multi_value_args}")
|
"${multi_value_args}")
|
||||||
|
|
||||||
set(bsp_output_path ${CMAKE_CURRENT_BINARY_DIR}/${arg_BSP_NAME})
|
set(bsp_output_path ${arg_DEST_DIR}/${arg_BSP_NAME})
|
||||||
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
|
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
|
||||||
add_custom_command(OUTPUT ${bsp_output_path}
|
|
||||||
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
|
||||||
build-bsp ${bsp_manifest} ${bsp_output_path}
|
|
||||||
DEPENDS ${bsp_targets}
|
|
||||||
COMMENT "Building bsp: ${arg_BSP_NAME}")
|
|
||||||
add_custom_target(bsp
|
add_custom_target(bsp
|
||||||
DEPENDS ${bsp_output_path})
|
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
|
||||||
|
build-bsp ${bsp_manifest}
|
||||||
|
$<TARGET_FILE:${arg_BOOTSTRAP_PROGRAM}> ${bsp_output_path}
|
||||||
|
DEPENDS ${bsp_targets} ${arg_BOOTSTRAP_PROGRAM}
|
||||||
|
COMMENT "Building bsp: ${arg_BSP_NAME}")
|
||||||
endfunction(bsp_finalise)
|
endfunction(bsp_finalise)
|
||||||
|
|||||||
@@ -30,19 +30,74 @@ function(sysroot_add_library)
|
|||||||
list(GET sysroot_targets ${serialiser_index} serialiser)
|
list(GET sysroot_targets ${serialiser_index} serialiser)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_custom_target(${sysroot_target_name}
|
if (arg_HEADER_DIR)
|
||||||
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
add_custom_target(${sysroot_target_name}
|
||||||
add-binary ${sysroot_manifest} ${target_name}
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
${arg_LIB_DIR} $<TARGET_FILE:${target_name}>
|
add-binary ${sysroot_manifest} ${target_name}
|
||||||
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
${arg_LIB_DIR} $<TARGET_FILE:${target_name}>
|
||||||
add-headers ${sysroot_manifest} ${target_name}
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
${arg_HEADER_DIR} ${header_dirs}
|
add-headers ${sysroot_manifest} ${target_name}
|
||||||
COMMENT "Preparing sysroot component: ${target_name}"
|
${arg_HEADER_DIR} ${header_dirs}
|
||||||
DEPENDS ${target_name} ${serialiser})
|
COMMENT "Preparing sysroot component: ${target_name}"
|
||||||
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
else()
|
||||||
|
add_custom_target(${sysroot_target_name}
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
|
add-binary ${sysroot_manifest} ${target_name}
|
||||||
|
${arg_LIB_DIR} $<TARGET_FILE:${target_name}>
|
||||||
|
COMMENT "Preparing sysroot component: ${target_name}"
|
||||||
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
endif ()
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
|
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
|
||||||
endfunction(sysroot_add_library)
|
endfunction(sysroot_add_library)
|
||||||
|
|
||||||
|
function(sysroot_add_object_library)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME HEADER_DIR LIB_DIR)
|
||||||
|
set(multi_value_args)
|
||||||
|
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(target_name ${arg_NAME})
|
||||||
|
set(sysroot_target_name _sysroot-${target_name})
|
||||||
|
meta_target_get_header_directories(TARGET ${target_name} OUT header_dirs)
|
||||||
|
|
||||||
|
get_property(sysroot_targets GLOBAL PROPERTY sysroot_target_list)
|
||||||
|
list(LENGTH sysroot_targets nr_sysroot_targets)
|
||||||
|
if (${nr_sysroot_targets} GREATER 0)
|
||||||
|
math(EXPR serialiser_index "${nr_sysroot_targets}-1")
|
||||||
|
list(GET sysroot_targets ${serialiser_index} serialiser)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (arg_HEADER_DIR)
|
||||||
|
add_custom_target(${sysroot_target_name}
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
|
add-binary ${sysroot_manifest} ${target_name}
|
||||||
|
${arg_LIB_DIR} $<TARGET_OBJECTS:${target_name}>
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
|
add-headers ${sysroot_manifest} ${target_name}
|
||||||
|
${arg_HEADER_DIR} ${header_dirs}
|
||||||
|
COMMENT "Preparing sysroot component: ${target_name}"
|
||||||
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
else()
|
||||||
|
add_custom_target(${sysroot_target_name}
|
||||||
|
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
|
||||||
|
add-binary ${sysroot_manifest} ${target_name}
|
||||||
|
${arg_LIB_DIR} $<TARGET_OBJECTS:${target_name}>
|
||||||
|
COMMENT "Preparing sysroot component: ${target_name}"
|
||||||
|
DEPENDS ${target_name} ${serialiser})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
get_property(tmp TARGET ${target_name} PROPERTY SUFFIX)
|
||||||
|
message(STATUS ${tmp})
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY sysroot_target_list ${sysroot_targets} ${sysroot_target_name})
|
||||||
|
endfunction(sysroot_add_object_library)
|
||||||
|
|
||||||
function(sysroot_add_program)
|
function(sysroot_add_program)
|
||||||
set(options)
|
set(options)
|
||||||
set(one_value_args NAME BIN_DIR)
|
set(one_value_args NAME BIN_DIR)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function(rosetta_add_executable)
|
function(rosetta_add_executable)
|
||||||
set(options)
|
set(options)
|
||||||
set(one_value_args NAME SYSROOT_PATH)
|
set(one_value_args NAME)
|
||||||
set(multi_value_args
|
set(multi_value_args
|
||||||
SUBDIRS
|
SUBDIRS
|
||||||
EXTRA_SOURCES)
|
EXTRA_SOURCES)
|
||||||
@@ -33,11 +33,77 @@ function(rosetta_add_executable)
|
|||||||
endfunction(rosetta_add_executable)
|
endfunction(rosetta_add_executable)
|
||||||
|
|
||||||
function(rosetta_add_library)
|
function(rosetta_add_library)
|
||||||
set(options SHARED)
|
set(options STATIC SHARED)
|
||||||
set(one_value_args NAME SYSROOT_PATH)
|
set(one_value_args NAME)
|
||||||
set(multi_value_args
|
set(multi_value_args
|
||||||
SOURCE_DIRS
|
PUBLIC_INCLUDE_DIRS
|
||||||
EXTRA_SOURCES)
|
SOURCES
|
||||||
|
HEADERS)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(lib_name ${arg_NAME})
|
||||||
|
set(targets)
|
||||||
|
|
||||||
|
if ((NOT ${arg_STATIC}) AND (NOT ${arg_SHARED}))
|
||||||
|
message(FATAL_ERROR "rosetta_add_library(${arg_NAME}): must specified SHARED and/or STATIC")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(static_lib_name ${lib_name})
|
||||||
|
set(shared_lib_name ${lib_name})
|
||||||
|
|
||||||
|
if (${arg_STATIC} AND ${arg_SHARED})
|
||||||
|
set(static_lib_name ${lib_name}-static)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
message(STATUS "Building library ${lib_name}")
|
||||||
|
if (${arg_STATIC})
|
||||||
|
add_library(${static_lib_name} STATIC
|
||||||
|
${arg_SOURCES}
|
||||||
|
${arg_HEADERS})
|
||||||
|
set(targets ${targets} ${static_lib_name})
|
||||||
|
|
||||||
|
if (arg_PUBLIC_INCLUDE_DIRS)
|
||||||
|
meta_target_add_header_directory(
|
||||||
|
TARGET ${static_lib_name}
|
||||||
|
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
|
endif ()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (${arg_SHARED})
|
||||||
|
add_library(${shared_lib_name} SHARED
|
||||||
|
${arg_SOURCES}
|
||||||
|
${arg_HEADERS})
|
||||||
|
set(targets ${targets} ${shared_lib_name})
|
||||||
|
set(soname ${shared_lib_name}.so)
|
||||||
|
|
||||||
|
if (arg_PUBLIC_INCLUDE_DIRS)
|
||||||
|
meta_target_add_header_directory(
|
||||||
|
TARGET ${shared_lib_name}
|
||||||
|
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set_target_properties(${shared_lib_name} PROPERTIES
|
||||||
|
SOVERSION 1)
|
||||||
|
target_link_options(${shared_lib_name} PRIVATE -Wl,--soname,${soname})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(${targets} PUBLIC ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
|
set_target_properties(${targets} PROPERTIES
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
src_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
PREFIX "")
|
||||||
|
endfunction(rosetta_add_library)
|
||||||
|
|
||||||
|
function(rosetta_add_object_library)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME)
|
||||||
|
set(multi_value_args
|
||||||
|
PUBLIC_INCLUDE_DIRS
|
||||||
|
SOURCES
|
||||||
|
HEADERS)
|
||||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
"${options}"
|
"${options}"
|
||||||
"${one_value_args}"
|
"${one_value_args}"
|
||||||
@@ -45,36 +111,70 @@ function(rosetta_add_library)
|
|||||||
|
|
||||||
set(lib_name ${arg_NAME})
|
set(lib_name ${arg_NAME})
|
||||||
|
|
||||||
get_property(libs GLOBAL PROPERTY rosetta_library_list)
|
|
||||||
set_property(GLOBAL PROPERTY rosetta_library_list ${libs} ${lib_name})
|
|
||||||
|
|
||||||
file(GLOB sources *.c *.h)
|
|
||||||
file(GLOB_RECURSE headers include/*.h)
|
|
||||||
|
|
||||||
foreach (dir ${arg_SOURCE_DIRS})
|
|
||||||
file(GLOB dir_sources ${dir}/*.c ${dir}/*.h)
|
|
||||||
set(sources ${sources} ${dir_sources})
|
|
||||||
endforeach (dir)
|
|
||||||
|
|
||||||
message(STATUS "Building library ${lib_name}")
|
message(STATUS "Building library ${lib_name}")
|
||||||
if (arg_SHARED)
|
add_library(${lib_name} OBJECT
|
||||||
add_library(${lib_name} SHARED
|
${arg_SOURCES}
|
||||||
${sources}
|
${arg_HEADERS})
|
||||||
${headers}
|
|
||||||
${arg_EXTRA_SOURCES})
|
|
||||||
else ()
|
|
||||||
add_library(${lib_name} STATIC
|
|
||||||
${sources}
|
|
||||||
${headers}
|
|
||||||
${arg_EXTRA_SOURCES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_include_directories(${lib_name} PUBLIC
|
target_include_directories(${lib_name} PUBLIC ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
||||||
set_target_properties(${lib_name} PROPERTIES
|
set_target_properties(${lib_name} PROPERTIES
|
||||||
POSITION_INDEPENDENT_CODE ON
|
POSITION_INDEPENDENT_CODE ON
|
||||||
src_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/include
|
src_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
sys_header_dir ${arg_SYSROOT_PATH}/include
|
|
||||||
sys_bin_dir ${arg_SYSROOT_PATH}/lib
|
|
||||||
PREFIX "")
|
PREFIX "")
|
||||||
endfunction(rosetta_add_library)
|
endfunction(rosetta_add_object_library)
|
||||||
|
|
||||||
|
function(rosetta_wrap_library)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME)
|
||||||
|
set(multi_value_args
|
||||||
|
PUBLIC_INCLUDE_DIRS)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(lib_name ${arg_NAME})
|
||||||
|
|
||||||
|
message(STATUS "Building library ${lib_name}")
|
||||||
|
|
||||||
|
if (arg_PUBLIC_INCLUDE_DIRS)
|
||||||
|
meta_target_add_header_directory(
|
||||||
|
TARGET ${lib_name}
|
||||||
|
PATH ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set_target_properties(${lib_name} PROPERTIES
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
src_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
PREFIX "")
|
||||||
|
endfunction(rosetta_wrap_library)
|
||||||
|
|
||||||
|
function(rosetta_add_object_library)
|
||||||
|
set(options)
|
||||||
|
set(one_value_args NAME)
|
||||||
|
set(multi_value_args
|
||||||
|
PUBLIC_INCLUDE_DIRS
|
||||||
|
SOURCES
|
||||||
|
HEADERS)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||||
|
"${options}"
|
||||||
|
"${one_value_args}"
|
||||||
|
"${multi_value_args}")
|
||||||
|
|
||||||
|
set(lib_name ${arg_NAME})
|
||||||
|
|
||||||
|
message(STATUS "Building library ${lib_name}")
|
||||||
|
add_library(${lib_name} OBJECT
|
||||||
|
${arg_SOURCES}
|
||||||
|
${arg_HEADERS})
|
||||||
|
#add_library(${lib_name} STATIC
|
||||||
|
# ${sources}
|
||||||
|
# ${headers}
|
||||||
|
# ${arg_EXTRA_SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(${lib_name} PUBLIC ${arg_PUBLIC_INCLUDE_DIRS})
|
||||||
|
set_target_properties(${lib_name} PROPERTIES
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
src_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
|
PREFIX "")
|
||||||
|
endfunction(rosetta_add_object_library)
|
||||||
|
|||||||
2
kernel
2
kernel
Submodule kernel updated: af0d97d6f5...9a90662eaa
26
lib/CMakeLists.txt
Normal file
26
lib/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
file(GLOB items *)
|
||||||
|
|
||||||
|
add_subdirectory(
|
||||||
|
${CMAKE_SOURCE_DIR}/kernel/libmango
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/libmango)
|
||||||
|
|
||||||
|
rosetta_wrap_library(
|
||||||
|
NAME libmango
|
||||||
|
PUBLIC_INCLUDE_DIRS
|
||||||
|
${CMAKE_SOURCE_DIR}/kernel/libmango/include
|
||||||
|
${CMAKE_SOURCE_DIR}/kernel/libmango/include-user
|
||||||
|
SOURCES ${asm_sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libmango
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
foreach(item ${items})
|
||||||
|
if (NOT IS_DIRECTORY ${item})
|
||||||
|
continue()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_subdirectory(${item})
|
||||||
|
endforeach (item)
|
||||||
36
lib/libc/CMakeLists.txt
Normal file
36
lib/libc/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
set(source_dirs string stdio)
|
||||||
|
foreach (dir ${source_dirs})
|
||||||
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
|
file(GLOB dir_headers ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.h)
|
||||||
|
|
||||||
|
set(sources ${sources} ${dir_sources})
|
||||||
|
set(headers ${headers} ${dir_headers})
|
||||||
|
endforeach (dir)
|
||||||
|
|
||||||
|
file(GLOB runtime_sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/runtime/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
||||||
|
set_property(SOURCE ${runtime_sources} PROPERTY LANGUAGE C)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(SHARED
|
||||||
|
NAME libc
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
rosetta_add_object_library(
|
||||||
|
NAME libc-rt STATIC
|
||||||
|
SOURCES ${runtime_sources})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libc
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
sysroot_add_object_library(
|
||||||
|
NAME libc-rt
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
bsp_add_library(
|
||||||
|
NAME libc
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
22
lib/libc/include/stdio.h
Normal file
22
lib/libc/include/stdio.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef STDIO_H_
|
||||||
|
#define STDIO_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int snprintf(char *buffer, size_t count, const char *format, ...);
|
||||||
|
extern int vsnprintf(
|
||||||
|
char *buffer,
|
||||||
|
size_t count,
|
||||||
|
const char *format,
|
||||||
|
va_list va);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
14
lib/libc/include/string.h
Normal file
14
lib/libc/include/string.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef STRING_H_
|
||||||
|
#define STRING_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern size_t strlen(const char *s);
|
||||||
|
|
||||||
|
extern int strcmp(const char *s1, const char *s2);
|
||||||
|
extern int strncmp(const char *s1, const char *s2, unsigned long n);
|
||||||
|
|
||||||
|
extern void *memset(void *str, int c, size_t n);
|
||||||
|
extern void *memcpy(void *dst, const void *src, size_t len);
|
||||||
|
|
||||||
|
#endif
|
||||||
16
lib/libc/runtime/x86_64/crt0.s
Normal file
16
lib/libc/runtime/x86_64/crt0.s
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
.code64
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
|
||||||
|
.extern main
|
||||||
|
.type main, @function
|
||||||
|
|
||||||
|
_start:
|
||||||
|
# Args (as provided by the ABI)
|
||||||
|
# %rdi: int argc
|
||||||
|
# %rsi: const char **argv
|
||||||
|
# %rdx: kern_handle_t task
|
||||||
|
# %rcx: kern_handle_t address_space
|
||||||
|
call main
|
||||||
|
1: jmp 1b
|
||||||
1215
lib/libc/stdio/printf.c
Normal file
1215
lib/libc/stdio/printf.c
Normal file
File diff suppressed because it is too large
Load Diff
107
lib/libc/string/memcpy.c
Normal file
107
lib/libc/string/memcpy.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Chris Torek.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uintptr_t word;
|
||||||
|
#define wsize sizeof(word)
|
||||||
|
#define wmask (wsize - 1)
|
||||||
|
|
||||||
|
void *memcpy(void *dst0, const void *src0, size_t length)
|
||||||
|
{
|
||||||
|
char *dst = dst0;
|
||||||
|
const char *src = src0;
|
||||||
|
size_t t;
|
||||||
|
|
||||||
|
if (length == 0 || dst == src) /* nothing to do */
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros: loop-t-times; and loop-t-times, t>0
|
||||||
|
*/
|
||||||
|
#define TLOOP(s) \
|
||||||
|
if (t) \
|
||||||
|
TLOOP1(s)
|
||||||
|
#define TLOOP1(s) \
|
||||||
|
do { \
|
||||||
|
s; \
|
||||||
|
} while (--t)
|
||||||
|
|
||||||
|
if ((uintptr_t)dst < (uintptr_t)src) {
|
||||||
|
/*
|
||||||
|
* Copy forward.
|
||||||
|
*/
|
||||||
|
t = (uintptr_t)src; /* only need low bits */
|
||||||
|
if ((t | (uintptr_t)dst) & wmask) {
|
||||||
|
/*
|
||||||
|
* Try to align operands. This cannot be done
|
||||||
|
* unless the low bits match.
|
||||||
|
*/
|
||||||
|
if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
|
||||||
|
t = length;
|
||||||
|
else
|
||||||
|
t = wsize - (t & wmask);
|
||||||
|
length -= t;
|
||||||
|
TLOOP1(*dst++ = *src++);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Copy whole words, then mop up any trailing bytes.
|
||||||
|
*/
|
||||||
|
t = length / wsize;
|
||||||
|
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
|
||||||
|
t = length & wmask;
|
||||||
|
TLOOP(*dst++ = *src++);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Copy backwards. Otherwise essentially the same.
|
||||||
|
* Alignment works as before, except that it takes
|
||||||
|
* (t&wmask) bytes to align, not wsize-(t&wmask).
|
||||||
|
*/
|
||||||
|
src += length;
|
||||||
|
dst += length;
|
||||||
|
t = (uintptr_t)src;
|
||||||
|
if ((t | (uintptr_t)dst) & wmask) {
|
||||||
|
if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
|
||||||
|
t = length;
|
||||||
|
else
|
||||||
|
t &= wmask;
|
||||||
|
length -= t;
|
||||||
|
TLOOP1(*--dst = *--src);
|
||||||
|
}
|
||||||
|
t = length / wsize;
|
||||||
|
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
|
||||||
|
t = length & wmask;
|
||||||
|
TLOOP(*--dst = *--src);
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return (dst0);
|
||||||
|
}
|
||||||
13
lib/libc/string/memset.c
Normal file
13
lib/libc/string/memset.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void *memset(void *str, int c, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char val = (unsigned char)c;
|
||||||
|
unsigned char *buf = str;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
buf[i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
21
lib/libc/string/strcmp.c
Normal file
21
lib/libc/string/strcmp.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
int strcmp(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; s1[i] == s2[i]; i++)
|
||||||
|
if (s1[i] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return s1[i] - s2[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int strncmp(const char *s1, const char *s2, unsigned long n)
|
||||||
|
{
|
||||||
|
for (; n > 0; s1++, s2++, --n)
|
||||||
|
if (*s1 != *s2)
|
||||||
|
return ((*(unsigned char *)s1 < *(unsigned char *)s2)
|
||||||
|
? -1
|
||||||
|
: 1);
|
||||||
|
else if (*s1 == '\0')
|
||||||
|
return 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
11
lib/libc/string/strlen.c
Normal file
11
lib/libc/string/strlen.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
size_t strlen(const char *str)
|
||||||
|
{
|
||||||
|
size_t res = 0;
|
||||||
|
while (str[res]) {
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
21
lib/liblaunch/CMakeLists.txt
Normal file
21
lib/liblaunch/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
|
file(GLOB headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/launch.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME liblaunch STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME liblaunch
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(liblaunch libmango ulibc)
|
||||||
547
lib/liblaunch/elf.c
Normal file
547
lib/liblaunch/elf.c
Normal file
@@ -0,0 +1,547 @@
|
|||||||
|
#include "elf.h"
|
||||||
|
|
||||||
|
#include <mango/config.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||||
|
|
||||||
|
#define NEEDS_NOTHING 0
|
||||||
|
#define NEEDS_VDSO 1
|
||||||
|
#define NEEDS_MORE 2
|
||||||
|
|
||||||
|
#define ACL (PF_R | PF_W | PF_X)
|
||||||
|
#define ACCESS(x) ((x) & ACL)
|
||||||
|
|
||||||
|
/* TODO in case we ever support ELF32 images */
|
||||||
|
#define elf_class_bits(x) (64)
|
||||||
|
|
||||||
|
#define PAGE_SIZE (page_size())
|
||||||
|
#define PAGE_MASK (page_size() - 1)
|
||||||
|
#define PAGE_OFFSET(v) ((v) & (PAGE_SIZE - 1))
|
||||||
|
#define PAGE_ALIGN_DOWN(v) (v) &= ~(PAGE_SIZE - 1)
|
||||||
|
#define PAGE_ALIGN_UP(v) \
|
||||||
|
do { \
|
||||||
|
if ((v) & (PAGE_SIZE - 1)) { \
|
||||||
|
v &= ~(PAGE_SIZE - 1); \
|
||||||
|
v += PAGE_SIZE; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#undef DEBUG_LOG
|
||||||
|
|
||||||
|
static size_t page_size(void)
|
||||||
|
{
|
||||||
|
static size_t pagesz = 0;
|
||||||
|
if (pagesz == 0) {
|
||||||
|
kern_config_get(KERN_CFG_PAGE_SIZE, &pagesz, sizeof pagesz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pagesz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status elf_validate_ehdr(elf_ehdr_t *hdr)
|
||||||
|
{
|
||||||
|
if (hdr->e_ident[EI_MAG0] != ELF_MAG0) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_ident[EI_MAG1] != ELF_MAG1) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_ident[EI_MAG2] != ELF_MAG2) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_ident[EI_MAG3] != ELF_MAG3) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||||
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_machine != EM_X86_64) {
|
||||||
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||||
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->e_ident[EI_VERSION] != EV_CURRENT) {
|
||||||
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status read_header(struct elf_image *image)
|
||||||
|
{
|
||||||
|
size_t nr_read = 0;
|
||||||
|
vm_object_read(
|
||||||
|
image->e_image,
|
||||||
|
&image->e_hdr,
|
||||||
|
0,
|
||||||
|
sizeof image->e_hdr,
|
||||||
|
&nr_read);
|
||||||
|
if (nr_read != sizeof image->e_hdr) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return elf_validate_ehdr(&image->e_hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status parse_phdr(struct elf_image *image)
|
||||||
|
{
|
||||||
|
elf_phdr_t phdr;
|
||||||
|
size_t r = 0;
|
||||||
|
image->e_total_size = 0;
|
||||||
|
image->e_data_size = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < image->e_hdr.e_phnum; i++) {
|
||||||
|
off_t offset
|
||||||
|
= image->e_hdr.e_phoff + (i * image->e_hdr.e_phentsize);
|
||||||
|
kern_status_t status = vm_object_read(
|
||||||
|
image->e_image,
|
||||||
|
&phdr,
|
||||||
|
offset,
|
||||||
|
sizeof phdr,
|
||||||
|
&r);
|
||||||
|
|
||||||
|
if (status != KERN_OK || r != sizeof phdr) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (phdr.p_type) {
|
||||||
|
case PT_DYNAMIC:
|
||||||
|
image->e_dynamic = phdr;
|
||||||
|
break;
|
||||||
|
case PT_LOAD:
|
||||||
|
if (phdr.p_vaddr & (PAGE_SIZE - 1)) {
|
||||||
|
phdr.p_vaddr &= (PAGE_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phdr.p_memsz & (PAGE_SIZE - 1)) {
|
||||||
|
phdr.p_memsz &= (PAGE_SIZE - 1);
|
||||||
|
phdr.p_memsz += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->e_total_size
|
||||||
|
= MAX(image->e_total_size,
|
||||||
|
phdr.p_vaddr + phdr.p_memsz);
|
||||||
|
break;
|
||||||
|
case PT_INTERP: {
|
||||||
|
size_t r = 0;
|
||||||
|
vm_object_read(
|
||||||
|
image->e_image,
|
||||||
|
image->e_interp,
|
||||||
|
phdr.p_offset,
|
||||||
|
MIN(sizeof image->e_interp - 1, phdr.p_filesz),
|
||||||
|
&r);
|
||||||
|
image->e_interp[r] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phdr.p_flags & PF_W) {
|
||||||
|
image->e_data_size
|
||||||
|
= MAX(image->e_data_size,
|
||||||
|
phdr.p_vaddr + phdr.p_memsz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t create_exec_regions(struct elf_image *image)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
if (image->e_local_space != KERN_HANDLE_INVALID) {
|
||||||
|
status = vm_region_create(
|
||||||
|
image->e_local_space,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
VM_REGION_ANY_OFFSET,
|
||||||
|
image->e_total_size,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC
|
||||||
|
| VM_PROT_USER,
|
||||||
|
&image->e_local_exec,
|
||||||
|
&image->e_local_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image->e_remote_space != KERN_HANDLE_INVALID) {
|
||||||
|
status = vm_region_create(
|
||||||
|
image->e_remote_space,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
VM_REGION_ANY_OFFSET,
|
||||||
|
image->e_total_size,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC
|
||||||
|
| VM_PROT_USER,
|
||||||
|
&image->e_remote_exec,
|
||||||
|
&image->e_remote_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
/* TODO cleanup e_local_exec */
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status map_executable(struct elf_image *image)
|
||||||
|
{
|
||||||
|
elf_phdr_t phdr;
|
||||||
|
size_t r = 0;
|
||||||
|
image->e_total_size = 0;
|
||||||
|
image->e_data_size = 0;
|
||||||
|
|
||||||
|
size_t data_offset = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < image->e_hdr.e_phnum; i++) {
|
||||||
|
off_t phdr_offset
|
||||||
|
= image->e_hdr.e_phoff + (i * image->e_hdr.e_phentsize);
|
||||||
|
kern_status_t status = vm_object_read(
|
||||||
|
image->e_image,
|
||||||
|
&phdr,
|
||||||
|
phdr_offset,
|
||||||
|
sizeof phdr,
|
||||||
|
&r);
|
||||||
|
|
||||||
|
if (status != KERN_OK || r != sizeof phdr) {
|
||||||
|
return LAUNCH_ERR_INVALID_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phdr.p_type != PT_LOAD) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t vmo = image->e_image;
|
||||||
|
vm_prot_t prot = VM_PROT_USER;
|
||||||
|
size_t offset = phdr.p_offset;
|
||||||
|
|
||||||
|
phdr.p_flags &PF_R && (prot |= VM_PROT_READ);
|
||||||
|
phdr.p_flags &PF_W && (prot |= VM_PROT_WRITE);
|
||||||
|
phdr.p_flags &PF_X && (prot |= VM_PROT_EXEC);
|
||||||
|
if (phdr.p_flags & PF_W) {
|
||||||
|
vmo = image->e_data;
|
||||||
|
offset = data_offset;
|
||||||
|
|
||||||
|
status = vm_object_copy(
|
||||||
|
image->e_data,
|
||||||
|
data_offset + (phdr.p_offset & PAGE_MASK),
|
||||||
|
image->e_image,
|
||||||
|
phdr.p_offset,
|
||||||
|
phdr.p_filesz,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return LAUNCH_ERR_IMAGE_DATA_LOAD_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image->e_local_exec != KERN_HANDLE_INVALID) {
|
||||||
|
status = vm_region_map_relative(
|
||||||
|
image->e_local_exec,
|
||||||
|
phdr.p_vaddr,
|
||||||
|
vmo,
|
||||||
|
offset,
|
||||||
|
phdr.p_memsz,
|
||||||
|
prot,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image->e_remote_exec != KERN_HANDLE_INVALID) {
|
||||||
|
status = vm_region_map_relative(
|
||||||
|
image->e_remote_exec,
|
||||||
|
phdr.p_vaddr,
|
||||||
|
vmo,
|
||||||
|
offset,
|
||||||
|
phdr.p_memsz,
|
||||||
|
prot,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phdr.p_flags & PF_W) {
|
||||||
|
data_offset += phdr.p_memsz;
|
||||||
|
if (data_offset & (PAGE_SIZE - 1)) {
|
||||||
|
data_offset &= (PAGE_SIZE - 1);
|
||||||
|
data_offset += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static elf_sym_t *get_dynsym(struct elf_image *image, size_t index)
|
||||||
|
{
|
||||||
|
return (elf_sym_t *)(image->e_local_base + image->e_dynsym
|
||||||
|
+ (index * image->e_dynsym_entsize));
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status do_rela(struct elf_image *image, elf_rela_t *rela)
|
||||||
|
{
|
||||||
|
int type = ELF64_R_TYPE(rela->r_info);
|
||||||
|
elf_sym_t *sym = NULL;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case R_X86_64_JUMP_SLOT:
|
||||||
|
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||||
|
*(uint64_t *)(image->e_local_base + rela->r_offset)
|
||||||
|
= image->e_remote_base + sym->st_value + rela->r_addend;
|
||||||
|
kern_tracef(
|
||||||
|
"JUMP_SLOT: offset=%zx, symbol=%zu, addend=%zx",
|
||||||
|
rela->r_offset,
|
||||||
|
ELF64_R_SYM(rela->r_info),
|
||||||
|
rela->r_addend);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kern_trace("Unknown relocation type");
|
||||||
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status do_rela_list(
|
||||||
|
struct elf_image *image,
|
||||||
|
off_t offset,
|
||||||
|
size_t size,
|
||||||
|
size_t entsize)
|
||||||
|
{
|
||||||
|
kern_tracef(
|
||||||
|
"do_rela_list(%p, %d, %d, %d)",
|
||||||
|
image,
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
entsize);
|
||||||
|
size_t entries = size / entsize;
|
||||||
|
elf_rela_t *rela = (elf_rela_t *)(image->e_local_base + offset);
|
||||||
|
enum launch_status status = LAUNCH_OK;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < entries; i++) {
|
||||||
|
status = do_rela(image, rela);
|
||||||
|
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rela = (elf_rela_t *)((char *)rela + entsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status do_rel(
|
||||||
|
struct elf_image *image,
|
||||||
|
off_t offset,
|
||||||
|
size_t size,
|
||||||
|
size_t entsize)
|
||||||
|
|
||||||
|
{
|
||||||
|
return LAUNCH_ERR_UNSUPPORTED_EXECUTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum launch_status relocate(struct elf_image *image)
|
||||||
|
{
|
||||||
|
elf_dyn_t *dyn
|
||||||
|
= (elf_dyn_t *)(image->e_local_base + image->e_dynamic.p_vaddr);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RT_REL,
|
||||||
|
RT_RELA,
|
||||||
|
RT_PLTREL,
|
||||||
|
RT_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
int pltrel_type = DT_NULL;
|
||||||
|
off_t offsets[RT_COUNT] = {0};
|
||||||
|
size_t sizes[RT_COUNT] = {0}, entsizes[RT_COUNT] = {0};
|
||||||
|
|
||||||
|
size_t nr_dyn = image->e_dynamic.p_filesz / sizeof *dyn;
|
||||||
|
for (size_t i = 0; i < nr_dyn; i++) {
|
||||||
|
switch (dyn[i].d_tag) {
|
||||||
|
case DT_SYMTAB:
|
||||||
|
image->e_dynsym = dyn[i].d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_SYMENT:
|
||||||
|
image->e_dynsym_entsize = dyn[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_REL:
|
||||||
|
offsets[RT_REL] = dyn[i].d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_RELSZ:
|
||||||
|
sizes[RT_REL] = dyn[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_RELENT:
|
||||||
|
entsizes[RT_REL] = dyn[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_RELA:
|
||||||
|
offsets[RT_RELA] = dyn[i].d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_RELASZ:
|
||||||
|
sizes[RT_RELA] = dyn[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_RELAENT:
|
||||||
|
entsizes[RT_RELA] = dyn[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
case DT_PLTREL:
|
||||||
|
pltrel_type = dyn[i].d_un.d_val;
|
||||||
|
switch (pltrel_type) {
|
||||||
|
case DT_REL:
|
||||||
|
entsizes[RT_PLTREL] = 0;
|
||||||
|
break;
|
||||||
|
case DT_RELA:
|
||||||
|
entsizes[RT_PLTREL] = sizeof(elf_rela_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_JMPREL:
|
||||||
|
offsets[RT_PLTREL] = dyn[i].d_un.d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_PLTRELSZ:
|
||||||
|
sizes[RT_PLTREL] = dyn[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dyn[i].d_tag == DT_NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum launch_status status = LAUNCH_OK;
|
||||||
|
if (offsets[RT_RELA] && sizes[RT_RELA] && entsizes[RT_RELA]) {
|
||||||
|
kern_trace("RELA");
|
||||||
|
status = do_rela_list(
|
||||||
|
image,
|
||||||
|
offsets[RT_RELA],
|
||||||
|
sizes[RT_RELA],
|
||||||
|
entsizes[RT_RELA]);
|
||||||
|
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offsets[RT_PLTREL] && entsizes[RT_PLTREL]) {
|
||||||
|
kern_trace("PLTREL");
|
||||||
|
if (pltrel_type == DT_REL) {
|
||||||
|
status = do_rel(
|
||||||
|
image,
|
||||||
|
offsets[RT_PLTREL],
|
||||||
|
sizes[RT_PLTREL],
|
||||||
|
entsizes[RT_PLTREL]);
|
||||||
|
} else {
|
||||||
|
status = do_rela_list(
|
||||||
|
image,
|
||||||
|
offsets[RT_PLTREL],
|
||||||
|
sizes[RT_PLTREL],
|
||||||
|
entsizes[RT_PLTREL]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void elf_image_init(struct elf_image *out)
|
||||||
|
{
|
||||||
|
memset(out, 0x0, sizeof(*out));
|
||||||
|
|
||||||
|
out->e_image = KERN_HANDLE_INVALID;
|
||||||
|
out->e_data = KERN_HANDLE_INVALID;
|
||||||
|
out->e_local_space = KERN_HANDLE_INVALID;
|
||||||
|
out->e_remote_space = KERN_HANDLE_INVALID;
|
||||||
|
out->e_local_exec = KERN_HANDLE_INVALID;
|
||||||
|
out->e_remote_exec = KERN_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum launch_status elf_image_load(
|
||||||
|
struct elf_image *image,
|
||||||
|
kern_handle_t exec_object,
|
||||||
|
kern_handle_t local_space,
|
||||||
|
kern_handle_t remote_space)
|
||||||
|
{
|
||||||
|
image->e_image = exec_object;
|
||||||
|
image->e_local_space = local_space;
|
||||||
|
image->e_remote_space = remote_space;
|
||||||
|
|
||||||
|
enum launch_status status = read_header(image);
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = parse_phdr(image);
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image->e_interp[0] != 0) {
|
||||||
|
return LAUNCH_ERR_INTERPRETER_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t kstatus = vm_object_create(
|
||||||
|
".data",
|
||||||
|
5,
|
||||||
|
image->e_data_size,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
|
&image->e_data);
|
||||||
|
if (kstatus != KERN_OK) {
|
||||||
|
return LAUNCH_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = create_exec_regions(image);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return LAUNCH_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = map_executable(image);
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = relocate(image);
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void elf_image_cleanup(struct elf_image *image)
|
||||||
|
{
|
||||||
|
vm_region_unmap_relative(image->e_local_exec, 0, image->e_total_size);
|
||||||
|
kern_handle_close(image->e_data);
|
||||||
|
kern_handle_close(image->e_local_exec);
|
||||||
|
kern_handle_close(image->e_remote_exec);
|
||||||
|
}
|
||||||
314
lib/liblaunch/elf.h
Normal file
314
lib/liblaunch/elf.h
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
#ifndef USERBOOT_ELF_H_
|
||||||
|
#define USERBOOT_ELF_H_
|
||||||
|
|
||||||
|
#include <launch.h>
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ELF_LOAD_ERR -1
|
||||||
|
#define ELF_LOADED_EXEC 0
|
||||||
|
#define ELF_LOADED_INTERP 1
|
||||||
|
|
||||||
|
#define ELF_MAG0 0x7f
|
||||||
|
#define ELF_MAG1 'E'
|
||||||
|
#define ELF_MAG2 'L'
|
||||||
|
#define ELF_MAG3 'F'
|
||||||
|
#define ELF_NIDENT 16
|
||||||
|
|
||||||
|
#define SHT_NONE 0
|
||||||
|
#define SHT_PROGBITS 1
|
||||||
|
#define SHT_SYMTAB 2
|
||||||
|
#define SHT_STRTAB 3
|
||||||
|
#define SHT_RELA 4
|
||||||
|
#define SHT_DYNAMIC 6
|
||||||
|
#define SHT_NOBITS 8
|
||||||
|
#define SHT_REL 9
|
||||||
|
#define SHT_DYNSYM 11
|
||||||
|
|
||||||
|
/** Little endian. */
|
||||||
|
#define ELFDATA2LSB (1)
|
||||||
|
|
||||||
|
/** 64-bit. */
|
||||||
|
#define ELFCLASS64 (2)
|
||||||
|
|
||||||
|
/** x86_64 machine type. */
|
||||||
|
#define EM_X86_64 (62)
|
||||||
|
|
||||||
|
/** ELF current version. */
|
||||||
|
#define EV_CURRENT (1)
|
||||||
|
|
||||||
|
/** Dynamic section tags. */
|
||||||
|
#define DT_NULL 0
|
||||||
|
#define DT_NEEDED 1
|
||||||
|
#define DT_PLTRELSZ 2
|
||||||
|
#define DT_PLTGOT 3
|
||||||
|
#define DT_HASH 4
|
||||||
|
#define DT_STRTAB 5
|
||||||
|
#define DT_SYMTAB 6
|
||||||
|
#define DT_RELA 7
|
||||||
|
#define DT_RELASZ 8
|
||||||
|
#define DT_RELAENT 9
|
||||||
|
#define DT_STRSZ 10
|
||||||
|
#define DT_SYMENT 11
|
||||||
|
#define DT_INIT 12
|
||||||
|
#define DT_FINI 13
|
||||||
|
#define DT_REL 17
|
||||||
|
#define DT_RELSZ 18
|
||||||
|
#define DT_RELENT 19
|
||||||
|
#define DT_PLTREL 20
|
||||||
|
#define DT_JMPREL 23
|
||||||
|
#define DT_GNU_HASH 0x6ffffef5
|
||||||
|
#define DT_AUXILIARY 0x7ffffffd
|
||||||
|
|
||||||
|
#define R_386_32 1
|
||||||
|
#define R_386_PC32 2
|
||||||
|
#define R_386_GOT32 3
|
||||||
|
#define R_386_PLT32 4
|
||||||
|
#define R_386_GOTOFF 9
|
||||||
|
#define R_386_GOTPC 10
|
||||||
|
#define R_386_GOT32X 43
|
||||||
|
|
||||||
|
#define R_X86_64_64 1
|
||||||
|
#define R_X86_64_PC32 2
|
||||||
|
#define R_X86_64_GOT32 3
|
||||||
|
#define R_X86_64_PLT32 4
|
||||||
|
#define R_X86_64_COPY 5
|
||||||
|
#define R_X86_64_GLOB_DAT 6
|
||||||
|
#define R_X86_64_JUMP_SLOT 7
|
||||||
|
#define R_X86_64_RELATIVE 8
|
||||||
|
#define R_X86_64_GOTPCREL 9
|
||||||
|
#define R_X86_64_32 10
|
||||||
|
|
||||||
|
#define STT_NOTYPE 0
|
||||||
|
#define STT_OBJECT 1
|
||||||
|
#define STT_FUNC 2
|
||||||
|
#define STT_SECTION 3
|
||||||
|
#define STT_FILE 4
|
||||||
|
#define STT_LOPROC 13
|
||||||
|
#define STT_HIPROC 15
|
||||||
|
|
||||||
|
/* Section flags */
|
||||||
|
#define SHF_WRITE 0x1
|
||||||
|
#define SHF_ALLOC 0x2
|
||||||
|
#define SHF_EXECINSTR 0x4
|
||||||
|
|
||||||
|
#define SHN_UNDEF 0
|
||||||
|
|
||||||
|
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||||
|
#define ELF64_R_TYPE(i) ((elf_word_t)(i))
|
||||||
|
#define ELF64_ST_BIND(i) ((i) >> 4)
|
||||||
|
#define ELF64_ST_TYPE(i) ((i) & 0xf)
|
||||||
|
|
||||||
|
#define STB_LOCAL 0
|
||||||
|
#define STB_GLOBAL 1
|
||||||
|
#define STB_WEAK 2
|
||||||
|
#define STB_NUM 3
|
||||||
|
|
||||||
|
typedef uint64_t elf_addr_t;
|
||||||
|
typedef uint64_t elf_off_t;
|
||||||
|
typedef uint16_t elf_half_t;
|
||||||
|
typedef uint32_t elf_word_t;
|
||||||
|
typedef int32_t elf_sword_t;
|
||||||
|
typedef uint64_t elf_xword_t;
|
||||||
|
typedef int64_t elf_sxword_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ELF file header.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t e_ident[ELF_NIDENT];
|
||||||
|
elf_half_t e_type;
|
||||||
|
elf_half_t e_machine;
|
||||||
|
elf_word_t e_version;
|
||||||
|
elf_addr_t e_entry;
|
||||||
|
elf_off_t e_phoff;
|
||||||
|
elf_off_t e_shoff;
|
||||||
|
elf_word_t e_flags;
|
||||||
|
elf_half_t e_ehsize;
|
||||||
|
elf_half_t e_phentsize;
|
||||||
|
elf_half_t e_phnum;
|
||||||
|
elf_half_t e_shentsize;
|
||||||
|
elf_half_t e_shnum;
|
||||||
|
elf_half_t e_shstrndx;
|
||||||
|
} elf_ehdr_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ELF section header.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
elf_word_t sh_name;
|
||||||
|
elf_word_t sh_type;
|
||||||
|
elf_xword_t sh_flags;
|
||||||
|
elf_addr_t sh_addr;
|
||||||
|
elf_off_t sh_offset;
|
||||||
|
elf_xword_t sh_size;
|
||||||
|
elf_word_t sh_link;
|
||||||
|
elf_word_t sh_info;
|
||||||
|
elf_xword_t sh_addralign;
|
||||||
|
elf_xword_t sh_entsize;
|
||||||
|
} elf_shdr_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ELF symbol.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
elf_word_t st_name;
|
||||||
|
unsigned char st_info;
|
||||||
|
unsigned char st_other;
|
||||||
|
elf_half_t st_shndx;
|
||||||
|
elf_addr_t st_value;
|
||||||
|
elf_xword_t st_size;
|
||||||
|
} elf_sym_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ELF program header.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
elf_word_t p_type;
|
||||||
|
elf_word_t p_flags;
|
||||||
|
elf_off_t p_offset;
|
||||||
|
elf_addr_t p_vaddr;
|
||||||
|
elf_addr_t p_paddr;
|
||||||
|
elf_xword_t p_filesz;
|
||||||
|
elf_xword_t p_memsz;
|
||||||
|
elf_xword_t p_align;
|
||||||
|
} elf_phdr_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended ELF relocation information.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
elf_addr_t r_offset;
|
||||||
|
elf_xword_t r_info;
|
||||||
|
elf_sxword_t r_addend;
|
||||||
|
} elf_rela_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamic section entries
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
elf_sxword_t d_tag;
|
||||||
|
union {
|
||||||
|
elf_xword_t d_val;
|
||||||
|
elf_addr_t d_ptr;
|
||||||
|
} d_un;
|
||||||
|
} elf_dyn_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Section header types.
|
||||||
|
*/
|
||||||
|
enum elf_stype {
|
||||||
|
ST_NONE = 0,
|
||||||
|
ST_PROGBITS = 1,
|
||||||
|
ST_SYMTAB = 2,
|
||||||
|
ST_STRTAB = 3,
|
||||||
|
ST_NOBITS = 8,
|
||||||
|
ST_REL = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Program header types.
|
||||||
|
*/
|
||||||
|
enum elf_ptype {
|
||||||
|
PT_NULL = 0,
|
||||||
|
PT_LOAD = 1,
|
||||||
|
PT_DYNAMIC = 2,
|
||||||
|
PT_INTERP = 3,
|
||||||
|
PT_NOTE = 4,
|
||||||
|
PT_SHLIB = 5,
|
||||||
|
PT_PHDR = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PF_X 0x1
|
||||||
|
#define PF_W 0x2
|
||||||
|
#define PF_R 0x4
|
||||||
|
|
||||||
|
#define PT_LOPROC 0x70000000
|
||||||
|
#define PT_HIPROC 0x7FFFFFFF
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ELF identification byte locations.
|
||||||
|
*/
|
||||||
|
enum elf_ident {
|
||||||
|
EI_MAG0 = 0,
|
||||||
|
EI_MAG1 = 1,
|
||||||
|
EI_MAG2 = 2,
|
||||||
|
EI_MAG3 = 3,
|
||||||
|
EI_CLASS = 4,
|
||||||
|
EI_DATA = 5,
|
||||||
|
EI_VERSION = 6,
|
||||||
|
EI_OSABI = 7,
|
||||||
|
EI_ABIVERSION = 8,
|
||||||
|
EI_PAD = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
enum elf_type {
|
||||||
|
ET_NONE = 0,
|
||||||
|
ET_REL = 1,
|
||||||
|
ET_EXEC = 2,
|
||||||
|
ET_DYN = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AT_NULL 0
|
||||||
|
#define AT_IGNORE 1
|
||||||
|
#define AT_EXECFD 2
|
||||||
|
#define AT_PHDR 3
|
||||||
|
#define AT_PHENT 4
|
||||||
|
#define AT_PHNUM 5
|
||||||
|
#define AT_PAGESZ 6
|
||||||
|
#define AT_BASE 7
|
||||||
|
#define AT_FLAGS 8
|
||||||
|
#define AT_ENTRY 9
|
||||||
|
#define AT_NOTELF 10
|
||||||
|
#define AT_UID 11
|
||||||
|
#define AT_EUID 12
|
||||||
|
#define AT_GID 13
|
||||||
|
#define AT_EGID 14
|
||||||
|
#define AT_CLKTCK 17
|
||||||
|
#define AT_PLATFORM 15
|
||||||
|
#define AT_HWCAP 16
|
||||||
|
#define AT_FPUCW 18
|
||||||
|
#define AT_DCACHEBSIZE 19
|
||||||
|
#define AT_ICACHEBSIZE 20
|
||||||
|
#define AT_UCACHEBSIZE 21
|
||||||
|
#define AT_IGNOREPPC 22
|
||||||
|
#define AT_SECURE 23
|
||||||
|
#define AT_BASE_PLATFORM 24
|
||||||
|
#define AT_RANDOM 25
|
||||||
|
#define AT_HWCAP2 26
|
||||||
|
#define AT_EXECFN 31
|
||||||
|
#define AT_SYSINFO 32
|
||||||
|
#define AT_SYSINFO_EHDR 33
|
||||||
|
#define AT_L1I_CACHESHAPE 34
|
||||||
|
#define AT_L1D_CACHESHAPE 35
|
||||||
|
#define AT_L2_CACHESHAPE 36
|
||||||
|
#define AT_L3_CACHESHAPE 37
|
||||||
|
#define AT_ENTRY_COUNT 38
|
||||||
|
|
||||||
|
struct bootdata;
|
||||||
|
struct bootfs_file;
|
||||||
|
|
||||||
|
struct elf_image {
|
||||||
|
kern_handle_t e_image, e_data;
|
||||||
|
kern_handle_t e_local_space, e_remote_space;
|
||||||
|
kern_handle_t e_local_exec, e_remote_exec;
|
||||||
|
virt_addr_t e_local_base, e_remote_base;
|
||||||
|
elf_ehdr_t e_hdr;
|
||||||
|
elf_phdr_t e_dynamic;
|
||||||
|
off_t e_dynsym;
|
||||||
|
size_t e_dynsym_entsize;
|
||||||
|
|
||||||
|
char e_interp[256];
|
||||||
|
size_t e_total_size, e_data_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void elf_image_init(struct elf_image *out);
|
||||||
|
extern enum launch_status elf_image_load(
|
||||||
|
struct elf_image *image,
|
||||||
|
kern_handle_t exec_object,
|
||||||
|
kern_handle_t local_space,
|
||||||
|
kern_handle_t remote_space);
|
||||||
|
|
||||||
|
extern void elf_image_cleanup(struct elf_image *image);
|
||||||
|
|
||||||
|
#endif
|
||||||
73
lib/liblaunch/include/launch.h
Normal file
73
lib/liblaunch/include/launch.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#ifndef LAUNCH_H_
|
||||||
|
#define LAUNCH_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
enum launch_status {
|
||||||
|
LAUNCH_OK,
|
||||||
|
/* a memory allocation failed */
|
||||||
|
LAUNCH_ERR_NO_MEMORY,
|
||||||
|
/* executable file is corrupt or of an unrecognised format. */
|
||||||
|
LAUNCH_ERR_INVALID_EXECUTABLE,
|
||||||
|
/* executable file IS valid and IS of a recognised format, but is
|
||||||
|
* not supported by this machine (different class, architecture,
|
||||||
|
* version, etc).
|
||||||
|
*/
|
||||||
|
LAUNCH_ERR_UNSUPPORTED_EXECUTABLE,
|
||||||
|
/* a particular dependency of the executable could not be resolved. */
|
||||||
|
LAUNCH_ERR_CANNOT_RESOLVE_DEPENDENCY,
|
||||||
|
LAUNCH_ERR_MEMORY_MAP_FAILED,
|
||||||
|
LAUNCH_ERR_IMAGE_DATA_LOAD_FAILED,
|
||||||
|
LAUNCH_ERR_INTERPRETER_REQUIRED,
|
||||||
|
LAUNCH_ERR_TASK_CREATION_FAILED,
|
||||||
|
LAUNCH_ERR_THREAD_CREATION_FAILED,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum launch_flags {
|
||||||
|
LAUNCH_F_NONE = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct launch_ctx;
|
||||||
|
|
||||||
|
typedef enum launch_status (*launch_resolve_library_function)(
|
||||||
|
struct launch_ctx *,
|
||||||
|
const char *,
|
||||||
|
kern_handle_t *,
|
||||||
|
void *);
|
||||||
|
|
||||||
|
struct launch_ctx {
|
||||||
|
launch_resolve_library_function ctx_resolve_library;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct launch_parameters {
|
||||||
|
kern_handle_t p_parent_task;
|
||||||
|
kern_handle_t p_local_address_space;
|
||||||
|
kern_handle_t p_executable;
|
||||||
|
|
||||||
|
const char *p_task_name;
|
||||||
|
|
||||||
|
int p_argc;
|
||||||
|
const char **p_argv;
|
||||||
|
|
||||||
|
int p_envc;
|
||||||
|
const char **p_envp;
|
||||||
|
|
||||||
|
void *p_resolver_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct launch_result {
|
||||||
|
kern_handle_t r_task;
|
||||||
|
kern_handle_t r_thread;
|
||||||
|
kern_handle_t r_address_space;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern enum launch_status launch_ctx_init(struct launch_ctx *ctx);
|
||||||
|
extern void launch_ctx_cleanup(struct launch_ctx *ctx);
|
||||||
|
|
||||||
|
extern enum launch_status launch_ctx_execute(
|
||||||
|
struct launch_ctx *ctx,
|
||||||
|
const struct launch_parameters *params,
|
||||||
|
enum launch_flags flags,
|
||||||
|
struct launch_result *result);
|
||||||
|
|
||||||
|
#endif
|
||||||
141
lib/liblaunch/launch.c
Normal file
141
lib/liblaunch/launch.c
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#include "elf.h"
|
||||||
|
|
||||||
|
#include <launch.h>
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define STACK_SIZE 0x10000
|
||||||
|
|
||||||
|
enum launch_status launch_ctx_init(struct launch_ctx *ctx)
|
||||||
|
{
|
||||||
|
memset(ctx, 0x0, sizeof *ctx);
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void launch_ctx_cleanup(struct launch_ctx *ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_handle_t get_library(
|
||||||
|
struct launch_ctx *ctx,
|
||||||
|
const char *name,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
enum launch_status status = LAUNCH_ERR_CANNOT_RESOLVE_DEPENDENCY;
|
||||||
|
kern_handle_t result = KERN_HANDLE_INVALID;
|
||||||
|
if (ctx->ctx_resolve_library) {
|
||||||
|
status = ctx->ctx_resolve_library(ctx, name, &result, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum launch_status launch_ctx_execute(
|
||||||
|
struct launch_ctx *ctx,
|
||||||
|
const struct launch_parameters *params,
|
||||||
|
enum launch_flags flags,
|
||||||
|
struct launch_result *result)
|
||||||
|
{
|
||||||
|
kern_status_t kstatus;
|
||||||
|
kern_handle_t stack_vmo;
|
||||||
|
|
||||||
|
kstatus = vm_object_create(
|
||||||
|
"stack",
|
||||||
|
5,
|
||||||
|
STACK_SIZE,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
|
&stack_vmo);
|
||||||
|
|
||||||
|
size_t name_len = params->p_task_name ? strlen(params->p_task_name) : 0;
|
||||||
|
kern_handle_t remote_task = KERN_HANDLE_INVALID,
|
||||||
|
remote_address_space = KERN_HANDLE_INVALID;
|
||||||
|
kstatus = task_create(
|
||||||
|
params->p_parent_task,
|
||||||
|
params->p_task_name,
|
||||||
|
name_len,
|
||||||
|
&remote_task,
|
||||||
|
&remote_address_space);
|
||||||
|
if (kstatus != KERN_OK) {
|
||||||
|
kern_handle_close(stack_vmo);
|
||||||
|
return LAUNCH_ERR_TASK_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct elf_image image;
|
||||||
|
elf_image_init(&image);
|
||||||
|
|
||||||
|
enum launch_status status = elf_image_load(
|
||||||
|
&image,
|
||||||
|
params->p_executable,
|
||||||
|
params->p_local_address_space,
|
||||||
|
remote_address_space);
|
||||||
|
|
||||||
|
if (status == LAUNCH_ERR_INTERPRETER_REQUIRED) {
|
||||||
|
kern_handle_t interp = get_library(
|
||||||
|
ctx,
|
||||||
|
image.e_interp,
|
||||||
|
params->p_resolver_arg);
|
||||||
|
if (interp == KERN_HANDLE_INVALID) {
|
||||||
|
elf_image_cleanup(&image);
|
||||||
|
kern_handle_close(stack_vmo);
|
||||||
|
kern_handle_close(remote_address_space);
|
||||||
|
kern_handle_close(remote_task);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
elf_image_init(&image);
|
||||||
|
status = elf_image_load(
|
||||||
|
&image,
|
||||||
|
interp,
|
||||||
|
params->p_local_address_space,
|
||||||
|
remote_address_space);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != LAUNCH_OK) {
|
||||||
|
elf_image_cleanup(&image);
|
||||||
|
kern_handle_close(stack_vmo);
|
||||||
|
kern_handle_close(remote_address_space);
|
||||||
|
kern_handle_close(remote_task);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
virt_addr_t stack_buf;
|
||||||
|
kstatus = vm_region_map_relative(
|
||||||
|
remote_address_space,
|
||||||
|
VM_REGION_ANY_OFFSET,
|
||||||
|
stack_vmo,
|
||||||
|
0,
|
||||||
|
STACK_SIZE,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
|
&stack_buf);
|
||||||
|
kern_handle_close(stack_vmo);
|
||||||
|
|
||||||
|
if (kstatus != KERN_OK) {
|
||||||
|
elf_image_cleanup(&image);
|
||||||
|
kern_handle_close(remote_address_space);
|
||||||
|
kern_handle_close(remote_task);
|
||||||
|
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
||||||
|
virt_addr_t sp = stack_buf + STACK_SIZE;
|
||||||
|
|
||||||
|
kern_handle_t thread;
|
||||||
|
kstatus = task_create_thread(remote_task, ip, sp, NULL, 0, &thread);
|
||||||
|
if (kstatus != KERN_OK) {
|
||||||
|
elf_image_cleanup(&image);
|
||||||
|
kern_handle_close(remote_address_space);
|
||||||
|
kern_handle_close(remote_task);
|
||||||
|
return LAUNCH_ERR_THREAD_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_start(thread);
|
||||||
|
|
||||||
|
kern_handle_close(thread);
|
||||||
|
elf_image_cleanup(&image);
|
||||||
|
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
21
lib/libmsg-fs/CMakeLists.txt
Normal file
21
lib/libmsg-fs/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
|
file(GLOB headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/rosetta/msg/fs.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME libmsg-fs STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libmsg-fs
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libmsg-fs libmsg libmango)
|
||||||
3
lib/libmsg-fs/fs.c
Normal file
3
lib/libmsg-fs/fs.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
void msg_fs_tmp(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
27
lib/libmsg-fs/include/rosetta/msg/fs.h
Normal file
27
lib/libmsg-fs/include/rosetta/msg/fs.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef ROSETTA_MSG_FS_H_
|
||||||
|
#define ROSETTA_MSG_FS_H_
|
||||||
|
|
||||||
|
#include <rosetta/msg.h>
|
||||||
|
|
||||||
|
/* rosetta.msg.fs protocol ID */
|
||||||
|
#define ROSETTA_MSG_FS 0x01409DD2U
|
||||||
|
|
||||||
|
/* rosetta.msg.fs.open message ID */
|
||||||
|
#define ROSETTA_MSG_FS_OPEN 0x7D837778U
|
||||||
|
|
||||||
|
struct rosetta_msg_fs_open {
|
||||||
|
struct rosetta_msg msg_base;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t o_path;
|
||||||
|
uint16_t o_flags;
|
||||||
|
} msg_request;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int o_err;
|
||||||
|
uint16_t o_fd_index;
|
||||||
|
} msg_response;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
21
lib/libmsg-ld/CMakeLists.txt
Normal file
21
lib/libmsg-ld/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
|
file(GLOB headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/rosetta/msg/ld.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME libmsg-ld STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libmsg-ld
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libmsg-ld libmsg libmango)
|
||||||
26
lib/libmsg-ld/include/rosetta/msg/ld.h
Normal file
26
lib/libmsg-ld/include/rosetta/msg/ld.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef ROSETTA_MSG_LD_H_
|
||||||
|
#define ROSETTA_MSG_LD_H_
|
||||||
|
|
||||||
|
#include <rosetta/msg.h>
|
||||||
|
|
||||||
|
/* rosetta.msg.ld protocol ID */
|
||||||
|
#define ROSETTA_MSG_LD 0x5563D896U
|
||||||
|
|
||||||
|
/* rosetta.msg.ld.get-object message ID */
|
||||||
|
#define ROSETTA_MSG_LD_GET_OBJECT 1
|
||||||
|
|
||||||
|
struct rosetta_msg_ld_get_object {
|
||||||
|
struct rosetta_msg msg_base;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t go_object_name;
|
||||||
|
} msg_request;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int go_err;
|
||||||
|
uint16_t go_object_index;
|
||||||
|
} msg_response;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
3
lib/libmsg-ld/ld.c
Normal file
3
lib/libmsg-ld/ld.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
void msg_ld_tmp(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
21
lib/libmsg/CMakeLists.txt
Normal file
21
lib/libmsg/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
file(GLOB sources
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
|
file(GLOB headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/rosetta/msg.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME libmsg STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
sysroot_add_library(
|
||||||
|
NAME libmsg
|
||||||
|
HEADER_DIR /usr/include
|
||||||
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
|
target_link_libraries(libmsg libmango)
|
||||||
15
lib/libmsg/include/rosetta/msg.h
Normal file
15
lib/libmsg/include/rosetta/msg.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef ROSETTA_MSG_H_
|
||||||
|
#define ROSETTA_MSG_H_
|
||||||
|
|
||||||
|
#define ROSETTA_MSG_MAGIC 0x9AB07D10U
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct rosetta_msg {
|
||||||
|
uint32_t msg_magic;
|
||||||
|
uint32_t msg_protocol;
|
||||||
|
uint16_t msg_id;
|
||||||
|
uint16_t msg_reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
3
lib/libmsg/msg.c
Normal file
3
lib/libmsg/msg.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
void msg_tmp(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
19
lib/ulibc/CMakeLists.txt
Normal file
19
lib/ulibc/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
set(source_dirs string stdio unistd)
|
||||||
|
foreach (dir ${source_dirs})
|
||||||
|
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||||
|
file(GLOB dir_headers ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.h)
|
||||||
|
|
||||||
|
set(sources ${sources} ${dir_sources})
|
||||||
|
set(headers ${headers} ${dir_headers})
|
||||||
|
endforeach (dir)
|
||||||
|
|
||||||
|
set(public_include_dirs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
rosetta_add_library(
|
||||||
|
NAME ulibc STATIC
|
||||||
|
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||||
|
SOURCES ${sources}
|
||||||
|
HEADERS ${headers})
|
||||||
|
|
||||||
|
target_link_libraries(ulibc libmango)
|
||||||
22
lib/ulibc/include/stdio.h
Normal file
22
lib/ulibc/include/stdio.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef STDIO_H_
|
||||||
|
#define STDIO_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int snprintf(char *buffer, size_t count, const char *format, ...);
|
||||||
|
extern int vsnprintf(
|
||||||
|
char *buffer,
|
||||||
|
size_t count,
|
||||||
|
const char *format,
|
||||||
|
va_list va);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
14
lib/ulibc/include/string.h
Normal file
14
lib/ulibc/include/string.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef STRING_H_
|
||||||
|
#define STRING_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern size_t strlen(const char *s);
|
||||||
|
|
||||||
|
extern int strcmp(const char *s1, const char *s2);
|
||||||
|
extern int strncmp(const char *s1, const char *s2, unsigned long n);
|
||||||
|
|
||||||
|
extern void *memset(void *str, int c, size_t n);
|
||||||
|
extern void *memcpy(void *dst, const void *src, size_t len);
|
||||||
|
|
||||||
|
#endif
|
||||||
8
lib/ulibc/include/unistd.h
Normal file
8
lib/ulibc/include/unistd.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef UNISTD_H_
|
||||||
|
#define UNISTD_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern void *sbrk(intptr_t increment);
|
||||||
|
|
||||||
|
#endif
|
||||||
1215
lib/ulibc/stdio/printf.c
Normal file
1215
lib/ulibc/stdio/printf.c
Normal file
File diff suppressed because it is too large
Load Diff
6295
lib/ulibc/stdlib/malloc.c
Normal file
6295
lib/ulibc/stdlib/malloc.c
Normal file
File diff suppressed because it is too large
Load Diff
637
lib/ulibc/stdlib/malloc.h
Normal file
637
lib/ulibc/stdlib/malloc.h
Normal file
@@ -0,0 +1,637 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2023 Doug Lea
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Default header file for malloc-2.8.x
|
||||||
|
Re-licensed 25 Sep 2023 with MIT-0 replacing obsolete CC0
|
||||||
|
See https://opensource.org/license/mit-0/
|
||||||
|
|
||||||
|
This header is for ANSI C/C++ only. You can set any of
|
||||||
|
the following #defines before including:
|
||||||
|
|
||||||
|
* If USE_DL_PREFIX is defined, it is assumed that malloc.c
|
||||||
|
was also compiled with this option, so all routines
|
||||||
|
have names starting with "dl".
|
||||||
|
|
||||||
|
* If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this
|
||||||
|
file will be #included AFTER <malloc.h>. This is needed only if
|
||||||
|
your system defines a struct mallinfo that is incompatible with the
|
||||||
|
standard one declared here. Otherwise, you can include this file
|
||||||
|
INSTEAD of your system system <malloc.h>. At least on ANSI, all
|
||||||
|
declarations should be compatible with system versions
|
||||||
|
|
||||||
|
* If MSPACES is defined, declarations for mspace versions are included.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MALLOC_280_H
|
||||||
|
#define MALLOC_280_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h> /* for size_t */
|
||||||
|
|
||||||
|
#ifndef ONLY_MSPACES
|
||||||
|
#define ONLY_MSPACES 0 /* define to a value */
|
||||||
|
#elif ONLY_MSPACES != 0
|
||||||
|
#define ONLY_MSPACES 1
|
||||||
|
#endif /* ONLY_MSPACES */
|
||||||
|
#ifndef NO_MALLINFO
|
||||||
|
#define NO_MALLINFO 0
|
||||||
|
#endif /* NO_MALLINFO */
|
||||||
|
|
||||||
|
#ifndef MSPACES
|
||||||
|
#if ONLY_MSPACES
|
||||||
|
#define MSPACES 1
|
||||||
|
#else /* ONLY_MSPACES */
|
||||||
|
#define MSPACES 0
|
||||||
|
#endif /* ONLY_MSPACES */
|
||||||
|
#endif /* MSPACES */
|
||||||
|
|
||||||
|
#if !ONLY_MSPACES
|
||||||
|
|
||||||
|
#ifndef USE_DL_PREFIX
|
||||||
|
#define dlcalloc calloc
|
||||||
|
#define dlfree free
|
||||||
|
#define dlmalloc malloc
|
||||||
|
#define dlmemalign memalign
|
||||||
|
#define dlposix_memalign posix_memalign
|
||||||
|
#define dlrealloc realloc
|
||||||
|
#define dlvalloc valloc
|
||||||
|
#define dlpvalloc pvalloc
|
||||||
|
#define dlmallinfo mallinfo
|
||||||
|
#define dlmallopt mallopt
|
||||||
|
#define dlmalloc_trim malloc_trim
|
||||||
|
#define dlmalloc_stats malloc_stats
|
||||||
|
#define dlmalloc_usable_size malloc_usable_size
|
||||||
|
#define dlmalloc_footprint malloc_footprint
|
||||||
|
#define dlmalloc_max_footprint malloc_max_footprint
|
||||||
|
#define dlmalloc_footprint_limit malloc_footprint_limit
|
||||||
|
#define dlmalloc_set_footprint_limit malloc_set_footprint_limit
|
||||||
|
#define dlmalloc_inspect_all malloc_inspect_all
|
||||||
|
#define dlindependent_calloc independent_calloc
|
||||||
|
#define dlindependent_comalloc independent_comalloc
|
||||||
|
#define dlbulk_free bulk_free
|
||||||
|
#endif /* USE_DL_PREFIX */
|
||||||
|
|
||||||
|
#if !NO_MALLINFO
|
||||||
|
#ifndef HAVE_USR_INCLUDE_MALLOC_H
|
||||||
|
#ifndef _MALLOC_H
|
||||||
|
#ifndef MALLINFO_FIELD_TYPE
|
||||||
|
#define MALLINFO_FIELD_TYPE size_t
|
||||||
|
#endif /* MALLINFO_FIELD_TYPE */
|
||||||
|
#ifndef STRUCT_MALLINFO_DECLARED
|
||||||
|
#define STRUCT_MALLINFO_DECLARED 1
|
||||||
|
struct mallinfo {
|
||||||
|
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
|
||||||
|
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
|
||||||
|
MALLINFO_FIELD_TYPE smblks; /* always 0 */
|
||||||
|
MALLINFO_FIELD_TYPE hblks; /* always 0 */
|
||||||
|
MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
|
||||||
|
MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
|
||||||
|
MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
|
||||||
|
MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
|
||||||
|
MALLINFO_FIELD_TYPE fordblks; /* total free space */
|
||||||
|
MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
|
||||||
|
};
|
||||||
|
#endif /* STRUCT_MALLINFO_DECLARED */
|
||||||
|
#endif /* _MALLOC_H */
|
||||||
|
#endif /* HAVE_USR_INCLUDE_MALLOC_H */
|
||||||
|
#endif /* !NO_MALLINFO */
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc(size_t n)
|
||||||
|
Returns a pointer to a newly allocated chunk of at least n bytes, or
|
||||||
|
null if no space is available, in which case errno is set to ENOMEM
|
||||||
|
on ANSI C systems.
|
||||||
|
|
||||||
|
If n is zero, malloc returns a minimum-sized chunk. (The minimum
|
||||||
|
size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
|
||||||
|
systems.) Note that size_t is an unsigned type, so calls with
|
||||||
|
arguments that would be negative if signed are interpreted as
|
||||||
|
requests for huge amounts of space, which will often fail. The
|
||||||
|
maximum supported value of n differs across systems, but is in all
|
||||||
|
cases less than the maximum representable value of a size_t.
|
||||||
|
*/
|
||||||
|
void* dlmalloc(size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
free(void* p)
|
||||||
|
Releases the chunk of memory pointed to by p, that had been previously
|
||||||
|
allocated using malloc or a related routine such as realloc.
|
||||||
|
It has no effect if p is null. If p was not malloced or already
|
||||||
|
freed, free(p) will by default cuase the current program to abort.
|
||||||
|
*/
|
||||||
|
void dlfree(void*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
calloc(size_t n_elements, size_t element_size);
|
||||||
|
Returns a pointer to n_elements * element_size bytes, with all locations
|
||||||
|
set to zero.
|
||||||
|
*/
|
||||||
|
void* dlcalloc(size_t, size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
realloc(void* p, size_t n)
|
||||||
|
Returns a pointer to a chunk of size n that contains the same data
|
||||||
|
as does chunk p up to the minimum of (n, p's size) bytes, or null
|
||||||
|
if no space is available.
|
||||||
|
|
||||||
|
The returned pointer may or may not be the same as p. The algorithm
|
||||||
|
prefers extending p in most cases when possible, otherwise it
|
||||||
|
employs the equivalent of a malloc-copy-free sequence.
|
||||||
|
|
||||||
|
If p is null, realloc is equivalent to malloc.
|
||||||
|
|
||||||
|
If space is not available, realloc returns null, errno is set (if on
|
||||||
|
ANSI) and p is NOT freed.
|
||||||
|
|
||||||
|
if n is for fewer bytes than already held by p, the newly unused
|
||||||
|
space is lopped off and freed if possible. realloc with a size
|
||||||
|
argument of zero (re)allocates a minimum-sized chunk.
|
||||||
|
|
||||||
|
The old unix realloc convention of allowing the last-free'd chunk
|
||||||
|
to be used as an argument to realloc is not supported.
|
||||||
|
*/
|
||||||
|
void* dlrealloc(void*, size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
realloc_in_place(void* p, size_t n)
|
||||||
|
Resizes the space allocated for p to size n, only if this can be
|
||||||
|
done without moving p (i.e., only if there is adjacent space
|
||||||
|
available if n is greater than p's current allocated size, or n is
|
||||||
|
less than or equal to p's size). This may be used instead of plain
|
||||||
|
realloc if an alternative allocation strategy is needed upon failure
|
||||||
|
to expand space; for example, reallocation of a buffer that must be
|
||||||
|
memory-aligned or cleared. You can use realloc_in_place to trigger
|
||||||
|
these alternatives only when needed.
|
||||||
|
|
||||||
|
Returns p if successful; otherwise null.
|
||||||
|
*/
|
||||||
|
void* dlrealloc_in_place(void*, size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
memalign(size_t alignment, size_t n);
|
||||||
|
Returns a pointer to a newly allocated chunk of n bytes, aligned
|
||||||
|
in accord with the alignment argument.
|
||||||
|
|
||||||
|
The alignment argument should be a power of two. If the argument is
|
||||||
|
not a power of two, the nearest greater power is used.
|
||||||
|
8-byte alignment is guaranteed by normal malloc calls, so don't
|
||||||
|
bother calling memalign with an argument of 8 or less.
|
||||||
|
|
||||||
|
Overreliance on memalign is a sure way to fragment space.
|
||||||
|
*/
|
||||||
|
void* dlmemalign(size_t, size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
int posix_memalign(void** pp, size_t alignment, size_t n);
|
||||||
|
Allocates a chunk of n bytes, aligned in accord with the alignment
|
||||||
|
argument. Differs from memalign only in that it (1) assigns the
|
||||||
|
allocated memory to *pp rather than returning it, (2) fails and
|
||||||
|
returns EINVAL if the alignment is not a power of two (3) fails and
|
||||||
|
returns ENOMEM if memory cannot be allocated.
|
||||||
|
*/
|
||||||
|
int dlposix_memalign(void**, size_t, size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
valloc(size_t n);
|
||||||
|
Equivalent to memalign(pagesize, n), where pagesize is the page
|
||||||
|
size of the system. If the pagesize is unknown, 4096 is used.
|
||||||
|
*/
|
||||||
|
void* dlvalloc(size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mallopt(int parameter_number, int parameter_value)
|
||||||
|
Sets tunable parameters The format is to provide a
|
||||||
|
(parameter-number, parameter-value) pair. mallopt then sets the
|
||||||
|
corresponding parameter to the argument value if it can (i.e., so
|
||||||
|
long as the value is meaningful), and returns 1 if successful else
|
||||||
|
0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
|
||||||
|
normally defined in malloc.h. None of these are use in this malloc,
|
||||||
|
so setting them has no effect. But this malloc also supports other
|
||||||
|
options in mallopt:
|
||||||
|
|
||||||
|
Symbol param # default allowed param values
|
||||||
|
M_TRIM_THRESHOLD -1 2*1024*1024 any (-1U disables trimming)
|
||||||
|
M_GRANULARITY -2 page size any power of 2 >= page size
|
||||||
|
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
|
||||||
|
*/
|
||||||
|
int dlmallopt(int, int);
|
||||||
|
|
||||||
|
#define M_TRIM_THRESHOLD (-1)
|
||||||
|
#define M_GRANULARITY (-2)
|
||||||
|
#define M_MMAP_THRESHOLD (-3)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_footprint();
|
||||||
|
Returns the number of bytes obtained from the system. The total
|
||||||
|
number of bytes allocated by malloc, realloc etc., is less than this
|
||||||
|
value. Unlike mallinfo, this function returns only a precomputed
|
||||||
|
result, so can be called frequently to monitor memory consumption.
|
||||||
|
Even if locks are otherwise defined, this function does not use them,
|
||||||
|
so results might not be up to date.
|
||||||
|
*/
|
||||||
|
size_t dlmalloc_footprint(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_max_footprint();
|
||||||
|
Returns the maximum number of bytes obtained from the system. This
|
||||||
|
value will be greater than current footprint if deallocated space
|
||||||
|
has been reclaimed by the system. The peak number of bytes allocated
|
||||||
|
by malloc, realloc etc., is less than this value. Unlike mallinfo,
|
||||||
|
this function returns only a precomputed result, so can be called
|
||||||
|
frequently to monitor memory consumption. Even if locks are
|
||||||
|
otherwise defined, this function does not use them, so results might
|
||||||
|
not be up to date.
|
||||||
|
*/
|
||||||
|
size_t dlmalloc_max_footprint(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_footprint_limit();
|
||||||
|
Returns the number of bytes that the heap is allowed to obtain from
|
||||||
|
the system, returning the last value returned by
|
||||||
|
malloc_set_footprint_limit, or the maximum size_t value if
|
||||||
|
never set. The returned value reflects a permission. There is no
|
||||||
|
guarantee that this number of bytes can actually be obtained from
|
||||||
|
the system.
|
||||||
|
*/
|
||||||
|
size_t dlmalloc_footprint_limit(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_set_footprint_limit();
|
||||||
|
Sets the maximum number of bytes to obtain from the system, causing
|
||||||
|
failure returns from malloc and related functions upon attempts to
|
||||||
|
exceed this value. The argument value may be subject to page
|
||||||
|
rounding to an enforceable limit; this actual value is returned.
|
||||||
|
Using an argument of the maximum possible size_t effectively
|
||||||
|
disables checks. If the argument is less than or equal to the
|
||||||
|
current malloc_footprint, then all future allocations that require
|
||||||
|
additional system memory will fail. However, invocation cannot
|
||||||
|
retroactively deallocate existing used memory.
|
||||||
|
*/
|
||||||
|
size_t dlmalloc_set_footprint_limit(size_t bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_inspect_all(void(*handler)(void *start,
|
||||||
|
void *end,
|
||||||
|
size_t used_bytes,
|
||||||
|
void* callback_arg),
|
||||||
|
void* arg);
|
||||||
|
Traverses the heap and calls the given handler for each managed
|
||||||
|
region, skipping all bytes that are (or may be) used for bookkeeping
|
||||||
|
purposes. Traversal does not include include chunks that have been
|
||||||
|
directly memory mapped. Each reported region begins at the start
|
||||||
|
address, and continues up to but not including the end address. The
|
||||||
|
first used_bytes of the region contain allocated data. If
|
||||||
|
used_bytes is zero, the region is unallocated. The handler is
|
||||||
|
invoked with the given callback argument. If locks are defined, they
|
||||||
|
are held during the entire traversal. It is a bad idea to invoke
|
||||||
|
other malloc functions from within the handler.
|
||||||
|
|
||||||
|
For example, to count the number of in-use chunks with size greater
|
||||||
|
than 1000, you could write:
|
||||||
|
static int count = 0;
|
||||||
|
void count_chunks(void* start, void* end, size_t used, void* arg) {
|
||||||
|
if (used >= 1000) ++count;
|
||||||
|
}
|
||||||
|
then:
|
||||||
|
malloc_inspect_all(count_chunks, NULL);
|
||||||
|
|
||||||
|
malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined.
|
||||||
|
*/
|
||||||
|
void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*),
|
||||||
|
void* arg);
|
||||||
|
|
||||||
|
#if !NO_MALLINFO
|
||||||
|
/*
|
||||||
|
mallinfo()
|
||||||
|
Returns (by copy) a struct containing various summary statistics:
|
||||||
|
|
||||||
|
arena: current total non-mmapped bytes allocated from system
|
||||||
|
ordblks: the number of free chunks
|
||||||
|
smblks: always zero.
|
||||||
|
hblks: current number of mmapped regions
|
||||||
|
hblkhd: total bytes held in mmapped regions
|
||||||
|
usmblks: the maximum total allocated space. This will be greater
|
||||||
|
than current total if trimming has occurred.
|
||||||
|
fsmblks: always zero
|
||||||
|
uordblks: current total allocated space (normal or mmapped)
|
||||||
|
fordblks: total free space
|
||||||
|
keepcost: the maximum number of bytes that could ideally be released
|
||||||
|
back to system via malloc_trim. ("ideally" means that
|
||||||
|
it ignores page restrictions etc.)
|
||||||
|
|
||||||
|
Because these fields are ints, but internal bookkeeping may
|
||||||
|
be kept as longs, the reported values may wrap around zero and
|
||||||
|
thus be inaccurate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct mallinfo dlmallinfo(void);
|
||||||
|
#endif /* NO_MALLINFO */
|
||||||
|
|
||||||
|
/*
|
||||||
|
independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
|
||||||
|
|
||||||
|
independent_calloc is similar to calloc, but instead of returning a
|
||||||
|
single cleared space, it returns an array of pointers to n_elements
|
||||||
|
independent elements that can hold contents of size elem_size, each
|
||||||
|
of which starts out cleared, and can be independently freed,
|
||||||
|
realloc'ed etc. The elements are guaranteed to be adjacently
|
||||||
|
allocated (this is not guaranteed to occur with multiple callocs or
|
||||||
|
mallocs), which may also improve cache locality in some
|
||||||
|
applications.
|
||||||
|
|
||||||
|
The "chunks" argument is optional (i.e., may be null, which is
|
||||||
|
probably the most typical usage). If it is null, the returned array
|
||||||
|
is itself dynamically allocated and should also be freed when it is
|
||||||
|
no longer needed. Otherwise, the chunks array must be of at least
|
||||||
|
n_elements in length. It is filled in with the pointers to the
|
||||||
|
chunks.
|
||||||
|
|
||||||
|
In either case, independent_calloc returns this pointer array, or
|
||||||
|
null if the allocation failed. If n_elements is zero and "chunks"
|
||||||
|
is null, it returns a chunk representing an array with zero elements
|
||||||
|
(which should be freed if not wanted).
|
||||||
|
|
||||||
|
Each element must be freed when it is no longer needed. This can be
|
||||||
|
done all at once using bulk_free.
|
||||||
|
|
||||||
|
independent_calloc simplifies and speeds up implementations of many
|
||||||
|
kinds of pools. It may also be useful when constructing large data
|
||||||
|
structures that initially have a fixed number of fixed-sized nodes,
|
||||||
|
but the number is not known at compile time, and some of the nodes
|
||||||
|
may later need to be freed. For example:
|
||||||
|
|
||||||
|
struct Node { int item; struct Node* next; };
|
||||||
|
|
||||||
|
struct Node* build_list() {
|
||||||
|
struct Node** pool;
|
||||||
|
int n = read_number_of_nodes_needed();
|
||||||
|
if (n <= 0) return 0;
|
||||||
|
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
|
||||||
|
if (pool == 0) die();
|
||||||
|
// organize into a linked list...
|
||||||
|
struct Node* first = pool[0];
|
||||||
|
for (i = 0; i < n-1; ++i)
|
||||||
|
pool[i]->next = pool[i+1];
|
||||||
|
free(pool); // Can now free the array (or not, if it is needed later)
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void** dlindependent_calloc(size_t, size_t, void**);
|
||||||
|
|
||||||
|
/*
|
||||||
|
independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
|
||||||
|
|
||||||
|
independent_comalloc allocates, all at once, a set of n_elements
|
||||||
|
chunks with sizes indicated in the "sizes" array. It returns
|
||||||
|
an array of pointers to these elements, each of which can be
|
||||||
|
independently freed, realloc'ed etc. The elements are guaranteed to
|
||||||
|
be adjacently allocated (this is not guaranteed to occur with
|
||||||
|
multiple callocs or mallocs), which may also improve cache locality
|
||||||
|
in some applications.
|
||||||
|
|
||||||
|
The "chunks" argument is optional (i.e., may be null). If it is null
|
||||||
|
the returned array is itself dynamically allocated and should also
|
||||||
|
be freed when it is no longer needed. Otherwise, the chunks array
|
||||||
|
must be of at least n_elements in length. It is filled in with the
|
||||||
|
pointers to the chunks.
|
||||||
|
|
||||||
|
In either case, independent_comalloc returns this pointer array, or
|
||||||
|
null if the allocation failed. If n_elements is zero and chunks is
|
||||||
|
null, it returns a chunk representing an array with zero elements
|
||||||
|
(which should be freed if not wanted).
|
||||||
|
|
||||||
|
Each element must be freed when it is no longer needed. This can be
|
||||||
|
done all at once using bulk_free.
|
||||||
|
|
||||||
|
independent_comallac differs from independent_calloc in that each
|
||||||
|
element may have a different size, and also that it does not
|
||||||
|
automatically clear elements.
|
||||||
|
|
||||||
|
independent_comalloc can be used to speed up allocation in cases
|
||||||
|
where several structs or objects must always be allocated at the
|
||||||
|
same time. For example:
|
||||||
|
|
||||||
|
struct Head { ... }
|
||||||
|
struct Foot { ... }
|
||||||
|
|
||||||
|
void send_message(char* msg) {
|
||||||
|
int msglen = strlen(msg);
|
||||||
|
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
|
||||||
|
void* chunks[3];
|
||||||
|
if (independent_comalloc(3, sizes, chunks) == 0)
|
||||||
|
die();
|
||||||
|
struct Head* head = (struct Head*)(chunks[0]);
|
||||||
|
char* body = (char*)(chunks[1]);
|
||||||
|
struct Foot* foot = (struct Foot*)(chunks[2]);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
In general though, independent_comalloc is worth using only for
|
||||||
|
larger values of n_elements. For small values, you probably won't
|
||||||
|
detect enough difference from series of malloc calls to bother.
|
||||||
|
|
||||||
|
Overuse of independent_comalloc can increase overall memory usage,
|
||||||
|
since it cannot reuse existing noncontiguous small chunks that
|
||||||
|
might be available for some of the elements.
|
||||||
|
*/
|
||||||
|
void** dlindependent_comalloc(size_t, size_t*, void**);
|
||||||
|
|
||||||
|
/*
|
||||||
|
bulk_free(void* array[], size_t n_elements)
|
||||||
|
Frees and clears (sets to null) each non-null pointer in the given
|
||||||
|
array. This is likely to be faster than freeing them one-by-one.
|
||||||
|
If footers are used, pointers that have been allocated in different
|
||||||
|
mspaces are not freed or cleared, and the count of all such pointers
|
||||||
|
is returned. For large arrays of pointers with poor locality, it
|
||||||
|
may be worthwhile to sort this array before calling bulk_free.
|
||||||
|
*/
|
||||||
|
size_t dlbulk_free(void**, size_t n_elements);
|
||||||
|
|
||||||
|
/*
|
||||||
|
pvalloc(size_t n);
|
||||||
|
Equivalent to valloc(minimum-page-that-holds(n)), that is,
|
||||||
|
round up n to nearest pagesize.
|
||||||
|
*/
|
||||||
|
void* dlpvalloc(size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_trim(size_t pad);
|
||||||
|
|
||||||
|
If possible, gives memory back to the system (via negative arguments
|
||||||
|
to sbrk) if there is unused memory at the `high' end of the malloc
|
||||||
|
pool or in unused MMAP segments. You can call this after freeing
|
||||||
|
large blocks of memory to potentially reduce the system-level memory
|
||||||
|
requirements of a program. However, it cannot guarantee to reduce
|
||||||
|
memory. Under some allocation patterns, some large free blocks of
|
||||||
|
memory will be locked between two used chunks, so they cannot be
|
||||||
|
given back to the system.
|
||||||
|
|
||||||
|
The `pad' argument to malloc_trim represents the amount of free
|
||||||
|
trailing space to leave untrimmed. If this argument is zero, only
|
||||||
|
the minimum amount of memory to maintain internal data structures
|
||||||
|
will be left. Non-zero arguments can be supplied to maintain enough
|
||||||
|
trailing space to service future expected allocations without having
|
||||||
|
to re-obtain memory from the system.
|
||||||
|
|
||||||
|
Malloc_trim returns 1 if it actually released any memory, else 0.
|
||||||
|
*/
|
||||||
|
int dlmalloc_trim(size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_stats();
|
||||||
|
Prints on stderr the amount of space obtained from the system (both
|
||||||
|
via sbrk and mmap), the maximum amount (which may be more than
|
||||||
|
current if malloc_trim and/or munmap got called), and the current
|
||||||
|
number of bytes allocated via malloc (or realloc, etc) but not yet
|
||||||
|
freed. Note that this is the number of bytes allocated, not the
|
||||||
|
number requested. It will be larger than the number requested
|
||||||
|
because of alignment and bookkeeping overhead. Because it includes
|
||||||
|
alignment wastage as being in use, this figure may be greater than
|
||||||
|
zero even when no user-level chunks are allocated.
|
||||||
|
|
||||||
|
The reported current and maximum system memory can be inaccurate if
|
||||||
|
a program makes other calls to system memory allocation functions
|
||||||
|
(normally sbrk) outside of malloc.
|
||||||
|
|
||||||
|
malloc_stats prints only the most commonly interesting statistics.
|
||||||
|
More information can be obtained by calling mallinfo.
|
||||||
|
|
||||||
|
malloc_stats is not compiled if NO_MALLOC_STATS is defined.
|
||||||
|
*/
|
||||||
|
void dlmalloc_stats(void);
|
||||||
|
|
||||||
|
#endif /* !ONLY_MSPACES */
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc_usable_size(void* p);
|
||||||
|
|
||||||
|
Returns the number of bytes you can actually use in
|
||||||
|
an allocated chunk, which may be more than you requested (although
|
||||||
|
often not) due to alignment and minimum size constraints.
|
||||||
|
You can use this many bytes without worrying about
|
||||||
|
overwriting other allocated objects. This is not a particularly great
|
||||||
|
programming practice. malloc_usable_size can be more useful in
|
||||||
|
debugging and assertions, for example:
|
||||||
|
|
||||||
|
p = malloc(n);
|
||||||
|
assert(malloc_usable_size(p) >= 256);
|
||||||
|
*/
|
||||||
|
size_t dlmalloc_usable_size(const void*);
|
||||||
|
|
||||||
|
#if MSPACES
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace is an opaque type representing an independent
|
||||||
|
region of space that supports mspace_malloc, etc.
|
||||||
|
*/
|
||||||
|
typedef void* mspace;
|
||||||
|
|
||||||
|
/*
|
||||||
|
create_mspace creates and returns a new independent space with the
|
||||||
|
given initial capacity, or, if 0, the default granularity size. It
|
||||||
|
returns null if there is no system memory available to create the
|
||||||
|
space. If argument locked is non-zero, the space uses a separate
|
||||||
|
lock to control access. The capacity of the space will grow
|
||||||
|
dynamically as needed to service mspace_malloc requests. You can
|
||||||
|
control the sizes of incremental increases of this space by
|
||||||
|
compiling with a different DEFAULT_GRANULARITY or dynamically
|
||||||
|
setting with mallopt(M_GRANULARITY, value).
|
||||||
|
*/
|
||||||
|
mspace create_mspace(size_t capacity, int locked);
|
||||||
|
|
||||||
|
/*
|
||||||
|
destroy_mspace destroys the given space, and attempts to return all
|
||||||
|
of its memory back to the system, returning the total number of
|
||||||
|
bytes freed. After destruction, the results of access to all memory
|
||||||
|
used by the space become undefined.
|
||||||
|
*/
|
||||||
|
size_t destroy_mspace(mspace msp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
create_mspace_with_base uses the memory supplied as the initial base
|
||||||
|
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
|
||||||
|
space is used for bookkeeping, so the capacity must be at least this
|
||||||
|
large. (Otherwise 0 is returned.) When this initial space is
|
||||||
|
exhausted, additional memory will be obtained from the system.
|
||||||
|
Destroying this space will deallocate all additionally allocated
|
||||||
|
space (if possible) but not the initial base.
|
||||||
|
*/
|
||||||
|
mspace create_mspace_with_base(void* base, size_t capacity, int locked);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_track_large_chunks controls whether requests for large chunks
|
||||||
|
are allocated in their own untracked mmapped regions, separate from
|
||||||
|
others in this mspace. By default large chunks are not tracked,
|
||||||
|
which reduces fragmentation. However, such chunks are not
|
||||||
|
necessarily released to the system upon destroy_mspace. Enabling
|
||||||
|
tracking by setting to true may increase fragmentation, but avoids
|
||||||
|
leakage when relying on destroy_mspace to release all memory
|
||||||
|
allocated using this space. The function returns the previous
|
||||||
|
setting.
|
||||||
|
*/
|
||||||
|
int mspace_track_large_chunks(mspace msp, int enable);
|
||||||
|
|
||||||
|
#if !NO_MALLINFO
|
||||||
|
/*
|
||||||
|
mspace_mallinfo behaves as mallinfo, but reports properties of
|
||||||
|
the given space.
|
||||||
|
*/
|
||||||
|
struct mallinfo mspace_mallinfo(mspace msp);
|
||||||
|
#endif /* NO_MALLINFO */
|
||||||
|
|
||||||
|
/*
|
||||||
|
An alias for mallopt.
|
||||||
|
*/
|
||||||
|
int mspace_mallopt(int, int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following operate identically to their malloc counterparts
|
||||||
|
but operate only for the given mspace argument
|
||||||
|
*/
|
||||||
|
void* mspace_malloc(mspace msp, size_t bytes);
|
||||||
|
void mspace_free(mspace msp, void* mem);
|
||||||
|
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
|
||||||
|
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
|
||||||
|
void* mspace_realloc_in_place(mspace msp, void* mem, size_t newsize);
|
||||||
|
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
|
||||||
|
void** mspace_independent_calloc(mspace msp, size_t n_elements,
|
||||||
|
size_t elem_size, void* chunks[]);
|
||||||
|
void** mspace_independent_comalloc(mspace msp, size_t n_elements,
|
||||||
|
size_t sizes[], void* chunks[]);
|
||||||
|
size_t mspace_bulk_free(mspace msp, void**, size_t n_elements);
|
||||||
|
size_t mspace_usable_size(const void* mem);
|
||||||
|
void mspace_malloc_stats(mspace msp);
|
||||||
|
int mspace_trim(mspace msp, size_t pad);
|
||||||
|
size_t mspace_footprint(mspace msp);
|
||||||
|
size_t mspace_max_footprint(mspace msp);
|
||||||
|
size_t mspace_footprint_limit(mspace msp);
|
||||||
|
size_t mspace_set_footprint_limit(mspace msp, size_t bytes);
|
||||||
|
void mspace_inspect_all(mspace msp,
|
||||||
|
void(*handler)(void *, void *, size_t, void*),
|
||||||
|
void* arg);
|
||||||
|
#endif /* MSPACES */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}; /* end of extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MALLOC_280_H */
|
||||||
107
lib/ulibc/string/memcpy.c
Normal file
107
lib/ulibc/string/memcpy.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Chris Torek.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uintptr_t word;
|
||||||
|
#define wsize sizeof(word)
|
||||||
|
#define wmask (wsize - 1)
|
||||||
|
|
||||||
|
void *memcpy(void *dst0, const void *src0, size_t length)
|
||||||
|
{
|
||||||
|
char *dst = dst0;
|
||||||
|
const char *src = src0;
|
||||||
|
size_t t;
|
||||||
|
|
||||||
|
if (length == 0 || dst == src) /* nothing to do */
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros: loop-t-times; and loop-t-times, t>0
|
||||||
|
*/
|
||||||
|
#define TLOOP(s) \
|
||||||
|
if (t) \
|
||||||
|
TLOOP1(s)
|
||||||
|
#define TLOOP1(s) \
|
||||||
|
do { \
|
||||||
|
s; \
|
||||||
|
} while (--t)
|
||||||
|
|
||||||
|
if ((uintptr_t)dst < (uintptr_t)src) {
|
||||||
|
/*
|
||||||
|
* Copy forward.
|
||||||
|
*/
|
||||||
|
t = (uintptr_t)src; /* only need low bits */
|
||||||
|
if ((t | (uintptr_t)dst) & wmask) {
|
||||||
|
/*
|
||||||
|
* Try to align operands. This cannot be done
|
||||||
|
* unless the low bits match.
|
||||||
|
*/
|
||||||
|
if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
|
||||||
|
t = length;
|
||||||
|
else
|
||||||
|
t = wsize - (t & wmask);
|
||||||
|
length -= t;
|
||||||
|
TLOOP1(*dst++ = *src++);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Copy whole words, then mop up any trailing bytes.
|
||||||
|
*/
|
||||||
|
t = length / wsize;
|
||||||
|
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
|
||||||
|
t = length & wmask;
|
||||||
|
TLOOP(*dst++ = *src++);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Copy backwards. Otherwise essentially the same.
|
||||||
|
* Alignment works as before, except that it takes
|
||||||
|
* (t&wmask) bytes to align, not wsize-(t&wmask).
|
||||||
|
*/
|
||||||
|
src += length;
|
||||||
|
dst += length;
|
||||||
|
t = (uintptr_t)src;
|
||||||
|
if ((t | (uintptr_t)dst) & wmask) {
|
||||||
|
if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
|
||||||
|
t = length;
|
||||||
|
else
|
||||||
|
t &= wmask;
|
||||||
|
length -= t;
|
||||||
|
TLOOP1(*--dst = *--src);
|
||||||
|
}
|
||||||
|
t = length / wsize;
|
||||||
|
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
|
||||||
|
t = length & wmask;
|
||||||
|
TLOOP(*--dst = *--src);
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return (dst0);
|
||||||
|
}
|
||||||
13
lib/ulibc/string/memset.c
Normal file
13
lib/ulibc/string/memset.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void *memset(void *str, int c, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char val = (unsigned char)c;
|
||||||
|
unsigned char *buf = str;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
buf[i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
21
lib/ulibc/string/strcmp.c
Normal file
21
lib/ulibc/string/strcmp.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
int strcmp(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; s1[i] == s2[i]; i++)
|
||||||
|
if (s1[i] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return s1[i] - s2[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int strncmp(const char *s1, const char *s2, unsigned long n)
|
||||||
|
{
|
||||||
|
for (; n > 0; s1++, s2++, --n)
|
||||||
|
if (*s1 != *s2)
|
||||||
|
return ((*(unsigned char *)s1 < *(unsigned char *)s2)
|
||||||
|
? -1
|
||||||
|
: 1);
|
||||||
|
else if (*s1 == '\0')
|
||||||
|
return 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
11
lib/ulibc/string/strlen.c
Normal file
11
lib/ulibc/string/strlen.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
size_t strlen(const char *str)
|
||||||
|
{
|
||||||
|
size_t res = 0;
|
||||||
|
while (str[res]) {
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
25
lib/ulibc/unistd/sbrk.c
Normal file
25
lib/ulibc/unistd/sbrk.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <mango/types.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define BRK_SIZE 0x400000
|
||||||
|
|
||||||
|
static kern_handle_t heap_region = KERN_HANDLE_INVALID;
|
||||||
|
static kern_handle_t heap_object = KERN_HANDLE_INVALID;
|
||||||
|
|
||||||
|
static void *init_brk(size_t size)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *sbrk(intptr_t increment)
|
||||||
|
{
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
if (heap_region == KERN_HANDLE_INVALID
|
||||||
|
|| heap_object == KERN_HANDLE_INVALID) {
|
||||||
|
return init_brk(BRK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)-1;
|
||||||
|
}
|
||||||
10
programs/systemd/CMakeLists.txt
Normal file
10
programs/systemd/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
file(GLOB sources *.c)
|
||||||
|
add_executable(systemd ${sources})
|
||||||
|
target_link_libraries(systemd libc libc-rt liblaunch libmango)
|
||||||
|
|
||||||
|
sysroot_add_program(
|
||||||
|
NAME systemd
|
||||||
|
BIN_DIR /usr/bin)
|
||||||
|
bsp_add_program(
|
||||||
|
NAME systemd
|
||||||
|
BIN_DIR /usr/bin)
|
||||||
4
programs/systemd/main.c
Normal file
4
programs/systemd/main.c
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
add_executable(test test.c)
|
add_executable(test test.c)
|
||||||
target_link_libraries(test c)
|
target_link_libraries(test libc libc-rt liblaunch)
|
||||||
|
|
||||||
sysroot_add_program(
|
sysroot_add_program(
|
||||||
NAME test
|
NAME test
|
||||||
|
|||||||
@@ -1,6 +1,157 @@
|
|||||||
#include <function.h>
|
#include <string.h>
|
||||||
|
|
||||||
int _start(void)
|
const char *s
|
||||||
|
= "RHZVNYYFPCGZIKWYLOZAKKLZGKWXDPXSTWNSWDBVDCPUMTAZCRNGNHGQPAGEWVAOCJST"
|
||||||
|
"PBXVWPKXQAHGETDTDETVYAEQGNBLEQIPHGGWKEDJAULOVMZKNABLUUXOTMHJNAVLSGCZ"
|
||||||
|
"QIFHIUCBCIRZIOFVHBPSGVBBZSRAQZYRPMYBNJDFTWSUUZVBQZTBUFUDJDYKUXWHDMXD"
|
||||||
|
"JKBSNWLFPUDGRMQPBCWVJZHOTJBTMGUSXQUZVXLDKWIKINXRFJKSYJEKDAPRQPMQMJPS"
|
||||||
|
"ICCTMELLKDFFJXOXISIXNVANFHLRPYMNPYCMUOYSPAYCKYJKRBZENHXYRJWRYXZGETMJ"
|
||||||
|
"XBFTCMSIHZQSCMLESDFKGTTNMCZSXEFMGXZYPWVPODMYTLDUOKGPMTMFBTQQHPBHMNCM"
|
||||||
|
"LYRGGUAIRSFFBRSKXOLJBWEMEODRQLXZJDRSTXBJOKOMUQKCJVKFHDYXCUUDHDEITHNH"
|
||||||
|
"VQLJJQMLYWGIDVLYCEJTJFJQLTKSAPZGEEZKVLQPHIVJNJVTXJUGPZODIFXTQNLBSFLG"
|
||||||
|
"NSPMGLUSEBOFJWXFFRBHIHYGGTILVVOJRPOFOIGDFCHLAZXLSOUCPCLZCBVWGZVKGDON"
|
||||||
|
"RPYOTSRWUNAGQSPHSGEQHOLUSOZCQQGJBLPKQNGKOPCVKLACDBPAPXDMGKLFPUOFQDWY"
|
||||||
|
"INIKZPLVFSZZZZHAYKXTETJDPMBHKNRCRLXZHFENZCABDTZULCRHCCVZFETBEBEJFVKJ"
|
||||||
|
"ADWFSHKKSMMKGTIHPAIAMWXTRJILBMWMBDZGRPZXHMJVCWPKSNPYPPNSAVQDSMANBFZO"
|
||||||
|
"LJBYKDOZNAPZRWEQDIIZRPNGZGHQWPIONPSAMBNNZERYMIQOVHRGZFXWVUARJMFWNPQP"
|
||||||
|
"GHDCZABLOYHCBCXAIDSPMDKZVBBOKHAHGTEPRQAIBVWTFBQDGDJPQGMVAGQQVMULVPMG"
|
||||||
|
"UPGEJUIZZXQRQKRJUCKDDZFTAHAAHMJLSISGFFOXOYNMJCAPPQXAVFSAFFRPRTEQLNCX"
|
||||||
|
"JVKTHBPZLAEXSIGVJASAERWDGDQDXASXHRSSCNAUMRWSQDZTOJHJGJLLXMJSTXBHOYPH"
|
||||||
|
"ELYKSXNJSPWPMFAKOOTXXTOEBLYFSOIJDWAOCTHDFOEBEEXVUBXOJDUCJWQOUUDOJNZG"
|
||||||
|
"PULPYTAOQEXMHSGOOUXHAJOKRHOOMZYMBHQNTQDWZPCXATDEKTYLNBKNUEIINHQTEGTR"
|
||||||
|
"ZKLMAKIIHHZBQIPXLAGADCFDYWEOJVHFPEMRDIOJYAMWSWEUOPJFEDGRGJOQNTSHRIJY"
|
||||||
|
"JPTOSWYZXJCGXLYVOWKAFGULLNCKIUZDWUXTHNYSWMMCJGTFVVVPJHEKYQVFRWLIZBBK"
|
||||||
|
"CNCRITFZYTQZZGZHXELBEYXSVVYRFBGRFPRDROUXKUMAGFYOJRMCLLHJVMQFYOBCXSEL"
|
||||||
|
"OQAQTRMLSGDAXWMBRSQHCIYYMBQQHMUQOKIANZCBGKHLCPUVUEZVKDTTSOWKKWIUBAIW"
|
||||||
|
"SOCJAUALJFEQQXJBHRRZBFMJZZMIWTFKQDPOBFIGABJTHFLLSZPWWGGLHLYXKBODKBIV"
|
||||||
|
"GAYGIKHNMTMJHCPRBQYAACGSFZPJWXUTRZFCGTLFQBVHZBKYBRMYTTCGIDKYWVRPJDTX"
|
||||||
|
"RKXGOPOQLNSEIGHTSAXGPBROFHQACSIVSLCXTEDUOEPRMGJDYWTKEHCXWINUDCAZWAEY"
|
||||||
|
"RQDKZRZXKWGHVWJDYHGFLCGKCLYCVHZTWWXPDBKTMBKBASERMURDREKNYVOCPHFSEGBQ"
|
||||||
|
"LAUHDDCAPPGOAFZYJYXPPAQLUQVKSDEHPPDXMNWAAYLHXBFEFXRLSMQNIYDECYVVPHEE"
|
||||||
|
"WXFFPEYLSHBXLYJWRABFKJYMJNWAUMVYJKZRDMPUQJKWVNTPRMHTAQGNSDLFTXVNIAIJ"
|
||||||
|
"HOIISROAJCWEOAIHYMDGWEOABPGIMBTTGWYVJDZOOMUSHYDPCMKWDIXDGJCGTQVXWBKP"
|
||||||
|
"DBCVJJDYIAPXKINQXACEMTJRCIAENGTTMWXVSQCCXRDVNZZNQDZTTYJHQGXZIJIIKPAU"
|
||||||
|
"TQJDDQQEPGYZNKCKNMVFCRHUECPVFZYVUWVMSCIQZBVLSTNFAHDDEQRKDOUAQVRVQAVB"
|
||||||
|
"ZCEMAJRJBVWKVBNEIQWWQSJPUVUKMBJIISCWXGGMWANYYLPCXHCBARMFTFMDXWSMKXPW"
|
||||||
|
"DZUGFBSGGWXLOFGYJVIDWNTSGODTHQNCKPWRJENDZNSCEYZRLEPNNYVBNUZMXAUWNAJD"
|
||||||
|
"XGTOLUAAIAHMDJERSESVFSMMHJKHIVIBWZLEAXUKRSWJOTFODRBZIJBRJQTFBVRQHITD"
|
||||||
|
"TDBAJZCZUKSIZJYDXWTSRPLXULXHGEKMWMICUYVAGNGEICEMMVWLLYWTAKWNGLRYOCIG"
|
||||||
|
"BEYTLVAZFHBYIJPUAQHITKHPWAQNEBQVAYZEINLRCKUZILAQPAGBJDWWLGCPQZOZVDQP"
|
||||||
|
"MWTIOAFMEMFKLGVGGHTTKNERTLPPQFALZMCWSOMJQQZMRABNKBCYPFJOWQCXJKXTNOMJ"
|
||||||
|
"MXAWMPFBJHOYHVOBDNWTKHYTISUQMFSNVBGUHDQFYCSZLZAFABKYQSZRQGKXOXORQPSJ"
|
||||||
|
"NKRVVAXMMVVPBSWMTHUNXBLSVIOOQPLRPROIBBQGNQVOXQXRNNMSFGUZEIGIYMLMLYYL"
|
||||||
|
"VINTZYXYXHUFMTQFPDGSFFDVCDMEZXSGQMMGJWMWANFSZNHDIIHVJFOZGMHAOVRUWWVX"
|
||||||
|
"RCOJJKZLTMAOGSRWNNXPYDCQWSSOFWUKFPKQGYLFSMZBZBKWSBMMZMFPOYYMLVYHQQQF"
|
||||||
|
"HORVESQYIKEBBKSEUYXUFRNNXZPUYESZWAKQQPAWZUHYJLXRXBFPRFSCHIHHDVAIKYDZ"
|
||||||
|
"IDLVQBCSGOSGFOUKVMKTODAHQVTACKAONRDYENPGSQFKGKYQROFOEKMJXKFIAEKWNRJH"
|
||||||
|
"RZCCSMNSSHZNSRTBGFJJDWAPVIOBDCQKMDEMUIWGMETBUTCGMMGXLHWWTXXQYAPMQQGU"
|
||||||
|
"CHECLYRWNFKHGRWYZISFYKSGTJXKTKIMJKTUWOQFHXUVTOBYUCOZKLCQCUIURHSIGUAU"
|
||||||
|
"FFSNEHFLHNGBNVTGPKCVCQLHEHLJRWPGSWHKFMMXSSCVTCUOEEZOFOPTDRUPPCYTRSKI"
|
||||||
|
"NJBPLOHMHQLWKMVBSZLZVDZEKXKSCNWPZTGZUXRYJEPENAYFCEKCAMWQLNYDHCSUUSTJ"
|
||||||
|
"GFZCTKDQYPEZKOOJQTYMWHZDDTCMYUXCAKFXISWQZDVETOAYIANBRSXLYKOGGHEEEGAX"
|
||||||
|
"SRIASWZBXTFCHLKMXQDYNLZICZZANCBUVGWFWFHYAWVLQXTQPGPQGRGBEZVIIGZJUVQU"
|
||||||
|
"PNXEMZDIFXAKSHTCCBQSAXWFBNLRYQKXKXQHAFZTUICFQVYOXQEHASXNSVUTYKSVYTMH"
|
||||||
|
"UTPBEVILWSKGQXPAEEOPUSMGQVPWFMRZRIMJZRRQRIZBTTRROUWENBHUYVMOMVPFDLZH"
|
||||||
|
"XMXYRNASODBTLCNRDSLGPTZBZHKTSMHIVNFJOMOFPHDANVSVOYZSTKOQJLDPKLOMAYUU"
|
||||||
|
"CKWTOTDONTXKCEGVXKZNNFIUXHLJPFFNVMWSFPXZKROEIGQNGXWDRFJWDCUEGJCUJGVG"
|
||||||
|
"PHYKQEWVOHHPURHBBIEZCKQCFUFFBDXYRNOHAVJISOQYXMRXIEFEISFEZHLNTJXYEAKM"
|
||||||
|
"EKZPJQVQBKPXPFSOANBBJBAFJQEMPIELYUHYCHUTADTCLFXUQLXWTJEFLJXVBRQXYSIR"
|
||||||
|
"RPMTNMFMUCHQJEVXUSFYUUYJHLEQBHUQOTVADYQGRXVLUPQXVXEDIGNSCYNMKPWLFLHZ"
|
||||||
|
"LMQGPTMBDVUJOBSXDFHKSIEXJJQTURPNZVQDLUEJHQZOQSBMPMBEQOCOSEKVXIVSQIQL"
|
||||||
|
"GSQAUMIAHHLQCBCQWFJWHSYNRFFTBKORISDYNRSMPVERKRJBWGYJRXMKHJDAKRANHFDH"
|
||||||
|
"WTZOHYRVCTTUXCRAFNOLYPRGDYTXNSOTCDNFVVURJILWVDWOCGPQOZIGGNOEAHCBYGMC"
|
||||||
|
"XGXAADYMYDAUXPDFADTVEQTHZRGYASPJRDIKJUFIRXGMFSCIURDNFIDUUDEKPFGWECZC"
|
||||||
|
"OOFZWESHSPSOOBWZKIGODSLXCALULNOLQLCMMLSQDWJDTEOIYXFCLSLKJKGCGURXEEIN"
|
||||||
|
"SCUQTRDGMYXFZEFBATVSYVAJISCBVDBZAJAPKBBQTQNNRZYBLGWPCIORYJJEKIZXRRCG"
|
||||||
|
"ZHGQNMGWVNIANJXYJMWRCGDGDFFQISSZOWTQOKWRGXSGRUSJOHABJUEUIHNTLCXJQPNF"
|
||||||
|
"YUKTQCGRFGZOQWYLJOGOGSRDXESAOTHZVHBEOOYJZYTMOSUUXDQNKTQBVUMRBPJEJIBU"
|
||||||
|
"TOVXSGYSTADWQKFUEFWJDCAYTEYVZYDCQTHXJWYUESZSLRBKRAMLVVVBMEYSYFNBLKTY"
|
||||||
|
"UJRQBOKJQTYXTOFPWGWEEANVFYMAVRKMNJARUOKTZTMMJKNVFEVSECABUZGGUEHRJIHO"
|
||||||
|
"JODXJOOGFZWNURNEXBUCCUHUDYXBZTNJZSQGHAGYLJQSSJERWEGUFAJXGNBXDWVFSCEG"
|
||||||
|
"SUCLQLHHTRQADZIBKFCBBEXUDLPCFUDONSHUUCREKHDUBQBKMECPPOGFYIUZNUDKTILB"
|
||||||
|
"IHMYNAMJIDTJEQTVPFZDNONMWFIJEAUOLPWOZVKEFTXRCXNWHWPYDHLWNSWTMUEIBMSK"
|
||||||
|
"FWROAFBMEOJAVLMNCNWEMGRUDKRPENXCJQQGLPCODNOTGPOQFZTOBEBJIDAMMZARXTMC"
|
||||||
|
"EAHKYNTYZKWCUFYOSCOPICKIDAUSZHWNTVRRSTIMHFBUALQECIZKYFUYJHDTFDODXXNJ"
|
||||||
|
"AKZNUMYZSHIGZQQXBTORWFCGQFKFURMZYWBAQSHAJEASIYAFQZDOUHBJXODDUAWNKWVB"
|
||||||
|
"NABZSUNRULZDXKBRGVCKUIYVRVRMTDFSWCTCDYKBZDELJBDIHLOALYEKHNMECBWRZQBK"
|
||||||
|
"XLWFYJYECKOJOGXJYBKFSUQZKEUWBHEWNHSZKJPRQRMLRFLJWBDZEJQVYRAFQGEOGUBU"
|
||||||
|
"SVVWUGKXHSXHRXWCZKASIYPZZDLRUVBNBUQEEPZPHMSNUETUKMYWNJLEZWVOLZBQMLWE"
|
||||||
|
"YPPVBOTADNFNJWUZKDWRXCJCMDQPGPBIVAVQJVTHEPLXEKPSPJQFNGILKTUETORGMHGH"
|
||||||
|
"HHXTZIXUXPDLKNYGHNNTKAZFCGCUONFANKRXHGPQLPDJACZDMSSFPJHRPPGGSVEYKQHF"
|
||||||
|
"JKASAYIFKXXVEYRCLIMLDEUQWIHZXPLKDCHUFYAHLOQUJMJCXTHFAOSOEYWOMFAZHGPE"
|
||||||
|
"UNYKWLFYQPMRYXDVGWWMOLXHCHQADSYAAQMLBGGNQELFWMYHPWNIDOIFLGHGQUPCVPHS"
|
||||||
|
"WDGERQMWOZBWFHTOSINKTPXQLFGHLVALHCYSPKFBWSYTUHMZQNZSDAQTAZLPHSYZKROA"
|
||||||
|
"PSKJEWCRABAGYIIAYAUOVMTYIQOWYWHLLEXOOVZNLXOIPFNRYHDJYVTJLOHODYRBBBSB"
|
||||||
|
"NPQCNUZHYTWDAQSEBEMDSEDTKORHUCILESZYYYLJNRCFHAWNUMQHDQKXGCJIZOGBDVTU"
|
||||||
|
"PWNKAHKIRBHINKVRRBOPVAWCSPVMTNQQYDYLCKHPKRFYCAYUPGAOQLJSTHGMCXUUQIVI"
|
||||||
|
"MNPISKLETFEWNDDTDHLCQXNGRJJZHGJYYWNXKQIWXENKWQAGAXTCTLGWNVXDMMPHYPBQ"
|
||||||
|
"GWWNCWJWYVBVYOWOEJJPZAZGKJEQHPDBYUQBMOLOIMZXYXFOBNNPMGDCTXLCHBEBHCOS"
|
||||||
|
"HGKAEBGPLANNUHMOHWHAQEWFJSWPIFTWZNKWHKZYDXDAJODTHPXPIGVFYVDNWEQFKKIC"
|
||||||
|
"EBMGPSBVTPXODJVAYJAURNSFOCUNJROYEMOELHMIGLFDMJQFVEOSINHIWDUUIPNSBHEC"
|
||||||
|
"TKUFRERFNYCWSSGCYQWMXOQFCZPCSAVRBMSFZEYDBSWWHYLHIGGIDQJRTLNJOMWQVKES"
|
||||||
|
"KTFWQIRKJEMAZSMFQQSSTCXKOUZLJJWNYJJKSHPAOTEWEKKABTJDOFRGKVBMJFKFFVSP"
|
||||||
|
"GPMUCDWAFPHLKKZGEYTQNFJBGJTSATHNVDWRKSMLAJAPHYEJXYEKCTKDFGDILOIRDWLV"
|
||||||
|
"LAMTOCSMRMXYYHPHYBMKAVDRWYSXVPLZUBPAVUUQDNRCNYPKUSWBTCHJMIHQJNXXXXQX"
|
||||||
|
"LIUZQDFCTJBHELXALVTAJDFIPIFAKJKCPPPPXAVPTOUTLTIGMBUWOIERHBYOIMWTTXOY"
|
||||||
|
"KCZKDVRSARRBMSQFZGGSVPVBHKBYXZBITZDBQDBZLQNPVEQTXECOHOJKEXUUIBXSORPF"
|
||||||
|
"THLTMDDDOYSQZBGMBGZFYAJMHWZOLRUUJAIHOLSCIYGHMRAEIKFLFNLEMHOPKVRTJCMJ"
|
||||||
|
"DKBKJCMDBPGUGPPZBCXYRLHZUYPMIQOXYOCGKBEHZFHGAAKQINMHUNTSJHPPZGNKFREX"
|
||||||
|
"HGGFEFDAWMCMIXEDLUPDAXNCTHFDMHJPZOGJILKJXRUQBGXKDXTBZXSPZLZUCNCZZYRU"
|
||||||
|
"DRUEVXRELACIWMGUIBKEXSYTBIJTJPJJLCIQQBVJGXHPCTSHPASIIAMPATSDCTXZAPCJ"
|
||||||
|
"ESVMBOTOLKGHVRZSBVOBSAAKRPSAFYNPIDVFUMNMJRGKWOANKHZYCABHWIWUJFLDPSFY"
|
||||||
|
"SPBXQEFLNEEMIGMWWXYTXNTHRXUZQKXCMBLEHGRBFPSUMGMBJFFWTAEFCLDBOHMNAICE"
|
||||||
|
"YAZCTBCHKXEIBYUTQEAOVDJVOLTYDJJUCPSXUEPTFZPSJOMQDSSKBAHRIVYHQJFVUQJH"
|
||||||
|
"HRAQYZLYTOAWWIIPEUPQEBYSKTRETZEDWVALVPISUBTOWJZQLVRWKLLLMWEAZZIGMTRV"
|
||||||
|
"DXJHBFOTBFYSKQYJSNVKINMYRAMBFMBZUVHEEUWRRCMLAPOKKIODTFIIVTIPTBMVMZIP"
|
||||||
|
"HKDIQRFOKYTVDLAPPUMYNZBJMZMDDQDTXZWOMAJSJETWLGSAJDNNCODMAMCGADNXJGPP"
|
||||||
|
"GMPQXTZYICNPVATOCYCCGVSAKGCSGCPVUFGNGJPCRVZQXIDIZYCEBNMLMYHUMJZNHGCZ"
|
||||||
|
"TIYTNXTCGMGSBGLIDHYABMLEBGAHLOEYVOAMROXQAFDNEIZAOFWDETNEZWJFHTYOEVDH"
|
||||||
|
"RZDIZNSNBDCERUYZRLFWAANFAETBEWWPNNMUYXVBVDKMWPJUZLEPXOJAZOAYNKZDTBJO"
|
||||||
|
"MKXEMIAGHIQIHXPZGWDEQJKBNTDIWPLDANSOQJTGVPPSROOXGEBBWKLXMUEKZBKTTQTN"
|
||||||
|
"HILWSXGGYZZFYPGDVMNGLGGBSZJYWXGVHAACMVKQLPYXWWJMOQJJCXQOUIRCXPYCITBW"
|
||||||
|
"WCOKSSDXXWHHSOPANMWVIKJFLYNBPQAUHWKZEQBDVWDDULWFVBXUBJVOMHNAELALFGZT"
|
||||||
|
"FHSVLXJTMSOAKGBXKHKDEKVVFRZPKLTRRKCREVPXQYEVGIHAUNEJDLWERMKWJJBONLPW"
|
||||||
|
"BNTDWFILGFYOOAPNXVBDGGYDCZWUSJLPLZRVYAVSQFEXRZACHLLGGDEJGURDPYFCQUCX"
|
||||||
|
"OTNJJUJMMBEYSKJPKBGMQAAWOSPYAWDPJEQRLDJVZMRCYSKBAOQYWTJXSRRRMSFGNFRX"
|
||||||
|
"VEWFGPXVPZQXGRGOLKIYCCAOAGCZSHGPEGVMWETUWVZXZKCJVGQNEJBICWINFFHIUSUE"
|
||||||
|
"SVKYPVAOKBQEMQNKAXHFDETVNNFPQAXQXFJSKJCFLAHNRQUQPXYELGDYJDEETNEYGTMQ"
|
||||||
|
"MYIGQUDGOUMZDQORHNVDXBCJYBFTCDEMATBUCGAEKONTAIRCOHHKJFORZVDQSOWKDLKU"
|
||||||
|
"UOTTLLKQHVKVYOLJWNRRWXEOJMDZIKPMZFBBJCQSVTMCFFZDCWLRQDKAOKEXFVDZCPHE"
|
||||||
|
"UGNBVSILDBRPBJKNZXIWTNOZEDDESKOGYFOWPZJBQIQXKQERGWTJCUXGTOHLAOWDLGPF"
|
||||||
|
"RHVNLXVTKDDCWWZUAXKJZKPMOZCZCYVOIRCJNIJAMFRPAWNKFYAGKHNEPKPFTTRXXGTN"
|
||||||
|
"XFHFJXQWMKDSODYMNWJIFQZJOCYHUKYNYKXSLJNMBKCUXETKQTSZAXZUEERRGNBFDXJW"
|
||||||
|
"IKSVAVDNXLHJXVNDGLFZNZYTMJPDDXCOPGEROKJOGHXLDZJTSWOXIVCJKLYYTKANVFIF"
|
||||||
|
"KRVVEXSZXREAOBPVQRZUQKIWNMPTFUWARTQJCDTPEOVDHTDCWAWTTMNLRTOPYGPBROQA"
|
||||||
|
"QSMTGDCATMYQDJZQAUBQPOZLXDIJCKEVXDTPDNCHNJXMHNRVLWLKSAUYTHVOIYAAHUCY"
|
||||||
|
"XUWPHXMFXBDNBSNZIVKZANBYCHTUDOLHVVXGFDRDOIRCCRTZRNPWFTHSQRYTLGETDTGZ"
|
||||||
|
"KQWQPZYUTFFVFRQCAJAFDJAUMHPRXGUTLMFKOGXQHGOACGELSACTSNJTSOGNJAODFCIB"
|
||||||
|
"EQGGZETTRWOLAPRYJIGCYSUIMDCRHRGBKJFPDXVGPSPGDMBOLAVARRJSNDMZIOPKTAMA"
|
||||||
|
"NRZOSWGMPBPDBPCUADFMIEWOEBNNDFHUJCFMWXAFDKSWUTMMSQZSFBOGSSKOITDUGLLA"
|
||||||
|
"NFCZSGCDFDWUDTBPFKMHROQMIQRLCNGGCSFTNCVXSJJGPUZQREUASWLVOFVHRZPQUYGE"
|
||||||
|
"TBCJUSBKOJVBDWDEGXWBJPFTBFEALLVFFREQSGIONNYQFBFNKENZKSWLEWGEJJPZLRPV"
|
||||||
|
"RLDHLELHFXXIEXDJOSAUGITKSWYCPMEBLWOLAEJXXARMXQCBEFKLOOIYRBYVWLNZKNCA"
|
||||||
|
"ISOZEWVWPUDRGLYYKWWTNCWPZLYYDBKARCATEJHLYYQFNYATGYJIUNMVLEGUYBJVEVVM"
|
||||||
|
"WBVJYQEGPZUOJYLWNEMODVPHTWTLURFETDHELDHPGEQWLRKZRFCEORRGYSBIJHPVNSNZ"
|
||||||
|
"CAVXFCESMJIXGJPGLKDREKYGBPQSACESXAAHVQYFBSYWDPHDNTOZTEGSCISTBUMLDOQP"
|
||||||
|
"WNQCSJUAENKYFCYIYENHTIAARBRTOCYDVMHPCPRGWQVDIFLHWMZWRGCWQTAIKCAJAMLG"
|
||||||
|
"OKGURQTGNNUSCBKTPUXIGKDUWUGMTLCAOTKMXVTAEYWNWBTIQMLVDIEVBAGJMCWMMGZI"
|
||||||
|
"USESSUIHYSYOXHFLNZVTCVATIUVWGDETJUEHTVQBJDGHIIDFYHTFDIDPLNGXLIBMKAYG"
|
||||||
|
"DOZLOFKQXVWSQPRYUKAMGEICLKOMYNLWEMKLWDOPEEZGTXVDQWMULORFGNLKNVVCGQXQ"
|
||||||
|
"CUIYKIAMJSJVQJKRBNBIEELCZLMPQILCEBLZZTKCPBOQLTMZRGTNWHPIUYWMBCNGIABH"
|
||||||
|
"WIAILEDQVNWKJGYWMZYWOZGRHQOUFGCAETYUTLYZBCHKANZYPXTLMVREDIWBPAISSWKP"
|
||||||
|
"IJIBRLWPFXQOLOFIXLUGDVMXNPJWBMMZYJUKUZPPTGVCRIMITUTPYLJOIDQGOMYUFSJB"
|
||||||
|
"MRAZFVZSFZUSNJYDWBUDMFTFDBRCZCZZERWZSOXVAZISSEOMPKHESJRLUMZBBLBIXPZR"
|
||||||
|
"UYRFMLZQMMZWMNXULVXZQPOUKPMXISKOPTEDXASVPAIENMUWMBNGIVWVOQQXKGYEAMAT"
|
||||||
|
"YLDPYAASJSACUYILVJBXLHEMYKRKXEIVCDWKPQUBHACBNBGVTQLFDFPLAGUWUPBNBSIT"
|
||||||
|
"UEENOTZFWDWNNYZTHJIBDYMCERWQNSDKDDUPPXPJTGDYQTFNSRQZZSZBYGSQHRRGSVAQ"
|
||||||
|
"QEICLCSLMWQYXGGJEPJWZXKJUCFHJRACHRHLCRQWKXSUFJNBOMGWAIBKNWUDBJTFWVBW"
|
||||||
|
"UPIUAKBMXXDVVKBEUAEHMOELYCJVEFJEDFBTITDNTEGRAIOACOHFCVERCTRMUZHPRNPQ"
|
||||||
|
"YCFDKGTRGWFEJAXVTTBMIAYLJZEJAAEOBCTIXHYNDWPXIWOVGXSOLTXIBPBLHYKHIDGX"
|
||||||
|
"HHXNVRCMUXBZGFIEDZDBZOKSMKRNYTWJGJBIMQIOZQRFROWMLNYPDDKTRESDVHHJNRMN"
|
||||||
|
"GASH";
|
||||||
|
|
||||||
|
int main(void)
|
||||||
{
|
{
|
||||||
return function();
|
const char *s = "Hello, world!";
|
||||||
|
return strlen(s);
|
||||||
}
|
}
|
||||||
|
|||||||
9
services/CMakeLists.txt
Normal file
9
services/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
file(GLOB items *)
|
||||||
|
|
||||||
|
foreach(item ${items})
|
||||||
|
if (NOT IS_DIRECTORY ${item})
|
||||||
|
continue()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_subdirectory(${item})
|
||||||
|
endforeach (item)
|
||||||
10
services/ldd/CMakeLists.txt
Normal file
10
services/ldd/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
file(GLOB sources *.c)
|
||||||
|
add_executable(ldd ${sources})
|
||||||
|
target_link_libraries(ldd ulibc libc-rt libmango)
|
||||||
|
|
||||||
|
sysroot_add_program(
|
||||||
|
NAME ldd
|
||||||
|
BIN_DIR /usr/bin)
|
||||||
|
bsp_add_program(
|
||||||
|
NAME ldd
|
||||||
|
BIN_DIR /usr/bin)
|
||||||
4
services/ldd/main.c
Normal file
4
services/ldd/main.c
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
add_subdirectory(ld)
|
||||||
|
add_subdirectory(bootstrap)
|
||||||
|
|||||||
14
sys/bootstrap/CMakeLists.txt
Normal file
14
sys/bootstrap/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
file(GLOB c_sources *.c *.h)
|
||||||
|
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
|
set_property(SOURCE ${arch_sources} PROPERTY LANGUAGE C)
|
||||||
|
|
||||||
|
add_executable(bootstrap ${c_sources} ${arch_sources})
|
||||||
|
|
||||||
|
target_link_libraries(bootstrap libmango ulibc liblaunch)
|
||||||
|
|
||||||
|
target_compile_options(bootstrap PRIVATE
|
||||||
|
-fPIC -pie -fno-stack-protector -nostdlib -ffreestanding)
|
||||||
|
target_link_options(bootstrap PRIVATE
|
||||||
|
-fPIC -static -pie -nostdlib -ffreestanding
|
||||||
|
-T ${CMAKE_CURRENT_SOURCE_DIR}/arch/${TARGET_ARCH}/layout.ld)
|
||||||
18
sys/bootstrap/arch/x86_64/layout.ld
Normal file
18
sys/bootstrap/arch/x86_64/layout.ld
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.text ALIGN(4K) : {
|
||||||
|
*(.text)
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN(4K) : {
|
||||||
|
*(.data)
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.interp)
|
||||||
|
*(.dynamic)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
sys/bootstrap/arch/x86_64/start.S
Normal file
15
sys/bootstrap/arch/x86_64/start.S
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.code64
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
|
||||||
|
.extern main
|
||||||
|
.type main, @function
|
||||||
|
|
||||||
|
.extern exit
|
||||||
|
.type exit, @function
|
||||||
|
|
||||||
|
_start:
|
||||||
|
call main
|
||||||
|
1: pause
|
||||||
|
jmp 1b
|
||||||
99
sys/bootstrap/main.c
Normal file
99
sys/bootstrap/main.c
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
#include <launch.h>
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/msg.h>
|
||||||
|
#include <mango/task.h>
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define INIT_PATH "/usr/bin/test"
|
||||||
|
|
||||||
|
static enum launch_status resolve_dependency(
|
||||||
|
struct launch_ctx *ctx,
|
||||||
|
const char *name,
|
||||||
|
kern_handle_t *out,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
char s[128];
|
||||||
|
while (*name == '/') {
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(s, sizeof s, "searching for library %s", name);
|
||||||
|
kern_log(s);
|
||||||
|
|
||||||
|
struct tar *fs = arg;
|
||||||
|
struct tar_file file = {0};
|
||||||
|
if (tar_open(fs, name, &file) != 0) {
|
||||||
|
snprintf(s, sizeof s, "cannot find library %s", name);
|
||||||
|
kern_log(s);
|
||||||
|
return LAUNCH_ERR_CANNOT_RESOLVE_DEPENDENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_handle_t image = KERN_HANDLE_INVALID;
|
||||||
|
int err = tar_file_create_vm_object(&file, &image);
|
||||||
|
if (err != 0) {
|
||||||
|
snprintf(s, sizeof s, "cannot load library %s", name);
|
||||||
|
kern_log(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = image;
|
||||||
|
return LAUNCH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(
|
||||||
|
int argc,
|
||||||
|
const char **argv,
|
||||||
|
kern_handle_t task,
|
||||||
|
kern_handle_t address_space,
|
||||||
|
uintptr_t bsp_base)
|
||||||
|
{
|
||||||
|
struct tar bsp = {0};
|
||||||
|
if (tar_init(&bsp, bsp_base) != 0) {
|
||||||
|
kern_log("cannot access bsp");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tar_file init = {0};
|
||||||
|
if (tar_open(&bsp, INIT_PATH, &init) != 0) {
|
||||||
|
kern_log("cannot find init program " INIT_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_trace("loading " INIT_PATH);
|
||||||
|
|
||||||
|
kern_handle_t image = KERN_HANDLE_INVALID;
|
||||||
|
int err = tar_file_create_vm_object(&init, &image);
|
||||||
|
if (err != 0) {
|
||||||
|
kern_log("cannot load executable " INIT_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_trace("loaded executable vm-object " INIT_PATH);
|
||||||
|
|
||||||
|
kern_tracef("task=%x, region=%x", task, address_space);
|
||||||
|
|
||||||
|
struct launch_ctx launch;
|
||||||
|
struct launch_result result;
|
||||||
|
struct launch_parameters params = {
|
||||||
|
.p_executable = image,
|
||||||
|
.p_parent_task = task,
|
||||||
|
.p_task_name = "init",
|
||||||
|
.p_local_address_space = address_space,
|
||||||
|
.p_resolver_arg = &bsp,
|
||||||
|
};
|
||||||
|
|
||||||
|
launch_ctx_init(&launch);
|
||||||
|
launch.ctx_resolve_library = resolve_dependency;
|
||||||
|
|
||||||
|
enum launch_status status
|
||||||
|
= launch_ctx_execute(&launch, ¶ms, LAUNCH_F_NONE, &result);
|
||||||
|
|
||||||
|
kern_tracef("launch result: %d", status);
|
||||||
|
|
||||||
|
return 102;
|
||||||
|
}
|
||||||
96
sys/bootstrap/tar.c
Normal file
96
sys/bootstrap/tar.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
#include <mango/handle.h>
|
||||||
|
#include <mango/vm.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
size_t getsize(const char *in)
|
||||||
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
size_t j;
|
||||||
|
size_t count = 1;
|
||||||
|
|
||||||
|
for (j = 11; j > 0; j--, count *= 8) {
|
||||||
|
size += ((in[j - 1] - '0') * count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_init(struct tar *tar, uintptr_t base)
|
||||||
|
{
|
||||||
|
memset(tar, 0x0, sizeof *tar);
|
||||||
|
tar->tar_entries = (struct tar_bin_header *)base;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_open(struct tar *tar, const char *path, struct tar_file *out)
|
||||||
|
{
|
||||||
|
while (*path == '/') {
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*path == '\0') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tar_bin_header *bin_header = tar->tar_entries;
|
||||||
|
struct tar_header header;
|
||||||
|
for (size_t i = 0;; i++) {
|
||||||
|
tar_header_decode(bin_header, &header);
|
||||||
|
if (bin_header->filename[0] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *s = (char *)bin_header;
|
||||||
|
s += sizeof *bin_header;
|
||||||
|
|
||||||
|
if (!strcmp(bin_header->filename, path)) {
|
||||||
|
out->f_header = header;
|
||||||
|
out->f_data = s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += header.size;
|
||||||
|
s += ((sizeof *bin_header)
|
||||||
|
- ((uintptr_t)s % (sizeof *bin_header)));
|
||||||
|
|
||||||
|
bin_header = (struct tar_bin_header *)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_file_create_vm_object(const struct tar_file *file, kern_handle_t *out)
|
||||||
|
{
|
||||||
|
const void *data = file->f_data;
|
||||||
|
size_t len = file->f_header.size;
|
||||||
|
kern_handle_t vmo = KERN_HANDLE_INVALID;
|
||||||
|
|
||||||
|
kern_status_t status = vm_object_create(
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
file->f_header.size,
|
||||||
|
VM_PROT_READ | VM_PROT_EXEC | VM_PROT_USER,
|
||||||
|
&vmo);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nr_written = 0;
|
||||||
|
status = vm_object_write(vmo, data, 0, len, &nr_written);
|
||||||
|
if (status != KERN_OK || nr_written != len) {
|
||||||
|
kern_handle_close(vmo);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = vmo;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_header_decode(const struct tar_bin_header *in, struct tar_header *out)
|
||||||
|
{
|
||||||
|
memcpy(out->filename, in->filename, sizeof out->filename);
|
||||||
|
out->size = getsize(in->size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
45
sys/bootstrap/tar.h
Normal file
45
sys/bootstrap/tar.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef TAR_H_
|
||||||
|
#define TAR_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct tar {
|
||||||
|
struct tar_bin_header *tar_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tar_bin_header {
|
||||||
|
char filename[100];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char size[12];
|
||||||
|
char mtime[12];
|
||||||
|
char chksum[8];
|
||||||
|
char typeflag[1];
|
||||||
|
} __attribute__((aligned(512)));
|
||||||
|
|
||||||
|
struct tar_header {
|
||||||
|
char filename[100];
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tar_file {
|
||||||
|
struct tar_header f_header;
|
||||||
|
const void *f_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int tar_init(struct tar *tar, uintptr_t base);
|
||||||
|
|
||||||
|
extern int tar_open(struct tar *tar, const char *path, struct tar_file *out);
|
||||||
|
|
||||||
|
extern int tar_file_create_vm_object(
|
||||||
|
const struct tar_file *file,
|
||||||
|
kern_handle_t *out);
|
||||||
|
|
||||||
|
extern int tar_header_decode(
|
||||||
|
const struct tar_bin_header *in,
|
||||||
|
struct tar_header *out);
|
||||||
|
|
||||||
|
#endif
|
||||||
24
sys/ld/CMakeLists.txt
Normal file
24
sys/ld/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
file(GLOB c_sources *.c *.h)
|
||||||
|
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
|
set_property(SOURCE ${arch_sources} PROPERTY LANGUAGE C)
|
||||||
|
|
||||||
|
add_executable(ld ${c_sources} ${arch_sources})
|
||||||
|
set_target_properties(ld PROPERTIES
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
OUTPUT_NAME "ld64"
|
||||||
|
SUFFIX ".so")
|
||||||
|
|
||||||
|
target_link_libraries(ld ulibc libmango)
|
||||||
|
|
||||||
|
target_compile_options(ld PRIVATE
|
||||||
|
-fPIC -fno-stack-protector -nostdlib -ffreestanding)
|
||||||
|
target_link_options(ld PRIVATE
|
||||||
|
-fPIC -nostdlib -ffreestanding -Wl,-shared)
|
||||||
|
|
||||||
|
sysroot_add_program(
|
||||||
|
NAME ld
|
||||||
|
BIN_DIR /lib)
|
||||||
|
bsp_add_program(
|
||||||
|
NAME ld
|
||||||
|
BIN_DIR /lib)
|
||||||
30
sys/ld/arch/x86_64/layout.ld
Normal file
30
sys/ld/arch/x86_64/layout.ld
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.text ALIGN(4K) : {
|
||||||
|
*(.text)
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata ALIGN(4K) : {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN(4K) : {
|
||||||
|
*(.data)
|
||||||
|
*(.bss)
|
||||||
|
*(.dynamic)
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic ALIGN(8) : {
|
||||||
|
*(.dynamic)
|
||||||
|
}
|
||||||
|
|
||||||
|
.got.plt ALIGN(4K) : {
|
||||||
|
*(.got.plt)
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.interp)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
sys/ld/arch/x86_64/start.S
Normal file
15
sys/ld/arch/x86_64/start.S
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.code64
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
|
||||||
|
.extern main
|
||||||
|
.type main, @function
|
||||||
|
|
||||||
|
.extern exit
|
||||||
|
.type exit, @function
|
||||||
|
|
||||||
|
_start:
|
||||||
|
call main
|
||||||
|
1: pause
|
||||||
|
jmp 1b
|
||||||
13
sys/ld/main.c
Normal file
13
sys/ld/main.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <mango/log.h>
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
int main(
|
||||||
|
int argc,
|
||||||
|
const char **argv,
|
||||||
|
kern_handle_t task,
|
||||||
|
kern_handle_t address_space,
|
||||||
|
uintptr_t bsp_base)
|
||||||
|
{
|
||||||
|
kern_log("ld!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tarfile
|
import tarfile
|
||||||
|
import struct
|
||||||
from lib.manifest import Manifest, Component
|
from lib.manifest import Manifest, Component
|
||||||
|
from lib.elf import ELF64Image
|
||||||
|
|
||||||
|
|
||||||
def reset():
|
def reset():
|
||||||
@@ -59,12 +61,13 @@ def add_binary():
|
|||||||
|
|
||||||
|
|
||||||
def build_bsp():
|
def build_bsp():
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 4:
|
||||||
print("USAGE: {} build-bsp <manifest-path> <dest-path>".format(sys.argv[0]))
|
print("USAGE: {} build-bsp <manifest-path> <bootstrap-program-path> <dest-path>".format(sys.argv[0]))
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
manifest_path = sys.argv[2]
|
manifest_path = sys.argv[2]
|
||||||
bsp_path = sys.argv[3]
|
bootstrap_path = sys.argv[3]
|
||||||
|
bsp_path = sys.argv[4]
|
||||||
|
|
||||||
if os.path.exists(bsp_path):
|
if os.path.exists(bsp_path):
|
||||||
os.remove(bsp_path)
|
os.remove(bsp_path)
|
||||||
@@ -82,9 +85,6 @@ def build_bsp():
|
|||||||
header_dest = header_dest[1:]
|
header_dest = header_dest[1:]
|
||||||
|
|
||||||
for f in os.listdir(header_src):
|
for f in os.listdir(header_src):
|
||||||
print('ADD {} -> {}'.format(
|
|
||||||
os.path.join(header_src, f),
|
|
||||||
os.path.join(header_dest, f)))
|
|
||||||
bsp_file.add(
|
bsp_file.add(
|
||||||
os.path.join(header_src, f),
|
os.path.join(header_src, f),
|
||||||
arcname=os.path.join(header_dest, f))
|
arcname=os.path.join(header_dest, f))
|
||||||
@@ -94,10 +94,54 @@ def build_bsp():
|
|||||||
binary_dest = b['dest']
|
binary_dest = b['dest']
|
||||||
while binary_dest.startswith('/'):
|
while binary_dest.startswith('/'):
|
||||||
binary_dest = binary_dest[1:]
|
binary_dest = binary_dest[1:]
|
||||||
|
binary_dest = os.path.join(binary_dest, os.path.basename(binary_src))
|
||||||
|
|
||||||
bsp_file.add(binary_src, arcname=binary_dest)
|
bsp_file.add(binary_src, arcname=binary_dest)
|
||||||
|
|
||||||
bsp_file.close()
|
bsp_file.close()
|
||||||
|
bootstrap_offset = os.path.getsize(bsp_path)
|
||||||
|
|
||||||
|
bsp = open(bsp_path, mode='ab')
|
||||||
|
prog = open(bootstrap_path, mode='rb')
|
||||||
|
|
||||||
|
padding = bootstrap_offset % 0x1000
|
||||||
|
bsp.write(b'\0' * padding)
|
||||||
|
bootstrap_offset += padding
|
||||||
|
prog_len = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
data = prog.read(1024)
|
||||||
|
bsp.write(data)
|
||||||
|
prog_len += len(data)
|
||||||
|
|
||||||
|
if len(data) < 1024:
|
||||||
|
break
|
||||||
|
|
||||||
|
prog.close
|
||||||
|
|
||||||
|
prog_elf = ELF64Image()
|
||||||
|
if prog_elf.load(bootstrap_path) != 0:
|
||||||
|
print('failed to parse bootstrap program')
|
||||||
|
|
||||||
|
for ph in prog_elf.ph_list:
|
||||||
|
print('{}: {}/{} ({}/{} bytes) {}'.format(
|
||||||
|
ph.type,
|
||||||
|
ph.offset, ph.vaddr,
|
||||||
|
ph.filesz, ph.memsz, ph.flags))
|
||||||
|
|
||||||
|
trailer = struct.pack('>IQIQIQQQQQQQ',
|
||||||
|
0xcafebabe,
|
||||||
|
0, bootstrap_offset,
|
||||||
|
bootstrap_offset, prog_len,
|
||||||
|
prog_elf.text.offset, prog_elf.text.vaddr, prog_elf.text.memsz,
|
||||||
|
prog_elf.data.offset, prog_elf.data.vaddr, prog_elf.data.memsz,
|
||||||
|
prog_elf.entry)
|
||||||
|
|
||||||
|
bsp.write(trailer)
|
||||||
|
|
||||||
|
bsp.close()
|
||||||
|
prog.close()
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1
util/lib/__init__.py
Normal file
1
util/lib/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import *
|
||||||
102
util/lib/elf.py
Normal file
102
util/lib/elf.py
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
from enum import Enum, Flag
|
||||||
|
import struct
|
||||||
|
|
||||||
|
class ELFPType(Enum):
|
||||||
|
NULL = 0
|
||||||
|
LOAD = 1
|
||||||
|
DYNAMIC = 2
|
||||||
|
INTERP = 3
|
||||||
|
NOTE = 4
|
||||||
|
SHLIB = 5
|
||||||
|
PHDR = 6
|
||||||
|
TLS = 7
|
||||||
|
|
||||||
|
|
||||||
|
class ELFPFlag(Flag):
|
||||||
|
NONE = 0
|
||||||
|
EXEC = 1
|
||||||
|
WRITE = 2
|
||||||
|
READ = 4
|
||||||
|
|
||||||
|
|
||||||
|
class ELFEndian(Enum):
|
||||||
|
LITTLE = 1
|
||||||
|
BIG = 2
|
||||||
|
|
||||||
|
|
||||||
|
class ELF64Phdr:
|
||||||
|
def __init__(self):
|
||||||
|
self.type = ELFPType.NULL
|
||||||
|
self.flags = 0
|
||||||
|
self.offset = 0
|
||||||
|
self.vaddr = 0
|
||||||
|
self.paddr = 0
|
||||||
|
self.filesz = 0
|
||||||
|
self.memsz = 0
|
||||||
|
self.align = 0
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def parse(self, buf, endian):
|
||||||
|
endian_marker = '>' if endian == ELFEndian.BIG else '<'
|
||||||
|
entry = struct.unpack('{}IIQQQQQQ'.format(endian_marker), buf)
|
||||||
|
|
||||||
|
self.type = ELFPType(entry[0])
|
||||||
|
self.flags = ELFPFlag.NONE
|
||||||
|
self.offset = entry[2]
|
||||||
|
self.vaddr = entry[3]
|
||||||
|
self.paddr = entry[4]
|
||||||
|
self.filesz = entry[5]
|
||||||
|
self.memsz = entry[6]
|
||||||
|
self.align = entry[7]
|
||||||
|
|
||||||
|
if entry[1] & ELFPFlag.READ.value: self.flags |= ELFPFlag.READ
|
||||||
|
if entry[1] & ELFPFlag.WRITE.value: self.flags |= ELFPFlag.WRITE
|
||||||
|
if entry[1] & ELFPFlag.EXEC.value: self.flags |= ELFPFlag.EXEC
|
||||||
|
|
||||||
|
|
||||||
|
class ELF64Image:
|
||||||
|
def __init__(self):
|
||||||
|
self.ph_list = []
|
||||||
|
self.text = None
|
||||||
|
self.data = None
|
||||||
|
self.entry = None
|
||||||
|
|
||||||
|
def load(self, path):
|
||||||
|
f = open(path, mode='rb')
|
||||||
|
ident_bytes = f.read(16)
|
||||||
|
|
||||||
|
ident = struct.unpack('BBBBBBBBBBBBBBBB', ident_bytes)
|
||||||
|
|
||||||
|
if ident[0] != 0x7F or ident[1] != ord('E') or ident[2] != ord('L') or ident[3] != ord('F'):
|
||||||
|
f.close()
|
||||||
|
return -1
|
||||||
|
|
||||||
|
endian = ELFEndian(ident[5])
|
||||||
|
endian_marker = '>' if endian == ELFEndian.BIG else '<'
|
||||||
|
|
||||||
|
hdr_bytes = f.read(48)
|
||||||
|
hdr = struct.unpack('{}HHIQQQIHHHHHH'.format(endian_marker), hdr_bytes)
|
||||||
|
|
||||||
|
self.entry = hdr[3]
|
||||||
|
phoff = hdr[4]
|
||||||
|
phnum = hdr[9]
|
||||||
|
phentsize = hdr[8]
|
||||||
|
|
||||||
|
for i in range(0, phnum):
|
||||||
|
f.seek(phoff + (i * phentsize))
|
||||||
|
phdr_bytes = f.read(phentsize)
|
||||||
|
|
||||||
|
phdr = ELF64Phdr()
|
||||||
|
phdr.parse(phdr_bytes, endian)
|
||||||
|
|
||||||
|
if phdr.flags == ELFPFlag.READ | ELFPFlag.EXEC:
|
||||||
|
self.text = phdr
|
||||||
|
if phdr.flags == ELFPFlag.READ | ELFPFlag.WRITE:
|
||||||
|
self.data = phdr
|
||||||
|
|
||||||
|
self.ph_list.append(phdr)
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
return 0
|
||||||
|
|
||||||
101
util/lib/manifest.py
Normal file
101
util/lib/manifest.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Component:
|
||||||
|
def __init__(self):
|
||||||
|
self.headers = []
|
||||||
|
self.binaries = []
|
||||||
|
return
|
||||||
|
|
||||||
|
def add_headers(self, src, dest):
|
||||||
|
for h in self.headers:
|
||||||
|
if h['src'] == src and h['dest'] == dest:
|
||||||
|
return
|
||||||
|
|
||||||
|
headers = {}
|
||||||
|
headers['src'] = src
|
||||||
|
headers['dest'] = dest
|
||||||
|
self.headers.append(headers)
|
||||||
|
|
||||||
|
|
||||||
|
def add_binary(self, src, dest):
|
||||||
|
for b in self.binaries:
|
||||||
|
if b['src'] == src and b['dest'] == dest:
|
||||||
|
return
|
||||||
|
|
||||||
|
binary = {}
|
||||||
|
binary['src'] = src
|
||||||
|
binary['dest'] = dest
|
||||||
|
self.binaries.append(binary)
|
||||||
|
|
||||||
|
|
||||||
|
def serialise(self):
|
||||||
|
data = {}
|
||||||
|
if len(self.headers) > 0:
|
||||||
|
data['headers'] = self.headers
|
||||||
|
|
||||||
|
if len(self.binaries) > 0:
|
||||||
|
data['binaries'] = self.binaries
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def deserialise(self, data):
|
||||||
|
if 'headers' in data:
|
||||||
|
self.headers = data['headers']
|
||||||
|
if 'binaries' in data:
|
||||||
|
self.binaries = data['binaries']
|
||||||
|
|
||||||
|
|
||||||
|
def get_headers(self):
|
||||||
|
return self.headers
|
||||||
|
|
||||||
|
|
||||||
|
def get_binaries(self):
|
||||||
|
return self.binaries
|
||||||
|
|
||||||
|
|
||||||
|
class Manifest:
|
||||||
|
def __init__(self, path):
|
||||||
|
self.path = path
|
||||||
|
self.components = {}
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
with open(self.path, 'r') as f:
|
||||||
|
self.data = json.load(f)
|
||||||
|
|
||||||
|
if 'components' not in self.data:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
for n, t in self.data['components'].items():
|
||||||
|
component = Component()
|
||||||
|
component.deserialise(t)
|
||||||
|
self.components[n] = component
|
||||||
|
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
component_data = {}
|
||||||
|
for n, t in self.components.items():
|
||||||
|
d = t.serialise()
|
||||||
|
component_data[n] = d
|
||||||
|
|
||||||
|
self.data['components'] = component_data
|
||||||
|
|
||||||
|
with open(self.path, 'w') as f:
|
||||||
|
json.dump(self.data, f, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.data = {}
|
||||||
|
|
||||||
|
|
||||||
|
def get_component(self, name):
|
||||||
|
if name in self.components:
|
||||||
|
return self.components[name]
|
||||||
|
|
||||||
|
component = Component()
|
||||||
|
self.components[name] = component
|
||||||
|
return component
|
||||||
|
|
||||||
|
def get_all_components(self):
|
||||||
|
return self.components
|
||||||
@@ -17,20 +17,22 @@ def reset():
|
|||||||
|
|
||||||
|
|
||||||
def add_headers():
|
def add_headers():
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 6:
|
||||||
print("USAGE: {} add-headers <manifest-path> <component-name> <source-directory> <dest-directory>".format(sys.argv[0]))
|
print("USAGE: {} add-headers <manifest-path> <component-name> <dest-directory> <source-directory>".format(sys.argv[0]))
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
manifest_path = sys.argv[2]
|
manifest_path = sys.argv[2]
|
||||||
component_name = sys.argv[3]
|
component_name = sys.argv[3]
|
||||||
dest_path = sys.argv[4]
|
dest_path = sys.argv[4]
|
||||||
src_path = sys.argv[5]
|
src_paths = sys.argv[5:]
|
||||||
|
|
||||||
manifest = Manifest(manifest_path)
|
manifest = Manifest(manifest_path)
|
||||||
manifest.load()
|
manifest.load()
|
||||||
|
|
||||||
component = manifest.get_component(component_name)
|
component = manifest.get_component(component_name)
|
||||||
component.add_headers(src_path, dest_path)
|
|
||||||
|
for p in src_paths:
|
||||||
|
component.add_headers(p, dest_path)
|
||||||
|
|
||||||
manifest.save()
|
manifest.save()
|
||||||
|
|
||||||
@@ -83,9 +85,18 @@ def build_sysroot():
|
|||||||
os.makedirs(header_dest)
|
os.makedirs(header_dest)
|
||||||
|
|
||||||
for f in os.listdir(header_src):
|
for f in os.listdir(header_src):
|
||||||
shutil.copy(
|
f_src = os.path.join(header_src, f)
|
||||||
os.path.join(header_src, f),
|
f_dst = os.path.join(header_dest, f)
|
||||||
os.path.join(header_dest, f))
|
if os.path.isfile(f_src):
|
||||||
|
shutil.copy(
|
||||||
|
os.path.join(header_src, f),
|
||||||
|
os.path.join(header_dest, f))
|
||||||
|
else:
|
||||||
|
shutil.copytree(
|
||||||
|
os.path.join(header_src, f),
|
||||||
|
os.path.join(header_dest, f),
|
||||||
|
dirs_exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
for b in c.get_binaries():
|
for b in c.get_binaries():
|
||||||
binary_src = b['src']
|
binary_src = b['src']
|
||||||
@@ -97,6 +108,9 @@ def build_sysroot():
|
|||||||
if not os.path.isdir(binary_dest):
|
if not os.path.isdir(binary_dest):
|
||||||
os.makedirs(binary_dest)
|
os.makedirs(binary_dest)
|
||||||
|
|
||||||
|
if binary_src.endswith('.s.o'):
|
||||||
|
binary_dest = os.path.join(binary_dest, os.path.basename(binary_src)[:-4] + '.o')
|
||||||
|
|
||||||
shutil.copy(binary_src, binary_dest)
|
shutil.copy(binary_src, binary_dest)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user