diff --git a/headers/private/kernel/syscalls.h b/headers/private/kernel/syscalls.h index 683793357c..d1988d6aba 100644 --- a/headers/private/kernel/syscalls.h +++ b/headers/private/kernel/syscalls.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006, Haiku Inc. All rights reserved. + * Copyright 2004-2007, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_SYSCALLS_H @@ -73,7 +73,7 @@ extern status_t _kern_set_sem_owner(sem_id id, team_id proc); extern thread_id _kern_load_image(int32 argCount, const char **args, int32 envCount, const char **envp, int32 priority, - uint32 flags); + uint32 flags, port_id errorPort, uint32 errorToken); extern void _kern_exit_team(status_t returnValue); extern status_t _kern_kill_team(team_id team); extern team_id _kern_get_current_team(); diff --git a/headers/private/kernel/team.h b/headers/private/kernel/team.h index 9e86229a0b..3faca4a019 100644 --- a/headers/private/kernel/team.h +++ b/headers/private/kernel/team.h @@ -6,7 +6,6 @@ #define _TEAM_H -#include #include @@ -15,37 +14,44 @@ extern "C" { #endif status_t team_init(struct kernel_args *args); -team_id team_create_team(const char *path, const char *name, char **args, int argc, - char **envp, int envc, int priority); +team_id team_create_team(const char *path, const char *name, char **args, + int argc, char **envp, int envc, int priority); status_t wait_for_team(team_id id, status_t *returnCode); void team_remove_team(struct team *team, struct process_group **_freeGroup); void team_delete_team(struct team *team); -struct process_group *team_get_process_group_locked(struct process_session *session, pid_t id); +struct process_group *team_get_process_group_locked( + struct process_session *session, pid_t id); void team_delete_process_group(struct process_group *group); struct team *team_get_kernel_team(void); team_id team_get_kernel_team_id(void); team_id team_get_current_team_id(void); -status_t team_get_address_space(team_id id, struct vm_address_space **_addressSpace); +status_t team_get_address_space(team_id id, + struct vm_address_space **_addressSpace); char **user_team_get_arguments(void); int user_team_get_arg_count(void); status_t team_get_death_entry(struct team *team, thread_id child, - struct death_entry *death, struct death_entry **_freeDeath); + struct death_entry *death, struct death_entry **_freeDeath); bool team_is_valid(team_id id); struct team *team_get_team_struct_locked(team_id id); int32 team_max_teams(void); int32 team_used_teams(void); -status_t start_watching_team(team_id team, void (*hook)(team_id, void *), void *data); -status_t stop_watching_team(team_id team, void (*hook)(team_id, void *), void *data); +status_t start_watching_team(team_id team, void (*hook)(team_id, void *), + void *data); +status_t stop_watching_team(team_id team, void (*hook)(team_id, void *), + void *data); // used in syscalls.c thread_id _user_load_image(int32 argCount, const char **args, int32 envCount, - const char **envp, int32 priority, uint32 flags); + const char **env, int32 priority, uint32 flags, + port_id errorPort, uint32 errorToken); status_t _user_wait_for_team(team_id id, status_t *_returnCode); void _user_exit_team(status_t returnValue); status_t _user_kill_team(thread_id thread); -thread_id _user_wait_for_child(thread_id child, uint32 flags, int32 *_reason, status_t *_returnCode); -status_t _user_exec(const char *path, int32 argc, char * const *argv, int32 envCount, char * const *environment); +thread_id _user_wait_for_child(thread_id child, uint32 flags, int32 *_reason, + status_t *_returnCode); +status_t _user_exec(const char *path, int32 argc, char * const *argv, + int32 envCount, char * const *environment); thread_id _user_fork(void); team_id _user_get_current_team(void); pid_t _user_process_info(pid_t process, int32 which); @@ -54,10 +60,11 @@ pid_t _user_setsid(void); status_t _user_get_team_info(team_id id, team_info *info); status_t _user_get_next_team_info(int32 *cookie, team_info *info); -status_t _user_get_team_usage_info(team_id team, int32 who, team_usage_info *info, size_t size); +status_t _user_get_team_usage_info(team_id team, int32 who, + team_usage_info *info, size_t size); #ifdef __cplusplus } #endif -#endif /* _TIME_H */ +#endif /* _TEAM_H */ diff --git a/headers/private/kernel/user_runtime.h b/headers/private/kernel/user_runtime.h index cf7036949a..fbc3a300f0 100644 --- a/headers/private/kernel/user_runtime.h +++ b/headers/private/kernel/user_runtime.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -15,13 +15,15 @@ #define MAGIC_APP_NAME "_APP_" -struct uspace_program_args { - char program_name[B_OS_NAME_LENGTH]; - char program_path[B_PATH_NAME_LENGTH]; - int argc; - int envc; - char **argv; - char **envp; +struct user_space_program_args { + char program_name[B_OS_NAME_LENGTH]; + char program_path[B_PATH_NAME_LENGTH]; + port_id error_port; + uint32 error_token; + int arg_count; + int env_count; + char **args; + char **env; }; struct rld_export { @@ -37,7 +39,7 @@ struct rld_export { status_t (*get_next_image_dependency)(image_id id, uint32 *cookie, const char **_name); - const struct uspace_program_args *program_args; + const struct user_space_program_args *program_args; }; extern struct rld_export *__gRuntimeLoader; diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index b197a7cf96..96afc23f9c 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef LIBROOT_PRIVATE_H @@ -10,7 +10,7 @@ #include -struct uspace_program_args; +struct user_space_program_args; struct real_time_data; extern char _single_threaded; @@ -26,7 +26,7 @@ status_t __parse_invoke_line(char *invoker, char ***_newArgs, status_t __get_next_image_dependency(image_id id, uint32 *cookie, const char **_name); status_t __test_executable(const char *path, char *invoker); -void __init_env(const struct uspace_program_args *args); +void __init_env(const struct user_space_program_args *args); void __init_heap(void); void __init_time(void); diff --git a/src/kits/Jamfile b/src/kits/Jamfile index 4454c7aaab..c8d59df7b1 100644 --- a/src/kits/Jamfile +++ b/src/kits/Jamfile @@ -17,8 +17,8 @@ if $(RUN_WITHOUT_APP_SERVER) != 0 { SubDirC++Flags $(defines) ; } -UsePrivateHeaders [ FDirName kernel util ] ; # For KMessage.h -UsePrivateHeaders syslog_daemon ; # For syslog.cpp +UsePrivateHeaders [ FDirName kernel ] # For KMessage.h +UsePrivateHeaders syslog_daemon ; # For syslog.cpp # Build our libbe.so diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index 48cb284c2e..549b31f6e6 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -2890,12 +2890,19 @@ _TrackerLaunchAppWithDocuments(const entry_ref *appRef, const BMessage *refs, bo } extern "C" char** environ; + +#ifdef __HAIKU__ +extern "C" status_t _kern_load_image(int32 argCount, const char **args, + int32 envCount, const char **env, int32 priority, uint32 flags, + port_id errorPort, uint32 errorToken); +#else extern "C" -#if !B_BEOS_VERSION_DANO +# if !B_BEOS_VERSION_DANO _IMPEXP_ROOT -#endif +# endif status_t _kload_image_etc_(int argc, char **argv, char **envp, char *buf, int bufsize); +#endif static status_t @@ -2903,17 +2910,74 @@ LoaderErrorDetails(const entry_ref *app, BString &details) { BPath path; BEntry appEntry(app, true); + status_t result = appEntry.GetPath(&path); - if (result != B_OK) return result; - + char *argv[2] = { const_cast(path.Path()), 0}; #ifdef __HAIKU__ - // ToDo: do this correctly! - result = load_image(1, (const char **)argv, (const char **)environ); - details.SetTo("ToDo: this is missing from Haiku"); + port_id errorPort = create_port(1, "Tracker loader error"); + + // count environment variables + uint32 envCount = 0; + while (environ[envCount] != NULL) + envCount++; + + result = _kern_load_image(1, (const char **)argv, envCount, + (const char **)environ, B_NORMAL_PRIORITY, B_WAIT_TILL_LOADED, + errorPort, 0); + if (result == B_OK) { + // we weren't supposed to be able to start the application... + return B_ERROR; + } + + // read error message from port and construct details string + + ssize_t bufferSize; + + do { + bufferSize = port_buffer_size_etc(errorPort, B_RELATIVE_TIMEOUT, 0); + } while (bufferSize == B_INTERRUPTED); + + if (bufferSize <= B_OK) { + delete_port(errorPort); + return bufferSize; + } + + uint8 *buffer = (uint8 *)malloc(bufferSize); + if (buffer == NULL) { + delete_port(errorPort); + return B_NO_MEMORY; + } + + bufferSize = read_port_etc(errorPort, NULL, buffer, bufferSize, + B_RELATIVE_TIMEOUT, 0); + delete_port(errorPort); + + if (bufferSize < B_OK) { + free(buffer); + return bufferSize; + } + + BMessage message; + result = message.Unflatten((const char *)buffer); + free(buffer); + + if (result != B_OK) + return result; + + message.PrintToStream(); + const char* library; + for (int32 i = 0; message.FindString("missing library", i, + &library) == B_OK; i++) { + if (i > 0) + details += ", "; + details += library; + } + + return B_OK; #else result = _kload_image_etc_(1, argv, environ, details.LockBuffer(1024), 1024); details.UnlockBuffer(); @@ -3048,7 +3112,7 @@ _TrackerLaunchDocuments(const entry_ref */*doNotUse*/, const BMessage *refs, alertString << "Could not open \"" << documentRef.name << "\" "; if (openedDocuments) alertString << "with application \"" << app.name << "\" "; - alertString << "(Missing library: " << loaderErrorString << "). \n"; + alertString << "(Missing libraries: " << loaderErrorString << "). \n"; alternative = kFindAlternativeStr; } else { alertString << "Could not open \"" << documentRef.name diff --git a/src/system/kernel/messaging/Jamfile b/src/system/kernel/messaging/Jamfile index 509046dda6..32ab38a63a 100644 --- a/src/system/kernel/messaging/Jamfile +++ b/src/system/kernel/messaging/Jamfile @@ -3,7 +3,6 @@ SubDir HAIKU_TOP src system kernel messaging ; UsePrivateHeaders [ FDirName kernel ] ; #UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; #UsePrivateHeaders [ FDirName kernel fs ] ; -UsePrivateHeaders [ FDirName kernel util ] ; # for UsePrivateHeaders shared ; UseHeaders [ FDirName $(HAIKU_TOP) src system kernel disk_device_manager ] ; # for "Locker.h" diff --git a/src/system/kernel/messaging/KMessage.cpp b/src/system/kernel/messaging/KMessage.cpp index 676b2cd53c..15aaad89d7 100644 --- a/src/system/kernel/messaging/KMessage.cpp +++ b/src/system/kernel/messaging/KMessage.cpp @@ -3,7 +3,7 @@ * All rights reserved. Distributed under the terms of the MIT License. */ -#include "KMessage.h" +#include #include #include @@ -12,7 +12,7 @@ #include #include -#if defined(_BOOT_MODE) +#if defined(_BOOT_MODE) || defined(_LOADER_MODE) # include #else # include @@ -32,6 +32,21 @@ using std::nothrow; # endif #endif +#ifdef _LOADER_MODE +# include + +# define KMESSAGE_NO_RECEIVE + +# define create_port(capacity, name) _kern_create_port(capacity, name) +# define delete_port(port) _kern_delete_port(port) +# define write_port(port, code, buffer, bufferSize) \ + _kern_write_port_etc(port, code, buffer, bufferSize, 0, 0) +# define write_port_etc(port, code, buffer, bufferSize, flags, timeout) \ + _kern_write_port_etc(port, code, buffer, bufferSize, flags, timeout) +# define set_port_owner(port, team) _kern_set_port_owner(port, team) +# define _get_port_info(port, info, size) _kern_get_port_info(port, info) +#endif + static const int32 kMessageReallocChunkSize = 64; // kMessageHeaderMagic @@ -546,6 +561,9 @@ KMessage::SendReply(KMessage* message, KMessage* reply, status_t KMessage::ReceiveFrom(port_id fromPort, bigtime_t timeout) { +#ifdef KMESSAGE_NO_RECEIVE + return B_NOT_SUPPORTED; +#else // get the port buffer size ssize_t size; if (timeout < 0) @@ -569,6 +587,7 @@ KMessage::ReceiveFrom(port_id fromPort, bigtime_t timeout) // init the message return SetTo(buffer, size, 0, KMESSAGE_OWNS_BUFFER | KMESSAGE_INIT_FROM_BUFFER); +#endif // !KMESSAGE_NO_RECEIVE } #endif // !KMESSAGE_CONTAINER_ONLY @@ -804,6 +823,7 @@ KMessage::_AllocateSpace(int32 size, bool alignAddress, bool alignSize, { if (fBuffer != &fHeader && (fFlags & KMESSAGE_READ_ONLY)) return B_NOT_ALLOWED; + int32 offset = ContentSize(); if (alignAddress) offset = _Align(offset); diff --git a/src/system/kernel/team.c b/src/system/kernel/team.c index 2efbc28f6a..49a2fa50e2 100644 --- a/src/system/kernel/team.c +++ b/src/system/kernel/team.c @@ -50,6 +50,8 @@ struct team_arg { char **args; uint32 env_count; char **env; + port_id error_port; + uint32 error_token; }; struct fork_arg { @@ -610,7 +612,7 @@ get_arguments_data_size(char **args, int32 argc) for (count = 0; count < argc; count++) size += strlen(args[count]) + 1; - return size + (argc + 1) * sizeof(char *) + sizeof(struct uspace_program_args); + return size + (argc + 1) * sizeof(char *) + sizeof(struct user_space_program_args); } @@ -626,7 +628,7 @@ free_team_arg(struct team_arg *teamArg) static status_t create_team_arg(struct team_arg **_teamArg, int32 argCount, char * const *args, - int32 envCount, char * const *env, bool kernel) + int32 envCount, char * const *env, port_id port, uint32 token, bool kernel) { status_t status; char **argsCopy; @@ -652,6 +654,8 @@ create_team_arg(struct team_arg **_teamArg, int32 argCount, char * const *args, teamArg->args = argsCopy; teamArg->env_count = envCount; teamArg->env = envCopy; + teamArg->error_port = port; + teamArg->error_token = token; *_teamArg = teamArg; return B_OK; @@ -669,10 +673,10 @@ team_create_thread_start(void *args) addr_t entry; char ustack_name[128]; uint32 sizeLeft; - char **uargs; - char **uenv; - char *udest; - struct uspace_program_args *uspa; + char **userArgs; + char **userEnv; + char *userDest; + struct user_space_program_args *programArgs; uint32 argCount, envCount, i; t = thread_get_current_thread(); @@ -717,32 +721,32 @@ team_create_thread_start(void *args) argCount = teamArgs->arg_count; envCount = teamArgs->env_count; - uspa = (struct uspace_program_args *)(t->user_stack_base + t->user_stack_size - + TLS_SIZE + ENV_SIZE); - uargs = (char **)(uspa + 1); - udest = (char *)(uargs + argCount + 1); + programArgs = (struct user_space_program_args *)(t->user_stack_base + + t->user_stack_size + TLS_SIZE + ENV_SIZE); + userArgs = (char **)(programArgs + 1); + userDest = (char *)(userArgs + argCount + 1); - TRACE(("addr: stack base = 0x%lx, uargs = %p, udest = %p, sizeLeft = %lu\n", - t->user_stack_base, uargs, udest, sizeLeft)); + TRACE(("addr: stack base = 0x%lx, userArgs = %p, userDest = %p, sizeLeft = %lu\n", + t->user_stack_base, userArgs, userDest, sizeLeft)); - sizeLeft = t->user_stack_base + sizeLeft - (addr_t)udest; + sizeLeft = t->user_stack_base + sizeLeft - (addr_t)userDest; for (i = 0; i < argCount; i++) { - ssize_t length = user_strlcpy(udest, teamArgs->args[i], sizeLeft); + ssize_t length = user_strlcpy(userDest, teamArgs->args[i], sizeLeft); if (length < B_OK) { argCount = 0; break; } - uargs[i] = udest; - udest += ++length; + userArgs[i] = userDest; + userDest += ++length; sizeLeft -= length; } - uargs[argCount] = NULL; + userArgs[argCount] = NULL; - uenv = (char **)(t->user_stack_base + t->user_stack_size + TLS_SIZE); + userEnv = (char **)(t->user_stack_base + t->user_stack_size + TLS_SIZE); sizeLeft = ENV_SIZE; - udest = (char *)uenv + ENV_SIZE - 1; + userDest = (char *)userEnv + ENV_SIZE - 1; // the environment variables are copied from back to front TRACE(("team_create_thread_start: envc: %ld, env: %p\n", @@ -750,29 +754,37 @@ team_create_thread_start(void *args) for (i = 0; i < envCount; i++) { ssize_t length = strlen(teamArgs->env[i]) + 1; - udest -= length; - if (udest < (char *)&uenv[envCount]) { + userDest -= length; + if (userDest < (char *)&userEnv[envCount]) { envCount = i; break; } - uenv[i] = udest; + userEnv[i] = userDest; - if (user_memcpy(udest, teamArgs->env[i], length) < B_OK) { + if (user_memcpy(userDest, teamArgs->env[i], length) < B_OK) { envCount = 0; break; } sizeLeft -= length; } - uenv[envCount] = NULL; + userEnv[envCount] = NULL; path = teamArgs->args[0]; - user_memcpy(uspa->program_path, path, sizeof(uspa->program_path)); - uspa->argc = argCount; - uspa->argv = uargs; - uspa->envc = envCount; - uspa->envp = uenv; + if (user_memcpy(programArgs->program_path, path, + sizeof(programArgs->program_path)) < B_OK + || user_memcpy(&programArgs->arg_count, &argCount, sizeof(int32)) < B_OK + || user_memcpy(&programArgs->args, &userArgs, sizeof(char **)) < B_OK + || user_memcpy(&programArgs->env_count, &envCount, sizeof(int32)) < B_OK + || user_memcpy(&programArgs->env, &userEnv, sizeof(char **)) < B_OK + || user_memcpy(&programArgs->error_port, &teamArgs->error_port, + sizeof(port_id)) < B_OK + || user_memcpy(&programArgs->error_token, &teamArgs->error_token, + sizeof(uint32)) < B_OK) { + // the team deletion process will clean this mess + return B_BAD_ADDRESS; + } TRACE(("team_create_thread_start: loading elf binary '%s'\n", path)); @@ -801,7 +813,7 @@ team_create_thread_start(void *args) team->state = TEAM_STATE_NORMAL; // jump to the entry point in user space - return arch_thread_enter_userspace(t, entry, uspa, NULL); + return arch_thread_enter_userspace(t, entry, programArgs, NULL); // only returns in case of error } @@ -811,8 +823,9 @@ team_create_thread_start(void *args) */ static thread_id -load_image_etc(int32 argCount, char * const *args, int32 envCount, char * const *env, - int32 priority, uint32 flags, bool kernel) +load_image_etc(int32 argCount, char * const *args, int32 envCount, + char * const *env, int32 priority, uint32 flags, + port_id errorPort, uint32 errorToken, bool kernel) { struct process_group *group; struct team *team, *parent; @@ -853,7 +866,8 @@ load_image_etc(int32 argCount, char * const *args, int32 envCount, char * const RELEASE_TEAM_LOCK(); restore_interrupts(state); - status = create_team_arg(&teamArgs, argCount, args, envCount, env, kernel); + status = create_team_arg(&teamArgs, argCount, args, envCount, env, + errorPort, errorToken, kernel); if (status != B_OK) goto err1; @@ -879,8 +893,8 @@ load_image_etc(int32 argCount, char * const *args, int32 envCount, char * const // Create a kernel thread, but under the context of the new team // The new thread will take over ownership of teamArgs - thread = spawn_kernel_thread_etc(team_create_thread_start, threadName, B_NORMAL_PRIORITY, - teamArgs, team->id, team->id); + thread = spawn_kernel_thread_etc(team_create_thread_start, threadName, + B_NORMAL_PRIORITY, teamArgs, team->id, team->id); if (thread < 0) { status = thread; goto err4; @@ -1007,9 +1021,8 @@ exec_team(const char *path, int32 argCount, char * const *args, if (status != B_OK) return status; - // ToDo: maybe we should make sure upfront that the target path is an app? - - status = create_team_arg(&teamArgs, argCount, args, envCount, env, false); + status = create_team_arg(&teamArgs, argCount, args, envCount, env, + -1, 0, false); if (status != B_OK) return status; @@ -1857,7 +1870,8 @@ load_image(int32 argCount, const char **args, const char **env) envCount++; return load_image_etc(argCount, (char * const *)args, envCount, - (char * const *)env, B_NORMAL_PRIORITY, B_WAIT_TILL_LOADED, true); + (char * const *)env, B_NORMAL_PRIORITY, B_WAIT_TILL_LOADED, + -1, 0, true); } @@ -2393,7 +2407,8 @@ _user_wait_for_team(team_id id, status_t *_userReturnCode) team_id _user_load_image(int32 argCount, const char **userArgs, int32 envCount, - const char **userEnv, int32 priority, uint32 flags) + const char **userEnv, int32 priority, uint32 flags, port_id errorPort, + uint32 errorToken) { TRACE(("_user_load_image_etc: argc = %ld\n", argCount)); @@ -2404,7 +2419,8 @@ _user_load_image(int32 argCount, const char **userArgs, int32 envCount, return B_BAD_ADDRESS; return load_image_etc(argCount, (char * const *)userArgs, - envCount, (char * const *)userEnv, priority, flags, false); + envCount, (char * const *)userEnv, priority, flags, errorPort, + errorToken, false); } diff --git a/src/system/kernel/util/kernel_cpp.cpp b/src/system/kernel/util/kernel_cpp.cpp index 3028c40626..616dbc59b9 100644 --- a/src/system/kernel/util/kernel_cpp.cpp +++ b/src/system/kernel/util/kernel_cpp.cpp @@ -1,17 +1,31 @@ -/* cpp - C++ in the kernel -** -** Initial version by Axel Dörfler, axeld@pinc-software.de -** This file may be used under the terms of the OpenBeOS License. -*/ +/* + * Copyright 2003-2007, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de. + * Ingo Weinhold, bonefish@users.sf.net. + */ + +//! C++ in the kernel + #include "util/kernel_cpp.h" #ifdef _BOOT_MODE # include -#elif defined(_KERNEL_MODE) +#else # include +# include #endif +#ifdef _LOADER_MODE +# define panic printf +# define dprintf printf +# define kernel_debugger printf +#endif + + // Always define the symbols needed when not linking against libgcc.a -- // we simply override them. @@ -39,9 +53,7 @@ __cxa_pure_virtual() #endif // full C++ support in the kernel -#if defined(_KERNEL_MODE) && !defined(_BOOT_MODE) - -#include +#if (defined(_KERNEL_MODE) || defined(_LOADER_MODE)) && !defined(_BOOT_MODE) FILE *stderr = NULL; diff --git a/src/system/libroot/libroot_init.c b/src/system/libroot/libroot_init.c index 4ddc01a306..c66dcfb9ac 100644 --- a/src/system/libroot/libroot_init.c +++ b/src/system/libroot/libroot_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -37,7 +37,7 @@ int _data_offset_main_; void initialize_before(image_id imageID) { - char *programPath = __gRuntimeLoader->program_args->argv[0]; + char *programPath = __gRuntimeLoader->program_args->args[0]; if (programPath) { if ((__progname = strrchr(programPath, '/')) == NULL) __progname = programPath; @@ -45,8 +45,8 @@ initialize_before(image_id imageID) __progname++; } - __libc_argc = __gRuntimeLoader->program_args->argc; - __libc_argv = __gRuntimeLoader->program_args->argv; + __libc_argc = __gRuntimeLoader->program_args->arg_count; + __libc_argv = __gRuntimeLoader->program_args->args; __init_time(); __init_fork(); diff --git a/src/system/libroot/os/image.c b/src/system/libroot/os/image.c index b20ba69a05..482c1747a7 100644 --- a/src/system/libroot/os/image.c +++ b/src/system/libroot/os/image.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -44,7 +44,7 @@ load_image(int32 argCount, const char **args, const char **environ) envCount++; thread = _kern_load_image(argCount, args, envCount, environ, - B_NORMAL_PRIORITY, B_WAIT_TILL_LOADED); + B_NORMAL_PRIORITY, B_WAIT_TILL_LOADED, -1, 0); free(newArgs); return thread; diff --git a/src/system/libroot/posix/stdlib/env.c b/src/system/libroot/posix/stdlib/env.c index 8af820fb7e..86cc5fea21 100644 --- a/src/system/libroot/posix/stdlib/env.c +++ b/src/system/libroot/posix/stdlib/env.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -148,12 +148,12 @@ environ_fork_hook(void) void -__init_env(const struct uspace_program_args *args) +__init_env(const struct user_space_program_args *args) { // Following POSIX, there is no need to make any of the // environment functions thread-safe - but we do it anyway sEnvLock = create_sem(1, "env lock"); - environ = args->envp; + environ = args->env; atfork(environ_fork_hook); } diff --git a/src/system/runtime_loader/Jamfile b/src/system/runtime_loader/Jamfile index 5bf7f16ee9..345630078d 100644 --- a/src/system/runtime_loader/Jamfile +++ b/src/system/runtime_loader/Jamfile @@ -9,11 +9,15 @@ SubDirCcFlags -fno-builtin ; SubDirC++Flags -fno-builtin -fno-exceptions ; # default to BeOS style symbol resolution -DEFINES += BEOS_STYLE_SYMBOLS_RESOLUTION ; +DEFINES += BEOS_STYLE_SYMBOLS_RESOLUTION + _LOADER_MODE +; # needed for "runtime_loader" only StaticLibrary libruntime_loader.a : kernel_vsprintf.c + kernel_cpp.cpp + KMessage.cpp : syscalls.o sem.o @@ -54,8 +58,12 @@ StaticLibrary libruntime_loader.a : [ FGristFiles kernel_vsprintf.o ] ; +SEARCH on [ FGristFiles kernel_cpp.cpp ] + = [ FDirName $(HAIKU_TOP) src system kernel util ] ; SEARCH on [ FGristFiles kernel_vsprintf.c ] = [ FDirName $(HAIKU_TOP) src system kernel lib ] ; +SEARCH on [ FGristFiles KMessage.cpp ] + = [ FDirName $(HAIKU_TOP) src system kernel messaging ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ; diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index 4f60d563da..0914f2560b 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -76,6 +76,7 @@ static image_queue_t sLoadedImages = {0, 0}; static image_queue_t sDisposableImages = {0, 0}; static uint32 sLoadedImageCount = 0; static image_t *sProgramImage; +static KMessage sErrorMessage; #ifdef BEOS_STYLE_SYMBOLS_RESOLUTION static bool sResolveSymbolsBeOSStyle = true; @@ -1096,8 +1097,8 @@ static status_t load_dependencies(image_t *image) { struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; - int neededOffset; - status_t status; + bool reportErrors = gProgramArgs->error_port >= 0; + status_t status = B_OK; uint32 i, j; const char *rpath; @@ -1121,15 +1122,30 @@ load_dependencies(image_t *image) for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) { switch (d[i].d_tag) { case DT_NEEDED: - neededOffset = d[i].d_un.d_val; + { + int32 neededOffset = d[i].d_un.d_val; + const char *name = STRING(image, neededOffset); - status = load_container(STRING(image, neededOffset), - B_LIBRARY_IMAGE, rpath, &image->needed[j]); - if (status < B_OK) - return status; + status_t loadStatus = load_container(name, B_LIBRARY_IMAGE, + rpath, &image->needed[j]); + if (loadStatus < B_OK) { + status = loadStatus; + // correct error code in case the file could not been found + if (status == B_ENTRY_NOT_FOUND) { + status = B_MISSING_LIBRARY; + + if (reportErrors) + sErrorMessage.AddString("missing library", name); + } + + // Collect all missing libraries in case we report back + if (!reportErrors) + return status; + } j += 1; break; + } default: // ignore any other tag @@ -1137,6 +1153,9 @@ load_dependencies(image_t *image) } } + if (status < B_OK) + return status; + if (j != image->num_needed) { FATAL("Internal error at load_dependencies()"); return B_ERROR; @@ -1255,8 +1274,7 @@ put_image(image_t *image) } -// #pragma mark - -// Exported functions (to libroot.so) +// #pragma mark - libroot.so exported functions image_id @@ -1271,11 +1289,8 @@ load_program(char const *path, void **_entry) TRACE(("rld: load %s\n", path)); status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage); - if (status < B_OK) { - _kern_loading_app_failed(status); - rld_unlock(); - return status; - } + if (status < B_OK) + goto err; for (image = sLoadedImages.head; image != NULL; image = image->next) { status = load_dependencies(image); @@ -1322,9 +1337,16 @@ load_program(char const *path, void **_entry) return sProgramImage->id; err: - _kern_loading_app_failed(status); delete_image(sProgramImage); + + if (gProgramArgs->error_port >= 0) { + sErrorMessage.AddInt32("error", status); + sErrorMessage.SendTo(gProgramArgs->error_port, gProgramArgs->error_token, + -1, 0, 0, find_thread(NULL)); + } + _kern_loading_app_failed(status); rld_unlock(); + return status; } @@ -1563,7 +1585,7 @@ get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) } -// #pragma mark - +// #pragma mark - runtime_loader private exports /** Read and verify the ELF header */ @@ -1627,4 +1649,13 @@ rldelf_init(void) area->loaded_images = &sLoadedImages; } + + // initialize error message if needed + if (gProgramArgs->error_port >= 0) { + void *buffer = malloc(1024); + if (buffer == NULL) + return; + + sErrorMessage.SetTo(buffer, 1024, 'Rler'); + } } diff --git a/src/system/runtime_loader/heap.cpp b/src/system/runtime_loader/heap.cpp index 586a526e83..f42ba8a185 100644 --- a/src/system/runtime_loader/heap.cpp +++ b/src/system/runtime_loader/heap.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -236,6 +236,14 @@ dump_chunks(void) #endif +void * +realloc(void *buffer, size_t newSize) +{ + // not implemented + return NULL; +} + + void * malloc(size_t size) { diff --git a/src/system/runtime_loader/runtime_loader.c b/src/system/runtime_loader/runtime_loader.c index 358c985d74..2ace6ec913 100644 --- a/src/system/runtime_loader/runtime_loader.c +++ b/src/system/runtime_loader/runtime_loader.c @@ -26,7 +26,7 @@ #endif -struct uspace_program_args *gProgramArgs; +struct user_space_program_args *gProgramArgs; static const char * @@ -254,12 +254,12 @@ open_executable(char *name, image_type type, const char *rpath) } -/** Tests if there is an executable file at the provided path. It will - * also test if the file has a valid ELF header or is a shell script. - * Even if the runtime loader does not need to be able to deal with - * both types, the caller will give scripts a proper treatment. - */ - +/*! + Tests if there is an executable file at the provided path. It will + also test if the file has a valid ELF header or is a shell script. + Even if the runtime loader does not need to be able to deal with + both types, the caller will give scripts a proper treatment. +*/ status_t test_executable(const char *name, uid_t user, gid_t group, char *invoker) { @@ -339,17 +339,17 @@ out: } -/** This is the main entry point of the runtime loader as - * specified by its ld-script. - */ - +/*! + This is the main entry point of the runtime loader as + specified by its ld-script. +*/ int runtime_loader(void *_args) { void *entry = NULL; int returnCode; - gProgramArgs = (struct uspace_program_args *)_args; + gProgramArgs = (struct user_space_program_args *)_args; #if DEBUG_RLD close(0); open("/dev/console", 0); /* stdin */ @@ -369,8 +369,8 @@ runtime_loader(void *_args) return -1; // call the program entry point (usually _start()) - returnCode = ((int (*)(int, void *, void *))entry)(gProgramArgs->argc, - gProgramArgs->argv, gProgramArgs->envp); + returnCode = ((int (*)(int, void *, void *))entry)(gProgramArgs->arg_count, + gProgramArgs->args, gProgramArgs->env); terminate_program(); diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index 58932f0e25..a6719dd51a 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -13,7 +13,7 @@ #include -extern struct uspace_program_args *gProgramArgs; +extern struct user_space_program_args *gProgramArgs; extern struct rld_export gRuntimeLoader; extern char *(*gGetEnv)(const char *name); diff --git a/src/system/runtime_loader/utility.cpp b/src/system/runtime_loader/utility.cpp index 18c02b91f4..32b4e1fdb4 100644 --- a/src/system/runtime_loader/utility.cpp +++ b/src/system/runtime_loader/utility.cpp @@ -24,12 +24,12 @@ extern "C" char * getenv(const char *name) { if (gGetEnv != NULL) { - // Use libroot's getenv() as soon as it is available to us - the environment - // in gProgramArgs is static. + // Use libroot's getenv() as soon as it is available to us - the + // environment in gProgramArgs is static. return gGetEnv(name); } - char **environ = gProgramArgs->envp; + char **environ = gProgramArgs->env; int32 length = strlen(name); int32 i; @@ -56,3 +56,23 @@ printf(const char *format, ...) return length; } + + +// Copied from libroot/os/thread.c: + + +extern "C" status_t +_get_thread_info(thread_id thread, thread_info *info, size_t size) +{ + if (info == NULL || size != sizeof(thread_info)) + return B_BAD_VALUE; + + return _kern_get_thread_info(thread, info); +} + + +status_t +snooze(bigtime_t timeout) +{ + return B_ERROR; +}