simple tricks to reduce memory/binary size

This commit is contained in:
IoIxD 2026-01-22 11:42:33 -07:00
commit 3028f3ee33
13 changed files with 99 additions and 109 deletions

View file

@ -1,12 +1,14 @@
SOURCES := src/main.c src/util/calloc.c src/util/string.c src/util/hash.c src/lexer/lexer.c src/builtins/builtins.c src/util/memset.c
CFLAGS := -g -Oz -nostdlib
LDFLAGS :=
UNAME := $(shell uname)
ARCH := $(shell uname -m)
ifeq ($(UNAME), Linux)
SOURCES += src/system/linux/linux.c src/system/linux/alloc.c src/system/linux/env.c src/system/linux/errno.c src/system/linux/signal.c
CFLAGS += -fno-stack-protector -Wno-incompatible-library-redeclaration
CFLAGS += -fno-stack-protector -Wno-incompatible-library-redeclaration -flto -ffunction-sections -fdata-sections -fshort-enums
LDFLAGS += -Wl,--gc-sections
CFLAGS += -DMSH_ENTRY_POINT="void _start()"
ifeq ($(ARCH),i386)
SOURCES += src/system/linux/i386.s
@ -19,7 +21,7 @@ endif
endif
all: $(SOURCES)
$(CC) $(SOURCES) $(CFLAGS) -o msh
$(CC) $(LDFLAGS) $(SOURCES) $(CFLAGS) -o msh
clean:
rm -f *.o msh

View file

@ -2,7 +2,7 @@
#include "../system/system.h"
#include "../util/util.h"
int hashes_calced = 0;
char hashes_calced = 0;
int cd_hash = 0;
int exit_hash = 0;

View file

@ -2,30 +2,25 @@
#include "../builtins/builtins.h"
#include "../system/system.h"
#include <linux/limits.h>
struct msh_lexer_t {
msh_lexer_item_list *item_list_head;
msh_lexer_item_list *item_list_cur;
char *path;
};
msh_lexer msh_lexer_new() {
msh_lexer l = {0};
l.item_list_head = msh_allocate(sizeof(struct msh_lexer_item_list_t));
msh_lexer *msh_lexer_new() {
msh_lexer *l = msh_allocate(sizeof(struct msh_lexer_t));
l->item_list_head = msh_allocate(sizeof(struct msh_lexer_item_list_t));
l.item_list_head->item = 0;
l.item_list_head->next = 0;
l->item_list_head->item = 0;
l->item_list_head->next = 0;
l.item_list_cur = l.item_list_head;
l->item_list_cur = l->item_list_head;
l->path = msh_env_get_path();
l.path = msh_env_get_path();
return l;
};
void msh_lexer_push_item(msh_lexer *lexer, msh_lexer_item_type type, char *buf,
SIZE_TYPE strlen) {
int i;
unsigned short i;
msh_lexer_item *item = msh_callocate(sizeof(msh_lexer_item), 1);
item->str = msh_allocate(strlen * sizeof(char));
@ -38,14 +33,13 @@ void msh_lexer_push_item(msh_lexer *lexer, msh_lexer_item_type type, char *buf,
lexer->item_list_cur->item = item;
lexer->item_list_cur->next = 0;
lexer->item_list_cur->next = msh_callocate(sizeof(msh_lexer_item_list), 1);
lexer->item_list_cur->next = msh_callocate(1, sizeof(msh_lexer_item_list));
lexer->item_list_cur = lexer->item_list_cur->next;
};
void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz) {
int i = 0, n = 0, j = 0;
char *cur_word_buf = msh_callocate(1024, sizeof(char));
char cur_word_buf[1024];
/*case '#':
do_clear = 1;
@ -80,11 +74,11 @@ void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz) {
break;
*/
int escaping = 0;
int quote_mode = 0;
char escaping = 0;
char quote_mode = 0;
for (i = 0; i < sz; i++) {
int do_clear = 0;
char do_clear = 0;
switch (buf[i]) {
case '#':
cur_word_buf[n++] = '\0';
@ -125,33 +119,20 @@ void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz) {
}
}
lexer_cancel:
msh_deallocate(cur_word_buf);
return;
}
void msh_lexer_execute(msh_lexer *lexer) {
msh_lexer_item_list *list = lexer->item_list_head;
char *cmd = 0;
char *cmd = list->item->str;
SIZE_TYPE cmd_size = list->item->strlen;
SIZE_TYPE cmd_size = 0;
SIZE_TYPE args_size = 0;
char **args = 0;
int is_first_arg = 0, i = 0, n = 0, j = 0, counter = 0, exec_success = 0;
char *full_path;
char is_first_arg = 0, exec_success = 0;
unsigned short i = 0, n = 0, j = 0, counter = 0;
char full_path[PATH_MAX];
char *args[512];
while (list != 0) {
if (!list->item) {
break;
}
if (cmd == 0) {
cmd = list->item->str;
cmd_size = list->item->strlen;
} else {
args_size += 1;
}
list = list->next;
}
list = lexer->item_list_head;
args = msh_allocate((args_size + 1) * sizeof(char *));
while (list != 0) {
if (!list->item) {
break;
@ -182,7 +163,6 @@ void msh_lexer_execute(msh_lexer *lexer) {
/* loop through all the path entries and check if the file exists in them.
*/
i = 0, n = 0, j = 0;
full_path = msh_allocate(1024);
while (1) {
full_path[n++] = lexer->path[j];
if (lexer->path[j] == '\0') {
@ -209,14 +189,11 @@ void msh_lexer_execute(msh_lexer *lexer) {
}
j++;
}
msh_deallocate(full_path);
}
if (!exec_success) {
msh_print_strings("msh: ", cmd, ": command not found\n\r", 0);
}
msh_deallocate(args);
msh_lexer_flush(lexer);
};

View file

@ -25,9 +25,13 @@ typedef struct msh_lexer_item_list_t {
struct msh_lexer_item_list_t *next;
} msh_lexer_item_list;
typedef struct msh_lexer_t msh_lexer;
typedef struct msh_lexer_t {
msh_lexer_item_list *item_list_head;
msh_lexer_item_list *item_list_cur;
char *path;
} msh_lexer;
msh_lexer *msh_lexer_new();
msh_lexer msh_lexer_new();
void msh_lexer_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz);
void msh_lexer_push_item(msh_lexer *lexer, msh_lexer_item_type type, char *buf,
SIZE_TYPE strlen);

View file

@ -3,7 +3,7 @@
/* Makefile-defined system entry point. */
MSH_ENTRY_POINT {
msh_lexer *lexer;
msh_lexer lexer;
msh_backend_init();
@ -11,10 +11,12 @@ MSH_ENTRY_POINT {
while (1) {
int out;
char *buf = msh_callocate(513, sizeof(char));
char buf[513];
int i = 0, n = 0, last = 0;
SIZE_TYPE sz = 0, leftoff = 0;
memset(buf, 0, sizeof(buf));
msh_print_strings(msh_working_directory(), " %> ", 0);
while ((out = msh_read_input(buf, &sz, 512)), out != -1) {
@ -64,17 +66,17 @@ MSH_ENTRY_POINT {
buf[sz] = '\0';
if (*buf != '\0') {
msh_lexer_parse(lexer, buf, sz + 1);
msh_lexer_execute(lexer);
msh_lexer_parse(&lexer, buf, sz + 1);
msh_lexer_execute(&lexer);
}
// msh_execute(buf, args);
end_loop:
msh_deallocate(buf);
continue;
}
msh_lexer_free(lexer);
msh_lexer_free(&lexer);
msh_backend_deinit();
}

View file

@ -1,6 +1,7 @@
#include "../system.h"
#include "syscall.h"
#pragma pack(1)
typedef struct msh_linux_block_t msh_linux_block;
#ifdef ARCH_32
@ -10,14 +11,13 @@ typedef struct msh_linux_block_t msh_linux_block;
#endif
struct msh_linux_block_t {
SIZE_TYPE size;
int size;
msh_linux_block *prev;
msh_linux_block *next;
int free;
unsigned char free;
char data[1];
};
#define MSH_BLOCK_SIZE 28
#define MSH_BLOCK_SIZE 21
static msh_linux_block *msh_linux_base = 0;

View file

@ -1,26 +1,23 @@
#include "../system.h"
#include "linux.h"
#include <linux/limits.h>
msh_linux_env_item *env_items = 0;
msh_linux_env_item env_items;
msh_linux_env_item *env_item_tail = 0;
void msh_linux_env_map_init() {
msh_file *env_file = 0;
msh_file env_file;
SIZE_TYPE cur = 0;
char *file_buf = 0;
char file_buf[PATH_MAX];
char ch = 1;
int counter = 0, i = 0;
if (!env_items) {
env_items = msh_callocate(1, sizeof(msh_linux_env_item));
}
env_item_tail = env_items;
env_item_tail = &env_items;
env_file = msh_file_open("/proc/self/environ");
file_buf = msh_callocate(512, sizeof(char));
while (1) {
msh_file_read(env_file, &ch, 1);
while (cur < PATH_MAX) {
msh_file_read(&env_file, &ch, 1);
if (ch != '=') {
file_buf[cur++] = ch;
@ -29,6 +26,8 @@ void msh_linux_env_map_init() {
}
if (ch == '=') {
/* the potentially small allocations made here are fine because these last
* the lifetime of the program and aren't freed either way */
env_item_tail->key = msh_allocate(cur);
msh_str_copy_str(env_item_tail->key, file_buf);
env_item_tail->key_len = cur;
@ -36,12 +35,16 @@ void msh_linux_env_map_init() {
if (env_item_tail->key_hash == str_hash("PATH")) {
env_item_tail->is_path = 1;
}
for (i = 0; i < cur; i++) {
file_buf[i] = 0;
}
memset(file_buf, 0, sizeof(file_buf));
cur = 0;
} else if (ch == '\0') {
env_item_tail->value = file_buf;
/* see comment above the env_item_tail->key comment */
env_item_tail->value = msh_allocate(cur);
for (i = 0; file_buf[i] && i < cur; i++) {
env_item_tail->value[i] = file_buf[i];
}
env_item_tail->value_len = cur;
env_item_tail->next = msh_callocate(1, sizeof(msh_linux_env_item));
@ -50,7 +53,7 @@ void msh_linux_env_map_init() {
file_buf[cur++] = '\0';
}
file_buf = msh_callocate(512, sizeof(char));
memset(file_buf, 0, sizeof(file_buf));
cur = 0;
env_item_tail = env_item_tail->next;
@ -64,14 +67,12 @@ void msh_linux_env_map_init() {
}
}
msh_deallocate(file_buf);
msh_file_close(env_file);
msh_file_close(&env_file);
};
void msh_linux_env_map_deinit() {};
const char *msh_env_get(const char *key) {
msh_linux_env_item *env_item_tail = env_items;
msh_linux_env_item *env_item_tail = &env_items;
int hash = str_hash((char *)key);
while (env_item_tail->next != 0) {
@ -85,7 +86,7 @@ const char *msh_env_get(const char *key) {
};
char *msh_env_get_path() {
msh_linux_env_item *env_item_tail = env_items;
msh_linux_env_item *env_item_tail = &env_items;
while (env_item_tail->next != 0) {
if (env_item_tail->is_path) {
@ -110,7 +111,7 @@ void msh_env_set(const char *key, char *value) {
int hash = str_hash((char *)key);
int env_was_set = 0;
int key_size = 0, value_size = 0;
msh_linux_env_item *env_item_local_cur = env_items;
msh_linux_env_item *env_item_local_cur = &env_items;
char ch = value[0];
while (ch != '\0') {

View file

@ -137,7 +137,7 @@ static const char *error_table[] = {
"Memory page has hardware error"};
void msh_linux_print_errno(int errno) {
char *errno_num_str = msh_allocate(64);
char errno_num_str[16];
itoa(errno, errno_num_str, 10);
if (errno - 1 >= sizeof(error_table)) {
msh_print_strings("Unknown error (errno ", errno_num_str, ")", 0);
@ -145,5 +145,4 @@ void msh_linux_print_errno(int errno) {
msh_print_strings("Error ", errno_num_str, " (", error_table[errno - 1],
")", 0);
}
msh_deallocate(errno_num_str);
}

View file

@ -3,6 +3,7 @@
#include "syscall.h"
#include <linux/kd.h>
#include <linux/limits.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
@ -80,17 +81,10 @@ int msh_execute(char *cmd, char **args) {
fork = (SIZE_TYPE)SYSCALL(fork, 0);
if (fork == 0) {
const char **env_translated = 0;
SIZE_TYPE env_translated_size = 0;
static char *env_translated[PATH_MAX];
SIZE_TYPE ret, i = 0, n = 0;
msh_linux_env_item *item_list = env_items;
while (item_list->next != 0) {
env_translated_size += 1;
item_list = item_list->next;
}
item_list = env_items;
msh_linux_env_item *item_list = &env_items;
env_translated = msh_callocate(env_translated_size + 1, sizeof(char *));
while (item_list != 0) {
if (item_list->key != 0) {
int n = 0;
@ -111,7 +105,6 @@ int msh_execute(char *cmd, char **args) {
for (n = 0; n < i; n++) {
msh_deallocate(env_translated[n]);
}
msh_deallocate(env_translated);
if (ret == -2) {
return -1;
@ -144,14 +137,14 @@ void msh_exit_shell() {
SYSCALL(exit, 0);
};
msh_file *msh_file_open(const char *file) {
msh_file *f = msh_allocate(sizeof(struct msh_file_t));
msh_file msh_file_open(const char *file) {
msh_file f;
f->fd = (int)(SIZE_TYPE)SYSCALL(open, file, O_RDONLY);
f.__fd = (int)(SIZE_TYPE)SYSCALL(open, file, O_RDONLY);
if (f->fd < 0) {
if (f.__fd < 0) {
msh_print_strings("Error opening ", file, ": ", 0);
msh_linux_print_errno(f->fd * -1);
msh_linux_print_errno(f.__fd * -1);
msh_print_string("\n");
msh_exit_shell();
@ -161,23 +154,23 @@ msh_file *msh_file_open(const char *file) {
};
void msh_file_close(msh_file *file) {
SYSCALL(close, file->fd);
SYSCALL(close, file->__fd);
msh_deallocate(file);
};
void msh_file_read(msh_file *file, char *ptr, SIZE_TYPE n) {
SYSCALL(read, file->fd, ptr, n);
SYSCALL(read, file->__fd, ptr, n);
};
SIZE_TYPE msh_file_size(msh_file *file) {
SIZE_TYPE sz;
SYSCALL(lseek, file->fd, 0, SEEK_END);
SYSCALL(lseek, file->__fd, 0, SEEK_END);
sz = (SIZE_TYPE)SYSCALL(lseek, file->fd, 0, SEEK_CUR);
sz = (SIZE_TYPE)SYSCALL(lseek, file->__fd, 0, SEEK_CUR);
SYSCALL(lseek, file->fd, 0, SEEK_SET);
SYSCALL(lseek, file->__fd, 0, SEEK_SET);
return sz;
};

View file

@ -13,10 +13,7 @@ void msh_linux_end_input_capture();
void msh_linux_setup_signals();
struct msh_file_t {
int fd;
};
#pragma pack(push, 1)
typedef struct msh_linux_env_item_t msh_linux_env_item;
struct msh_linux_env_item_t {
char *key;
@ -27,6 +24,8 @@ struct msh_linux_env_item_t {
int is_path;
msh_linux_env_item *next;
};
extern msh_linux_env_item *env_items;
#pragma pack(pop)
extern msh_linux_env_item env_items;
#endif

View file

@ -25,12 +25,16 @@ void msh_deallocate(void *ptr);
void msh_exit_shell();
/* File given by the file functions */
typedef struct msh_file_t msh_file;
typedef struct msh_file_t {
#ifdef __linux__
int __fd;
#endif
} msh_file;
/*
* Open the given file
*/
msh_file *msh_file_open(const char *file);
msh_file msh_file_open(const char *file);
/*
* Close the given file

View file

@ -82,3 +82,10 @@ int itoa(int value, char *sp, int radix) {
return len;
}
SIZE_TYPE strlen(char *str) {
SIZE_TYPE i = 0;
while (*str++) {
++i;
}
return i;
};

View file

@ -21,6 +21,8 @@ void msh_print_string(char *str);
/* Hash string */
unsigned long str_hash(char *str);
SIZE_TYPE strlen(char *str);
/* satisfy glibc */
void *memset(void *b, int c, SIZE_TYPE len);