1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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;
}
|