Skip to content

Commit

Permalink
Enhance code profiling
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Mar 26, 2023
1 parent 683fc6c commit 3497515
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 74 deletions.
15 changes: 1 addition & 14 deletions CMakeLists.txt
Expand Up @@ -563,25 +563,12 @@ if(LIEF_FUZZING)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/fuzzing")
endif()

# Compile Flags
# =============
include(LIEFCompilerFlags)

# Profiling flags
# ---------------
if(LIEF_PROFILING)
set(PROFILING_FLAGS
-fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc
-fno-builtin-free -fno-omit-frame-pointer -g)
target_compile_options(LIB_LIEF PUBLIC ${PROFILING_FLAGS})

add_executable(elf_profiler profiling/elf_profiler.cpp)
target_compile_options(elf_profiler PUBLIC ${PROFILING_FLAGS})
target_link_libraries(elf_profiler PRIVATE LIB_LIEF)

add_executable(macho_profiler profiling/macho_profiler.cpp)
target_compile_options(macho_profiler PUBLIC ${PROFILING_FLAGS})
target_link_libraries(macho_profiler PRIVATE LIB_LIEF)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/profiling")
endif()

# Coverage flags
Expand Down
33 changes: 33 additions & 0 deletions profiling/CMakeLists.txt
@@ -0,0 +1,33 @@
set(PROFILING_FLAGS
-fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc
-fno-builtin-free -fno-omit-frame-pointer -g)
target_compile_options(LIB_LIEF PUBLIC ${PROFILING_FLAGS})

add_executable(elf_profiler elf_profiler.cpp)

set_target_properties(elf_profiler
PROPERTIES POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON)

target_compile_options(elf_profiler PUBLIC ${PROFILING_FLAGS})
target_link_libraries(elf_profiler PRIVATE LIB_LIEF)

add_executable(macho_profiler macho_profiler.cpp)
target_compile_options(macho_profiler PUBLIC ${PROFILING_FLAGS})
target_link_libraries(macho_profiler PRIVATE LIB_LIEF)

set_target_properties(macho_profiler
PROPERTIES POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON)

add_executable(pe_profilier pe_profilier.cpp)
target_compile_options(pe_profilier PUBLIC ${PROFILING_FLAGS})
target_link_libraries(pe_profilier PRIVATE LIB_LIEF)

set_target_properties(pe_profilier
PROPERTIES POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON)

25 changes: 21 additions & 4 deletions profiling/elf_profiler.cpp
@@ -1,10 +1,27 @@
#include <LIEF/LIEF.hpp>
#include <filesystem>

void process_file(const std::filesystem::path& target) {
LIEF::ELF::Parser::parse(target);
}

void process_dir(const std::filesystem::path& target) {
for (const auto& e : std::filesystem::directory_iterator(target)) {
if (e.is_directory()) {
process_dir(e.path());
}
else if (e.is_regular_file() && LIEF::ELF::is_elf(e.path())) {
process_file(e.path());
}
}
}

int main(int argc, const char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <binary>" << '\n';
return EXIT_FAILURE;
const std::filesystem::path target{argv[1]};
if (std::filesystem::is_directory(target)) {
process_dir(target);
} else {
process_file(target);
}
std::unique_ptr<LIEF::ELF::Binary> binary = LIEF::ELF::Parser::parse(argv[1]);
return EXIT_SUCCESS;
}
31 changes: 24 additions & 7 deletions profiling/macho_profiler.cpp
@@ -1,14 +1,31 @@
#include <LIEF/LIEF.hpp>

int main(int argc, const char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <binary>" << '\n';
return EXIT_FAILURE;
}
#include <filesystem>
void process_file(const std::filesystem::path& target) {
LIEF::MachO::ParserConfig config;
config.parse_dyld_rebases = false;
config.parse_dyld_exports = false;
config.parse_dyld_bindings = false;
auto binary = LIEF::MachO::Parser::parse(argv[1], config);
auto binary = LIEF::MachO::Parser::parse(target, config);

}

void process_dir(const std::filesystem::path& target) {
for (const auto& e : std::filesystem::directory_iterator(target)) {
if (e.is_directory()) {
process_dir(e.path());
}
else if (e.is_regular_file() && LIEF::MachO::is_macho(e.path())) {
process_file(e.path());
}
}
}

int main(int argc, const char** argv) {
const std::filesystem::path target{argv[1]};
if (std::filesystem::is_directory(target)) {
process_dir(target);
} else {
process_file(target);
}
return EXIT_SUCCESS;
}
1 change: 1 addition & 0 deletions profiling/oat_profiler.cpp
@@ -1,4 +1,5 @@
#include <LIEF/LIEF.hpp>
#include <iostream>

int main(int argc, char** argv) {
if (argc != 2) {
Expand Down
28 changes: 28 additions & 0 deletions profiling/pe_profilier.cpp
@@ -0,0 +1,28 @@
#include <LIEF/LIEF.hpp>
#include <filesystem>
#include <iostream>

void process_file(const std::filesystem::path& target) {
LIEF::PE::Parser::parse(target);
}

void process_dir(const std::filesystem::path& target) {
for (const auto& e : std::filesystem::directory_iterator(target)) {
if (e.is_directory()) {
process_dir(e.path());
}
else if (e.is_regular_file() && LIEF::PE::is_pe(e.path())) {
process_file(e.path());
}
}
}

int main(int argc, const char** argv) {
const std::filesystem::path target{argv[1]};
if (std::filesystem::is_directory(target)) {
process_dir(target);
} else {
process_file(target);
}
return EXIT_SUCCESS;
}
22 changes: 0 additions & 22 deletions src/ELF/Builder.tcc
Expand Up @@ -365,9 +365,7 @@ ok_error_t Builder::build_exe_lib() {
// ----------------------------------------------------------------

if (config_.gnu_hash || config_.dt_hash) {
LIEF_SW_START(sw);
build_hash_table<ELF_T>();
LIEF_SW_END("hash table built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.dyn_str) {
Expand All @@ -377,63 +375,43 @@ ok_error_t Builder::build_exe_lib() {
}

if (config_.interpreter && binary_->has(SEGMENT_TYPES::PT_INTERP)) {
LIEF_SW_START(sw);
build_interpreter<ELF_T>();
LIEF_SW_END(".interp built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.notes && binary_->has(SEGMENT_TYPES::PT_NOTE)) {
LIEF_SW_START(sw);
build_notes<ELF_T>();
LIEF_SW_END(".note built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.dynamic_section && binary_->has(SEGMENT_TYPES::PT_DYNAMIC)) {
LIEF_SW_START(sw);
build_dynamic_section<ELF_T>();
LIEF_SW_END(".dynamic built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.symtab && binary_->has(DYNAMIC_TAGS::DT_SYMTAB)) {
LIEF_SW_START(sw);
build_dynamic_symbols<ELF_T>();
LIEF_SW_END(".dynsym built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.sym_versym && binary_->has(DYNAMIC_TAGS::DT_VERSYM)) {
LIEF_SW_START(sw);
build_symbol_version<ELF_T>();
LIEF_SW_END(".gnu.version built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.sym_verdef && binary_->has(DYNAMIC_TAGS::DT_VERDEF)) {
LIEF_SW_START(sw);
build_symbol_definition<ELF_T>();
LIEF_SW_END(".gnu.version_d built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.sym_verneed && binary_->has(DYNAMIC_TAGS::DT_VERNEED)) {
LIEF_SW_START(sw);
build_symbol_requirement<ELF_T>();
LIEF_SW_END(".gnu.version_r built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.rela) {
LIEF_SW_START(sw);
build_dynamic_relocations<ELF_T>();
LIEF_SW_END(".rela.dyn built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.jmprel) {
LIEF_SW_START(sw);
build_pltgot_relocations<ELF_T>();
LIEF_SW_END(".rela.plt built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

if (config_.static_symtab && binary_->has(ELF_SECTION_TYPES::SHT_SYMTAB)) {
LIEF_SW_START(sw);
build_static_symbols<ELF_T>();
LIEF_SW_END(".symtab built in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}

// Build sections
Expand Down
3 changes: 1 addition & 2 deletions src/ELF/ExeLayout.hpp
Expand Up @@ -81,7 +81,7 @@ class LIEF_LOCAL ExeLayout : public Layout {
if (!raw_dynstr_.empty()) {
return raw_dynstr_.size();
}
LIEF_SW_START(sw);

// Start with dynamic entries: NEEDED / SONAME etc
vector_iostream raw_dynstr;
raw_dynstr.write<uint8_t>(0);
Expand Down Expand Up @@ -177,7 +177,6 @@ class LIEF_LOCAL ExeLayout : public Layout {
}
}
raw_dynstr.move(raw_dynstr_);
LIEF_SW_END(".dynstr values computed in {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
return raw_dynstr_.size();
}

Expand Down
12 changes: 7 additions & 5 deletions src/ELF/Parser.tcc
Expand Up @@ -73,9 +73,7 @@ ok_error_t Parser::parse_binary() {
// Parse segments
// ==============
if (binary_->header_.program_headers_offset() > 0) {
LIEF_SW_START(sw);
parse_segments<ELF_T>();
LIEF_SW_END("segments parsed in {}", duration_cast<std::chrono::microseconds>(sw.elapsed()));
} else {
if (binary_->header().file_type() != E_TYPE::ET_REL) {
LIEF_WARN("Binary doesn't have a program header");
Expand Down Expand Up @@ -926,6 +924,7 @@ ok_error_t Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64
auto nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));

nb_entries = std::min<uint32_t>(nb_entries, Parser::NB_MAX_RELOCATIONS);
binary_->relocations_.reserve(nb_entries);

stream_->setpos(relocations_offset);
const ARCH arch = binary_->header().machine_type();
Expand All @@ -934,7 +933,7 @@ ok_error_t Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64
if (!raw_reloc) {
break;
}
auto reloc = std::make_unique<Relocation>(*raw_reloc);
auto reloc = std::make_unique<Relocation>(std::move(*raw_reloc));
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC);
reloc->architecture_ = arch;

Expand All @@ -959,14 +958,15 @@ ok_error_t Parser::parse_static_symbols(uint64_t offset, uint32_t nb_symbols,

using Elf_Sym = typename ELF_T::Elf_Sym;
LIEF_DEBUG("== Parsing static symbols ==");
binary_->static_symbols_.reserve(nb_symbols);

stream_->setpos(offset);
for (uint32_t i = 0; i < nb_symbols; ++i) {
const auto raw_sym = stream_->read_conv<Elf_Sym>();
if (!raw_sym) {
break;
}
auto symbol = std::make_unique<Symbol>(*raw_sym);
auto symbol = std::make_unique<Symbol>(std::move(*raw_sym));
auto symbol_name = stream_->peek_string_at(string_section.file_offset() + raw_sym->st_name);
if (symbol_name) {
symbol->name(std::move(*symbol_name));
Expand Down Expand Up @@ -1014,14 +1014,16 @@ ok_error_t Parser::parse_dynamic_symbols(uint64_t offset) {
return make_error_code(lief_errors::parsing_error);
}

binary_->dynamic_symbols_.reserve(nb_symbols);
stream_->setpos(dynamic_symbols_offset);

for (size_t i = 0; i < nb_symbols; ++i) {
const auto symbol_header = stream_->read_conv<Elf_Sym>();
if (!symbol_header) {
LIEF_DEBUG("Break on symbol #{:d}", i);
break;
}
auto symbol = std::make_unique<Symbol>(*symbol_header);
auto symbol = std::make_unique<Symbol>(std::move(*symbol_header));

if (symbol_header->st_name > 0) {
auto name = stream_->peek_string_at(string_offset + symbol_header->st_name);
Expand Down
6 changes: 0 additions & 6 deletions src/MachO/Builder.tcc
Expand Up @@ -386,9 +386,7 @@ ok_error_t Builder::build(DyldInfo& dyld_info) {
LIEF_DEBUG("linkedit_.size(): {:x}", linkedit_.size());
raw_cmd.rebase_off = linkedit_.size();
{
LIEF_SW_START(sw);
dyld_info.update_rebase_info(linkedit_);
LIEF_SW_END("update_rebase_info(): {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}
raw_cmd.rebase_size = linkedit_.size() - raw_cmd.rebase_off;
if (raw_cmd.rebase_size > 0) {
Expand All @@ -402,9 +400,7 @@ ok_error_t Builder::build(DyldInfo& dyld_info) {
dyld_info.rebase().second, raw_cmd.rebase_size);
}
{
LIEF_SW_START(sw);
dyld_info.update_binding_info(linkedit_, raw_cmd);
LIEF_SW_END("update_binding_info(): {}", duration_cast<std::chrono::seconds>(sw.elapsed()));
if (raw_cmd.bind_size > 0) {
raw_cmd.bind_off += linkedit_offset_;

Expand Down Expand Up @@ -438,9 +434,7 @@ ok_error_t Builder::build(DyldInfo& dyld_info) {
{
raw_cmd.export_off = linkedit_.size();
{
LIEF_SW_START(sw);
dyld_info.update_export_trie(linkedit_);
LIEF_SW_END("update_export_trie(): {}", sw.elapsed());
}
raw_cmd.export_size = linkedit_.size() - raw_cmd.export_off;
if (raw_cmd.export_size > 0) {
Expand Down
6 changes: 0 additions & 6 deletions src/MachO/DyldInfo.cpp
Expand Up @@ -1341,9 +1341,7 @@ bool operator!=(uint8_t lhs, REBASE_OPCODES rhs) {
if (!standard_binds.empty()) {
cmd.bind_off = stream.size();
{
LIEF_SW_START(sw);
update_standard_bindings(standard_binds, stream);
LIEF_SW_END("update_standard_bindings(): {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}
cmd.bind_size = stream.size() - cmd.bind_off;

Expand All @@ -1355,18 +1353,14 @@ bool operator!=(uint8_t lhs, REBASE_OPCODES rhs) {
if (!weak_binds.empty()) {
cmd.weak_bind_off = stream.size();
{
LIEF_SW_START(sw);
update_weak_bindings(weak_binds, stream);
LIEF_SW_END("update_weak_bindings(): {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}
cmd.weak_bind_size = stream.size() - cmd.weak_bind_off;
}
if (!lazy_binds.empty()) {
cmd.lazy_bind_off = stream.size();
{
LIEF_SW_START(sw);
update_lazy_bindings(lazy_binds, stream);
LIEF_SW_END("update_lazy_bindings(): {}", duration_cast<std::chrono::milliseconds>(sw.elapsed()));
}
cmd.lazy_bind_size = stream.size() - cmd.lazy_bind_off;
}
Expand Down

0 comments on commit 3497515

Please sign in to comment.