diff options
author | Valtteri Koskivuori <vkoskiv@gmail.com> | 2021-10-18 02:21:44 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-21 01:14:09 +0200 |
commit | a3b3800cd45410e65f148b4e0877503bf653f8dd (patch) | |
tree | 8d1c08af4d18e3e0ca74a784f9ad50ce3cf55914 /Userland/Utilities/file.cpp | |
parent | efbcfe0498311e96077562cabb3f347e4c58c35f (diff) | |
download | serenity-a3b3800cd45410e65f148b4e0877503bf653f8dd.zip |
Userland: Teach the file utility more about ELF files
It now shows some useful at-a-glance information about ELF files, like
it does on other *nix systems.
Diffstat (limited to 'Userland/Utilities/file.cpp')
-rw-r--r-- | Userland/Utilities/file.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/Userland/Utilities/file.cpp b/Userland/Utilities/file.cpp index 64290726de..c1e7adb011 100644 --- a/Userland/Utilities/file.cpp +++ b/Userland/Utilities/file.cpp @@ -10,6 +10,8 @@ #include <LibCore/ArgsParser.h> #include <LibCore/FileStream.h> #include <LibCore/MimeData.h> +#include <LibELF/Image.h> +#include <LibELF/Validation.h> #include <LibGfx/ImageDecoder.h> #include <stdio.h> #include <sys/stat.h> @@ -52,6 +54,40 @@ static Optional<String> gzip_details(String description, const String& path) return String::formatted("{}, {}", description, gzip_details.value()); } +static Optional<String> elf_details(String description, const String& path) +{ + auto file_or_error = MappedFile::map(path); + if (file_or_error.is_error()) + return {}; + auto& mapped_file = *file_or_error.value(); + auto elf_data = mapped_file.bytes(); + ELF::Image elf_image(elf_data); + if (!elf_image.is_valid()) + return {}; + + String interpreter_path; + if (!ELF::validate_program_headers(*(const ElfW(Ehdr)*)elf_data.data(), elf_data.size(), (const u8*)elf_data.data(), elf_data.size(), &interpreter_path)) + return {}; + + auto& header = *reinterpret_cast<const ElfW(Ehdr)*>(elf_data.data()); + + auto bitness = header.e_ident[EI_CLASS] == ELFCLASS64 ? "64" : "32"; + auto byteorder = header.e_ident[EI_DATA] == ELFDATA2LSB ? "LSB" : "MSB"; + + bool is_dynamically_linked = !interpreter_path.is_empty(); + String dynamic_section = String::formatted(", dynamically linked, interpreter {}", interpreter_path); + + return String::formatted("{} {}-bit {} {}, {}, version {} ({}){}", + description, + bitness, + byteorder, + ELF::Image::object_file_type_to_string(header.e_type).value_or("(?)"), + ELF::Image::object_machine_type_to_string(header.e_machine).value_or("(?)"), + header.e_ident[EI_ABIVERSION], + ELF::Image::object_abi_type_to_string(header.e_ident[EI_OSABI]).value_or("(?)"), + is_dynamically_linked ? dynamic_section : ""); +} + #define ENUMERATE_MIME_TYPE_DESCRIPTIONS \ __ENUMERATE_MIME_TYPE_DESCRIPTION("application/gzip", "gzip compressed data", gzip_details) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("application/javascript", "JavaScript source", description_only) \ @@ -63,6 +99,7 @@ static Optional<String> gzip_details(String description, const String& path) __ENUMERATE_MIME_TYPE_DESCRIPTION("application/x-7z-compressed", "7-Zip archive", description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("audio/midi", "MIDI sound", description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/blender", "Blender project file", description_only) \ + __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/elf", "ELF", elf_details) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/ext", "ext filesystem", description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/flac", "FLAC audio", description_only) \ __ENUMERATE_MIME_TYPE_DESCRIPTION("extra/iso-9660", "ISO 9660 CD/DVD image", description_only) \ |