Imported Upstream version 3.2.2
[debian/gnuradio] / gcell / lib / runtime / gc_proc_def_utils.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gc_proc_def_utils.h>
27 #include <gcell/gc_declare_proc.h>
28 #include <elf.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 static const unsigned char expected[EI_PAD] = {
33   ELFMAG0,
34   ELFMAG1,
35   ELFMAG2,
36   ELFMAG3,
37   ELFCLASS32,
38   ELFDATA2MSB,
39   EV_CURRENT,
40   ELFOSABI_SYSV,
41   0
42 };
43
44
45 /*
46  * Basically we're going to find the GC_PROC_DEF_SECTION section
47  * in the ELF file and return a pointer to it.  The only things in that
48  * section are gc_proc_def's
49  */
50 bool 
51 gcpd_find_table(spe_program_handle_t *handle,
52                 struct gc_proc_def **table, int *nentries, uint32_t *ls_addr)
53 {
54   if (!handle || !table || !nentries)
55     return false;
56
57   *table = 0;
58   *nentries = 0;
59   
60   Elf32_Ehdr *ehdr = (Elf32_Ehdr *)handle->elf_image;
61   if (!ehdr){
62     fprintf(stderr, "gcpd: No ELF image has been loaded\n");
63     return false;
64   }
65
66   // quick check that we're looking at a SPE EXEC object
67
68   if (memcmp(ehdr->e_ident, expected, EI_PAD) != 0){
69     fprintf(stderr, "gcpd: invalid ELF header\n");
70     return false;
71   }
72
73   if (ehdr->e_machine != 0x17){         // confirm machine type (EM_SPU)
74     fprintf(stderr, "gcpd: not an SPE ELF object\n");
75     return false;
76   }
77
78   if (ehdr->e_type != ET_EXEC){
79     fprintf(stderr, "gcpd: invalid SPE ELF type.\n");
80     fprintf(stderr, "gcpd: SPE type %d != %d\n", ehdr->e_type, ET_EXEC);
81     return false;
82   }
83
84   // find the section header table
85
86   Elf32_Shdr *shdr;
87   Elf32_Shdr *sh;
88
89   if (ehdr->e_shentsize != sizeof (*shdr)){
90     fprintf(stderr, "gcpd: invalid section header format.\n");
91     return false;
92   }
93
94   if (ehdr->e_shnum == 0){
95     fprintf(stderr, "gcpd: no section headers in file.\n");
96     return false;
97   }
98
99   shdr = (Elf32_Shdr *) ((char *)ehdr + ehdr->e_shoff);
100   char *str_table = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
101
102   // traverse the sections looking for GC_PROC_DEF_SECTION
103   
104   for (sh = shdr; sh < &shdr[ehdr->e_shnum]; sh++){
105     if (0){
106       fprintf(stderr, "section name: %s (start: 0x%04x, size: 0x%04x)\n",
107               str_table + sh->sh_name, sh->sh_offset, sh->sh_size);
108     }
109
110     if (strcmp(GC_PROC_DEF_SECTION, str_table+sh->sh_name) == 0){
111       *table = (struct gc_proc_def *)((char *)ehdr + sh->sh_offset);
112       if (sh->sh_size % (sizeof(struct gc_proc_def)) != 0){
113         fprintf(stderr, "gcpd: %s section has invalid format\n", GC_PROC_DEF_SECTION);
114         return false;
115       }
116       *nentries = sh->sh_size / sizeof(struct gc_proc_def);
117       *ls_addr = sh->sh_addr;
118       return true;
119     }
120   }
121
122   return false;
123 }