mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 17:58:18 +03:00
readelf: Use Loader.so interpreter for dynamic section and symbols
This commit is contained in:
parent
8ad74684ea
commit
677e5e4d84
Notes:
sideshowbarker
2024-07-18 21:08:42 +09:00
Author: https://github.com/bcoles Commit: https://github.com/SerenityOS/serenity/commit/677e5e4d847 Pull-request: https://github.com/SerenityOS/serenity/pull/5895 Reviewed-by: https://github.com/ADKaster
@ -29,6 +29,9 @@
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibCore/ArgsParser.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibELF/DynamicLoader.h>
|
||||
#include <LibELF/DynamicObject.h>
|
||||
#include <LibELF/Image.h>
|
||||
#include <LibELF/Validation.h>
|
||||
#include <ctype.h>
|
||||
@ -267,6 +270,98 @@ static const char* object_relocation_type_to_string(Elf32_Word type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* object_tag_to_string(Elf32_Sword dt_tag)
|
||||
{
|
||||
switch (dt_tag) {
|
||||
case DT_NULL:
|
||||
return "NULL"; /* marks end of _DYNAMIC array */
|
||||
case DT_NEEDED:
|
||||
return "NEEDED"; /* string table offset of needed lib */
|
||||
case DT_PLTRELSZ:
|
||||
return "PLTRELSZ"; /* size of relocation entries in PLT */
|
||||
case DT_PLTGOT:
|
||||
return "PLTGOT"; /* address PLT/GOT */
|
||||
case DT_HASH:
|
||||
return "HASH"; /* address of symbol hash table */
|
||||
case DT_STRTAB:
|
||||
return "STRTAB"; /* address of string table */
|
||||
case DT_SYMTAB:
|
||||
return "SYMTAB"; /* address of symbol table */
|
||||
case DT_RELA:
|
||||
return "RELA"; /* address of relocation table */
|
||||
case DT_RELASZ:
|
||||
return "RELASZ"; /* size of relocation table */
|
||||
case DT_RELAENT:
|
||||
return "RELAENT"; /* size of relocation entry */
|
||||
case DT_STRSZ:
|
||||
return "STRSZ"; /* size of string table */
|
||||
case DT_SYMENT:
|
||||
return "SYMENT"; /* size of symbol table entry */
|
||||
case DT_INIT:
|
||||
return "INIT"; /* address of initialization func. */
|
||||
case DT_FINI:
|
||||
return "FINI"; /* address of termination function */
|
||||
case DT_SONAME:
|
||||
return "SONAME"; /* string table offset of shared obj */
|
||||
case DT_RPATH:
|
||||
return "RPATH"; /* string table offset of library search path */
|
||||
case DT_SYMBOLIC:
|
||||
return "SYMBOLIC"; /* start sym search in shared obj. */
|
||||
case DT_REL:
|
||||
return "REL"; /* address of rel. tbl. w addends */
|
||||
case DT_RELSZ:
|
||||
return "RELSZ"; /* size of DT_REL relocation table */
|
||||
case DT_RELENT:
|
||||
return "RELENT"; /* size of DT_REL relocation entry */
|
||||
case DT_PLTREL:
|
||||
return "PLTREL"; /* PLT referenced relocation entry */
|
||||
case DT_DEBUG:
|
||||
return "DEBUG"; /* bugger */
|
||||
case DT_TEXTREL:
|
||||
return "TEXTREL"; /* Allow rel. mod. to unwritable seg */
|
||||
case DT_JMPREL:
|
||||
return "JMPREL"; /* add. of PLT's relocation entries */
|
||||
case DT_BIND_NOW:
|
||||
return "BIND_NOW"; /* Bind now regardless of env setting */
|
||||
case DT_INIT_ARRAY:
|
||||
return "INIT_ARRAY"; /* address of array of init func */
|
||||
case DT_FINI_ARRAY:
|
||||
return "FINI_ARRAY"; /* address of array of term func */
|
||||
case DT_INIT_ARRAYSZ:
|
||||
return "INIT_ARRAYSZ"; /* size of array of init func */
|
||||
case DT_FINI_ARRAYSZ:
|
||||
return "FINI_ARRAYSZ"; /* size of array of term func */
|
||||
case DT_RUNPATH:
|
||||
return "RUNPATH"; /* strtab offset of lib search path */
|
||||
case DT_FLAGS:
|
||||
return "FLAGS"; /* Set of DF_* flags */
|
||||
case DT_ENCODING:
|
||||
return "ENCODING"; /* further DT_* follow encoding rules */
|
||||
case DT_PREINIT_ARRAY:
|
||||
return "PREINIT_ARRAY"; /* address of array of preinit func */
|
||||
case DT_PREINIT_ARRAYSZ:
|
||||
return "PREINIT_ARRAYSZ"; /* size of array of preinit func */
|
||||
case DT_LOOS:
|
||||
return "LOOS"; /* reserved range for OS */
|
||||
case DT_HIOS:
|
||||
return "HIOS"; /* specific dynamic array tags */
|
||||
case DT_LOPROC:
|
||||
return "LOPROC"; /* reserved range for processor */
|
||||
case DT_HIPROC:
|
||||
return "HIPROC"; /* specific dynamic array tags */
|
||||
case DT_GNU_HASH:
|
||||
return "GNU_HASH"; /* address of GNU hash table */
|
||||
case DT_RELACOUNT:
|
||||
return "RELACOUNT"; /* if present, number of RELATIVE */
|
||||
case DT_RELCOUNT:
|
||||
return "RELCOUNT"; /* relocs, which must come first */
|
||||
case DT_FLAGS_1:
|
||||
return "FLAGS_1";
|
||||
default:
|
||||
return "??";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (pledge("stdio rpath", nullptr) < 0) {
|
||||
@ -295,6 +390,7 @@ int main(int argc, char** argv)
|
||||
args_parser.add_option(display_section_headers, "Display section headers", "section-headers", 'S');
|
||||
args_parser.add_option(display_headers, "Equivalent to: -h -l -S -s -r -d -n -u -c", "headers", 'e');
|
||||
args_parser.add_option(display_symbol_table, "Display the symbol table", "syms", 's');
|
||||
args_parser.add_option(display_dynamic_symbol_table, "Display the dynamic symbol table", "dyn-syms", '\0');
|
||||
args_parser.add_option(display_dynamic_section, "Display the dynamic section", "dynamic", 'd');
|
||||
args_parser.add_option(display_core_notes, "Display core notes", "notes", 'n');
|
||||
args_parser.add_option(display_relocations, "Display relocations", "relocs", 'r');
|
||||
@ -333,9 +429,9 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
auto elf_image_data = file_or_error.value()->bytes();
|
||||
ELF::Image executable_elf(elf_image_data);
|
||||
ELF::Image elf_image(elf_image_data);
|
||||
|
||||
if (!executable_elf.is_valid()) {
|
||||
if (!elf_image.is_valid()) {
|
||||
fprintf(stderr, "File is not a valid ELF object\n");
|
||||
return -1;
|
||||
}
|
||||
@ -347,29 +443,61 @@ int main(int argc, char** argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (executable_elf.is_dynamic() && interpreter_path.is_null()) {
|
||||
fprintf(stderr, "Warning: Dynamic ELF object has no interpreter path\n");
|
||||
auto& header = *reinterpret_cast<const Elf32_Ehdr*>(elf_image_data.data());
|
||||
|
||||
RefPtr<ELF::DynamicObject> object = nullptr;
|
||||
|
||||
if (elf_image.is_dynamic()) {
|
||||
if (interpreter_path.is_null()) {
|
||||
interpreter_path = "/usr/lib/Loader.so";
|
||||
fprintf(stderr, "Warning: Dynamic ELF object has no interpreter path. Using: %s\n", interpreter_path.characters());
|
||||
}
|
||||
|
||||
ELF::Image interpreter_image(elf_image_data);
|
||||
auto interpreter_file_or_error = MappedFile::map(interpreter_path);
|
||||
|
||||
if (!interpreter_image.is_valid()) {
|
||||
fprintf(stderr, "ELF image is invalid\n");
|
||||
if (interpreter_file_or_error.is_error()) {
|
||||
warnln("Unable to map interpreter file {}: {}", interpreter_path, interpreter_file_or_error.error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto& header = *reinterpret_cast<const Elf32_Ehdr*>(elf_image_data.data());
|
||||
auto interpreter_image_data = interpreter_file_or_error.value()->bytes();
|
||||
|
||||
ELF::Image interpreter_image(interpreter_image_data);
|
||||
|
||||
if (!interpreter_image.is_valid()) {
|
||||
fprintf(stderr, "ELF interpreter image is invalid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
outln(String::formatted("Unable to open file {}", path).characters());
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto loader = ELF::DynamicLoader::try_create(fd, path);
|
||||
if (!loader || !loader->is_valid()) {
|
||||
outln(String::formatted("{} is not a valid ELF dynamic shared object!", path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
object = loader->map();
|
||||
if (!object) {
|
||||
outln(String::formatted("Failed to map dynamic ELF object {}", path));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (display_elf_header) {
|
||||
printf("ELF header:\n");
|
||||
|
||||
String magic = String::format("%s", header.e_ident);
|
||||
printf(" Magic: ");
|
||||
for (size_t i = 0; i < magic.length(); i++) {
|
||||
if (isprint(magic[i])) {
|
||||
printf("%c ", magic[i]);
|
||||
for (char i : magic) {
|
||||
if (isprint(i)) {
|
||||
printf("%c ", i);
|
||||
} else {
|
||||
printf("%02x ", magic[i]);
|
||||
printf("%02x ", i);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
@ -396,13 +524,13 @@ int main(int argc, char** argv)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (!interpreter_image.section_count()) {
|
||||
if (!elf_image.section_count()) {
|
||||
printf("There are no sections in this file.\n");
|
||||
} else {
|
||||
printf("Section Headers:\n");
|
||||
printf(" Name Type Address Offset Size Flags\n");
|
||||
|
||||
interpreter_image.for_each_section([](const ELF::Image::Section& section) {
|
||||
elf_image.for_each_section([](const ELF::Image::Section& section) {
|
||||
printf(" %-19s ", StringView(section.name()).to_string().characters());
|
||||
printf("%-15s ", object_section_header_type_to_string(section.type()));
|
||||
printf("%08x ", section.address());
|
||||
@ -427,7 +555,7 @@ int main(int argc, char** argv)
|
||||
printf("Program Headers:\n");
|
||||
printf(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n");
|
||||
|
||||
interpreter_image.for_each_program_header([](const ELF::Image::ProgramHeader& program_header) {
|
||||
elf_image.for_each_program_header([](const ELF::Image::ProgramHeader& program_header) {
|
||||
printf(" %-14s ", object_program_header_type_to_string(program_header.type()));
|
||||
printf("0x%08x ", program_header.offset());
|
||||
printf("%p ", program_header.vaddr().as_ptr());
|
||||
@ -450,24 +578,50 @@ int main(int argc, char** argv)
|
||||
|
||||
if (display_dynamic_section) {
|
||||
auto found_dynamic_section = false;
|
||||
interpreter_image.for_each_section([&found_dynamic_section](const ELF::Image::Section& section) {
|
||||
if (elf_image.is_dynamic()) {
|
||||
elf_image.for_each_section([&found_dynamic_section](const ELF::Image::Section& section) {
|
||||
if (section.name() != ELF_DYNAMIC)
|
||||
return IterationDecision::Continue;
|
||||
|
||||
found_dynamic_section = true;
|
||||
|
||||
if (!section.entry_count()) {
|
||||
if (section.entry_count()) {
|
||||
printf("Dynamic section '%s' at offset 0x%08x contains %u entries.\n", section.name().to_string().characters(), section.offset(), section.entry_count());
|
||||
} else {
|
||||
printf("Dynamic section '%s' at offset 0x%08x contains zero entries.\n", section.name().to_string().characters(), section.offset());
|
||||
return IterationDecision::Continue;
|
||||
}
|
||||
|
||||
printf("Dynamic section '%s' at offset 0x%08x contains %u entries.\n", section.name().to_string().characters(), section.offset(), section.entry_count());
|
||||
|
||||
// TODO: Display dynamic section
|
||||
return IterationDecision::Break;
|
||||
});
|
||||
|
||||
Vector<String> libraries;
|
||||
object->for_each_needed_library([&libraries](StringView entry) {
|
||||
libraries.append(String::formatted("{}", entry).characters());
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
auto library_index = 0;
|
||||
printf(" Tag Type Name / Value\n");
|
||||
object->for_each_dynamic_entry([&library_index, &libraries, &object](const ELF::DynamicObject::DynamicEntry& entry) {
|
||||
printf(" 0x%08x ", entry.tag());
|
||||
printf("%-17s ", object_tag_to_string(entry.tag()));
|
||||
|
||||
if (entry.tag() == DT_NEEDED) {
|
||||
printf("Shared library: %s\n", String(libraries[library_index]).characters());
|
||||
library_index++;
|
||||
} else if (entry.tag() == DT_RPATH) {
|
||||
printf("Library rpath: %s\n", String(object->rpath()).characters());
|
||||
} else if (entry.tag() == DT_RUNPATH) {
|
||||
printf("Library runpath: %s\n", String(object->runpath()).characters());
|
||||
} else if (entry.tag() == DT_SONAME) {
|
||||
printf("Library soname: %s\n", String(object->soname()).characters());
|
||||
} else {
|
||||
printf("0x%08x\n", entry.val());
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
if (!found_dynamic_section)
|
||||
printf("No dynamic section in this file.\n");
|
||||
|
||||
@ -475,22 +629,13 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
if (display_relocations) {
|
||||
auto found_relocations = false;
|
||||
interpreter_image.for_each_section([&found_relocations](const ELF::Image::Section& section) {
|
||||
// FIXME: support dynamic relocations (.rel.dyn)
|
||||
if (!section.relocations().relocation_count())
|
||||
return IterationDecision::Continue;
|
||||
|
||||
found_relocations = true;
|
||||
|
||||
if (!section.relocations().entry_count()) {
|
||||
printf("Relocation section '%s' at offset 0x%08x contains zero entries.\n", section.name().to_string().characters(), section.offset());
|
||||
return IterationDecision::Continue;
|
||||
}
|
||||
|
||||
printf("Relocation section '%s' at offset 0x%08x contains %u entries:\n", section.relocations().name().to_string().characters(), section.relocations().offset(), section.relocations().entry_count());
|
||||
if (elf_image.is_dynamic()) {
|
||||
if (!object->relocation_section().entry_count()) {
|
||||
printf("Relocation section '%s' at offset 0x%08x contains zero entries:\n", object->relocation_section().name().to_string().characters(), object->relocation_section().offset());
|
||||
} else {
|
||||
printf("Relocation section '%s' at offset 0x%08x contains %u entries:\n", object->relocation_section().name().to_string().characters(), object->relocation_section().offset(), object->relocation_section().entry_count());
|
||||
printf(" Offset Type Sym Value Sym Name\n");
|
||||
section.relocations().for_each_relocation([](const ELF::Image::Relocation& reloc) {
|
||||
object->relocation_section().for_each_relocation([](const ELF::DynamicObject::Relocation& reloc) {
|
||||
printf(" 0x%08x ", reloc.offset());
|
||||
printf(" %-17s ", object_relocation_type_to_string(reloc.type()));
|
||||
printf(" 0x%08x ", reloc.symbol().value());
|
||||
@ -498,13 +643,26 @@ int main(int argc, char** argv)
|
||||
printf("\n");
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (!object->plt_relocation_section().entry_count()) {
|
||||
printf("Relocation section '%s' at offset 0x%08x contains zero entries:\n", object->plt_relocation_section().name().to_string().characters(), object->plt_relocation_section().offset());
|
||||
} else {
|
||||
printf("Relocation section '%s' at offset 0x%08x contains %u entries:\n", object->plt_relocation_section().name().to_string().characters(), object->plt_relocation_section().offset(), object->plt_relocation_section().entry_count());
|
||||
printf(" Offset Type Sym Value Sym Name\n");
|
||||
object->plt_relocation_section().for_each_relocation([](const ELF::DynamicObject::Relocation& reloc) {
|
||||
printf(" 0x%08x ", reloc.offset());
|
||||
printf(" %-17s ", object_relocation_type_to_string(reloc.type()));
|
||||
printf(" 0x%08x ", reloc.symbol().value());
|
||||
printf(" %s", reloc.symbol().name().to_string().characters());
|
||||
printf("\n");
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
if (!found_relocations)
|
||||
}
|
||||
} else {
|
||||
printf("No relocations in this file.\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
@ -517,7 +675,7 @@ int main(int argc, char** argv)
|
||||
|
||||
if (display_core_notes) {
|
||||
auto found_notes = false;
|
||||
interpreter_image.for_each_program_header([&found_notes](const ELF::Image::ProgramHeader& program_header) {
|
||||
elf_image.for_each_program_header([&found_notes](const ELF::Image::ProgramHeader& program_header) {
|
||||
if (program_header.type() != PT_NOTE)
|
||||
return IterationDecision::Continue;
|
||||
|
||||
@ -539,7 +697,9 @@ int main(int argc, char** argv)
|
||||
|
||||
if (display_dynamic_symbol_table || display_symbol_table) {
|
||||
auto found_dynamic_symbol_table = false;
|
||||
interpreter_image.for_each_section([&found_dynamic_symbol_table](const ELF::Image::Section& section) {
|
||||
|
||||
if (elf_image.is_dynamic()) {
|
||||
elf_image.for_each_section([&found_dynamic_symbol_table](const ELF::Image::Section& section) {
|
||||
if (section.name() != ELF_DYNSYM)
|
||||
return IterationDecision::Continue;
|
||||
|
||||
@ -547,28 +707,17 @@ int main(int argc, char** argv)
|
||||
|
||||
if (!section.entry_count()) {
|
||||
printf("Symbol table '%s' contains zero entries.\n", ELF_DYNSYM);
|
||||
return IterationDecision::Continue;
|
||||
} else {
|
||||
printf("Symbol table '%s' contains %u entries.\n", ELF_DYNSYM, section.entry_count());
|
||||
}
|
||||
|
||||
printf("Symbol table '%s' contains %u entries.\n", ELF_DYNSYM, section.entry_count());
|
||||
|
||||
// TODO: display dynamic symbol table
|
||||
|
||||
return IterationDecision::Continue;
|
||||
return IterationDecision::Break;
|
||||
});
|
||||
|
||||
if (!found_dynamic_symbol_table)
|
||||
printf("No dynamic symbol information for this file.\n");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (display_symbol_table) {
|
||||
if (interpreter_image.symbol_count()) {
|
||||
printf("Symbol table '%s' contains %u entries:\n", ELF_SYMTAB, interpreter_image.symbol_count());
|
||||
if (object->symbol_count()) {
|
||||
// FIXME: Add support for init/fini/start/main sections
|
||||
printf(" Num: Value Size Type Bind Name\n");
|
||||
|
||||
interpreter_image.for_each_symbol([](const ELF::Image::Symbol& sym) {
|
||||
object->for_each_symbol([](const ELF::DynamicObject::Symbol& sym) {
|
||||
printf(" %4u: ", sym.index());
|
||||
printf("%08x ", sym.value());
|
||||
printf("%08x ", sym.size());
|
||||
@ -579,16 +728,41 @@ int main(int argc, char** argv)
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_dynamic_symbol_table)
|
||||
printf("No dynamic symbol information for this file.\n");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (display_symbol_table) {
|
||||
if (elf_image.symbol_count()) {
|
||||
printf("Symbol table '%s' contains %u entries:\n", ELF_SYMTAB, elf_image.symbol_count());
|
||||
printf(" Num: Value Size Type Bind Name\n");
|
||||
|
||||
elf_image.for_each_symbol([](const ELF::Image::Symbol& sym) {
|
||||
printf(" %4u: ", sym.index());
|
||||
printf("%08x ", sym.value());
|
||||
printf("%08x ", sym.size());
|
||||
printf("%-8s ", object_symbol_type_to_string(sym.type()));
|
||||
printf("%-8s ", object_symbol_binding_to_string(sym.bind()));
|
||||
printf("%s", StringView(sym.name()).to_string().characters());
|
||||
printf("\n");
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
} else {
|
||||
printf("Symbol table '%s' contains zero entries.\n", ELF_SYMTAB);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (display_hardening) {
|
||||
printf("Security Hardening:\n");
|
||||
printf("RELRO Stack Canary NX PIE Symbols\n");
|
||||
printf("RELRO Stack Canary NX PIE RPATH RUNPATH Symbols \n");
|
||||
|
||||
// FIXME: Add support for full/partial RELRO detection using DT_BIND_NOW
|
||||
bool relro = false;
|
||||
interpreter_image.for_each_program_header([&relro](const ELF::Image::ProgramHeader& program_header) {
|
||||
elf_image.for_each_program_header([&relro](const ELF::Image::ProgramHeader& program_header) {
|
||||
if (program_header.type() == PT_GNU_RELRO) {
|
||||
relro = true;
|
||||
return IterationDecision::Break;
|
||||
@ -596,13 +770,25 @@ int main(int argc, char** argv)
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
if (relro)
|
||||
printf("\033[0;32m%-12s\033[0m ", "RELRO");
|
||||
bool full_relro = false;
|
||||
if (relro) {
|
||||
object->for_each_dynamic_entry([&full_relro](const ELF::DynamicObject::DynamicEntry& entry) {
|
||||
if (entry.tag() == DT_BIND_NOW) {
|
||||
full_relro = true;
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
if (full_relro)
|
||||
printf("\033[0;32m%-13s\033[0m ", "Full RELRO");
|
||||
else
|
||||
printf("\033[0;31m%-12s\033[0m ", "No RELRO");
|
||||
printf("\033[0;33m%-13s\033[0m ", "Partial RELRO");
|
||||
} else {
|
||||
printf("\033[0;31m%-13s\033[0m ", "No RELRO");
|
||||
}
|
||||
|
||||
bool canary = false;
|
||||
interpreter_image.for_each_symbol([&canary](const ELF::Image::Symbol& sym) {
|
||||
elf_image.for_each_symbol([&canary](const ELF::Image::Symbol& sym) {
|
||||
if (sym.name() == "__stack_chk_fail" || sym.name() == "__intel_security_cookie") {
|
||||
canary = true;
|
||||
return IterationDecision::Break;
|
||||
@ -616,7 +802,7 @@ int main(int argc, char** argv)
|
||||
printf("\033[0;31m%-12s\033[0m ", "No canary");
|
||||
|
||||
bool nx = false;
|
||||
interpreter_image.for_each_program_header([&nx](const ELF::Image::ProgramHeader& program_header) {
|
||||
elf_image.for_each_program_header([&nx](const ELF::Image::ProgramHeader& program_header) {
|
||||
if (program_header.type() == PT_GNU_STACK) {
|
||||
if (program_header.flags() & PF_X)
|
||||
nx = false;
|
||||
@ -637,11 +823,29 @@ int main(int argc, char** argv)
|
||||
pie = true;
|
||||
|
||||
if (pie)
|
||||
printf("\033[0;32m%-6s\033[0m ", "PIE");
|
||||
printf("\033[0;32m%-12s\033[0m ", "PIE enabled");
|
||||
else
|
||||
printf("\033[0;31m%-6s\033[0m ", "No PIE");
|
||||
printf("\033[0;31m%-12s\033[0m ", "No PIE");
|
||||
|
||||
printf("%u symbols ", interpreter_image.symbol_count());
|
||||
StringView rpath;
|
||||
if (elf_image.is_dynamic())
|
||||
rpath = object->rpath();
|
||||
|
||||
if (rpath.is_empty())
|
||||
printf("\033[0;32m%-12s\033[0m ", "No RPATH");
|
||||
else
|
||||
printf("\033[0;31m%-12s\033[0m ", rpath.to_string().characters());
|
||||
|
||||
StringView runpath;
|
||||
if (elf_image.is_dynamic())
|
||||
runpath = object->runpath();
|
||||
|
||||
if (runpath.is_empty())
|
||||
printf("\033[0;32m%-12s\033[0m ", "No RUNPATH");
|
||||
else
|
||||
printf("\033[0;31m%-12s\033[0m ", runpath.to_string().characters());
|
||||
|
||||
printf("%u symbols ", elf_image.symbol_count());
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user