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 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 CFLAGS := -g -Oz -nostdlib
LDFLAGS :=
UNAME := $(shell uname) UNAME := $(shell uname)
ARCH := $(shell uname -m) ARCH := $(shell uname -m)
ifeq ($(UNAME), Linux) 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 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()" CFLAGS += -DMSH_ENTRY_POINT="void _start()"
ifeq ($(ARCH),i386) ifeq ($(ARCH),i386)
SOURCES += src/system/linux/i386.s SOURCES += src/system/linux/i386.s
@ -19,7 +21,7 @@ endif
endif endif
all: $(SOURCES) all: $(SOURCES)
$(CC) $(SOURCES) $(CFLAGS) -o msh $(CC) $(LDFLAGS) $(SOURCES) $(CFLAGS) -o msh
clean: clean:
rm -f *.o msh rm -f *.o msh

View file

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

View file

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

View file

@ -25,9 +25,13 @@ typedef struct msh_lexer_item_list_t {
struct msh_lexer_item_list_t *next; struct msh_lexer_item_list_t *next;
} msh_lexer_item_list; } 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_parse(msh_lexer *lexer, char *buf, SIZE_TYPE sz);
void msh_lexer_push_item(msh_lexer *lexer, msh_lexer_item_type type, char *buf, void msh_lexer_push_item(msh_lexer *lexer, msh_lexer_item_type type, char *buf,
SIZE_TYPE strlen); SIZE_TYPE strlen);

View file

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

View file

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

View file

@ -1,26 +1,23 @@
#include "../system.h" #include "../system.h"
#include "linux.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; msh_linux_env_item *env_item_tail = 0;
void msh_linux_env_map_init() { void msh_linux_env_map_init() {
msh_file *env_file = 0; msh_file env_file;
SIZE_TYPE cur = 0; SIZE_TYPE cur = 0;
char *file_buf = 0; char file_buf[PATH_MAX];
char ch = 1; char ch = 1;
int counter = 0, i = 0; int counter = 0, i = 0;
if (!env_items) { env_item_tail = &env_items;
env_items = msh_callocate(1, sizeof(msh_linux_env_item));
}
env_item_tail = env_items;
env_file = msh_file_open("/proc/self/environ"); env_file = msh_file_open("/proc/self/environ");
file_buf = msh_callocate(512, sizeof(char));
while (1) { while (cur < PATH_MAX) {
msh_file_read(env_file, &ch, 1); msh_file_read(&env_file, &ch, 1);
if (ch != '=') { if (ch != '=') {
file_buf[cur++] = ch; file_buf[cur++] = ch;
@ -29,6 +26,8 @@ void msh_linux_env_map_init() {
} }
if (ch == '=') { 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); env_item_tail->key = msh_allocate(cur);
msh_str_copy_str(env_item_tail->key, file_buf); msh_str_copy_str(env_item_tail->key, file_buf);
env_item_tail->key_len = cur; 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")) { if (env_item_tail->key_hash == str_hash("PATH")) {
env_item_tail->is_path = 1; env_item_tail->is_path = 1;
} }
for (i = 0; i < cur; i++) { memset(file_buf, 0, sizeof(file_buf));
file_buf[i] = 0;
}
cur = 0; cur = 0;
} else if (ch == '\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->value_len = cur;
env_item_tail->next = msh_callocate(1, sizeof(msh_linux_env_item)); 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[cur++] = '\0';
} }
file_buf = msh_callocate(512, sizeof(char)); memset(file_buf, 0, sizeof(file_buf));
cur = 0; cur = 0;
env_item_tail = env_item_tail->next; 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() {}; void msh_linux_env_map_deinit() {};
const char *msh_env_get(const char *key) { 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); int hash = str_hash((char *)key);
while (env_item_tail->next != 0) { while (env_item_tail->next != 0) {
@ -85,7 +86,7 @@ const char *msh_env_get(const char *key) {
}; };
char *msh_env_get_path() { 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) { while (env_item_tail->next != 0) {
if (env_item_tail->is_path) { 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 hash = str_hash((char *)key);
int env_was_set = 0; int env_was_set = 0;
int key_size = 0, value_size = 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]; char ch = value[0];
while (ch != '\0') { while (ch != '\0') {

View file

@ -137,7 +137,7 @@ static const char *error_table[] = {
"Memory page has hardware error"}; "Memory page has hardware error"};
void msh_linux_print_errno(int errno) { 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); itoa(errno, errno_num_str, 10);
if (errno - 1 >= sizeof(error_table)) { if (errno - 1 >= sizeof(error_table)) {
msh_print_strings("Unknown error (errno ", errno_num_str, ")", 0); 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], msh_print_strings("Error ", errno_num_str, " (", error_table[errno - 1],
")", 0); ")", 0);
} }
msh_deallocate(errno_num_str);
} }

View file

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

View file

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

View file

@ -25,12 +25,16 @@ void msh_deallocate(void *ptr);
void msh_exit_shell(); void msh_exit_shell();
/* File given by the file functions */ /* 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 * Open the given file
*/ */
msh_file *msh_file_open(const char *file); msh_file msh_file_open(const char *file);
/* /*
* Close the given file * Close the given file

View file

@ -82,3 +82,10 @@ int itoa(int value, char *sp, int radix) {
return len; 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 */ /* Hash string */
unsigned long str_hash(char *str); unsigned long str_hash(char *str);
SIZE_TYPE strlen(char *str);
/* satisfy glibc */ /* satisfy glibc */
void *memset(void *b, int c, SIZE_TYPE len); void *memset(void *b, int c, SIZE_TYPE len);