Skip to content

Commit

Permalink
Fix: #1351
Browse files Browse the repository at this point in the history
Don't attempt to apply relocations to sections that aren't loaded into memory.
  • Loading branch information
uxmal committed Aug 21, 2024
1 parent df5c4a5 commit 72a6b8f
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/Core/Hll/C/CParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1577,7 +1577,7 @@ private static (int?, int?) infixBindingPower(CTokenType tokenType)
//Expr = AssignExpr {',' AssignExpr}.
public CExpression Parse_Expr()
{
return this.expr_bp(0);
//return this.expr_bp(0);

var left = Parse_AssignExpr();
while (PeekThenDiscard(CTokenType.Comma))
Expand Down
6 changes: 5 additions & 1 deletion src/ImageLoaders/Elf/ElfImageLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using Reko.Core.Loading;
using Reko.Core.Memory;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Reko.ImageLoaders.Elf
Expand Down Expand Up @@ -81,9 +82,11 @@ public override Program LoadProgram(Address? addrLoad)
innerLoader.LoadSymbolsFromSections();
//innerLoader.Dump(); // This spews a lot into the unit test output.
Program program;
Dictionary<ElfSymbol, Address> plt;
if (cHeaders > 0)
{
program = innerLoader.LoadImage(platform, RawImage);
plt = new Dictionary<ElfSymbol, Address>();
}
else
{
Expand All @@ -97,8 +100,9 @@ public override Program LoadProgram(Address? addrLoad)
// linked before we can load it.
var linker = innerLoader.CreateLinker();
program = linker.LinkObject(platform, addrLoad, RawImage);
plt = linker.PltEntries;
}
innerLoader!.Relocate(program, addrLoad!);
innerLoader!.Relocate(program, addrLoad!, plt);
return program;
}

Expand Down
9 changes: 6 additions & 3 deletions src/ImageLoaders/Elf/ElfLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,10 @@ public IPlatform LoadPlatform(byte osAbi, IProcessorArchitecture arch)
return platform;
}

public virtual ElfRelocator CreateRelocator(ElfMachine machine, SortedList<Address, ImageSymbol> symbols)
public virtual ElfRelocator CreateRelocator(
ElfMachine machine,
SortedList<Address, ImageSymbol> symbols,
Dictionary<ElfSymbol, Address> plt)
{
throw new NotSupportedException($"Relocator for architecture {machine} not implemented yet.");
}
Expand Down Expand Up @@ -836,10 +839,10 @@ public string ReadAsciiString(ulong fileOffset)
return Encoding.ASCII.GetString(bytes, (int) fileOffset, u - (int) fileOffset);
}

public void Relocate(Program program, Address addrLoad)
public void Relocate(Program program, Address addrLoad, Dictionary<ElfSymbol, Address> plt)
{
var symbols = CreateSymbolDictionaries(IsExecutableFile);
var relocator = CreateRelocator(this.Machine, symbols);
var relocator = CreateRelocator(this.Machine, symbols, plt);
relocator.Relocate(program);
relocator.LocateGotPointers(program, symbols);
symbols = symbols.Values.Select(relocator.AdjustImageSymbol).ToSortedList(s => s.Address!);
Expand Down
7 changes: 5 additions & 2 deletions src/ImageLoaders/Elf/ElfLoader32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ public override ElfObjectLinker CreateLinker()
return new ElfObjectLinker32(this, Architecture, rawImage);
}

public override ElfRelocator CreateRelocator(ElfMachine machine, SortedList<Address, ImageSymbol> imageSymbols)
public override ElfRelocator CreateRelocator(
ElfMachine machine,
SortedList<Address, ImageSymbol> imageSymbols,
Dictionary<ElfSymbol, Address> plt)
{
switch (machine)
{
Expand Down Expand Up @@ -191,7 +194,7 @@ public override ElfRelocator CreateRelocator(ElfMachine machine, SortedList<Addr
case ElfMachine.EM_ALTERA_NIOS2: return new Nios2Relocator(this, imageSymbols);
case ElfMachine.EM_TC32: return new TC32Relocator(this, imageSymbols);
}
return base.CreateRelocator(machine, imageSymbols);
return base.CreateRelocator(machine, imageSymbols, plt);
}

public ImageSegmentRenderer? CreateRenderer(ElfSection shdr, ElfMachine machine)
Expand Down
9 changes: 6 additions & 3 deletions src/ImageLoaders/Elf/ElfLoader64.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,15 @@ public override ElfObjectLinker CreateLinker()
}
}

public override ElfRelocator CreateRelocator(ElfMachine machine, SortedList<Address, ImageSymbol> symbols)
public override ElfRelocator CreateRelocator(
ElfMachine machine,
SortedList<Address, ImageSymbol> symbols,
Dictionary<ElfSymbol, Address> plt)
{
switch (machine)
{
case ElfMachine.EM_AARCH64: return new Arm64Relocator(this, symbols);
case ElfMachine.EM_X86_64: return new x86_64Relocator(this, symbols);
case ElfMachine.EM_X86_64: return new x86_64Relocator(this, symbols, plt);
case ElfMachine.EM_PPC64: return new PpcRelocator64(this, symbols);
case ElfMachine.EM_MIPS: return new MipsRelocator64(this, symbols);
case ElfMachine.EM_RISCV: return new RiscVRelocator64(this, symbols);
Expand All @@ -154,7 +157,7 @@ public override ElfRelocator CreateRelocator(ElfMachine machine, SortedList<Addr
case ElfMachine.EM_SPARCV9: return new Sparc64Relocator(this, symbols);
case ElfMachine.EM_IA_64: return new Ia64Relocator(this, symbols);
}
return base.CreateRelocator(machine, symbols);
return base.CreateRelocator(machine, symbols, plt);
}

public override void Dump(Address addrLoad, TextWriter writer)
Expand Down
21 changes: 18 additions & 3 deletions src/ImageLoaders/Elf/ElfObjectLinker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public abstract class ElfObjectLinker
protected readonly IProcessorArchitecture arch;
private readonly ElfLoader loader;
protected byte[] rawImage;

/// <summary>
/// Section used to simulate the presence of external functions.
/// </summary>
protected readonly ElfSection rekoExtfn;
protected readonly List<ElfSymbol> unresolvedSymbols;

Expand All @@ -58,16 +62,24 @@ public ElfObjectLinker(ElfLoader loader, IProcessorArchitecture arch, byte[] raw
Alignment = 0x10,
};
this.unresolvedSymbols = new List<ElfSymbol>();
this.PltEntries = new Dictionary<ElfSymbol, Address>();
}

public Dictionary<ElfSymbol, Address> PltEntries { get; }

public abstract Program LinkObject(IPlatform platform, Address? addrLoad, byte[] rawImage);

protected Address? ComputeBaseAddressFromSections(IEnumerable<ElfSection> sections)
{
return sections.Where(s => s.Address != null && (s.Flags & ElfLoader.SHF_ALLOC) != 0)
var address = sections.Where(s => s.Address != null && (s.Flags & ElfLoader.SHF_ALLOC) != 0)
.OrderBy(s => s.Address)
.Select(s => s.Address)
.First();
.FirstOrDefault();
if (address is null)
return loader.CreateAddress(0x1000);
if (address.Offset == 0)
address += 0x1000;
return address;
}

/// <summary>
Expand All @@ -88,6 +100,7 @@ public void LoadExternalProcedures(Dictionary<Address, ExternalProcedure> interc
//$TODO: try guessing the signature based on the symbol name.
var sig = new FunctionType();
interceptedCalls.Add(addr, new ExternalProcedure(sym.Name, sig));
PltEntries[sym] = addr;
}
}
}
Expand All @@ -105,7 +118,9 @@ protected ElfObjectLinker(TLoader loader, IProcessorArchitecture arch, byte[] im

public override Program LinkObject(IPlatform platform, Address? addrLoad, byte[] rawImage)
{
var addrBase = addrLoad ?? ComputeBaseAddressFromSections(loader.Sections)!;
var addrBase = addrLoad is not null && addrLoad.Offset != 0
? addrLoad
: ComputeBaseAddressFromSections(loader.Sections)!;
CollectCommonSymbolsIntoSection();
CollectUndefinedSymbolsIntoSection();
var segments = ComputeSegmentSizes();
Expand Down
13 changes: 6 additions & 7 deletions src/ImageLoaders/Elf/Relocators/ElfRelocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace Reko.ImageLoaders.Elf.Relocators
{
public abstract class ElfRelocator
{
private readonly SortedList<Address, ImageSymbol> imageSymbols;
protected readonly SortedList<Address, ImageSymbol> imageSymbols;

public ElfRelocator(SortedList<Address, ImageSymbol> syms)
{
Expand Down Expand Up @@ -188,7 +188,7 @@ public List<ElfSymbol> RelocateDynamicSymbols(Program program)
throw new BadImageFormatException("ELF dynamic segment lacks the size of relocation table entries.");
relTable = new RelaTable(this, rela.UValue, relasz.UValue);
}
else if (rel != null)
else if (rel is { })
{
if (relsz is null)
throw new BadImageFormatException("ELF dynamic segment lacks the size of the relocation table.");
Expand Down Expand Up @@ -421,12 +421,10 @@ public virtual void LocateGotPointers(Program program, SortedList<Address, Image
public abstract class ElfRelocator32 : ElfRelocator
{
protected ElfLoader32 loader;
protected SortedList<Address, ImageSymbol> imageSymbols;

public ElfRelocator32(ElfLoader32 loader, SortedList<Address, ImageSymbol> imageSymbols) : base(imageSymbols)
{
this.loader = loader;
this.imageSymbols = imageSymbols;
}

public override ElfLoader Loader => loader;
Expand Down Expand Up @@ -534,12 +532,11 @@ protected void DumpRela32(ElfLoader32 loader)
public abstract class ElfRelocator64 : ElfRelocator
{
protected ElfLoader64 loader;
protected SortedList<Address, ImageSymbol> imageSymbols;

public ElfRelocator64(ElfLoader64 loader, SortedList<Address, ImageSymbol> imageSymbols) : base(imageSymbols)
public ElfRelocator64(ElfLoader64 loader, SortedList<Address, ImageSymbol> imageSymbols)
: base(imageSymbols)
{
this.loader = loader;
this.imageSymbols = imageSymbols;
}

public override ElfLoader Loader => loader;
Expand All @@ -565,6 +562,8 @@ public override void Relocate(Program program)

foreach (var relSection in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA))
{
if (relSection.RelocatedSection?.Address is null)
continue;
var symbols = loader.Symbols[relSection.LinkedSection!.FileOffset];
var referringSection = relSection.RelocatedSection;
var rdr = loader.CreateReader(relSection.FileOffset);
Expand Down
27 changes: 25 additions & 2 deletions src/ImageLoaders/Elf/Relocators/x86_64Relocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ namespace Reko.ImageLoaders.Elf.Relocators
public class x86_64Relocator : ElfRelocator64
{
private Dictionary<Address, ImportReference>? importReferences;
private Dictionary<ElfSymbol, Address> plt;

public x86_64Relocator(ElfLoader64 loader, SortedList<Address, ImageSymbol> imageSymbols) : base(loader, imageSymbols)
public x86_64Relocator(
ElfLoader64 loader,
SortedList<Address, ImageSymbol> imageSymbols,
Dictionary<ElfSymbol, Address> plt) : base(loader, imageSymbols)
{
this.loader = loader;
this.plt = plt;
}

/// <remarks>
Expand Down Expand Up @@ -83,6 +88,8 @@ private void LoadImportReferencesFromRelaPlt()

public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol sym, ElfSection? referringSection, ElfRelocation rela)
{
if (rela.Offset == 0x540)
_ = this; //$DEBUG
var rt = (x86_64Rt)(rela.Info & 0xFF);
if (loader.Sections.Count <= sym.SectionIndex)
return (null, null);
Expand All @@ -103,6 +110,8 @@ public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol
if (sym.SectionIndex != 0)
{
var symSection = loader.Sections[(int) sym.SectionIndex];
if (symSection.Address is null)
return (null, null);
S = (ulong) sym.Value + symSection.Address!.ToLinear();
}
long A = 0;
Expand Down Expand Up @@ -130,6 +139,20 @@ public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol
break;
case x86_64Rt.R_X86_64_COPY:
break;
case x86_64Rt.R_X86_64_PC32:
relW.WriteUInt32(
(uint)(S + (ulong) rela.Addend!.Value - P));
return (addr, null);
case x86_64Rt.R_X86_64_PLT32:
if (!plt.TryGetValue(sym, out var L))
{
Debug.Print("ELF external symbol {0} not present in PLT", sym);
return (null, null);
}
relW.WriteUInt32(
(uint) (L.Offset + (ulong) rela.Addend!.Value - P));
return (addr, null);

default:
Debug.Print("x86_64 ELF relocation type {0} not implemented yet.",
rt);
Expand All @@ -138,7 +161,7 @@ public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol
// "x86_64 ELF relocation type {0} not implemented yet.",
// rt));
}
if (relR != null)
if (relR is not null)
{
var w = relR.ReadUInt64();
w += ((ulong)(S + (ulong)A + P) >> sh) & mask;
Expand Down
4 changes: 2 additions & 2 deletions src/UnitTests/Arch/Avr/Avr32RewriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ public void Avr32Rw_muls_d()
Given_HexString("F6080444");
AssertCode( // muls.d r4,r11,r8
"0|L--|00100000(4): 1 instructions",
"1|L--|r5_r4 = r11 *s r8");
"1|L--|r5_r4 = r11 *s64 r8");
}

[Test]
Expand All @@ -605,7 +605,7 @@ public void Avr32Rw_mulu_d()
Given_HexString("F6080644");
AssertCode( // mulu.d r4,r11,r8
"0|L--|00100000(4): 1 instructions",
"1|L--|r5_r4 = r11 *u r8");
"1|L--|r5_r4 = r11 *u64 r8");
}

[Test]
Expand Down
10 changes: 8 additions & 2 deletions subjects/regression.log

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 72a6b8f

Please sign in to comment.