Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/coffelf.c
2 views
1
/* Copyright 2007 Theo Berkau
2
Copyright 2009 Lawrence Sebald
3
4
This file is part of Yabause.
5
6
Yabause is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
11
Yabause is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with Yabause; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include "core.h"
22
#include "debug.h"
23
#include "sh2core.h"
24
#include "yabause.h"
25
#include "coffelf.h"
26
27
typedef struct
28
{
29
u8 magic[2];
30
u16 numsections;
31
u32 timedate;
32
u32 symtabptr;
33
u32 numsymtabs;
34
u16 optheader;
35
u16 flags;
36
} coff_header_struct;
37
38
typedef struct
39
{
40
u8 magic[2];
41
u16 versionstamp;
42
u32 textsize;
43
u32 datasize;
44
u32 bsssize;
45
u32 entrypoint;
46
u32 textaddr;
47
u32 dataaddr;
48
} aout_header_struct;
49
50
typedef struct
51
{
52
s8 name[8];
53
u32 physaddr;
54
u32 virtaddr;
55
u32 sectionsize;
56
u32 sectionptr;
57
u32 relptr;
58
u32 linenoptr;
59
u16 numreloc;
60
u16 numlineno;
61
u32 flags;
62
} section_header_struct;
63
64
typedef struct
65
{
66
u8 ident[16];
67
u16 type;
68
u16 machine;
69
u32 version;
70
u32 entry;
71
u32 phdr;
72
u32 shdr;
73
u32 flags;
74
u16 hdrsize;
75
u16 phdrsize;
76
u16 phdrcount;
77
u16 shdrsize;
78
u16 shdrcount;
79
u16 shdrstridx;
80
} elf_header_struct;
81
82
#define ELF_MACHINE_SH 42
83
84
typedef struct
85
{
86
u32 name;
87
u32 type;
88
u32 flags;
89
u32 addr;
90
u32 offs;
91
u32 size;
92
u32 link;
93
u32 inf;
94
u32 align;
95
u32 esize;
96
} elf_section_header_struct;
97
98
#define ELF_SECTION_TYPE_NODATA 8
99
#define ELF_SECTION_FLAG_ALLOC 2
100
101
#define WordSwap(x) x = ((x & 0xFF00) >> 8) + ((x & 0x00FF) << 8);
102
#define DoubleWordSwap(x) x = (((x & 0xFF000000) >> 24) + \
103
((x & 0x00FF0000) >> 8) + \
104
((x & 0x0000FF00) << 8) + \
105
((x & 0x000000FF) << 24));
106
107
//////////////////////////////////////////////////////////////////////////////
108
109
int MappedMemoryLoadCoff(const char *filename)
110
{
111
coff_header_struct coff_header;
112
aout_header_struct aout_header;
113
section_header_struct *section_headers=NULL;
114
FILE *fp;
115
u8 *buffer;
116
u32 i, j;
117
118
if ((fp = fopen(filename, "rb")) == NULL)
119
return -1;
120
121
fread((void *)&coff_header, sizeof(coff_header), 1, fp);
122
#ifndef WORDS_BIGENDIAN
123
WordSwap(coff_header.numsections);
124
DoubleWordSwap(coff_header.timedate);
125
DoubleWordSwap(coff_header.timedate);
126
DoubleWordSwap(coff_header.symtabptr);
127
DoubleWordSwap(coff_header.numsymtabs);
128
WordSwap(coff_header.optheader);
129
WordSwap(coff_header.flags);
130
#endif
131
132
if (coff_header.magic[0] != 0x05 || coff_header.magic[1] != 0x00 ||
133
coff_header.optheader != sizeof(aout_header))
134
{
135
// Not SH COFF or is missing the optional header
136
fclose(fp);
137
return -1;
138
}
139
140
fread((void *)&aout_header, sizeof(aout_header), 1, fp);
141
#ifndef WORDS_BIGENDIAN
142
WordSwap(aout_header.versionstamp);
143
DoubleWordSwap(aout_header.textsize);
144
DoubleWordSwap(aout_header.datasize);
145
DoubleWordSwap(aout_header.bsssize);
146
DoubleWordSwap(aout_header.entrypoint);
147
DoubleWordSwap(aout_header.textaddr);
148
DoubleWordSwap(aout_header.dataaddr);
149
#endif
150
151
// Read in each section header
152
if ((section_headers = (section_header_struct *)malloc(sizeof(section_header_struct) * coff_header.numsections)) == NULL)
153
{
154
fclose(fp);
155
return -2;
156
}
157
158
// read in section headers
159
for (i = 0; i < coff_header.numsections; i++)
160
{
161
fread((void *)&section_headers[i], sizeof(section_header_struct), 1, fp);
162
#ifndef WORDS_BIGENDIAN
163
DoubleWordSwap(section_headers[i].physaddr);
164
DoubleWordSwap(section_headers[i].virtaddr);
165
DoubleWordSwap(section_headers[i].sectionsize);
166
DoubleWordSwap(section_headers[i].sectionptr);
167
DoubleWordSwap(section_headers[i].relptr);
168
DoubleWordSwap(section_headers[i].linenoptr);
169
WordSwap(section_headers[i].numreloc);
170
WordSwap(section_headers[i].numlineno);
171
DoubleWordSwap(section_headers[i].flags);
172
#endif
173
}
174
175
YabauseResetNoLoad();
176
177
// Setup the vector table area, etc.
178
YabauseSpeedySetup();
179
180
// Read in sections, load them to ram
181
for (i = 0; i < coff_header.numsections; i++)
182
{
183
if (section_headers[i].sectionsize == 0 ||
184
section_headers[i].sectionptr == 0)
185
// Skip to the next section
186
continue;
187
188
if ((buffer = (u8 *)malloc(section_headers[i].sectionsize)) == NULL)
189
{
190
fclose(fp);
191
free(section_headers);
192
return -2;
193
}
194
195
fseek(fp, section_headers[i].sectionptr, SEEK_SET);
196
fread((void *)buffer, 1, section_headers[i].sectionsize, fp);
197
198
for (j = 0; j < section_headers[i].sectionsize; j++)
199
MappedMemoryWriteByte(section_headers[i].physaddr+j, buffer[j]);
200
SH2WriteNotify(section_headers[i].physaddr,
201
section_headers[i].sectionsize);
202
203
free(buffer);
204
}
205
206
// Clean up
207
free(section_headers);
208
fclose(fp);
209
210
SH2GetRegisters(MSH2, &MSH2->regs);
211
MSH2->regs.PC = aout_header.entrypoint;
212
SH2SetRegisters(MSH2, &MSH2->regs);
213
return 0;
214
}
215
216
217
//////////////////////////////////////////////////////////////////////////////
218
219
int MappedMemoryLoadElf(const char *filename)
220
{
221
elf_header_struct elf_hdr;
222
elf_section_header_struct *sections = NULL;
223
FILE *fp;
224
u16 i;
225
u32 j;
226
u8 *buffer;
227
228
fp = fopen(filename, "rb");
229
230
if(fp == NULL)
231
return -1;
232
233
fread(&elf_hdr, sizeof(elf_header_struct), 1, fp);
234
235
if(elf_hdr.ident[0] != 0x7F || elf_hdr.ident[1] != 'E' ||
236
elf_hdr.ident[2] != 'L' || elf_hdr.ident[3] != 'F' ||
237
elf_hdr.ident[4] != 1)
238
{
239
/* Doesn't appear to be a valid ELF file. */
240
fclose(fp);
241
return -1;
242
}
243
244
if(elf_hdr.ident[5] != 2)
245
{
246
/* Doesn't appear to be a big-endian file. */
247
fclose(fp);
248
return -1;
249
}
250
251
#ifndef WORDS_BIGENDIAN
252
WordSwap(elf_hdr.type);
253
WordSwap(elf_hdr.machine);
254
DoubleWordSwap(elf_hdr.version);
255
DoubleWordSwap(elf_hdr.entry);
256
DoubleWordSwap(elf_hdr.phdr);
257
DoubleWordSwap(elf_hdr.shdr);
258
DoubleWordSwap(elf_hdr.flags);
259
WordSwap(elf_hdr.hdrsize);
260
WordSwap(elf_hdr.phdrsize);
261
WordSwap(elf_hdr.phdrcount);
262
WordSwap(elf_hdr.shdrsize);
263
WordSwap(elf_hdr.shdrcount);
264
WordSwap(elf_hdr.shdrstridx);
265
#endif
266
267
LOG("Loading ELF file %s\n", filename);
268
LOG("Type: %d\n", elf_hdr.type);
269
LOG("Machine code: %d\n", elf_hdr.machine);
270
LOG("Version: %d\n", elf_hdr.version);
271
LOG("Entry point: 0x%08X\n", elf_hdr.entry);
272
LOG("Program header offset: %d\n", elf_hdr.phdr);
273
LOG("Section header offset: %d\n", elf_hdr.shdr);
274
LOG("Flags: %d\n", elf_hdr.flags);
275
LOG("ELF Header Size: %d\n", elf_hdr.hdrsize);
276
LOG("Program header size: %d\n", elf_hdr.phdrsize);
277
LOG("Program header count: %d\n", elf_hdr.phdrcount);
278
LOG("Section header size: %d\n", elf_hdr.shdrsize);
279
LOG("Section header count: %d\n", elf_hdr.shdrcount);
280
LOG("String table section: %d\n", elf_hdr.shdrstridx);
281
282
if(elf_hdr.machine != ELF_MACHINE_SH)
283
{
284
/* Not a SuperH ELF file. */
285
fclose(fp);
286
return -1;
287
}
288
289
/* Allocate space for the section headers. */
290
sections =
291
(elf_section_header_struct *)malloc(sizeof(elf_section_header_struct) *
292
elf_hdr.shdrcount);
293
if(sections == NULL)
294
{
295
fclose(fp);
296
return -2;
297
}
298
299
/* Look at the actual section headers. */
300
fseek(fp, elf_hdr.shdr, SEEK_SET);
301
302
/* Read in each section header. */
303
for(i = 0; i < elf_hdr.shdrcount; ++i)
304
{
305
fread(sections + i, sizeof(elf_section_header_struct), 1, fp);
306
#ifndef WORDS_BIGENDIAN
307
DoubleWordSwap(sections[i].name);
308
DoubleWordSwap(sections[i].type);
309
DoubleWordSwap(sections[i].flags);
310
DoubleWordSwap(sections[i].addr);
311
DoubleWordSwap(sections[i].offs);
312
DoubleWordSwap(sections[i].size);
313
DoubleWordSwap(sections[i].link);
314
DoubleWordSwap(sections[i].inf);
315
DoubleWordSwap(sections[i].align);
316
DoubleWordSwap(sections[i].esize);
317
#endif
318
319
LOG("Section header %d:\n", i);
320
LOG("Name index: %d\n", sections[i].name);
321
LOG("Type: %d\n", sections[i].type);
322
LOG("Flags: 0x%X\n", sections[i].flags);
323
LOG("In-memory address: 0x%08X\n", sections[i].addr);
324
LOG("In-file offset: %d\n", sections[i].offs);
325
LOG("Size: %d\n", sections[i].size);
326
LOG("Link field: %d\n", sections[i].link);
327
LOG("Info field: %d\n", sections[i].inf);
328
LOG("Alignment: %d\n", sections[i].align);
329
LOG("Entry size: %d\n", sections[i].esize);
330
}
331
332
YabauseResetNoLoad();
333
334
/* Set up the vector table area, etc. */
335
YabauseSpeedySetup();
336
337
/* Read in the sections and load them to RAM. */
338
for(i = 0; i < elf_hdr.shdrcount; ++i)
339
{
340
/* Does the header request actual storage for this section? */
341
if(sections[i].flags & ELF_SECTION_FLAG_ALLOC)
342
{
343
/* Check if the section contains data, or if its just a marker for a
344
section of zero bytes. */
345
if(sections[i].type == ELF_SECTION_TYPE_NODATA)
346
{
347
for(j = 0; j < sections[i].size; ++j)
348
{
349
MappedMemoryWriteByte(sections[i].addr + j, 0);
350
}
351
}
352
else
353
{
354
buffer = (u8 *)malloc(sections[i].size);
355
356
if(buffer == NULL)
357
{
358
fclose(fp);
359
free(sections);
360
return -2;
361
}
362
363
fseek(fp, sections[i].offs, SEEK_SET);
364
fread(buffer, 1, sections[i].size, fp);
365
366
for(j = 0; j < sections[i].size; ++j)
367
{
368
MappedMemoryWriteByte(sections[i].addr + j, buffer[j]);
369
}
370
371
free(buffer);
372
}
373
}
374
}
375
376
/* Clean up. */
377
free(sections);
378
fclose(fp);
379
380
/* Set up our entry point. */
381
SH2GetRegisters(MSH2, &MSH2->regs);
382
MSH2->regs.PC = elf_hdr.entry;
383
SH2SetRegisters(MSH2, &MSH2->regs);
384
385
return 0;
386
}
387
388
//////////////////////////////////////////////////////////////////////////////
389
390