diff --git a/libexeinfo/ELF/ELF.cs b/libexeinfo/ELF/ELF.cs
index 8e66e62..191dbb3 100644
--- a/libexeinfo/ELF/ELF.cs
+++ b/libexeinfo/ELF/ELF.cs
@@ -190,7 +190,7 @@ namespace libexeinfo
buffer = new byte[sections[i].sh_size];
BaseStream.Read(buffer, 0, buffer.Length);
- if(sectionNames[i] == ".interp" || sectionNames[i] == ".dynstr" || sectionNames[i] == ".comment")
+ if(sectionNames[i] == ".interp" || sectionNames[i] == ".dynstr" || sectionNames[i] == ".comment" || sectionNames[i] == ".strtab")
{
strStart = 0;
len = 0;
@@ -211,7 +211,7 @@ namespace libexeinfo
len++;
}
}
- else if(sectionNames[i].StartsWith(".note"))
+ else if(sectionNames[i].StartsWith(".note") && buffer.Length > 12)
{
uint namesz = BitConverter.ToUInt32(buffer, 0);
uint descsz = BitConverter.ToUInt32(buffer, 4);
@@ -237,10 +237,10 @@ namespace libexeinfo
switch(Header.ei_class)
{
case eiClass.ELFCLASS32:
- pos += pos % 4;
+ pos += pos % 4 != 0 ? 4 - (pos % 4) : 0;
break;
case eiClass.ELFCLASS64:
- pos += pos % 8;
+ pos += pos % 8 != 0 ? 8 - (pos % 8) : 0;
break;
}
@@ -260,7 +260,78 @@ namespace libexeinfo
MajorVersion = (int)gnuAbiTag.major,
MinorVersion = (int)gnuAbiTag.minor
};
+ else if(!string.IsNullOrEmpty(interpreter))
+ RequiredOperatingSystem = new OperatingSystem {Name = interpreter};
}
+ else if(notes.TryGetValue(".note.netbsd.ident", out ElfNote netbsdIdent) && netbsdIdent.name == "NetBSD")
+ {
+ uint netbsdVersionConstant = BitConverter.ToUInt32(netbsdIdent.contents, 0);
+ if(IsBigEndian) netbsdVersionConstant = Swapping.Swap(netbsdVersionConstant);
+
+ if(netbsdVersionConstant > 100000000)
+ {
+ RequiredOperatingSystem = new OperatingSystem
+ {
+ Name = "NetBSD",
+ MajorVersion = (int)(netbsdVersionConstant / 100000000),
+ MinorVersion = (int)((netbsdVersionConstant / 1000000) % 100)
+ };
+ }
+ else
+ {
+ RequiredOperatingSystem = new OperatingSystem
+ {
+ Name = "NetBSD"
+ };
+ }
+ }
+ else if(notes.TryGetValue(".note.minix.ident", out ElfNote minixIdent) && minixIdent.name == "Minix")
+ {
+ uint minixVersionConstant = BitConverter.ToUInt32(minixIdent.contents, 0);
+ if(IsBigEndian) minixVersionConstant = Swapping.Swap(minixVersionConstant);
+
+ if(minixVersionConstant > 100000000)
+ {
+ RequiredOperatingSystem = new OperatingSystem
+ {
+ Name = "MINIX",
+ MajorVersion = (int)(minixVersionConstant / 100000000),
+ MinorVersion = (int)((minixVersionConstant / 1000000) % 100)
+ };
+ }
+ else
+ {
+ RequiredOperatingSystem = new OperatingSystem
+ {
+ Name = "MINIX"
+ };
+ }
+ }
+ else if(notes.TryGetValue(".note.openbsd.ident", out ElfNote openbsdIdent) && openbsdIdent.name == "OpenBSD")
+ {
+ RequiredOperatingSystem = new OperatingSystem
+ {
+ Name = "OpenBSD"
+ };
+ }
+ else if(notes.TryGetValue(".note.tag", out ElfNote freebsdTag) && freebsdTag.name == "FreeBSD")
+ {
+ uint freebsdVersionConstant = BitConverter.ToUInt32(freebsdTag.contents, 0);
+ if(IsBigEndian) freebsdVersionConstant = Swapping.Swap(freebsdVersionConstant);
+
+ FreeBSDTag freeBsdVersion = DecodeFreeBSDTag(freebsdVersionConstant);
+
+ RequiredOperatingSystem = new OperatingSystem
+ {
+ Name = "FreeBSD",
+ MajorVersion = (int)freeBsdVersion.major,
+ MinorVersion = (int)freeBsdVersion.minor
+ };
+ }
+
+ else if(!string.IsNullOrEmpty(interpreter))
+ RequiredOperatingSystem = new OperatingSystem {Name = interpreter};
+
if(strings.Count > 0)
{
diff --git a/libexeinfo/ELF/Enums.cs b/libexeinfo/ELF/Enums.cs
index 98ec325..7ce2134 100644
--- a/libexeinfo/ELF/Enums.cs
+++ b/libexeinfo/ELF/Enums.cs
@@ -944,7 +944,11 @@ namespace libexeinfo
enum GnuAbiSystem : uint
{
- Linux = 0
+ Linux = 0,
+ Hurd = 1,
+ Solaris = 2,
+ kFreeBSD = 3,
+ kNetBSD = 4
}
}
}
\ No newline at end of file
diff --git a/libexeinfo/ELF/FreeBSD.cs b/libexeinfo/ELF/FreeBSD.cs
new file mode 100644
index 0000000..e73082c
--- /dev/null
+++ b/libexeinfo/ELF/FreeBSD.cs
@@ -0,0 +1,34 @@
+namespace libexeinfo
+{
+ public partial class ELF
+ {
+ static FreeBSDTag DecodeFreeBSDTag(uint desc)
+ {
+ FreeBSDTag tag = new FreeBSDTag {major = desc / 100000};
+
+ if(desc == 460002)
+ {
+ tag.major = 4;
+ tag.minor = 6;
+ tag.revision = 2;
+ }
+ else if(desc < 460100)
+ {
+ tag.minor = desc / 10000 % 10;
+ if(desc / 1000 % 10 > 0) tag.revision = desc / 1000 % 10;
+ }
+ else if(desc < 500000)
+ {
+ tag.minor = desc / 10000 % 10 + desc / 1000 % 10;
+ if(desc / 10 % 10 > 0) tag.revision = desc / 10 % 10;
+ }
+ else
+ {
+ tag.minor = desc / 1000 % 100;
+ if(desc / 10 % 10 > 0) tag.revision = desc / 10 % 10;
+ }
+
+ return tag;
+ }
+ }
+}
\ No newline at end of file
diff --git a/libexeinfo/ELF/Info.cs b/libexeinfo/ELF/Info.cs
index e562391..8899697 100644
--- a/libexeinfo/ELF/Info.cs
+++ b/libexeinfo/ELF/Info.cs
@@ -1,4 +1,5 @@
-using System.Text;
+using System;
+using System.Text;
namespace libexeinfo
{
@@ -83,12 +84,91 @@ namespace libexeinfo
sb.AppendFormat("\t\t\tLength: {0} bytes", note.contents.Length).AppendLine();
}
- if(notes.TryGetValue(".note.ABI-tag", out ElfNote abiTag))
+ if(notes.TryGetValue(".note.ABI-tag", out ElfNote abiTag) && abiTag.name == "GNU")
{
GnuAbiTag gnuAbiTag = DecodeGnuAbiTag(abiTag, IsBigEndian);
- if(gnuAbiTag != null)
- sb.AppendFormat("\tGNU ABI tag: Requires {0} version {1}.{2}.{3}", gnuAbiTag.system,
- gnuAbiTag.major, gnuAbiTag.minor, gnuAbiTag.revision).AppendLine();
+ sb.AppendFormat("\tGNU ABI tag: Requires {0} version {1}.{2}.{3}", gnuAbiTag.system,
+ gnuAbiTag.major, gnuAbiTag.minor, gnuAbiTag.revision).AppendLine();
+ }
+
+ if(notes.TryGetValue(".note.netbsd.ident", out ElfNote netbsdIdent) && netbsdIdent.name == "NetBSD")
+ {
+ uint netbsdVersionConstant = BitConverter.ToUInt32(netbsdIdent.contents, 0);
+ if(IsBigEndian) netbsdVersionConstant = Swapping.Swap(netbsdVersionConstant);
+
+ if(netbsdVersionConstant > 100000000)
+ {
+ uint nbsdPatch = (netbsdVersionConstant / 100) % 100;
+ uint nbsdRel = (netbsdVersionConstant / 10000) % 100;
+ uint nbsdMinor = (netbsdVersionConstant / 1000000) % 100;
+ uint nbsdMajor = netbsdVersionConstant / 100000000;
+
+ sb.AppendFormat("\tNetBSD version: {0}.{1}", nbsdMajor, nbsdMinor);
+
+ if(nbsdRel == 0 && nbsdPatch != 0) sb.AppendFormat(".{0}", nbsdPatch);
+ else if(nbsdRel != 0)
+ {
+ while(nbsdRel > 26)
+ {
+ sb.Append("Z");
+ nbsdRel -= 26;
+ }
+
+ sb.AppendFormat("{0}", (char)('A' + nbsdRel - 1));
+ }
+
+ sb.AppendLine();
+ }
+ else
+ {
+ sb.AppendFormat("\tNetBSD version constant: {0}", netbsdVersionConstant).AppendLine();
+ }
+ }
+
+ if(notes.TryGetValue(".note.minix.ident", out ElfNote minixIdent) && minixIdent.name == "Minix")
+ {
+ uint minixVersionConstant = BitConverter.ToUInt32(minixIdent.contents, 0);
+ if(IsBigEndian) minixVersionConstant = Swapping.Swap(minixVersionConstant);
+
+ if(minixVersionConstant > 100000000)
+ {
+ uint minixPath = (minixVersionConstant / 100) % 100;
+ uint minixRel = (minixVersionConstant / 10000) % 100;
+ uint minixMinor = (minixVersionConstant / 1000000) % 100;
+ uint minixMajor = minixVersionConstant / 100000000;
+
+ sb.AppendFormat("\tMINIX version: {0}.{1}", minixMajor, minixMinor);
+
+ if(minixRel == 0 && minixPath != 0) sb.AppendFormat(".{0}", minixPath);
+ else if(minixRel != 0)
+ {
+ while(minixRel > 26)
+ {
+ sb.Append("Z");
+ minixRel -= 26;
+ }
+
+ sb.AppendFormat("{0}", (char)('A' + minixRel - 1));
+ }
+
+ sb.AppendLine();
+ }
+ else
+ {
+ sb.AppendFormat("\tMINIX version constant: {0}", minixVersionConstant).AppendLine();
+ }
+ }
+
+ if(notes.TryGetValue(".note.tag", out ElfNote freebsdTag) && freebsdTag.name == "FreeBSD")
+ {
+ uint freebsdVersionConstant = BitConverter.ToUInt32(freebsdTag.contents, 0);
+ if(IsBigEndian) freebsdVersionConstant = Swapping.Swap(freebsdVersionConstant);
+
+ FreeBSDTag freeBsdVersion = DecodeFreeBSDTag(freebsdVersionConstant);
+
+ sb.AppendFormat("\tFreeBSD version: {0}.{1}");
+ if(freeBsdVersion.revision > 0) sb.AppendFormat("{0}", freeBsdVersion.revision);
+ sb.AppendLine();
}
if(notes.TryGetValue(".note.gnu.build-id", out ElfNote buildId))
diff --git a/libexeinfo/ELF/Structs.cs b/libexeinfo/ELF/Structs.cs
index 6d62ba1..803f00e 100644
--- a/libexeinfo/ELF/Structs.cs
+++ b/libexeinfo/ELF/Structs.cs
@@ -384,5 +384,12 @@ namespace libexeinfo
public uint minor;
public uint revision;
}
+
+ struct FreeBSDTag
+ {
+ public uint major;
+ public uint minor;
+ public uint revision;
+ }
}
}
\ No newline at end of file
diff --git a/libexeinfo/libexeinfo.csproj b/libexeinfo/libexeinfo.csproj
index 7c7b39a..9eb4087 100644
--- a/libexeinfo/libexeinfo.csproj
+++ b/libexeinfo/libexeinfo.csproj
@@ -57,6 +57,7 @@
+