Skip to content

Commit bf73964

Browse files
committed
Add Elf dynamic support
1 parent 09365c1 commit bf73964

4 files changed

Lines changed: 393 additions & 0 deletions

File tree

src/LibObjectFile/Elf/ElfSectionHeaderTable.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ private static ElfSection CreateElfSection(ElfReader reader, uint sectionIndex,
133133
ElfSectionType.Note => new ElfNoteTable(),
134134
ElfSectionType.SymbolTableSectionHeaderIndices => new ElfSymbolTableSectionHeaderIndices(),
135135
ElfSectionType.NoBits => new ElfNoBitsSection(),
136+
ElfSectionType.DynamicLinking => new ElfDynamicLinkingTable(),
136137
_ => new ElfStreamSection(sectionType)
137138
};
138139
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
2+
// This file is licensed under the BSD-Clause 2 license.
3+
// See the license.txt file in the project root for more information.
4+
5+
namespace LibObjectFile.Elf
6+
{
7+
/// <summary>
8+
/// Dynamic table entry for ELF.
9+
/// </summary>
10+
public record struct ElfDynamic
11+
{
12+
/// <summary>
13+
/// Type of dynamic table entry.
14+
/// </summary>
15+
public long Tag { get; set; }
16+
17+
/// <summary>
18+
/// Integer value of entry.
19+
/// </summary>
20+
public ulong Value { get; set; }
21+
22+
/// <summary>
23+
/// Pointer value of entry.
24+
/// </summary>
25+
public ulong Pointer => Value;
26+
27+
/// <summary>
28+
/// Dynamic Tag
29+
/// </summary>
30+
public ElfDynamicTag TagType => (ElfDynamicTag)Tag;
31+
}
32+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
2+
// This file is licensed under the BSD-Clause 2 license.
3+
// See the license.txt file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Runtime.CompilerServices;
9+
using System.Runtime.InteropServices;
10+
using LibObjectFile.Diagnostics;
11+
using LibObjectFile.IO;
12+
13+
namespace LibObjectFile.Elf
14+
{
15+
public class ElfDynamicLinkingTable : ElfSection
16+
{
17+
private Stream _stream;
18+
private bool _is32;
19+
20+
public Stream Stream
21+
{
22+
get => _stream;
23+
set
24+
{
25+
ArgumentNullException.ThrowIfNull(value);
26+
_stream = value;
27+
Size = (ulong)_stream.Length;
28+
}
29+
}
30+
31+
public List<ElfDynamic> Entries { get; }
32+
33+
public ElfDynamicLinkingTable() : base(ElfSectionType.DynamicLinking)
34+
{
35+
Name = ElfSectionSpecialType.Dynamic.GetDefaultName();
36+
Flags = ElfSectionSpecialType.Dynamic.GetSectionFlags();
37+
_stream = new MemoryStream();
38+
39+
Entries = [];
40+
}
41+
42+
public override void Read(ElfReader reader)
43+
{
44+
reader.Position = Position;
45+
Entries.Clear();
46+
47+
var numberOfEntries = (int)(base.Size / base.TableEntrySize);
48+
var entries = Entries;
49+
CollectionsMarshal.SetCount(entries, numberOfEntries);
50+
51+
if (_is32)
52+
Read32(reader, numberOfEntries);
53+
else
54+
Read64(reader, numberOfEntries);
55+
}
56+
57+
private void Read32(ElfReader reader, int numberOfEntries)
58+
{
59+
using var batch = new BatchDataReader<ElfNative.Elf32_Dyn>(reader.Stream, numberOfEntries);
60+
var span = CollectionsMarshal.AsSpan(Entries);
61+
ref var entry = ref MemoryMarshal.GetReference(span);
62+
while (batch.HasNext())
63+
{
64+
ref var dyn = ref batch.Read();
65+
66+
entry.Tag = reader.Decode(dyn.d_tag);
67+
entry.Value = reader.Decode(dyn.d_un.d_val);
68+
69+
entry = ref Unsafe.Add(ref entry, 1);
70+
}
71+
}
72+
73+
private void Read64(ElfReader reader, int numberOfEntries)
74+
{
75+
using var batch = new BatchDataReader<ElfNative.Elf64_Dyn>(reader.Stream, numberOfEntries);
76+
var span = CollectionsMarshal.AsSpan(Entries);
77+
ref var entry = ref MemoryMarshal.GetReference(span);
78+
while (batch.HasNext())
79+
{
80+
ref var dyn = ref batch.Read();
81+
82+
entry.Tag = reader.Decode(dyn.d_tag);
83+
entry.Value = reader.Decode(dyn.d_un.d_val);
84+
85+
entry = ref Unsafe.Add(ref entry, 1);
86+
}
87+
}
88+
89+
public override void Write(ElfWriter writer)
90+
{
91+
if (_is32)
92+
Write32(writer);
93+
else
94+
Write64(writer);
95+
}
96+
97+
private void Write32(ElfWriter writer)
98+
{
99+
var entries = CollectionsMarshal.AsSpan(Entries);
100+
using var batch = new BatchDataWriter<ElfNative.Elf32_Dyn>(writer.Stream, entries.Length);
101+
var dyn = new ElfNative.Elf32_Dyn();
102+
for (int i = 0; i < entries.Length; i++)
103+
{
104+
ref var entry = ref entries[i];
105+
106+
writer.Encode(out dyn.d_tag, (int)entry.Tag);
107+
writer.Encode(out dyn.d_un.d_val, (uint)entry.Value);
108+
109+
batch.Write(dyn);
110+
}
111+
}
112+
113+
private void Write64(ElfWriter writer)
114+
{
115+
var entries = CollectionsMarshal.AsSpan(Entries);
116+
using var batch = new BatchDataWriter<ElfNative.Elf64_Dyn>(writer.Stream, entries.Length);
117+
var dyn = new ElfNative.Elf64_Dyn();
118+
for (int i = 0; i < entries.Length; i++)
119+
{
120+
ref var entry = ref entries[i];
121+
122+
writer.Encode(out dyn.d_tag, entry.Tag);
123+
writer.Encode(out dyn.d_un.d_val, entry.Value);
124+
125+
batch.Write(dyn);
126+
}
127+
}
128+
129+
protected override unsafe void ValidateParent(ObjectElement parent)
130+
{
131+
base.ValidateParent(parent);
132+
133+
var elf = (ElfFile)parent;
134+
_is32 = elf.FileClass == ElfFileClass.Is32;
135+
136+
BaseTableEntrySize = (uint)(_is32 ? sizeof(ElfNative.Elf32_Dyn) : sizeof(ElfNative.Elf64_Dyn));
137+
AdditionalTableEntrySize = 0;
138+
}
139+
140+
internal override unsafe void InitializeEntrySizeFromRead(DiagnosticBag diagnostics, ulong entrySize, bool is32)
141+
{
142+
_is32 = is32;
143+
144+
if (is32)
145+
throw new NotImplementedException();
146+
else
147+
{
148+
if (entrySize != (ulong)sizeof(ElfNative.Elf64_Dyn))
149+
diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSectionEntrySize, $"Invalid size [{entrySize}] for dynamic entry. Expecting to be equal to [{sizeof(ElfNative.Elf64_Dyn)}] bytes.");
150+
else
151+
{
152+
BaseTableEntrySize = (uint)sizeof(ElfNative.Elf64_Dyn);
153+
AdditionalTableEntrySize = (uint)(entrySize - AdditionalTableEntrySize);
154+
}
155+
}
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)