我是从 main 函数开始分析的
tinyinst-converage.cpp 中的 面函数
int main(int argc, char **argv)
{
instrumentation = new LiteCov();
instrumentation->Init(argc, argv);
int target_opt_ind = 0;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--") == 0) {
target_opt_ind = i + 1;
break;
}
}
int target_argc = (target_opt_ind) ? argc - target_opt_ind : 0;
char **target_argv = (target_opt_ind) ? argv + target_opt_ind : NULL;
unsigned int pid = GetIntOption("-pid", argc, argv, 0);
persist = GetBinaryOption("-persist", argc, argv, false);
num_iterations = GetIntOption("-iterations", argc, argv, 1);
char *outfile = GetOption("-coverage_file", argc, argv);
if (!target_argc && !pid) {
printf("Usage:\n");
printf("%s <options> -- <target command line>\n", argv[0]);
printf("Or:\n");
printf("%s <options> -pid <pid to attach to>\n", argv[0]);
return 0;
}
Coverage coverage, newcoverage;
for (int i = 0; i < num_iterations; i++) {
RunTarget(target_argc, target_argv, pid, 0xFFFFFFFF);
Coverage newcoverage;
instrumentation->GetCoverage(newcoverage, true);
for (auto iter = newcoverage.begin(); iter != newcoverage.end(); iter++) {
printf("Found %zd new offsets in %s\n", iter->offsets.size(), iter->module_name.c_str());
}
instrumentation->IgnoreCoverage(newcoverage);
MergeCoverage(coverage, newcoverage);
}
if (outfile) WriteCoverage(coverage, outfile);
instrumentation->Kill();
return 0;
}
首先创建一个 ListCov 对象
然后进行初始化 instrumentation->Init(argc, argv)
2.1 这里先初始化 父类 TinyInst::Init
void LiteCov::Init(int argc, char **argv) {
TinyInst::Init(argc, argv);
coverage_type = COVTYPE_BB;
char *option = GetOption("-covtype", argc, argv);
if (option) {
if (strcmp(option, "bb") == 0)
coverage_type = COVTYPE_BB;
else if (strcmp(option, "edge") == 0)
coverage_type = COVTYPE_EDGE;
else
FATAL("Unknown coverage type");
}
compare_coverage = GetBinaryOption("-cmp_coverage", argc, argv, false);
for (auto iter = instrumented_modules.begin();
iter != instrumented_modules.end(); iter++) {
ModuleInfo *module = *iter;
module->client_data = new ModuleCovData();
}
}
2.1.1 其中父类 TinyInst 的初始化 主要就是我们的根据我们的命令行参数进行一个对应的 参数初始化
// initializes instrumentation from command line options
void TinyInst::Init(int argc, char **argv) {
// init the debugger first
Debugger::Init(argc, argv);
#ifdef ARM64
#else
assembler_ = new X86Assembler(*this);
#endif
assembler_->Init();
instrumentation_disabled = false;
instrument_modules_on_load = GetBinaryOption("-instrument_modules_on_load", argc, argv, false);
patch_return_addresses = GetBinaryOption("-patch_return_addresses", argc, argv, false);
instrument_cross_module_calls = GetBinaryOption("-instrument_cross_module_calls", argc, argv, true);
persist_instrumentation_data = GetBinaryOption("-persist_instrumentation_data", argc, argv, true);
trace_basic_blocks = GetBinaryOption("-trace_basic_blocks", argc, argv, false);
trace_module_entries = GetBinaryOption("-trace_module_entries", argc, argv, false);
sp_offset = GetIntOption("-stack_offset", argc, argv, 0);
list <char *> module_names;
GetOptionAll("-instrument_module", argc, argv, &module_names);
for (auto iter = module_names.begin(); iter != module_names.end(); iter++) {
ModuleInfo *new_module = new ModuleInfo();
new_module->module_name = *iter;
instrumented_modules.push_back(new_module);
}
char *option;
indirect_instrumentation_mode = II_AUTO;
option = GetOption("-indirect_instrumentation", argc, argv);
if (option) {
if (strcmp(option, "none") == 0)
indirect_instrumentation_mode = II_NONE;
else if (strcmp(option, "local") == 0)
indirect_instrumentation_mode = II_LOCAL;
else if (strcmp(option, "global") == 0)
indirect_instrumentation_mode = II_GLOBAL;
else if (strcmp(option, "auto") == 0)
indirect_instrumentation_mode = II_AUTO;
else
FATAL("Unknown indirect instrumentation mode");
}
generate_unwind = GetBinaryOption("-generate_unwind", argc, argv, false);
if (!generate_unwind) {
unwind_generator = new UnwindGenerator(*this);
} else {
#ifdef __APPLE__
unwind_generator = new UnwindGeneratorMacOS(*this);
#else
WARN("Unwind generator not implemented for the current platform");
unwind_generator = new UnwindGenerator(*this);
#endif
}
}
其中初始化 了 Debugger类 根据逻辑 这个类是最先被初始化的
然后其中还初始化了 每个模块,且把每个 模块加入到了 instrumented_modules 中。
2.1接着回到 LiteCov 的初始化。
这里初始化 覆盖的 类型 coverage_type 默认是基本快覆盖率。
coverage_type = COVTYPE_BB;
char *option = GetOption("-covtype", argc, argv);
if (option) {
if (strcmp(option, "bb") == 0)
coverage_type = COVTYPE_BB;
else if (strcmp(option, "edge") == 0)
coverage_type = COVTYPE_EDGE;
else
FATAL("Unknown coverage type");
}
然后每个 模块的 client_data 初始化为 ModuleCovData类 记录覆盖率相关的内容
然后获取对应的 参数 格式的定义和 其他参数的初始化
int target_opt_ind = 0;
for (int i = 1; i < argc; i++) {54
if (strcmp(argv[i], "--") == 0) {
target_opt_ind = i + 1;
break;
}
}
int target_argc = (target_opt_ind) ? argc - target_opt_ind : 0;
char **target_argv = (target_opt_ind) ? argv + target_opt_ind : NULL;
unsigned int pid = GetIntOption("-pid", argc, argv, 0);
persist = GetBinaryOption("-persist", argc, argv, false);
num_iterations = GetIntOption("-iterations", argc, argv, 1);
char *outfile = GetOption("-coverage_file", argc, argv);
if (!target_argc && !pid) {
printf("Usage:\n");
printf("%s <options> -- <target command line>\n", argv[0]);
printf("Or:\n");
printf("%s <options> -pid <pid to attach to>\n", argv[0]);
return 0;
}