protected void ApplyRelocations( BinaryReader reader, IMemory memory, ElfSection section, uint baseAddress ) { List<HiReloc> hiRelocs = new List<HiReloc>(); ElfSection linked = section.Reference; if( ( linked.Flags & ElfSectionFlags.Alloc ) != ElfSectionFlags.Alloc ) return; Debug.WriteLine( string.Format( "Relocating section {0} using {1}, {2} relocations total", linked.Name, section.Name, section.Length / 8 ) ); ElfSection textSection = _sectionLookup[ ".text" ]; ElfSection dataSection = _sectionLookup[ ".data" ]; Debug.Assert( textSection != null ); Debug.Assert( dataSection != null ); for( int n = 0; n < section.Length / 8; n++ ) { reader.BaseStream.Seek( section.ElfOffset + ( 8 * n ), SeekOrigin.Begin ); NativeElfRel rel = new NativeElfRel( reader ); ElfRelocation relocation = new ElfRelocation(); //relocation.Section = section; relocation.Offset = rel.Offset; relocation.BaseAddress = ( rel.Info >> 16 ) & 0xFF; relocation.Symbol = ( rel.Info >> 8 ) & 0xFF; relocation.RelocationType = ( ElfRelocationType )( byte )( rel.Info & 0xFF ); uint pointer = relocation.Offset; //ElfSection offsetBase = null; //ElfSection addressBase = null; if( ( relocation.Symbol & ( uint )RelocationOffset.Data ) == ( uint )RelocationOffset.Data ) { //offsetBase = dataSection; pointer += dataSection.Address; } //else if( relocation.BaseAddress == 0x1 ) //{ // offsetBase = textSection; // pointer += textSection.Address; //} else { //offsetBase = textSection; pointer += baseAddress; } //ElfSection offsetBase = _sections[ ( int )relocation.Symbol ]; //ElfSection addressBase = _sections[ ( int )relocation.BaseAddress ]; // Happens sometime if( _symbols.Count == 0 ) { Debug.WriteLine( "Unable to relocate symbol; symbol table is empty - possibly no .symtab section?" ); return; } ElfSymbol symbol = _symbols[ ( int )relocation.Symbol ]; uint symbolValue = symbol.Value; // !!! This could be bogus if( ( ( rel.Info >> 8 ) & RelocationRelativeData ) == RelocationRelativeData ) symbolValue += dataSection.Address; else symbolValue += baseAddress; //if( addressBase.Address == 0 ) // symbolValue += baseAddress; //else // symbolValue += addressBase.Address; uint value = ( uint )memory.ReadWord( ( int )pointer ); //Debug.WriteLine( string.Format( " Relocation pointer 0x{0:X8} (elf {1:X8}), value {2:X8}, type {3}, existing memory value {4:X8}", // pointer, relocation.Offset, symbolValue, relocation.RelocationType, value ) ); bool writeMemory = false; switch( relocation.RelocationType ) { case ElfRelocationType.None: break; case ElfRelocationType.Mips32: value += symbolValue; writeMemory = true; break; case ElfRelocationType.Mips26: Debug.Assert( symbolValue % 4 == 0 ); value = ( uint )( ( value & ~0x03FFFFFF ) | ( ( value + ( symbolValue >> 2 ) ) & 0x03FFFFFF ) ); writeMemory = true; break; case ElfRelocationType.Hi16: { HiReloc hiReloc = new HiReloc(); hiReloc.Address = pointer; hiReloc.Value = symbolValue; hiRelocs.Add( hiReloc ); } break; case ElfRelocationType.Lo16: { uint vallo = ( ( value & 0x0000FFFF ) ^ 0x00008000 ) - 0x00008000; while( hiRelocs.Count > 0 ) { HiReloc hiReloc = hiRelocs[ hiRelocs.Count - 1 ]; hiRelocs.RemoveAt( hiRelocs.Count - 1 ); Debug.Assert( hiReloc.Value == symbolValue ); uint value2 = ( uint )memory.ReadWord( ( int )hiReloc.Address ); uint temp = ( ( value2 & 0x0000FFFF ) << 16 ) + vallo; temp += symbolValue; temp = ( ( temp >> 16 ) + ( ( ( temp & 0x00008000 ) != 0 ) ? ( uint )1 : ( uint )0 ) ) & 0x0000FFFF; value2 = ( uint )( ( value2 & ~0x0000FFFF ) | temp ); //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8} (from previous HI16)", hiReloc.Address, value2 ) ); memory.WriteWord( ( int )hiReloc.Address, 4, ( int )value2 ); } value = ( uint )( ( value & ~0x0000FFFF ) | ( ( symbolValue + vallo ) & 0x0000FFFF ) ); } writeMemory = true; break; default: // Unsupported type Debugger.Break(); break; } if( writeMemory == true ) { //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8}", pointer, value ) ); memory.WriteWord( ( int )pointer, 4, ( int )value ); } } }
protected void ApplyRelocations(BinaryReader reader, IMemory memory, ElfSection section, uint baseAddress) { List <HiReloc> hiRelocs = new List <HiReloc>(); ElfSection linked = section.Reference; if ((linked.Flags & ElfSectionFlags.Alloc) != ElfSectionFlags.Alloc) { return; } Debug.WriteLine(string.Format("Relocating section {0} using {1}, {2} relocations total", linked.Name, section.Name, section.Length / 8)); ElfSection textSection = _sectionLookup[".text"]; ElfSection dataSection = _sectionLookup[".data"]; Debug.Assert(textSection != null); Debug.Assert(dataSection != null); for (int n = 0; n < section.Length / 8; n++) { reader.BaseStream.Seek(section.ElfOffset + (8 * n), SeekOrigin.Begin); NativeElfRel rel = new NativeElfRel(reader); ElfRelocation relocation = new ElfRelocation(); //relocation.Section = section; relocation.Offset = rel.Offset; relocation.BaseAddress = (rel.Info >> 16) & 0xFF; relocation.Symbol = (rel.Info >> 8) & 0xFF; relocation.RelocationType = ( ElfRelocationType )( byte )(rel.Info & 0xFF); uint pointer = relocation.Offset; //ElfSection offsetBase = null; //ElfSection addressBase = null; if ((relocation.Symbol & ( uint )RelocationOffset.Data) == ( uint )RelocationOffset.Data) { //offsetBase = dataSection; pointer += dataSection.Address; } //else if( relocation.BaseAddress == 0x1 ) //{ // offsetBase = textSection; // pointer += textSection.Address; //} else { //offsetBase = textSection; pointer += baseAddress; } //ElfSection offsetBase = _sections[ ( int )relocation.Symbol ]; //ElfSection addressBase = _sections[ ( int )relocation.BaseAddress ]; // Happens sometime if (_symbols.Count == 0) { Debug.WriteLine("Unable to relocate symbol; symbol table is empty - possibly no .symtab section?"); return; } ElfSymbol symbol = _symbols[( int )relocation.Symbol]; uint symbolValue = symbol.Value; // !!! This could be bogus if (((rel.Info >> 8) & RelocationRelativeData) == RelocationRelativeData) { symbolValue += dataSection.Address; } else { symbolValue += baseAddress; } //if( addressBase.Address == 0 ) // symbolValue += baseAddress; //else // symbolValue += addressBase.Address; uint value = ( uint )memory.ReadWord(( int )pointer); //Debug.WriteLine( string.Format( " Relocation pointer 0x{0:X8} (elf {1:X8}), value {2:X8}, type {3}, existing memory value {4:X8}", // pointer, relocation.Offset, symbolValue, relocation.RelocationType, value ) ); bool writeMemory = false; switch (relocation.RelocationType) { case ElfRelocationType.None: break; case ElfRelocationType.Mips32: value += symbolValue; writeMemory = true; break; case ElfRelocationType.Mips26: Debug.Assert(symbolValue % 4 == 0); value = ( uint )((value & ~0x03FFFFFF) | ((value + (symbolValue >> 2)) & 0x03FFFFFF)); writeMemory = true; break; case ElfRelocationType.Hi16: { HiReloc hiReloc = new HiReloc(); hiReloc.Address = pointer; hiReloc.Value = symbolValue; hiRelocs.Add(hiReloc); } break; case ElfRelocationType.Lo16: { uint vallo = ((value & 0x0000FFFF) ^ 0x00008000) - 0x00008000; while (hiRelocs.Count > 0) { HiReloc hiReloc = hiRelocs[hiRelocs.Count - 1]; hiRelocs.RemoveAt(hiRelocs.Count - 1); Debug.Assert(hiReloc.Value == symbolValue); uint value2 = ( uint )memory.ReadWord(( int )hiReloc.Address); uint temp = ((value2 & 0x0000FFFF) << 16) + vallo; temp += symbolValue; temp = ((temp >> 16) + (((temp & 0x00008000) != 0) ? ( uint )1 : ( uint )0)) & 0x0000FFFF; value2 = ( uint )((value2 & ~0x0000FFFF) | temp); //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8} (from previous HI16)", hiReloc.Address, value2 ) ); memory.WriteWord(( int )hiReloc.Address, 4, ( int )value2); } value = ( uint )((value & ~0x0000FFFF) | ((symbolValue + vallo) & 0x0000FFFF)); } writeMemory = true; break; default: // Unsupported type Debugger.Break(); break; } if (writeMemory == true) { //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8}", pointer, value ) ); memory.WriteWord(( int )pointer, 4, ( int )value); } } }