我打电话时似乎遇到了分段错误std::make_unique<uint8_t []>
。我很确定我知道分段错误发生在哪里,因为我使用了 gdb;但是,我不知道如何解决它。这是过滤掉不相关部分的源代码。
加载器.cc:
#include "loader.h"
... // Other code that would make this post unnecessarily long
Section::Section(Binary& bin, bfd *bfd_h, asection *as) : binary(bin) {
int bfd_flags = bfd_section_flags(as);
const char *secname;
Section::SectionType sectype;
sectype = Section::SectionType::NONE;
if (bfd_flags & SEC_CODE) {
sectype = Section::SectionType::CODE;
} else if (bfd_flags & SEC_DATA) {
sectype = Section::SectionType::DATA;
}
this->type = sectype;
this->vma = bfd_section_vma(as);
this->size = bfd_section_size(as);
secname = bfd_section_name(as);
this->name = std::string { secname != nullptr ? secname : "<unnamed>" };
this->bytes = std::make_unique<uint8_t []>(this->size); // SEGFAULT RIGHT HERE
if (!bfd_get_section_contents(bfd_h, as, this->bytes.get(), 0, this->size)) {
throw std::runtime_error("Failed to read section");
}
}
int Binary::load_binary(std::string& fname) {
int ret;
const bfd_arch_info_type *bfd_info;
std::unique_ptr<bfd, bfd_deleter> bfd_h;
try {
bfd_h = open_bfd(fname);
} catch (bfd_exception& be) {
std::cerr << be.fname() << ": " << be.what() << " (" << be.errormsg() << ")" << std::endl;
goto fail;
}
this->filename = std::string (fname);
this->entry = bfd_get_start_address(bfd_h.get());
this->type_str = std::string (bfd_h->xvec->name);
switch (bfd_h->xvec->flavour) {
case bfd_target_elf_flavour:
this->type = Binary::BinaryType::ELF;
break;
case bfd_target_coff_flavour:
this->type = Binary::BinaryType::PE;
break;
case bfd_target_unknown_flavour:
default:
std::cerr << "unsupported binary type ("
<< bfd_h->xvec->name << ")" << std::endl;
goto fail;
}
bfd_info = bfd_get_arch_info(bfd_h.get());
this->arch_str = std::string{bfd_info->printable_name};
switch (bfd_info->mach) {
case bfd_mach_i386_i386:
this->arch = Binary::BinaryArch::X86;
this->bits = 32;
break;
case bfd_mach_x86_64:
this->arch = Binary::BinaryArch::X86;
this->bits = 64;
break;
default:
std::cerr << "unsupported architecture (" << bfd_info->printable_name·
<< bfd_info->printable_name << ")" << std::endl;
goto fail;
}
this->load_symbols(bfd_h.get());
this->load_dynsym(bfd_h.get());
if (this->load_sections(bfd_h.get()) < 0) goto fail;
ret = 0;
goto success;
fail:
ret = -1;
success:
return ret;
}
... // Other code that would make this post unnecessarily long
装载机.h:
#include <memory>
#include <vector>
#include <bfd.h>
#include <inttype.h>
... // Other code that would make this post unnecessarily long
class Section {
public:
enum class SectionType { NONE, CODE, DATA };
Section(Binary& bin);
Section(Binary& bin, bfd *bfd_h, asection *as);
bool contains(uint64_t addr);
void info();
private:
friend class Binary;
Binary& binary;
std::string name;
SectionType type;
uint64_t vma;
uint64_t size;
std::unique_ptr<uint8_t []> bytes;
};
class Binary {
public:
enum class BinaryType { AUTO, ELF, PE };
enum class BinaryArch { NONE, X86 };
Binary();
Section* get_section_text();
int load_binary(std::string &fname);
void info();
private:
std::string filename;
BinaryType type;
std::string type_str;
BinaryArch arch;
std::string arch_str;
unsigned bits;
uint64_t entry;
std::vector<Section> sections;
std::vector<Symbol> symbols;
int load_symbols(bfd *bfd_h);
int load_dynsym(bfd *bfd_h);
int load_sections(bfd *bfd_h);
... // Other code that would make this post unnecessarily long
};
这是 gdb 返回的回溯:
(gdb) bt
#0 0x00007fffff335b9f in unlink_chunk (p=p@entry=0x802b7d0, av=0x7fffff46cb80 <main_arena>) at malloc.c:1453
#1 0x00007fffff338881 in _int_malloc (av=av@entry=0x7fffff46cb80 <main_arena>, bytes=bytes@entry=36) at malloc.c:4041 #2 0x00007fffff339a84 in __GI___libc_malloc (bytes=36) at malloc.c:3058
#3 0x00007fffff546045 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x0000000008003b94 in std::make_unique<unsigned char []> (__num=36) at /usr/include/c++/10/bits/unique_ptr.h:966
#5 Section::Section (this=0x7ffffffedd80, bin=..., bfd_h=0x801b730, as=0x801dbf8) at loader.cc:66
#6 0x0000000008003d53 in Binary::load_sections (this=this@entry=0x7ffffffedec0, bfd_h=bfd_h@entry=0x801b730)
at loader.cc:122
#7 0x000000000800487e in Binary::load_binary (this=0x7ffffffedec0, fname=...) at loader.cc:185
#8 0x0000000008002451 in main (argc=<optimized out>, argv=<optimized out>) at loader_demo.cc:13
此代码基于“实用二进制分析”中的代码,因此请原谅 goto。我也在使用 bfd 库。