Skip to content

Commit

Permalink
Add ObjectList to manage ownership/parent more easily
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Sep 18, 2024
1 parent c855cea commit b46e2bc
Show file tree
Hide file tree
Showing 25 changed files with 906 additions and 366 deletions.
4 changes: 2 additions & 2 deletions src/LibObjectFile/Ar/ArArchiveFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void AddFile(ArFile file)
}

file.Parent = this;
file.Index = (uint)_files.Count;
file.Index = _files.Count;
_files.Add(file);
}

Expand Down Expand Up @@ -123,7 +123,7 @@ public void InsertFileAt(int index, ArFile file)
}
}

file.Index = (uint)index;
file.Index = index;
_files.Insert(index, file);
file.Parent = this;

Expand Down
157 changes: 78 additions & 79 deletions src/LibObjectFile/DiagnosticBag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,100 +8,99 @@
using System.Text;
using LibObjectFile.Utils;

namespace LibObjectFile
namespace LibObjectFile;

/// <summary>
/// A container for <see cref="DiagnosticMessage"/> used for error reporting while reading/writing object files.
/// </summary>
[DebuggerDisplay("Count = {Messages.Count}, HasErrors = {" + nameof(HasErrors) + "}")]
public class DiagnosticBag
{
/// <summary>
/// A container for <see cref="DiagnosticMessage"/> used for error reporting while reading/writing object files.
/// </summary>
[DebuggerDisplay("Count = {Messages.Count}, HasErrors = {" + nameof(HasErrors) + "}")]
public class DiagnosticBag
{
private readonly List<DiagnosticMessage> _messages;
private readonly List<DiagnosticMessage> _messages;

public DiagnosticBag()
{
_messages = new List<DiagnosticMessage>();
}
public DiagnosticBag()
{
_messages = new List<DiagnosticMessage>();
}

/// <summary>
/// List of messages.
/// </summary>
public ReadOnlyList<DiagnosticMessage> Messages => _messages;
/// <summary>
/// List of messages.
/// </summary>
public ReadOnlyList<DiagnosticMessage> Messages => _messages;

/// <summary>
/// If this instance contains error messages.
/// </summary>
public bool HasErrors { get; private set; }
/// <summary>
/// If this instance contains error messages.
/// </summary>
public bool HasErrors { get; private set; }

/// <summary>
/// Clear all messages.
/// </summary>
public void Clear()
{
_messages.Clear();
HasErrors = false;
}
/// <summary>
/// Clear all messages.
/// </summary>
public void Clear()
{
_messages.Clear();
HasErrors = false;
}

/// <summary>
/// Copy all the <see cref="Messages"/> in this bag to another bag.
/// </summary>
/// <param name="diagnostics">The diagnostics receiving the copy of the <see cref="Messages"/></param>
public void CopyTo(DiagnosticBag diagnostics)
/// <summary>
/// Copy all the <see cref="Messages"/> in this bag to another bag.
/// </summary>
/// <param name="diagnostics">The diagnostics receiving the copy of the <see cref="Messages"/></param>
public void CopyTo(DiagnosticBag diagnostics)
{
if (diagnostics == null) throw new ArgumentNullException(nameof(diagnostics));
foreach (var diagnosticMessage in Messages)
{
if (diagnostics == null) throw new ArgumentNullException(nameof(diagnostics));
foreach (var diagnosticMessage in Messages)
{
diagnostics.Log(diagnosticMessage);
}
diagnostics.Log(diagnosticMessage);
}
}

/// <summary>
/// Logs the specified <see cref="DiagnosticMessage"/>.
/// </summary>
/// <param name="message">The diagnostic message</param>
public void Log(DiagnosticMessage message)
/// <summary>
/// Logs the specified <see cref="DiagnosticMessage"/>.
/// </summary>
/// <param name="message">The diagnostic message</param>
public void Log(DiagnosticMessage message)
{
if (message.Message == null) throw new InvalidOperationException($"{nameof(DiagnosticMessage)}.{nameof(DiagnosticMessage.Message)} cannot be null");
_messages.Add(message);
if (message.Kind == DiagnosticKind.Error)
{
if (message.Message == null) throw new InvalidOperationException($"{nameof(DiagnosticMessage)}.{nameof(DiagnosticMessage.Message)} cannot be null");
_messages.Add(message);
if (message.Kind == DiagnosticKind.Error)
{
HasErrors = true;
}
HasErrors = true;
}
}

/// <summary>
/// Log an error <see cref="DiagnosticMessage"/>.
/// </summary>
/// <param name="id">The identifier of the diagnostic.</param>
/// <param name="message">The text of the message</param>
/// <param name="context">An optional context</param>
public void Error(DiagnosticId id, string message, object? context = null)
{
if (message == null) throw new ArgumentNullException(nameof(message));
Log(new DiagnosticMessage(DiagnosticKind.Error, id, message, context));
}
/// <summary>
/// Log an error <see cref="DiagnosticMessage"/>.
/// </summary>
/// <param name="id">The identifier of the diagnostic.</param>
/// <param name="message">The text of the message</param>
/// <param name="context">An optional context</param>
public void Error(DiagnosticId id, string message, object? context = null)
{
if (message == null) throw new ArgumentNullException(nameof(message));
Log(new DiagnosticMessage(DiagnosticKind.Error, id, message, context));
}

/// <summary>
/// Log an error <see cref="DiagnosticMessage"/>.
/// </summary>
/// <param name="id">The identifier of the diagnostic.</param>
/// <param name="message">The text of the message</param>
/// <param name="context">An optional context</param>
public void Warning(DiagnosticId id, string message, object? context = null)
{
if (message == null) throw new ArgumentNullException(nameof(message));
Log(new DiagnosticMessage(DiagnosticKind.Warning, id, message, context));
}
/// <summary>
/// Log an error <see cref="DiagnosticMessage"/>.
/// </summary>
/// <param name="id">The identifier of the diagnostic.</param>
/// <param name="message">The text of the message</param>
/// <param name="context">An optional context</param>
public void Warning(DiagnosticId id, string message, object? context = null)
{
if (message == null) throw new ArgumentNullException(nameof(message));
Log(new DiagnosticMessage(DiagnosticKind.Warning, id, message, context));
}

public override string ToString()
public override string ToString()
{
var builder = new StringBuilder();
foreach (var diagnosticMessage in Messages)
{
var builder = new StringBuilder();
foreach (var diagnosticMessage in Messages)
{
builder.AppendLine(diagnosticMessage.ToString());
}

return builder.ToString();
builder.AppendLine(diagnosticMessage.ToString());
}

return builder.ToString();
}
}
6 changes: 5 additions & 1 deletion src/LibObjectFile/DiagnosticId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,9 @@ public enum DiagnosticId
// PE Import
PE_ERR_ImportDirectoryInvalidEndOfStream = 3040,
PE_ERR_ImportLookupTableInvalidEndOfStream = 3041,
PE_ERR_ImportLookupTableInvalidHintNameTableRVA = 3042,
PE_ERR_ImportLookupTableInvalidParent = 3043,
PE_ERR_ImportDirectoryInvalidImportAddressTableRVA = 3044,
PE_ERR_ImportDirectoryInvalidImportLookupTableRVA = 3045,
}
}
}
8 changes: 4 additions & 4 deletions src/LibObjectFile/Elf/ElfObjectFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public void AddSegment(ElfSegment segment)
}

segment.Parent = this;
segment.Index = (uint)_segments.Count;
segment.Index = _segments.Count;
_segments.Add(segment);
}

Expand All @@ -351,7 +351,7 @@ public void InsertSegmentAt(int index, ElfSegment segment)
if (segment.Parent != this) throw new InvalidOperationException($"Cannot add the segment as it is already added to another {nameof(ElfObjectFile)} instance");
}

segment.Index = (uint)index;
segment.Index = index;
_segments.Insert(index, segment);
segment.Parent = this;

Expand Down Expand Up @@ -415,7 +415,7 @@ public TSection AddSection<TSection>(TSection section) where TSection : ElfSecti
}

section.Parent = this;
section.Index = (uint)_sections.Count;
section.Index = _sections.Count;
_sections.Add(section);

if (section.IsShadow)
Expand Down Expand Up @@ -454,7 +454,7 @@ public void InsertSectionAt(int index, ElfSection section)
}

section.Parent = this;
section.Index = (uint)index;
section.Index = index;
_sections.Insert(index, section);

if (section.IsShadow)
Expand Down
6 changes: 3 additions & 3 deletions src/LibObjectFile/ObjectFileExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static void Add<TParent, TChild>(this List<TChild> list, TParent parent,
}

element.Parent = parent;
element.Index = (uint)list.Count;
element.Index = list.Count;
list.Add(element);
}

Expand Down Expand Up @@ -63,7 +63,7 @@ public static void AddSorted<TParent, TChild>(this List<TChild> list, TParent pa
list.Insert(index, element);
}

element.Index = (uint)index;
element.Index = index;

// Update the index of following attributes
for (int i = index + 1; i < list.Count; i++)
Expand All @@ -88,7 +88,7 @@ public static void InsertAt<TParent, TChild>(this List<TChild> list, TParent par
if (element.Parent != parent) throw new InvalidOperationException($"Cannot add the {element.GetType()} as it is already added to another {parent.GetType()} instance");
}

element.Index = (uint)index;
element.Index = index;
list.Insert(index, element);
element.Parent = parent;

Expand Down
14 changes: 12 additions & 2 deletions src/LibObjectFile/ObjectFileNodeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public abstract class ObjectFileNodeBase
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObjectFileNodeBase? _parent;

protected ObjectFileNodeBase()
{
Index = -1;
}

/// <summary>
/// Gets or sets the position of this element relative to the top level parent.
/// </summary>
Expand Down Expand Up @@ -45,9 +50,14 @@ protected virtual void ValidateParent(ObjectFileNodeBase parent)
}

/// <summary>
/// Index within the containing list in a parent.
/// Index within the containing list in a parent. If this object is not part of a list, this value is -1.
/// </summary>
public uint Index { get; internal set; }
public int Index { get; internal set; }

internal void ResetIndex()
{
Index = -1;
}

/// <summary>
/// Gets or sets the size of this section or segment in the parent <see cref="TParentFile"/>.
Expand Down
32 changes: 9 additions & 23 deletions src/LibObjectFile/PE/DataDirectory/PEDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,19 @@ internal static PEDirectory Create(ImageDataDirectoryKind kind, RVALink<PESectio
ImageDataDirectoryKind.LoadConfig => new PELoadConfigDirectory(),
ImageDataDirectoryKind.BoundImport => new PEBoundImportDirectory(),
ImageDataDirectoryKind.DelayImport => new PEDelayImportDirectory(),
ImageDataDirectoryKind.ImportAddressTable => new PEImportAddressTable(),
ImageDataDirectoryKind.ImportAddressTable => new PEImportAddressTableDirectory(),
ImageDataDirectoryKind.ClrMetadata => new PEClrMetadata(),
_ => throw new ArgumentOutOfRangeException(nameof(kind))
};
}

protected override void ValidateParent(ObjectFileNodeBase parent)
{
if (parent is not PESection)
{
throw new ArgumentException($"Invalid parent type [{parent?.GetType()}] for [{GetType()}]");
}
}
}

public sealed class PEExportDirectory : PEDirectory
Expand Down Expand Up @@ -178,28 +186,6 @@ protected override void Write(PEImageWriter writer)
}
}

public sealed class PEImportAddressTable : PEDirectory
{
public PEImportAddressTable() : base(ImageDataDirectoryKind.ImportAddressTable)
{
}

public override void UpdateLayout(DiagnosticBag diagnostics)
{
throw new NotImplementedException();
}

protected override void Read(PEImageReader reader)
{
throw new NotImplementedException();
}

protected override void Write(PEImageWriter writer)
{
throw new NotImplementedException();
}
}

public sealed class PETlsDirectory : PEDirectory
{
public PETlsDirectory() : base(ImageDataDirectoryKind.Tls)
Expand Down
2 changes: 1 addition & 1 deletion src/LibObjectFile/PE/DataDirectory/PEDirectoryTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ internal PEDirectoryTable()
/// <summary>
/// Gets the import address table directory information from the PE file.
/// </summary>
public PEImportAddressTable? ImportAddressTable => (PEImportAddressTable?)this[ImageDataDirectoryKind.ImportAddressTable];
public PEImportAddressTableDirectory? ImportAddressTable => (PEImportAddressTableDirectory?)this[ImageDataDirectoryKind.ImportAddressTable];

/// <summary>
/// Gets the CLR metadata directory information from the PE file, if present.
Expand Down
Loading

0 comments on commit b46e2bc

Please sign in to comment.