summaryrefslogtreecommitdiff
path: root/gcell/lib/runtime/gc_proc_def_utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcell/lib/runtime/gc_proc_def_utils.cc')
-rw-r--r--gcell/lib/runtime/gc_proc_def_utils.cc123
1 files changed, 123 insertions, 0 deletions
diff --git a/gcell/lib/runtime/gc_proc_def_utils.cc b/gcell/lib/runtime/gc_proc_def_utils.cc
new file mode 100644
index 0000000000..0250d677a3
--- /dev/null
+++ b/gcell/lib/runtime/gc_proc_def_utils.cc
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gc_proc_def_utils.h>
+#include <gcell/gc_declare_proc.h>
+#include <elf.h>
+#include <stdio.h>
+#include <string.h>
+
+static const unsigned char expected[EI_PAD] = {
+ ELFMAG0,
+ ELFMAG1,
+ ELFMAG2,
+ ELFMAG3,
+ ELFCLASS32,
+ ELFDATA2MSB,
+ EV_CURRENT,
+ ELFOSABI_SYSV,
+ 0
+};
+
+
+/*
+ * Basically we're going to find the GC_PROC_DEF_SECTION section
+ * in the ELF file and return a pointer to it. The only things in that
+ * section are gc_proc_def's
+ */
+bool
+gcpd_find_table(spe_program_handle_t *handle,
+ struct gc_proc_def **table, int *nentries, uint32_t *ls_addr)
+{
+ if (!handle || !table || !nentries)
+ return false;
+
+ *table = 0;
+ *nentries = 0;
+
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)handle->elf_image;
+ if (!ehdr){
+ fprintf(stderr, "gcpd: No ELF image has been loaded\n");
+ return false;
+ }
+
+ // quick check that we're looking at a SPE EXEC object
+
+ if (memcmp(ehdr->e_ident, expected, EI_PAD) != 0){
+ fprintf(stderr, "gcpd: invalid ELF header\n");
+ return false;
+ }
+
+ if (ehdr->e_machine != 0x17){ // confirm machine type (EM_SPU)
+ fprintf(stderr, "gcpd: not an SPE ELF object\n");
+ return false;
+ }
+
+ if (ehdr->e_type != ET_EXEC){
+ fprintf(stderr, "gcpd: invalid SPE ELF type.\n");
+ fprintf(stderr, "gcpd: SPE type %d != %d\n", ehdr->e_type, ET_EXEC);
+ return false;
+ }
+
+ // find the section header table
+
+ Elf32_Shdr *shdr;
+ Elf32_Shdr *sh;
+
+ if (ehdr->e_shentsize != sizeof (*shdr)){
+ fprintf(stderr, "gcpd: invalid section header format.\n");
+ return false;
+ }
+
+ if (ehdr->e_shnum == 0){
+ fprintf(stderr, "gcpd: no section headers in file.\n");
+ return false;
+ }
+
+ shdr = (Elf32_Shdr *) ((char *)ehdr + ehdr->e_shoff);
+ char *str_table = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
+
+ // traverse the sections looking for GC_PROC_DEF_SECTION
+
+ for (sh = shdr; sh < &shdr[ehdr->e_shnum]; sh++){
+ if (0){
+ fprintf(stderr, "section name: %s (start: 0x%04x, size: 0x%04x)\n",
+ str_table + sh->sh_name, sh->sh_offset, sh->sh_size);
+ }
+
+ if (strcmp(GC_PROC_DEF_SECTION, str_table+sh->sh_name) == 0){
+ *table = (struct gc_proc_def *)((char *)ehdr + sh->sh_offset);
+ if (sh->sh_size % (sizeof(struct gc_proc_def)) != 0){
+ fprintf(stderr, "gcpd: %s section has invalid format\n", GC_PROC_DEF_SECTION);
+ return false;
+ }
+ *nentries = sh->sh_size / sizeof(struct gc_proc_def);
+ *ls_addr = sh->sh_addr;
+ return true;
+ }
+ }
+
+ return false;
+}