]> code.bitgloo.com Git - clyne/stmdsp.git/commitdiff
add elf load draft, filter program template
authorClyne Sullivan <clyne@bitgloo.com>
Sat, 15 Aug 2020 13:16:54 +0000 (09:16 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Sat, 15 Aug 2020 13:16:54 +0000 (09:16 -0400)
.gitignore
filter/Makefile [new file with mode: 0644]
filter/test.cpp [new file with mode: 0644]
source/elf_format.hpp [new file with mode: 0644]
source/elf_load.cpp [new file with mode: 0644]
source/elf_load.hpp [new file with mode: 0644]

index c24aa5fd649d4cae617b04ea932eb3f641193d98..d01aefece62dd4144425177eaebed2604c7edb25 100644 (file)
@@ -3,5 +3,6 @@ ChibiOS_*
 **/.*
 gui/stmdspgui
 **/*.o
+**/*.so
 perf*
 
diff --git a/filter/Makefile b/filter/Makefile
new file mode 100644 (file)
index 0000000..a1ce186
--- /dev/null
@@ -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 (file)
index 0000000..0953539
--- /dev/null
@@ -0,0 +1,15 @@
+#include <cstdint>
+
+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 (file)
index 0000000..ed74c7b
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef STMDSP_ELF_FORMAT_HPP_
+#define STMDSP_ELF_FORMAT_HPP_
+
+#include <cstdint>
+
+#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 (file)
index 0000000..661dbc3
--- /dev/null
@@ -0,0 +1,77 @@
+#include "elf_load.hpp"
+#include "elf_format.hpp"
+
+#include <algorithm>
+#include <cstring>
+
+extern void *elf_load_offset;
+static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' };
+
+template<typename T>
+constexpr static auto ptr_from_offset(void *base, uint32_t offset)
+{
+    return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(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<Elf32_Ehdr *>(elf_data);
+    if (std::equal(ehdr->e_ident, ehdr->e_ident + 4, elf_header))
+        return nullptr;
+
+    auto phdr = ptr_from_offset<Elf32_Phdr *>(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<void *>(elf_load_offset, phdr->p_vaddr),
+                        ptr_from_offset<void *>(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<uint32_t *>(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<void **>(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<void *>(got[i], reinterpret_cast<uint32_t>(elf_load_offset));
+    }
+
+    //// Run any initial constructors
+    //if (auto init_section = find_section(ehdr, ".init_array"); init_section) {
+    //    auto init_array = reinterpret_cast<void (**)()>(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<entry_t>(elf_load_offset, ehdr->e_entry);
+}
+
+} // namespace elf
+
+Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name)
+{
+       auto shdr = ptr_from_offset<Elf32_Shdr *>(ehdr, ehdr->e_shoff);
+       auto shdr_str = ptr_from_offset<Elf32_Shdr *>(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<char *>(ehdr, shdr_str->sh_offset) + shdr->sh_name;
+               if (!strcmp(section, name))
+                       return shdr;
+
+               shdr = ptr_from_offset<Elf32_Shdr *>(shdr, ehdr->e_shentsize);
+       }
+
+       return 0;
+}
+
diff --git a/source/elf_load.hpp b/source/elf_load.hpp
new file mode 100644 (file)
index 0000000..722b19b
--- /dev/null
@@ -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_
+