forked from raburton/esptool2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathesptool2_elf.c
183 lines (155 loc) · 5.48 KB
/
esptool2_elf.c
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/**********************************************************************************
*
* Copyright (c) 2015 Richard A Burton <[email protected]>
*
* This file is part of esptool2.
*
* esptool2 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 of the License, or
* (at your option) any later version.
*
* esptool2 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 esptool2. If not, see <http://www.gnu.org/licenses/>.
*
**********************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "esptool2.h"
#include "esptool2_elf.h"
// Find a section in an elf file by name.
// Returns pointer to section if found, else returns zero.
// Does not produce any messages.
MyElf_Section* GetElfSection(MyElf_File *elf, char *name) {
int i;
for(i = 0; i < elf->header.e_shnum - 1; i++) {
if(!strcmp(name, elf->sections[i].name)) {
debug("Found section '%s'.\r\n", name);
return &elf->sections[i];
}
}
debug("Could not find section '%s'.\r\n", name);
return 0;
}
// Reads an elf section (actual data) from the elf file.
// Returns a pointer to newly allocated memory (or zero on error),
// which should be freed by the caller when finished with.
// Produces error message on failure (so caller doesn't need to).
unsigned char* GetElfSectionData(MyElf_File *elf, MyElf_Section *section) {
unsigned char *data = 0;
if (section->size && section->offset) {
data = (unsigned char*)malloc(section->size);
if(!data) {
error("Error: Out of memory!\r\n");
return 0;
}
if(fseek(elf->fd, section->offset, SEEK_SET) ||
fread(data, 1, section->size, elf->fd) != section->size) {
error("Error: Can't read section '%s' data from elf file.\r\n", section->name);
free(data);
return 0;
}
} else {
error("Error: Section '%s' has no data to read.\r\n", section->name);
}
return data;
}
// Opens an elf file and reads the string table and file & section headers.
// Returns a pointer to a MyElf_File structure (or zero on error).
// UnloadElf should be called to dispose of the MyElf_File structure.
// Produces error message on failure (so caller doesn't need to).
MyElf_File* LoadElf(char *infile) {
int i;
MyElf_File *elf;
Elf32_Shdr temp;
// allocate the elf structure
elf = (MyElf_File*)malloc(sizeof(MyElf_File));
if(!elf) {
error("Error: Out of memory!\r\n");
goto error_exit;
}
memset(elf, 0, sizeof(MyElf_File));
// open the file
elf->fd = fopen(infile, "rb");
if(!elf->fd) {
error("Error: Can't open elf file '%s'.\r\n", infile);
goto error_exit;
}
// read the header
if(fread(&elf->header, 1, sizeof(Elf32_Ehdr), elf->fd) != sizeof(Elf32_Ehdr)) {
error("Error: Can't read elf file header.\r\n");
goto error_exit;
}
// check the file header
if (memcmp(elf->header.e_ident, "\x7f" "ELF", 4)) {
error("Error: Input files doesn't look like an elf file (bad header).\r\n");
goto error_exit;
}
// is there a string table section (we need one)
if(!elf->header.e_shstrndx) {
error("Error: Elf file does not contain a string table.\r\n");
goto error_exit;
}
// get the string table section header
if(fseek(elf->fd, elf->header.e_shoff + (elf->header.e_shentsize * elf->header.e_shstrndx), SEEK_SET) ||
fread(&temp, 1, sizeof(Elf32_Shdr), elf->fd) != sizeof(Elf32_Shdr)) {
error("Error: Can't read string table section from elf file.\r\n");
goto error_exit;
}
// read the actual string table
if(!temp.sh_size) {
error("Error: Elf file contains an empty string table.\r\n");
goto error_exit;
}
elf->strings = (char*)malloc(temp.sh_size);
if(!elf->strings) {
error("Error: Out of memory!\r\n");
goto error_exit;
}
if(fseek(elf->fd, temp.sh_offset, SEEK_SET) ||
fread(elf->strings, 1, temp.sh_size, elf->fd) != temp.sh_size) {
error("Error: Failed to read string stable from elf file.\r\n");
goto error_exit;
}
// read section headers
elf->sections = (MyElf_Section*)malloc(sizeof(MyElf_Section) * elf->header.e_shnum);
if(!elf->sections) {
error("Error: Out of memory!\r\n");
goto error_exit;
}
for(i = 1; i < elf->header.e_shnum; i++) {
if(fseek(elf->fd, elf->header.e_shoff + (elf->header.e_shentsize * i), SEEK_SET)
|| fread(&temp, 1, sizeof(Elf32_Shdr), elf->fd) != sizeof(Elf32_Shdr)) {
error("Error: Can't read section %d from elf file.\r\n", i);
break;
}
debug("Read section %d '%s'.\r\n", i, elf->strings + temp.sh_name);
elf->sections[i-1].address = temp.sh_addr;
elf->sections[i-1].offset = temp.sh_offset;
elf->sections[i-1].size = temp.sh_size;
elf->sections[i-1].name = elf->strings + temp.sh_name;
}
return elf;
error_exit:
if (elf) {
if (elf->fd) fclose(elf->fd);
if (elf->strings) free(elf->strings);
free(elf);
}
return 0;
}
// Close an elf file and dispose of the MyElf_File structure.
void UnloadElf(MyElf_File *elf) {
if (elf) {
debug("Unloading elf file.\r\n");
if(elf->fd) fclose(elf->fd);
if(elf->strings) free(elf->strings);
if(elf->sections) free(elf->sections);
free(elf);
}
}