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