* syscalls.c -> syscalls.cpp
* With post syscall debugging enabled, the x86 syscall handling didn't remove all parameters from the stack after calling the respective user debugger hook. Should have been harmless though, since the following code didn't rely on the stack being in order. * Added syscall pre/post (kernel) tracing functions trace_{pre,post}_syscall(). They are generic, but need to be invoked by the architecture specific syscall code. Currently only done for x86. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23600 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
21c92a08d4
commit
548dcc600e
@ -37,7 +37,7 @@ KernelMergeObject kernel_core.o :
|
||||
signal.cpp
|
||||
system_info.c
|
||||
smp.c
|
||||
syscalls.c
|
||||
syscalls.cpp
|
||||
team.cpp
|
||||
thread.cpp
|
||||
timer.c
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "syscall_table.h"
|
||||
|
||||
|
||||
//#define SYSCALL_TRACING
|
||||
// also define this macro in syscalls.cpp
|
||||
|
||||
#define FUNCTION(x) .global x; .type x,@function; x
|
||||
|
||||
#define UPDATE_THREAD_USER_TIME_COMMON() \
|
||||
@ -131,6 +134,31 @@
|
||||
movl %dr3, %edi; /* thread pointer */ \
|
||||
movl $0, THREAD_fault_handler(%edi)
|
||||
|
||||
#ifdef SYSCALL_TRACING
|
||||
# define TRACE_PRE_SYSCALL() \
|
||||
movl %esp, %eax; /* syscall parameters */ \
|
||||
push %eax; \
|
||||
movl IFRAME_orig_eax(%ebp), %eax; /* syscall number */ \
|
||||
push %eax; \
|
||||
call trace_pre_syscall; \
|
||||
addl $8, %esp;
|
||||
|
||||
# define TRACE_POST_SYSCALL() \
|
||||
testl $THREAD_FLAGS_64_BIT_SYSCALL_RETURN, THREAD_flags(%edi); \
|
||||
jnz 1f; \
|
||||
xor %edx, %edx; \
|
||||
1: \
|
||||
push %edx; /* syscall return value */ \
|
||||
push %eax; \
|
||||
movl IFRAME_orig_eax(%ebp), %eax; /* syscall number */ \
|
||||
push %eax; \
|
||||
call trace_post_syscall; \
|
||||
addl $12, %esp
|
||||
#else
|
||||
# define TRACE_PRE_SYSCALL()
|
||||
# define TRACE_POST_SYSCALL()
|
||||
#endif
|
||||
|
||||
|
||||
.text
|
||||
|
||||
@ -308,6 +336,7 @@ trap99:
|
||||
COPY_SYSCALL_PARAMETERS()
|
||||
|
||||
// pre syscall debugging
|
||||
TRACE_PRE_SYSCALL()
|
||||
testl $THREAD_FLAGS_DEBUGGER_INSTALLED, THREAD_flags(%edi)
|
||||
jnz do_pre_syscall_debug
|
||||
pre_syscall_debug_done:
|
||||
@ -320,6 +349,8 @@ trap99:
|
||||
movl %edx, IFRAME_edx(%ebp)
|
||||
movl %eax, IFRAME_eax(%ebp)
|
||||
|
||||
TRACE_POST_SYSCALL()
|
||||
|
||||
testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \
|
||||
| THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED) \
|
||||
, THREAD_flags(%edi)
|
||||
@ -365,7 +396,7 @@ trap99:
|
||||
movl IFRAME_orig_eax(%ebp), %eax // syscall number
|
||||
push %eax
|
||||
call user_debug_post_syscall
|
||||
addl $8, %esp
|
||||
addl $24, %esp
|
||||
1:
|
||||
|
||||
bad_syscall_number:
|
||||
@ -454,6 +485,7 @@ FUNCTION(x86_sysenter):
|
||||
COPY_SYSCALL_PARAMETERS()
|
||||
|
||||
// pre syscall debugging
|
||||
TRACE_PRE_SYSCALL()
|
||||
testl $THREAD_FLAGS_DEBUGGER_INSTALLED, THREAD_flags(%edi)
|
||||
jnz do_pre_syscall_debug
|
||||
// if debugging is enabled, we take the slow syscall exit
|
||||
@ -466,6 +498,8 @@ FUNCTION(x86_sysenter):
|
||||
movl %edx, IFRAME_edx(%ebp)
|
||||
movl %eax, IFRAME_eax(%ebp)
|
||||
|
||||
TRACE_POST_SYSCALL()
|
||||
|
||||
testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \
|
||||
| THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED \
|
||||
| THREAD_FLAGS_64_BIT_SYSCALL_RETURN) \
|
||||
|
@ -9,8 +9,9 @@
|
||||
#include <ksyscalls.h>
|
||||
#include <syscalls.h>
|
||||
#include <generic_syscall.h>
|
||||
#include <int.h>
|
||||
#include <debug.h>
|
||||
#include <int.h>
|
||||
#include <elf.h>
|
||||
#include <vfs.h>
|
||||
#include <vm.h>
|
||||
#include <thread.h>
|
||||
@ -25,9 +26,10 @@
|
||||
#include <kimage.h>
|
||||
#include <ksignal.h>
|
||||
#include <real_time_clock.h>
|
||||
#include <system_info.h>
|
||||
#include <user_atomic.h>
|
||||
#include <safemode.h>
|
||||
#include <system_info.h>
|
||||
#include <tracing.h>
|
||||
#include <user_atomic.h>
|
||||
#include <arch/system_info.h>
|
||||
#include <messaging.h>
|
||||
#include <frame_buffer_console.h>
|
||||
@ -37,6 +39,9 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//#define SYSCALL_TRACING
|
||||
|
||||
|
||||
typedef struct generic_syscall generic_syscall;
|
||||
|
||||
struct generic_syscall {
|
||||
@ -59,7 +64,8 @@ find_generic_syscall(const char *subsystem)
|
||||
|
||||
ASSERT_LOCKED_MUTEX(&sGenericSyscallLock);
|
||||
|
||||
while ((syscall = list_get_next_item(&sGenericSyscalls, syscall)) != NULL) {
|
||||
while ((syscall = (generic_syscall*)list_get_next_item(&sGenericSyscalls,
|
||||
syscall)) != NULL) {
|
||||
if (!strcmp(syscall->subsystem, subsystem))
|
||||
return syscall;
|
||||
}
|
||||
@ -193,7 +199,7 @@ syscall_dispatcher(uint32 call_num, void *args, uint64 *call_ret)
|
||||
#include "syscall_dispatcher.h"
|
||||
|
||||
default:
|
||||
*call_ret = -1;
|
||||
*call_ret = (uint64)B_BAD_VALUE;
|
||||
}
|
||||
|
||||
user_debug_post_syscall(call_num, args, *call_ret, startTime);
|
||||
@ -290,6 +296,134 @@ unregister_generic_syscall(const char *subsystem, uint32 version)
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - syscall tracing
|
||||
|
||||
|
||||
#ifdef SYSCALL_TRACING
|
||||
|
||||
namespace SyscallTracing {
|
||||
|
||||
|
||||
static const char*
|
||||
get_syscall_name(uint32 syscall)
|
||||
{
|
||||
addr_t baseAddress;
|
||||
const char* symbolName;
|
||||
const char* imageName;
|
||||
bool exactMatch;
|
||||
|
||||
if (syscall >= (uint32)kSyscallCount)
|
||||
return "<invalid syscall number>";
|
||||
|
||||
if (elf_debug_lookup_symbol_address(
|
||||
(addr_t)kSyscallInfos[syscall].function,
|
||||
&baseAddress, &symbolName, &imageName,
|
||||
&exactMatch) != B_OK) {
|
||||
return "<lookup failed>";
|
||||
}
|
||||
|
||||
return symbolName;
|
||||
}
|
||||
|
||||
|
||||
class PreSyscall : public AbstractTraceEntry {
|
||||
public:
|
||||
PreSyscall(uint32 syscall, const void* parameters)
|
||||
:
|
||||
fSyscall(syscall),
|
||||
fParameters(NULL)
|
||||
{
|
||||
if (syscall < (uint32)kSyscallCount) {
|
||||
fParameters = alloc_tracing_buffer_memcpy(parameters,
|
||||
kSyscallInfos[syscall].parameter_size, false);
|
||||
}
|
||||
|
||||
Initialized();
|
||||
}
|
||||
|
||||
virtual void AddDump(char *buffer, size_t size)
|
||||
{
|
||||
snprintf(buffer, size, "syscall pre: %s(",
|
||||
get_syscall_name(fSyscall));
|
||||
|
||||
size_t bytesPrinted = strlen(buffer);
|
||||
buffer += bytesPrinted;
|
||||
size -= bytesPrinted;
|
||||
|
||||
if (fParameters != NULL) {
|
||||
uint32* params = (uint32*)fParameters;
|
||||
int32 paramSize = kSyscallInfos[fSyscall].parameter_size;
|
||||
bool first = true;
|
||||
while (paramSize >= 4 && size > 0) {
|
||||
if (first) {
|
||||
snprintf(buffer, size, "0x%lx", *params);
|
||||
first = false;
|
||||
} else
|
||||
snprintf(buffer, size, ", 0x%lx", *params);
|
||||
|
||||
bytesPrinted = strlen(buffer);
|
||||
buffer += bytesPrinted;
|
||||
size -= bytesPrinted;
|
||||
params++;
|
||||
paramSize -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
strlcat(buffer, ")", size);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 fSyscall;
|
||||
void* fParameters;
|
||||
};
|
||||
|
||||
|
||||
class PostSyscall : public AbstractTraceEntry {
|
||||
public:
|
||||
PostSyscall(uint32 syscall, uint64 returnValue)
|
||||
:
|
||||
fSyscall(syscall),
|
||||
fReturnValue(returnValue)
|
||||
{
|
||||
Initialized();
|
||||
}
|
||||
|
||||
virtual void AddDump(char *buffer, size_t size)
|
||||
{
|
||||
snprintf(buffer, size, "syscall post: %s() -> 0x%llx",
|
||||
get_syscall_name(fSyscall), fReturnValue);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 fSyscall;
|
||||
uint64 fReturnValue;
|
||||
};
|
||||
|
||||
} // namespace TeamTracing
|
||||
|
||||
|
||||
extern "C" void trace_pre_syscall(uint32 syscallNumber, const void* parameters);
|
||||
|
||||
void
|
||||
trace_pre_syscall(uint32 syscallNumber, const void* parameters)
|
||||
{
|
||||
new(std::nothrow) SyscallTracing::PreSyscall(syscallNumber, parameters);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void trace_post_syscall(int syscallNumber, uint64 returnValue);
|
||||
|
||||
void
|
||||
trace_post_syscall(int syscallNumber, uint64 returnValue)
|
||||
{
|
||||
new(std::nothrow) SyscallTracing::PostSyscall(syscallNumber, returnValue);
|
||||
}
|
||||
|
||||
|
||||
#endif // SYSCALL_TRACING
|
||||
|
||||
|
||||
/*
|
||||
* kSyscallCount and kSyscallInfos here
|
||||
*/
|
Loading…
Reference in New Issue
Block a user