diff --git a/plugins/elf.lua b/plugins/elf.lua new file mode 100644 index 0000000..6fa2223 --- /dev/null +++ b/plugins/elf.lua @@ -0,0 +1,309 @@ +-- +-- elf.lua: Executable and Linkable Format +-- +-- Copyright (c) 2017, Přemysl Janouch +-- +-- Permission to use, copy, modify, and/or distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +-- + +local detect = function (c) + return c:read (4) == "\x7FELF" +end + +local type_table = { + [0] = "no file type", + [1] = "relocatable file", + [2] = "executable file", + [3] = "shared object file", + [4] = "core file" +} + +local machine_table = { + [0] = "no machine", + [1] = "AT&T WE 32100", + [2] = "SPARC", + [3] = "Intel 386", + [4] = "Motorola 68000", + [5] = "Motorola 88000", + [6] = "Intel MCU", + [7] = "Intel 80860", + [8] = "MIPS R3000", + [9] = "IBM System/370", + [10] = "MIPS RS3000 Little-endian", + [15] = "Hewlett-Packard PA-RISC", + [17] = "Fujitsu VPP500", + [18] = "Enhanced instruction set SPARC", + [19] = "Intel 80960", + [20] = "PowerPC", + [21] = "PowerPC64", + [22] = "IBM System/390", + [23] = "IBM SPU/SPC", + [36] = "NEC V800", + [37] = "Fujitsu FR20", + [38] = "TRW RH-32", + [39] = "Motorola RCE", + [40] = "ARM", + [41] = "DEC Alpha", + [42] = "Hitachi SH", + [43] = "SPARC V9", + [44] = "Siemens TriCore", + [45] = "Argonaut RISC Core", + [46] = "Hitachi H8/300", + [47] = "Hitachi H8/300H", + [48] = "Hitachi H8S", + [49] = "Hitachi H8/500", + [50] = "Intel IA-64 processor architecture", + [51] = "Stanford MIPS-X", + [52] = "Motorola ColdFire", + [53] = "Motorola M68HC12", + [54] = "Fujitsu MMA Multimedia Accelerator", + [55] = "Siemens PCP", + [56] = "Sony nCPU embedded RISC processor", + [57] = "Denso NDR1 microprocessor", + [58] = "Motorola Star*Core processor", + [59] = "Toyota ME16 processor", + [60] = "STMicroelectronics ST100 processor", + [61] = "Advanced Logic Corp. TinyJ embedded processor family", + [62] = "AMD x86-64 architecture", + [63] = "Sony DSP Processor", + [64] = "Digital Equipment Corp. PDP-10", + [65] = "Digital Equipment Corp. PDP-11", + [66] = "Siemens FX66 microcontroller", + [67] = "STMicroelectronics ST9+ 8/16 bit microcontroller", + [68] = "STMicroelectronics ST7 8-bit microcontroller", + [69] = "Motorola MC68HC16 Microcontroller", + [70] = "Motorola MC68HC11 Microcontroller", + [71] = "Motorola MC68HC08 Microcontroller", + [72] = "Motorola MC68HC05 Microcontroller", + [73] = "Silicon Graphics SVx", + [74] = "STMicroelectronics ST19 8-bit microcontroller", + [75] = "Digital VAX", + [76] = "Axis Communications 32-bit embedded processor", + [77] = "Infineon Technologies 32-bit embedded processor", + [78] = "Element 14 64-bit DSP Processor", + [79] = "LSI Logic 16-bit DSP Processor", + [80] = "Donald Knuth's educational 64-bit processor", + [81] = "Harvard University machine-independent object files", + [82] = "SiTera Prism", + [83] = "Atmel AVR 8-bit microcontroller", + [84] = "Fujitsu FR30", + [85] = "Mitsubishi D10V", + [86] = "Mitsubishi D30V", + [87] = "NEC v850", + [88] = "Mitsubishi M32R", + [89] = "Matsushita MN10300", + [90] = "Matsushita MN10200", + [91] = "picoJava", + [92] = "OpenRISC 32-bit embedded processor", + [93] = "ARC International ARCompact processor", + [94] = "Tensilica Xtensa Architecture", + [95] = "Alphamosaic VideoCore processor", + [96] = "Thompson Multimedia General Purpose Processor", + [97] = "National Semiconductor 32000 series", + [98] = "Tenor Network TPC processor", + [99] = "Trebia SNP 1000 processor", + [100] = "STMicroelectronics (www.st.com) ST200", + [101] = "Ubicom IP2xxx microcontroller family", + [102] = "MAX Processor", + [103] = "National Semiconductor CompactRISC microprocessor", + [104] = "Fujitsu F2MC16", + [105] = "Texas Instruments embedded microcontroller msp430", + [106] = "Analog Devices Blackfin (DSP) processor", + [107] = "S1C33 Family of Seiko Epson processors", + [108] = "Sharp embedded microprocessor", + [109] = "Arca RISC Microprocessor", + [110] = "microprocessor series from PKU-Unity Ltd." .. + " and MPRC of Peking University", + [111] = "eXcess: 16/32/64-bit configurable embedded CPU", + [112] = "Icera Semiconductor Inc. Deep Execution Processor", + [113] = "Altera Nios II soft-core processor", + [114] = "National Semiconductor CompactRISC CRX", + [115] = "Motorola XGATE embedded processor", + [116] = "Infineon C16x/XC16x processor", + [117] = "Renesas M16C series microprocessors", + [118] = "Microchip Technology dsPIC30F Digital Signal Controller", + [119] = "Freescale Communication Engine RISC core", + [120] = "Renesas M32C series microprocessors", + [131] = "Altium TSK3000 core", + [132] = "Freescale RS08 embedded processor", + [133] = "Analog Devices SHARC family of 32-bit DSP processors", + [134] = "Cyan Technology eCOG2 microprocessor", + [135] = "Sunplus S+core7 RISC processor", + [136] = "New Japan Radio (NJR) 24-bit DSP Processor", + [137] = "Broadcom VideoCore III processor", + [138] = "RISC processor for Lattice FPGA architecture", + [139] = "Seiko Epson C17 family", + [140] = "The Texas Instruments TMS320C6000 DSP family", + [141] = "The Texas Instruments TMS320C2000 DSP family", + [142] = "The Texas Instruments TMS320C55x DSP family", + [160] = "STMicroelectronics 64bit VLIW Data Signal Processor", + [161] = "Cypress M8C microprocessor", + [162] = "Renesas R32C series microprocessors", + [163] = "NXP Semiconductors TriMedia architecture family", + [164] = "Qualcomm Hexagon processor", + [165] = "Intel 8051 and variants", + [166] = "STMicroelectronics STxP7x family of configurable" .. + " and extensible RISC processors", + [167] = "Andes Technology compact code size embedded RISC processor family", + [168] = "Cyan Technology eCOG1X family", + [168] = "Cyan Technology eCOG1X family", + [169] = "Dallas Semiconductor MAXQ30 Core Micro-controllers", + [170] = "New Japan Radio (NJR) 16-bit DSP Processor", + [171] = "M2000 Reconfigurable RISC Microprocessor", + [172] = "Cray Inc. NV2 vector architecture", + [173] = "Renesas RX family", + [174] = "Imagination Technologies META processor architecture", + [175] = "MCST Elbrus general purpose hardware architecture", + [176] = "Cyan Technology eCOG16 family", + [177] = "National Semiconductor CompactRISC CR16 16-bit microprocessor", + [178] = "Freescale Extended Time Processing Unit", + [179] = "Infineon Technologies SLE9X core", + [180] = "Intel L10M", + [181] = "Intel K10M", + [183] = "ARM AArch64", + [185] = "Atmel Corporation 32-bit microprocessor family", + [186] = "STMicroeletronics STM8 8-bit microcontroller", + [187] = "Tilera TILE64 multicore architecture family", + [188] = "Tilera TILEPro multicore architecture family", + [190] = "NVIDIA CUDA architecture", + [191] = "Tilera TILE-Gx multicore architecture family", + [192] = "CloudShield architecture family", + [193] = "KIPO-KAIST Core-A 1st generation processor family", + [194] = "KIPO-KAIST Core-A 2nd generation processor family", + [195] = "Synopsys ARCompact V2", + [196] = "Open8 8-bit RISC soft processor core", + [197] = "Renesas RL78 family", + [198] = "Broadcom VideoCore V processor", + [199] = "Renesas 78KOR family", + [200] = "Freescale 56800EX Digital Signal Controller (DSC)", + [201] = "Beyond BA1 CPU architecture", + [202] = "Beyond BA2 CPU architecture", + [203] = "XMOS xCORE processor family", + [204] = "Microchip 8-bit PIC(r) family", + [205] = "reserved by Intel", + [206] = "reserved by Intel", + [207] = "reserved by Intel", + [208] = "reserved by Intel", + [209] = "reserved by Intel", + [210] = "KM211 KM32 32-bit processor", + [211] = "KM211 KMX32 32-bit processor", + [212] = "KM211 KMX16 16-bit processor", + [213] = "KM211 KMX8 8-bit processor", + [214] = "KM211 KVARC processor", + [215] = "Paneve CDP architecture family", + [216] = "Cognitive Smart Memory Processor", + [217] = "iCelero CoolEngine", + [218] = "Nanoradio Optimized RISC", + [219] = "CSR Kalimba architecture family", + [224] = "AMD GPU architecture", + [244] = "Lanai 32-bit processor", + [247] = "Linux kernel bpf virtual machine" +} + +local decode32 = function (c) + -- TODO: like the 64-bit version, maybe try to merge the code somehow +end + +local decode64 = function (c) + local type = c:u16 ("type of file: %s", function (u16) + name = type_table[u16] + if name then return name end + return "unknown: %d", u16 + end) + local machine = c:u16 ("required architecture: %s", function (u16) + name = machine_table[u16] + if name then return name end + return "unknown: %d", u16 + end) + local version = c:u32 ("version: %d") + local entry = c:u64 ("program entry address: %#x") + local ph_offset = c:u64 ("program header table offset: %#x") + local sh_offset = c:u64 ("section header table offset: %#x") + local flags = c:u32 ("processor-specific flags: %#x") + local eh_size = c:u16 ("ELF header size: %d") + local ph_entry_size = c:u16 ("program header size: %d") + local ph_number = c:u16 ("program header count: %d") + local sh_entry_size = c:u16 ("section header size: %d") + local sh_number = c:u16 ("section header count: %d") + local sh_string_index = c:u16 ("section header index for strings: %d") + + -- TODO: decode all sections as well, see man 5 elf, + -- /usr/include/elf.h and /usr/include/llvm/Support/ELF.h +end + +local abi_table = { + [0] = "UNIX System V ABI", + [1] = "HP-UX operating system", + [2] = "NetBSD", + [3] = "GNU/Linux", + [4] = "GNU/Hurd", + [6] = "Solaris", + [7] = "AIX", + [8] = "IRIX", + [9] = "FreeBSD", + [10] = "TRU64 UNIX", + [11] = "Novell Modesto", + [12] = "OpenBSD", + [13] = "OpenVMS", + [14] = "Hewlett-Packard Non-Stop Kernel", + [15] = "AROS", + [16] = "FenixOS", + [17] = "Nuxi CloudABI", + [64] = "Bare-metal TMS320C6000", + [64] = "AMD HSA runtime", + [65] = "Linux TMS320C6000", + [97] = "ARM", + [255] = "Standalone (embedded) application" +} + +local decode = function (c) + if not detect (c ()) then error ("not an ELF file") end + + local p = c.position, c:read (4) + c (p, p + 3):mark ("ELF magic") + + local class = c:u8 ("ELF class: %s", function (u8) + if u8 == 1 then return "32-bit" end + if u8 == 2 then return "64-bit" end + return "invalid: %d", u8 + end) + local data = c:u8 ("ELF data: %s", function (u8) + if u8 == 1 then + c.endianity = "le" + return "little-endian" + end + if u8 == 2 then + c.endianity = "be" + return "big-endian" + end + return "invalid: %d", u8 + end) + local version = c:u8 ("ELF version: %d") + local abi = c:u8 ("OS ABI: %s", function (u8) + name = abi_table[u8] + if name then return name end + return "unknown: %d", u8 + end) + local abi_version = c:u8 ("OS ABI version: %d") + + -- The padding is reserved, no big sense in marking it + local padding = c:read (7) + + -- We cannot decode anything further as we don't know how + if data ~= 1 and data ~= 2 then return end + + if class == 1 then decode32 (c) end + if class == 2 then decode64 (c) end +end + +hex.register { type="elf", detect=detect, decode=decode }