mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-04-27 21:04:32 +00:00
Fix MachO meme leaks (related #99)
This commit is contained in:
parent
d9b1436730
commit
554fa153af
@ -284,7 +284,6 @@ if (LIEF_FUZZING)
|
||||
|
||||
set_source_files_properties(${LIBFUZZER_SRC_FILES} PROPERTIES GENERATED TRUE)
|
||||
|
||||
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/fuzzing")
|
||||
endif()
|
||||
|
||||
|
@ -28,6 +28,7 @@ class BinaryStream {
|
||||
virtual uint64_t size(void) const = 0;
|
||||
virtual const void* read(uint64_t offset, uint64_t size) const = 0;
|
||||
virtual const char* read_string(uint64_t offset, uint64_t size) const = 0;
|
||||
virtual std::string get_string(uint64_t offset, uint64_t size) const = 0;
|
||||
|
||||
template<typename T>
|
||||
T read_integer(uint64_t offset, bool swap = false) const;
|
||||
|
@ -30,6 +30,7 @@ class VectorStream : public BinaryStream {
|
||||
virtual uint64_t size(void) const override;
|
||||
virtual const void* read(uint64_t offset, uint64_t size) const override;
|
||||
virtual const char* read_string(uint64_t offset, uint64_t size = 0) const override;
|
||||
virtual std::string get_string(uint64_t offset, uint64_t size = 0) const override;
|
||||
|
||||
const std::vector<uint8_t>& content(void) const;
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace ELF {
|
||||
namespace DataHandler {
|
||||
class DLL_PUBLIC Handler {
|
||||
public:
|
||||
static constexpr size_t MAX_SIZE = 10_GB;
|
||||
static constexpr size_t MAX_SIZE = 3_GB;
|
||||
Handler(const std::vector<uint8_t>& content);
|
||||
Handler(std::vector<uint8_t>&& content);
|
||||
~Handler(void);
|
||||
|
@ -49,12 +49,14 @@ class DLL_PUBLIC Relocation : public LIEF::Relocation {
|
||||
Relocation(void);
|
||||
Relocation(uint64_t address, uint8_t type);
|
||||
|
||||
//Relocation& operator=(Relocation other);
|
||||
//Relocation& operator=(const Relocation& other);
|
||||
Relocation(const Relocation& other);
|
||||
void swap(Relocation& other);
|
||||
|
||||
virtual ~Relocation(void);
|
||||
|
||||
virtual Relocation* clone(void) const = 0;
|
||||
|
||||
//! @brief For @link MachO::FILE_TYPES::MH_OBJECT object @endlink this is an
|
||||
//! offset from the start of the @link MachO::Section section @endlink
|
||||
//! to the item containing the address requiring relocation.
|
||||
|
@ -45,6 +45,8 @@ class DLL_PUBLIC RelocationDyld : public Relocation {
|
||||
|
||||
virtual ~RelocationDyld(void);
|
||||
|
||||
virtual Relocation* clone(void) const override;
|
||||
|
||||
//! @brief Indicates whether the item containing the address to be
|
||||
//! relocated is part of a CPU instruction that uses PC-relative addressing.
|
||||
//!
|
||||
|
@ -42,13 +42,15 @@ class DLL_PUBLIC RelocationObject : public Relocation {
|
||||
RelocationObject(const relocation_info *relocinfo);
|
||||
RelocationObject(const scattered_relocation_info *scattered_relocinfo);
|
||||
|
||||
RelocationObject& operator=(const RelocationObject&);
|
||||
RelocationObject(const RelocationObject&);
|
||||
RelocationObject& operator=(RelocationObject other);
|
||||
RelocationObject(const RelocationObject& other);
|
||||
|
||||
void swap(RelocationObject& other);
|
||||
|
||||
virtual ~RelocationObject(void);
|
||||
|
||||
virtual RelocationObject* clone(void) const override;
|
||||
|
||||
virtual bool is_pc_relative(void) const override;
|
||||
|
||||
virtual size_t size(void) const override;
|
||||
|
@ -113,7 +113,7 @@ class DLL_PUBLIC SegmentCommand : public LoadCommand {
|
||||
|
||||
std::vector<uint8_t> data_;
|
||||
|
||||
std::vector<Section> sections_;
|
||||
sections_t sections_;
|
||||
|
||||
relocations_t relocations_;
|
||||
|
||||
|
@ -86,12 +86,27 @@ const char* VectorStream::read_string(uint64_t offset, uint64_t size) const {
|
||||
throw LIEF::read_out_of_bound(offset);
|
||||
}
|
||||
|
||||
|
||||
uint64_t max_size = this->size() - (offset + size);
|
||||
if (size > 0) {
|
||||
return reinterpret_cast<const char*>(this->read(offset, size));
|
||||
max_size = std::min<uint64_t>(max_size, size);
|
||||
}
|
||||
|
||||
return reinterpret_cast<const char*>(this->binary_.data() + offset);
|
||||
return reinterpret_cast<const char*>(this->read(offset, max_size));
|
||||
}
|
||||
|
||||
std::string VectorStream::get_string(uint64_t offset, uint64_t size) const {
|
||||
|
||||
if ((offset + size) > this->size()) {
|
||||
throw LIEF::read_out_of_bound(offset);
|
||||
}
|
||||
|
||||
uint64_t max_size = this->size() - (offset + size);
|
||||
if (size > 0) {
|
||||
max_size = std::min<uint64_t>(max_size, size);
|
||||
}
|
||||
std::string tmp{this->read_string(offset, max_size), max_size};
|
||||
return tmp.c_str();
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,26 +86,30 @@ BinaryParser::BinaryParser(const std::string& file) :
|
||||
|
||||
void BinaryParser::init(void) {
|
||||
VLOG(VDEBUG) << "Parsing MachO" << std::endl;
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(
|
||||
*reinterpret_cast<const uint32_t*>(this->stream_->read(0, sizeof(uint32_t))));
|
||||
try {
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(
|
||||
*reinterpret_cast<const uint32_t*>(this->stream_->read(0, sizeof(uint32_t))));
|
||||
|
||||
if (type == MACHO_TYPES::MH_MAGIC_64 or
|
||||
type == MACHO_TYPES::MH_CIGAM_64 )
|
||||
{
|
||||
this->is64_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->is64_ = false;
|
||||
}
|
||||
if (type == MACHO_TYPES::MH_MAGIC_64 or
|
||||
type == MACHO_TYPES::MH_CIGAM_64 )
|
||||
{
|
||||
this->is64_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->is64_ = false;
|
||||
}
|
||||
|
||||
this->binary_->is64_ = this->is64_;
|
||||
this->type_ = type;
|
||||
this->binary_->is64_ = this->is64_;
|
||||
this->type_ = type;
|
||||
|
||||
if (this->is64_) {
|
||||
this->parse<MachO64>();
|
||||
} else {
|
||||
this->parse<MachO32>();
|
||||
if (this->is64_) {
|
||||
this->parse<MachO64>();
|
||||
} else {
|
||||
this->parse<MachO32>();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
VLOG(VDEBUG) << e.what();
|
||||
}
|
||||
|
||||
}
|
||||
@ -117,6 +121,10 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, ui
|
||||
return;
|
||||
}
|
||||
|
||||
if (start < current_offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t terminal_size = this->stream_->read_integer<uint8_t>(current_offset);
|
||||
current_offset += sizeof(uint8_t);
|
||||
|
||||
@ -134,11 +142,11 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, ui
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
const std::string& symbol_name = prefix;
|
||||
ExportInfo* export_info = new ExportInfo{address, flags, offset};
|
||||
std::unique_ptr<ExportInfo> export_info{new ExportInfo{address, flags, offset}};
|
||||
if (this->binary_->has_symbol(symbol_name)) {
|
||||
Symbol& symbol = this->binary_->get_symbol(symbol_name);
|
||||
export_info->symbol_ = &symbol;
|
||||
symbol.export_info_ = export_info;
|
||||
symbol.export_info_ = export_info.get();
|
||||
//if (symbol.is_external()) {
|
||||
// //LOG(WARNING) << "FOOOOO " << symbol_name;
|
||||
// //TODO
|
||||
@ -146,7 +154,7 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, ui
|
||||
} else {
|
||||
LOG(WARNING) << "'" << symbol_name << "' is not registred";
|
||||
}
|
||||
this->binary_->dyld_info().export_info_.push_back(export_info);
|
||||
this->binary_->dyld_info().export_info_.push_back(export_info.release());
|
||||
|
||||
}
|
||||
|
||||
@ -161,6 +169,9 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, ui
|
||||
value_delta = this->stream_->read_uleb128(children_offset);
|
||||
uint32_t child_node_offet = static_cast<uint32_t>(std::get<0>(value_delta));
|
||||
children_offset += std::get<1>(value_delta);
|
||||
if (start + child_node_offet == start) {
|
||||
break;
|
||||
}
|
||||
this->parse_export_trie(start, start + child_node_offet, end, name);
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const load_command* command = reinterpret_cast<const load_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(load_command)));
|
||||
|
||||
LoadCommand* load_command = nullptr;
|
||||
std::unique_ptr<LoadCommand> load_command{nullptr};
|
||||
switch (command->cmd) {
|
||||
|
||||
// ===============
|
||||
@ -109,13 +109,13 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_SEGMENT:
|
||||
{
|
||||
uint64_t local_offset = loadcommands_offset;
|
||||
load_command = new SegmentCommand{
|
||||
load_command = std::unique_ptr<SegmentCommand>{new SegmentCommand{
|
||||
reinterpret_cast<const segment_command_t*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(segment_command_t)))};
|
||||
this->stream_->read(loadcommands_offset, sizeof(segment_command_t)))}};
|
||||
|
||||
local_offset += sizeof(segment_command_t);
|
||||
|
||||
SegmentCommand* segment = dynamic_cast<SegmentCommand*>(load_command);
|
||||
SegmentCommand* segment = dynamic_cast<SegmentCommand*>(load_command.get());
|
||||
|
||||
const uint8_t* content = static_cast<const uint8_t*>(
|
||||
this->stream_->read(segment->file_offset(), segment->file_size()));
|
||||
@ -129,9 +129,10 @@ void BinaryParser::parse_load_commands(void) {
|
||||
// Sections
|
||||
// --------
|
||||
for (size_t j = 0; j < segment->numberof_sections(); ++j) {
|
||||
Section section{reinterpret_cast<const section_t*>(this->stream_->read(local_offset, sizeof(section_t)))};
|
||||
section.segment_ = segment;
|
||||
segment->sections_.push_back(std::move(section));
|
||||
const section_t* section_header = reinterpret_cast<const section_t*>(this->stream_->read(local_offset, sizeof(section_t)));
|
||||
std::unique_ptr<Section> section{new Section{section_header}};
|
||||
section->segment_ = segment;
|
||||
segment->sections_.push_back(section.release());
|
||||
local_offset += sizeof(section_t);
|
||||
}
|
||||
break;
|
||||
@ -149,11 +150,11 @@ void BinaryParser::parse_load_commands(void) {
|
||||
reinterpret_cast<const dylib_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dylib_command)));
|
||||
|
||||
load_command = new DylibCommand{cmd};
|
||||
load_command = std::unique_ptr<DylibCommand>{new DylibCommand{cmd}};
|
||||
const uint32_t str_name_offset = cmd->dylib.name;
|
||||
std::string name = {this->stream_->read_string(loadcommands_offset + str_name_offset)};
|
||||
|
||||
dynamic_cast<DylibCommand*>(load_command)->name(name);
|
||||
dynamic_cast<DylibCommand*>(load_command.get())->name(name);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -166,7 +167,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const uuid_command* cmd =
|
||||
reinterpret_cast<const uuid_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(uuid_command)));
|
||||
load_command = new UUIDCommand{cmd};
|
||||
load_command = std::unique_ptr<UUIDCommand>{new UUIDCommand{cmd}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -185,8 +186,8 @@ void BinaryParser::parse_load_commands(void) {
|
||||
loadcommands_offset +
|
||||
linker_name_offset)};
|
||||
|
||||
load_command = new DylinkerCommand{cmd};
|
||||
dynamic_cast<DylinkerCommand*>(load_command)->name(name);
|
||||
load_command = std::unique_ptr<DylinkerCommand>{new DylinkerCommand{cmd}};
|
||||
dynamic_cast<DylinkerCommand*>(load_command.get())->name(name);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -197,7 +198,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_PREBOUND_DYLIB";
|
||||
|
||||
load_command = new LoadCommand{command};
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{command}};
|
||||
const prebound_dylib_command* cmd =
|
||||
reinterpret_cast<const prebound_dylib_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(prebound_dylib_command)));
|
||||
@ -223,8 +224,10 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const thread_command* cmd =
|
||||
reinterpret_cast<const thread_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(thread_command)));
|
||||
load_command = new ThreadCommand{cmd};
|
||||
dynamic_cast<ThreadCommand*>(load_command)->architecture_ = this->binary_->header().cpu_type();
|
||||
load_command = std::unique_ptr<ThreadCommand>{new ThreadCommand{cmd}};
|
||||
|
||||
ThreadCommand* thread = dynamic_cast<ThreadCommand*>(load_command.get());
|
||||
thread->architecture_ = this->binary_->header().cpu_type();
|
||||
VLOG(VDEBUG) << "FLAVOR: " << cmd->flavor << std::endl
|
||||
<< "COUNT: " << cmd->count;
|
||||
switch(this->binary_->header().cpu_type()) {
|
||||
@ -232,7 +235,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(x86_thread_state_t)));
|
||||
dynamic_cast<ThreadCommand*>(load_command)->state_ = {pstart, pstart + sizeof(x86_thread_state_t)};
|
||||
thread->state_ = {pstart, pstart + sizeof(x86_thread_state_t)};
|
||||
|
||||
break;
|
||||
}
|
||||
@ -241,7 +244,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(x86_thread_state64_t)));
|
||||
dynamic_cast<ThreadCommand*>(load_command)->state_ = {pstart, pstart + sizeof(x86_thread_state64_t)};
|
||||
thread->state_ = {pstart, pstart + sizeof(x86_thread_state64_t)};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -249,7 +252,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(arm_thread_state_t)));
|
||||
dynamic_cast<ThreadCommand*>(load_command)->state_ = {pstart, pstart + sizeof(arm_thread_state_t)};
|
||||
thread->state_ = {pstart, pstart + sizeof(arm_thread_state_t)};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -257,7 +260,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(arm_thread_state64_t)));
|
||||
dynamic_cast<ThreadCommand*>(load_command)->state_ = {pstart, pstart + sizeof(arm_thread_state64_t)};
|
||||
thread->state_ = {pstart, pstart + sizeof(arm_thread_state64_t)};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -277,7 +280,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_ROUTINE";
|
||||
|
||||
load_command = new LoadCommand{command};
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{command}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -294,20 +297,20 @@ void BinaryParser::parse_load_commands(void) {
|
||||
this->stream_->read(loadcommands_offset, sizeof(symtab_command)));
|
||||
|
||||
|
||||
load_command = new SymbolCommand{cmd};
|
||||
load_command = std::unique_ptr<SymbolCommand>{new SymbolCommand{cmd}};
|
||||
|
||||
|
||||
const nlist_t* nlist = reinterpret_cast<const nlist_t*>(
|
||||
this->stream_->read(cmd->symoff, sizeof(nlist_t)));
|
||||
|
||||
for (size_t j = 0; j < cmd->nsyms; ++j) {
|
||||
Symbol* symbol = new Symbol{&nlist[j]};
|
||||
std::unique_ptr<Symbol> symbol{new Symbol{&nlist[j]}};
|
||||
uint32_t idx = nlist[j].n_strx;
|
||||
if (idx > 0) {
|
||||
symbol->name(
|
||||
this->stream_->read_string(cmd->stroff + idx));
|
||||
}
|
||||
this->binary_->symbols_.push_back(symbol);
|
||||
this->binary_->symbols_.push_back(symbol.release());
|
||||
}
|
||||
|
||||
break;
|
||||
@ -323,7 +326,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
reinterpret_cast<const dysymtab_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dysymtab_command)));
|
||||
|
||||
load_command = new DynamicSymbolCommand{cmd};
|
||||
load_command = std::unique_ptr<DynamicSymbolCommand>{new DynamicSymbolCommand{cmd}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -338,7 +341,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
reinterpret_cast<const dyld_info_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dyld_info_command)));
|
||||
|
||||
load_command = new DyldInfo{cmd};
|
||||
load_command = std::unique_ptr<DyldInfo>{new DyldInfo{cmd}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -353,7 +356,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
reinterpret_cast<const source_version_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(version_min_command)));
|
||||
|
||||
load_command = new SourceVersion{cmd};
|
||||
load_command = std::unique_ptr<SourceVersion>{new SourceVersion{cmd}};
|
||||
VLOG(VDEBUG) << "Version: " << std::hex << cmd->version;
|
||||
break;
|
||||
}
|
||||
@ -369,7 +372,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
VLOG(VDEBUG) << "Version: " << std::hex << cmd->version;
|
||||
VLOG(VDEBUG) << "SDK: " << std::hex << cmd->sdk;
|
||||
|
||||
load_command = new VersionMin{cmd};
|
||||
load_command = std::unique_ptr<VersionMin>{new VersionMin{cmd}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -427,7 +430,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
reinterpret_cast<const entry_point_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(entry_point_command)));
|
||||
|
||||
load_command = new MainCommand{cmd};
|
||||
load_command = std::unique_ptr<MainCommand>{new MainCommand{cmd}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -440,12 +443,12 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const linkedit_data_command* cmd =
|
||||
reinterpret_cast<const linkedit_data_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(linkedit_data_command)));
|
||||
load_command = new FunctionStarts{cmd};
|
||||
load_command = std::unique_ptr<FunctionStarts>{new FunctionStarts{cmd}};
|
||||
|
||||
uint64_t offset = cmd->dataoff;
|
||||
std::pair<uint64_t, uint64_t> value_delta;
|
||||
uint64_t value = 0;
|
||||
|
||||
FunctionStarts* fstart = dynamic_cast<FunctionStarts*>(load_command.get());
|
||||
do {
|
||||
value_delta = this->stream_->read_uleb128(offset);
|
||||
if (std::get<0>(value_delta) == 0) {
|
||||
@ -455,7 +458,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
offset += std::get<1>(value_delta);
|
||||
|
||||
VLOG(VDEBUG) << "Value: " << std::hex << value;
|
||||
dynamic_cast<FunctionStarts*>(load_command)->add_function(value);
|
||||
fstart->add_function(value);
|
||||
} while(offset < (cmd->dataoff + cmd->datasize) and std::get<0>(value_delta) > 0);
|
||||
|
||||
break;
|
||||
@ -473,7 +476,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
LOG(WARNING) << "Command '" << to_string(static_cast<LOAD_COMMAND_TYPES>(command->cmd))
|
||||
<< "' not parsed";
|
||||
|
||||
load_command = new LoadCommand{command};
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{command}};
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,7 +490,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
});
|
||||
|
||||
load_command->command_offset(loadcommands_offset);
|
||||
this->binary_->commands_.push_back(load_command);
|
||||
this->binary_->commands_.push_back(load_command.release());
|
||||
}
|
||||
loadcommands_offset += command->cmdsize;
|
||||
}
|
||||
@ -511,20 +514,25 @@ void BinaryParser::parse_relocations(Section& section) {
|
||||
<< "Only the first " << std::dec << numberof_relocations << " will be parsed";
|
||||
|
||||
}
|
||||
if (current_reloc_offset + numberof_relocations * 2 * sizeof(uint32_t) > this->stream_->size()) {
|
||||
LOG(WARNING) << "Relocations corrupted";
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<RelocationObject> reloc{nullptr};
|
||||
for (size_t i = 0; i < numberof_relocations; ++i) {
|
||||
int32_t address = this->stream_->read_integer<int32_t>(current_reloc_offset);
|
||||
bool is_scattered = static_cast<bool>(address & R_SCATTERED);
|
||||
RelocationObject* reloc = nullptr;
|
||||
|
||||
if (is_scattered) {
|
||||
const scattered_relocation_info* reloc_info = reinterpret_cast<const scattered_relocation_info*>(
|
||||
this->stream_->read(current_reloc_offset, sizeof(scattered_relocation_info)));
|
||||
reloc = new RelocationObject{reloc_info};
|
||||
this->stream_->read(current_reloc_offset, sizeof(scattered_relocation_info)));
|
||||
reloc = std::unique_ptr<RelocationObject>{new RelocationObject{reloc_info}};
|
||||
reloc->section_ = §ion;
|
||||
} else {
|
||||
const relocation_info* reloc_info = reinterpret_cast<const relocation_info*>(
|
||||
this->stream_->read(current_reloc_offset, sizeof(relocation_info)));
|
||||
reloc = new RelocationObject{reloc_info};
|
||||
reloc = std::unique_ptr<RelocationObject>{new RelocationObject{reloc_info}};
|
||||
reloc->section_ = §ion;
|
||||
|
||||
if (reloc_info->r_extern == 1 and reloc_info->r_symbolnum != R_ABS) {
|
||||
@ -548,15 +556,20 @@ void BinaryParser::parse_relocations(Section& section) {
|
||||
LOG(WARNING) << "Relocation #" << std::dec << i << " of " << section.name() << " seems corrupted";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (not reloc->has_section()) {
|
||||
reloc->section_ = §ion;
|
||||
if (reloc) {
|
||||
if (not reloc->has_section()) {
|
||||
reloc->section_ = §ion;
|
||||
}
|
||||
reloc->architecture_ = this->binary_->header().cpu_type();
|
||||
RelocationObject *r = reloc.release();
|
||||
auto&& result = section.relocations_.emplace(r);
|
||||
if (not result.second) { // Not inserted (Relocation already present)
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
reloc->architecture_ = this->binary_->header().cpu_type();
|
||||
|
||||
section.relocations_.emplace(reloc);
|
||||
current_reloc_offset += 2 * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
@ -1355,6 +1368,7 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
|
||||
// Check if a relocation already exists:
|
||||
Relocation* reloc = nullptr;
|
||||
std::unique_ptr<Relocation> new_relocation{nullptr};
|
||||
bool reloc_exists = false;
|
||||
|
||||
auto&& it_reloc = std::find_if(
|
||||
@ -1368,7 +1382,8 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
reloc = *it_reloc;
|
||||
reloc_exists = true;
|
||||
} else {
|
||||
reloc = new RelocationDyld{address, type};
|
||||
new_relocation = std::unique_ptr<Relocation>{new RelocationDyld{address, type}};
|
||||
reloc = new_relocation.get();
|
||||
}
|
||||
|
||||
reloc->architecture_ = this->binary_->header().cpu_type();
|
||||
@ -1404,7 +1419,7 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
}
|
||||
|
||||
// Create a BindingInfo object
|
||||
BindingInfo* binding_info = new BindingInfo{cls, static_cast<BIND_TYPES>(type), address, addend, ord, is_weak};
|
||||
std::unique_ptr<BindingInfo> binding_info{new BindingInfo{cls, static_cast<BIND_TYPES>(type), address, addend, ord, is_weak}};
|
||||
binding_info->segment_ = &segment;
|
||||
|
||||
|
||||
@ -1425,15 +1440,15 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
reloc->symbol_ = &symbol;
|
||||
//symbol.value(address);
|
||||
binding_info->symbol_ = &symbol;
|
||||
symbol.binding_info_ = binding_info;
|
||||
symbol.binding_info_ = binding_info.get();
|
||||
} else {
|
||||
LOG(ERROR) << "New symbol found: " << symbol_name;
|
||||
}
|
||||
|
||||
if (not reloc_exists) {
|
||||
segment.relocations_.emplace(reloc);
|
||||
segment.relocations_.emplace(new_relocation.release());
|
||||
}
|
||||
this->binary_->dyld_info().binding_info_.push_back(binding_info);
|
||||
this->binary_->dyld_info().binding_info_.push_back(binding_info.release());
|
||||
VLOG(VDEBUG) << to_string(cls) << segment.name() << " - " << symbol_name;
|
||||
}
|
||||
|
||||
|
@ -118,16 +118,20 @@ void Parser::build_fat(void) {
|
||||
}
|
||||
|
||||
void Parser::build(void) {
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(
|
||||
*reinterpret_cast<const uint32_t*>(this->stream_->read(0, sizeof(uint32_t))));
|
||||
try {
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(
|
||||
*reinterpret_cast<const uint32_t*>(this->stream_->read(0, sizeof(uint32_t))));
|
||||
|
||||
// Fat binary
|
||||
if (type == MACHO_TYPES::FAT_MAGIC or
|
||||
type == MACHO_TYPES::FAT_CIGAM) {
|
||||
this->build_fat();
|
||||
} else { // fit binary
|
||||
Binary *binary = BinaryParser(std::move(this->stream_)).get_binary();
|
||||
this->binaries_.push_back(binary);
|
||||
// Fat binary
|
||||
if (type == MACHO_TYPES::FAT_MAGIC or
|
||||
type == MACHO_TYPES::FAT_CIGAM) {
|
||||
this->build_fat();
|
||||
} else { // fit binary
|
||||
Binary *binary = BinaryParser(std::move(this->stream_)).get_binary();
|
||||
this->binaries_.push_back(binary);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
VLOG(VDEBUG) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,11 @@ Relocation::Relocation(uint64_t address, uint8_t type) :
|
||||
this->type_ = type;
|
||||
}
|
||||
|
||||
|
||||
//Relocation& Relocation::operator=(const Relocation& other) {
|
||||
// return *other.clone();
|
||||
//}
|
||||
|
||||
Relocation::Relocation(const Relocation& other) :
|
||||
LIEF::Relocation{other},
|
||||
symbol_{nullptr},
|
||||
|
@ -34,6 +34,11 @@ bool RelocationDyld::is_pc_relative(void) const {
|
||||
}
|
||||
|
||||
|
||||
Relocation* RelocationDyld::clone(void) const {
|
||||
return new RelocationDyld(*this);
|
||||
}
|
||||
|
||||
|
||||
RELOCATION_ORIGINS RelocationDyld::origin(void) const {
|
||||
return RELOCATION_ORIGINS::ORIGIN_DYLDINFO;
|
||||
}
|
||||
|
@ -25,8 +25,18 @@ namespace LIEF {
|
||||
namespace MachO {
|
||||
|
||||
|
||||
RelocationObject& RelocationObject::operator=(const RelocationObject&) = default;
|
||||
RelocationObject::RelocationObject(const RelocationObject&) = default;
|
||||
RelocationObject& RelocationObject::operator=(RelocationObject other) {
|
||||
this->swap(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RelocationObject::RelocationObject(const RelocationObject& other) :
|
||||
Relocation{other},
|
||||
is_pcrel_{other.is_pcrel_},
|
||||
is_scattered_{other.is_scattered_},
|
||||
value_{other.value_}
|
||||
{}
|
||||
|
||||
RelocationObject::~RelocationObject(void) = default;
|
||||
|
||||
RelocationObject::RelocationObject(void) :
|
||||
@ -59,6 +69,10 @@ RelocationObject::RelocationObject(const scattered_relocation_info *scattered_re
|
||||
}
|
||||
|
||||
|
||||
RelocationObject* RelocationObject::clone(void) const {
|
||||
return new RelocationObject(*this);
|
||||
}
|
||||
|
||||
|
||||
void RelocationObject::swap(RelocationObject& other) {
|
||||
Relocation::swap(other);
|
||||
|
@ -29,6 +29,10 @@ SegmentCommand::~SegmentCommand(void) {
|
||||
for (Relocation* reloc : this->relocations_) {
|
||||
delete reloc;
|
||||
}
|
||||
|
||||
for (Section* section : this->sections_) {
|
||||
delete section;
|
||||
}
|
||||
}
|
||||
|
||||
SegmentCommand::SegmentCommand(const segment_command_32 *segmentCmd) :
|
||||
@ -101,20 +105,12 @@ uint32_t SegmentCommand::flags(void) const {
|
||||
}
|
||||
|
||||
it_sections SegmentCommand::sections(void) {
|
||||
sections_t result;
|
||||
for (Section& s : this->sections_) {
|
||||
result.push_back(&s);
|
||||
}
|
||||
return it_sections{result};
|
||||
return this->sections_;
|
||||
}
|
||||
|
||||
|
||||
it_const_sections SegmentCommand::sections(void) const {
|
||||
sections_t result;
|
||||
for (const Section& s : this->sections_) {
|
||||
result.push_back(const_cast<Section*>(&s));
|
||||
}
|
||||
return it_const_sections{result};
|
||||
return this->sections_;
|
||||
}
|
||||
|
||||
|
||||
|
@ -638,7 +638,7 @@ void Parser::build_exports(void) {
|
||||
uint32_t name_offset = this->binary_->rva_to_offset(name_table[i]);
|
||||
std::string name = "";
|
||||
try {
|
||||
name = this->stream_->read_string(name_offset);
|
||||
name = this->stream_->get_string(name_offset);
|
||||
} catch (const LIEF::read_out_of_bound& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user