* 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:
@@ -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();
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#define _TEAM_H
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <thread_types.h>
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
#ifndef LIBROOT_PRIVATE_H
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <image.h>
|
||||
|
||||
|
||||
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);
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
|
||||
@@ -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<char *>(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
|
||||
|
||||
@@ -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 <KMessage.h>
|
||||
UsePrivateHeaders shared ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src system kernel disk_device_manager ] ;
|
||||
# for "Locker.h"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "KMessage.h"
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <KernelExport.h>
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#if defined(_BOOT_MODE)
|
||||
#if defined(_BOOT_MODE) || defined(_LOADER_MODE)
|
||||
# include <util/kernel_cpp.h>
|
||||
#else
|
||||
# include <new>
|
||||
@@ -32,6 +32,21 @@ using std::nothrow;
|
||||
# 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;
|
||||
|
||||
// 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);
|
||||
|
||||
+57
-41
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 <boot/platform.h>
|
||||
#elif defined(_KERNEL_MODE)
|
||||
#else
|
||||
# include <KernelExport.h>
|
||||
# include <stdio.h>
|
||||
#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 <stdio.h>
|
||||
#if (defined(_KERNEL_MODE) || defined(_LOADER_MODE)) && !defined(_BOOT_MODE)
|
||||
|
||||
FILE *stderr = NULL;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
:
|
||||
<src!system!libroot!os>syscalls.o
|
||||
<src!system!libroot!os>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) ] ;
|
||||
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 <runtime_loader.h>
|
||||
|
||||
|
||||
extern struct uspace_program_args *gProgramArgs;
|
||||
extern struct user_space_program_args *gProgramArgs;
|
||||
extern struct rld_export gRuntimeLoader;
|
||||
extern char *(*gGetEnv)(const char *name);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user