Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler V3 #39

Merged
merged 53 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
f04018a
feat: added compiler utils header
Dec 19, 2024
8228e15
feat: added write8, write16 and write32 into compiler utils header
Dec 19, 2024
09f6fb2
chore: added clean target
Dec 19, 2024
19fa7f2
feat: added docs for previously added functions
Zffu Dec 19, 2024
5c6553b
feat: added writestr8 and writestr16 functions in header
Zffu Dec 19, 2024
b117b32
feat: added seek in header
Zffu Dec 19, 2024
a659532
feat: added align_to in header
Zffu Dec 19, 2024
0a991ed
feat: added implementations of compiler utils
Zffu Dec 19, 2024
a2ebf86
fix: added missing includes
Zffu Dec 19, 2024
d80c897
fix: misc impl errors
Zffu Dec 19, 2024
0e0f010
feat: started working on compiler win header
Zffu Dec 19, 2024
b1bbe29
feat: added win compiling constants
Zffu Dec 19, 2024
56e1f10
feat: added writWinExecutableHeader, writeWinPESignature, writeWinCof…
Zffu Dec 19, 2024
9187c95
feat: started working on the win writing functions implementations (w…
Zffu Dec 19, 2024
3939f06
fix: fixed header constants names
Zffu Dec 19, 2024
aef6ef9
feat: added writeWinExecutable in header
Zffu Dec 19, 2024
537d402
feat: added two implementations of win comp header
Zffu Dec 19, 2024
914f9d6
refactor: changed functions to pass calculated vars
Zffu Dec 19, 2024
2834230
feat: writeCoffHeader impl
Zffu Dec 19, 2024
0dad446
feat: added writeWinSTDFields
Zffu Dec 19, 2024
edfed2a
feat: added win specific fields
Zffu Dec 19, 2024
290f135
feat: added windows data fields
Zffu Dec 19, 2024
a3b33d7
feat: added section headers
Zffu Dec 19, 2024
8a995c5
tables
Zffu Dec 19, 2024
b5d4d0c
feat: added win .idata tables sizes
Zffu Dec 20, 2024
959d83d
feat: added import table for win
Zffu Dec 20, 2024
b04bf02
feat: added win hint table
Zffu Dec 20, 2024
d44e242
feat: started working on passing imports size and imports in paramete…
Zffu Dec 20, 2024
da0ee1f
feat: made num_imports change behaviors
Zffu Dec 20, 2024
62fbc62
fix: typo at WIN_NAME_TABLE_ENTRY_SZ
Zffu Dec 20, 2024
43b93a4
feat: made hint table dependant on num_imports and imports
Zffu Dec 20, 2024
6e3337a
bump
Zffu Dec 20, 2024
9efdb12
feat: added size for dos program and program in params
Zffu Dec 21, 2024
e07d3e7
chore: removed old not working windows pe format
Zffu Dec 22, 2024
720c21c
feat: added compiler PE format datatypes
Zffu Dec 22, 2024
0d108a5
refactor: moved datatypes into def
Zffu Dec 22, 2024
7b4a80a
fix: fixed WORD and added PE_DOS_HEADER
Zffu Dec 22, 2024
07c367e
feat: added PE_HEADER_SIGNATURE
Zffu Dec 22, 2024
a263300
refactor: started moving pe format around
Zffu Dec 22, 2024
0883149
feat: added units in header file
Zffu Dec 22, 2024
5c07010
refactor: finished moving pe format around
Zffu Dec 22, 2024
acfad1f
fix: struct def
Zffu Dec 22, 2024
f35c273
feat: added PE_HEADER
Zffu Dec 22, 2024
aba326a
feat: added PE_SECTION_HEADER
Zffu Dec 22, 2024
ad8c1fb
fix: types
Zffu Dec 22, 2024
4de307e
feat: added new structs
Zffu Dec 22, 2024
445a236
feat: added potentially working PE compiling
Zffu Dec 22, 2024
c9f1567
feat: it works WWW
Zffu Dec 22, 2024
e26945c
feat: made .text section the same size as the program instead of 0x200
Zffu Dec 22, 2024
2e4d9c7
feat: added function invoke parsing
Zffu Dec 22, 2024
c06611b
fix: lexer fixes
Zffu Dec 23, 2024
fb81854
fix: final fixes
Zffu Dec 23, 2024
f99bc8a
fix: final fixes
Zffu Dec 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,13 @@ prepare_build:
@echo [INFO] Using "${COMPILER}" as a compiler!
@echo [INFO] Detected current operating system as ${DETECTED_OS}
$(CHECK_COMMANDS)
@echo [INFO] Clearing old builds
@echo [INFO] Starting building logic

clean:
$(RM) build
$(RM) $(TARGET)
$(RM) $(TEST_TARGET)
$(RM) $(BENCH_TARGET)
Comment on lines +87 to 91
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add .PHONY declaration for the clean target

The clean target should be declared as .PHONY to ensure it runs even if a file named 'clean' exists in the directory. This is a common Makefile best practice.

Add this line at the beginning of the Makefile:

+.PHONY: clean

Committable suggestion skipped: line range outside the PR's diff.

@echo [INFO] Starting building logic

$(TARGET):
$(COMPILER) $(FLAGS) $(SOURCES) src/cli/main.c -o $(TARGET)
Expand Down
18 changes: 6 additions & 12 deletions benchmarks/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void main(int argc, char* argv[]) {
endTimer(i, 0);
startTimer();

struct LexerResult result = runLexer(buff);
struct LexerResult result = runLexer(buff, size);

free(buff);

Expand All @@ -136,20 +136,14 @@ void main(int argc, char* argv[]) {
endTimer(i, 2);
startTimer();

struct Context ctx = parseContext(node);
char* compiled = compileV2(ctx);
fptr = fopen("output.txt", "w");

endTimer(i, 3);

startTimer();

fptr = fopen("output.txt", "w");
fprintf(fptr, compiled);
fclose(fptr);
IR_CTX* ctx = makeContext(node);
compile(ctx, fptr);

endTimer(i, 4);
fclose(fptr);

free(compiled);
endTimer(i, 3);
Comment on lines +139 to +146
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Add error handling for IR context creation and file operations
The codebase shows inconsistent error handling patterns. While src/cli/main.c properly checks for both file operations (fopen) and IR context creation (makeContext), the benchmark code lacks these safety checks. Add the following error handling:

  • Check if fopen returns NULL for the output file
  • Verify if makeContext returns NULL, as seen in tests/ir.c and src/cli/main.c
🔗 Analysis chain

Consolidate compilation steps
Opening the file, creating the IR context, compiling, and closing the file are well-structured. Double-check error handling (e.g., verify IR_CTX != NULL) for production readiness.


Let me gather information about error handling in the codebase, particularly around IR_CTX creation and file operations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Check IR_CTX creation and error handling patterns
ast-grep --pattern 'makeContext($_)'

# Look for error handling patterns around fopen
rg "fopen.*\(" -A 3

# Check IR_CTX struct definition and related error handling
rg "IR_CTX" -A 3

Length of output: 2457

}

printf("========= Benchmarking Results =========\n");
Expand Down
14 changes: 11 additions & 3 deletions src/cli/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "../lexer/lexer.h"

#include "../parser/ast.h"
#include "../parser/parser.h"

#include "../compiler/compiler.h"
#include "../compiler/pe/pe.h"
#include "../compiler/ir.h"

#include "../utils/logging.c"

// Version
#define VERSION "0.1.0"

uint8_t code_section[6] = {
0xB8, 0x4C, 0x00, 0x00, 0x00, 0xC3
};

void showCommandEntry(char* commandName, char* description, int argumentCount, char* argumentNames[], char* argumentDescriptions[]) {
printf("\n > %s\n\n %s%sDescription%s: %s\n", commandName, STYLE_BOLD, STYLE_UNDERLINE, RESET, description);
Expand Down Expand Up @@ -108,11 +113,11 @@

char* buff = malloc(size + 1); // Allocates one more byte for the \0 char.

fread(buff, 1, size, fptr);
size = fread(buff, 1, size, fptr);
buff[size] = '\0';
fclose(fptr);

struct LexerResult result = runLexer(buff);
struct LexerResult result = runLexer(buff, size);
struct ASTNode* root = parseNodes(result, 0, AST_ROOT);

IR_CTX* ctx = makeContext(root);
Expand All @@ -122,7 +127,10 @@
return -1;
}

compile(ctx, outputFile);
fptr = fopen(outputFile, "w");

Check notice on line 130 in src/cli/main.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/cli/main.c#L130

Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362).

Check warning on line 130 in src/cli/main.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/cli/main.c#L130

Usage of the `open` family of functions may hint at a potential Time Of Check Time Of Use (TOCTOU) vulnerability.
compile(ctx, fptr);

//compilePE(fptr, code_section, sizeof(code_section));

break;
case 'v':
Expand Down
68 changes: 60 additions & 8 deletions src/compiler/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* The compiler of Quickfall.
*/

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

Expand All @@ -13,6 +14,8 @@
#include "../utils/hash.h"
#include "../utils/hashmap.h"

#include "./pe/pe.h"

/**
* Parses the AST tree into a context.
* @param tree the AST tree.
Expand All @@ -26,9 +29,7 @@ IR_CTX* makeContext(AST_NODE* tree) {
ctx->nodeIndex = 0;
ctx->nodeMap = createHashmap(512,200);

while(tree->next != NULL) {
tree = tree->next;

while(tree != NULL) {
switch(tree->type) {
case AST_VARIABLE_DECLARATION:

Expand Down Expand Up @@ -59,10 +60,10 @@ IR_CTX* makeContext(AST_NODE* tree) {

case AST_FUNCTION_DECLARATION:

hash = hashstr(tree->left->value);
hash = hashstr(tree->left->right->value);

if(hashGet(ctx->nodeMap, hash) != NULL) {
printf("Function %s was already declared!\n", tree->left->value);
printf("Function %s was already declared!\n", tree->left->right->value);
return NULL;
}

Expand All @@ -77,18 +78,20 @@ IR_CTX* makeContext(AST_NODE* tree) {
node->variables[node->variableIndex] = var;
node->variableIndex++;

hashPut(node->variableMap, hashstr(tree->right->value), var);
hashPut(node->variableMap, hashstr(tree->left->left->right->value), var);

tree->left->left = tree->left->left->next;
}

node->tree = tree->right;

ctx->nodes[ctx->nodeIndex] = node;
ctx->nodeIndex++;

hashPut(ctx->nodeMap, hash, node);
break;

case AST_ASM_FUNCTION_DECLARATION:

hash = hashstr(tree->left->right->value);

if(hashGet(ctx->nodeMap, hash) != NULL) {
Expand All @@ -99,6 +102,7 @@ IR_CTX* makeContext(AST_NODE* tree) {
node = createIRNode(IR_ASM_FUNCTION, tree->left->right->value);

node->value = tree->value;
node->valueSize = tree->valueSize;

while(tree->left->left->next != NULL) {

Expand All @@ -121,6 +125,8 @@ IR_CTX* makeContext(AST_NODE* tree) {
break;

}

tree = tree->next;
}

return ctx;
Expand All @@ -131,6 +137,52 @@ IR_CTX* makeContext(AST_NODE* tree) {
* @param ctx the IR context.
* @param char the output file name.
*/
void compile(IR_CTX* ctx, char* outputFileName) {
void compile(IR_CTX* ctx, FILE* out) {

uint8_t* buff = malloc(sizeof(uint8_t) * 512);
int i = 0;

int h = hashstr("main");

if(hashGet(ctx->nodeMap, h) == NULL) {
printf("Error: the main function wasn't defined!\n");
return;
}
Comment on lines +147 to +150
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix memory leaks on early returns.

When returning at lines 149 or 157, the allocated buffer "buff" is never freed.

Apply this minimal patch to free memory before returning:

 if(hashGet(ctx->nodeMap, h) == NULL) {
   printf("Error: the main function wasn't defined!\n");
+  free(buff);
   return;
 }

 if(node->nodeType != IR_FUNCTION) {
   printf("Error: main must be a function!\n");
+  free(buff);
   return;
 }

Also applies to: 155-157

🧰 Tools
🪛 cppcheck (2.10-2)

[error] 149-149: Memory leak

(memleak)


IR_NODE* node = hashGet(ctx->nodeMap, h);

if(node->nodeType != IR_FUNCTION) {
printf("Error: main must be a function!\n");
return;
}

while(node->tree != NULL) {

if(node->tree->type == AST_FUNCTION_INVOKE) {

int hash = hashstr(node->tree->value);

IR_NODE* wa = hashGet(ctx->nodeMap, hash);

if(wa == NULL) {
printf("Error: The %s function doesn't exist!\n", node->tree->value);
return;
}

if(wa->nodeType == IR_ASM_FUNCTION) {
unsigned char b;
unsigned char* ptr = (unsigned char*) wa->value;

for(int ii = 0; ii < wa->valueSize; ++ii) {
buff[i] = ptr[ii];
++i;
}
}
}

node->tree = node->tree->next;
}

//todo: change format based on user
compilePE(out, buff, i);
Comment on lines +186 to +187
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Deallocate "buff" after compiling.

Add a free call to avoid leaking memory in the normal completion path:

 compilePE(out, buff, i);
+free(buff);
}

Committable suggestion skipped: line range outside the PR's diff.

}
4 changes: 2 additions & 2 deletions src/compiler/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ IR_CTX* makeContext(AST_NODE* tree);
/**
* Compiles the Context tree to an executable named the provided name.
* @param ctx the IR context.
* @param char the output file name.
* @param char the output file.
*/
void compile(IR_CTX* ctx, char* outputFileName);
void compile(IR_CTX* ctx, FILE* outputFileName);

#endif
6 changes: 5 additions & 1 deletion src/compiler/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ struct IRNode {
char* type;

// Variable Properties
char* value;
void* value;
int valueSize;

// Function Properties
struct IRNode** variables;
Expand All @@ -49,6 +50,9 @@ struct IRContext {
int nodeIndex;

struct Hashmap* nodeMap;

IR_NODE* mainFunc;

};

typedef struct IRContext IR_CTX;
Expand Down
110 changes: 110 additions & 0 deletions src/compiler/pe/format.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* Quickfall PE Format Defintion.
*/

#include "../units.h"

#ifndef PE_FORMAT
#define PE_FORMAT

/**
* Constants.
*/

#define PE_HEADER_SIGNATURE 0x00004550
#define PE_DOS_HDR_SZ 0x40

/**
* Structures.
*/

#pragma pack(push, 1)

typedef struct {
uint16_t e_magic;
uint16_t e_cblp;
uint16_t e_cp;
uint16_t e_crlc;
uint16_t e_cparhdr;
uint16_t e_minalloc;
uint16_t e_maxalloc;
uint16_t e_ss;
uint16_t e_sp;
uint16_t e_csum;
uint16_t e_ip;
uint16_t e_cs;
uint16_t e_lfarlc;
uint16_t e_ovno;
uint16_t e_res[4];
uint16_t e_oemid;
uint16_t e_oeminfo;
uint16_t e_res2[10];
uint32_t e_lfanew;
} PE_DOS_HEADER;

typedef struct {
uint32_t Signature;
uint16_t Machine;
uint16_t NumberOfSections;
uint32_t TimeDateStamp;
uint32_t PointerToSymbolTable;
uint32_t NumberOfSymbols;
uint16_t SizeOfOptionalHeader;
uint16_t Characteristics;
} PE_NT_HEADERS;

typedef struct {
uint16_t Magic;
uint8_t MajorLinkerVersion;
uint8_t MinorLinkerVersion;
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
uint64_t ImageBase;
uint32_t SectionAlignment;
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
uint16_t MinorImageVersion;
uint16_t MajorSubsystemVersion;
uint16_t MinorSubsystemVersion;
uint32_t Win32VersionValue;
uint32_t SizeOfImage;
uint32_t SizeOfHeaders;
uint32_t CheckSum;
uint16_t Subsystem;
uint16_t DllCharacteristics;
uint64_t SizeOfStackReserve;
uint64_t SizeOfStackCommit;
uint64_t SizeOfHeapReserve;
uint64_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
struct {
uint32_t VirtualAddress;
uint32_t Size;
} DataDirectory[16];
} PE_OPTIONAL_HEADER;

typedef struct {
uint8_t Name[8];
union {
uint32_t PhysicalAddress;
uint32_t VirtualSize;
} Misc;
uint32_t VirtualAddress;
uint32_t SizeOfRawData;
uint32_t PointerToRawData;
uint32_t PointerToRelocations;
uint32_t PointerToLinenumbers;
uint16_t NumberOfRelocations;
uint16_t NumberOfLinenumbers;
uint32_t Characteristics;
} PE_SECTION_HEADER;

#pragma pack(pop)

#endif
Loading
Loading