elfinfo.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Name: elfinfo
  3. * Version: 0.1.2
  4. * Description: Utility to print information about ELF files
  5. * Dependencies: bzbutil, bzbfile
  6. */
  7. #include "balzebub.h"
  8. #include <unistd.h>
  9. using namespace bzbterm;
  10. using namespace bzbio;
  11. using namespace bzbshell;
  12. using namespace bzbfile;
  13. EscSeq TITLE_COLOR = fg::bright_yellow;
  14. EscSeq DATA_COLOR = fg::bright_cyan;
  15. EscSeq HEADER_COLOR = fg::blue;
  16. constexpr int VERSION_MAJOR = 0;
  17. constexpr int VERSION_MINOR = 1;
  18. constexpr int VERSION_PATCH = 3;
  19. const char* PROGNAME = "elfinfo";
  20. void print_version_exit() {
  21. std::cout << PROGNAME << " v";
  22. std::cout << VERSION_MAJOR << "." <<
  23. VERSION_MINOR << "." <<
  24. VERSION_PATCH << std::endl;
  25. std::cout << "This program is part of the Balzebub project." << std::endl;
  26. exit(0);
  27. }
  28. void print_help_exit(int err = 0) {
  29. println("Usage: ", PROGNAME, " <filename> [ -no-color ]");
  30. println("Show information about an ELF file");
  31. println("-no-color\tPrint information without color escape codes");
  32. exit(err);
  33. }
  34. template<typename T>
  35. void print_elf_info(T elf_file) {
  36. print(TITLE_COLOR, "Class: ");
  37. if(elf_file.e_ident[ELF_EI_CLASS] == ELF_CLASS_32) {
  38. println(DATA_COLOR, "ELF32");
  39. } else if(elf_file.e_ident[ELF_EI_CLASS] == ELF_CLASS_64) {
  40. println(DATA_COLOR, "ELF64");
  41. } else {
  42. println(DATA_COLOR, "Unknown");
  43. }
  44. print(TITLE_COLOR, "Endianness: ");
  45. print(DATA_COLOR);
  46. if(elf_file.e_ident[ELF_EI_DATA] == ELF_LITTLE_ENDIAN) {
  47. print("Little Endian");
  48. } else if (elf_file.e_ident[ELF_EI_DATA] == ELF_BIG_ENDIAN) {
  49. print("Big Endian");
  50. } else {
  51. print("Unknown");
  52. }
  53. c_println();
  54. print(TITLE_COLOR, "ELF version: ");
  55. println(DATA_COLOR, (uint32_t) elf_file.e_ident[ELF_EI_VERSION]);
  56. print(TITLE_COLOR, "Target system: ");
  57. print(DATA_COLOR);
  58. switch(elf_file.e_ident[ELF_EI_OSABI]) {
  59. case ELF_ABI_SYSTEM_V: print("UNIX - System V (default)"); break;
  60. case ELF_ABI_HP_UX: print("HP-UX"); break;
  61. case ELF_ABI_NETBSD: print("NetBSD"); break;
  62. case ELF_ABI_LINUX: print("Linux"); break;
  63. case ELF_ABI_GNUHURD: print("GNU Hurd"); break;
  64. case ELF_ABI_SOLARIS: print("Solaris"); break;
  65. case ELF_ABI_AIX: print("AIX"); break;
  66. case ELF_ABI_IRIX: print("IRIX"); break;
  67. case ELF_ABI_FREEBSD: print("FreeBSD"); break;
  68. case ELF_ABI_TRU64: print("Tru64"); break;
  69. case ELF_ABI_NOVELL_MODESTO: print("Novell Modesto"); break;
  70. case ELF_ABI_OPENBSD: print("OpenBSD"); break;
  71. case ELF_ABI_OPENVMS: print("OpenVMS"); break;
  72. case ELF_ABI_NONSTOP_KERNEL: print("NonStop Kernel"); break;
  73. case ELF_ABI_AROS: print("AROS"); break;
  74. case ELF_ABI_FENIXOS: print("FenixOS"); break;
  75. case ELF_ABI_CLOUDABI: print("CloudABI"); break;
  76. default: print("Unknown"); break;
  77. }
  78. c_println();
  79. print(TITLE_COLOR, "ABI version: ");
  80. println(DATA_COLOR, (uint32_t) elf_file.e_ident[ELF_EI_ABIVERSION]);
  81. print(TITLE_COLOR, "Type:", " ");
  82. print(DATA_COLOR);
  83. switch(elf_file.e_type) {
  84. case ELF_ET_NONE: print("NONE (None)"); break;
  85. case ELF_ET_REL: print("REL (Relocatable file)"); break;
  86. case ELF_ET_EXEC: print("EXEC (Executable file)"); break;
  87. case ELF_ET_DYN: print("DYN (Shared object file)"); break;
  88. case ELF_ET_CORE: print("CORE (Core file)"); break;
  89. case ELF_ET_LOOS: print("LOOS (Operating system-specific)"); break;
  90. case ELF_ET_HIOS: print("HIOS (Operating system-specific)"); break;
  91. case ELF_ET_LOPROC: print("LOPROC (Processor-specific)"); break;
  92. case ELF_ET_HIPROC: print("HIPROC (Processor-specific)"); break;
  93. default: print("Unknown "); break;
  94. }
  95. c_println();
  96. print(TITLE_COLOR, "Target machine: ");
  97. print(DATA_COLOR);
  98. switch(elf_file.e_machine) {
  99. case ELF_ARCH_UNSPECIFIED: print("Unspecified"); break;
  100. case ELF_ARCH_SPARC: print("SPARC"); break;
  101. case ELF_ARCH_X86: print("x86"); break;
  102. case ELF_ARCH_MIPS: print("MIPS"); break;
  103. case ELF_ARCH_POWERPC: print("PowerPC"); break;
  104. case ELF_ARCH_S390: print("S390"); break;
  105. case ELF_ARCH_ARM: print("ARM"); break;
  106. case ELF_ARCH_SUPERH: print("SuperH"); break;
  107. case ELF_ARCH_IA_64: print("IA-64"); break;
  108. case ELF_ARCH_X86_64: print("x86-64"); break;
  109. case ELF_ARCH_AARCH64: print("AArch64"); break;
  110. case ELF_ARCH_RISC_V: print("RISC-V"); break;
  111. default: print("Unknown (0x", std::hex,
  112. elf_file.e_machine,
  113. std::dec, ")");
  114. }
  115. c_println();
  116. print(TITLE_COLOR, "Version: ");
  117. if(elf_file.e_version == 1) {
  118. println(DATA_COLOR, "1 (current)");
  119. } else {
  120. println(DATA_COLOR, elf_file.e_version, " (invalid)");
  121. }
  122. print(TITLE_COLOR, "Entry point: ");
  123. println(DATA_COLOR, "0x", std::hex, elf_file.e_entry, std::dec);
  124. print(TITLE_COLOR, "Program header offset: ");
  125. println(DATA_COLOR, elf_file.e_phoff);
  126. print(TITLE_COLOR, "Section header offset: ");
  127. println(DATA_COLOR, elf_file.e_shoff);
  128. print(TITLE_COLOR, "Flags: ");
  129. println(DATA_COLOR, std::hex, "0x", elf_file.e_flags, std::dec);
  130. print(TITLE_COLOR, "ELF header size: ");
  131. println(DATA_COLOR, elf_file.e_ehsize);
  132. print(TITLE_COLOR, "Program header entry size: ");
  133. println(DATA_COLOR, elf_file.e_phentsize);
  134. print(TITLE_COLOR, "Number of program headers: ");
  135. println(DATA_COLOR, elf_file.e_phnum);
  136. print(TITLE_COLOR, "Section header entry size: ");
  137. println(DATA_COLOR, elf_file.e_shentsize);
  138. print(TITLE_COLOR, "Number of section headers: ");
  139. println(DATA_COLOR, elf_file.e_shnum);
  140. print(TITLE_COLOR, "Section headers string table index: ");
  141. println(DATA_COLOR, elf_file.e_shstrndx);
  142. println(TITLE_COLOR, "Interpreter: ", DATA_COLOR, elf_file.interpreter);
  143. for(size_t i = 0; i < elf_file.prog_headers.size(); i++) {
  144. println(HEADER_COLOR, "\nProgram header number ", i);
  145. print(TITLE_COLOR, "Type:", " ");
  146. print(DATA_COLOR);
  147. switch(elf_file.prog_headers[i].p_type) {
  148. case ELF_PT_NULL: print("NULL (Unused)"); break;
  149. case ELF_PT_LOAD: print("LOAD (Loadable segment)"); break;
  150. case ELF_PT_DYNAMIC: print("DYNAMIC (Dynamic linking information)"); break;
  151. case ELF_PT_INTERP: print("INTERP (Interpreter)"); break;
  152. case ELF_PT_NOTE: print("NOTE (Notes)"); break;
  153. case ELF_PT_SHLIB: print("SHLIB (Invalid)"); break;
  154. case ELF_PT_PHDR: print("PHDR (Program header pointer)"); break;
  155. case ELF_PT_LOOS: print("LOOS (System specific)"); break;
  156. case ELF_PT_HIOS: print("HIOS (System specific)"); break;
  157. case ELF_PT_LOPROC: print("LOPROC (Processor specific)"); break;
  158. case ELF_PT_HIPROC: print("HIPROC (Processor specific)"); break;
  159. case ELF_PT_GNU_EH_FRAME: print("GNU_EH_FRAME"); break;
  160. case ELF_PT_GNU_STACK: print("GNU_STACK"); break;
  161. case ELF_PT_GNU_RELRO: print("GNU_RELRO"); break;
  162. default: print("Unknown (0x", std::hex,
  163. elf_file.prog_headers[i].p_type,
  164. std::dec, ")");
  165. }
  166. c_println();
  167. print(TITLE_COLOR, "Offset: ");
  168. println(DATA_COLOR, elf_file.prog_headers[i].p_offset);
  169. print(TITLE_COLOR, "Virtual Address: ");
  170. println(DATA_COLOR, "0x", std::hex, elf_file.prog_headers[i].p_vaddr, std::dec);
  171. print(TITLE_COLOR, "Physical Address: ");
  172. println(DATA_COLOR, "0x", std::hex, elf_file.prog_headers[i].p_paddr, std::dec);
  173. print(TITLE_COLOR, "Segment size in the image file (may be 0): ");
  174. println(DATA_COLOR, elf_file.prog_headers[i].p_filesz);
  175. print(TITLE_COLOR, "Segment size in memory (may be 0): ");
  176. println(DATA_COLOR, elf_file.prog_headers[i].p_memsz);
  177. print(TITLE_COLOR, "Alignment: ");
  178. println(DATA_COLOR, "0x", std::hex, elf_file.prog_headers[i].p_align, std::dec);
  179. print(TITLE_COLOR, "Flags: ");
  180. print(DATA_COLOR);
  181. if(elf_file.prog_headers[i].p_flags & ELF_PH_FLAG_READ) {
  182. print("R");
  183. } else {
  184. print("-");
  185. }
  186. if(elf_file.prog_headers[i].p_flags & ELF_PH_FLAG_WRITE) {
  187. print("W");
  188. } else {
  189. print("-");
  190. }
  191. if(elf_file.prog_headers[i].p_flags & ELF_PH_FLAG_EXEC) {
  192. print("X");
  193. } else {
  194. print("-");
  195. }
  196. c_println();
  197. }
  198. for(size_t i = 0; i < elf_file.sec_headers.size(); i++) {
  199. println(HEADER_COLOR, "\nSection header number ", i);
  200. println(TITLE_COLOR, "Name: ", DATA_COLOR, elf_file.sec_headers[i].name);
  201. println(TITLE_COLOR, "Name offset inside shstrtab: ", DATA_COLOR,
  202. "0x", std::hex, elf_file.sec_headers[i].sh_name, std::dec);
  203. print(TITLE_COLOR, "Type: ");
  204. print(DATA_COLOR);
  205. switch(elf_file.sec_headers[i].sh_type) {
  206. case ELF_SHT_NULL: print("NULL (Unused)"); break;
  207. case ELF_SHT_PROGBITS: print("PROGBITS (Program data)"); break;
  208. case ELF_SHT_SYMTAB: print("SYMTAB (Symbol table)"); break;
  209. case ELF_SHT_STRTAB: print("STRTAB (String table)"); break;
  210. case ELF_SHT_RELA: print("RELA (Relocation entries with addends)"); break;
  211. case ELF_SHT_HASH: print("HASH (Symbol hash table)"); break;
  212. case ELF_SHT_DYNAMIC: print("DYNAMIC (Dynamic linking information)"); break;
  213. case ELF_SHT_NOTE: print("NOTE (Notes)"); break;
  214. case ELF_SHT_NOBITS: print("NOBITS (Program space with no data, BSS)"); break;
  215. case ELF_SHT_REL: print("REL (Relocation entries without addends)"); break;
  216. case ELF_SHT_SHLIB: print("SHLIB (Reserved)"); break;
  217. case ELF_SHT_DYNSYM: print("DYNSYM (Dynamic linker symbol table)"); break;
  218. case ELF_SHT_INIT_ARRAY: print("INIT_ARRAY (Array of constructors)"); break;
  219. case ELF_SHT_FINI_ARRAY: print("FINI_ARRAY (Array of destructors)"); break;
  220. case ELF_SHT_PREINIT_ARRAY: print("PREINIT_ARRAY (// Array of pre-constructors)"); break;
  221. case ELF_SHT_GROUP: print("GROUP (Section group)"); break;
  222. case ELF_SHT_SYMTAB_SHNDX: print("SYMTAB_SHNDX (Extended section indices)"); break;
  223. case ELF_SHT_NUM: print("NUM (Number of defined types)"); break;
  224. case ELF_SHT_LOOS: print("LOOS (System specific)"); break;
  225. case ELF_SHT_HIOS: print("HIOS (System specific) or VERSYM (GNU)"); break;
  226. case ELF_SHT_LOPROC: print("LOPROC (Processor specific)"); break;
  227. case ELF_SHT_HIPROC: print("HIPROC (Processor specific)"); break;
  228. case ELF_SHT_LOUSER: print("LOUSER (Application specific)"); break;
  229. case ELF_SHT_HIUSER: print("HIUSER (Application specific)"); break;
  230. case ELF_SHT_GNU_HASH: print("GNU_HASH"); break;
  231. case ELF_SHT_VERNEED: print("VERNEED"); break;
  232. default: print("Unknown (0x", std::hex,
  233. elf_file.sec_headers[i].sh_type,
  234. std::dec, ")");
  235. }
  236. c_println();
  237. print(TITLE_COLOR, "Flags: ", DATA_COLOR);
  238. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_WRITE) {
  239. print("W");
  240. }
  241. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_ALLOC) {
  242. print("A");
  243. }
  244. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_EXECINSTR) {
  245. print("X");
  246. }
  247. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_MERGE) {
  248. print("M");
  249. }
  250. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_STRINGS) {
  251. print("S");
  252. }
  253. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_INFO_LINK) {
  254. print("I");
  255. }
  256. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_LINK_ORDER) {
  257. print("L");
  258. }
  259. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_OS_NONCONFORMING) {
  260. print("O");
  261. }
  262. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_GROUP) {
  263. print("G");
  264. }
  265. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_TLS) {
  266. print("T");
  267. }
  268. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_COMPRESSED) {
  269. print("C");
  270. }
  271. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_MASKOS) {
  272. print("o");
  273. }
  274. if(elf_file.sec_headers[i].sh_flags & ELF_SHF_MASKPROC) {
  275. print("p");
  276. }
  277. c_println();
  278. println(TITLE_COLOR, "Address: ",
  279. DATA_COLOR, "0x", std::hex, elf_file.sec_headers[i].sh_addr,
  280. std::dec);
  281. println(TITLE_COLOR, "Offset: ",
  282. DATA_COLOR, "0x", std::hex, elf_file.sec_headers[i].sh_offset,
  283. std::dec);
  284. println(TITLE_COLOR, "Size: ",
  285. DATA_COLOR, elf_file.sec_headers[i].sh_size);
  286. println(TITLE_COLOR, "Link: ",
  287. DATA_COLOR, elf_file.sec_headers[i].sh_link);
  288. println(TITLE_COLOR, "Info: ",
  289. DATA_COLOR, elf_file.sec_headers[i].sh_info);
  290. println(TITLE_COLOR, "Address alignment: ",
  291. DATA_COLOR, "0x", std::hex, elf_file.sec_headers[i].sh_addralign,
  292. std::dec);
  293. println(TITLE_COLOR, "Entry size: ",
  294. DATA_COLOR, elf_file.sec_headers[i].sh_entsize);
  295. }
  296. }
  297. int main(int argc, char const *argv[]) {
  298. if(argc < 2) {
  299. print_help_exit(1);
  300. }
  301. if(argc == 3) {
  302. std::string arg3 = argv[2];
  303. if(arg3 == "-no-color") {
  304. TITLE_COLOR = EscSeq("");
  305. DATA_COLOR = EscSeq("");
  306. HEADER_COLOR = EscSeq("");
  307. }
  308. }
  309. std::string filename = argv[1];
  310. if(filename == "--help" || filename == "-h") {
  311. print_help_exit(0);
  312. }
  313. if(filename == "--version" || filename == "-v") {
  314. print_version_exit();
  315. }
  316. if(!bzbfile::exists(filename)) {
  317. println(fg::red, "ERROR This file does not exist");
  318. exit(2);
  319. }
  320. uint8_t arch = bzbfile::get_elf_class(filename);
  321. if(arch == ELF_CLASS_32) {
  322. ELF32 elf_file(filename);
  323. print_elf_info(elf_file);
  324. } else if(arch == ELF_CLASS_64) {
  325. ELF64 elf_file(filename);
  326. print_elf_info(elf_file);
  327. } else {
  328. println(fg::red, "ERROR Malformed ELF file (EI_CLASS is uncorrect)");
  329. exit(3);
  330. }
  331. return 0;
  332. }