这是一篇关于fcd编译器的源码分析,一些不重要的细节会略过
(流水账及咕咕咕预警
初步解析
下面是main函数的初步解析过程
1 | EnablePrettyStackTrace(); |
首先读取命令行参数并进行解析,然后初始化Passes
从解析到的命令行参数中拿到要反编译的文件的文件名
后面有
1 |
|
这里就不过多分析
1 | // step one: create annotated module from executable (or load it from .ll) |
这一部分就是从程序或者.ll文件中读取IR,因为我们主要重点在解析程序那里,所以就只分析那一块
1 | PrettyStackTraceFormat parsingIR("Parsing executable \"%s\"", inputFile.c_str()); |
从文件中读取内容,然后在mainObj.parseExecutable函数里面解析
跟进去可以看到是1
2
3
4
5
6ErrorOr<unique_ptr<Executable>> parseExecutable(MemoryBuffer& executableCode)
{
auto start = reinterpret_cast<const uint8_t*>(executableCode.getBufferStart());
auto end = reinterpret_cast<const uint8_t*>(executableCode.getBufferEnd());
return Executable::parse(start, end);
}
然后是1
2
3
4ErrorOr<unique_ptr<Executable>> Executable::parse(const uint8_t* begin, const uint8_t* end)
{
return executableFactory->parse(begin, end);
}
再到这里,大概是一个根据文件格式来判断用的解析器,这里好像只支持ELF1
2
3
4
5
6
7
8
9
10
11virtual llvm::ErrorOr<std::unique_ptr<Executable>> parse(const uint8_t* begin, const uint8_t* end) override
{
assert(end >= begin);
uintptr_t size = static_cast<uintptr_t>(end - begin);
if (size >= sizeof elf_magic && memcmp(begin, elf_magic, sizeof elf_magic) == 0)
{
return ElfExecutableFactory().parse(begin, end);
}
return make_error_code(ExecutableParsingError::Generic_UnknownFormat);
}
跟进去会发现根据ELF32位和64位不同,进行不同的解析1
2
3
4
5
6
7
8
9if (auto classByte = bounded_cast<uint8_t>(begin, end, EI_CLASS))
{
switch (*classByte)
{
case 1: return ElfExecutable<Elf32Types>::parse(begin, end);
case 2: return ElfExecutable<Elf64Types>::parse(begin, end);
default: break;
}
}
再往里面的parse就不分析了,看了下,大概就是解析各个结构体,识别出段和symbol之类的东西
进一步解析
回到main函数,上面初步解析完各种结构了,接下来是将机器码翻译为IR
1 | executable = move(executableOrError.get()); |
进入generateAnnotatedModule进行分析
1 | // Load headers here, since this is the earliest point where we have an executable and a module. |
读取headers等来添加到entrypoint
下面省略大部分东西,直接到关键的部分
1 | if (Function* fn = transl.createFunction(functionInfo.virtualAddress)) |
这里是创建一个function,在createFunction里面是具体的解析过程
大概就是 capstone反编译 -> 将反编译结果转换为IR
翻译IR那部分具体可以看code_generator.cpp的resolveIntrinsics函数,跟着进去分析就可以了,这里就不多说了