Skip to content

Commit

Permalink
Feature: do ELF relocations using new BinaryImage
Browse files Browse the repository at this point in the history
  • Loading branch information
uxmal committed Oct 21, 2024
1 parent 536aef7 commit b802813
Show file tree
Hide file tree
Showing 41 changed files with 17,814 additions and 1,920 deletions.
2 changes: 0 additions & 2 deletions src/Core/Loading/ImageSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ public static ImageSymbol Create(
public string? Name { get => n; set
{
n = value;
if (n == "_mm_free")
_ = this; //$DEBUG
}
}
private string? n;
Expand Down
2 changes: 0 additions & 2 deletions src/Decompiler/Analysis/ConditionCodeEliminator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ public void Transform()
{
try
{
if (u.Block.Address.Offset == 0x0A68)
_ = this; //$DEBUG
useStm = u;
trace.Inform("CCE: used {0}", useStm.Instruction);
useStm.Instruction.Accept(this);
Expand Down
1 change: 0 additions & 1 deletion src/Decompiler/Analysis/LongAddRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,6 @@ ass.Src is BinaryExpression bin &&
return default;
if (shConst1 is not null)
{
_ = this;//$DEBUG
if (exp1 is not Identifier idRight)
return default;
var (sidOtherDst, otherSrc) = FindOtherShiftUse(op1.Type == OperatorType.Shl, idRight);
Expand Down
1 change: 1 addition & 0 deletions src/ImageLoaders/Elf/ElfImageLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public override Program LoadProgram(Address? addrLoad)
binaryImage.AddSections(innerLoader.LoadSectionHeaders());
innerLoader.LoadSymbolsFromSections();
innerLoader.LoadRelocations();
innerLoader.LoadDynamicSegment();
var dynRelocs = innerLoader.LoadDynamicRelocations();
binaryImage.AddDynamicRelocations(dynRelocs);

Expand Down
85 changes: 66 additions & 19 deletions src/ImageLoaders/Elf/ElfLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,6 @@ public Program LoadImage(IPlatform platform, byte[] rawImage)
var addrPreferred = ComputeBaseAddress(platform);
Dump(addrPreferred);
this.segmentMap = LoadImageBytes(platform, rawImage, addrPreferred);
LoadDynamicSegment();
var program = new Program(new ByteProgramMemory(segmentMap), platform.Architecture, platform);
return program;
}
Expand Down Expand Up @@ -566,12 +565,55 @@ public void LocateGotPointers(Program program, SortedList<Address, ImageSymbol>
// Locate the GOT. It's fully possible that the binary doesn't have a
// .got section.
var got = program.SegmentMap.Segments.Values.FirstOrDefault(s => s.Name == ".got");
if (got is null)
return;
if (got is not null)
{
var gotStart = got.Address;
var gotEnd = got.EndAddress;
int cEntries = ConstructGotEntries(program, symbols, gotStart, gotEnd, false);
if (cEntries > 0)
return;
}
// Ain't got no GOT!
// Reconstruct GOT pointers from the dynamic relocations
ReconstructGotPointersFromDynamicRelocations(program, symbols);
}

var gotStart = got.Address;
var gotEnd = got.EndAddress;
ConstructGotEntries(program, symbols, gotStart, gotEnd, false);
int ReconstructGotPointersFromDynamicRelocations(
Program program,
SortedList<Address, ImageSymbol> symbols)
{
int cSymbols = 0;
foreach (var reloc in BinaryImage.DynamicRelocations)
{
var symbol = reloc.Symbol;
var addrGot = CreateAddress(reloc.Offset);
if (symbol is not null &&
(symbol.Type == ElfSymbolType.STT_FUNC))
// || symbol.Type == ElfSymbolType.STT_OBJECT))
{
var name = symbol.Name;
ImageSymbol gotSym = CreateGotSymbol(program.Architecture, addrGot, name);
symbols[addrGot] = gotSym;
var symType = symbol.Type == ElfSymbolType.STT_FUNC
? SymbolType.ExternalProcedure
: SymbolType.Data;
if (symbol.SectionIndex == 0) // An external thing
{
++cSymbols;
if (!program.ImportReferences.TryGetValue(addrGot, out var oldImpRef))
{
program.ImportReferences.Add(
addrGot,
new NamedImportReference(
addrGot,
null,
name,
symType));
}
}
}
}
return cSymbols;
}

/// <summary>
Expand All @@ -583,11 +625,12 @@ public void LocateGotPointers(Program program, SortedList<Address, ImageSymbol>
/// <param name="symbols"></param>
/// <param name="gotStart"></param>
/// <param name="gotEnd"></param>
public void ConstructGotEntries(Program program, SortedList<Address, ImageSymbol> symbols, Address gotStart, Address gotEnd, bool makeGlobals)
public int ConstructGotEntries(Program program, SortedList<Address, ImageSymbol> symbols, Address gotStart, Address gotEnd, bool makeGlobals)
{
ElfImageLoader.trace.Verbose("== Constructing GOT entries ==");
ElfImageLoader.trace.Verbose("== Constructing GOT from .got section entries ==");
if (!program.TryCreateImageReader(program.Architecture, gotStart, out var rdr))
return;
return 0;
int cEntries = 0;
var arch = program.Architecture;
while (rdr.Address < gotEnd)
{
Expand All @@ -600,6 +643,7 @@ public void ConstructGotEntries(Program program, SortedList<Address, ImageSymbol
// This GOT entry is a known symbol!
if (symbol.Type == SymbolType.Procedure || symbol.Type == SymbolType.ExternalProcedure)
{
++cEntries;
var name = symbol.Name!;
ImageSymbol gotSym = CreateGotSymbol(arch, addrGot, name);
symbols[addrGot] = gotSym;
Expand All @@ -626,6 +670,7 @@ public void ConstructGotEntries(Program program, SortedList<Address, ImageSymbol
ImageSymbol gotDataSym = ImageSymbol.Create(SymbolType.Data, program.Architecture, addrGot);
ElfImageLoader.trace.Verbose("{0}+{1:X4}: GOT entry with no symbol, assuming local data {2}",
gotStart, addrGot - gotStart, addrGot);
++cEntries;
program.ImportReferences.Add(
addrGot,
new NamedImportReference(
Expand All @@ -635,6 +680,7 @@ public void ConstructGotEntries(Program program, SortedList<Address, ImageSymbol
gotDataSym.Type));
}
}
return cEntries;
}

public ImageSymbol CreateGotSymbol(IProcessorArchitecture arch, Address addrGot, string name)
Expand Down Expand Up @@ -810,10 +856,6 @@ public void LoadSymbolsFromSections()
ElfImageLoader.trace.Inform("== Loading ELF symbols from section {0} (at offset {1:X})", section.Name!, section.FileOffset);
var symtab = LoadSymbolsSection(section);
BinaryImage.SymbolsByFileOffset[section.FileOffset] = symtab;
if (section.Type == SectionHeaderType.SHT_DYNSYM)
{
BinaryImage.AddDynamicSymbols(symtab);
}
}
}

Expand Down Expand Up @@ -915,7 +957,8 @@ public void LoadRelocations()
var cEntries = relSection.EntryCount();

var relocations = LoadRelEntries(sectionSymbols, fileOffset, cEntries);
if (referringSection?.VirtualAddress is not null)
var vaddr = referringSection?.VirtualAddress;
if (vaddr is not null && vaddr.Offset != 0 && this.IsRelocatableFile)
{
BinaryImage.AddRelocations(referringSection?.Index ?? 0, relocations);
}
Expand Down Expand Up @@ -979,15 +1022,17 @@ public IReadOnlyCollection<ElfRelocation> LoadDynamicRelocations()
{
var symbols = new List<ElfSymbol>();
var result = new List<ElfRelocation>();
bool alreadSeen = false;
bool alreadySeen = false;
foreach (var dynSeg in EnumerateDynamicSegments())
{
if (alreadSeen)
if (alreadySeen)
{
var eventListener = Services.GetService<IEventListener>();
eventListener?.Warn("Multiple dynamic ELF sections detected. Results may be unpredictable.");
return result;
}
alreadySeen = true;

var dynEntries = this.BinaryImage.DynamicEntries;
dynEntries.TryGetValue(ElfDynamicEntry.DT_STRTAB, out var strtab);
dynEntries.TryGetValue(ElfDynamicEntry.DT_SYMTAB, out var symtab);
Expand Down Expand Up @@ -1015,14 +1060,16 @@ public IReadOnlyCollection<ElfRelocation> LoadDynamicRelocations()
var syms = LoadSymbolsFromDynamicSegment(dynSeg, symtab, syment, offStrtab, offSymtab)
.Select((s, i) => (s, i))
.ToDictionary(x => x.i, x => x.s);
BinaryImage.AddDynamicSymbols(syms);

if (rela is { })
{
if (relasz is null || relasz.UValue == 0)
throw new BadImageFormatException("ELF dynamic segment lacks the size of the relocation table.");
if (relaent is null)
throw new BadImageFormatException("ELF dynamic segment lacks the size of relocation table entries.");
var relocations = LoadRelaEntries(syms, rela.UValue, (uint)(relaent.UValue / relasz.UValue));
var fileOffset = this.AddressToFileOffset(rela.UValue);
var relocations = LoadRelaEntries(syms, fileOffset, (uint)(relaent.UValue / relasz.UValue));
result.AddRange(relocations);
}
else if (rel is { })
Expand All @@ -1031,7 +1078,8 @@ public IReadOnlyCollection<ElfRelocation> LoadDynamicRelocations()
throw new BadImageFormatException("ELF dynamic segment lacks the size of the relocation table.");
if (relent is null)
throw new BadImageFormatException("ELF dynamic segment lacks the size of relocation table entries.");
var relocations = LoadRelEntries(syms, rel.UValue, (uint) (relsz.UValue / relent.UValue));
var fileOffset = this.AddressToFileOffset(rel.UValue);
var relocations = LoadRelEntries(syms, fileOffset, (uint) (relsz.UValue / relent.UValue));
result.AddRange(relocations);
}

Expand Down Expand Up @@ -1136,7 +1184,6 @@ private List<ElfSymbol> LoadSymbolsFromDynamicSegment(
return result;
}


public IEnumerable<ElfSegment> EnumerateDynamicSegments()
{
return BinaryImage.Segments
Expand Down
3 changes: 0 additions & 3 deletions src/ImageLoaders/Elf/ElfSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ public class ElfSymbol : IBinarySymbol
public ElfSymbol(string name)
{
this.Name = name;
if (name == "_mm_free")
_ = this; //$DEBUG

}

public string Name { get; }
Expand Down
Loading

0 comments on commit b802813

Please sign in to comment.