feat(tools): fas2dump: generate elf file with symbol table from .fas

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-08-17 13:25:31 +02:00
parent ca6e6e9487
commit 81abea70fd
12 changed files with 1320 additions and 25 deletions

3
.gitignore vendored
View file

@ -33,6 +33,9 @@ bochsrc.bxrc
*.EFI
*.fd
*.mod
*.fas
*.sym
*.dbg
webring.json
webring.txt
kernel/const.inc

39
bin/fas2sym/buffer.c Normal file
View file

@ -0,0 +1,39 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "fas2sym.h"
int
buffer_put(struct buffer *buff, const uint8_t *data, size_t size,
size_t *index)
{
if (index != NULL)
{
*index = buff->cnt;
}
while (buff->cap < buff->cnt + size)
{
buff->cap = (buff->cap == 0 ? 32 : buff->cap * 2);
buff->data = (uint8_t *)realloc(buff->data, buff->cap);
if (buff->data == NULL)
{
msg_err(NULL);
return (-1);
}
}
memcpy(buff->data + buff->cnt, data, size);
buff->cnt += size;
return (0);
}
void
buffer_cleanup(struct buffer *buff)
{
buff->cnt = 0;
buff->cap = 0;
free(buff->data);
buff->data = 0;
}

216
bin/fas2sym/elf.c Normal file
View file

@ -0,0 +1,216 @@
#include <stdlib.h>
#include <stdio.h>
#include <elf.h>
#include "fas2sym.h"
enum sections {
SEC_NULL = 0,
SEC_SHSTRTAB,
SEC_STRTAB,
SEC_SYMTAB,
SEC_END
};
static Elf32_Ehdr elf_ehdr = {
{
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
ELFCLASS32, ELFDATA2LSB, EV_CURRENT,
0, 0, 0, 0, 0, 0, 0, 0, 0
},
ET_REL, EM_386, EV_CURRENT, 0, 0, 0, 0,
sizeof(Elf32_Ehdr), sizeof(Elf32_Phdr), 0,
sizeof(Elf32_Shdr), SEC_END, SEC_SHSTRTAB
};
static Elf32_Shdr elf_shdrs[SEC_END] = {
{ 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 },
/* .shstrtab */
{ 1, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 },
/* .strtab */
{ 11, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 },
/* .symtab */
{
19, SHT_SYMTAB, 0, 0, 0, 0,
SEC_STRTAB, 0, 4, sizeof(Elf32_Sym)
}
};
static struct buffer elf_shstrtab = { 0, 0, NULL };
static struct buffer elf_strtab = { 0, 0, NULL };
static struct buffer elf_symtab = { 0, 0, NULL };
static int
elf_shstrtab_init(void)
{
const uint8_t initial[] = "\0.shstrtab\0.strtab\0.symtab\0";
return (buffer_put(&elf_shstrtab, initial, sizeof(initial), NULL));
}
static int
elf_strtab_init(void)
{
const uint8_t initial[] = "\0";
return (buffer_put(&elf_strtab, initial, sizeof(initial), NULL));
}
static int
elf_symtab_init(void)
{
const Elf32_Sym initial = { 0, 0, 0, 0, 0, SHN_UNDEF };
return (buffer_put(&elf_symtab, (uint8_t *)&initial,
sizeof(Elf32_Sym), NULL));
}
int
elf_init(void)
{
if (elf_shstrtab_init() != 0)
{
return (-1);
}
if (elf_strtab_init() != 0)
{
return (-1);
}
if (elf_symtab_init() != 0)
{
return (-1);
}
return (0);
}
int
elf_add_symbol(uint32_t name_off, uint32_t value, uint32_t size,
uint8_t info, uint16_t sect)
{
Elf32_Sym sym = { 0 };
sym.st_name = name_off;
sym.st_value = value;
sym.st_size = size;
sym.st_info = info;
sym.st_shndx = sect;
msg_verbose(2, "add symbol: %s",
(char *)(elf_strtab.data + name_off));
return (buffer_put(&elf_symtab, (uint8_t *)&sym,
sizeof(Elf32_Sym), NULL));
}
int
elf_add_str(const char *str, size_t len, size_t *idx)
{
return (buffer_put(&elf_strtab, (uint8_t *)str, len, idx));
}
static int
elf_write_tab(struct buffer *buff, FILE *fp)
{
if (buff->cnt == 0 || buff->data == NULL)
{
return (0);
}
if (fwrite(buff->data, buff->cnt, 1, fp) != 1)
{
return (-1);
}
return (0);
}
static void
elf_compute_section_offsets(void)
{
size_t offset;
offset = sizeof(Elf32_Ehdr);
elf_shdrs[SEC_SHSTRTAB].sh_offset = offset;
elf_shdrs[SEC_SHSTRTAB].sh_size = elf_shstrtab.cnt;
offset += elf_shstrtab.cnt;
elf_shdrs[SEC_STRTAB].sh_offset = offset;
elf_shdrs[SEC_STRTAB].sh_size = elf_strtab.cnt;
offset += elf_strtab.cnt;
elf_shdrs[SEC_SYMTAB].sh_offset = offset;
elf_shdrs[SEC_SYMTAB].sh_size = elf_symtab.cnt;
}
int
elf_write(const char *file)
{
FILE *fp;
int status;
size_t offset;
fp = fopen(file, "wb");
if (fp == NULL)
{
msg_err(file);
return (-1);
}
status = -1;
/* compute section headers offset */
elf_ehdr.e_shoff = sizeof(Elf32_Ehdr);
elf_ehdr.e_shoff += elf_shstrtab.cnt + elf_strtab.cnt;
elf_ehdr.e_shoff += elf_symtab.cnt;
if (fwrite(&elf_ehdr, sizeof(Elf32_Ehdr), 1, fp) != 1)
{
msg_errx("%s: An error occurred while writting elf header", file);
goto end;
}
if (elf_write_tab(&elf_shstrtab, fp) != 0)
{
msg_errx("%s: An error occured while writting .shstrtab data", file);
goto end;
}
if (elf_write_tab(&elf_strtab, fp) != 0)
{
msg_errx("%s: An error occured while writting .strtab data", file);
goto end;
}
if (elf_write_tab(&elf_symtab, fp) != 0)
{
msg_errx("%s: An error occured while writting .symtab data", file);
goto end;
}
/* section headers */
elf_compute_section_offsets();
/* XXX: fix me */
elf_shdrs[SEC_SYMTAB].sh_info = 0; /* (elf_symtab.cnt / sizeof(Elf32_Sym)) + 1;*/
if (fwrite(elf_shdrs, sizeof(Elf32_Shdr), SEC_END, fp) != SEC_END)
{
msg_errx("%s: An error occured while writting sections headers", file);
goto end;
}
status = 0;
end:
fclose(fp);
return (status);
}
void
elf_cleanup(void)
{
buffer_cleanup(&elf_shstrtab);
buffer_cleanup(&elf_strtab);
buffer_cleanup(&elf_symtab);
}

192
bin/fas2sym/fas.c Normal file
View file

@ -0,0 +1,192 @@
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <fas.h>
#include <elf.h>
#include "fas2sym.h"
static FAS_Hdr fas_hdr;
static char *fas_strtab = NULL;
static FAS_Sym *fas_symtab = NULL;
static uint8_t *fas_psrc = NULL;
static size_t fas_sym_cnt = 0;
static void
pstr2cstr(char *dst, const uint8_t *src)
{
size_t psz;
psz = *src++;
while (psz > 0)
{
*dst++ = *src++;
psz--;
}
*dst = '\0';
}
static int
fas_load_table(uint8_t **dest, size_t offset, size_t size, FILE *fp)
{
if (size == 0)
{
return (0); /* XXX */
}
*dest = (uint8_t *)malloc(size);
if (*dest == NULL)
{
msg_err(NULL);
return (-1);
}
if (fseek(fp, offset, SEEK_SET) != 0)
{
msg_err(NULL);
return (-1);
}
if (fread(*dest, size, 1, fp) != 1)
{
msg_errx("An unexpected error/eof occured while reading");
return (-1);
}
return (0);
}
int
fas_load_file(const char *file)
{
FILE *fp;
fp = fopen(file, "rb");
if (fp == NULL)
{
msg_err(file);
return (-1);
}
if (fread(&fas_hdr, sizeof(FAS_Hdr), 1, fp) != 1)
{
msg_errx("%s: unexpected error/eof while reading FAS header",
file);
goto err;
}
if (fas_hdr.magic != FAS_MAGIC)
{
msg_errx("%s: invalid magic, got '%08" PRIX32
"' instead of '%08" PRIX32 "'",
file, (uint32_t)FAS_MAGIC);
goto err;
}
if (fas_load_table((uint8_t **)&fas_strtab, fas_hdr.strtab_off,
fas_hdr.strtab_len, fp) != 0)
{
msg_errx("%s: can't load string table", file);
goto err_cleanup;
}
if (fas_load_table((uint8_t **)&fas_symtab, fas_hdr.symtab_off,
fas_hdr.symtab_len, fp) != 0)
{
msg_errx("%s: can't load symbol table", file);
goto err_cleanup;
}
if (fas_load_table(&fas_psrc, fas_hdr.psrc_off, fas_hdr.psrc_len,
fp) != 0)
{
msg_errx("%s: can't load preprocessed sources", file);
goto err_cleanup;
}
fas_sym_cnt = fas_hdr.symtab_len / sizeof(FAS_Sym);
msg_verbose(1, "%zu symbol(s) loaded from %s", fas_sym_cnt, file);
fclose(fp);
return (0);
err_cleanup:
fas_cleanup();
err:
fclose(fp);
return (-1);
}
static uint32_t
fas_export_symbol_name(uint32_t name_off)
{
size_t idx = 0;
char *ptr;
char name[256] = { 0 };
if (name_off == 0)
{
return (0); /* anonymous symbol */
}
if (name_off & (1<<31)) /* if in fas strtab */
{
ptr = fas_strtab + (name_off & ~(1<<31)); /* XXX */
}
else /* otherwhise it's in psrc */
{
pstr2cstr(name, fas_psrc + name_off);
ptr = name;
}
if (elf_add_str(ptr, strlen(ptr) + 1, &idx) != 0)
{
/* error occured */
return (0);
}
return (idx);
}
void
fas_export_symbols(void)
{
size_t idx;
char *name_ptr;
size_t name_idx;
/* export file name symbol */
name_ptr = fas_strtab + fas_hdr.ifnm_off;
elf_add_str(name_ptr, strlen(name_ptr) + 1, &name_idx);
elf_add_symbol(name_idx, 0, 0, ELF32_ST_INFO(STB_LOCAL, STT_FILE),
SHN_ABS);
/* export other symbol */
for (idx = 0; idx < fas_sym_cnt; idx++)
{
if ((fas_symtab[idx].flags & FAS_SYM_DEF) == 0 ||
fas_symtab[idx].flags & FAS_SYM_ASM_TIME)
{
continue;
}
name_idx = fas_export_symbol_name(fas_symtab[idx].name_off);
elf_add_symbol(name_idx, fas_symtab[idx].value, 0,
ELF32_ST_INFO(STB_LOCAL, STT_OBJECT), SHN_ABS);
}
}
void
fas_cleanup(void)
{
free(fas_psrc);
fas_psrc = NULL;
free(fas_symtab);
fas_symtab = NULL;
free(fas_strtab);
fas_strtab = NULL;
}

37
bin/fas2sym/fas2sym.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef FAS2SYM_H
# define FAS2SYM_H 1
# include <stddef.h>
# include <stdint.h>
# include <stdarg.h>
struct buffer {
size_t cap;
size_t cnt;
uint8_t *data;
};
/* buffer.c */
int buffer_put(struct buffer *buff, const uint8_t *data,
size_t size, size_t *index);
void buffer_cleanup(struct buffer *buff);
/* fas.c */
int fas_load_file(const char *file);
void fas_export_symbols(void);
void fas_cleanup(void);
/* elf.c */
int elf_init(void);
int elf_add_str(const char *str, size_t len, size_t *idx);
int elf_add_symbol(uint32_t name_off, uint32_t value, uint32_t size,
uint8_t info, uint16_t sect);
int elf_write(const char *file);
void elf_cleanup(void);
/* main.c */
void msg_err(const char *fmt, ...);
void msg_errx(const char *fmt, ...);
void msg_verbose(int level, const char *fmt, ...);
#endif /* !FAS2SYM_H */

152
bin/fas2sym/main.c Normal file
View file

@ -0,0 +1,152 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include "fas2sym.h"
static const char *prg_name;
static const char *outfile = "out.sym";
static int verbose = 0;
static void
msg_err_common(const char *fmt, va_list ap)
{
fprintf(stderr, "%s: ", prg_name);
if (fmt)
{
vfprintf(stderr, fmt, ap);
}
}
void
msg_errx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
msg_err_common(fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
void
msg_err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
msg_err_common(fmt, ap);
if (fmt)
{
fprintf(stderr, ": ");
}
fprintf(stderr, "%s\n", strerror(errno));
va_end(ap);
}
void
msg_verbose(int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (level <= verbose)
{
vprintf(fmt, ap);
printf("\n");
}
va_end(ap);
}
static void
usage(int retval)
{
if (retval == EXIT_FAILURE)
{
fprintf(stderr, "Try '%s -h' for more information.\n",
prg_name);
}
else
{
printf("Usage: %s [-o OUTPUT] file\n", prg_name);
}
exit(retval);
}
static void
version(void)
{
printf("%s (%s) %s\n", prg_name, MK_PACKAGE, MK_COMMIT);
exit(EXIT_SUCCESS);
}
int
main(int argc, char **argv)
{
int c;
int status;
prg_name = basename(argv[0]);
while ((c = getopt(argc, argv, "hvVo:")) != -1)
{
switch (c)
{
case 'h':
usage(EXIT_SUCCESS);
break;
case 'V':
version();
break;
case 'v':
verbose++;
break;
case 'o':
outfile = optarg;
break;
default:
usage(EXIT_FAILURE);
break;
}
}
if (optind >= argc)
{
usage(EXIT_FAILURE);
}
if (fas_load_file(argv[optind]) != 0)
{
return (EXIT_FAILURE);
}
status = EXIT_FAILURE;
if (elf_init() != 0)
{
goto cleanup;
}
fas_export_symbols();
if (elf_write(outfile) != 0)
{
goto cleanup;
}
status = EXIT_SUCCESS;
cleanup:
elf_cleanup();
fas_cleanup();
return (status);
}

338
bin/fasdump/main.c Normal file
View file

@ -0,0 +1,338 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <fas.h>
struct buff {
size_t size;
uint8_t *data;
};
static char *prg_name = "fasdump";
static struct fas_header hdr;
static struct buff strtab = { 0, NULL };
static struct buff symtab = { 0, NULL };
static struct buff psrc = { 0, NULL };
static struct buff asmdmp = { 0, NULL };
static struct buff sectab = { 0, NULL };
static struct buff symref = { 0, NULL };
static void
version(void)
{
printf("%s (%s) %s\n", prg_name, MK_PACKAGE, MK_COMMIT);
exit(EXIT_SUCCESS);
}
static void
usage(int retval)
{
if (retval == EXIT_FAILURE)
{
fprintf(stderr, "Try '%s -h' for more informations.", prg_name);
}
exit(retval);
}
static int
readall(uint8_t *dest, size_t size, FILE *fp)
{
size_t total;
size_t byte_read;
total = 0;
do
{
byte_read = fread(dest + total, 1, size - total, fp);
if (byte_read == 0)
{
return (-1);
}
total += byte_read;
}
while (total < size);
return (0);
}
static int
load_table(struct buff *dst, size_t off, size_t len, FILE *fp)
{
dst->size = len;
if (len == 0)
{
return (0);
}
dst->data = (uint8_t *)malloc(len);
if (dst->data == NULL)
{
return (-1);
}
if (fseek(fp, off, SEEK_SET) != 0)
{
goto clean_up;
}
if (readall(dst->data, len, fp) != 0)
{
goto clean_up;
}
return (0);
clean_up:
free(dst->data);
dst->size = 0;
return (-1);
}
static int
read_header(FILE *fp)
{
if (readall((uint8_t *)&hdr, sizeof(struct fas_header), fp) != 0)
{
return (-1);
}
if (hdr.magic != FAS_MAGIC)
{
return (-1);
}
return (0);
}
static inline char *
strtab_get(size_t off)
{
if (off > strtab.size)
{
return (NULL);
}
return (strtab.data + off);
}
static void
print_header(void)
{
printf("FAS Header:\n");
printf(" Magic: %X\n", hdr.magic);
printf(" Fasm version: %d.%d\n", hdr.ver_major,
hdr.ver_minor);
printf(" Length: %hu\n", hdr.length);
printf(" Input file: %s\n", strtab_get(hdr.ifnm_off));
printf(" Output file: %s\n", strtab_get(hdr.ofnm_off));
printf(" String table offset: 0x%08X\n", hdr.strtab_off);
printf(" String table length: %u\n", hdr.strtab_len);
printf(" Symbol table offset: 0x%08X\n", hdr.symtab_off);
printf(" Symbol table length: %u\n", hdr.symtab_len);
printf(" ASM dump offset: 0x%08X\n", hdr.asmdmp_off);
printf(" ASM dump length: %d\n", hdr.asmdmp_len);
printf(" Section table offset: 0x%08X\n", hdr.sectab_off);
printf(" Section table length: %d\n", hdr.sectab_len);
printf(" Symref table offset: 0x%08X\n", hdr.symref_off);
printf(" Symref table length: %d\n", hdr.symref_len);
printf("\n");
}
static void
print_sections(void)
{
size_t seccnt;
size_t idx;
uint32_t *sec;
seccnt = sectab.size / sizeof(uint32_t);
sec = (uint32_t *)sectab.data;
printf("Section names:\n");
for (idx = 0; idx < seccnt; idx++)
{
printf(" %s\n", strtab_get(sec[idx]));
}
printf("\n");
}
static void
pstr2cstr(char *dst, const char *src)
{
size_t plen;
plen = *src++;
while (plen > 0)
{
*dst++ = *src++;
plen--;
}
*dst = '\0';
}
static void
print_sym_name(uint32_t off)
{
char name_str[255] = {0};
if (off == 0)
{
return;
}
if (off & (1<<31))
{
strncpy(name_str, strtab_get(off & ~(1<<31)), 255);
name_str[254] = '\0';
}
else
{
pstr2cstr(name_str, psrc.data + off);
}
printf("%s", name_str);
}
static void
print_sym_section(uint8_t type, uint32_t rel)
{
if (type == FAS_ABS)
{
printf("ABS ");
return;
}
if (rel & (1<<31))
{
printf("UND ");
}
else
{
printf("%-3" PRIu32 " %-2" PRIu8 " ", rel, type);
}
}
/*
static const char *
get_symbol_type(uint8_t type)
{
switch (type)
{
case FAS_ABS:
return ("ABS");
case FAS_REL_32:
return ("REL_32");
default:
break;
}
return ("???");
}
*/
static void
print_symbols(void)
{
size_t symcnt;
size_t idx;
struct fas_symbol *sym;
printf("Symbol table:\n");
symcnt = symtab.size / sizeof(struct fas_symbol);
sym = (struct fas_symbol *)symtab.data;
printf(" Num: Value Size Ndx Name\n");
for (idx = 0; idx < symcnt; idx++)
{
printf("%6d: ", idx);
printf("0x%016" PRIx64 " ", sym[idx].value);
printf("%-4" PRIu8 " ", sym[idx].size);
//printf("%s ", get_symbol_type(sym[idx].type));
print_sym_section(sym[idx].type, sym[idx].reloc);
print_sym_name(sym[idx].name_off);
printf("\n");
/*
printf("\t %04" PRIx16 " : ", sym[idx].flags);
if (sym[idx].flags & FAS_SYM_DEF) printf("DEF ");
if (sym[idx].flags & FAS_SYM_ASM_TIME) printf("ASM_TIME ");
if (sym[idx].flags & FAS_SYM_NOT_FWD_REF) printf("NOT_FWD ");
if (sym[idx].flags & FAS_SYM_USED) printf("USED ");
if (sym[idx].flags & FAS_SYM_PRD_USED) printf("PRD_USED ");
if (sym[idx].flags & FAS_SYM_LPRD_USED) printf("LPRD_USED ");
if (sym[idx].flags & FAS_SYM_PRD_DEF) printf("PRD_DEF ");
if (sym[idx].flags & FAS_SYM_LPRD_DEF) printf("LPRD_DEF ");
if (sym[idx].flags & FAS_SYM_OPT_ADJ) printf("OPT_ADJ ");
if (sym[idx].flags & FAS_SYM_TWO_CMPLMNT) printf("TWO_CMPLMNT ");
if (sym[idx].flags & FAS_SYM_MARKER) printf("MARKER ");
printf("\n");
*/
/*printf("%X\n", sym[idx].value);*/
}
printf("\n");
}
static void
print_asm_dump(void)
{
struct fas_asmdmp *dmp;
dmp = (struct fas_asmdmp *)asmdmp.data;
printf(" 0x%" PRIx32 " 0x%" PRIx64 "\n", dmp->of_off, dmp->addr);
}
static int
process_file(char *fname)
{
FILE *fp;
fp = fopen(fname, "rb");
if (fp == NULL)
{
return (EXIT_FAILURE);
}
read_header(fp);
load_table(&strtab, hdr.strtab_off, hdr.strtab_len, fp);
load_table(&symtab, hdr.symtab_off, hdr.symtab_len, fp);
load_table(&psrc, hdr.psrc_off, hdr.psrc_len, fp);
load_table(&asmdmp, hdr.asmdmp_off, hdr.asmdmp_len, fp);
load_table(&sectab, hdr.sectab_off, hdr.sectab_len, fp);
print_header();
print_sections();
print_symbols();
print_asm_dump();
fclose(fp);
return (EXIT_SUCCESS);
}
int
main(int argc, char *argv[])
{
while ((argc > 1) && (argv[1][0] == '-'))
{
switch (argv[1][1])
{
case 'h':
usage(EXIT_SUCCESS);
break;
case 'V':
version();
break;
default:
usage(EXIT_FAILURE);
break;
}
argv++;
argc--;
}
if (argc <= 1) usage(EXIT_FAILURE);
return (process_file(argv[1]));
}

View file

@ -98,7 +98,7 @@ _start:
jmp .skip_fat
; fallback to fat12
; fallback to fat12
; for now fat12 is asumed
.fat_fallback:
mov si, szMsgFatFallback
@ -129,7 +129,7 @@ _start:
xor bx, bx
call disk_read_sectors
; load stage 2
mov ax, KERNEL_PRELOAD/0x10
mov es, ax
@ -146,7 +146,7 @@ _start:
call boot_info_print_mmap
; video information
;call video_setup
call video_setup
; load GDT and enter Protected-Mode
lgdt [gdt_ptr]

View file

@ -6,7 +6,7 @@ struc VesaInfo
.Version dw ?
.OEMNamePtr dd ?
.Capabilities dd ?
.VideoModesPtr dw ?
.VideoModesPtr dd ?
.CountOf64KBlocks dw ?
.OEMSoftwareRevision dw ?
.OEMVendorNamePtr dd ?
@ -28,7 +28,7 @@ struc VesaModeInfo
.WindowPositioning dd ?
.BytesPerScanLine dw ?
; --
; --
.Width dw ?
.Height dw ?
.WidthChar db ?
@ -72,11 +72,11 @@ video_setup:
jne .err
cmp [vesa_block_buffer.Signature], 'VESA'
jne .err
push [vesa_block_buffer.OEMProductNamePtr]
push [vesa_block_buffer.OEMVendorNamePtr]
push [vesa_block_buffer.CountOf64KBlocks]
push [vesa_block_buffer.OEMNamePtr]
; XXX: fix me
push word [vesa_block_buffer.OEMProductNamePtr]
push word [vesa_block_buffer.OEMVendorNamePtr]
push word [vesa_block_buffer.CountOf64KBlocks]
push word [vesa_block_buffer.OEMNamePtr]
xor ecx, ecx
mov cx, [vesa_block_buffer.Version]
push ecx
@ -84,7 +84,7 @@ video_setup:
call bios_log
mov di, vesa_info_block_buffer
mov bx, [vesa_block_buffer.VideoModesPtr]
mov ebx, [vesa_block_buffer.VideoModesPtr]
mov cx, [bx]
cmp cx, 0xFFFF
je .err
@ -110,6 +110,7 @@ vesa_block_buffer VesaInfo
vesa_info_block_buffer VesaModeInfo
szMsgVesaInfo db "Version: %x", CR, LF, "OEM Name: %s", CR, LF, "Total Memory: %d", CR, LF, "Vendor name: %s", CR, LF, "Product name: %s", 0
szMsgVesaModeInfo db "%dx%dx%d", CR, LF, 0
szMsgDetectVideo db "Fetch video information.", 0
szMsgFramebuffer db "Fb: %x", 0
szMsgErrorVesa db "Failed to detect VBE mode", 0

View file

@ -1,23 +1,189 @@
#ifndef ELF_H
# define ELF_H 1
/* spec: https://refspecs.linuxfoundation.org/elf/elf.pdf
* elf(5)
*/
# include <stdint.h>
# define ELF_MAG0 0x7F
# define ELF_MAG1 0x45
# define ELF_MAG2 0x4C
# define ELF_MAG3 0x46
# define ELFMAG0 0x7F
# define ELFMAG1 0x45
# define ELFMAG2 0x4C
# define ELFMAG3 0x46
# define EI_NIDENT 16
# define EI_MAG0 0
# define EI_MAG1 1
# define EI_MAG2 2
# define EI_MAG3 3
# define EI_CLASS 4
# define EI_DATA 5
# define EI_VERSION 6
# define EI_PAD 7
# define EI_NIDENT 16
struct elf_header
{
uint8_t e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
};
# define ET_NONE 0
# define ET_REL 1
# define ET_EXEC 2
# define ET_DYN 3
# define ET_CORE 4
# define ET_LOPROC 0xFF00
# define ET_HIPROC 0xFFFF
/* TODO */
# define EM_NONE 0
# define EM_M32 1
# define EM_SPARC 2
# define EM_386 3
# define EM_68K 4
# define EM_88K 5
# define EM_860 7
# define EM_MIPS 8
# define EM_MIPS_RS4_BE 10
# define EV_NONE 0
# define EV_CURRENT 1
# define ELFCLASSNONE 0
# define ELFCLASS32 1
# define ELFCLASS64 2
# define ELFDATANONE 0
# define ELFDATA2LSB 1
# define ELFDATA2MSB 2
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
typedef struct {
uint8_t e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
# define SHN_UNDEF 0
# define SHN_LORESERVE 0xFF00
# define SHN_LOPROC 0xFF00
# define SHN_HIPROC 0xFF1F
# define SHN_ABS 0xFFF1
# define SHN_COMMON 0xFFF2
# define SHN_HIRESERVE 0xFFFF
# define SHT_NULL 0
# define SHT_PROGBITS 1
# define SHT_SYMTAB 2
# define SHT_STRTAB 3
# define SHT_RELA 4
# define SHT_HASH 5
# define SHT_DYNAMIC 6
# define SHT_NOTE 7
# define SHT_NOBITS 8
# define SHT_REL 9
# define SHT_SHLIB 10
# define SHT_DYNSYM 11
# define SHT_LOPROC 0x70000000
# define SHT_HIPROC 0x7FFFFFFF
# define SHT_LOUSER 0x80000000
# define SHT_HIUSER 0xFFFFFFFF
# define SHF_WRITE 0x1
# define SHF_ALLOC 0x2
# define SHF_EXECINSTR 0x4
# define SHF_MASKPROC 0xF0000000
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
# define STN_UNDER 0
typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
uint8_t st_info;
uint8_t st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
# define ELF32_ST_BIND(x) ((x)>>4)
# define ELF32_ST_TYPE(x) ((x)&0xf)
# define ELF32_ST_INFO(b, t) (((b)<<4)+((t)&0xf))
# define STB_LOCAL 0
# define STB_GLOBAL 1
# define STB_WEAK 2
# define STB_LOPROC 13
# define STB_HIPROC 15
# define STT_NOTYPE 0
# define STT_OBJECT 1
# define STT_FUNC 2
# define STT_SECTION 3
# define STT_FILE 4
# define STT_LOPROC 13
# define STT_HIPROC 15
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
# define ELF32_R_SYM(x) ((x)>>8)
# define ELF32_R_TYPE(x) ((uint8_t)(i));
# define ELF32_R_INFO(s,t) (((s)<<8)+(uint8_t)(t))
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
# define PT_NULL 0
# define PT_LOAD 1
# define PT_DYNAMIC 2
# define PT_INTERP 3
# define PT_NOTE 4
# define PT_SHLIB 5
# define PT_PHDR 6
# define PT_LOPROC 0x70000000
# define PT_HIPROC 0x7FFFFFFF
# define PF_X 0x1
# define PF_W 0x2
# define PF_R 0x4
# define PF_MASKPROC 0xF0000000
#endif /* !ELF_H */

140
include/fas.h Normal file
View file

@ -0,0 +1,140 @@
#ifndef FAS_H
# define FAS_H 1
# include <stdint.h>
# define FAS_MAGIC 0x1A736166
typedef struct fas_header
{
uint32_t magic;
uint8_t ver_major;
uint8_t ver_minor;
uint16_t length;
uint32_t ifnm_off;
uint32_t ofnm_off;
uint32_t strtab_off;
uint32_t strtab_len;
uint32_t symtab_off;
uint32_t symtab_len;
uint32_t psrc_off;
uint32_t psrc_len;
uint32_t asmdmp_off;
uint32_t asmdmp_len;
uint32_t sectab_off;
uint32_t sectab_len;
uint32_t symref_off;
uint32_t symref_len;
} FAS_Hdr;
# define FAS_SYM_DEF 0x001
# define FAS_SYM_ASM_TIME 0x002
# define FAS_SYM_NOT_FWD_REF 0x004
# define FAS_SYM_USED 0x008
# define FAS_SYM_PRD_USED 0x010
# define FAS_SYM_LPRD_USED 0x020
# define FAS_SYM_PRD_DEF 0x040
# define FAS_SYM_LPRD_DEF 0x080
# define FAS_SYM_OPT_ADJ 0x100
# define FAS_SYM_TWO_CMPLMNT 0x200
# define FAS_SYM_MARKER 0x400
enum fas_symbol_type
{
FAS_ABS,
FAS_REL_SEG,
FAS_REL_32,
FAS_REL_R_32,
FAS_REL_64,
FAS_GOT_32,
FAS_PLT_32,
FAS_PLT_R_32
};
typedef struct fas_symbol
{
uint64_t value;
uint16_t flags;
uint8_t size;
uint8_t type;
uint32_t ext_SIB;
uint16_t pass_ldef;
uint16_t pass_lused;
uint32_t reloc;
uint32_t name_off;
uint32_t psrc_line_off;
} FAS_Sym;
struct fas_psrc_line
{
uint32_t from;
uint32_t lineno;
uint32_t src_off;
uint32_t macro_off;
uint8_t tokens[];
};
enum fas_code
{
FAS_CODE_16 = 16,
FAS_CODE_32 = 32,
FAS_CODE_64 = 64
};
struct fas_asmdmp
{
uint32_t of_off;
uint32_t psrc_line_off;
uint64_t addr;
uint32_t ext_SIB;
uint32_t reloc;
uint8_t type;
uint8_t code;
uint8_t virt;
uint8_t high;
};
enum fas_register
{
FAS_REG_BX = 0x23,
FAS_REG_BP = 0x25,
FAS_REG_SI = 0x26,
FAS_REG_DI = 0x27,
FAS_REG_EAX = 0x40,
FAS_REG_ECX = 0x41,
FAS_REG_EDX = 0x42,
FAS_REG_EBX = 0x43,
FAS_REG_ESP = 0x44,
FAS_REG_EBP = 0x45,
FAS_REG_ESI = 0x46,
FAS_REG_EDI = 0x47,
FAS_REG_R8D = 0x48,
FAS_REG_R9D = 0x49,
FAS_REG_R10D = 0x4A,
FAS_REG_R11D = 0x4B,
FAS_REG_R12D = 0x4C,
FAS_REG_R13D = 0x4D,
FAS_REG_R14D = 0x4E,
FAS_REG_R15D = 0x4F,
FAS_REG_RAX = 0x80,
FAS_REG_RCX = 0x81,
FAS_REG_RDX = 0x82,
FAS_REG_RBX = 0x83,
FAS_REG_RSP = 0x84,
FAS_REG_RBP = 0x85,
FAS_REG_RSI = 0x86,
FAS_REG_RDI = 0x87,
FAS_REG_R8 = 0x88,
FAS_REG_R9 = 0x89,
FAS_REG_R10 = 0x8A,
FAS_REG_R11 = 0x8B,
FAS_REG_R12 = 0x8C,
FAS_REG_R13 = 0x8D,
FAS_REG_R14 = 0x8E,
FAS_REG_R15 = 0x8F,
FAS_REG_EIP = 0x94,
FAS_REG_RIP = 0x98,
};
#endif /* !FAS_H */

View file

@ -1,4 +1,9 @@
TARGET = ld$(EXEXT) parted$(EXEXT) readcoff$(EXEXT) elf2coff$(EXEXT) ar$(EXEXT) ranlib$(EXEXT)
TARGET = ld$(EXEXT) parted$(EXEXT) readcoff$(EXEXT) \
elf2coff$(EXEXT) ar$(EXEXT) ranlib$(EXEXT) \
fasdump$(EXEXT) fas2sym$(EXEXT)
FAS2SYM_SRCS = main.c fas.c elf.c buffer.c
FAS2SYM_OBJS = $(addprefix ../bin/fas2sym/, $(FAS2SYM_SRCS:.c=.o))
.PHONY: all
all: $(TARGET)
@ -21,6 +26,12 @@ ranlib$(EXEXT): ../bin/ranlib/main.c ../bin/ar/archive.c
ar$(EXEXT): ../bin/ar/main.c
$(TOOL_CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
fasdump$(EXEXT): ../bin/fasdump/main.c
$(TOOL_CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
fas2sym$(EXEXT): $(FAS2SYM_OBJS)
$(TOOL_CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
.PHONY: install
install: $(TARGET)