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:
Trung Nguyen
2023-06-06 15:10:35 +00:00
committed by waddlesplash
parent 9686d93151
commit a2cb4665de
6 changed files with 151 additions and 17 deletions
+12
View File
@@ -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
{
+11
View File
@@ -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;
}
+1
View File
@@ -21,6 +21,7 @@ local straceSources =
MemoryReader.cpp
area.cpp
exec.cpp
fcntl.cpp
ioctl.cpp
network.cpp
+11 -17
View File
@@ -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);
}
+114
View File
@@ -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());
}
+2
View File
@@ -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();