feat(tools): fas2sym: .sym file are now usable with gdb

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-10-18 16:51:01 +02:00
parent 34025f7766
commit 62127fc4fd
7 changed files with 104 additions and 13 deletions

View file

@ -1,10 +1,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <elf.h> #include <elf.h>
#include "fas2sym.h" #include "fas2sym.h"
enum sections { enum sections {
SEC_NULL = 0, SEC_NULL = 0,
SEC_TEXT,
SEC_SHSTRTAB, SEC_SHSTRTAB,
SEC_STRTAB, SEC_STRTAB,
SEC_SYMTAB, SEC_SYMTAB,
@ -17,20 +19,25 @@ static Elf32_Ehdr elf_ehdr = {
ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFCLASS32, ELFDATA2LSB, EV_CURRENT,
0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0
}, },
ET_REL, EM_386, EV_CURRENT, 0, 0, 0, 0, ET_DYN, EM_386, EV_CURRENT, 0, 0, 0, 0,
sizeof(Elf32_Ehdr), sizeof(Elf32_Phdr), 0, sizeof(Elf32_Ehdr), sizeof(Elf32_Phdr), 0,
sizeof(Elf32_Shdr), SEC_END, SEC_SHSTRTAB sizeof(Elf32_Shdr), SEC_END, SEC_SHSTRTAB
}; };
static Elf32_Shdr elf_shdrs[SEC_END] = { static Elf32_Shdr elf_shdrs[SEC_END] = {
{ 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 }, { 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 },
/* .text */
{
1, SHT_NOBITS, SHF_ALLOC | SHF_EXECINSTR,
0, 0, 0, SHN_UNDEF, 0, 1, 0
},
/* .shstrtab */ /* .shstrtab */
{ 1, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 }, { 7, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 },
/* .strtab */ /* .strtab */
{ 11, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 }, { 17, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 },
/* .symtab */ /* .symtab */
{ {
19, SHT_SYMTAB, 0, 0, 0, 0, 25, SHT_SYMTAB, 0, 0, 0, 0,
SEC_STRTAB, 0, 4, sizeof(Elf32_Sym) SEC_STRTAB, 0, 4, sizeof(Elf32_Sym)
} }
}; };
@ -42,7 +49,7 @@ static struct buffer elf_symtab = { 0, 0, NULL };
static int static int
elf_shstrtab_init(void) elf_shstrtab_init(void)
{ {
const uint8_t initial[] = "\0.shstrtab\0.strtab\0.symtab\0"; const uint8_t initial[] = "\0.text\0.shstrtab\0.strtab\0.symtab\0";
return (buffer_put(&elf_shstrtab, initial, sizeof(initial), NULL)); return (buffer_put(&elf_shstrtab, initial, sizeof(initial), NULL));
} }
@ -100,6 +107,8 @@ elf_add_symbol(uint32_t name_off, uint32_t value, uint32_t size,
msg_verbose(2, "add symbol: %s", msg_verbose(2, "add symbol: %s",
(char *)(elf_strtab.data + name_off)); (char *)(elf_strtab.data + name_off));
elf_shdrs[SEC_SYMTAB].sh_info += 1;
return (buffer_put(&elf_symtab, (uint8_t *)&sym, return (buffer_put(&elf_symtab, (uint8_t *)&sym,
sizeof(Elf32_Sym), NULL)); sizeof(Elf32_Sym), NULL));
} }
@ -146,6 +155,55 @@ elf_compute_section_offsets(void)
elf_shdrs[SEC_SYMTAB].sh_size = elf_symtab.cnt; elf_shdrs[SEC_SYMTAB].sh_size = elf_symtab.cnt;
} }
static void
elf_resolve_symbols(void)
{
Elf32_Sym *syms;
char *strtab;
size_t idx;
size_t symcnt;
uint32_t begin = 0;
uint32_t end = 0;
if (text_begin == NULL || text_end == NULL)
{
return;
}
syms = (Elf32_Sym *)elf_symtab.data;
strtab = (char *)elf_strtab.data;
symcnt = (elf_symtab.cnt / sizeof(Elf32_Sym));
for (idx = 0; idx < symcnt; idx++)
{
if (strcmp(strtab + syms[idx].st_name, text_begin) == 0)
{
begin = syms[idx].st_value;
msg_verbose(1, "Sym %s: %X\n", text_begin, begin);
}
else if (strcmp(strtab + syms[idx].st_name, text_end) == 0)
{
end = syms[idx].st_value;
}
if (begin != 0 && end != 0)
{
break;
}
}
elf_shdrs[SEC_TEXT].sh_addr = begin;
elf_shdrs[SEC_TEXT].sh_size = end - begin;
for (idx = 0; idx < symcnt; idx++)
{
if (syms[idx].st_value >= begin && syms[idx].st_value <= end)
{
syms[idx].st_shndx = SEC_TEXT;
}
}
}
int int
elf_write(const char *file) elf_write(const char *file)
{ {
@ -167,6 +225,8 @@ elf_write(const char *file)
elf_ehdr.e_shoff += elf_shstrtab.cnt + elf_strtab.cnt; elf_ehdr.e_shoff += elf_shstrtab.cnt + elf_strtab.cnt;
elf_ehdr.e_shoff += elf_symtab.cnt; elf_ehdr.e_shoff += elf_symtab.cnt;
elf_resolve_symbols();
if (fwrite(&elf_ehdr, sizeof(Elf32_Ehdr), 1, fp) != 1) if (fwrite(&elf_ehdr, sizeof(Elf32_Ehdr), 1, fp) != 1)
{ {
msg_errx("%s: An error occurred while writting elf header", file); msg_errx("%s: An error occurred while writting elf header", file);
@ -193,7 +253,7 @@ elf_write(const char *file)
/* section headers */ /* section headers */
elf_compute_section_offsets(); elf_compute_section_offsets();
/* XXX: fix me */ /* XXX: fix me */
elf_shdrs[SEC_SYMTAB].sh_info = 0; /* (elf_symtab.cnt / sizeof(Elf32_Sym)) + 1;*/ elf_shdrs[SEC_SYMTAB].sh_info += 1;/*= 0; *//* (elf_symtab.cnt / sizeof(Elf32_Sym)) + 1;*/
if (fwrite(elf_shdrs, sizeof(Elf32_Shdr), SEC_END, fp) != SEC_END) if (fwrite(elf_shdrs, sizeof(Elf32_Shdr), SEC_END, fp) != SEC_END)
{ {

View file

@ -131,9 +131,9 @@ fas_export_symbol_name(uint32_t name_off)
return (0); /* anonymous symbol */ return (0); /* anonymous symbol */
} }
if (name_off & (1<<31)) /* if in fas strtab */ if (name_off & (1u<<31)) /* if in fas strtab */
{ {
ptr = fas_strtab + (name_off & ~(1<<31)); /* XXX */ ptr = fas_strtab + (name_off & ~(1u<<31)); /* XXX */
} }
else /* otherwhise it's in psrc */ else /* otherwhise it's in psrc */
{ {

View file

@ -30,6 +30,9 @@ int elf_write(const char *file);
void elf_cleanup(void); void elf_cleanup(void);
/* main.c */ /* main.c */
extern const char *text_begin;
extern const char *text_end;
void msg_err(const char *fmt, ...); void msg_err(const char *fmt, ...);
void msg_errx(const char *fmt, ...); void msg_errx(const char *fmt, ...);
void msg_verbose(int level, const char *fmt, ...); void msg_verbose(int level, const char *fmt, ...);

View file

@ -10,6 +10,8 @@
static const char *prg_name; static const char *prg_name;
static const char *outfile = "out.sym"; static const char *outfile = "out.sym";
static int verbose = 0; static int verbose = 0;
const char *text_begin = NULL;
const char *text_end = NULL;
static void static void
msg_err_common(const char *fmt, va_list ap) msg_err_common(const char *fmt, va_list ap)
@ -77,6 +79,15 @@ usage(int retval)
else else
{ {
printf("Usage: %s [-o OUTPUT] file\n", prg_name); printf("Usage: %s [-o OUTPUT] file\n", prg_name);
printf("OPTIONS:\n");
printf(" -o OUTPUT Set output file (default: %s)\n",
outfile);
printf(" -t begin,end XXXX (addr or symbol)\n");
/*
* -t start,end (text)
* -b start,end (bss)
* -d start,end (data)
*/
} }
exit(retval); exit(retval);
@ -95,10 +106,11 @@ main(int argc, char **argv)
{ {
int c; int c;
int status; int status;
char *tmp;
prg_name = basename(argv[0]); prg_name = basename(argv[0]);
while ((c = getopt(argc, argv, "hvVo:")) != -1) while ((c = getopt(argc, argv, "hvVo:t:")) != -1)
{ {
switch (c) switch (c)
{ {
@ -114,6 +126,19 @@ main(int argc, char **argv)
case 'o': case 'o':
outfile = optarg; outfile = optarg;
break; break;
case 't':
tmp = strchr(optarg, ',');
if (tmp == NULL)
{
usage(EXIT_FAILURE);
}
*tmp = '\0';
text_begin = optarg;
text_end = tmp + 1;
msg_verbose(2, ".text: %s, %s", text_begin, text_end);
break;
default: default:
usage(EXIT_FAILURE); usage(EXIT_FAILURE);
break; break;

View file

@ -185,7 +185,7 @@ print_symbol_section(uint8_t type, uint32_t rel)
return; return;
} }
if (rel & (1<<31)) if (rel & (1u<<31))
{ {
printf("UND "); printf("UND ");
} }
@ -204,9 +204,9 @@ print_symbol_name(uint32_t off)
{ {
return; return;
} }
if (off & (1<<31)) if (off & (1u<<31))
{ {
printf("%s", strtab + (off & ~(1<<31))); printf("%s", strtab + (off & ~(1u<<31)));
} }
else else
{ {
@ -230,6 +230,7 @@ print_symbols(void)
printf("%-4" PRIu8 " ", symtab[idx].size); printf("%-4" PRIu8 " ", symtab[idx].size);
print_symbol_section(symtab[idx].type, symtab[idx].reloc); print_symbol_section(symtab[idx].type, symtab[idx].reloc);
print_symbol_name(symtab[idx].name_off); print_symbol_name(symtab[idx].name_off);
/*printf(" %" PRIx8, symtab[idx].flags); */
printf("\n"); printf("\n");
} }
printf("\n"); printf("\n");

View file

@ -42,6 +42,8 @@ SRCS = kernel.asm \
bio.inc \ bio.inc \
$(ASMINCS) $(ASMINCS)
FAS2SYMFLAGS = -t kmain,kend
.PHONY: const.inc .PHONY: const.inc
const.inc: const.inc.in const.inc: const.inc.in
@$(VERSION_SH) @$(VERSION_SH)

View file

@ -11,7 +11,7 @@ $(KERNEL).sys $(KERNEL).fas &: $(SRCS)
$(KERNEL).sym: $(KERNEL).fas $(KERNEL).sym: $(KERNEL).fas
$(MSG_CREATE) $(MSG_CREATE)
@$(FAS2SYM) -o $@ $< @$(FAS2SYM) $(FAS2SYMFLAGS) -o $@ $<
.PHONY: install .PHONY: install
install: $(DESTDIR)/$(KERNEL).sys $(SYMSDIR)/$(KERNEL).sym install: $(DESTDIR)/$(KERNEL).sys $(SYMSDIR)/$(KERNEL).sym