Skip to content

Commit 7cd8794

Browse files
committed
Progressing with assembly stores + shared libraries
1 parent 4550bef commit 7cd8794

14 files changed

+370
-43
lines changed

tools/apput/src/ApplicationAssembly/ApplicationAssembly.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ public class ApplicationAssembly : IAspect
1313
public ulong Size { get; private set; }
1414
public bool IgnoreOnLoad { get; private set; }
1515

16-
public static IAspect LoadAspect (Stream stream, string? description)
16+
public static IAspect LoadAspect (Stream stream, IAspectState state, string? description)
1717
{
1818
throw new NotImplementedException ();
1919
}
2020

21-
public static bool ProbeAspect (Stream stream, string? description)
21+
public static IAspectState ProbeAspect (Stream stream, string? description)
2222
{
2323
throw new NotImplementedException ();
2424
}

tools/apput/src/AssemblyStore/AssemblyStore.cs

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,46 +18,78 @@ public class AssemblyStore : IAspect
1818
public AndroidTargetArch Architecture { get; private set; } = AndroidTargetArch.None;
1919
public ulong NumberOfAssemblies => (ulong)(Assemblies?.Count ?? 0);
2020

21-
public static IAspect LoadAspect (Stream stream, string? description)
21+
public static IAspect LoadAspect (Stream stream, IAspectState state, string? description)
2222
{
23+
var storeState = state as AssemblyStoreAspectState;
2324
throw new NotImplementedException ();
2425
}
2526

26-
public static bool ProbeAspect (Stream stream, string? description)
27+
public static IAspectState ProbeAspect (Stream stream, string? description)
2728
{
28-
// TODO: check if it's an ELF .so and extract the payload, if necessary
29+
Stream? storeStream = null;
2930

31+
try {
32+
IAspectState state = SharedLibrary.ProbeAspect (stream, description);
33+
if (!state.Success) {
34+
return DoProbeAspect (stream, description);
35+
}
36+
37+
var library = (SharedLibrary)SharedLibrary.LoadAspect (stream, state, description);
38+
if (!library.HasAndroidPayload) {
39+
Log.Debug ($"AssemblyStore: stream ('{description}') is an ELF shared library, without payload");
40+
return new BasicAspectState (false);
41+
}
42+
Log.Debug ($"AssemblyStore: stream ('{description}') is an ELF shared library with .NET for Android payload section");
43+
storeStream = library.OpenAndroidPayload ();
44+
return DoProbeAspect (storeStream, description);
45+
} finally {
46+
storeStream?.Dispose ();
47+
}
48+
}
49+
50+
// We return `BasicAspectState` instance for all failures, since there's no extra information we can
51+
// pass on.
52+
static IAspectState DoProbeAspect (Stream storeStream, string? description)
53+
{
3054
// All assembly store files are at least 8 bytes long - space taken up by
3155
// the magic number + store version.
32-
if (stream.Length < MinimumStoreSize) {
56+
if (storeStream.Length < MinimumStoreSize) {
3357
Log.Debug ($"AssemblyStore: stream ('{description}') isn't long enough. Need at least {MinimumStoreSize} bytes");
34-
return false;
58+
return new BasicAspectState (false);
3559
}
3660

37-
stream.Seek (0, SeekOrigin.Begin);
38-
using var reader = new BinaryReader (stream, Encoding.UTF8, leaveOpen: true);
61+
storeStream.Seek (0, SeekOrigin.Begin);
62+
using var reader = new BinaryReader (storeStream, Encoding.UTF8, leaveOpen: true);
3963
uint magic = reader.ReadUInt32 ();
4064
if (magic != MagicNumber) {
4165
Log.Debug ($"AssemblyStore: stream ('{description}') doesn't have the correct signature.");
42-
return false;
66+
return new BasicAspectState (false);
4367
}
4468

4569
uint version = reader.ReadUInt32 ();
4670

4771
// We currently support version 3. Main store version is kept in the lower 16 bits of the version word
4872
uint mainVersion = version & 0xFFFF;
73+
FormatBase? validator = null;
74+
4975
switch (mainVersion) {
76+
case 2:
77+
validator = new Format_V2 (storeStream, description);
78+
break;
79+
5080
case 3:
51-
return ValidateFormatVersion3 (stream, description);
81+
validator = new Format_V3 (storeStream, description);
82+
break;
5283

5384
default:
5485
Log.Debug ($"AssemblyStore: unsupported store version: {mainVersion}");
55-
return false;
86+
return new BasicAspectState (false);
5687
}
57-
}
5888

59-
static bool ValidateFormatVersion3 (Stream stream, string? description)
60-
{
61-
return true;
89+
if (validator == null) {
90+
throw new InvalidOperationException ("Internal error: validator should never be null here");
91+
}
92+
93+
return validator.Validate ();
6294
}
6395
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
3+
namespace ApplicationUtility;
4+
5+
class AssemblyStoreAspectState : BasicAspectState
6+
{
7+
public AssemblyStoreHeader Header { get; }
8+
public AssemblyStoreIndex Index { get; }
9+
10+
public AssemblyStoreAspectState (bool success)
11+
: base (success)
12+
{}
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using ApplicationUtility;
2+
3+
class AssemblyStoreIndex
4+
{
5+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.IO;
2+
3+
namespace ApplicationUtility;
4+
5+
abstract class FormatBase
6+
{
7+
protected Stream StoreStream { get; }
8+
protected string? Description { get; }
9+
10+
protected FormatBase (Stream storeStream, string? description)
11+
{
12+
this.StoreStream = storeStream;
13+
this.Description = description;
14+
}
15+
16+
public abstract IAspectState Validate ();
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.IO;
3+
4+
namespace ApplicationUtility;
5+
6+
class Format_V2 : FormatBase
7+
{
8+
public Format_V2 (Stream storeStream, string? description)
9+
: base (storeStream, description)
10+
{}
11+
12+
public override IAspectState Validate ()
13+
{
14+
throw new NotImplementedException ();
15+
}
16+
}
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1+
using System.IO;
2+
13
namespace ApplicationUtility;
24

3-
class Format_V3
5+
class Format_V3 : FormatBase
46
{
7+
public Format_V3 (Stream storeStream, string? description)
8+
: base (storeStream, description)
9+
{}
10+
11+
public override IAspectState Validate ()
12+
{
13+
// TODO: validate that the store has correct format and populate the state below accordingly
14+
// to save time later.
15+
return new AssemblyStoreAspectState (true);
16+
}
517
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace ApplicationUtility;
2+
3+
class BasicAspectState : IAspectState
4+
{
5+
public bool Success { get; }
6+
7+
public BasicAspectState (bool success)
8+
{
9+
Success = success;
10+
}
11+
}

tools/apput/src/Common/IAspect.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ public interface IAspect
2323
/// `false` otherwise. The <paramref name="description"/> parameter can be anything that makes
2424
/// sense for the given aspect (e.g. a file name).
2525
/// </summary>
26-
static bool ProbeAspect (Stream stream, string? description = null) => throw new NotImplementedException ();
26+
static IAspectState ProbeAspect (Stream stream, string? description = null) => throw new NotImplementedException ();
2727

2828
/// <summary>
2929
/// Load the aspect and return instance of a class implementing support for it.
3030
/// The <paramref name="description"/> parameter can be anything that makes
3131
/// sense for the given aspect (e.g. a file name).
3232
/// </summary>
33-
static IAspect LoadAspect (Stream stream, string? description = null) => throw new NotImplementedException ();
33+
static IAspect LoadAspect (Stream stream, IAspectState state, string? description = null) => throw new NotImplementedException ();
3434
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace ApplicationUtility;
2+
3+
/// <summary>
4+
/// An empty interface which can be used by the aspect detection mechanism to
5+
/// preserve some state between <see cref="IAspect.ProbeAspect"/> and
6+
/// <see cref="IAspect.LoadAspect"/> calls, to optimize resource usage.
7+
/// </summary>
8+
public interface IAspectState
9+
{
10+
/// <summary>
11+
/// Indicates that whatever method returned instance of this interface, the operation was
12+
/// successful if `true`.
13+
/// </summary>
14+
bool Success { get; }
15+
}

0 commit comments

Comments
 (0)