Skip to content

Commit a4e1dce

Browse files
committed
Fix: crash loading non-PIC MIPS ELF images (#1196)
1 parent f99cd5a commit a4e1dce

File tree

7 files changed

+142
-49
lines changed

7 files changed

+142
-49
lines changed

src/Environments/SysV/ArchSpecific/TrampolineFinder.cs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,20 @@ load.Dst is Identifier ptrGotSlot &&
212212
return null;
213213
}
214214

215+
216+
public static Expression? Mips32(IProcessorArchitecture arch, Address addrInstr, IEnumerable<RtlInstruction> instrs, IRewriterHost host)
217+
{
218+
var stubInstrs = instrs.Take(4).ToArray();
219+
220+
var dst = Mips32_Variant1(arch, host, stubInstrs);
221+
if (dst is not null)
222+
return dst;
223+
dst = Mips32_Variant2(arch, host, stubInstrs);
224+
if (dst is not null)
225+
return dst;
226+
return null;
227+
}
228+
215229
/// <summary>
216230
/// Find the destination of a MIPS32 plt stub.
217231
/// </summary>
@@ -221,9 +235,8 @@ load.Dst is Identifier ptrGotSlot &&
221235
/// jalr ra,r25
222236
/// addiu r24,r0,+00000010
223237
/// </code>
224-
public static Expression? Mips32(IProcessorArchitecture arch, Address addrInstr, IEnumerable<RtlInstruction> instrs, IRewriterHost host)
238+
public static Expression? Mips32_Variant1(IProcessorArchitecture arch, IRewriterHost host, RtlInstruction[] stubInstrs)
225239
{
226-
var stubInstrs = instrs.Take(4).ToArray();
227240
if (stubInstrs.Length != 4)
228241
return null;
229242

@@ -263,6 +276,47 @@ init.Src is Constant &&
263276
return null;
264277
}
265278

279+
/// <summary>
280+
/// Find the destination of a MIPS32 plt stub.
281+
/// </summary>
282+
/// r15 = 0x00410000
283+
/// r25 = Mem0[r15 + 0x111C:word32]
284+
/// r24 = r15 + 0x0000111C
285+
/// call r25 (retsize: 0;)
286+
public static Expression? Mips32_Variant2(IProcessorArchitecture arch, IRewriterHost host, RtlInstruction[] stubInstrs)
287+
{
288+
if (stubInstrs.Length < 3)
289+
return null;
290+
291+
if (stubInstrs[0] is RtlAssignment ass &&
292+
ass.Dst is Identifier idBase &&
293+
ass.Src is Constant imm)
294+
{
295+
}
296+
else return null;
297+
298+
if (stubInstrs[1] is RtlAssignment load &&
299+
load.Dst is Identifier idDst &&
300+
idDst.Name == "r25" &&
301+
load.Src is MemoryAccess mem &&
302+
mem.EffectiveAddress is BinaryExpression bin &&
303+
bin.Left == idBase &&
304+
bin.Right is Constant immOffset)
305+
{
306+
}
307+
else return null;
308+
309+
if (stubInstrs[2] is RtlGoto jmp &&
310+
jmp.Class.HasFlag(InstrClass.Delay) &&
311+
jmp.Target is Identifier idTarget &&
312+
idTarget == idDst)
313+
{ }
314+
else return null;
315+
316+
var sAddrGotSlot = imm.ToInt32() + immOffset.ToInt32();
317+
return Address.Ptr32((uint) sAddrGotSlot);
318+
}
319+
266320
/// <summary>
267321
/// Find the destination of a Risc-V PLT stub.
268322
/// </summary>

src/Environments/Windows/Win_x86_64_Platform.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public override int GetBitSizeFromCBasicType(CBasicType cb)
159159
public override ProcedureBase? GetTrampolineDestination(Address addrInstr, IEnumerable<RtlInstruction> rw, IRewriterHost host)
160160
{
161161
var instr = rw.FirstOrDefault();
162-
if (instr == null)
162+
if (instr is null)
163163
return null;
164164
if (instr is not RtlGoto jump)
165165
return null;
@@ -188,7 +188,7 @@ public override int GetBitSizeFromCBasicType(CBasicType cb)
188188

189189
public override ExternalProcedure? LookupProcedureByName(string? moduleName, string procName)
190190
{
191-
if (moduleName == null || !Metadata!.Modules.TryGetValue(moduleName.ToUpper(), out ModuleDescriptor? mod))
191+
if (moduleName is null || !Metadata!.Modules.TryGetValue(moduleName.ToUpper(), out ModuleDescriptor? mod))
192192
return null;
193193
if (mod.ServicesByName.TryGetValue(procName, out SystemService? svc))
194194
{

src/ImageLoaders/Elf/ElfLoader.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ public abstract class ElfLoader
8888
public const uint PF_W = 2;
8989
public const uint PF_X = 1;
9090

91-
protected ElfMachine machine;
9291
protected uint flags;
9392
protected EndianServices endianness;
9493
protected IPlatform? platform;
@@ -103,7 +102,7 @@ protected ElfLoader(
103102
byte[] rawImage) : this()
104103
{
105104
this.Services = services;
106-
this.machine = machine;
105+
this.Machine = machine;
107106
this.flags = flags;
108107
this.endianness = endianness;
109108
this.rawImage = rawImage;
@@ -123,6 +122,7 @@ protected ElfLoader()
123122
this.rawImage = null!;
124123
}
125124

125+
public ElfMachine Machine { get; }
126126
public IProcessorArchitecture Architecture { get; private set; }
127127
public IServiceProvider Services { get; }
128128
public abstract Address DefaultAddress { get; }
@@ -239,7 +239,7 @@ public void LoadArchitectureFromHeader()
239239
options[ProcessorOption.Endianness] = endianness == EndianServices.Little ? "le" : "be";
240240

241241
string? stackRegName = null;
242-
switch (this.machine)
242+
switch (this.Machine)
243243
{
244244
case ElfMachine.EM_NONE: return null; // No machine
245245
case ElfMachine.EM_SPARC:
@@ -304,7 +304,7 @@ public void LoadArchitectureFromHeader()
304304
arch = "loongaArch";
305305
break;
306306
default:
307-
throw new NotImplementedException($"ELF machine type {machine} is not implemented yet.");
307+
throw new NotImplementedException($"ELF machine type {Machine} is not implemented yet.");
308308
}
309309
var a = cfgSvc.GetArchitecture(arch, options);
310310
if (a is null)
@@ -405,7 +405,7 @@ public ulong GuessAreaEnd(ulong addrStart, ElfSegment dynSeg)
405405
{
406406
if (de.UValue <= addrStart)
407407
continue;
408-
var tagInfo = de.GetTagInfo(machine);
408+
var tagInfo = de.GetTagInfo(Machine);
409409
if (tagInfo?.Format == DtFormat.Address)
410410
{
411411
// This might be a pointer.
@@ -814,7 +814,7 @@ public string ReadAsciiString(ulong fileOffset)
814814
public void Relocate(Program program, Address addrLoad)
815815
{
816816
var symbols = CreateSymbolDictionaries(IsExecutableFile);
817-
var relocator = CreateRelocator(this.machine, symbols);
817+
var relocator = CreateRelocator(this.Machine, symbols);
818818
relocator.Relocate(program);
819819
relocator.LocateGotPointers(program, symbols);
820820
symbols = symbols.Values.Select(relocator.AdjustImageSymbol).ToSortedList(s => s.Address!);

src/ImageLoaders/Elf/ElfLoader32.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public override Address CreateAddress(ulong uAddr)
8888
var options = new Dictionary<string, object>();
8989
string? stackRegName = null;
9090
options[ProcessorOption.Endianness] = endianness == EndianServices.Little ? "le" : "be";
91-
switch (machine)
91+
switch (Machine)
9292
{
9393
case ElfMachine.EM_MIPS:
9494
//$TODO: detect release 6 of the MIPS architecture.
@@ -378,7 +378,7 @@ public override SegmentMap LoadImageBytes(IPlatform platform, byte[] rawImage, A
378378
{
379379
Size = (uint) section.Size
380380
});
381-
seg.Designer = CreateRenderer(section, machine);
381+
seg.Designer = CreateRenderer(section, Machine);
382382
}
383383
else
384384
{

src/ImageLoaders/Elf/ElfLoader64.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public override Address CreateAddress(ulong uAddr)
7878
var options = new Dictionary<string, object>();
7979
options[ProcessorOption.Endianness] = endianness == EndianServices.Little ? "le" : "be";
8080
string archName;
81-
switch (machine)
81+
switch (Machine)
8282
{
8383
case ElfMachine.EM_IA_64:
8484
archName = "ia64";
@@ -127,7 +127,7 @@ public override ElfObjectLinker CreateLinker()
127127
switch (shdr.Type)
128128
{
129129
case SectionHeaderType.SHT_DYNAMIC:
130-
return new DynamicSectionRenderer64(this, shdr, machine);
130+
return new DynamicSectionRenderer64(this, shdr, Machine);
131131
case SectionHeaderType.SHT_RELA:
132132
return new RelaSegmentRenderer64(this, shdr);
133133
case SectionHeaderType.SHT_SYMTAB:

src/ImageLoaders/Elf/Relocators/ElfRelocator.cs

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -169,54 +169,56 @@ public List<ElfSymbol> RelocateDynamicSymbols(Program program)
169169
Loader.DynamicEntries.TryGetValue(ElfDynamicEntry.DT_RELENT, out var relent);
170170

171171
Loader.DynamicEntries.TryGetValue(ElfDynamicEntry.DT_SYMENT, out var syment);
172-
if (symtab == null || (rela == null && rel == null))
172+
if (symtab is null)
173173
continue;
174-
if (strtab == null)
174+
if (strtab is null)
175175
throw new BadImageFormatException("ELF dynamic segment lacks a string table.");
176-
if (syment == null)
176+
if (syment is null)
177177
throw new BadImageFormatException("ELF dynamic segment lacks the size of symbol table entries.");
178-
RelocationTable relTable;
179-
if (rela != null)
178+
var offStrtab = Loader.AddressToFileOffset(strtab.UValue);
179+
var offSymtab = Loader.AddressToFileOffset(symtab.UValue);
180+
181+
RelocationTable? relTable = null;
182+
if (rela is { })
180183
{
181-
if (relasz == null)
184+
if (relasz is null)
182185
throw new BadImageFormatException("ELF dynamic segment lacks the size of the relocation table.");
183-
if (relaent == null)
186+
if (relaent is null)
184187
throw new BadImageFormatException("ELF dynamic segment lacks the size of relocation table entries.");
185188
relTable = new RelaTable(this, rela.UValue, relasz.UValue);
186189
}
187-
else
190+
else if (rel != null)
188191
{
189-
Debug.Assert(rel != null);
190-
if (relsz == null)
192+
if (relsz is null)
191193
throw new BadImageFormatException("ELF dynamic segment lacks the size of the relocation table.");
192-
if (relent == null)
194+
if (relent is null)
193195
throw new BadImageFormatException("ELF dynamic segment lacks the size of relocation table entries.");
194196
relTable = new RelTable(this, rel.UValue, relsz.UValue);
195197
}
196198

197-
var offStrtab = Loader.AddressToFileOffset(strtab.UValue);
198-
var offSymtab = Loader.AddressToFileOffset(symtab.UValue);
199-
200-
LoadSymbolsFromDynamicSegment(dynSeg, symtab, syment, offStrtab, offSymtab);
201-
202-
// Generate a symbol for each relocation.
203-
ElfImageLoader.trace.Inform("Relocating entries in .dynamic:");
204-
foreach (var (_, elfSym, _) in relTable.RelocateEntries(program, offStrtab, offSymtab, syment.UValue))
199+
if (relTable is { })
205200
{
206-
symbols.Add(elfSym);
207-
var imgSym = Loader.CreateImageSymbol(elfSym, true);
208-
// Symbols need to refer to the loaded image, if their value is 0,
209-
// they are imported symbols.
210-
if (imgSym == null || imgSym.Address!.ToLinear() == 0)
211-
continue;
212-
imageSymbols[imgSym.Address] = imgSym;
201+
LoadSymbolsFromDynamicSegment(dynSeg, symtab, syment, offStrtab, offSymtab);
202+
203+
// Generate a symbol for each relocation.
204+
ElfImageLoader.trace.Inform("Relocating entries in .dynamic:");
205+
foreach (var (_, elfSym, _) in relTable.RelocateEntries(program, offStrtab, offSymtab, syment.UValue))
206+
{
207+
symbols.Add(elfSym);
208+
var imgSym = Loader.CreateImageSymbol(elfSym, true);
209+
// Symbols need to refer to the loaded image, if their value is 0,
210+
// they are imported symbols.
211+
if (imgSym == null || imgSym.Address!.ToLinear() == 0)
212+
continue;
213+
imageSymbols[imgSym.Address] = imgSym;
214+
}
213215
}
214216

215217
// Relocate the DT_JMPREL table.
216218
Loader.DynamicEntries.TryGetValue(ElfDynamicEntry.DT_JMPREL, out var jmprel);
217219
Loader.DynamicEntries.TryGetValue(ElfDynamicEntry.DT_PLTRELSZ, out var pltrelsz);
218220
Loader.DynamicEntries.TryGetValue(ElfDynamicEntry.DT_PLTREL, out var pltrel);
219-
if (jmprel != null && pltrelsz != null && pltrel != null)
221+
if (jmprel is { } && pltrelsz is { } && pltrel is { })
220222
{
221223
if (pltrel.SValue == ElfDynamicEntry.DT_RELA) // entries are in RELA format.
222224
{
@@ -228,7 +230,8 @@ public List<ElfSymbol> RelocateDynamicSymbols(Program program)
228230
}
229231
else
230232
{
231-
//$REVIEW: bad elf format!
233+
var listener = Loader.Services.RequireService<DecompilerEventListener>();
234+
listener.Warn("Invalid value for DT_PLTREL: {0}", pltrel.UValue);
232235
continue;
233236
}
234237

@@ -411,7 +414,7 @@ public ElfRelocator32(ElfLoader32 loader, SortedList<Address, ImageSymbol> image
411414

412415
protected override void DumpDynamicSegment(ElfSegment dynSeg)
413416
{
414-
var renderer = new DynamicSectionRenderer32(Loader, null!, ElfMachine.EM_NONE);
417+
var renderer = new DynamicSectionRenderer32(Loader, null!, loader.Machine);
415418
var sw = new StringWriter();
416419
renderer.Render(dynSeg.p_offset, new TextFormatter(sw));
417420
Debug.WriteLine(sw.ToString());
@@ -462,7 +465,7 @@ protected void DumpRel32(ElfLoader32 loader)
462465
{
463466
foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_REL))
464467
{
465-
ElfImageLoader.trace.Inform("REL: offset {0:X} symbol section {1}, relocating in section {2}",
468+
ElfImageLoader.trace.Inform("REL: Offset {0:X} symbol section {1}, relocating in section {2}",
466469
section.FileOffset,
467470
section.LinkedSection?.Name ?? "?",
468471
section.RelocatedSection?.Name ?? "?");
@@ -487,7 +490,7 @@ protected void DumpRela32(ElfLoader32 loader)
487490
foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA))
488491
{
489492
ElfImageLoader.trace.Inform(
490-
"RELA: offset {0:X} symbol section {1}, relocating in section {2}",
493+
"RELA: Offset {0:X} symbol section {1}, relocating in section {2}",
491494
section.FileOffset,
492495
section.LinkedSection!.Name,
493496
section.RelocatedSection!.Name);
@@ -573,7 +576,7 @@ protected void DumpRel64(ElfLoader64 loader)
573576
{
574577
foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_REL))
575578
{
576-
ElfImageLoader.trace.Inform("REL: offset {0:X} symbol section {1}, relocating in section {2}",
579+
ElfImageLoader.trace.Inform("REL: Offset {0:X} symbol section {1}, relocating in section {2}",
577580
section.FileOffset,
578581
section.LinkedSection?.Name ?? "?",
579582
section.RelocatedSection?.Name ?? "?");
@@ -600,7 +603,7 @@ protected void DumpRela64(ElfLoader64 loader)
600603
s.LinkedSection != null &&
601604
s.LinkedSection.FileOffset != 0))
602605
{
603-
Debug.Print("RELA: offset {0:X} symbol section {1}, relocating in section {2}",
606+
Debug.Print("RELA: Offset {0:X} symbol section {1}, relocating in section {2}",
604607
section.FileOffset,
605608
section.LinkedSection?.Name ?? "?",
606609
section.RelocatedSection?.Name ?? "?");

0 commit comments

Comments
 (0)