in jvm/src/main/kotlin/com/jetbrains/util/filetype/elf/ElfUtil.kt [9:131]
fun GetElfInfo(@NotNull stream: SeekableByteChannel): ElfInfo {
val reader = BinaryReader(stream.Rewind())
try {
if (reader.ReadUInt32Be() != 0x7F454C46u)
error("Unknown format")
val ei_class: ElfClass = when (reader.ReadByte().toInt()) {
1 -> {
ElfClass.ELFCLASS32
}
2 -> {
ElfClass.ELFCLASS64
}
else ->
error("Inconsistent ELF class")
}
val isBe: Boolean
val ei_data: ElfData
when (reader.ReadByte().toInt()) {
1 -> {
isBe = false
ei_data = ElfData.ELFDATA2LSB
}
2 -> {
isBe = true
ei_data = ElfData.ELFDATA2MSB
}
else -> {
error("Inconsistent ELF data")
}
}
val version = ElfVersion.fromValue(reader.ReadByte())
if (version != ElfVersion.EV_CURRENT)
error("Inconsistent ELF version")
val osabi = ElfOsAbi.fromValue(reader.ReadByte())
val osAbiVersion = reader.ReadByte()
val type: ElfType
val machine: ElfMachine
val flags: ULong
var interpreter: String? = null
stream.Seek(7, SeekOrigin.Current)// skip EI_PAD
when (ei_class) {
ElfClass.ELFCLASS32 -> {
type = ElfType.fromValue(reader.ReadUInt16(isBe).toInt())
machine = ElfMachine.fromValue(reader.ReadUInt16(isBe).toInt())
val e_version32 = ElfVersion.fromValue(reader.ReadUInt32(isBe).toByte())
if (e_version32 != ElfVersion.EV_CURRENT)
error("Invalid version of ELF32 program header")
stream.Seek(4, SeekOrigin.Current)// skip e_entry
val ePhOff32 = reader.ReadUInt32(isBe)
stream.Seek(4, SeekOrigin.Current)// skip e_shoff
flags = reader.ReadUInt32(isBe).toULong()
stream.Seek(2, SeekOrigin.Current)// skip e_ehsize
val e_phentsize32 = reader.ReadUInt16(isBe)
val ePhNum32 = reader.ReadUInt16(isBe)
stream.Seek(ePhOff32.toLong(), SeekOrigin.Begin)
var phi = ePhNum32.toInt()
while (phi-- > 0) {
val p_type = reader.ReadUInt32(isBe).toInt()
if (p_type == ElfSegmentType.PT_INTERP) {
val pOffset32 = reader.ReadUInt32(isBe)
stream.Seek(8, SeekOrigin.Current)//skip p_vaddr, p_paddr
val pFileSz32 = reader.ReadUInt32(isBe)
stream.Seek(pOffset32.toLong(), SeekOrigin.Begin)
interpreter = reader.ReadString(pFileSz32.toInt() - 1)
break
}
stream.Seek(e_phentsize32.toLong() - 4, SeekOrigin.Current)
}
}
ElfClass.ELFCLASS64 -> {
type = ElfType.fromValue(reader.ReadUInt16(isBe).toInt())
machine = ElfMachine.fromValue(reader.ReadUInt16(isBe).toInt())
val e_version64 = ElfVersion.fromValue(reader.ReadUInt32(isBe).toByte())
if (e_version64 != ElfVersion.EV_CURRENT)
error("Invalid version of ELF64 program header")
stream.Seek(8, SeekOrigin.Current)// skip e_entry
val ePhOff64 = reader.ReadUInt64(isBe)
stream.Seek(8, SeekOrigin.Current)// skip e_shoff
flags = reader.ReadUInt32(isBe).toULong()
stream.Seek(2, SeekOrigin.Current)// skip e_ehsize
val e_phentsize64 = reader.ReadUInt16(isBe)
val ePhNum64 = reader.ReadUInt16(isBe)
stream.Seek(ePhOff64.toLong(), SeekOrigin.Begin)
var phi = ePhNum64.toInt()
while (phi-- > 0) {
val p_type = reader.ReadUInt32(isBe).toInt()
if (p_type == ElfSegmentType.PT_INTERP) {
stream.Seek(4, SeekOrigin.Current)//skip p_flags
val pOffset64 = reader.ReadUInt64(isBe)
stream.Seek(16, SeekOrigin.Current)//skip p_vaddr, p_paddr
val pFileSz64 = reader.ReadUInt64(isBe)
stream.Seek(pOffset64.toLong(), SeekOrigin.Begin)
interpreter = reader.ReadString(pFileSz64.toInt() - 1)
break
}
stream.Seek(e_phentsize64.toLong() - 4, SeekOrigin.Current)
}
}
else -> {
error("Unknown ELF class")
}
}
return ElfInfo(ei_class, ei_data, osabi, osAbiVersion, type, machine, flags, interpreter)
} catch (ex: IOException) {
error("Unknown format")
}
}