diff --git a/.gitignore b/.gitignore index c24aa5f..d01aefe 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ ChibiOS_* **/.* gui/stmdspgui **/*.o +**/*.so perf* diff --git a/filter/Makefile b/filter/Makefile new file mode 100644 index 0000000..a1ce186 --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,14 @@ +all: + @arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os --specs=nosys.specs -nostartfiles -fPIE -c test.cpp + @arm-none-eabi-ld -shared -n -N -z max-page-size=512 -Ttext-segment=0 \ + test.o -o test.so + @arm-none-eabi-strip -s -S --strip-unneeded test.so + @arm-none-eabi-objcopy --remove-section .dynsym \ + --remove-section .dynstr \ + --remove-section .dynamic \ + --remove-section .hash \ + --remove-section .ARM.exidx \ + --remove-section .ARM.attributes \ + --remove-section .comment \ + test.so + diff --git a/filter/test.cpp b/filter/test.cpp new file mode 100644 index 0000000..0953539 --- /dev/null +++ b/filter/test.cpp @@ -0,0 +1,15 @@ +#include + +using adcsample_t = uint16_t; +__attribute__((section(".process_data"))) +void process_data(adcsample_t *samples, unsigned int size); + +//////////////////////////////////////////////////////////////////////////////// + +void process_data(adcsample_t *samples, unsigned int size) +{ + size--; + for (unsigned int i = 0; i < size; i++) + samples[i] = samples[i] * 80 / 100 + samples[i + 1] * 20 / 100; +} + diff --git a/source/elf_format.hpp b/source/elf_format.hpp new file mode 100644 index 0000000..ed74c7b --- /dev/null +++ b/source/elf_format.hpp @@ -0,0 +1,93 @@ +#ifndef STMDSP_ELF_FORMAT_HPP_ +#define STMDSP_ELF_FORMAT_HPP_ + +#include + +#define EI_NIDENT 16 + +#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_RESERVED 0x70000000 + +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xF) +#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xF)) + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xFF) +#define ELF32_R_INFO(s, t) (((s) << 8) + ((t) & 0xFF)) + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef struct { + unsigned char 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; +} __attribute__((packed)) Elf32_Ehdr; + +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; +} __attribute__((packed)) Elf32_Shdr; + +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} __attribute__((packed)) Elf32_Sym; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} __attribute__((packed)) Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} __attribute__((packed)) Elf32_Rela; + +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; +} __attribute__((packed)) Elf32_Phdr; + +#endif // STMDSP_ELF_FORMAT_HPP_ + diff --git a/source/elf_load.cpp b/source/elf_load.cpp new file mode 100644 index 0000000..661dbc3 --- /dev/null +++ b/source/elf_load.cpp @@ -0,0 +1,77 @@ +#include "elf_load.hpp" +#include "elf_format.hpp" + +#include +#include + +extern void *elf_load_offset; +static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' }; + +template +constexpr static auto ptr_from_offset(void *base, uint32_t offset) +{ + return reinterpret_cast(reinterpret_cast(base) + offset); +} + +static Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name); + +namespace elf { + +entry_t elf_load(void *elf_data) +{ + auto ehdr = reinterpret_cast(elf_data); + if (std::equal(ehdr->e_ident, ehdr->e_ident + 4, elf_header)) + return nullptr; + + auto phdr = ptr_from_offset(elf_data, ehdr->e_phoff); + for (Elf32_Half i = 0; i < ehdr->e_phnum; i++) { + if (phdr->p_type == PT_LOAD) { + std::memcpy(ptr_from_offset(elf_load_offset, phdr->p_vaddr), + ptr_from_offset(elf_data, phdr->p_offset), + phdr->p_filesz); + //break; + } + } + + // Zero .bss section + if (auto bss_section = find_section(ehdr, ".bss"); bss_section) { + auto bss = ptr_from_offset(elf_load_offset, bss_section->sh_addr); + std::fill(bss, bss + bss_section->sh_size / sizeof(uint32_t), 0); + } + + // Fix global offset table (GOT) entries + if (auto got_section = find_section(ehdr, ".got"); got_section) { + auto got = ptr_from_offset(elf_load_offset, got_section->sh_addr); + for (size_t i = 0; i < got_section->sh_size / sizeof(void *); i++) + got[i] = ptr_from_offset(got[i], reinterpret_cast(elf_load_offset)); + } + + //// Run any initial constructors + //if (auto init_section = find_section(ehdr, ".init_array"); init_section) { + // auto init_array = reinterpret_cast(elf_load_offset + init_section->sh_addr); + // std::for_each(init_array, init_array + init_section->sh_size / sizeof(void (*)()), + // [elf_load_offset](auto func) { (func + elf_load_offset)(); }); + //} + + return ptr_from_offset(elf_load_offset, ehdr->e_entry); +} + +} // namespace elf + +Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name) +{ + auto shdr = ptr_from_offset(ehdr, ehdr->e_shoff); + auto shdr_str = ptr_from_offset(ehdr, + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize); + + for (Elf32_Half i = 0; i < ehdr->e_shnum; i++) { + char *section = ptr_from_offset(ehdr, shdr_str->sh_offset) + shdr->sh_name; + if (!strcmp(section, name)) + return shdr; + + shdr = ptr_from_offset(shdr, ehdr->e_shentsize); + } + + return 0; +} + diff --git a/source/elf_load.hpp b/source/elf_load.hpp new file mode 100644 index 0000000..722b19b --- /dev/null +++ b/source/elf_load.hpp @@ -0,0 +1,12 @@ +#ifndef ELF_LOAD_HPP_ +#define ELF_LOAD_HPP_ + +namespace elf +{ + using entry_t = void (*)(); + + entry_t load(void *file_data); +} + +#endif // ELF_LOAD_HPP_ +