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 <stdio.h>
#include <string.h>
#include <elf.h>
#include "fas2sym.h"
enum sections {
SEC_NULL = 0,
SEC_TEXT,
SEC_SHSTRTAB,
SEC_STRTAB,
SEC_SYMTAB,
@ -17,20 +19,25 @@ static Elf32_Ehdr elf_ehdr = {
ELFCLASS32, ELFDATA2LSB, EV_CURRENT,
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_Shdr), SEC_END, SEC_SHSTRTAB
};
static Elf32_Shdr elf_shdrs[SEC_END] = {
{ 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 */
{ 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 */
{ 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 */
{
19, SHT_SYMTAB, 0, 0, 0, 0,
25, SHT_SYMTAB, 0, 0, 0, 0,
SEC_STRTAB, 0, 4, sizeof(Elf32_Sym)
}
};
@ -42,7 +49,7 @@ 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";
const uint8_t initial[] = "\0.text\0.shstrtab\0.strtab\0.symtab\0";
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",
(char *)(elf_strtab.data + name_off));
elf_shdrs[SEC_SYMTAB].sh_info += 1;
return (buffer_put(&elf_symtab, (uint8_t *)&sym,
sizeof(Elf32_Sym), NULL));
}
@ -146,6 +155,55 @@ elf_compute_section_offsets(void)
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
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_symtab.cnt;
elf_resolve_symbols();
if (fwrite(&elf_ehdr, sizeof(Elf32_Ehdr), 1, fp) != 1)
{
msg_errx("%s: An error occurred while writting elf header", file);
@ -193,7 +253,7 @@ elf_write(const char *file)
/* section headers */
elf_compute_section_offsets();
/* 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)
{

View file

@ -131,9 +131,9 @@ fas_export_symbol_name(uint32_t name_off)
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 */
{

View file

@ -30,6 +30,9 @@ int elf_write(const char *file);
void elf_cleanup(void);
/* main.c */
extern const char *text_begin;
extern const char *text_end;
void msg_err(const char *fmt, ...);
void msg_errx(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 *outfile = "out.sym";
static int verbose = 0;
const char *text_begin = NULL;
const char *text_end = NULL;
static void
msg_err_common(const char *fmt, va_list ap)
@ -77,6 +79,15 @@ usage(int retval)
else
{
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);
@ -95,10 +106,11 @@ main(int argc, char **argv)
{
int c;
int status;
char *tmp;
prg_name = basename(argv[0]);
while ((c = getopt(argc, argv, "hvVo:")) != -1)
while ((c = getopt(argc, argv, "hvVo:t:")) != -1)
{
switch (c)
{
@ -114,6 +126,19 @@ main(int argc, char **argv)
case 'o':
outfile = optarg;
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:
usage(EXIT_FAILURE);
break;

View file

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

View file

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

View file

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