Skip to content

Commit b02433c

Browse files
committed
Fix: #1362
This commit fixes a crash in the COFF loader reported by @lighth7015. You can now override the platform of any loader's Programs by specifying the `--env` command line parameter to the Reko cli: ``` reko decompile --env msdos-386 DPMIAPP.EXE ``` will now work.
1 parent e0b7934 commit b02433c

File tree

86 files changed

+378
-272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+378
-272
lines changed

src/Arch/Cray/UnicosLoader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public enum MachineType
9090
A_PMT_C90 = 8, // CRAY C90
9191
}
9292

93-
public override Program LoadProgram(Address? addrLoad)
93+
public override Program LoadProgram(Address? addrLoad, string? platformOverride)
9494
{
9595
var rdr = new BeImageReader(RawImage);
9696
if (!rdr.TryReadBeUInt64(out ulong magic))
@@ -121,7 +121,7 @@ public override Program LoadProgram(Address? addrLoad)
121121
new ImageSegment("text", text, AccessMode.ReadExecute),
122122
new ImageSegment("data", data, AccessMode.ReadWrite),
123123
new ImageSegment("bss", bss, AccessMode.ReadWrite));
124-
var platform = cfgSvc.GetEnvironment("unicos").Load(Services, arch);
124+
var platform = Platform.Load(Services, "unicos", platformOverride, arch);
125125
var program = new Program(new ByteProgramMemory(segs), arch, platform);
126126
var entry = ImageSymbol.Procedure(program.Architecture, Address.Ptr32((uint) a_entry), "_start");
127127
program.EntryPoints[entry.Address] = entry;

src/Core/Configuration/RekoConfigurationService.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,10 @@ public interface IConfigurationService
6767
/// <summary>
6868
/// Given an platform or environment name, gets its corresponding platform definition.
6969
/// </summary>
70-
/// <param name="envName">Name of the environment.</param>
70+
/// <param name="envName">Name of the environment. If null is passed,
71+
/// fall back to the <see cref="DefaultPlatform"/>.</param>
7172
/// <returns>A platform definition for that environment.</returns>
72-
PlatformDefinition GetEnvironment(string envName);
73+
PlatformDefinition GetEnvironment(string? envName);
7374

7475
/// <summary>
7576
/// Given the name of an architecture, creates an instance of that architecture.
@@ -640,7 +641,7 @@ public virtual ICollection<RawFileDefinition> GetRawFiles()
640641
}
641642

642643
/// <inheritdoc/>
643-
public PlatformDefinition GetEnvironment(string envName)
644+
public PlatformDefinition GetEnvironment(string? envName)
644645
{
645646
var env = GetEnvironments()
646647
.Where(e => e.Name == envName).SingleOrDefault();

src/Core/Loading/ILoader.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public interface ILoader
4343
/// </summary>
4444
/// <param name="imageLocation">The <see cref="ImageLocation"/> from which</param>
4545
/// <param name="loader">Optional name of a specific image loader to use.</param>
46+
/// <param name="environmentName">Optional name of operating environment to use.</param>
4647
/// <param name="addrLoad">Optional address at which to load the image.</param>
4748
/// <returns>
4849
/// An <see cref="ILoadedImage"/> instance. In particular, if the
@@ -52,6 +53,7 @@ public interface ILoader
5253
ILoadedImage Load(
5354
ImageLocation imageLocation,
5455
string? loader = null,
56+
string? environmentName = null,
5557
Address? addrLoad = null);
5658

5759
/// <summary>

src/Core/Loading/ProgramImageLoader.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,18 @@ public ProgramImageLoader(IServiceProvider services, ImageLocation imageLocation
5454
/// <returns>A <see cref="ILoadedImage"/>.</returns>
5555
public override ILoadedImage Load(Address? addrLoad)
5656
{
57-
return LoadProgram(addrLoad);
57+
return LoadProgram(addrLoad, null);
5858
}
5959

6060
/// <summary>
6161
/// Loads a program image into memory.
6262
/// </summary>
6363
/// <param name="address">Optional base address of the program image. If not specified,
6464
/// use the image format's default loading address.</param>
65+
/// <param name="platformOverride">Optional name of platform to use instead
66+
/// of the one determined by the loader.</param>
6567
/// <returns>An object implementing the <see cref="ILoadedImage"/> interface.</returns>
66-
public abstract Program LoadProgram(Address? address);
68+
public abstract Program LoadProgram(Address? address, string? platformOverride);
6769

6870
/// <summary>
6971
/// Loads the image into memory at the specified address, using the

src/Core/Memory/ByteMemoryArea.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,10 @@ public static bool TryReadLe(byte[] abImage, long imageOffset, DataType type, ou
383383
c = Constant.Create(type, l);
384384
return true;
385385
default:
386-
throw new NotImplementedException(string.Format("Primitive type {0} not supported.", type));
386+
//$TODO:
387+
// #1362: consider writing this to error output?
388+
// throw new NotImplementedException(string.Format("Primitive type {0} not supported.", type));
389+
break;
387390
}
388391
c = default!;
389392
return false;

src/Core/Platform.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,59 @@ public virtual (string, SerializedType, SerializedType)? DataTypeFromImportName(
10801080
public virtual void WriteMetadata(Program program, string path)
10811081
{
10821082
}
1083+
1084+
/// <summary>
1085+
/// Helper method used to obtain an <see cref="IPlatform"/> implementation,
1086+
/// given an optional override.
1087+
/// </summary>
1088+
/// <param name="services"><see cref="IServiceProvider"/> instance to use.</param>
1089+
/// <param name="platform"><see cref="IPlatform"/> instance to use if no <paramref name="sPlatformOverride" />
1090+
/// <param name="sPlatformOverride">Name of platform to use. If null, the method falls
1091+
/// back to using the provided <paramref name="platform"/>.</param>
1092+
/// is provided.</param>
1093+
/// <param name="arch">Processor architecture to use when obtaining the <see cref="IPlatform"/>
1094+
/// instance</param>
1095+
/// <returns>An <see cref="IPlatform"/> instance.</returns>
1096+
public static IPlatform Load(
1097+
IServiceProvider services,
1098+
IPlatform? platform,
1099+
string? sPlatformOverride,
1100+
IProcessorArchitecture arch)
1101+
{
1102+
if (string.IsNullOrWhiteSpace(sPlatformOverride) && platform is not null)
1103+
return platform;
1104+
var cfgSvc = services.RequireService<IConfigurationService>();
1105+
var platform2 = cfgSvc.GetEnvironment(sPlatformOverride)
1106+
.Load(services, arch);
1107+
return platform2;
1108+
}
1109+
1110+
/// <summary>
1111+
/// Helper method used to obtain an <see cref="IPlatform"/> implementation,
1112+
/// given an optional override.
1113+
/// </summary>
1114+
/// <param name="services"><see cref="IServiceProvider"/> instance to use.</param>
1115+
/// <param name="sPlatform">Name of the platform to use if no <paramref name="sPlatformOverride" /> was provided.
1116+
/// </param>
1117+
/// <param name="sPlatformOverride">Name of platform to use. If null, the method falls
1118+
/// back to using the provided <paramref name="sPlatform"/>.</param>
1119+
/// <param name="arch">Processor architecture to use when obtaining the <see cref="IPlatform"/>
1120+
/// instance</param>
1121+
/// <returns>An <see cref="IPlatform"/> instance.</returns>
1122+
public static IPlatform Load(
1123+
IServiceProvider services,
1124+
string? sPlatform,
1125+
string? sPlatformOverride,
1126+
IProcessorArchitecture arch)
1127+
{
1128+
if (!string.IsNullOrWhiteSpace(sPlatformOverride))
1129+
sPlatform = sPlatformOverride;
1130+
var cfgSvc = services.RequireService<IConfigurationService>();
1131+
var platform = cfgSvc.GetEnvironment(sPlatform)
1132+
.Load(services, arch);
1133+
return platform;
1134+
}
1135+
10831136
}
10841137

10851138
/// <summary>

src/Core/Serialization/ProjectLoader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ private Program LoadProgram(ImageLocation projectLocation, DecompilerInput_v5 sI
314314
}
315315
else
316316
{
317-
if (loader.Load(binLocation, null, address) is not Program p)
317+
if (loader.Load(binLocation, null, sUser.PlatformOptions?.Name, address) is not Program p)
318318
{
319319
// A previous save of the project was able to read the file,
320320
// but now we can't...

src/Decompiler/Loading/Loader.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,20 @@ public Program AssembleExecutable(ImageLocation asmFileLocation, byte[] image, I
125125
/// <param name="imageLocation">The location of the image to load.</param>
126126
/// <param name="loaderName">Optional .NET class name of a custom
127127
/// image loader</param>
128+
/// <param name="environmentName">Optional name of the environment
129+
/// to use, overriding any environment loaded by the image loader.</param>
128130
/// <param name="addrLoad">Optional address at which to load the image.
129131
/// </param>
130132
/// <returns>
131133
/// An <see cref="ILoadedImage"/> instance. In particular, if the
132134
/// file format wasn't recognized an instance of <see cref="Blob"/> is
133135
/// returned.
134136
/// </returns>
135-
public ILoadedImage Load(ImageLocation imageLocation, string? loaderName = null, Address? addrLoad = null)
137+
public ILoadedImage Load(
138+
ImageLocation imageLocation,
139+
string? loaderName = null,
140+
string? environmentName = null,
141+
Address? addrLoad = null)
136142
{
137143
byte[] image = LoadFileBytes(imageLocation.FilesystemPath);
138144

@@ -334,11 +340,7 @@ public Program ParseRawImage(byte[] image, Address? loadingAddress, LoadDetails
334340
if (arch is null)
335341
throw new ApplicationException($"Unknown processor architecture '{details.ArchitectureName}");
336342
arch.LoadUserOptions(details.ArchitectureOptions);
337-
IPlatform platform;
338-
if (details.PlatformName is null)
339-
platform = new DefaultPlatform(Services, arch);
340-
else
341-
platform = cfgSvc.GetEnvironment(details.PlatformName).Load(Services, arch);
343+
IPlatform platform = Platform.Load(Services, details.PlatformName, null, arch);
342344
Address addrLoad;
343345
if (loadingAddress is null)
344346
{

src/Decompiler/Loading/NullImageLoader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public override Address PreferredBaseAddress
7373
}
7474

7575
/// <inheritdoc/>
76-
public override Program LoadProgram(Address? addrLoad)
76+
public override Program LoadProgram(Address? addrLoad, string? platformOverride)
7777
{
7878
if (Architecture is null)
7979
throw new InvalidOperationException("A processor architecture must be specified.");
@@ -87,7 +87,7 @@ public override Program Load(Address? addrLoad, IProcessorArchitecture? arch)
8787
throw new InvalidOperationException("A processor architecture must be specified.");
8888
if (addrLoad is null)
8989
addrLoad = PreferredBaseAddress;
90-
var platform = Platform ?? new DefaultPlatform(Services, arch);
90+
var platform = Reko.Core.Platform.Load(Services, Platform, "", arch);
9191
return LoadProgram(addrLoad.Value, arch, platform, new());
9292
}
9393

src/Drivers/CmdLine/CmdLineDriver.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,14 @@ public static bool OverridesRequested(Dictionary<string,object> pArgs)
169169
private void Decompile(Dictionary<string, object> pArgs)
170170
{
171171
pArgs.TryGetValue("--loader", out object? imgLoader);
172+
pArgs.TryGetValue("--env", out object? environmentName);
172173
var addrLoad = ParseAddress(pArgs, "--base");
173174
try
174175
{
175176
var fileName = (string) pArgs["filename"];
176177
var filePath = Path.GetFullPath(fileName);
177178
var imageLocation = ImageLocation.FromUri(filePath);
178-
var loadedImage = ldr.Load(imageLocation, (string?) imgLoader, addrLoad);
179+
var loadedImage = ldr.Load(imageLocation, (string?) imgLoader, (string?)environmentName, addrLoad);
179180
Project project;
180181
switch (loadedImage)
181182
{

0 commit comments

Comments
 (0)