strace: Improvements
- Added some utility functions to the `Context` class. - Updated the `sockaddr` handler to retrieve the next sibling rather than the sibling at index 2. This allows the handler to work for syscalls where the `socklen_t` argument is not the third one, for example, `_kern_recvfrom`. - Added the ability to print the `flatArgs` for `_kern_exec` and `_kern_load_image`. Change-Id: Ia4cf0a30a5cf972274820bbf068101450db52189 Reviewed-on: https://review.haiku-os.org/c/haiku/+/6498 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
9686d93151
commit
a2cb4665de
@@ -12,6 +12,18 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
Parameter *
|
||||
Context::GetNextSibling(Parameter *param) const
|
||||
{
|
||||
for (int32 i = 0; i + 1 < fSyscall->CountParameters(); i++) {
|
||||
if (fSyscall->ParameterAt(i) == param)
|
||||
return fSyscall->ParameterAt(i + 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
string
|
||||
Context::FormatSigned(int64 value, int bytes) const
|
||||
{
|
||||
|
||||
@@ -33,10 +33,21 @@ public:
|
||||
return fSyscall->ParameterAt(index);
|
||||
}
|
||||
|
||||
Parameter *GetNextSibling(Parameter *param) const;
|
||||
|
||||
const void *GetValue(Parameter *param) const {
|
||||
return fData + param->Offset();
|
||||
}
|
||||
|
||||
template<typename value_t>
|
||||
value_t ReadValue(Parameter *param) const {
|
||||
const void *address = GetValue(param);
|
||||
if (sizeof(align_t) > sizeof(value_t))
|
||||
return value_t(*(align_t*)address);
|
||||
else
|
||||
return *(value_t*)address;
|
||||
}
|
||||
|
||||
uint64 GetReturnValue() const {
|
||||
return fReturnValue;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ local straceSources =
|
||||
MemoryReader.cpp
|
||||
|
||||
area.cpp
|
||||
exec.cpp
|
||||
fcntl.cpp
|
||||
ioctl.cpp
|
||||
network.cpp
|
||||
|
||||
@@ -169,17 +169,6 @@ format_pointer(Context &context, flock *lock)
|
||||
|
||||
|
||||
|
||||
template<typename value_t>
|
||||
static inline value_t
|
||||
get_value(const void *address)
|
||||
{
|
||||
if (sizeof(align_t) > sizeof(value_t))
|
||||
return value_t(*(align_t*)address);
|
||||
else
|
||||
return *(value_t*)address;
|
||||
}
|
||||
|
||||
|
||||
static string
|
||||
format_signed_number(int32 value)
|
||||
{
|
||||
@@ -192,7 +181,7 @@ format_signed_number(int32 value)
|
||||
static string
|
||||
read_pollfd(Context &context, void *data)
|
||||
{
|
||||
nfds_t numfds = get_value<nfds_t>(context.GetValue(context.GetSibling(1)));
|
||||
nfds_t numfds = context.ReadValue<nfds_t>(context.GetSibling(1));
|
||||
if ((int64)numfds <= 0)
|
||||
return string();
|
||||
|
||||
@@ -424,10 +413,15 @@ format_pointer(Context &context, sockaddr *saddr)
|
||||
|
||||
|
||||
static string
|
||||
read_sockaddr(Context &context, void *address)
|
||||
read_sockaddr(Context &context, Parameter *param, void *address)
|
||||
{
|
||||
param = context.GetNextSibling(param);
|
||||
if (param == NULL)
|
||||
return context.FormatPointer(address);
|
||||
|
||||
socklen_t addrlen = context.ReadValue<socklen_t>(param);
|
||||
|
||||
sockaddr_storage data;
|
||||
socklen_t addrlen = get_value<socklen_t>(context.GetValue(context.GetSibling(2)));
|
||||
|
||||
if (addrlen > sizeof(data))
|
||||
return context.FormatPointer(address);
|
||||
@@ -443,12 +437,12 @@ read_sockaddr(Context &context, void *address)
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<sockaddr *>::GetParameterValue(Context &context, Parameter *,
|
||||
const void *address)
|
||||
TypeHandlerImpl<sockaddr *>::GetParameterValue(Context &context,
|
||||
Parameter *param, const void *address)
|
||||
{
|
||||
void *data = *(void **)address;
|
||||
if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS))
|
||||
return read_sockaddr(context, data);
|
||||
return read_sockaddr(context, param, data);
|
||||
return context.FormatPointer(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2023, Trung Nguyen, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "strace.h"
|
||||
#include "Context.h"
|
||||
#include "MemoryReader.h"
|
||||
#include "TypeHandler.h"
|
||||
|
||||
|
||||
using BPrivate::AutoDeleter;
|
||||
|
||||
|
||||
class FlatArgsTypeHandler : public TypeHandler {
|
||||
public:
|
||||
string GetParameterValue(Context &context, Parameter *param,
|
||||
const void *address)
|
||||
{
|
||||
size_t flatArgsSize;
|
||||
int32 argCount, envCount;
|
||||
char *flatArgs, *flatArgsEnd;
|
||||
int32 bytesRead;
|
||||
status_t err;
|
||||
ArrayDeleter<char> flatArgsDeleter;
|
||||
string r;
|
||||
|
||||
if (!context.GetContents(Context::COMPLEX_STRUCTS))
|
||||
goto fallback;
|
||||
|
||||
param = context.GetNextSibling(param);
|
||||
if (param == NULL)
|
||||
goto fallback;
|
||||
flatArgsSize = context.ReadValue<size_t>(param);
|
||||
|
||||
param = context.GetNextSibling(param);
|
||||
if (param == NULL)
|
||||
goto fallback;
|
||||
argCount = context.ReadValue<int32>(param);
|
||||
|
||||
param = context.GetNextSibling(param);
|
||||
if (param == NULL)
|
||||
goto fallback;
|
||||
envCount = context.ReadValue<int32>(param);
|
||||
|
||||
flatArgs = new (std::nothrow) char[flatArgsSize + 1];
|
||||
if (flatArgs == NULL)
|
||||
goto fallback;
|
||||
|
||||
flatArgsDeleter.SetTo(flatArgs);
|
||||
|
||||
// Guard with a null byte to prevent faulty buffers.
|
||||
flatArgsEnd = flatArgs + flatArgsSize;
|
||||
*flatArgsEnd = '\0';
|
||||
|
||||
err = context.Reader().Read(*(void **)address, flatArgs, flatArgsSize,
|
||||
bytesRead);
|
||||
if (err != B_OK)
|
||||
goto fallback;
|
||||
|
||||
flatArgs += sizeof(void *) * (argCount + envCount + 2);
|
||||
|
||||
r = "{args = [";
|
||||
|
||||
for (int32 i = 0; i < argCount && flatArgs < flatArgsEnd; i++) {
|
||||
if (i > 0)
|
||||
r += ", ";
|
||||
size_t currentLen = strlen(flatArgs);
|
||||
r += "\"";
|
||||
r += flatArgs;
|
||||
r += "\"";
|
||||
flatArgs += currentLen + 1;
|
||||
}
|
||||
|
||||
r += "], env = [";
|
||||
|
||||
for (int32 i = 0; i < envCount && flatArgs < flatArgsEnd; i++) {
|
||||
if (i > 0)
|
||||
r += ", ";
|
||||
size_t currentLen = strlen(flatArgs);
|
||||
r += "\"";
|
||||
r += flatArgs;
|
||||
r += "\"";
|
||||
flatArgs += currentLen + 1;
|
||||
}
|
||||
|
||||
r += "]}";
|
||||
|
||||
return r;
|
||||
fallback:
|
||||
return context.FormatPointer(address);
|
||||
}
|
||||
|
||||
string GetReturnValue(Context &context, uint64 value)
|
||||
{
|
||||
return context.FormatPointer((void *)value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
patch_exec()
|
||||
{
|
||||
Syscall *exec = get_syscall("_kern_exec");
|
||||
exec->GetParameter("flatArgs")->SetHandler(new FlatArgsTypeHandler());
|
||||
|
||||
Syscall *load_image = get_syscall("_kern_load_image");
|
||||
load_image->GetParameter("flatArgs")->SetHandler(new FlatArgsTypeHandler());
|
||||
}
|
||||
@@ -230,6 +230,7 @@ patch_syscalls()
|
||||
// kernel/syscalls.h and have it parsed automatically
|
||||
|
||||
extern void patch_area();
|
||||
extern void patch_exec();
|
||||
extern void patch_fcntl();
|
||||
extern void patch_ioctl();
|
||||
extern void patch_network();
|
||||
@@ -246,6 +247,7 @@ patch_syscalls()
|
||||
}
|
||||
|
||||
patch_area();
|
||||
patch_exec();
|
||||
patch_fcntl();
|
||||
patch_ioctl();
|
||||
patch_network();
|
||||
|
||||
Reference in New Issue
Block a user