/[pcsx2_0.9.7]/trunk/pcsx2/Elfheader.cpp
ViewVC logotype

Contents of /trunk/pcsx2/Elfheader.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 14221 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "Common.h"
18
19 #include "GS.h" // for sending game crc to mtgs
20 #include "Elfheader.h"
21
22 using namespace std;
23
24 u32 ElfCRC;
25 u32 ElfEntry;
26 wxString LastELF;
27
28 #if 0
29 // fixme: ELF command line option system.
30 // It parses a command line and pastes it into PS2 memory, and then points the a0 register at it.
31 // A user-written ELF can then load the data and respond accordingly. Needs a rewrite using modern
32 // string parsing utils. :)
33
34 //2002-09-19 (Florin)
35 char args[256]="ez.m2v"; //to be accessed by other files
36 uptr args_ptr; //a big value; in fact, it is an address
37
38 static bool isEmpty(int addr)
39 {
40 return ((eeMem->Main[addr] == 0) || (eeMem->Main[addr] == 32));
41 }
42
43 //in a0 is passed the address of the command line args,
44 //i.e. a pointer to an area like this:
45 //+00 unknown/unused
46 //+04 argc; number of arguments
47 //+08 argv[0]; address of the first parameter - program name (char*) -
48 //+08 argv[1]; address of the second parameter (char*) |
49 //+0C argv[2]; and so on |
50 //........ |
51 //+08+4*argc the program name(first param) <--
52 //+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args'
53 // see above 'char args[256];'
54
55 // The results of this function will normally be that it finds an arg at 13 chars, and another at 0.
56 // It'd probably be easier to 0 out all 256 chars, split args, copy all the arguments in, and note
57 // the locations of each split... --arcum42
58
59 static uint parseCommandLine( const wxString& filename )
60 {
61 if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > (4 + 4 + 256) ) )
62 {
63 const char *p;
64 int argc, i, ret = 0;
65 u32 args_end;
66
67 args_ptr -= 256;
68
69 args[ 255 ] = 0;
70
71 // Copy the parameters into the section of memory at args_ptr,
72 // then zero out anything past the end of args till 256 chars is reached.
73 memcpy( &eeMem->Main[ args_ptr ], args, 256 );
74 memset( &eeMem->Main[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) );
75 args_end = args_ptr + strlen( args );
76
77 // Set p to just the filename, no path.
78 #ifdef _WIN32
79 p = strrchr( filename, '\\' );
80 #else //linux
81 p = strrchr( filename, '/' );
82 if( p == NULL ) p = strchr(filename, '\\');
83 #endif
84 if (p)
85 p++;
86 else
87 p = filename;
88
89
90 args_ptr -= strlen( p ) + 1;
91
92 //fill param 0; i.e. name of the program
93 strcpy( (char*)&eeMem->Main[ args_ptr ], p );
94
95 // Start from the end of where we wrote to, not including all the zero'd out area.
96 for ( i = args_end - args_ptr + 1, argc = 0; i > 0; i-- )
97 {
98 while (i && isEmpty(args_ptr + i )) { i--; }
99
100 // If the last char is a space, set it to 0.
101 if ( eeMem->Main[ args_ptr + i + 1 ] == ' ') eeMem->Main[ args_ptr + i + 1 ] = 0;
102
103 while (i && !isEmpty(args_ptr + i )) { i--; }
104
105 // Now that we've gone back a word, increase the number of arguments,
106 // and mark the location of the argument.
107 if (!isEmpty(args_ptr + i )) // i <= 0
108 {
109 // If the spot we are on is not a space or null , use it.
110 argc++;
111 ret = args_ptr - 4 - 4 - argc * 4;
112
113 if (ret < 0 ) return 0;
114 ((u32*)eeMem->Main)[ args_ptr / 4 - argc ] = args_ptr + i;
115 }
116 else
117 {
118 if (!isEmpty(args_ptr + i + 1))
119 {
120 // Otherwise, use the next character .
121 argc++;
122 ret = args_ptr - 4 - 4 - argc * 4;
123
124 if (ret < 0 ) return 0;
125 ((u32*)eeMem->Main)[ args_ptr / 4 - argc ] = args_ptr + i + 1;
126 }
127 }
128 }
129
130 // Pass the number of arguments, and if we have arguments.
131 ((u32*)eeMem->Main)[ args_ptr /4 - argc - 1 ] = argc; //how many args
132 ((u32*)eeMem->Main)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all
133
134 return ret;
135 }
136
137 return 0;
138 }
139 #endif
140 //---------------
141
142 // All of ElfObjects functions.
143 ElfObject::ElfObject(const wxString& srcfile, IsoFile isofile)
144 : filename( srcfile )
145
146 , data( wxULongLong(isofile.getLength()).GetLo(), L"ELF headers" )
147 , header( *(ELF_HEADER*)data.GetPtr() )
148 , proghead( NULL )
149 , secthead( NULL )
150 {
151 isCdvd = true;
152 checkElfSize(data.GetSizeInBytes());
153 readIso(isofile);
154 initElfHeaders();
155 }
156
157 ElfObject::ElfObject( const wxString& srcfile, uint hdrsize )
158 : filename( srcfile )
159 , data( wxULongLong(hdrsize).GetLo(), L"ELF headers" )
160 , header( *(ELF_HEADER*)data.GetPtr() )
161 , proghead( NULL )
162 , secthead( NULL )
163 {
164 isCdvd = false;
165 checkElfSize(data.GetSizeInBytes());
166 readFile();
167 initElfHeaders();
168 }
169
170 void ElfObject::initElfHeaders()
171 {
172 Console.WriteLn( L"Initializing Elf: %d bytes", data.GetSizeInBytes());
173
174 if ( header.e_phnum > 0 )
175 proghead = (ELF_PHR*)&data[header.e_phoff];
176
177 if ( header.e_shnum > 0 )
178 secthead = (ELF_SHR*)&data[header.e_shoff];
179
180 if ( ( header.e_shnum > 0 ) && ( header.e_shentsize != sizeof(ELF_SHR) ) )
181 Console.Error( "(ELF) Size of section headers is not standard" );
182
183 if ( ( header.e_phnum > 0 ) && ( header.e_phentsize != sizeof(ELF_PHR) ) )
184 Console.Error( "(ELF) Size of program headers is not standard" );
185
186 //getCRC();
187
188 const char* elftype = NULL;
189 switch( header.e_type )
190 {
191 default:
192 ELF_LOG( "type: unknown = %x", header.e_type );
193 break;
194
195 case 0x0: elftype = "no file type"; break;
196 case 0x1: elftype = "relocatable"; break;
197 case 0x2: elftype = "executable"; break;
198 }
199
200 if (elftype != NULL) ELF_LOG( "type: %s", elftype );
201
202 const char* machine = NULL;
203
204 switch(header.e_machine)
205 {
206 case 1: machine = "AT&T WE 32100"; break;
207 case 2: machine = "SPARC"; break;
208 case 3: machine = "Intel 80386"; break;
209 case 4: machine = "Motorola 68000"; break;
210 case 5: machine = "Motorola 88000"; break;
211 case 7: machine = "Intel 80860"; break;
212 case 8: machine = "mips_rs3000"; break;
213
214 default:
215 ELF_LOG( "machine: unknown = %x", header.e_machine );
216 break;
217 }
218
219 if (machine != NULL) ELF_LOG( "machine: %s", machine );
220
221 ELF_LOG("version: %d",header.e_version);
222 ELF_LOG("entry: %08x",header.e_entry);
223 ELF_LOG("flags: %08x",header.e_flags);
224 ELF_LOG("eh size: %08x",header.e_ehsize);
225 ELF_LOG("ph off: %08x",header.e_phoff);
226 ELF_LOG("ph entsiz: %08x",header.e_phentsize);
227 ELF_LOG("ph num: %08x",header.e_phnum);
228 ELF_LOG("sh off: %08x",header.e_shoff);
229 ELF_LOG("sh entsiz: %08x",header.e_shentsize);
230 ELF_LOG("sh num: %08x",header.e_shnum);
231 ELF_LOG("sh strndx: %08x",header.e_shstrndx);
232
233 ELF_LOG("\n");
234
235 //applyPatches();
236 }
237
238 bool ElfObject::hasProgramHeaders() { return (proghead != NULL); }
239 bool ElfObject::hasSectionHeaders() { return (secthead != NULL); }
240 bool ElfObject::hasHeaders() { return (hasProgramHeaders() && hasSectionHeaders()); }
241
242 void ElfObject::readIso(IsoFile file)
243 {
244 int rsize = file.read(data.GetPtr(), data.GetSizeInBytes());
245 if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream(filename);
246 }
247
248 void ElfObject::readFile()
249 {
250 int rsize = 0;
251 FILE *f;
252
253 f = fopen( filename.ToUTF8(), "rb" );
254 if (f == NULL) Exception::FileNotFound( filename );
255
256 fseek(f, 0, SEEK_SET);
257 rsize = fread(data.GetPtr(), 1, data.GetSizeInBytes(), f);
258 fclose( f );
259
260 if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream(filename);
261 }
262
263 void ElfObject::checkElfSize(s64 elfsize)
264 {
265 if (elfsize > 0xfffffff)
266 throw Exception::BadStream(filename).SetBothMsgs(wxLt("Illegal ELF file size over 2GB!"));
267
268 if (elfsize == -1)
269 throw Exception::BadStream(filename).SetBothMsgs(wxLt("ELF file does not exist!"));
270
271 if (elfsize == 0)
272 throw Exception::BadStream(filename).SetBothMsgs(wxLt("Unexpected end of ELF file."));
273 }
274
275 u32 ElfObject::getCRC()
276 {
277 u32 CRC = 0;
278
279 const u32* srcdata = (u32*)data.GetPtr();
280 for(u32 i=data.GetSizeInBytes()/4; i; --i, ++srcdata)
281 CRC ^= *srcdata;
282
283 return CRC;
284 }
285
286 void ElfObject::loadProgramHeaders()
287 {
288 if (proghead == NULL) return;
289
290 for( int i = 0 ; i < header.e_phnum ; i++ )
291 {
292 ELF_LOG( "Elf32 Program Header" );
293 ELF_LOG( "type: " );
294
295 switch(proghead[ i ].p_type)
296 {
297 default:
298 ELF_LOG( "unknown %x", (int)proghead[ i ].p_type );
299 break;
300
301 case 0x1:
302 {
303 ELF_LOG("load");
304 const uint elfsize = data.GetLength();
305
306 if (proghead[ i ].p_offset < elfsize)
307 {
308 int size;
309
310 if ((proghead[ i ].p_filesz + proghead[ i ].p_offset) > elfsize)
311 size = elfsize - proghead[ i ].p_offset;
312 else
313 size = proghead[ i ].p_filesz;
314
315 if (proghead[ i ].p_vaddr != proghead[ i ].p_paddr)
316 Console.Warning( "ElfProgram different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x",
317 proghead[ i ].p_paddr, proghead[ i ].p_vaddr);
318
319 // used to be paddr
320 memcpy_fast(
321 &eeMem->Main[proghead[ i ].p_vaddr & 0x1ffffff],
322 data.GetPtr(proghead[ i ].p_offset), size
323 );
324
325 ELF_LOG("\t*LOADED*");
326 }
327 }
328 break;
329 }
330
331 ELF_LOG("\n");
332 ELF_LOG("offset: %08x",proghead[i].p_offset);
333 ELF_LOG("vaddr: %08x",proghead[i].p_vaddr);
334 ELF_LOG("paddr: %08x",proghead[i].p_paddr);
335 ELF_LOG("file size: %08x",proghead[i].p_filesz);
336 ELF_LOG("mem size: %08x",proghead[i].p_memsz);
337 ELF_LOG("flags: %08x",proghead[i].p_flags);
338 ELF_LOG("palign: %08x",proghead[i].p_align);
339 ELF_LOG("\n");
340 }
341 }
342
343 void ElfObject::loadSectionHeaders()
344 {
345 if (secthead == NULL || header.e_shoff > (u32)data.GetLength()) return;
346
347 const u8* sections_names = data.GetPtr( secthead[ (header.e_shstrndx == 0xffff ? 0 : header.e_shstrndx) ].sh_offset );
348
349 int i_st = -1, i_dt = -1;
350
351 for( int i = 0 ; i < header.e_shnum ; i++ )
352 {
353 ELF_LOG( "ELF32 Section Header [%x] %s", i, &sections_names[ secthead[ i ].sh_name ] );
354
355 // used by parseCommandLine
356 //if ( secthead[i].sh_flags & 0x2 )
357 // args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff );
358
359 ELF_LOG("\n");
360
361 const char* sectype = NULL;
362 switch(secthead[ i ].sh_type)
363 {
364 case 0x0: sectype = "null"; break;
365 case 0x1: sectype = "progbits"; break;
366 case 0x2: sectype = "symtab"; break;
367 case 0x3: sectype = "strtab"; break;
368 case 0x4: sectype = "rela"; break;
369 case 0x8: sectype = "no bits"; break;
370 case 0x9: sectype = "rel"; break;
371
372 default:
373 ELF_LOG("type: unknown %08x",secthead[i].sh_type);
374 break;
375 }
376
377 ELF_LOG("type: %s", sectype);
378 ELF_LOG("flags: %08x", secthead[i].sh_flags);
379 ELF_LOG("addr: %08x", secthead[i].sh_addr);
380 ELF_LOG("offset: %08x", secthead[i].sh_offset);
381 ELF_LOG("size: %08x", secthead[i].sh_size);
382 ELF_LOG("link: %08x", secthead[i].sh_link);
383 ELF_LOG("info: %08x", secthead[i].sh_info);
384 ELF_LOG("addralign: %08x", secthead[i].sh_addralign);
385 ELF_LOG("entsize: %08x", secthead[i].sh_entsize);
386 // dump symbol table
387
388 if (secthead[ i ].sh_type == 0x02)
389 {
390 i_st = i;
391 i_dt = secthead[i].sh_link;
392 }
393 }
394
395 if ((i_st >= 0) && (i_dt >= 0))
396 {
397 const char * SymNames;
398 Elf32_Sym * eS;
399
400 SymNames = (char*)data.GetPtr(secthead[i_dt].sh_offset);
401 eS = (Elf32_Sym*)data.GetPtr(secthead[i_st].sh_offset);
402 Console.WriteLn("found %d symbols", secthead[i_st].sh_size / sizeof(Elf32_Sym));
403
404 for(uint i = 1; i < (secthead[i_st].sh_size / sizeof(Elf32_Sym)); i++) {
405 if ((eS[i].st_value != 0) && (ELF32_ST_TYPE(eS[i].st_info) == 2))
406 {
407 R5900::disR5900AddSym(eS[i].st_value, &SymNames[eS[i].st_name]);
408 }
409 }
410 }
411 }
412
413 void ElfObject::loadHeaders()
414 {
415 loadProgramHeaders();
416 loadSectionHeaders();
417 }
418
419 // return value:
420 // 0 - Invalid or unknown disc.
421 // 1 - PS1 CD
422 // 2 - PS2 CD
423 int GetPS2ElfName( wxString& name )
424 {
425 int retype = 0;
426
427 try {
428 IsoFSCDVD isofs;
429 IsoFile file( isofs, L"SYSTEM.CNF;1");
430
431 int size = file.getLength();
432 if( size == 0 ) return 0;
433
434 while( !file.eof() )
435 {
436 const wxString original( fromUTF8(file.readLine().c_str()) );
437 const ParsedAssignmentString parts( original );
438
439 if( parts.lvalue.IsEmpty() && parts.rvalue.IsEmpty() ) continue;
440 if( parts.rvalue.IsEmpty() )
441 {
442 Console.Warning( "(SYSTEM.CNF) Unusual or malformed entry in SYSTEM.CNF ignored:" );
443 Console.Indent().WriteLn( original );
444 continue;
445 }
446
447 if( parts.lvalue == L"BOOT2" )
448 {
449 name = parts.rvalue;
450 Console.WriteLn( Color_StrongBlue, L"(SYSTEM.CNF) Detected PS2 Disc = " + name );
451 retype = 2;
452 }
453 else if( parts.lvalue == L"BOOT" )
454 {
455 name = parts.rvalue;
456 Console.WriteLn( Color_StrongBlue, L"(SYSTEM.CNF) Detected PSX/PSone Disc = " + name );
457 retype = 1;
458 }
459 else if( parts.lvalue == L"VMODE" )
460 {
461 Console.WriteLn( Color_Blue, L"(SYSTEM.CNF) Disc region type = " + parts.rvalue );
462 }
463 else if( parts.lvalue == L"VER" )
464 {
465 Console.WriteLn( Color_Blue, L"(SYSTEM.CNF) Software version = " + parts.rvalue );
466 }
467 }
468
469 if( retype == 0 )
470 {
471 Console.Error("(GetElfName) Disc image is *not* a Playstation or PS2 game!");
472 return 0;
473 }
474 }
475 catch (Exception::BadStream& ex)
476 {
477 Console.Error(ex.FormatDiagnosticMessage());
478 return 0; // ISO error
479 }
480 catch( Exception::FileNotFound& )
481 {
482 //Console.Warning(ex.FormatDiagnosticMessage());
483 return 0; // no SYSTEM.CNF, not a PS1/PS2 disc.
484 }
485
486 #ifdef PCSX2_DEVBUILD
487 FILE *fp;
488 int i;
489 char buffer[512];
490
491 fp = fopen("System.map", "r");
492 if( fp == NULL ) return 2;
493
494 u32 addr;
495
496 Console.WriteLn("Loading System.map...");
497 while (!feof(fp)) {
498 fseek(fp, 8, SEEK_CUR);
499 buffer[0] = '0'; buffer[1] = 'x';
500 for (i=2; i<10; i++) buffer[i] = fgetc(fp); buffer[i] = 0;
501 addr = strtoul(buffer, (char**)NULL, 0);
502 fseek(fp, 3, SEEK_CUR);
503 for (i=0; i<512; i++) {
504 buffer[i] = fgetc(fp);
505 if (buffer[i] == '\n' || buffer[i] == 0) break;
506 }
507 if (buffer[i] == 0) break;
508 buffer[i] = 0;
509
510 R5900::disR5900AddSym(addr, buffer);
511 }
512 fclose(fp);
513 #endif
514
515 return retype;
516 }

  ViewVC Help
Powered by ViewVC 1.1.22