mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
LibCpp: Add regression tests for the parser
For each .cpp file in the test suite data, there is a .ast file that represents the "known good" baseline of the parser result. Each .cpp file goes through the parser, and the result of invoking `ASTNode::dump()` on the root node is compared to the baseline to find regressions. We also check that there were no parser errors when parsing the .cpp files.
This commit is contained in:
parent
fbf796cd9f
commit
832e9c6e02
Notes:
sideshowbarker
2024-07-18 17:44:49 +09:00
Author: https://github.com/itamar8910 Commit: https://github.com/SerenityOS/serenity/commit/832e9c6e02b Pull-request: https://github.com/SerenityOS/serenity/pull/7261
16 changed files with 1264 additions and 3 deletions
|
@ -110,6 +110,7 @@ cp "$SERENITY_SOURCE_DIR"/README.md mnt/home/anon/
|
|||
cp -r "$SERENITY_SOURCE_DIR"/Userland/Libraries/LibJS/Tests mnt/home/anon/js-tests
|
||||
cp -r "$SERENITY_SOURCE_DIR"/Userland/Libraries/LibWeb/Tests mnt/home/anon/web-tests
|
||||
cp -r "$SERENITY_SOURCE_DIR"/Userland/DevTools/HackStudio/LanguageServers/Cpp/Tests mnt/home/anon/cpp-tests/comprehension
|
||||
cp -r "$SERENITY_SOURCE_DIR"/Userland/Libraries/LibCpp/Tests mnt/home/anon/cpp-tests/parser
|
||||
chmod 700 mnt/root
|
||||
chmod 700 mnt/home/anon
|
||||
chmod 700 mnt/home/nona
|
||||
|
|
|
@ -12,7 +12,7 @@ cd "$script_path/.." || exit 1
|
|||
# */
|
||||
GOOD_LICENSE_HEADER_PATTERN=$'^/\*\n( \* Copyright \(c\) [0-9]{4}(-[0-9]{4})?, .*\n)+ \*\n \* SPDX-License-Identifier: BSD-2-Clause\n \*/\n\n'
|
||||
BAD_LICENSE_HEADER_ERRORS=()
|
||||
LICENSE_HEADER_CHECK_EXCLUDES=(AK/Checked.h AK/Function.h Userland/Libraries/LibC/elf.h Userland/DevTools/HackStudio/LanguageServers/Cpp/Tests/*)
|
||||
LICENSE_HEADER_CHECK_EXCLUDES=(AK/Checked.h AK/Function.h Userland/Libraries/LibC/elf.h Userland/DevTools/HackStudio/LanguageServers/Cpp/Tests/* Userland/Libraries/LibCpp/Tests/*)
|
||||
|
||||
# We check that "#pragma once" is present
|
||||
PRAGMA_ONCE_PATTERN='#pragma once'
|
||||
|
|
|
@ -13,7 +13,8 @@ if [ "$#" -eq "1" ]; then
|
|||
':!:Base' \
|
||||
':!:Kernel/FileSystem/ext2_fs.h' \
|
||||
':!:Userland/Libraries/LibC/syslog.h' \
|
||||
':!:Userland/DevTools/HackStudio/LanguageServers/Cpp/Tests/*'
|
||||
':!:Userland/DevTools/HackStudio/LanguageServers/Cpp/Tests/*' \
|
||||
':!:Userland/Libraries/LibCpp/Tests/*'
|
||||
)
|
||||
else
|
||||
files=()
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
add_subdirectory(AK)
|
||||
add_subdirectory(Kernel)
|
||||
add_subdirectory(LibC)
|
||||
add_subdirectory(LibCore)
|
||||
add_subdirectory(LibCompress)
|
||||
add_subdirectory(LibCore)
|
||||
add_subdirectory(LibCpp)
|
||||
add_subdirectory(LibELF)
|
||||
add_subdirectory(LibGfx)
|
||||
add_subdirectory(LibJS)
|
||||
|
|
5
Tests/LibCpp/CMakeLists.txt
Normal file
5
Tests/LibCpp/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
|
||||
|
||||
foreach(CMD_SRC ${CMD_SOURCES})
|
||||
serenity_test(${CMD_SRC} LibCpp LIBS LibCpp)
|
||||
endforeach()
|
80
Tests/LibCpp/test-cpp-parser.cpp
Normal file
80
Tests/LibCpp/test-cpp-parser.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <LibCore/DirIterator.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibCpp/Parser.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
constexpr char TESTS_ROOT_DIR[] = "/home/anon/cpp-tests/parser";
|
||||
|
||||
static String read_all(const String& path)
|
||||
{
|
||||
auto result = Core::File::open(path, Core::OpenMode::ReadOnly);
|
||||
VERIFY(!result.is_error());
|
||||
auto content = result.value()->read_all();
|
||||
return { reinterpret_cast<const char*>(content.data()), content.size() };
|
||||
}
|
||||
|
||||
TEST_CASE(test_regression)
|
||||
{
|
||||
Core::DirIterator directory_iterator(TESTS_ROOT_DIR, Core::DirIterator::Flags::SkipDots);
|
||||
|
||||
while (directory_iterator.has_next()) {
|
||||
auto file_path = directory_iterator.next_full_path();
|
||||
|
||||
auto path = LexicalPath { file_path };
|
||||
if (!path.has_extension(".cpp"))
|
||||
continue;
|
||||
|
||||
outln("Checking {}...", path.basename());
|
||||
|
||||
auto ast_file_path = String::formatted("{}.ast", file_path.substring(0, file_path.length() - sizeof(".cpp") + 1));
|
||||
|
||||
auto source = read_all(file_path);
|
||||
auto target_ast = read_all(ast_file_path);
|
||||
|
||||
StringView source_view(source);
|
||||
::Cpp::Parser parser(source_view, file_path);
|
||||
auto root = parser.parse();
|
||||
|
||||
EXPECT(parser.errors().is_empty());
|
||||
|
||||
int pipefd[2] = {};
|
||||
if (pipe(pipefd) < 0) {
|
||||
perror("pipe");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
FILE* input_stream = fdopen(pipefd[0], "r");
|
||||
FILE* output_stream = fdopen(pipefd[1], "w");
|
||||
|
||||
root->dump(output_stream);
|
||||
|
||||
fclose(output_stream);
|
||||
|
||||
ByteBuffer buffer;
|
||||
while (!feof(input_stream)) {
|
||||
char chunk[4096];
|
||||
size_t size = fread(chunk, sizeof(char), sizeof(chunk), input_stream);
|
||||
if (size == 0)
|
||||
break;
|
||||
buffer.append(chunk, size);
|
||||
}
|
||||
|
||||
fclose(input_stream);
|
||||
|
||||
String content { reinterpret_cast<const char*>(buffer.data()), buffer.size() };
|
||||
|
||||
auto equal = content == target_ast;
|
||||
EXPECT(equal);
|
||||
}
|
||||
}
|
10
Userland/Libraries/LibCpp/Tests/function-decl.ast
Normal file
10
Userland/Libraries/LibCpp/Tests/function-decl.ast
Normal file
|
@ -0,0 +1,10 @@
|
|||
TranslationUnit[0:0->2:0]
|
||||
FunctionDeclaration[0:0->2:0]
|
||||
Type[0:0->0:4]
|
||||
int
|
||||
foo
|
||||
(
|
||||
)
|
||||
FunctionDefinition[1:0->2:0]
|
||||
{
|
||||
}
|
3
Userland/Libraries/LibCpp/Tests/function-decl.cpp
Normal file
3
Userland/Libraries/LibCpp/Tests/function-decl.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
int foo()
|
||||
{
|
||||
}
|
33
Userland/Libraries/LibCpp/Tests/if-else.ast
Normal file
33
Userland/Libraries/LibCpp/Tests/if-else.ast
Normal file
|
@ -0,0 +1,33 @@
|
|||
TranslationUnit[0:0->7:0]
|
||||
FunctionDeclaration[0:0->7:0]
|
||||
Type[0:0->0:4]
|
||||
int
|
||||
foo
|
||||
(
|
||||
)
|
||||
FunctionDefinition[1:0->7:0]
|
||||
{
|
||||
IfStatement[2:4->3:16]
|
||||
Predicate:
|
||||
NumericLiteral[2:8->2:8]
|
||||
2
|
||||
Then:
|
||||
ReturnStatement[3:8->3:16]
|
||||
NumericLiteral[3:15->3:15]
|
||||
2
|
||||
IfStatement[4:4->5:16]
|
||||
Predicate:
|
||||
BinaryExpression[4:8->4:12]
|
||||
NumericLiteral[4:8->4:8]
|
||||
1
|
||||
<
|
||||
NumericLiteral[4:12->4:12]
|
||||
2
|
||||
Then:
|
||||
ReturnStatement[5:8->5:16]
|
||||
NumericLiteral[5:15->5:15]
|
||||
1
|
||||
ReturnStatement[6:4->6:12]
|
||||
NumericLiteral[6:11->6:11]
|
||||
0
|
||||
}
|
8
Userland/Libraries/LibCpp/Tests/if-else.cpp
Normal file
8
Userland/Libraries/LibCpp/Tests/if-else.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
int foo()
|
||||
{
|
||||
if (2)
|
||||
return 2;
|
||||
if (1 < 2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
33
Userland/Libraries/LibCpp/Tests/local-vars.ast
Normal file
33
Userland/Libraries/LibCpp/Tests/local-vars.ast
Normal file
|
@ -0,0 +1,33 @@
|
|||
TranslationUnit[1:0->7:0]
|
||||
FunctionDeclaration[1:0->7:0]
|
||||
Type[1:0->1:4]
|
||||
int
|
||||
foo
|
||||
(
|
||||
)
|
||||
FunctionDefinition[2:0->7:0]
|
||||
{
|
||||
VariableDeclaration[3:4->3:9]
|
||||
Type[3:4->3:8]
|
||||
int
|
||||
x
|
||||
VariableDeclaration[4:4->4:16]
|
||||
Type[4:4->4:11]
|
||||
double
|
||||
y
|
||||
NumericLiteral[4:15->4:15]
|
||||
2
|
||||
VariableDeclaration[5:4->5:20]
|
||||
Type[5:4->5:11]
|
||||
double
|
||||
z
|
||||
BinaryExpression[5:15->5:20]
|
||||
Name[5:15->5:17]
|
||||
x
|
||||
+
|
||||
Name[5:19->5:20]
|
||||
y
|
||||
ReturnStatement[6:4->6:12]
|
||||
Name[6:11->6:12]
|
||||
z
|
||||
}
|
8
Userland/Libraries/LibCpp/Tests/local-vars.cpp
Normal file
8
Userland/Libraries/LibCpp/Tests/local-vars.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
int foo()
|
||||
{
|
||||
int x;
|
||||
double y = 2;
|
||||
double z = x + y;
|
||||
return z;
|
||||
}
|
879
Userland/Libraries/LibCpp/Tests/strace.ast
Normal file
879
Userland/Libraries/LibCpp/Tests/strace.ast
Normal file
|
@ -0,0 +1,879 @@
|
|||
TranslationUnit[0:0->144:0]
|
||||
VariableDeclaration[0:0->2:0]
|
||||
Type[0:0->0:11]
|
||||
[static] int
|
||||
g_pid
|
||||
UnaryExpression[0:19->0:20]
|
||||
-
|
||||
NumericLiteral[0:20->0:20]
|
||||
1
|
||||
FunctionDeclaration[2:0->10:0]
|
||||
[static]
|
||||
Type[2:7->2:12]
|
||||
void
|
||||
handle_sigint
|
||||
(
|
||||
Parameter[2:26->2:29]
|
||||
Type[2:26->2:29]
|
||||
int
|
||||
)
|
||||
FunctionDefinition[3:0->10:0]
|
||||
{
|
||||
IfStatement[4:4->5:14]
|
||||
Predicate:
|
||||
BinaryExpression[4:8->4:18]
|
||||
Name[4:8->4:14]
|
||||
g_pid
|
||||
==
|
||||
UnaryExpression[4:17->4:18]
|
||||
-
|
||||
NumericLiteral[4:18->4:18]
|
||||
1
|
||||
Then:
|
||||
ReturnStatement[5:8->5:14]
|
||||
IfStatement[7:4->10:0]
|
||||
Predicate:
|
||||
BinaryExpression[7:8->7:43]
|
||||
FunctionCall[7:8->7:39]
|
||||
Name[7:8->7:14]
|
||||
ptrace
|
||||
Name[7:15->7:24]
|
||||
PT_DETACH
|
||||
Name[7:26->7:31]
|
||||
g_pid
|
||||
NumericLiteral[7:33->7:33]
|
||||
0
|
||||
NumericLiteral[7:36->7:36]
|
||||
0
|
||||
==
|
||||
UnaryExpression[7:42->7:43]
|
||||
-
|
||||
NumericLiteral[7:43->7:43]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[7:46->10:0]
|
||||
FunctionCall[8:8->8:24]
|
||||
Name[8:8->8:14]
|
||||
perror
|
||||
StringLiteral[8:15->8:22]
|
||||
"detach"
|
||||
}
|
||||
FunctionDeclaration[12:0->144:0]
|
||||
Type[12:0->12:4]
|
||||
int
|
||||
main
|
||||
(
|
||||
Parameter[12:9->12:16]
|
||||
argc
|
||||
Type[12:9->12:13]
|
||||
int
|
||||
Parameter[12:24->12:29]
|
||||
argv
|
||||
Pointer[12:24->12:26]
|
||||
Pointer[12:23->12:24]
|
||||
Type[12:19->12:23]
|
||||
char
|
||||
)
|
||||
FunctionDefinition[13:0->144:0]
|
||||
{
|
||||
IfStatement[14:4->19:4]
|
||||
Predicate:
|
||||
BinaryExpression[14:8->14:74]
|
||||
FunctionCall[14:8->14:72]
|
||||
Name[14:8->14:14]
|
||||
pledge
|
||||
StringLiteral[14:15->14:60]
|
||||
"stdio wpath cpath proc exec ptrace sigaction"
|
||||
NullPointerLiteral[14:63->14:69]
|
||||
<
|
||||
NumericLiteral[14:74->14:74]
|
||||
0
|
||||
Then:
|
||||
BlockStatement[14:77->19:4]
|
||||
FunctionCall[15:8->15:24]
|
||||
Name[15:8->15:14]
|
||||
perror
|
||||
StringLiteral[15:15->15:22]
|
||||
"pledge"
|
||||
ReturnStatement[16:8->16:16]
|
||||
NumericLiteral[16:15->16:15]
|
||||
1
|
||||
VariableDeclaration[19:4->19:34]
|
||||
Type[19:4->19:24]
|
||||
Vector<[const] char*>
|
||||
child_argv
|
||||
VariableDeclaration[21:4->21:41]
|
||||
Pointer[21:14->21:16]
|
||||
Type[21:4->21:14]
|
||||
[const] char
|
||||
output_filename
|
||||
NullPointerLiteral[21:34->21:40]
|
||||
VariableDeclaration[22:4->22:50]
|
||||
Type[22:4->22:9]
|
||||
auto
|
||||
trace_file
|
||||
FunctionCall[22:22->22:50]
|
||||
Name[22:22->22:48]
|
||||
Core::File::standard_error
|
||||
VariableDeclaration[24:4->24:27]
|
||||
Type[24:4->24:21]
|
||||
Core::ArgsParser
|
||||
parser
|
||||
FunctionCall[25:4->26:47]
|
||||
MemberExpression[25:4->25:27]
|
||||
Name[25:4->25:10]
|
||||
parser
|
||||
Identifier[25:11->25:26]
|
||||
set_general_help
|
||||
StringLiteral[26:8->26:45]
|
||||
"Trace all syscalls and their result."
|
||||
FunctionCall[27:4->27:70]
|
||||
MemberExpression[27:4->27:21]
|
||||
Name[27:4->27:10]
|
||||
parser
|
||||
Identifier[27:11->27:20]
|
||||
add_option
|
||||
Name[27:22->27:27]
|
||||
g_pid
|
||||
StringLiteral[27:29->27:49]
|
||||
"Trace the given PID"
|
||||
StringLiteral[27:52->27:56]
|
||||
"pid"
|
||||
StringLiteral[27:59->27:61]
|
||||
'p'
|
||||
StringLiteral[27:64->27:68]
|
||||
"pid"
|
||||
FunctionCall[28:4->28:94]
|
||||
MemberExpression[28:4->28:21]
|
||||
Name[28:4->28:10]
|
||||
parser
|
||||
Identifier[28:11->28:20]
|
||||
add_option
|
||||
Name[28:22->28:37]
|
||||
output_filename
|
||||
StringLiteral[28:39->28:67]
|
||||
"Filename to write output to"
|
||||
StringLiteral[28:70->28:77]
|
||||
"output"
|
||||
StringLiteral[28:80->28:82]
|
||||
'o'
|
||||
StringLiteral[28:85->28:92]
|
||||
"output"
|
||||
FunctionCall[29:4->29:111]
|
||||
MemberExpression[29:4->29:34]
|
||||
Name[29:4->29:10]
|
||||
parser
|
||||
Identifier[29:11->29:33]
|
||||
add_positional_argument
|
||||
Name[29:35->29:45]
|
||||
child_argv
|
||||
StringLiteral[29:47->29:65]
|
||||
"Arguments to exec"
|
||||
StringLiteral[29:68->29:77]
|
||||
"argument"
|
||||
Name[29:80->29:110]
|
||||
Core::ArgsParser::Required::No
|
||||
FunctionCall[31:4->31:28]
|
||||
MemberExpression[31:4->31:16]
|
||||
Name[31:4->31:10]
|
||||
parser
|
||||
Identifier[31:11->31:15]
|
||||
parse
|
||||
Name[31:17->31:21]
|
||||
argc
|
||||
Name[31:23->31:27]
|
||||
argv
|
||||
IfStatement[33:4->42:4]
|
||||
Predicate:
|
||||
BinaryExpression[33:8->33:33]
|
||||
Name[33:8->33:24]
|
||||
output_filename
|
||||
!=
|
||||
NullPointerLiteral[33:27->33:33]
|
||||
Then:
|
||||
BlockStatement[33:36->42:4]
|
||||
VariableDeclaration[34:8->34:87]
|
||||
Type[34:8->34:13]
|
||||
auto
|
||||
open_result
|
||||
FunctionCall[34:27->34:87]
|
||||
Name[34:27->34:43]
|
||||
Core::File::open
|
||||
Name[34:44->34:59]
|
||||
output_filename
|
||||
Name[34:61->34:86]
|
||||
Core::OpenMode::WriteOnly
|
||||
IfStatement[35:8->39:8]
|
||||
Predicate:
|
||||
FunctionCall[35:12->35:34]
|
||||
MemberExpression[35:12->35:32]
|
||||
Name[35:12->35:23]
|
||||
open_result
|
||||
Identifier[35:24->35:31]
|
||||
is_error
|
||||
Then:
|
||||
BlockStatement[35:36->39:8]
|
||||
FunctionCall[36:12->36:80]
|
||||
Name[36:12->36:17]
|
||||
outln
|
||||
Name[36:18->36:24]
|
||||
stderr
|
||||
StringLiteral[36:26->36:57]
|
||||
"Failed to open output file: {}"
|
||||
FunctionCall[36:60->36:79]
|
||||
MemberExpression[36:60->36:77]
|
||||
Name[36:60->36:71]
|
||||
open_result
|
||||
Identifier[36:72->36:76]
|
||||
error
|
||||
ReturnStatement[37:12->37:20]
|
||||
NumericLiteral[37:19->37:19]
|
||||
1
|
||||
AssignmentExpression[39:8->39:40]
|
||||
Name[39:8->39:19]
|
||||
trace_file
|
||||
=
|
||||
FunctionCall[39:21->39:40]
|
||||
MemberExpression[39:21->39:38]
|
||||
Name[39:21->39:32]
|
||||
open_result
|
||||
Identifier[39:33->39:37]
|
||||
value
|
||||
IfStatement[42:4->47:4]
|
||||
Predicate:
|
||||
BinaryExpression[42:8->42:62]
|
||||
FunctionCall[42:8->42:60]
|
||||
Name[42:8->42:14]
|
||||
pledge
|
||||
StringLiteral[42:15->42:48]
|
||||
"stdio proc exec ptrace sigaction"
|
||||
NullPointerLiteral[42:51->42:57]
|
||||
<
|
||||
NumericLiteral[42:62->42:62]
|
||||
0
|
||||
Then:
|
||||
BlockStatement[42:65->47:4]
|
||||
FunctionCall[43:8->43:24]
|
||||
Name[43:8->43:14]
|
||||
perror
|
||||
StringLiteral[43:15->43:22]
|
||||
"pledge"
|
||||
ReturnStatement[44:8->44:16]
|
||||
NumericLiteral[44:15->44:15]
|
||||
1
|
||||
VariableDeclaration[47:4->47:14]
|
||||
Type[47:4->47:8]
|
||||
int
|
||||
status
|
||||
IfStatement[48:4->81:4]
|
||||
Predicate:
|
||||
BinaryExpression[48:8->48:18]
|
||||
Name[48:8->48:14]
|
||||
g_pid
|
||||
==
|
||||
UnaryExpression[48:17->48:18]
|
||||
-
|
||||
NumericLiteral[48:18->48:18]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[48:21->81:4]
|
||||
IfStatement[49:8->54:8]
|
||||
Predicate:
|
||||
FunctionCall[49:12->49:33]
|
||||
MemberExpression[49:12->49:31]
|
||||
Name[49:12->49:22]
|
||||
child_argv
|
||||
Identifier[49:23->49:30]
|
||||
is_empty
|
||||
Then:
|
||||
BlockStatement[49:35->54:8]
|
||||
FunctionCall[50:12->50:78]
|
||||
Name[50:12->50:17]
|
||||
outln
|
||||
Name[50:18->50:24]
|
||||
stderr
|
||||
StringLiteral[50:26->50:76]
|
||||
"strace: Expected either a pid or some arguments\n"
|
||||
ReturnStatement[51:12->51:20]
|
||||
NumericLiteral[51:19->51:19]
|
||||
1
|
||||
FunctionCall[54:8->54:34]
|
||||
MemberExpression[54:8->54:25]
|
||||
Name[54:8->54:18]
|
||||
child_argv
|
||||
Identifier[54:19->54:24]
|
||||
append
|
||||
NullPointerLiteral[54:26->54:32]
|
||||
VariableDeclaration[55:8->55:24]
|
||||
Type[55:8->55:12]
|
||||
int
|
||||
pid
|
||||
FunctionCall[55:18->55:24]
|
||||
Name[55:18->55:22]
|
||||
fork
|
||||
IfStatement[56:8->61:8]
|
||||
Predicate:
|
||||
BinaryExpression[56:12->56:18]
|
||||
Name[56:12->56:16]
|
||||
pid
|
||||
<
|
||||
NumericLiteral[56:18->56:18]
|
||||
0
|
||||
Then:
|
||||
BlockStatement[56:21->61:8]
|
||||
FunctionCall[57:12->57:26]
|
||||
Name[57:12->57:18]
|
||||
perror
|
||||
StringLiteral[57:19->57:24]
|
||||
"fork"
|
||||
ReturnStatement[58:12->58:20]
|
||||
NumericLiteral[58:19->58:19]
|
||||
1
|
||||
IfStatement[61:8->74:8]
|
||||
Predicate:
|
||||
UnaryExpression[61:12->61:16]
|
||||
!
|
||||
Name[61:13->61:16]
|
||||
pid
|
||||
Then:
|
||||
BlockStatement[61:18->74:8]
|
||||
IfStatement[62:12->66:12]
|
||||
Predicate:
|
||||
BinaryExpression[62:16->62:49]
|
||||
FunctionCall[62:16->62:45]
|
||||
Name[62:16->62:22]
|
||||
ptrace
|
||||
Name[62:23->62:34]
|
||||
PT_TRACE_ME
|
||||
NumericLiteral[62:36->62:36]
|
||||
0
|
||||
NumericLiteral[62:39->62:39]
|
||||
0
|
||||
NumericLiteral[62:42->62:42]
|
||||
0
|
||||
==
|
||||
UnaryExpression[62:48->62:49]
|
||||
-
|
||||
NumericLiteral[62:49->62:49]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[62:52->66:12]
|
||||
FunctionCall[63:16->63:33]
|
||||
Name[63:16->63:22]
|
||||
perror
|
||||
StringLiteral[63:23->63:31]
|
||||
"traceme"
|
||||
ReturnStatement[64:16->64:24]
|
||||
NumericLiteral[64:23->64:23]
|
||||
1
|
||||
VariableDeclaration[66:12->66:86]
|
||||
Type[66:12->66:16]
|
||||
int
|
||||
rc
|
||||
FunctionCall[66:21->66:86]
|
||||
Name[66:21->66:27]
|
||||
execvp
|
||||
FunctionCall[66:28->66:46]
|
||||
MemberExpression[66:28->66:44]
|
||||
Name[66:28->66:38]
|
||||
child_argv
|
||||
Identifier[66:39->66:43]
|
||||
first
|
||||
CppCastExpression[66:48->66:85]
|
||||
const_cast
|
||||
<
|
||||
Pointer[66:64->66:65]
|
||||
Pointer[66:63->66:64]
|
||||
Type[66:59->66:63]
|
||||
char
|
||||
>
|
||||
FunctionCall[66:67->66:84]
|
||||
MemberExpression[66:67->66:82]
|
||||
Name[66:67->66:77]
|
||||
child_argv
|
||||
Identifier[66:78->66:81]
|
||||
data
|
||||
IfStatement[67:12->71:12]
|
||||
Predicate:
|
||||
BinaryExpression[67:16->67:21]
|
||||
Name[67:16->67:19]
|
||||
rc
|
||||
<
|
||||
NumericLiteral[67:21->67:21]
|
||||
0
|
||||
Then:
|
||||
BlockStatement[67:24->71:12]
|
||||
FunctionCall[68:16->68:32]
|
||||
Name[68:16->68:22]
|
||||
perror
|
||||
StringLiteral[68:23->68:30]
|
||||
"execvp"
|
||||
FunctionCall[69:16->69:23]
|
||||
Name[69:16->69:20]
|
||||
exit
|
||||
NumericLiteral[69:21->69:21]
|
||||
1
|
||||
FunctionCall[71:12->71:32]
|
||||
Name[71:12->71:30]
|
||||
VERIFY_NOT_REACHED
|
||||
AssignmentExpression[74:8->74:19]
|
||||
Name[74:8->74:14]
|
||||
g_pid
|
||||
=
|
||||
Name[74:16->74:19]
|
||||
pid
|
||||
IfStatement[75:8->79:4]
|
||||
Predicate:
|
||||
BinaryExpression[75:12->75:83]
|
||||
FunctionCall[75:12->75:54]
|
||||
Name[75:12->75:19]
|
||||
waitpid
|
||||
Name[75:20->75:23]
|
||||
pid
|
||||
UnaryExpression[75:25->75:32]
|
||||
&
|
||||
Name[75:26->75:32]
|
||||
status
|
||||
BinaryExpression[75:34->75:52]
|
||||
Name[75:34->75:43]
|
||||
WSTOPPED
|
||||
|
|
||||
Name[75:45->75:52]
|
||||
WEXITED
|
||||
!=
|
||||
BinaryExpression[75:57->75:83]
|
||||
Name[75:57->75:61]
|
||||
pid
|
||||
||
|
||||
UnaryExpression[75:64->75:83]
|
||||
!
|
||||
FunctionCall[75:65->75:83]
|
||||
Name[75:65->75:75]
|
||||
WIFSTOPPED
|
||||
Name[75:76->75:82]
|
||||
status
|
||||
Then:
|
||||
BlockStatement[75:85->79:4]
|
||||
FunctionCall[76:12->76:29]
|
||||
Name[76:12->76:18]
|
||||
perror
|
||||
StringLiteral[76:19->76:27]
|
||||
"waitpid"
|
||||
ReturnStatement[77:12->77:20]
|
||||
NumericLiteral[77:19->77:19]
|
||||
1
|
||||
VariableDeclaration[81:4->81:23]
|
||||
Type[81:4->81:21]
|
||||
sigaction
|
||||
sa
|
||||
FunctionCall[82:4->82:44]
|
||||
Name[82:4->82:10]
|
||||
memset
|
||||
UnaryExpression[82:11->82:14]
|
||||
&
|
||||
Name[82:12->82:14]
|
||||
sa
|
||||
NumericLiteral[82:16->82:16]
|
||||
0
|
||||
SizeofExpression[82:19->82:43]
|
||||
Type[82:26->82:42]
|
||||
sigaction
|
||||
AssignmentExpression[83:4->83:33]
|
||||
MemberExpression[83:4->83:18]
|
||||
Name[83:4->83:6]
|
||||
sa
|
||||
Identifier[83:7->83:16]
|
||||
sa_handler
|
||||
=
|
||||
Name[83:20->83:33]
|
||||
handle_sigint
|
||||
FunctionCall[84:4->84:35]
|
||||
Name[84:4->84:13]
|
||||
sigaction
|
||||
Name[84:14->84:20]
|
||||
SIGINT
|
||||
UnaryExpression[84:22->84:25]
|
||||
&
|
||||
Name[84:23->84:25]
|
||||
sa
|
||||
NullPointerLiteral[84:27->84:33]
|
||||
IfStatement[86:4->90:4]
|
||||
Predicate:
|
||||
BinaryExpression[86:8->86:43]
|
||||
FunctionCall[86:8->86:39]
|
||||
Name[86:8->86:14]
|
||||
ptrace
|
||||
Name[86:15->86:24]
|
||||
PT_ATTACH
|
||||
Name[86:26->86:31]
|
||||
g_pid
|
||||
NumericLiteral[86:33->86:33]
|
||||
0
|
||||
NumericLiteral[86:36->86:36]
|
||||
0
|
||||
==
|
||||
UnaryExpression[86:42->86:43]
|
||||
-
|
||||
NumericLiteral[86:43->86:43]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[86:46->90:4]
|
||||
FunctionCall[87:8->87:24]
|
||||
Name[87:8->87:14]
|
||||
perror
|
||||
StringLiteral[87:15->87:22]
|
||||
"attach"
|
||||
ReturnStatement[88:8->88:16]
|
||||
NumericLiteral[88:15->88:15]
|
||||
1
|
||||
IfStatement[90:4->95:4]
|
||||
Predicate:
|
||||
BinaryExpression[90:8->90:83]
|
||||
FunctionCall[90:8->90:52]
|
||||
Name[90:8->90:15]
|
||||
waitpid
|
||||
Name[90:16->90:21]
|
||||
g_pid
|
||||
UnaryExpression[90:23->90:30]
|
||||
&
|
||||
Name[90:24->90:30]
|
||||
status
|
||||
BinaryExpression[90:32->90:50]
|
||||
Name[90:32->90:41]
|
||||
WSTOPPED
|
||||
|
|
||||
Name[90:43->90:50]
|
||||
WEXITED
|
||||
!=
|
||||
BinaryExpression[90:55->90:83]
|
||||
Name[90:55->90:61]
|
||||
g_pid
|
||||
||
|
||||
UnaryExpression[90:64->90:83]
|
||||
!
|
||||
FunctionCall[90:65->90:83]
|
||||
Name[90:65->90:75]
|
||||
WIFSTOPPED
|
||||
Name[90:76->90:82]
|
||||
status
|
||||
Then:
|
||||
BlockStatement[90:85->95:4]
|
||||
FunctionCall[91:8->91:25]
|
||||
Name[91:8->91:14]
|
||||
perror
|
||||
StringLiteral[91:15->91:23]
|
||||
"waitpid"
|
||||
ReturnStatement[92:8->92:16]
|
||||
NumericLiteral[92:15->92:15]
|
||||
1
|
||||
ForStatement[95:4->143:4]
|
||||
BlockStatement[95:13->143:4]
|
||||
IfStatement[96:8->100:8]
|
||||
Predicate:
|
||||
BinaryExpression[96:12->96:48]
|
||||
FunctionCall[96:12->96:44]
|
||||
Name[96:12->96:18]
|
||||
ptrace
|
||||
Name[96:19->96:29]
|
||||
PT_SYSCALL
|
||||
Name[96:31->96:36]
|
||||
g_pid
|
||||
NumericLiteral[96:38->96:38]
|
||||
0
|
||||
NumericLiteral[96:41->96:41]
|
||||
0
|
||||
==
|
||||
UnaryExpression[96:47->96:48]
|
||||
-
|
||||
NumericLiteral[96:48->96:48]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[96:51->100:8]
|
||||
FunctionCall[97:12->97:29]
|
||||
Name[97:12->97:18]
|
||||
perror
|
||||
StringLiteral[97:19->97:27]
|
||||
"syscall"
|
||||
ReturnStatement[98:12->98:20]
|
||||
NumericLiteral[98:19->98:19]
|
||||
1
|
||||
IfStatement[100:8->104:8]
|
||||
Predicate:
|
||||
BinaryExpression[100:12->100:87]
|
||||
FunctionCall[100:12->100:56]
|
||||
Name[100:12->100:19]
|
||||
waitpid
|
||||
Name[100:20->100:25]
|
||||
g_pid
|
||||
UnaryExpression[100:27->100:34]
|
||||
&
|
||||
Name[100:28->100:34]
|
||||
status
|
||||
BinaryExpression[100:36->100:54]
|
||||
Name[100:36->100:45]
|
||||
WSTOPPED
|
||||
|
|
||||
Name[100:47->100:54]
|
||||
WEXITED
|
||||
!=
|
||||
BinaryExpression[100:59->100:87]
|
||||
Name[100:59->100:65]
|
||||
g_pid
|
||||
||
|
||||
UnaryExpression[100:68->100:87]
|
||||
!
|
||||
FunctionCall[100:69->100:87]
|
||||
Name[100:69->100:79]
|
||||
WIFSTOPPED
|
||||
Name[100:80->100:86]
|
||||
status
|
||||
Then:
|
||||
BlockStatement[100:89->104:8]
|
||||
FunctionCall[101:12->101:30]
|
||||
Name[101:12->101:18]
|
||||
perror
|
||||
StringLiteral[101:19->101:28]
|
||||
"wait_pid"
|
||||
ReturnStatement[102:12->102:20]
|
||||
NumericLiteral[102:19->102:19]
|
||||
1
|
||||
VariableDeclaration[104:8->104:33]
|
||||
Type[104:8->104:24]
|
||||
PtraceRegisters
|
||||
regs
|
||||
BracedInitList[104:31->104:33]
|
||||
IfStatement[105:8->109:8]
|
||||
Predicate:
|
||||
BinaryExpression[105:12->105:52]
|
||||
FunctionCall[105:12->105:48]
|
||||
Name[105:12->105:18]
|
||||
ptrace
|
||||
Name[105:19->105:29]
|
||||
PT_GETREGS
|
||||
Name[105:31->105:36]
|
||||
g_pid
|
||||
UnaryExpression[105:38->105:43]
|
||||
&
|
||||
Name[105:39->105:43]
|
||||
regs
|
||||
NumericLiteral[105:45->105:45]
|
||||
0
|
||||
==
|
||||
UnaryExpression[105:51->105:52]
|
||||
-
|
||||
NumericLiteral[105:52->105:52]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[105:55->109:8]
|
||||
FunctionCall[106:12->106:29]
|
||||
Name[106:12->106:18]
|
||||
perror
|
||||
StringLiteral[106:19->106:27]
|
||||
"getregs"
|
||||
ReturnStatement[107:12->107:20]
|
||||
NumericLiteral[107:19->107:19]
|
||||
1
|
||||
VariableDeclaration[109:8->109:36]
|
||||
Type[109:8->109:12]
|
||||
u32
|
||||
syscall_index
|
||||
MemberExpression[109:28->109:36]
|
||||
Name[109:28->109:32]
|
||||
regs
|
||||
Identifier[109:33->109:35]
|
||||
eax
|
||||
VariableDeclaration[110:8->110:27]
|
||||
Type[110:8->110:12]
|
||||
u32
|
||||
arg1
|
||||
MemberExpression[110:19->110:27]
|
||||
Name[110:19->110:23]
|
||||
regs
|
||||
Identifier[110:24->110:26]
|
||||
edx
|
||||
VariableDeclaration[111:8->111:27]
|
||||
Type[111:8->111:12]
|
||||
u32
|
||||
arg2
|
||||
MemberExpression[111:19->111:27]
|
||||
Name[111:19->111:23]
|
||||
regs
|
||||
Identifier[111:24->111:26]
|
||||
ecx
|
||||
VariableDeclaration[112:8->112:27]
|
||||
Type[112:8->112:12]
|
||||
u32
|
||||
arg3
|
||||
MemberExpression[112:19->112:27]
|
||||
Name[112:19->112:23]
|
||||
regs
|
||||
Identifier[112:24->112:26]
|
||||
ebx
|
||||
IfStatement[114:8->118:8]
|
||||
Predicate:
|
||||
BinaryExpression[114:12->114:48]
|
||||
FunctionCall[114:12->114:44]
|
||||
Name[114:12->114:18]
|
||||
ptrace
|
||||
Name[114:19->114:29]
|
||||
PT_SYSCALL
|
||||
Name[114:31->114:36]
|
||||
g_pid
|
||||
NumericLiteral[114:38->114:38]
|
||||
0
|
||||
NumericLiteral[114:41->114:41]
|
||||
0
|
||||
==
|
||||
UnaryExpression[114:47->114:48]
|
||||
-
|
||||
NumericLiteral[114:48->114:48]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[114:51->118:8]
|
||||
FunctionCall[115:12->115:29]
|
||||
Name[115:12->115:18]
|
||||
perror
|
||||
StringLiteral[115:19->115:27]
|
||||
"syscall"
|
||||
ReturnStatement[116:12->116:20]
|
||||
NumericLiteral[116:19->116:19]
|
||||
1
|
||||
IfStatement[118:8->123:8]
|
||||
Predicate:
|
||||
BinaryExpression[118:12->118:87]
|
||||
FunctionCall[118:12->118:56]
|
||||
Name[118:12->118:19]
|
||||
waitpid
|
||||
Name[118:20->118:25]
|
||||
g_pid
|
||||
UnaryExpression[118:27->118:34]
|
||||
&
|
||||
Name[118:28->118:34]
|
||||
status
|
||||
BinaryExpression[118:36->118:54]
|
||||
Name[118:36->118:45]
|
||||
WSTOPPED
|
||||
|
|
||||
Name[118:47->118:54]
|
||||
WEXITED
|
||||
!=
|
||||
BinaryExpression[118:59->118:87]
|
||||
Name[118:59->118:65]
|
||||
g_pid
|
||||
||
|
||||
UnaryExpression[118:68->118:87]
|
||||
!
|
||||
FunctionCall[118:69->118:87]
|
||||
Name[118:69->118:79]
|
||||
WIFSTOPPED
|
||||
Name[118:80->118:86]
|
||||
status
|
||||
Then:
|
||||
BlockStatement[118:89->123:8]
|
||||
FunctionCall[119:12->119:30]
|
||||
Name[119:12->119:18]
|
||||
perror
|
||||
StringLiteral[119:19->119:28]
|
||||
"wait_pid"
|
||||
ReturnStatement[120:12->120:20]
|
||||
NumericLiteral[120:19->120:19]
|
||||
1
|
||||
IfStatement[123:8->128:8]
|
||||
Predicate:
|
||||
BinaryExpression[123:12->123:52]
|
||||
FunctionCall[123:12->123:48]
|
||||
Name[123:12->123:18]
|
||||
ptrace
|
||||
Name[123:19->123:29]
|
||||
PT_GETREGS
|
||||
Name[123:31->123:36]
|
||||
g_pid
|
||||
UnaryExpression[123:38->123:43]
|
||||
&
|
||||
Name[123:39->123:43]
|
||||
regs
|
||||
NumericLiteral[123:45->123:45]
|
||||
0
|
||||
==
|
||||
UnaryExpression[123:51->123:52]
|
||||
-
|
||||
NumericLiteral[123:52->123:52]
|
||||
1
|
||||
Then:
|
||||
BlockStatement[123:55->128:8]
|
||||
FunctionCall[124:12->124:29]
|
||||
Name[124:12->124:18]
|
||||
perror
|
||||
StringLiteral[124:19->124:27]
|
||||
"getregs"
|
||||
ReturnStatement[125:12->125:20]
|
||||
NumericLiteral[125:19->125:19]
|
||||
1
|
||||
VariableDeclaration[128:8->128:26]
|
||||
Type[128:8->128:12]
|
||||
u32
|
||||
res
|
||||
MemberExpression[128:18->128:26]
|
||||
Name[128:18->128:22]
|
||||
regs
|
||||
Identifier[128:23->128:25]
|
||||
eax
|
||||
VariableDeclaration[130:8->135:16]
|
||||
Type[130:8->130:13]
|
||||
auto
|
||||
string
|
||||
FunctionCall[130:22->135:16]
|
||||
Name[130:22->130:39]
|
||||
String::formatted
|
||||
StringLiteral[130:40->130:77]
|
||||
"{}({:#08x}, {:#08x}, {:#08x})\t={}\n"
|
||||
FunctionCall[131:12->131:64]
|
||||
Name[131:12->131:30]
|
||||
Syscall::to_string
|
||||
CStyleCastExpression[131:31->131:63]
|
||||
Type[131:32->131:49]
|
||||
Syscall::Function
|
||||
Name[131:50->131:63]
|
||||
syscall_index
|
||||
Name[132:12->132:16]
|
||||
arg1
|
||||
Name[133:12->133:16]
|
||||
arg2
|
||||
Name[134:12->134:16]
|
||||
arg3
|
||||
Name[135:12->135:15]
|
||||
res
|
||||
IfStatement[137:8->141:4]
|
||||
Predicate:
|
||||
UnaryExpression[137:12->137:38]
|
||||
!
|
||||
BinaryExpression[137:13->137:38]
|
||||
Name[137:13->137:23]
|
||||
trace_file
|
||||
->
|
||||
FunctionCall[137:25->137:38]
|
||||
Name[137:25->137:30]
|
||||
write
|
||||
Name[137:31->137:37]
|
||||
string
|
||||
Then:
|
||||
BlockStatement[137:40->141:4]
|
||||
FunctionCall[138:12->138:59]
|
||||
Name[138:12->138:18]
|
||||
warnln
|
||||
StringLiteral[138:19->138:29]
|
||||
"write: {}"
|
||||
BinaryExpression[138:32->138:58]
|
||||
Name[138:32->138:42]
|
||||
trace_file
|
||||
->
|
||||
FunctionCall[138:44->138:58]
|
||||
Name[138:44->138:56]
|
||||
error_string
|
||||
ReturnStatement[139:12->139:20]
|
||||
NumericLiteral[139:19->139:19]
|
||||
1
|
||||
ReturnStatement[143:4->143:12]
|
||||
NumericLiteral[143:11->143:11]
|
||||
0
|
||||
}
|
145
Userland/Libraries/LibCpp/Tests/strace.cpp
Normal file
145
Userland/Libraries/LibCpp/Tests/strace.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
static int g_pid = -1;
|
||||
|
||||
static void handle_sigint(int)
|
||||
{
|
||||
if (g_pid == -1)
|
||||
return;
|
||||
|
||||
if (ptrace(PT_DETACH, g_pid, 0, 0) == -1) {
|
||||
perror("detach");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (pledge("stdio wpath cpath proc exec ptrace sigaction", nullptr) < 0) {
|
||||
perror("pledge");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vector<const char*> child_argv;
|
||||
|
||||
const char* output_filename = nullptr;
|
||||
auto trace_file = Core::File::standard_error();
|
||||
|
||||
Core::ArgsParser parser;
|
||||
parser.set_general_help(
|
||||
"Trace all syscalls and their result.");
|
||||
parser.add_option(g_pid, "Trace the given PID", "pid", 'p', "pid");
|
||||
parser.add_option(output_filename, "Filename to write output to", "output", 'o', "output");
|
||||
parser.add_positional_argument(child_argv, "Arguments to exec", "argument", Core::ArgsParser::Required::No);
|
||||
|
||||
parser.parse(argc, argv);
|
||||
|
||||
if (output_filename != nullptr) {
|
||||
auto open_result = Core::File::open(output_filename, Core::OpenMode::WriteOnly);
|
||||
if (open_result.is_error()) {
|
||||
outln(stderr, "Failed to open output file: {}", open_result.error());
|
||||
return 1;
|
||||
}
|
||||
trace_file = open_result.value();
|
||||
}
|
||||
|
||||
if (pledge("stdio proc exec ptrace sigaction", nullptr) < 0) {
|
||||
perror("pledge");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int status;
|
||||
if (g_pid == -1) {
|
||||
if (child_argv.is_empty()) {
|
||||
outln(stderr, "strace: Expected either a pid or some arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
child_argv.append(nullptr);
|
||||
int pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pid) {
|
||||
if (ptrace(PT_TRACE_ME, 0, 0, 0) == -1) {
|
||||
perror("traceme");
|
||||
return 1;
|
||||
}
|
||||
int rc = execvp(child_argv.first(), const_cast<char**>(child_argv.data()));
|
||||
if (rc < 0) {
|
||||
perror("execvp");
|
||||
exit(1);
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
g_pid = pid;
|
||||
if (waitpid(pid, &status, WSTOPPED | WEXITED) != pid || !WIFSTOPPED(status)) {
|
||||
perror("waitpid");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sa.sa_handler = handle_sigint;
|
||||
sigaction(SIGINT, &sa, nullptr);
|
||||
|
||||
if (ptrace(PT_ATTACH, g_pid, 0, 0) == -1) {
|
||||
perror("attach");
|
||||
return 1;
|
||||
}
|
||||
if (waitpid(g_pid, &status, WSTOPPED | WEXITED) != g_pid || !WIFSTOPPED(status)) {
|
||||
perror("waitpid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (ptrace(PT_SYSCALL, g_pid, 0, 0) == -1) {
|
||||
perror("syscall");
|
||||
return 1;
|
||||
}
|
||||
if (waitpid(g_pid, &status, WSTOPPED | WEXITED) != g_pid || !WIFSTOPPED(status)) {
|
||||
perror("wait_pid");
|
||||
return 1;
|
||||
}
|
||||
PtraceRegisters regs = {};
|
||||
if (ptrace(PT_GETREGS, g_pid, ®s, 0) == -1) {
|
||||
perror("getregs");
|
||||
return 1;
|
||||
}
|
||||
u32 syscall_index = regs.eax;
|
||||
u32 arg1 = regs.edx;
|
||||
u32 arg2 = regs.ecx;
|
||||
u32 arg3 = regs.ebx;
|
||||
|
||||
if (ptrace(PT_SYSCALL, g_pid, 0, 0) == -1) {
|
||||
perror("syscall");
|
||||
return 1;
|
||||
}
|
||||
if (waitpid(g_pid, &status, WSTOPPED | WEXITED) != g_pid || !WIFSTOPPED(status)) {
|
||||
perror("wait_pid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ptrace(PT_GETREGS, g_pid, ®s, 0) == -1) {
|
||||
perror("getregs");
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 res = regs.eax;
|
||||
|
||||
auto string = String::formatted("{}({:#08x}, {:#08x}, {:#08x})\t={}\n",
|
||||
Syscall::to_string((Syscall::Function)syscall_index),
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
res);
|
||||
|
||||
if (!trace_file->write(string)) {
|
||||
warnln("write: {}", trace_file->error_string());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
41
Userland/Libraries/LibCpp/Tests/struct.ast
Normal file
41
Userland/Libraries/LibCpp/Tests/struct.ast
Normal file
|
@ -0,0 +1,41 @@
|
|||
TranslationUnit[1:0->12:0]
|
||||
StructOrClassDeclaration[1:0->7:0]
|
||||
MyStruct
|
||||
MemberDeclaration[3:4->4:4]
|
||||
Type[3:4->3:8]
|
||||
int
|
||||
x
|
||||
MemberDeclaration[4:4->5:0]
|
||||
Pointer[4:12->4:14]
|
||||
Type[4:4->4:12]
|
||||
s
|
||||
next
|
||||
FunctionDeclaration[7:0->12:0]
|
||||
Type[7:0->7:4]
|
||||
int
|
||||
foo
|
||||
(
|
||||
)
|
||||
FunctionDefinition[8:0->12:0]
|
||||
{
|
||||
VariableDeclaration[9:4->9:14]
|
||||
Type[9:4->9:13]
|
||||
MyStruct
|
||||
s
|
||||
FunctionCall[10:4->10:23]
|
||||
Name[10:4->10:10]
|
||||
printf
|
||||
StringLiteral[10:11->10:16]
|
||||
"%d\n"
|
||||
MemberExpression[10:19->10:22]
|
||||
Name[10:19->10:20]
|
||||
s
|
||||
Identifier[10:21->10:21]
|
||||
x
|
||||
ReturnStatement[11:4->11:14]
|
||||
MemberExpression[11:11->11:14]
|
||||
Name[11:11->11:12]
|
||||
s
|
||||
Identifier[11:13->11:13]
|
||||
x
|
||||
}
|
13
Userland/Libraries/LibCpp/Tests/struct.cpp
Normal file
13
Userland/Libraries/LibCpp/Tests/struct.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
struct MyStruct
|
||||
{
|
||||
int x;
|
||||
struct s* next;
|
||||
};
|
||||
|
||||
int foo()
|
||||
{
|
||||
MyStruct s;
|
||||
printf("%d\n", s.x);
|
||||
return s.x;
|
||||
}
|
Loading…
Reference in a new issue