* Added a mechanism to retrieve a BMessage with eventual error descriptions

for _kern_load_image().
* Added KMessage to the runtime_loader (a bit hacky, though) - it will use
  it to deliver the above mentioned functionality.
* load_dependencies() did return the wrong status code in case a library
  was missing; now it returns B_MISSING_LIBRARY.
* load_dependencies() will now try to load all dependencies when a report
  message is requested; therefore, all missing libraries are listed.
* Renamed uspace_program_args to user_space_program_args.
* The kernel filled in various members of the user_space_program_args structure
  unsafely, ie. was not using user_memcpy().
* Renamed some local variables in team.c to better fit our style guide (ie.
  uargs to userArgs).
* Changed Tracker to use the new _kern_load_image() variant on Haiku to retrieve
  and report all missing libraries. This fixes bug #1324.
* Adapted kernel_cpp.cpp to the runtime loader as well; the latter will now
  compile with _LOADER_MODE defined.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21715 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-07-27 02:32:19 +00:00
parent d6dfbc4de5
commit 74c0424a43
19 changed files with 323 additions and 136 deletions
+2 -2
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _KERNEL_SYSCALLS_H #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, extern thread_id _kern_load_image(int32 argCount, const char **args,
int32 envCount, const char **envp, int32 priority, 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 void _kern_exit_team(status_t returnValue);
extern status_t _kern_kill_team(team_id team); extern status_t _kern_kill_team(team_id team);
extern team_id _kern_get_current_team(); extern team_id _kern_get_current_team();
+20 -13
View File
@@ -6,7 +6,6 @@
#define _TEAM_H #define _TEAM_H
#include <OS.h>
#include <thread_types.h> #include <thread_types.h>
@@ -15,37 +14,44 @@ extern "C" {
#endif #endif
status_t team_init(struct kernel_args *args); status_t team_init(struct kernel_args *args);
team_id team_create_team(const char *path, const char *name, char **args, int argc, team_id team_create_team(const char *path, const char *name, char **args,
char **envp, int envc, int priority); int argc, char **envp, int envc, int priority);
status_t wait_for_team(team_id id, status_t *returnCode); status_t wait_for_team(team_id id, status_t *returnCode);
void team_remove_team(struct team *team, struct process_group **_freeGroup); void team_remove_team(struct team *team, struct process_group **_freeGroup);
void team_delete_team(struct team *team); 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); void team_delete_process_group(struct process_group *group);
struct team *team_get_kernel_team(void); struct team *team_get_kernel_team(void);
team_id team_get_kernel_team_id(void); team_id team_get_kernel_team_id(void);
team_id team_get_current_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); char **user_team_get_arguments(void);
int user_team_get_arg_count(void); int user_team_get_arg_count(void);
status_t team_get_death_entry(struct team *team, thread_id child, 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); bool team_is_valid(team_id id);
struct team *team_get_team_struct_locked(team_id id); struct team *team_get_team_struct_locked(team_id id);
int32 team_max_teams(void); int32 team_max_teams(void);
int32 team_used_teams(void); int32 team_used_teams(void);
status_t start_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 *),
status_t stop_watching_team(team_id team, void (*hook)(team_id, void *), void *data); void *data);
status_t stop_watching_team(team_id team, void (*hook)(team_id, void *),
void *data);
// used in syscalls.c // used in syscalls.c
thread_id _user_load_image(int32 argCount, const char **args, int32 envCount, 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); status_t _user_wait_for_team(team_id id, status_t *_returnCode);
void _user_exit_team(status_t returnValue); void _user_exit_team(status_t returnValue);
status_t _user_kill_team(thread_id thread); status_t _user_kill_team(thread_id thread);
thread_id _user_wait_for_child(thread_id child, uint32 flags, int32 *_reason, status_t *_returnCode); thread_id _user_wait_for_child(thread_id child, uint32 flags, int32 *_reason,
status_t _user_exec(const char *path, int32 argc, char * const *argv, int32 envCount, char * const *environment); 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); thread_id _user_fork(void);
team_id _user_get_current_team(void); team_id _user_get_current_team(void);
pid_t _user_process_info(pid_t process, int32 which); 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_team_info(team_id id, team_info *info);
status_t _user_get_next_team_info(int32 *cookie, 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 #ifdef __cplusplus
} }
#endif #endif
#endif /* _TIME_H */ #endif /* _TEAM_H */
+11 -9
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2006, Axel Dörfler, [email protected]. * Copyright 2003-2007, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * Copyright 2002, Manuel J. Petit. All rights reserved.
@@ -15,13 +15,15 @@
#define MAGIC_APP_NAME "_APP_" #define MAGIC_APP_NAME "_APP_"
struct uspace_program_args { struct user_space_program_args {
char program_name[B_OS_NAME_LENGTH]; char program_name[B_OS_NAME_LENGTH];
char program_path[B_PATH_NAME_LENGTH]; char program_path[B_PATH_NAME_LENGTH];
int argc; port_id error_port;
int envc; uint32 error_token;
char **argv; int arg_count;
char **envp; int env_count;
char **args;
char **env;
}; };
struct rld_export { struct rld_export {
@@ -37,7 +39,7 @@ struct rld_export {
status_t (*get_next_image_dependency)(image_id id, uint32 *cookie, status_t (*get_next_image_dependency)(image_id id, uint32 *cookie,
const char **_name); const char **_name);
const struct uspace_program_args *program_args; const struct user_space_program_args *program_args;
}; };
extern struct rld_export *__gRuntimeLoader; extern struct rld_export *__gRuntimeLoader;
+3 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2006, Axel Dörfler, [email protected]. * Copyright 2004-2007, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef LIBROOT_PRIVATE_H #ifndef LIBROOT_PRIVATE_H
@@ -10,7 +10,7 @@
#include <image.h> #include <image.h>
struct uspace_program_args; struct user_space_program_args;
struct real_time_data; struct real_time_data;
extern char _single_threaded; 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, status_t __get_next_image_dependency(image_id id, uint32 *cookie,
const char **_name); const char **_name);
status_t __test_executable(const char *path, char *invoker); 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_heap(void);
void __init_time(void); void __init_time(void);
+2 -2
View File
@@ -17,8 +17,8 @@ if $(RUN_WITHOUT_APP_SERVER) != 0 {
SubDirC++Flags $(defines) ; SubDirC++Flags $(defines) ;
} }
UsePrivateHeaders [ FDirName kernel util ] ; # For KMessage.h UsePrivateHeaders [ FDirName kernel ] # For KMessage.h
UsePrivateHeaders syslog_daemon ; # For syslog.cpp UsePrivateHeaders syslog_daemon ; # For syslog.cpp
# Build our libbe.so # Build our libbe.so
+72 -8
View File
@@ -2890,12 +2890,19 @@ _TrackerLaunchAppWithDocuments(const entry_ref *appRef, const BMessage *refs, bo
} }
extern "C" char** environ; 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" extern "C"
#if !B_BEOS_VERSION_DANO # if !B_BEOS_VERSION_DANO
_IMPEXP_ROOT _IMPEXP_ROOT
#endif # endif
status_t _kload_image_etc_(int argc, char **argv, char **envp, status_t _kload_image_etc_(int argc, char **argv, char **envp,
char *buf, int bufsize); char *buf, int bufsize);
#endif
static status_t static status_t
@@ -2903,17 +2910,74 @@ LoaderErrorDetails(const entry_ref *app, BString &details)
{ {
BPath path; BPath path;
BEntry appEntry(app, true); BEntry appEntry(app, true);
status_t result = appEntry.GetPath(&path); status_t result = appEntry.GetPath(&path);
if (result != B_OK) if (result != B_OK)
return result; return result;
char *argv[2] = { const_cast<char *>(path.Path()), 0}; char *argv[2] = { const_cast<char *>(path.Path()), 0};
#ifdef __HAIKU__ #ifdef __HAIKU__
// ToDo: do this correctly! port_id errorPort = create_port(1, "Tracker loader error");
result = load_image(1, (const char **)argv, (const char **)environ);
details.SetTo("ToDo: this is missing from Haiku"); // 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 #else
result = _kload_image_etc_(1, argv, environ, details.LockBuffer(1024), 1024); result = _kload_image_etc_(1, argv, environ, details.LockBuffer(1024), 1024);
details.UnlockBuffer(); details.UnlockBuffer();
@@ -3048,7 +3112,7 @@ _TrackerLaunchDocuments(const entry_ref */*doNotUse*/, const BMessage *refs,
alertString << "Could not open \"" << documentRef.name << "\" "; alertString << "Could not open \"" << documentRef.name << "\" ";
if (openedDocuments) if (openedDocuments)
alertString << "with application \"" << app.name << "\" "; alertString << "with application \"" << app.name << "\" ";
alertString << "(Missing library: " << loaderErrorString << "). \n"; alertString << "(Missing libraries: " << loaderErrorString << "). \n";
alternative = kFindAlternativeStr; alternative = kFindAlternativeStr;
} else { } else {
alertString << "Could not open \"" << documentRef.name alertString << "Could not open \"" << documentRef.name
-1
View File
@@ -3,7 +3,6 @@ SubDir HAIKU_TOP src system kernel messaging ;
UsePrivateHeaders [ FDirName kernel ] ; UsePrivateHeaders [ FDirName kernel ] ;
#UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; #UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
#UsePrivateHeaders [ FDirName kernel fs ] ; #UsePrivateHeaders [ FDirName kernel fs ] ;
UsePrivateHeaders [ FDirName kernel util ] ; # for <KMessage.h>
UsePrivateHeaders shared ; UsePrivateHeaders shared ;
UseHeaders [ FDirName $(HAIKU_TOP) src system kernel disk_device_manager ] ; UseHeaders [ FDirName $(HAIKU_TOP) src system kernel disk_device_manager ] ;
# for "Locker.h" # for "Locker.h"
+22 -2
View File
@@ -3,7 +3,7 @@
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
#include "KMessage.h" #include <util/KMessage.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -12,7 +12,7 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <TypeConstants.h> #include <TypeConstants.h>
#if defined(_BOOT_MODE) #if defined(_BOOT_MODE) || defined(_LOADER_MODE)
# include <util/kernel_cpp.h> # include <util/kernel_cpp.h>
#else #else
# include <new> # include <new>
@@ -32,6 +32,21 @@ using std::nothrow;
# endif # endif
#endif #endif
#ifdef _LOADER_MODE
# include <syscalls.h>
# 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; static const int32 kMessageReallocChunkSize = 64;
// kMessageHeaderMagic // kMessageHeaderMagic
@@ -546,6 +561,9 @@ KMessage::SendReply(KMessage* message, KMessage* reply,
status_t status_t
KMessage::ReceiveFrom(port_id fromPort, bigtime_t timeout) KMessage::ReceiveFrom(port_id fromPort, bigtime_t timeout)
{ {
#ifdef KMESSAGE_NO_RECEIVE
return B_NOT_SUPPORTED;
#else
// get the port buffer size // get the port buffer size
ssize_t size; ssize_t size;
if (timeout < 0) if (timeout < 0)
@@ -569,6 +587,7 @@ KMessage::ReceiveFrom(port_id fromPort, bigtime_t timeout)
// init the message // init the message
return SetTo(buffer, size, 0, return SetTo(buffer, size, 0,
KMESSAGE_OWNS_BUFFER | KMESSAGE_INIT_FROM_BUFFER); KMESSAGE_OWNS_BUFFER | KMESSAGE_INIT_FROM_BUFFER);
#endif // !KMESSAGE_NO_RECEIVE
} }
#endif // !KMESSAGE_CONTAINER_ONLY #endif // !KMESSAGE_CONTAINER_ONLY
@@ -804,6 +823,7 @@ KMessage::_AllocateSpace(int32 size, bool alignAddress, bool alignSize,
{ {
if (fBuffer != &fHeader && (fFlags & KMESSAGE_READ_ONLY)) if (fBuffer != &fHeader && (fFlags & KMESSAGE_READ_ONLY))
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
int32 offset = ContentSize(); int32 offset = ContentSize();
if (alignAddress) if (alignAddress)
offset = _Align(offset); offset = _Align(offset);
+57 -41
View File
@@ -50,6 +50,8 @@ struct team_arg {
char **args; char **args;
uint32 env_count; uint32 env_count;
char **env; char **env;
port_id error_port;
uint32 error_token;
}; };
struct fork_arg { struct fork_arg {
@@ -610,7 +612,7 @@ get_arguments_data_size(char **args, int32 argc)
for (count = 0; count < argc; count++) for (count = 0; count < argc; count++)
size += strlen(args[count]) + 1; 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 static status_t
create_team_arg(struct team_arg **_teamArg, int32 argCount, char * const *args, 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; status_t status;
char **argsCopy; char **argsCopy;
@@ -652,6 +654,8 @@ create_team_arg(struct team_arg **_teamArg, int32 argCount, char * const *args,
teamArg->args = argsCopy; teamArg->args = argsCopy;
teamArg->env_count = envCount; teamArg->env_count = envCount;
teamArg->env = envCopy; teamArg->env = envCopy;
teamArg->error_port = port;
teamArg->error_token = token;
*_teamArg = teamArg; *_teamArg = teamArg;
return B_OK; return B_OK;
@@ -669,10 +673,10 @@ team_create_thread_start(void *args)
addr_t entry; addr_t entry;
char ustack_name[128]; char ustack_name[128];
uint32 sizeLeft; uint32 sizeLeft;
char **uargs; char **userArgs;
char **uenv; char **userEnv;
char *udest; char *userDest;
struct uspace_program_args *uspa; struct user_space_program_args *programArgs;
uint32 argCount, envCount, i; uint32 argCount, envCount, i;
t = thread_get_current_thread(); t = thread_get_current_thread();
@@ -717,32 +721,32 @@ team_create_thread_start(void *args)
argCount = teamArgs->arg_count; argCount = teamArgs->arg_count;
envCount = teamArgs->env_count; envCount = teamArgs->env_count;
uspa = (struct uspace_program_args *)(t->user_stack_base + t->user_stack_size programArgs = (struct user_space_program_args *)(t->user_stack_base
+ TLS_SIZE + ENV_SIZE); + t->user_stack_size + TLS_SIZE + ENV_SIZE);
uargs = (char **)(uspa + 1); userArgs = (char **)(programArgs + 1);
udest = (char *)(uargs + argCount + 1); userDest = (char *)(userArgs + argCount + 1);
TRACE(("addr: stack base = 0x%lx, uargs = %p, udest = %p, sizeLeft = %lu\n", TRACE(("addr: stack base = 0x%lx, userArgs = %p, userDest = %p, sizeLeft = %lu\n",
t->user_stack_base, uargs, udest, sizeLeft)); 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++) { 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) { if (length < B_OK) {
argCount = 0; argCount = 0;
break; break;
} }
uargs[i] = udest; userArgs[i] = userDest;
udest += ++length; userDest += ++length;
sizeLeft -= 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; sizeLeft = ENV_SIZE;
udest = (char *)uenv + ENV_SIZE - 1; userDest = (char *)userEnv + ENV_SIZE - 1;
// the environment variables are copied from back to front // the environment variables are copied from back to front
TRACE(("team_create_thread_start: envc: %ld, env: %p\n", 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++) { for (i = 0; i < envCount; i++) {
ssize_t length = strlen(teamArgs->env[i]) + 1; ssize_t length = strlen(teamArgs->env[i]) + 1;
udest -= length; userDest -= length;
if (udest < (char *)&uenv[envCount]) { if (userDest < (char *)&userEnv[envCount]) {
envCount = i; envCount = i;
break; 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; envCount = 0;
break; break;
} }
sizeLeft -= length; sizeLeft -= length;
} }
uenv[envCount] = NULL; userEnv[envCount] = NULL;
path = teamArgs->args[0]; path = teamArgs->args[0];
user_memcpy(uspa->program_path, path, sizeof(uspa->program_path)); if (user_memcpy(programArgs->program_path, path,
uspa->argc = argCount; sizeof(programArgs->program_path)) < B_OK
uspa->argv = uargs; || user_memcpy(&programArgs->arg_count, &argCount, sizeof(int32)) < B_OK
uspa->envc = envCount; || user_memcpy(&programArgs->args, &userArgs, sizeof(char **)) < B_OK
uspa->envp = uenv; || 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)); 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; team->state = TEAM_STATE_NORMAL;
// jump to the entry point in user space // 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 // only returns in case of error
} }
@@ -811,8 +823,9 @@ team_create_thread_start(void *args)
*/ */
static thread_id static thread_id
load_image_etc(int32 argCount, char * const *args, int32 envCount, char * const *env, load_image_etc(int32 argCount, char * const *args, int32 envCount,
int32 priority, uint32 flags, bool kernel) char * const *env, int32 priority, uint32 flags,
port_id errorPort, uint32 errorToken, bool kernel)
{ {
struct process_group *group; struct process_group *group;
struct team *team, *parent; struct team *team, *parent;
@@ -853,7 +866,8 @@ load_image_etc(int32 argCount, char * const *args, int32 envCount, char * const
RELEASE_TEAM_LOCK(); RELEASE_TEAM_LOCK();
restore_interrupts(state); 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) if (status != B_OK)
goto err1; 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 // Create a kernel thread, but under the context of the new team
// The new thread will take over ownership of teamArgs // The new thread will take over ownership of teamArgs
thread = spawn_kernel_thread_etc(team_create_thread_start, threadName, B_NORMAL_PRIORITY, thread = spawn_kernel_thread_etc(team_create_thread_start, threadName,
teamArgs, team->id, team->id); B_NORMAL_PRIORITY, teamArgs, team->id, team->id);
if (thread < 0) { if (thread < 0) {
status = thread; status = thread;
goto err4; goto err4;
@@ -1007,9 +1021,8 @@ exec_team(const char *path, int32 argCount, char * const *args,
if (status != B_OK) if (status != B_OK)
return status; 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,
-1, 0, false);
status = create_team_arg(&teamArgs, argCount, args, envCount, env, false);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -1857,7 +1870,8 @@ load_image(int32 argCount, const char **args, const char **env)
envCount++; envCount++;
return load_image_etc(argCount, (char * const *)args, 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 team_id
_user_load_image(int32 argCount, const char **userArgs, int32 envCount, _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)); 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 B_BAD_ADDRESS;
return load_image_etc(argCount, (char * const *)userArgs, return load_image_etc(argCount, (char * const *)userArgs,
envCount, (char * const *)userEnv, priority, flags, false); envCount, (char * const *)userEnv, priority, flags, errorPort,
errorToken, false);
} }
+21 -9
View File
@@ -1,17 +1,31 @@
/* cpp - C++ in the kernel /*
** * Copyright 2003-2007, Haiku Inc. All rights reserved.
** Initial version by Axel Dörfler, axeld@pinc-software.de * Distributed under the terms of the MIT License.
** This file may be used under the terms of the OpenBeOS License. *
*/ * Authors:
* Axel Dörfler, axeld@pinc-software.de.
* Ingo Weinhold, bonefish@users.sf.net.
*/
//! C++ in the kernel
#include "util/kernel_cpp.h" #include "util/kernel_cpp.h"
#ifdef _BOOT_MODE #ifdef _BOOT_MODE
# include <boot/platform.h> # include <boot/platform.h>
#elif defined(_KERNEL_MODE) #else
# include <KernelExport.h> # include <KernelExport.h>
# include <stdio.h>
#endif #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 -- // Always define the symbols needed when not linking against libgcc.a --
// we simply override them. // we simply override them.
@@ -39,9 +53,7 @@ __cxa_pure_virtual()
#endif #endif
// full C++ support in the kernel // full C++ support in the kernel
#if defined(_KERNEL_MODE) && !defined(_BOOT_MODE) #if (defined(_KERNEL_MODE) || defined(_LOADER_MODE)) && !defined(_BOOT_MODE)
#include <stdio.h>
FILE *stderr = NULL; FILE *stderr = NULL;
+4 -4
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
@@ -37,7 +37,7 @@ int _data_offset_main_;
void void
initialize_before(image_id imageID) initialize_before(image_id imageID)
{ {
char *programPath = __gRuntimeLoader->program_args->argv[0]; char *programPath = __gRuntimeLoader->program_args->args[0];
if (programPath) { if (programPath) {
if ((__progname = strrchr(programPath, '/')) == NULL) if ((__progname = strrchr(programPath, '/')) == NULL)
__progname = programPath; __progname = programPath;
@@ -45,8 +45,8 @@ initialize_before(image_id imageID)
__progname++; __progname++;
} }
__libc_argc = __gRuntimeLoader->program_args->argc; __libc_argc = __gRuntimeLoader->program_args->arg_count;
__libc_argv = __gRuntimeLoader->program_args->argv; __libc_argv = __gRuntimeLoader->program_args->args;
__init_time(); __init_time();
__init_fork(); __init_fork();
+2 -2
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
@@ -44,7 +44,7 @@ load_image(int32 argCount, const char **args, const char **environ)
envCount++; envCount++;
thread = _kern_load_image(argCount, args, envCount, environ, 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); free(newArgs);
return thread; return thread;
+3 -3
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
@@ -148,12 +148,12 @@ environ_fork_hook(void)
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 // Following POSIX, there is no need to make any of the
// environment functions thread-safe - but we do it anyway // environment functions thread-safe - but we do it anyway
sEnvLock = create_sem(1, "env lock"); sEnvLock = create_sem(1, "env lock");
environ = args->envp; environ = args->env;
atfork(environ_fork_hook); atfork(environ_fork_hook);
} }
+9 -1
View File
@@ -9,11 +9,15 @@ SubDirCcFlags -fno-builtin ;
SubDirC++Flags -fno-builtin -fno-exceptions ; SubDirC++Flags -fno-builtin -fno-exceptions ;
# default to BeOS style symbol resolution # default to BeOS style symbol resolution
DEFINES += BEOS_STYLE_SYMBOLS_RESOLUTION ; DEFINES += BEOS_STYLE_SYMBOLS_RESOLUTION
_LOADER_MODE
;
# needed for "runtime_loader" only # needed for "runtime_loader" only
StaticLibrary libruntime_loader.a : StaticLibrary libruntime_loader.a :
kernel_vsprintf.c kernel_vsprintf.c
kernel_cpp.cpp
KMessage.cpp
: :
<src!system!libroot!os>syscalls.o <src!system!libroot!os>syscalls.o
<src!system!libroot!os>sem.o <src!system!libroot!os>sem.o
@@ -54,8 +58,12 @@ StaticLibrary libruntime_loader.a :
[ FGristFiles kernel_vsprintf.o ] [ FGristFiles kernel_vsprintf.o ]
; ;
SEARCH on [ FGristFiles kernel_cpp.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
SEARCH on [ FGristFiles kernel_vsprintf.c ] SEARCH on [ FGristFiles kernel_vsprintf.c ]
= [ FDirName $(HAIKU_TOP) src system kernel lib ] ; = [ 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) ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
+47 -16
View File
@@ -76,6 +76,7 @@ static image_queue_t sLoadedImages = {0, 0};
static image_queue_t sDisposableImages = {0, 0}; static image_queue_t sDisposableImages = {0, 0};
static uint32 sLoadedImageCount = 0; static uint32 sLoadedImageCount = 0;
static image_t *sProgramImage; static image_t *sProgramImage;
static KMessage sErrorMessage;
#ifdef BEOS_STYLE_SYMBOLS_RESOLUTION #ifdef BEOS_STYLE_SYMBOLS_RESOLUTION
static bool sResolveSymbolsBeOSStyle = true; static bool sResolveSymbolsBeOSStyle = true;
@@ -1096,8 +1097,8 @@ static status_t
load_dependencies(image_t *image) load_dependencies(image_t *image)
{ {
struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
int neededOffset; bool reportErrors = gProgramArgs->error_port >= 0;
status_t status; status_t status = B_OK;
uint32 i, j; uint32 i, j;
const char *rpath; const char *rpath;
@@ -1121,15 +1122,30 @@ load_dependencies(image_t *image)
for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) { for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
switch (d[i].d_tag) { switch (d[i].d_tag) {
case DT_NEEDED: 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), status_t loadStatus = load_container(name, B_LIBRARY_IMAGE,
B_LIBRARY_IMAGE, rpath, &image->needed[j]); rpath, &image->needed[j]);
if (status < B_OK) if (loadStatus < B_OK) {
return status; 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; j += 1;
break; break;
}
default: default:
// ignore any other tag // ignore any other tag
@@ -1137,6 +1153,9 @@ load_dependencies(image_t *image)
} }
} }
if (status < B_OK)
return status;
if (j != image->num_needed) { if (j != image->num_needed) {
FATAL("Internal error at load_dependencies()"); FATAL("Internal error at load_dependencies()");
return B_ERROR; return B_ERROR;
@@ -1255,8 +1274,7 @@ put_image(image_t *image)
} }
// #pragma mark - // #pragma mark - libroot.so exported functions
// Exported functions (to libroot.so)
image_id image_id
@@ -1271,11 +1289,8 @@ load_program(char const *path, void **_entry)
TRACE(("rld: load %s\n", path)); TRACE(("rld: load %s\n", path));
status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage); status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage);
if (status < B_OK) { if (status < B_OK)
_kern_loading_app_failed(status); goto err;
rld_unlock();
return status;
}
for (image = sLoadedImages.head; image != NULL; image = image->next) { for (image = sLoadedImages.head; image != NULL; image = image->next) {
status = load_dependencies(image); status = load_dependencies(image);
@@ -1322,9 +1337,16 @@ load_program(char const *path, void **_entry)
return sProgramImage->id; return sProgramImage->id;
err: err:
_kern_loading_app_failed(status);
delete_image(sProgramImage); 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(); rld_unlock();
return status; 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 */ /** Read and verify the ELF header */
@@ -1627,4 +1649,13 @@ rldelf_init(void)
area->loaded_images = &sLoadedImages; 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');
}
} }
+9 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
@@ -236,6 +236,14 @@ dump_chunks(void)
#endif #endif
void *
realloc(void *buffer, size_t newSize)
{
// not implemented
return NULL;
}
void * void *
malloc(size_t size) malloc(size_t size)
{ {
+14 -14
View File
@@ -26,7 +26,7 @@
#endif #endif
struct uspace_program_args *gProgramArgs; struct user_space_program_args *gProgramArgs;
static const char * 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. Tests if there is an executable file at the provided path. It will
* Even if the runtime loader does not need to be able to deal with also test if the file has a valid ELF header or is a shell script.
* both types, the caller will give scripts a proper treatment. 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 status_t
test_executable(const char *name, uid_t user, gid_t group, char *invoker) 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 int
runtime_loader(void *_args) runtime_loader(void *_args)
{ {
void *entry = NULL; void *entry = NULL;
int returnCode; int returnCode;
gProgramArgs = (struct uspace_program_args *)_args; gProgramArgs = (struct user_space_program_args *)_args;
#if DEBUG_RLD #if DEBUG_RLD
close(0); open("/dev/console", 0); /* stdin */ close(0); open("/dev/console", 0); /* stdin */
@@ -369,8 +369,8 @@ runtime_loader(void *_args)
return -1; return -1;
// call the program entry point (usually _start()) // call the program entry point (usually _start())
returnCode = ((int (*)(int, void *, void *))entry)(gProgramArgs->argc, returnCode = ((int (*)(int, void *, void *))entry)(gProgramArgs->arg_count,
gProgramArgs->argv, gProgramArgs->envp); gProgramArgs->args, gProgramArgs->env);
terminate_program(); terminate_program();
@@ -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. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * Copyright 2002, Manuel J. Petit. All rights reserved.
@@ -13,7 +13,7 @@
#include <runtime_loader.h> #include <runtime_loader.h>
extern struct uspace_program_args *gProgramArgs; extern struct user_space_program_args *gProgramArgs;
extern struct rld_export gRuntimeLoader; extern struct rld_export gRuntimeLoader;
extern char *(*gGetEnv)(const char *name); extern char *(*gGetEnv)(const char *name);
+23 -3
View File
@@ -24,12 +24,12 @@ extern "C" char *
getenv(const char *name) getenv(const char *name)
{ {
if (gGetEnv != NULL) { if (gGetEnv != NULL) {
// Use libroot's getenv() as soon as it is available to us - the environment // Use libroot's getenv() as soon as it is available to us - the
// in gProgramArgs is static. // environment in gProgramArgs is static.
return gGetEnv(name); return gGetEnv(name);
} }
char **environ = gProgramArgs->envp; char **environ = gProgramArgs->env;
int32 length = strlen(name); int32 length = strlen(name);
int32 i; int32 i;
@@ -56,3 +56,23 @@ printf(const char *format, ...)
return length; 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;
}