[Scummvm-cvs-logs] SF.net SVN: scummvm:[51818] scummvm/branches/gsoc2010-plugins/backends

toneman1138 at users.sourceforge.net toneman1138 at users.sourceforge.net
Sat Aug 7 02:40:15 CEST 2010


Revision: 51818
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51818&view=rev
Author:   toneman1138
Date:     2010-08-07 00:40:15 +0000 (Sat, 07 Aug 2010)

Log Message:
-----------
made MIPSDLObject and PS2 plugin provider that uses it

Modified Paths:
--------------
    scummvm/branches/gsoc2010-plugins/backends/module.mk
    scummvm/branches/gsoc2010-plugins/backends/platform/ps2/Makefile.ps2
    scummvm/branches/gsoc2010-plugins/backends/platform/ps2/systemps2.cpp
    scummvm/branches/gsoc2010-plugins/backends/plugins/arm-loader.cpp
    scummvm/branches/gsoc2010-plugins/backends/plugins/ds/ds-provider.cpp

Added Paths:
-----------
    scummvm/branches/gsoc2010-plugins/backends/plugins/mips-loader.cpp

Removed Paths:
-------------
    scummvm/branches/gsoc2010-plugins/backends/plugins/mips-relocs.cpp

Modified: scummvm/branches/gsoc2010-plugins/backends/module.mk
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/module.mk	2010-08-07 00:34:38 UTC (rev 51817)
+++ scummvm/branches/gsoc2010-plugins/backends/module.mk	2010-08-07 00:40:15 UTC (rev 51818)
@@ -37,6 +37,7 @@
 	plugins/sdl/sdl-provider.o \
 	plugins/win32/win32-provider.o \
 	plugins/psp/psp-provider.o \
+	plugins/ps2/ps2-provider.o \
 	plugins/gp2xwiz/gp2xwiz-provider.o \
 	saves/savefile.o \
 	saves/default/default-saves.o \

Modified: scummvm/branches/gsoc2010-plugins/backends/platform/ps2/Makefile.ps2
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/platform/ps2/Makefile.ps2	2010-08-07 00:34:38 UTC (rev 51817)
+++ scummvm/branches/gsoc2010-plugins/backends/platform/ps2/Makefile.ps2	2010-08-07 00:40:15 UTC (rev 51818)
@@ -77,7 +77,7 @@
 
 TARGET = elf/scummvm.elf
 
-DEFINES  += -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -DDISABLE_SAVEGAME_SORTING -D_EE -D__PLAYSTATION2__ -DELF_LOADER_TARGET -G2 -O2 -Wall -Wno-multichar -fno-rtti -fno-exceptions -DNO_ADAPTOR -DNEW_PLUGIN_DESIGN_FIRST_REFINEMENT
+DEFINES  += -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -DDISABLE_SAVEGAME_SORTING -D_EE -D__PLAYSTATION2__ -DELF_LOADER_TARGET -G2 -O2 -Wall -Wno-multichar -fno-rtti -fno-exceptions -DNO_ADAPTOR#-DNEW_PLUGIN_DESIGN_FIRST_REFINEMENT
 
 INCLUDES  = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) 
 INCLUDES += -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines
@@ -112,7 +112,7 @@
 	$(srcdir)/backends/platform/ps2/ps2mutex.o \
 	$(srcdir)/backends/platform/ps2/ps2time.o \
 	$(srcdir)/backends/plugins/elf-loader.o \
-	$(srcdir)/backends/plugins/mips-relocs.o \
+	$(srcdir)/backends/plugins/mips-loader.o \
 	$(srcdir)/backends/plugins/shorts-segment-manager.o \
 	$(srcdir)/backends/platform/ps2/ps2debug.o
 

Modified: scummvm/branches/gsoc2010-plugins/backends/platform/ps2/systemps2.cpp
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/platform/ps2/systemps2.cpp	2010-08-07 00:34:38 UTC (rev 51817)
+++ scummvm/branches/gsoc2010-plugins/backends/platform/ps2/systemps2.cpp	2010-08-07 00:40:15 UTC (rev 51818)
@@ -59,7 +59,7 @@
 #include "backends/platform/ps2/ps2debug.h"
 #include "backends/fs/ps2/ps2-fs-factory.h"
 
-#include "backends/plugins/elf-provider.h"
+#include "backends/plugins/ps2/ps2-provider.h"
 
 #include "backends/saves/default/default-saves.h"
 #include "common/config-manager.h"
@@ -132,7 +132,7 @@
 	g_system = g_systemPs2 = new OSystem_PS2(argv[0]);
 
 #ifdef DYNAMIC_MODULES
-	PluginManager::instance().addPluginProvider(new ELFPluginProvider());
+	PluginManager::instance().addPluginProvider(new PS2PluginProvider());
 #endif
 
 	g_systemPs2->init();

Modified: scummvm/branches/gsoc2010-plugins/backends/plugins/arm-loader.cpp
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/plugins/arm-loader.cpp	2010-08-07 00:34:38 UTC (rev 51817)
+++ scummvm/branches/gsoc2010-plugins/backends/plugins/arm-loader.cpp	2010-08-07 00:40:15 UTC (rev 51818)
@@ -23,7 +23,7 @@
  *
  */
 
-#if defined(DYNAMIC_MODULES) && defined(ARM)
+#if defined(DYNAMIC_MODULES)
 
 #include "backends/fs/ds/ds-fs.h"
 #include "elf-loader.h"
@@ -146,7 +146,7 @@
 		Elf32_Shdr *curShdr = &(shdr[i]);
 
 		if ((curShdr->sh_type == SHT_REL || curShdr->sh_type == SHT_RELA) &&		// Check for a relocation section
-		        curShdr->sh_entsize == sizeof(Elf32_Rel) &&		// Check for proper relocation size
+		        curShdr->sh_entsize == sizeof(Elf32_Rel) &&			// Check for proper relocation size
 		        (int)curShdr->sh_link == _symtab_sect &&			// Check that the sh_link connects to our symbol table
 		        curShdr->sh_info < ehdr->e_shnum &&					// Check that the relocated section exists
 		        (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) {  	// Check if relocated section resides in memory
@@ -166,4 +166,4 @@
 	return true;
 }
 
-#endif /* defined(DYNAMIC_MODULES) && defined(ARM) */
+#endif /* defined(DYNAMIC_MODULES) */

Modified: scummvm/branches/gsoc2010-plugins/backends/plugins/ds/ds-provider.cpp
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/plugins/ds/ds-provider.cpp	2010-08-07 00:34:38 UTC (rev 51817)
+++ scummvm/branches/gsoc2010-plugins/backends/plugins/ds/ds-provider.cpp	2010-08-07 00:40:15 UTC (rev 51818)
@@ -25,17 +25,11 @@
 
 #if defined(DYNAMIC_MODULES) && defined(__DS__)
 
-/*#include "base/plugins.h"
-#include "backends/plugins/dynamic-plugin.h"
-#include "common/fs.h"
-
-#include "backends/plugins/elf-loader.h"*/
 #include "backends/plugins/arm-loader.h"
 #include "backends/plugins/elf-provider.h"
 #include "backends/plugins/ds/ds-provider.h"
 
 
-
 class DSPlugin : public ELFPlugin {
 public:
 	DSPlugin(const Common::String &filename) {

Copied: scummvm/branches/gsoc2010-plugins/backends/plugins/mips-loader.cpp (from rev 51772, scummvm/branches/gsoc2010-plugins/backends/plugins/mips-relocs.cpp)
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/plugins/mips-loader.cpp	                        (rev 0)
+++ scummvm/branches/gsoc2010-plugins/backends/plugins/mips-loader.cpp	2010-08-07 00:40:15 UTC (rev 51818)
@@ -0,0 +1,262 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES)
+
+#include "mips-loader.h"
+
+#define __DEBUG_PLUGINS__
+
+#ifdef __DEBUG_PLUGINS__
+#define DBG(x,...) printf(x, ## __VA_ARGS__)
+#else
+#define DBG(x,...)
+#endif
+
+#define seterror(x,...) printf(x, ## __VA_ARGS__)
+
+/**
+ * Follow the instruction of a relocation section.
+ *
+ * @param DLFile 	 SeekableReadStream of File
+ * @param offset 	 Offset into the File
+ * @param size   	 Size of relocation section
+ * @param relSegment Base address of relocated segment in memory (memory offset)
+ *
+ */
+bool MIPSDLObject::relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) {
+	Elf32_Rel *rel = NULL;	// relocation entry
+
+	// Allocate memory for relocation table
+	if (!(rel = (Elf32_Rel *)malloc(size))) {
+		seterror("Out of memory.");
+		return false;
+	}
+
+	// Read in our relocation table
+	if (DLFile->seek(offset, SEEK_SET) < 0 ||
+	        DLFile->read(rel, size) != (ssize_t)size) {
+		seterror("Relocation table load failed.");
+		free(rel);
+		return false;
+	}
+
+	// Treat each relocation entry. Loop over all of them
+	int cnt = size / sizeof(*rel);
+
+	DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
+
+	bool seenHi16 = false;	// For treating HI/LO16 commands
+	int firstHi16 = -1;		// Mark the point of the first hi16 seen
+	Elf32_Addr ahl = 0;		// Calculated addend
+	int a = 0;				// Addend: taken from the target
+
+	unsigned int *lastTarget = 0;	// For processing hi16 when lo16 arrives
+	unsigned int relocation = 0;
+	int debugRelocs[10] = {0};		// For debugging
+	int extendedHi16 = 0;			// Count extended hi16 treatments
+	Elf32_Addr lastHiSymVal = 0;
+	bool hi16InShorts = false;
+
+#define DEBUG_NUM 2
+
+	// Loop over relocation entries
+	for (int i = 0; i < cnt; i++) {
+		// Get the symbol this relocation entry is referring to
+		Elf32_Sym *sym = (Elf32_Sym *)(_symtab) + (REL_INDEX(rel[i].r_info));
+
+		// Get the target instruction in the code
+		unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset);
+
+		unsigned int origTarget = *target;	// Save for debugging
+
+		// Act differently based on the type of relocation
+		switch (REL_TYPE(rel[i].r_info)) {
+
+		case R_MIPS_HI16:						// Absolute addressing.
+			if (sym->st_shndx < SHN_LOPROC &&		// Only shift for plugin section (ie. has a real section index)
+			        firstHi16 < 0) {				// Only process first in block of HI16s
+				firstHi16 = i;						// Keep the first Hi16 we saw
+				seenHi16 = true;
+				ahl = (*target & 0xffff) << 16;		// Take lower 16 bits shifted up
+
+				lastHiSymVal = sym->st_value;
+				hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments
+				if (debugRelocs[0]++ < DEBUG_NUM)	// Print only a set number
+					DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n",
+					    i, rel[i].r_offset, ahl, *target);
+			}
+			break;
+
+		case R_MIPS_LO16:						// Absolute addressing. Needs a HI16 to come before it
+			if (sym->st_shndx < SHN_LOPROC) {		// Only shift for plugin section. (ie. has a real section index)
+				if (!seenHi16) {					// We MUST have seen HI16 first
+					seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i);
+					free(rel);
+					return false;
+				}
+
+				// Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment)
+				// Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section
+				//	and will be screened out above
+				bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value);
+
+				// Correct the bug by getting the proper value in ahl (taken from the current symbol)
+				if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) {
+					ahl -= (lastHiSymVal & 0xffff0000);		// We assume gcc meant the same offset
+					ahl += (sym->st_value & 0xffff0000);
+				}
+
+				ahl &= 0xffff0000;				// Clean lower 16 bits for repeated LO16s
+				a = *target & 0xffff;			// Take lower 16 bits of the target
+				a = (a << 16) >> 16;			// Sign extend them
+				ahl += a;						// Add lower 16 bits. AHL is now complete
+
+				// Fix: we can have LO16 access to the short segment sometimes
+				if (lo16InShorts) {
+					relocation = ahl + _shortsSegment->getOffset();		// Add in the short segment offset
+				} else	// It's in the regular segment
+					relocation = ahl + (Elf32_Addr)_segment;			// Add in the new offset for the segment
+
+				if (firstHi16 >= 0) {					// We haven't treated the HI16s yet so do it now
+					for (int j = firstHi16; j < i; j++) {
+						if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16) continue;	// Skip over non-Hi16s
+
+						lastTarget = (unsigned int *)((char *)relSegment + rel[j].r_offset);	// get hi16 target
+						*lastTarget &= 0xffff0000;		// Clear the lower 16 bits of the last target
+						*lastTarget |= (relocation >> 16) & 0xffff;	// Take the upper 16 bits of the relocation
+						if (relocation & 0x8000)(*lastTarget)++;	// Subtle: we need to add 1 to the HI16 in this case
+					}
+					firstHi16 = -1;						// Reset so we'll know we treated it
+				} else {
+					extendedHi16++;
+				}
+
+				*target &= 0xffff0000;						// Clear the lower 16 bits of current target
+				*target |= relocation & 0xffff;				// Take the lower 16 bits of the relocation
+
+				if (debugRelocs[1]++ < DEBUG_NUM)
+					DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
+					    i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
+				if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
+					DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
+					    i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
+			}
+			break;
+
+		case R_MIPS_26:									// Absolute addressing (for jumps and branches only)
+			if (sym->st_shndx < SHN_LOPROC) {			// Only relocate for main segment
+				a = *target & 0x03ffffff;				// Get 26 bits' worth of the addend
+				a = (a << 6) >> 6; 							// Sign extend a
+				relocation = ((a << 2) + (Elf32_Addr)_segment) >> 2;	// a already points to the target. Subtract our offset
+				*target &= 0xfc000000;					// Clean lower 26 target bits
+				*target |= (relocation & 0x03ffffff);
+
+				if (debugRelocs[3]++ < DEBUG_NUM)
+					DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
+					    i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
+			} else {
+				if (debugRelocs[4]++ < DEBUG_NUM)
+					DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
+					    i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
+			}
+			break;
+
+		case R_MIPS_GPREL16:							// GP Relative addressing
+			if (_shortsSegment->getOffset() != 0 && 	// Only relocate if we shift the shorts section
+			        ShortsMan.inGeneralSegment((char *)sym->st_value)) {	// Only relocate things in the plugin hole
+				a = *target & 0xffff;				    // Get 16 bits' worth of the addend
+				a = (a << 16) >> 16;						// Sign extend it
+
+				relocation = a + _shortsSegment->getOffset();
+
+				*target &= 0xffff0000;					// Clear the lower 16 bits of the target
+				*target |= relocation & 0xffff;
+
+				if (debugRelocs[5]++ < DEBUG_NUM)
+					DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n",
+					    i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
+			}
+
+			break;
+
+		case R_MIPS_32:									// Absolute addressing
+			if (sym->st_shndx < SHN_LOPROC) {			// Only shift for plugin section.
+				a = *target;							// Get full 32 bits of addend
+
+				if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment
+					relocation = a + _shortsSegment->getOffset();	   // Shift by shorts offset
+				else												   // We're in the main section
+					relocation = a + (Elf32_Addr)_segment;			   // Shift by main offset
+				*target = relocation;
+
+				if (debugRelocs[6]++ < DEBUG_NUM)
+					DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
+			}
+			break;
+
+		default:
+			seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i);
+			free(rel);
+			return false;
+		}
+	}
+
+	DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16);
+
+	free(rel);
+	return true;
+}
+
+bool MIPSDLObject::relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+
+	// Loop over sections, finding relocation sections
+	for (int i = 0; i < ehdr->e_shnum; i++) {
+
+		Elf32_Shdr *curShdr = &(shdr[i]);
+		//Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]);
+
+		if (curShdr->sh_type == SHT_REL && 						// Check for a relocation section
+		        curShdr->sh_entsize == sizeof(Elf32_Rel) &&		    // Check for proper relocation size
+		        (int)curShdr->sh_link == _symtab_sect &&			// Check that the sh_link connects to our symbol table
+		        curShdr->sh_info < ehdr->e_shnum &&					// Check that the relocated section exists
+		        (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) {  	// Check if relocated section resides in memory
+			if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) {			// regular segment
+				if (!relocate(DLFile, curShdr->sh_offset, curShdr->sh_size, _segment)) {
+					return false;
+				}
+			} else { 	// In Shorts segment
+				if (!relocate(DLFile, curShdr->sh_offset, curShdr->sh_size, (void *)_shortsSegment->getOffset())) {
+					return false;
+				}
+			}
+
+		}
+	}
+
+	return true;
+}
+
+#endif /* defined(DYNAMIC_MODULES) */

Deleted: scummvm/branches/gsoc2010-plugins/backends/plugins/mips-relocs.cpp
===================================================================
--- scummvm/branches/gsoc2010-plugins/backends/plugins/mips-relocs.cpp	2010-08-07 00:34:38 UTC (rev 51817)
+++ scummvm/branches/gsoc2010-plugins/backends/plugins/mips-relocs.cpp	2010-08-07 00:40:15 UTC (rev 51818)
@@ -1,259 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
-
- * This program 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.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "elf-loader.h"
-
-#define __DEBUG_PLUGINS__
-
-#ifdef __DEBUG_PLUGINS__
-#define DBG(x,...) printf(x, ## __VA_ARGS__)
-#else
-#define DBG(x,...)
-#endif
-
-#define seterror(x,...) printf(x, ## __VA_ARGS__)
-
-/**
- * Follow the instruction of a relocation section.
- *
- * @param DLFile 	 SeekableReadStream of File
- * @param offset 	 Offset into the File
- * @param size   	 Size of relocation section
- * @param relSegment Base address of relocated segment in memory (memory offset)
- *
- */
-bool DLObject::relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) {
-	Elf32_Rel *rel = NULL;	// relocation entry
-
-	// Allocate memory for relocation table
-	if (!(rel = (Elf32_Rel *)malloc(size))) {
-		seterror("Out of memory.");
-		return false;
-	}
-
-	// Read in our relocation table
-	if (DLFile->seek(offset, SEEK_SET) < 0 ||
-	        DLFile->read(rel, size) != (ssize_t)size) {
-		seterror("Relocation table load failed.");
-		free(rel);
-		return false;
-	}
-
-	// Treat each relocation entry. Loop over all of them
-	int cnt = size / sizeof(*rel);
-
-	DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
-
-	bool seenHi16 = false;	// For treating HI/LO16 commands
-	int firstHi16 = -1;		// Mark the point of the first hi16 seen
-	Elf32_Addr ahl = 0;		// Calculated addend
-	int a = 0;				// Addend: taken from the target
-
-	unsigned int *lastTarget = 0;	// For processing hi16 when lo16 arrives
-	unsigned int relocation = 0;
-	int debugRelocs[10] = {0};		// For debugging
-	int extendedHi16 = 0;			// Count extended hi16 treatments
-	Elf32_Addr lastHiSymVal = 0;
-	bool hi16InShorts = false;
-
-#define DEBUG_NUM 2
-
-	// Loop over relocation entries
-	for (int i = 0; i < cnt; i++) {
-		// Get the symbol this relocation entry is referring to
-		Elf32_Sym *sym = (Elf32_Sym *)(_symtab) + (REL_INDEX(rel[i].r_info));
-
-		// Get the target instruction in the code
-		unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset);
-
-		unsigned int origTarget = *target;	// Save for debugging
-
-		// Act differently based on the type of relocation
-		switch (REL_TYPE(rel[i].r_info)) {
-
-		case R_MIPS_HI16:						// Absolute addressing.
-			if (sym->st_shndx < SHN_LOPROC &&		// Only shift for plugin section (ie. has a real section index)
-			        firstHi16 < 0) {				// Only process first in block of HI16s
-				firstHi16 = i;						// Keep the first Hi16 we saw
-				seenHi16 = true;
-				ahl = (*target & 0xffff) << 16;		// Take lower 16 bits shifted up
-
-				lastHiSymVal = sym->st_value;
-				hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments
-				if (debugRelocs[0]++ < DEBUG_NUM)	// Print only a set number
-					DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n",
-					    i, rel[i].r_offset, ahl, *target);
-			}
-			break;
-
-		case R_MIPS_LO16:						// Absolute addressing. Needs a HI16 to come before it
-			if (sym->st_shndx < SHN_LOPROC) {		// Only shift for plugin section. (ie. has a real section index)
-				if (!seenHi16) {					// We MUST have seen HI16 first
-					seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i);
-					free(rel);
-					return false;
-				}
-
-				// Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment)
-				// Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section
-				//	and will be screened out above
-				bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value);
-
-				// Correct the bug by getting the proper value in ahl (taken from the current symbol)
-				if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) {
-					ahl -= (lastHiSymVal & 0xffff0000);		// We assume gcc meant the same offset
-					ahl += (sym->st_value & 0xffff0000);
-				}
-
-				ahl &= 0xffff0000;				// Clean lower 16 bits for repeated LO16s
-				a = *target & 0xffff;			// Take lower 16 bits of the target
-				a = (a << 16) >> 16;			// Sign extend them
-				ahl += a;						// Add lower 16 bits. AHL is now complete
-
-				// Fix: we can have LO16 access to the short segment sometimes
-				if (lo16InShorts) {
-					relocation = ahl + _shortsSegment->getOffset();		// Add in the short segment offset
-				} else	// It's in the regular segment
-					relocation = ahl + (Elf32_Addr)_segment;			// Add in the new offset for the segment
-
-				if (firstHi16 >= 0) {					// We haven't treated the HI16s yet so do it now
-					for (int j = firstHi16; j < i; j++) {
-						if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16) continue;	// Skip over non-Hi16s
-
-						lastTarget = (unsigned int *)((char *)relSegment + rel[j].r_offset);	// get hi16 target
-						*lastTarget &= 0xffff0000;		// Clear the lower 16 bits of the last target
-						*lastTarget |= (relocation >> 16) & 0xffff;	// Take the upper 16 bits of the relocation
-						if (relocation & 0x8000)(*lastTarget)++;	// Subtle: we need to add 1 to the HI16 in this case
-					}
-					firstHi16 = -1;						// Reset so we'll know we treated it
-				} else {
-					extendedHi16++;
-				}
-
-				*target &= 0xffff0000;						// Clear the lower 16 bits of current target
-				*target |= relocation & 0xffff;				// Take the lower 16 bits of the relocation
-
-				if (debugRelocs[1]++ < DEBUG_NUM)
-					DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
-					    i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
-				if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
-					DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
-					    i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
-			}
-			break;
-
-		case R_MIPS_26:									// Absolute addressing (for jumps and branches only)
-			if (sym->st_shndx < SHN_LOPROC) {			// Only relocate for main segment
-				a = *target & 0x03ffffff;				// Get 26 bits' worth of the addend
-				a = (a << 6) >> 6; 							// Sign extend a
-				relocation = ((a << 2) + (Elf32_Addr)_segment) >> 2;	// a already points to the target. Subtract our offset
-				*target &= 0xfc000000;					// Clean lower 26 target bits
-				*target |= (relocation & 0x03ffffff);
-
-				if (debugRelocs[3]++ < DEBUG_NUM)
-					DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
-					    i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
-			} else {
-				if (debugRelocs[4]++ < DEBUG_NUM)
-					DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
-					    i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
-			}
-			break;
-
-		case R_MIPS_GPREL16:							// GP Relative addressing
-			if (_shortsSegment->getOffset() != 0 && 	// Only relocate if we shift the shorts section
-			        ShortsMan.inGeneralSegment((char *)sym->st_value)) {	// Only relocate things in the plugin hole
-				a = *target & 0xffff;				    // Get 16 bits' worth of the addend
-				a = (a << 16) >> 16;						// Sign extend it
-
-				relocation = a + _shortsSegment->getOffset();
-
-				*target &= 0xffff0000;					// Clear the lower 16 bits of the target
-				*target |= relocation & 0xffff;
-
-				if (debugRelocs[5]++ < DEBUG_NUM)
-					DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n",
-					    i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
-			}
-
-			break;
-
-		case R_MIPS_32:									// Absolute addressing
-			if (sym->st_shndx < SHN_LOPROC) {			// Only shift for plugin section.
-				a = *target;							// Get full 32 bits of addend
-
-				if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment
-					relocation = a + _shortsSegment->getOffset();	   // Shift by shorts offset
-				else												   // We're in the main section
-					relocation = a + (Elf32_Addr)_segment;			   // Shift by main offset
-				*target = relocation;
-
-				if (debugRelocs[6]++ < DEBUG_NUM)
-					DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
-			}
-			break;
-
-		default:
-			seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i);
-			free(rel);
-			return false;
-		}
-	}
-
-	DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16);
-
-	free(rel);
-	return true;
-}
-
-bool DLObject::relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
-
-	// Loop over sections, finding relocation sections
-	for (int i = 0; i < ehdr->e_shnum; i++) {
-
-		Elf32_Shdr *curShdr = &(shdr[i]);
-		//Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]);
-
-		if (curShdr->sh_type == SHT_REL && 						// Check for a relocation section
-		        curShdr->sh_entsize == sizeof(Elf32_Rel) &&		    // Check for proper relocation size
-		        (int)curShdr->sh_link == _symtab_sect &&			// Check that the sh_link connects to our symbol table
-		        curShdr->sh_info < ehdr->e_shnum &&					// Check that the relocated section exists
-		        (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) {  	// Check if relocated section resides in memory
-			if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) {			// regular segment
-				if (!relocate(DLFile, curShdr->sh_offset, curShdr->sh_size, _segment)) {
-					return false;
-				}
-			} else { 	// In Shorts segment
-				if (!relocate(DLFile, curShdr->sh_offset, curShdr->sh_size, (void *)_shortsSegment->getOffset())) {
-					return false;
-				}
-			}
-
-		}
-	}
-
-	return true;
-}
-


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list