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/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(Rosetta C CXX ASM)
|
||||
|
||||
set(sys_dir ${CMAKE_CURRENT_BINARY_DIR}/sys)
|
||||
|
||||
set(kernel_name mango_kernel)
|
||||
set(bsp_name rosetta-system.bsp)
|
||||
|
||||
@@ -15,16 +17,21 @@ bsp_reset()
|
||||
sysroot_reset()
|
||||
|
||||
add_subdirectory(kernel)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(programs)
|
||||
add_subdirectory(sys)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(services)
|
||||
add_subdirectory(programs)
|
||||
|
||||
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(
|
||||
ID bsp
|
||||
SRC_PATH ${CMAKE_BINARY_DIR}/${bsp_name}
|
||||
SRC_PATH ${CMAKE_BINARY_DIR}/sys/${bsp_name}
|
||||
DEST_DIR /boot
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/${bsp_name})
|
||||
DEPENDS bsp)
|
||||
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(ASM_COMPILER x86_64-elf-as REQUIRED)
|
||||
|
||||
add_compile_definitions(__mango__=1)
|
||||
|
||||
set(CMAKE_C_COMPILER ${C_COMPILER})
|
||||
set(CMAKE_CXX_COMPILER ${CXX_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(LLDB lldb REQUIRED)
|
||||
|
||||
add_custom_target(run-kernel
|
||||
COMMAND ${QEMU} -kernel $<TARGET_FILE:${kernel_name}>
|
||||
DEPENDS ${kernel_name} ${bsp_name})
|
||||
COMMAND
|
||||
${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}
|
||||
add-binary ${bsp_manifest} ${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}"
|
||||
DEPENDS ${target_name} ${serialiser})
|
||||
|
||||
@@ -75,7 +72,7 @@ endfunction(bsp_add_program)
|
||||
|
||||
function(bsp_finalise)
|
||||
set(options)
|
||||
set(one_value_args BSP_NAME)
|
||||
set(one_value_args BOOTSTRAP_PROGRAM DEST_DIR BSP_NAME)
|
||||
set(multi_value_args)
|
||||
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||
@@ -83,13 +80,12 @@ function(bsp_finalise)
|
||||
"${one_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)
|
||||
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
|
||||
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)
|
||||
|
||||
@@ -30,6 +30,7 @@ function(sysroot_add_library)
|
||||
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}
|
||||
@@ -39,10 +40,64 @@ function(sysroot_add_library)
|
||||
${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_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})
|
||||
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)
|
||||
set(options)
|
||||
set(one_value_args NAME BIN_DIR)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function(rosetta_add_executable)
|
||||
set(options)
|
||||
set(one_value_args NAME SYSROOT_PATH)
|
||||
set(one_value_args NAME)
|
||||
set(multi_value_args
|
||||
SUBDIRS
|
||||
EXTRA_SOURCES)
|
||||
@@ -33,11 +33,77 @@ function(rosetta_add_executable)
|
||||
endfunction(rosetta_add_executable)
|
||||
|
||||
function(rosetta_add_library)
|
||||
set(options SHARED)
|
||||
set(one_value_args NAME SYSROOT_PATH)
|
||||
set(options STATIC SHARED)
|
||||
set(one_value_args NAME)
|
||||
set(multi_value_args
|
||||
SOURCE_DIRS
|
||||
EXTRA_SOURCES)
|
||||
PUBLIC_INCLUDE_DIRS
|
||||
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
|
||||
"${options}"
|
||||
"${one_value_args}"
|
||||
@@ -45,36 +111,70 @@ function(rosetta_add_library)
|
||||
|
||||
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}")
|
||||
if (arg_SHARED)
|
||||
add_library(${lib_name} SHARED
|
||||
${sources}
|
||||
${headers}
|
||||
${arg_EXTRA_SOURCES})
|
||||
else ()
|
||||
add_library(${lib_name} STATIC
|
||||
${sources}
|
||||
${headers}
|
||||
${arg_EXTRA_SOURCES})
|
||||
endif ()
|
||||
add_library(${lib_name} OBJECT
|
||||
${arg_SOURCES}
|
||||
${arg_HEADERS})
|
||||
|
||||
target_include_directories(${lib_name} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
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
|
||||
sys_header_dir ${arg_SYSROOT_PATH}/include
|
||||
sys_bin_dir ${arg_SYSROOT_PATH}/lib
|
||||
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)
|
||||
target_link_libraries(test c)
|
||||
target_link_libraries(test libc libc-rt liblaunch)
|
||||
|
||||
sysroot_add_program(
|
||||
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 shutil
|
||||
import tarfile
|
||||
import struct
|
||||
from lib.manifest import Manifest, Component
|
||||
from lib.elf import ELF64Image
|
||||
|
||||
|
||||
def reset():
|
||||
@@ -59,12 +61,13 @@ def add_binary():
|
||||
|
||||
|
||||
def build_bsp():
|
||||
if len(sys.argv) < 3:
|
||||
print("USAGE: {} build-bsp <manifest-path> <dest-path>".format(sys.argv[0]))
|
||||
if len(sys.argv) < 4:
|
||||
print("USAGE: {} build-bsp <manifest-path> <bootstrap-program-path> <dest-path>".format(sys.argv[0]))
|
||||
return -1
|
||||
|
||||
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):
|
||||
os.remove(bsp_path)
|
||||
@@ -82,9 +85,6 @@ def build_bsp():
|
||||
header_dest = header_dest[1:]
|
||||
|
||||
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(
|
||||
os.path.join(header_src, f),
|
||||
arcname=os.path.join(header_dest, f))
|
||||
@@ -94,10 +94,54 @@ def build_bsp():
|
||||
binary_dest = b['dest']
|
||||
while binary_dest.startswith('/'):
|
||||
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.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
|
||||
|
||||
|
||||
|
||||
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():
|
||||
if len(sys.argv) < 3:
|
||||
print("USAGE: {} add-headers <manifest-path> <component-name> <source-directory> <dest-directory>".format(sys.argv[0]))
|
||||
if len(sys.argv) < 6:
|
||||
print("USAGE: {} add-headers <manifest-path> <component-name> <dest-directory> <source-directory>".format(sys.argv[0]))
|
||||
return -1
|
||||
|
||||
manifest_path = sys.argv[2]
|
||||
component_name = sys.argv[3]
|
||||
dest_path = sys.argv[4]
|
||||
src_path = sys.argv[5]
|
||||
src_paths = sys.argv[5:]
|
||||
|
||||
manifest = Manifest(manifest_path)
|
||||
manifest.load()
|
||||
|
||||
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()
|
||||
|
||||
@@ -83,9 +85,18 @@ def build_sysroot():
|
||||
os.makedirs(header_dest)
|
||||
|
||||
for f in os.listdir(header_src):
|
||||
f_src = os.path.join(header_src, f)
|
||||
f_dst = 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():
|
||||
binary_src = b['src']
|
||||
@@ -97,6 +108,9 @@ def build_sysroot():
|
||||
if not os.path.isdir(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)
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user