8
8
9
9
namespace ApplicationUtility ;
10
10
11
- class SharedLibrary : IAspect , IDisposable
11
+ public class SharedLibrary : IAspect , IDisposable
12
12
{
13
13
const uint ELF_MAGIC = 0x464c457f ;
14
14
const string DebugLinkSectionName = ".gnu_debuglink" ;
15
15
const string PayloadSectionName = "payload" ;
16
16
17
- readonly IELF elf ;
18
- readonly NativeArchitecture nativeArch = NativeArchitecture . Unknown ;
19
- readonly Stream libraryStream ;
20
- readonly bool hasDebugInfo ;
21
- readonly bool is64Bit ;
22
- readonly string libraryName ;
23
17
readonly string ? androidIdent ;
24
18
readonly string ? buildId ;
25
19
readonly string ? debugLink ;
20
+ readonly IELF elf ;
21
+ readonly bool hasDebugInfo ;
22
+ readonly bool is64Bit ;
26
23
readonly ulong libraryAlignment ;
24
+ readonly string libraryName ;
25
+ readonly Stream libraryStream ;
26
+ readonly NativeArchitecture nativeArch = NativeArchitecture . Unknown ;
27
27
readonly ulong payloadOffset ;
28
28
readonly ulong payloadSize ;
29
+ readonly string ? soname ;
29
30
30
31
bool disposed ;
31
32
32
33
public static string AspectName { get ; } = "Native shared library" ;
33
34
34
- public NativeArchitecture TargetArchitecture => nativeArch ;
35
+ public ulong Alignment => libraryAlignment ;
36
+ public bool AlignmentCompatibleWith16k => libraryAlignment >= 0x4000 && ( libraryAlignment % 0x4000 == 0 ) ;
37
+ public string ? AndroidIdent => androidIdent ;
38
+ public string ? BuildID => buildId ;
39
+ public string ? DebugLink => debugLink ;
35
40
public bool HasAndroidIdent => ! String . IsNullOrEmpty ( androidIdent ) ;
36
41
public bool HasAndroidPayload => payloadSize > 0 ;
37
42
public bool HasBuildID => ! String . IsNullOrEmpty ( buildId ) ;
38
43
public bool HasDebugInfo => hasDebugInfo ;
39
44
public bool HasDebugLink => ! String . IsNullOrEmpty ( debugLink ) ;
45
+ public bool HasSoname => ! String . IsNullOrEmpty ( soname ) ;
40
46
public bool Is64Bit => is64Bit ;
41
47
public string Name => libraryName ;
42
- public string ? AndroidIdent => androidIdent ;
43
- public string ? BuildID => buildId ;
44
- public string ? DebugLink => debugLink ;
45
- public ulong Alignment => libraryAlignment ;
48
+ public string ? Soname => soname ;
49
+ public NativeArchitecture TargetArchitecture => nativeArch ;
46
50
47
51
protected IELF ELF => elf ;
48
52
@@ -56,6 +60,7 @@ protected SharedLibrary (Stream stream, string libraryName)
56
60
( hasDebugInfo , debugLink ) = DetectDebugInfo ( elf , libraryName ) ;
57
61
buildId = GetBuildID ( elf , is64Bit ) ;
58
62
androidIdent = GetAndroidIdent ( elf , is64Bit ) ;
63
+ soname = GetSoname ( elf , is64Bit ) ;
59
64
}
60
65
61
66
public static IAspect LoadAspect ( Stream stream , IAspectState ? state , string ? description )
@@ -291,23 +296,73 @@ static ulong DetectAlignment (IELF elf, bool is64Bit)
291
296
return 0 ;
292
297
}
293
298
299
+ static string ? GetSoname ( IELF elf , bool is64Bit )
300
+ {
301
+ IDynamicEntry ? sonameEntry = null ;
302
+
303
+ foreach ( IDynamicSection section in elf . GetSections < IDynamicSection > ( ) ) {
304
+ foreach ( IDynamicEntry dyne in section . Entries ) {
305
+ if ( dyne . Tag != DynamicTag . SoName ) {
306
+ continue ;
307
+ }
308
+ sonameEntry = dyne ;
309
+ break ;
310
+ }
311
+
312
+ if ( sonameEntry != null ) {
313
+ break ;
314
+ }
315
+ }
316
+
317
+ if ( sonameEntry == null ) {
318
+ return null ;
319
+ }
320
+
321
+ ulong stringIndex = is64Bit switch {
322
+ true => ( ( DynamicEntry < ulong > ) sonameEntry ) . Value ,
323
+ false => ( ( DynamicEntry < uint > ) sonameEntry ) . Value
324
+ } ;
325
+
326
+ // Offset is into the .dynstr section
327
+ if ( ! elf . TryGetSection ( ".dynstr" , out ISection ? strtabSection ) || strtabSection == null || strtabSection . Type != SectionType . StringTable ) {
328
+ return null ;
329
+ }
330
+
331
+ var strtab = ( IStringTable ) strtabSection ;
332
+ try {
333
+ return strtab [ ( long ) stringIndex ] ;
334
+ } catch ( Exception ex ) {
335
+ Log . Debug ( $ "Failed to obtain soname from the string table (asked for index { stringIndex } )", ex ) ;
336
+ return null ;
337
+ }
338
+ }
339
+
294
340
static string ? GetBuildID ( IELF elf , bool is64Bit )
295
341
{
296
- byte [ ] ? contents = GetNoteSectionContents ( elf , is64Bit , ".note.gnu.build-id" ) ;
342
+ // From elf_common.h
343
+ //
344
+ // #define NT_GNU_BUILD_ID 3
345
+ //
346
+ const ulong NT_GNU_BUILD_ID = 0 ;
347
+ byte [ ] ? contents = GetNoteSectionContents ( elf , is64Bit , ".note.gnu.build-id" , NT_GNU_BUILD_ID ) ;
297
348
if ( contents == null ) {
298
349
return null ;
299
350
}
300
351
301
- // TODO: decode
302
- return "decoding not implemented yet" ;
352
+ var sb = new StringBuilder ( ) ;
353
+ foreach ( byte b in contents ) {
354
+ sb . Append ( $ "{ b : x02} ") ;
355
+ }
356
+
357
+ return sb . ToString ( ) ;
303
358
}
304
359
305
360
static string ? GetAndroidIdent ( IELF elf , bool is64Bit )
306
361
{
307
362
return GetNoteSectionContentsAsString ( elf , is64Bit , ".note.android.ident" ) ; ;
308
363
}
309
364
310
- static string ? GetNoteSectionContentsAsString ( IELF elf , bool is64Bit , string sectionName )
365
+ static string ? GetNoteSectionContentsAsString ( IELF elf , bool is64Bit , string sectionName , ulong noteType = 0 )
311
366
{
312
367
byte [ ] ? contents = GetNoteSectionContents ( elf , is64Bit , sectionName ) ;
313
368
if ( contents == null ) {
@@ -317,13 +372,27 @@ static ulong DetectAlignment (IELF elf, bool is64Bit)
317
372
return Encoding . UTF8 . GetString ( contents ) ;
318
373
}
319
374
320
- static byte [ ] ? GetNoteSectionContents ( IELF elf , bool is64Bit , string sectionName )
375
+ static byte [ ] ? GetNoteSectionContents ( IELF elf , bool is64Bit , string sectionName , ulong noteType = 0 )
321
376
{
322
377
if ( ! elf . TryGetSection ( sectionName , out ISection ? section ) || section == null || section . Type != SectionType . Note ) {
323
378
return null ;
324
379
}
325
380
326
- return ( ( INoteSection ) section ) . Description ;
381
+ var note = ( INoteSection ) section ;
382
+ if ( noteType == 0 ) {
383
+ return note . Description ;
384
+ }
385
+
386
+ ulong type = is64Bit switch {
387
+ true => ( ( NoteSection < ulong > ) note ) . NoteType ,
388
+ false => ( ( NoteSection < uint > ) note ) . NoteType
389
+ } ;
390
+
391
+ if ( type != noteType ) {
392
+ return null ;
393
+ }
394
+
395
+ return note . Description ;
327
396
}
328
397
329
398
public bool HasSection ( string name , SectionType type = SectionType . Null )
0 commit comments