Compare commits
12 Commits
ac8f669e6b
...
1e3e38b0e2
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e3e38b0e2 | |||
| c1e10e8b70 | |||
| 7b89a038a2 | |||
| a792bbe5db | |||
| dd46a378b3 | |||
| 33888e364b | |||
| a535c588f1 | |||
| 9f4c4cbc9d | |||
| 3e0fdb616c | |||
| 44cd6c551a | |||
| 60e1ca951c | |||
| 119a86b8e6 |
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
project(Rosetta C CXX ASM)
|
||||
|
||||
include(CheckPIESupported)
|
||||
|
||||
@@ -5,13 +5,13 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
||||
|
||||
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)
|
||||
#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_ASM_COMPILER ${ASM_COMPILER})
|
||||
|
||||
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)
|
||||
@@ -19,6 +19,7 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,--unresolved-symbols=report-all,--dynamic-linker
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE "-pie")
|
||||
set(CMAKE_C_LINK_PIE_SUPPORTED TRUE)
|
||||
set(CMAKE_C_LINK_NO_PIE_SUPPORTED TRUE)
|
||||
SET(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
|
||||
|
||||
set(CMAKE_C_OUTPUT_EXTENSION .o)
|
||||
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
||||
|
||||
2
kernel
2
kernel
Submodule kernel updated: a2c89df195...110f625f04
@@ -26,7 +26,7 @@ bsp_add_library(
|
||||
NAME libc
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc libmango libxpc-static interface::fs)
|
||||
target_link_libraries(libc PRIVATE libmango librosetta libxpc-static interface::fs)
|
||||
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
||||
|
||||
add_subdirectory(pthread)
|
||||
|
||||
@@ -8,13 +8,17 @@ foreach (dir ${source_dirs})
|
||||
set(headers ${headers} ${dir_headers})
|
||||
endforeach (dir)
|
||||
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
file(GLOB sys_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||
|
||||
set(component_sources ${sources} ${sys_sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-core
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||
SOURCES ${sources}
|
||||
SOURCES ${sources} ${sys_sources}
|
||||
HEADERS ${headers})
|
||||
|
||||
sysroot_add_library(
|
||||
@@ -22,4 +26,4 @@ sysroot_add_library(
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc-core libmango)
|
||||
target_link_libraries(libc-core PRIVATE libmango librosetta)
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
#include <errno.h>
|
||||
#include <mango/log.h>
|
||||
#include <mango/status.h>
|
||||
|
||||
static int __errno = 32;
|
||||
|
||||
int __attribute__((weak)) * __errno_location(void)
|
||||
{
|
||||
kern_log("using builtin errno");
|
||||
return &__errno;
|
||||
}
|
||||
|
||||
#if defined(BUILD_STATIC)
|
||||
int __set_errno(int err)
|
||||
{
|
||||
@@ -12,6 +21,7 @@ int __set_errno(int err)
|
||||
int __set_errno(int err)
|
||||
{
|
||||
/* TODO */
|
||||
*__errno_location() = err;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
18
lib/libc/core/sys/x86_64/init.c
Normal file
18
lib/libc/core/sys/x86_64/init.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <mango/log.h>
|
||||
#include <rosetta/bootstrap.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern int main(int, const char **, const char **);
|
||||
|
||||
void *__attribute__((weak)) pthread_self(void)
|
||||
{
|
||||
/* Nothing */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int __libc_init(const struct rosetta_bootstrap *bsinfo)
|
||||
{
|
||||
(volatile void)pthread_self();
|
||||
kern_logf("bsinfo = %p", bsinfo);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef ERRNO_H_
|
||||
#define ERRNO_H_
|
||||
|
||||
#define errno (*__errno_location())
|
||||
|
||||
#define SUCCESS 0 /* Success */
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
@@ -142,4 +144,6 @@
|
||||
extern int __set_errno(int err);
|
||||
extern int __errno_from_kern_status(unsigned int err);
|
||||
|
||||
extern int __attribute__((weak)) * __errno_location(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
set(source_dirs thread)
|
||||
set(pthread_source_dirs thread)
|
||||
|
||||
foreach (dir ${source_dirs})
|
||||
foreach (dir ${pthread_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})
|
||||
set(pthread_sources ${pthread_sources} ${dir_sources})
|
||||
set(pthread_headers ${pthread_headers} ${dir_headers})
|
||||
endforeach (dir)
|
||||
|
||||
file(GLOB sys_sources
|
||||
file(GLOB pthread_sys_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||
set_property(SOURCE ${sys_sources} PROPERTY LANGUAGE C)
|
||||
|
||||
set(sources ${sources} ${sys_sources})
|
||||
set(pthread_sources ${pthread_sources} ${pthread_sys_sources})
|
||||
|
||||
set(headers ${headers} ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread.h)
|
||||
set(public_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
set(pthread_headers ${pthread_headers} ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread.h)
|
||||
set(pthread_public_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-pthread
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dir}
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
PUBLIC_INCLUDE_DIRS ${pthread_public_include_dir}
|
||||
SOURCES ${pthread_sources}
|
||||
HEADERS ${pthread_headers})
|
||||
rosetta_add_library(SHARED
|
||||
NAME libpthread
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dir}
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
PUBLIC_INCLUDE_DIRS ${pthread_public_include_dir}
|
||||
SOURCES ${pthread_sources}
|
||||
HEADERS ${pthread_headers})
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc-pthread
|
||||
@@ -38,5 +37,10 @@ sysroot_add_library(
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc-pthread libc-io libmango)
|
||||
target_link_libraries(libpthread libmango libc)
|
||||
bsp_add_library(
|
||||
NAME libpthread
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc-pthread PRIVATE libc-io libmango)
|
||||
target_link_libraries(libpthread PRIVATE libmango)
|
||||
target_link_libraries(libpthread PUBLIC libc)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.code64
|
||||
|
||||
.global pthread_self
|
||||
.type pthread_self, @function
|
||||
.global __pthread_self
|
||||
.type __pthread_self, @function
|
||||
|
||||
pthread_self:
|
||||
__pthread_self:
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
|
||||
|
||||
12
lib/libc/pthread/thread/errno.c
Normal file
12
lib/libc/pthread/thread/errno.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "pthread.h"
|
||||
|
||||
#include <mango/log.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int *__errno_location(void)
|
||||
{
|
||||
struct __pthread *self = pthread_self();
|
||||
kern_logf("using pthread errno %p", &self->thr_errno);
|
||||
return &self->thr_errno;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ enum pthread_flags {
|
||||
|
||||
struct __pthread {
|
||||
struct __pthread *thr_self;
|
||||
int thr_errno;
|
||||
enum pthread_flags thr_flags;
|
||||
kern_handle_t thr_handle;
|
||||
void *thr_map_base;
|
||||
@@ -16,6 +17,7 @@ struct __pthread {
|
||||
void *thr_result;
|
||||
};
|
||||
|
||||
extern struct __pthread *__pthread_self(void);
|
||||
extern void __pthread_unmap_exit(
|
||||
kern_handle_t address_space,
|
||||
void *unmap_base,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "pthread.h"
|
||||
|
||||
#include <mango/task.h>
|
||||
#include <mango/types.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
static struct __pthread main_thread = {0};
|
||||
|
||||
struct __pthread *pthread_self(void)
|
||||
{
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
kern_handle_t self_handle = KERN_HANDLE_INVALID;
|
||||
kern_status_t status = thread_self(&self_handle);
|
||||
if (status != KERN_OK) {
|
||||
/* TODO set an errno value in a way that doesn't result
|
||||
* in a recursive call to pthread_self */
|
||||
return NULL;
|
||||
}
|
||||
struct __pthread *self = &main_thread;
|
||||
self->thr_self = self;
|
||||
self->thr_handle = self_handle;
|
||||
self->thr_map_base = self;
|
||||
self->thr_map_size = sizeof *self;
|
||||
thread_config_set(
|
||||
self_handle,
|
||||
THREAD_CFG_GSBASE,
|
||||
&self,
|
||||
sizeof(void *));
|
||||
init = 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
return __pthread_self();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
file(GLOB runtime_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
||||
set_property(SOURCE ${runtime_sources} PROPERTY LANGUAGE C)
|
||||
|
||||
rosetta_add_object_library(
|
||||
NAME libc-runtime STATIC
|
||||
|
||||
@@ -3,18 +3,20 @@
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
.extern main
|
||||
.type main, @function
|
||||
.extern __libc_init
|
||||
.type __libc_init, @function
|
||||
|
||||
.extern task_exit
|
||||
.type task_exit, @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
|
||||
# %rdi: (struct rosetta_bootstrap *)bs_info
|
||||
mov %rdi, %rbx
|
||||
call __libc_init
|
||||
|
||||
mov 0(%rbx), %rdi # argc
|
||||
mov 8(%rbx), %rsi # argv
|
||||
mov 24(%rbx), %rdx # envp
|
||||
call main
|
||||
|
||||
mov %rax, %rdi
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <fs/context.h>
|
||||
#include <fs/file.h>
|
||||
#include <fs/status.h>
|
||||
#include <mango/log.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern kern_status_t fs_msg_open(
|
||||
xpc_context_t *xpc,
|
||||
@@ -39,7 +41,7 @@ extern kern_status_t fs_msg_open(
|
||||
= fs_context_resolve_path(ctx, path_buf, &dent);
|
||||
if (fs_status != FS_SUCCESS) {
|
||||
fs_context_close_file(ctx, f);
|
||||
*out_err = fs_status_to_errno(status);
|
||||
*out_err = fs_status_to_errno(fs_status);
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,4 +18,4 @@ sysroot_add_library(
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(liblaunch librosetta libmango libc-core)
|
||||
target_link_libraries(liblaunch PRIVATE librosetta libmango libc-core)
|
||||
|
||||
@@ -70,15 +70,14 @@ static virt_addr_t write_bootstrap_data(
|
||||
bs->bs_argv = (const char **)remote_argv;
|
||||
}
|
||||
|
||||
if (bs->bs_envc > 0) {
|
||||
virt_addr_t remote_envp;
|
||||
envp = stack_writer_put(
|
||||
stack,
|
||||
NULL,
|
||||
bs->bs_envc * sizeof(char *),
|
||||
&remote_envp);
|
||||
bs->bs_envp = (const char **)remote_envp;
|
||||
}
|
||||
/* envc+1 so there is space for a null terminator */
|
||||
virt_addr_t remote_envp;
|
||||
envp = stack_writer_put(
|
||||
stack,
|
||||
NULL,
|
||||
(bs->bs_envc + 1) * sizeof(char *),
|
||||
&remote_envp);
|
||||
bs->bs_envp = (const char **)remote_envp;
|
||||
|
||||
size_t i = 0, j = 0;
|
||||
if (interpreter) {
|
||||
@@ -95,11 +94,12 @@ static virt_addr_t write_bootstrap_data(
|
||||
argv[i] = (const char *)arg_ptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < bs->bs_envc; i++) {
|
||||
virt_addr_t env_ptr;
|
||||
virt_addr_t env_ptr;
|
||||
for (i = 0; i < bs->bs_envc; i++) {
|
||||
stack_writer_put_string(stack, params->p_envp[i], &env_ptr);
|
||||
envp[i] = (const char *)env_ptr;
|
||||
}
|
||||
envp[i] = NULL;
|
||||
|
||||
return bs_remote;
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ sysroot_add_library(
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(librosetta libmango)
|
||||
target_link_libraries(librosetta PRIVATE libmango)
|
||||
|
||||
@@ -26,17 +26,17 @@ struct rosetta_bootstrap_channel {
|
||||
};
|
||||
|
||||
struct rosetta_bootstrap {
|
||||
int bs_argc;
|
||||
uintptr_t bs_argc;
|
||||
const char **bs_argv;
|
||||
|
||||
int bs_envc;
|
||||
uintptr_t bs_envc;
|
||||
const char **bs_envp;
|
||||
|
||||
const struct rosetta_bootstrap_handle *bs_handles;
|
||||
size_t bs_handles_count;
|
||||
uintptr_t bs_handles_count;
|
||||
|
||||
const struct rosetta_bootstrap_channel *bs_channels;
|
||||
size_t bs_channels_count;
|
||||
uintptr_t bs_channels_count;
|
||||
};
|
||||
|
||||
extern const struct rosetta_bootstrap_channel *rosetta_bootstrap_get_channel(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
file(GLOB sources *.c)
|
||||
add_executable(systemd ${sources})
|
||||
target_link_libraries(systemd libc libc-runtime liblaunch libmango)
|
||||
target_link_libraries(systemd libc libc-runtime libpthread liblaunch libmango)
|
||||
|
||||
sysroot_add_program(
|
||||
NAME systemd
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_executable(test test.c)
|
||||
target_link_libraries(test libc libc-runtime liblaunch)
|
||||
target_link_libraries(test libc libc-runtime libmango liblaunch)
|
||||
|
||||
sysroot_add_program(
|
||||
NAME test
|
||||
|
||||
@@ -1,12 +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 libc-core libc-malloc libc-pthread libfs-static liblaunch libxpc-static
|
||||
libmango librosetta
|
||||
libc-core libc-malloc libc-pthread
|
||||
libfs-static
|
||||
liblaunch
|
||||
libxpc-static
|
||||
interface::fs)
|
||||
|
||||
target_compile_options(bootstrap PRIVATE
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
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
|
||||
|
||||
@@ -12,8 +12,6 @@ _dl_runtime_resolve:
|
||||
pop %rax
|
||||
pop %r11
|
||||
|
||||
push %rsp
|
||||
push %rbp
|
||||
push %rdi
|
||||
push %rsi
|
||||
push %rdx
|
||||
@@ -41,7 +39,5 @@ _dl_runtime_resolve:
|
||||
pop %rdx
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
pop %rbp
|
||||
pop %rsp
|
||||
|
||||
jmp *%rax
|
||||
|
||||
195
sys/ld/elf.c
195
sys/ld/elf.c
@@ -1,5 +1,7 @@
|
||||
#include "elf.h"
|
||||
|
||||
#include "image-list.h"
|
||||
#include "ld.h"
|
||||
#include "resolve.h"
|
||||
|
||||
#include <errno.h>
|
||||
@@ -181,6 +183,7 @@ static int map_image(struct elf_image *image)
|
||||
}
|
||||
}
|
||||
|
||||
kern_logf("ld: image %s -> %zx", image->e_leaf.l_name, image->e_base);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -297,7 +300,7 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
|
||||
rela->r_addend);
|
||||
break;
|
||||
default:
|
||||
kern_log("Unknown relocation type");
|
||||
kern_trace("Unknown relocation type");
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
@@ -644,7 +647,7 @@ int elf_image_link(struct elf_image *img)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
extern int elf_image_collect_dependencies(
|
||||
int elf_image_collect_dependencies(
|
||||
struct elf_image *img,
|
||||
struct image_list *dest)
|
||||
{
|
||||
@@ -652,6 +655,7 @@ extern int elf_image_collect_dependencies(
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
kern_tracef("collecting dependencies for %s", img->e_leaf.l_name);
|
||||
int nr_added = 0;
|
||||
img->e_links = calloc(img->e_nr_links, sizeof(struct elf_image *));
|
||||
|
||||
@@ -663,24 +667,45 @@ extern int elf_image_collect_dependencies(
|
||||
const char *name = (const char *)img->e_base + img->e_strtab
|
||||
+ img->e_dyn[i].d_un.d_val;
|
||||
|
||||
if (image_list_get(dest, name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct elf_image *dep = NULL;
|
||||
int status = create_image_with_name(name, &dep);
|
||||
if (status != SUCCESS) {
|
||||
return -status;
|
||||
struct image_list_leaf *leaf = NULL;
|
||||
if ((leaf = image_list_get(dest, name))) {
|
||||
dep = QUEUE_CONTAINER(struct elf_image, e_leaf, leaf);
|
||||
} else {
|
||||
int status = create_image_with_name(name, &dep);
|
||||
if (status != SUCCESS) {
|
||||
return -status;
|
||||
}
|
||||
|
||||
image_list_put(dest, &dep->e_leaf);
|
||||
}
|
||||
|
||||
image_list_put(dest, &dep->e_leaf);
|
||||
img->e_links[nr_added] = dep;
|
||||
kern_tracef(
|
||||
"%s dependency %u = %s",
|
||||
img->e_leaf.l_name,
|
||||
nr_added,
|
||||
dep->e_leaf.l_name);
|
||||
nr_added++;
|
||||
}
|
||||
|
||||
return nr_added;
|
||||
}
|
||||
|
||||
int elf_image_add_dependency(struct elf_image *img, struct elf_image *dep)
|
||||
{
|
||||
struct elf_image **deps = realloc(
|
||||
img->e_links,
|
||||
sizeof(struct elf_image *) * img->e_nr_links + 1);
|
||||
if (!deps) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
deps[img->e_nr_links++] = dep;
|
||||
img->e_links = deps;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void elf_image_close(struct elf_image *image)
|
||||
{
|
||||
if (image->e_fd) {
|
||||
@@ -714,7 +739,7 @@ static uint32_t gnu_hash(const char *name)
|
||||
return h;
|
||||
}
|
||||
|
||||
static virt_addr_t find_symbol_stdhash(
|
||||
static const elf_sym_t *find_symbol_stdhash(
|
||||
struct elf_image *img,
|
||||
const char *name,
|
||||
uint32_t hash)
|
||||
@@ -733,15 +758,22 @@ static virt_addr_t find_symbol_stdhash(
|
||||
const uint32_t *chain = &bucket[nbucket];
|
||||
|
||||
for (uint32_t i = bucket[hash % nbucket]; i; i = chain[i]) {
|
||||
if (strcmp(name, strtab + symtab[i].st_name) == 0) {
|
||||
return img->e_base + symtab[i].st_value;
|
||||
const elf_sym_t *sym = &symtab[i];
|
||||
if (strcmp(name, strtab + sym->st_name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sym->st_value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virt_addr_t find_symbol_gnuhash(
|
||||
static const elf_sym_t *find_symbol_gnuhash(
|
||||
struct elf_image *img,
|
||||
const char *name,
|
||||
uint32_t hash)
|
||||
@@ -749,12 +781,14 @@ static virt_addr_t find_symbol_gnuhash(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virt_addr_t find_symbol_slow(struct elf_image *img, const char *name)
|
||||
static const elf_sym_t *find_symbol_slow(
|
||||
struct elf_image *img,
|
||||
const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virt_addr_t find_symbol(
|
||||
static const elf_sym_t *find_symbol(
|
||||
struct elf_image *img,
|
||||
const char *name,
|
||||
uint32_t std_hash,
|
||||
@@ -770,31 +804,144 @@ static virt_addr_t find_symbol(
|
||||
}
|
||||
}
|
||||
|
||||
virt_addr_t elf_image_find_symbol(struct elf_image *img, const char *name)
|
||||
int elf_image_find_symbol(
|
||||
struct elf_image *img,
|
||||
const char *name,
|
||||
struct elf_symbol *out)
|
||||
{
|
||||
uint32_t std_hash_val = std_hash(name);
|
||||
uint32_t gnu_hash_val = gnu_hash(name);
|
||||
return find_symbol(img, name, std_hash_val, gnu_hash_val);
|
||||
const elf_sym_t *sym
|
||||
= find_symbol(img, name, std_hash_val, gnu_hash_val);
|
||||
|
||||
if (sym) {
|
||||
out->sym_container = img;
|
||||
out->sym_info = sym;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
virt_addr_t elf_image_find_linked_symbol(
|
||||
int elf_image_find_linked_symbol(
|
||||
struct elf_image *img,
|
||||
const char *name)
|
||||
const char *name,
|
||||
struct elf_symbol *out)
|
||||
{
|
||||
uint32_t std_hash_val = std_hash(name);
|
||||
uint32_t gnu_hash_val = gnu_hash(name);
|
||||
|
||||
virt_addr_t sym = 0;
|
||||
struct elf_image *candidate_container = NULL;
|
||||
const elf_sym_t *candidate = NULL;
|
||||
const elf_sym_t *sym = NULL;
|
||||
|
||||
kern_tracef("searching %p (%zx)", img, img->e_base);
|
||||
sym = find_symbol(img, name, std_hash_val, gnu_hash_val);
|
||||
if (sym) {
|
||||
if (ELF64_ST_BIND(sym->st_info) == STB_WEAK) {
|
||||
kern_tracef(
|
||||
"found %s:%s (weak): %zx",
|
||||
img->e_leaf.l_name,
|
||||
name,
|
||||
sym->st_value);
|
||||
candidate = sym;
|
||||
candidate_container = img;
|
||||
} else {
|
||||
kern_tracef(
|
||||
"found %s:%s (strong): %zx",
|
||||
img->e_leaf.l_name,
|
||||
name,
|
||||
sym->st_value);
|
||||
out->sym_container = img;
|
||||
out->sym_info = sym;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < img->e_nr_links; i++) {
|
||||
kern_tracef(
|
||||
"searching %p (%zx)",
|
||||
img->e_links[i],
|
||||
img->e_links[i]->e_base);
|
||||
sym = find_symbol(
|
||||
img->e_links[i],
|
||||
name,
|
||||
std_hash_val,
|
||||
gnu_hash_val);
|
||||
if (sym) {
|
||||
break;
|
||||
if (!sym) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ELF64_ST_BIND(sym->st_info) == STB_WEAK) {
|
||||
kern_tracef(
|
||||
"found %s:%s (weak): %zx",
|
||||
img->e_links[i]->e_leaf.l_name,
|
||||
name,
|
||||
sym->st_value);
|
||||
candidate = sym;
|
||||
candidate_container = img->e_links[i];
|
||||
} else {
|
||||
kern_tracef(
|
||||
"found %s:%s (strong): %zx",
|
||||
img->e_links[i]->e_leaf.l_name,
|
||||
name,
|
||||
sym->st_value);
|
||||
out->sym_container = img;
|
||||
out->sym_info = sym;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return sym;
|
||||
if (candidate) {
|
||||
out->sym_container = candidate_container;
|
||||
out->sym_info = candidate;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
virt_addr_t find_global_symbol(const char *name)
|
||||
{
|
||||
struct image_list *images = global_image_list();
|
||||
if (!images) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct image_list_iterator it;
|
||||
image_list_iterator_begin(&it, images);
|
||||
|
||||
virt_addr_t candidate = 0;
|
||||
struct elf_symbol sym = {0};
|
||||
while (it.it_leaf) {
|
||||
struct elf_image *image
|
||||
= QUEUE_CONTAINER(struct elf_image, e_leaf, it.it_leaf);
|
||||
int status = elf_image_find_symbol(image, name, &sym);
|
||||
if (status == ENOENT) {
|
||||
image_list_iterator_move_next(&it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ELF64_ST_BIND(sym.sym_info->st_info) == STB_WEAK) {
|
||||
kern_tracef(
|
||||
"found %s:%s (weak): %zx",
|
||||
sym.sym_container->e_leaf.l_name,
|
||||
name,
|
||||
sym.sym_info->st_value);
|
||||
candidate = (virt_addr_t)sym.sym_container->e_base
|
||||
+ sym.sym_info->st_value;
|
||||
} else {
|
||||
kern_tracef(
|
||||
"found %s:%s (strong): %zx",
|
||||
sym.sym_container->e_leaf.l_name,
|
||||
name,
|
||||
sym.sym_info->st_value);
|
||||
return (virt_addr_t)sym.sym_container->e_base
|
||||
+ sym.sym_info->st_value;
|
||||
}
|
||||
|
||||
image_list_iterator_move_next(&it);
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
24
sys/ld/elf.h
24
sys/ld/elf.h
@@ -344,6 +344,11 @@ struct elf_image {
|
||||
size_t e_nr_links;
|
||||
};
|
||||
|
||||
struct elf_symbol {
|
||||
struct elf_image *sym_container;
|
||||
const elf_sym_t *sym_info;
|
||||
};
|
||||
|
||||
extern const char *elf_image_status_to_string(enum elf_image_status status);
|
||||
|
||||
extern int elf_image_open(const char *path, struct elf_image **out);
|
||||
@@ -352,14 +357,25 @@ extern int elf_image_load(struct elf_image *img);
|
||||
extern int elf_image_collect_dependencies(
|
||||
struct elf_image *img,
|
||||
struct image_list *dest);
|
||||
extern int elf_image_add_dependency(
|
||||
struct elf_image *img,
|
||||
struct elf_image *dep);
|
||||
extern int elf_image_link(struct elf_image *img);
|
||||
extern void elf_image_close(struct elf_image *img);
|
||||
|
||||
extern virt_addr_t elf_image_find_symbol(
|
||||
extern int elf_image_find_symbol(
|
||||
struct elf_image *img,
|
||||
const char *name);
|
||||
extern virt_addr_t elf_image_find_linked_symbol(
|
||||
const char *name,
|
||||
struct elf_symbol *out);
|
||||
extern int elf_image_find_symbol(
|
||||
struct elf_image *img,
|
||||
const char *name);
|
||||
const char *name,
|
||||
struct elf_symbol *out);
|
||||
extern int elf_image_find_linked_symbol(
|
||||
struct elf_image *img,
|
||||
const char *name,
|
||||
struct elf_symbol *out);
|
||||
|
||||
extern virt_addr_t find_global_symbol(const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
8
sys/ld/ld.h
Normal file
8
sys/ld/ld.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef LD_H_
|
||||
#define LD_H_
|
||||
|
||||
struct image_list;
|
||||
|
||||
extern struct image_list *global_image_list(void);
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,13 @@ static const char *search_paths[] = {
|
||||
static const size_t nr_search_paths
|
||||
= sizeof search_paths / sizeof search_paths[0];
|
||||
|
||||
static struct image_list images = {0};
|
||||
|
||||
struct image_list *global_image_list(void)
|
||||
{
|
||||
return &images;
|
||||
}
|
||||
|
||||
static void report_error(const char *name, int err, const char *msg, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
@@ -35,7 +42,7 @@ static void report_error(const char *name, int err, const char *msg, ...)
|
||||
vsnprintf(buf, sizeof buf, msg, arg);
|
||||
va_end(arg);
|
||||
|
||||
kern_tracef("%s: %s: %s", name, buf, strerror(err));
|
||||
kern_logf("%s: %s: %s", name, buf, strerror(err));
|
||||
}
|
||||
|
||||
static const char *get_image_name(const char *path)
|
||||
@@ -71,7 +78,7 @@ static int find_image(struct elf_image *img)
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
static int load_images(struct image_list *list)
|
||||
static int load_images(const char *task_name, struct image_list *list)
|
||||
{
|
||||
int status = SUCCESS;
|
||||
struct image_list_iterator it;
|
||||
@@ -91,18 +98,33 @@ static int load_images(struct image_list *list)
|
||||
/* Find the image using its name */
|
||||
status = find_image(image);
|
||||
if (status != SUCCESS) {
|
||||
report_error(
|
||||
task_name,
|
||||
status,
|
||||
"error while loading %s",
|
||||
image->e_leaf.l_name);
|
||||
return status;
|
||||
}
|
||||
case ELF_IMAGE_OPEN:
|
||||
/* parse the image */
|
||||
status = elf_image_parse(image);
|
||||
if (status != SUCCESS) {
|
||||
report_error(
|
||||
task_name,
|
||||
status,
|
||||
"error while loading %s",
|
||||
image->e_leaf.l_name);
|
||||
return status;
|
||||
}
|
||||
case ELF_IMAGE_PARSED:
|
||||
/* load the image */
|
||||
status = elf_image_load(image);
|
||||
if (status != SUCCESS) {
|
||||
report_error(
|
||||
task_name,
|
||||
status,
|
||||
"error while loading %s",
|
||||
image->e_leaf.l_name);
|
||||
return status;
|
||||
}
|
||||
case ELF_IMAGE_LOADED:
|
||||
@@ -114,6 +136,11 @@ static int load_images(struct image_list *list)
|
||||
}
|
||||
|
||||
if (new_dependencies < 0) {
|
||||
report_error(
|
||||
task_name,
|
||||
-new_dependencies,
|
||||
"error while loading %s",
|
||||
image->e_leaf.l_name);
|
||||
return -new_dependencies;
|
||||
}
|
||||
|
||||
@@ -127,7 +154,7 @@ static int load_images(struct image_list *list)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int link_images(struct image_list *list)
|
||||
static int link_images(const char *task_name, struct image_list *list)
|
||||
{
|
||||
int status = SUCCESS;
|
||||
struct image_list_iterator it;
|
||||
@@ -143,6 +170,14 @@ static int link_images(struct image_list *list)
|
||||
elf_image_status_to_string(image->e_status));
|
||||
|
||||
status = elf_image_link(image);
|
||||
if (status != SUCCESS) {
|
||||
report_error(
|
||||
task_name,
|
||||
status,
|
||||
"error while loading %s",
|
||||
image->e_leaf.l_name);
|
||||
return status;
|
||||
}
|
||||
|
||||
image_list_iterator_move_next(&it);
|
||||
}
|
||||
@@ -162,7 +197,6 @@ int main(const struct rosetta_bootstrap *bs)
|
||||
const char *task_name = bs->bs_argv[2];
|
||||
const char *image_name = get_image_name(exec_path);
|
||||
|
||||
struct image_list images;
|
||||
image_list_init(&images);
|
||||
|
||||
struct elf_image *exec = NULL;
|
||||
@@ -183,23 +217,13 @@ int main(const struct rosetta_bootstrap *bs)
|
||||
image_name);
|
||||
|
||||
image_list_put(&images, &exec->e_leaf);
|
||||
err = load_images(&images);
|
||||
err = load_images(task_name, &images);
|
||||
if (err != SUCCESS) {
|
||||
report_error(
|
||||
task_name,
|
||||
err,
|
||||
"error while loading %s",
|
||||
exec_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = link_images(&images);
|
||||
err = link_images(task_name, &images);
|
||||
if (err != SUCCESS) {
|
||||
report_error(
|
||||
task_name,
|
||||
err,
|
||||
"error while loading %s",
|
||||
exec_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -218,7 +242,12 @@ int main(const struct rosetta_bootstrap *bs)
|
||||
}
|
||||
|
||||
kern_tracef("ld finished");
|
||||
int (*entry)(int, const char **)
|
||||
= (int (*)(int, const char **))exec->e_entry;
|
||||
return entry(bs->bs_argc - 2, bs->bs_argv + 2);
|
||||
struct rosetta_bootstrap exec_bsinfo;
|
||||
memcpy(&exec_bsinfo, bs, sizeof exec_bsinfo);
|
||||
|
||||
exec_bsinfo.bs_argc -= 2;
|
||||
exec_bsinfo.bs_argv += 2;
|
||||
int (*entry)(const struct rosetta_bootstrap *)
|
||||
= (int (*)(const struct rosetta_bootstrap *))exec->e_entry;
|
||||
return entry(&exec_bsinfo);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,46 @@
|
||||
|
||||
uintptr_t dl_runtime_resolve(struct elf_image *img, unsigned long sym_id)
|
||||
{
|
||||
unsigned long slot_id = sym_id;
|
||||
switch (img->e_rel_entsize[ELF_RT_PLTREL]) {
|
||||
case sizeof(elf_rela_t): {
|
||||
elf_rela_t *rela
|
||||
= (elf_rela_t *)((virt_addr_t)img->e_base
|
||||
+ img->e_rel_offset[ELF_RT_PLTREL]);
|
||||
elf_rela_t *rela_sym = &rela[sym_id];
|
||||
kern_tracef(
|
||||
"rela %u -> .dynsym %u, .got %u",
|
||||
sym_id,
|
||||
ELF64_R_SYM(rela_sym->r_info),
|
||||
slot_id);
|
||||
sym_id = ELF64_R_SYM(rela_sym->r_info);
|
||||
/* the first three entries in the GOT are not symbols. */
|
||||
slot_id += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
elf_sym_t *sym
|
||||
= (elf_sym_t *)((virt_addr_t)img->e_base + img->e_dynsym);
|
||||
virt_addr_t *got
|
||||
= (virt_addr_t *)((virt_addr_t)img->e_base + img->e_got_plt);
|
||||
const char *sym_name = (const char *)img->e_base + img->e_strtab
|
||||
+ sym[sym_id + 1].st_name;
|
||||
// kern_logf("%s: request for symbol %s", img->e_leaf.l_name, sym_name);
|
||||
+ sym[sym_id].st_name;
|
||||
kern_tracef(
|
||||
"%s: request for symbol %u: %s",
|
||||
img->e_leaf.l_name,
|
||||
sym_id,
|
||||
sym_name);
|
||||
#if 0
|
||||
virt_addr_t sym_addr = elf_image_find_linked_symbol(img, sym_name);
|
||||
virt_addr_t *sym_slot
|
||||
= (virt_addr_t *)((virt_addr_t)img->e_base + img->e_got_plt
|
||||
+ ((sym_id + 3) * sizeof(virt_addr_t)));
|
||||
// kern_logf("symbol %s = %zx", sym_name, sym_addr);
|
||||
// kern_logf("slot %s = %zx", sym_name, sym_slot);
|
||||
*sym_slot = sym_addr;
|
||||
#else
|
||||
virt_addr_t sym_addr = find_global_symbol(sym_name);
|
||||
#endif
|
||||
kern_tracef("symbol %s = %zx", sym_name, sym_addr);
|
||||
kern_tracef("slot %s = %zx", sym_name, &got[slot_id]);
|
||||
got[slot_id] = sym_addr;
|
||||
return sym_addr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user