Move to master
Test: existing
Bug: 74013711
Change-Id: I99feee1db313644f5f7547a9670e3f5a8b3d2abc
diff --git a/dexter/Android.bp b/dexter/Android.bp
index db4654b..6d1e9f8 100644
--- a/dexter/Android.bp
+++ b/dexter/Android.bp
@@ -13,8 +13,6 @@
rtti: true,
host_supported: true,
device_supported: true,
- // TODO move includes so this isn't needed.
- include_dirs: ["tools/dexter"],
cflags: [
"-Wall",
"-Werror",
diff --git a/dexter/dexter.cc b/dexter/dexter.cc
index 75bb8d8..7943314 100644
--- a/dexter/dexter.cc
+++ b/dexter/dexter.cc
@@ -283,7 +283,7 @@
return false;
}
- SCOPE_EXIT {
+ SLICER_SCOPE_EXIT {
allocator.Free(new_image);
};
@@ -300,12 +300,12 @@
return false;
}
- SCOPE_EXIT {
+ SLICER_SCOPE_EXIT {
fclose(out_file);
};
// write the new image
- CHECK(fwrite(new_image, 1, new_image_size, out_file) == new_image_size);
+ SLICER_CHECK(fwrite(new_image, 1, new_image_size, out_file) == new_image_size);
}
return true;
@@ -324,7 +324,7 @@
return 1;
}
- SCOPE_EXIT {
+ SLICER_SCOPE_EXIT {
fclose(in_file);
};
@@ -337,7 +337,7 @@
// read input .dex file
fseek(in_file, 0, SEEK_SET);
- CHECK(fread(in_buff.get(), 1, in_size, in_file) == in_size);
+ SLICER_CHECK(fread(in_buff.get(), 1, in_size, in_file) == in_size);
// initialize the .dex reader
dex::Reader reader(in_buff.get(), in_size);
diff --git a/dexter/dexter_tests.py b/dexter/dexter_tests.py
index 16066f0..7a47c01 100644
--- a/dexter/dexter_tests.py
+++ b/dexter/dexter_tests.py
@@ -38,7 +38,7 @@
'exit_hooks.dex', 'medium.dex', 'try_catch.dex' ] },
'wrap_invoke' : { 'args' : '-d -x stress_wrap_invoke', 'input' : [
'hello.dex', 'hello_nodebug.dex', 'medium.dex' ] },
- 'mi' : { 'args' : '-d -x test_method_instrumenter', 'input' : ['entry_hooks.dex'] },
+ 'mi' : { 'args' : '-d -x test_method_instrumenter', 'input' : ['mi.dex'] },
'find_method' : { 'args' : '-x stress_find_method', 'input' : [
'hello.dex', 'entry_hooks.dex', 'medium.dex', 'large.dex', 'try_catch.dex' ] },
'verbose_cfg' : { 'args' : '-d --cfg=verbose', 'input' : ['*.dex'] },
diff --git a/dexter/dissasembler.cc b/dexter/dissasembler.cc
index e2edffe..1f44ee1 100644
--- a/dexter/dissasembler.cc
+++ b/dexter/dissasembler.cc
@@ -195,21 +195,21 @@
}
bool PrintCodeIrVisitor::Visit(lir::Type* type) {
- CHECK(type->index != dex::kNoIndex);
+ SLICER_CHECK(type->index != dex::kNoIndex);
auto ir_type = type->ir_type;
printf("%s", ir_type->Decl().c_str());
return true;
}
bool PrintCodeIrVisitor::Visit(lir::Field* field) {
- CHECK(field->index != dex::kNoIndex);
+ SLICER_CHECK(field->index != dex::kNoIndex);
auto ir_field = field->ir_field;
printf("%s.%s", ir_field->parent->Decl().c_str(), ir_field->name->c_str());
return true;
}
bool PrintCodeIrVisitor::Visit(lir::Method* method) {
- CHECK(method->index != dex::kNoIndex);
+ SLICER_CHECK(method->index != dex::kNoIndex);
auto ir_method = method->ir_method;
printf("%s.%s%s",
ir_method->parent->Decl().c_str(),
diff --git a/dexter/experimental.cc b/dexter/experimental.cc
index 5f9c14b..97a126a 100644
--- a/dexter/experimental.cc
+++ b/dexter/experimental.cc
@@ -236,22 +236,22 @@
switch (bytecode->opcode) {
case dex::OP_RETURN_VOID:
- CHECK(return_void);
+ SLICER_CHECK(return_void);
break;
case dex::OP_RETURN:
- CHECK(!return_void);
+ SLICER_CHECK(!return_void);
move_result_opcode = dex::OP_MOVE_RESULT;
reg = bytecode->CastOperand<lir::VReg>(0)->reg;
reg_count = 1;
break;
case dex::OP_RETURN_OBJECT:
- CHECK(!return_void);
+ SLICER_CHECK(!return_void);
move_result_opcode = dex::OP_MOVE_RESULT_OBJECT;
reg = bytecode->CastOperand<lir::VReg>(0)->reg;
reg_count = 1;
break;
case dex::OP_RETURN_WIDE:
- CHECK(!return_void);
+ SLICER_CHECK(!return_void);
move_result_opcode = dex::OP_MOVE_RESULT_WIDE;
reg = bytecode->CastOperand<lir::VRegPair>(0)->base_reg;
reg_count = 2;
@@ -296,13 +296,16 @@
mi.AddTransformation<slicer::ExitHook>(ir::MethodId("LTracer;", "onFooExit"));
mi.AddTransformation<slicer::DetourVirtualInvoke>(
ir::MethodId("LBase;", "foo", "(ILjava/lang/String;)I"),
- ir::MethodId("LTracer;", "wrapFoo")) ;
+ ir::MethodId("LTracer;", "wrapFoo"));
+ mi.AddTransformation<slicer::DetourInterfaceInvoke>(
+ ir::MethodId("LIBase;", "bar", "(Ljava/lang/String;)V"),
+ ir::MethodId("LTracer;", "wrapBar"));
auto method1 = ir::MethodId("LTarget;", "foo", "(ILjava/lang/String;)I");
- CHECK(mi.InstrumentMethod(method1));
+ SLICER_CHECK(mi.InstrumentMethod(method1));
auto method2 = ir::MethodId("LTarget;", "foo", "(I[[Ljava/lang/String;)Ljava/lang/Integer;");
- CHECK(mi.InstrumentMethod(method2));
+ SLICER_CHECK(mi.InstrumentMethod(method2));
}
// Stress scratch register allocation
@@ -318,11 +321,11 @@
// apply the transformations to every single method
for (auto& ir_method : dex_ir->encoded_methods) {
if (ir_method->code != nullptr) {
- CHECK(mi.InstrumentMethod(ir_method.get()));
- CHECK(t1->ScratchRegs().size() == 1);
- CHECK(t2->ScratchRegs().size() == 1);
- CHECK(t3->ScratchRegs().size() == 1);
- CHECK(t4->ScratchRegs().size() == 20);
+ SLICER_CHECK(mi.InstrumentMethod(ir_method.get()));
+ SLICER_CHECK(t1->ScratchRegs().size() == 1);
+ SLICER_CHECK(t2->ScratchRegs().size() == 1);
+ SLICER_CHECK(t3->ScratchRegs().size() == 1);
+ SLICER_CHECK(t4->ScratchRegs().size() == 20);
}
}
}
@@ -401,7 +404,7 @@
break;
}
}
- CHECK(trace_point != nullptr);
+ SLICER_CHECK(trace_point != nullptr);
// special case: don't separate 'move-result-<kind>' from the preceding invoke
auto opcode = static_cast<lir::Bytecode*>(trace_point)->opcode;
@@ -442,7 +445,7 @@
auto signature = decl->prototype->Signature();
auto class_descriptor = decl->parent->descriptor;
ir::MethodId method_id(class_descriptor->c_str(), decl->name->c_str(), signature.c_str());
- CHECK(builder.FindMethod(method_id) == ir_method.get());
+ SLICER_CHECK(builder.FindMethod(method_id) == ir_method.get());
++method_count;
}
printf("Everything looks fine, found %d methods.\n", method_count);
@@ -474,7 +477,7 @@
if (ir_method->code != nullptr) {
const int regs = ir_method->code->registers;
const int ins = ir_method->code->ins_count;
- CHECK(regs >= ins);
+ SLICER_CHECK(regs >= ins);
regs_histogram[regs]++;
param_histogram[ins]++;
extra_histogram[regs - ins]++;
diff --git a/slicer/Android.bp b/slicer/Android.bp
index 5a154f3..075b896 100644
--- a/slicer/Android.bp
+++ b/slicer/Android.bp
@@ -16,8 +16,7 @@
"tryblocks_encoder.cc",
"writer.cc",
],
- // TODO Move includes around so we don't need to have include_dirs in users.
- export_include_dirs: ["."],
+ export_include_dirs: ["export"],
device_supported: true,
shared_libs: ["libz"],
rtti: true,
diff --git a/slicer/bytecode_encoder.cc b/slicer/bytecode_encoder.cc
index c1659a9..f4caae4 100644
--- a/slicer/bytecode_encoder.cc
+++ b/slicer/bytecode_encoder.cc
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "bytecode_encoder.h"
-#include "common.h"
-#include "chronometer.h"
+#include "slicer/bytecode_encoder.h"
+#include "slicer/common.h"
+#include "slicer/chronometer.h"
#include <assert.h>
@@ -25,68 +25,68 @@
// Pack a 16bit word: 00AA
static dex::u2 Pack_Z_8(dex::u4 a) {
dex::u2 fa = (a & 0xff);
- CHECK(fa == a);
+ SLICER_CHECK(fa == a);
return fa;
}
// Pack a 16bit word: AABB
static dex::u2 Pack_8_8(dex::u4 a, dex::u4 b) {
dex::u2 fa = (a & 0xff);
- CHECK(fa == a);
+ SLICER_CHECK(fa == a);
dex::u2 fb = (b & 0xff);
- CHECK(fb == b);
+ SLICER_CHECK(fb == b);
return (fa << 8) | fb;
}
// Pack a 16bit word: ABCC
static dex::u2 Pack_4_4_8(dex::u4 a, dex::u4 b, dex::u4 c) {
dex::u2 fa = (a & 0xf);
- CHECK(fa == a);
+ SLICER_CHECK(fa == a);
dex::u2 fb = (b & 0xf);
- CHECK(fb == b);
+ SLICER_CHECK(fb == b);
dex::u2 fc = (c & 0xff);
- CHECK(fc == c);
+ SLICER_CHECK(fc == c);
return (fa << 12) | (fb << 8) | fc;
}
// Pack a 16bit word: ABCD
static dex::u2 Pack_4_4_4_4(dex::u4 a, dex::u4 b, dex::u4 c, dex::u4 d) {
dex::u2 fa = (a & 0xf);
- CHECK(fa == a);
+ SLICER_CHECK(fa == a);
dex::u2 fb = (b & 0xf);
- CHECK(fb == b);
+ SLICER_CHECK(fb == b);
dex::u2 fc = (c & 0xf);
- CHECK(fc == c);
+ SLICER_CHECK(fc == c);
dex::u2 fd = (d & 0xf);
- CHECK(fd == d);
+ SLICER_CHECK(fd == d);
return (fa << 12) | (fb << 8) | (fc << 4) | fd;
}
// Pack a 16bit word: AAAA
static dex::u2 Pack_16(dex::u4 a) {
dex::u2 fa = (a & 0xffff);
- CHECK(fa == a);
+ SLICER_CHECK(fa == a);
return fa;
}
// Trim a 4bit signed integer, making sure we're not discarding significant bits
static dex::u4 Trim_S0(dex::u4 value) {
dex::u4 trim = value & 0xf;
- CHECK(dex::u4(dex::s4(trim << 28) >> 28) == value);
+ SLICER_CHECK(dex::u4(dex::s4(trim << 28) >> 28) == value);
return trim;
}
// Trim a 8bit signed integer, making sure we're not discarding significant bits
static dex::u4 Trim_S1(dex::u4 value) {
dex::u4 trim = value & 0xff;
- CHECK(dex::u4(dex::s4(trim << 24) >> 24) == value);
+ SLICER_CHECK(dex::u4(dex::s4(trim << 24) >> 24) == value);
return trim;
}
// Trim a 16bit signed integer, making sure we're not discarding significant bits
static dex::u4 Trim_S2(dex::u4 value) {
dex::u4 trim = value & 0xffff;
- CHECK(dex::u4(dex::s4(trim << 16) >> 16) == value);
+ SLICER_CHECK(dex::u4(dex::s4(trim << 16) >> 16) == value);
return trim;
}
@@ -139,13 +139,13 @@
switch (format) {
case dex::kFmt10x: // op
{
- CHECK(bytecode->operands.size() == 0);
+ SLICER_CHECK(bytecode->operands.size() == 0);
bytecode_.Push<dex::u2>(Pack_Z_8(opcode));
} break;
case dex::kFmt12x: // op vA, vB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
bytecode_.Push<dex::u2>(Pack_4_4_8(vB, vA, opcode));
@@ -153,7 +153,7 @@
case dex::kFmt22x: // op vAA, vBBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
@@ -162,7 +162,7 @@
case dex::kFmt32x: // op vAAAA, vBBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
bytecode_.Push<dex::u2>(Pack_Z_8(opcode));
@@ -172,7 +172,7 @@
case dex::kFmt11n: // op vA, #+B
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 B = Trim_S0(bytecode->CastOperand<Const32>(1)->u.u4_value);
bytecode_.Push<dex::u2>(Pack_4_4_8(B, vA, opcode));
@@ -180,7 +180,7 @@
case dex::kFmt21s: // op vAA, #+BBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 B = Trim_S2(bytecode->CastOperand<Const32>(1)->u.u4_value);
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
@@ -189,14 +189,14 @@
case dex::kFmt11x: // op vAA
{
- CHECK(bytecode->operands.size() == 1);
+ SLICER_CHECK(bytecode->operands.size() == 1);
dex::u4 vA = GetRegA(bytecode, 0);
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
} break;
case dex::kFmt31i: // op vAA, #+BBBBBBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 B = bytecode->CastOperand<Const32>(1)->u.u4_value;
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
@@ -206,14 +206,14 @@
case dex::kFmt20t: // op +AAAA
{
- CHECK(bytecode->operands.size() == 1);
+ SLICER_CHECK(bytecode->operands.size() == 1);
auto label = bytecode->CastOperand<CodeLocation>(0)->label;
dex::u4 A = 0;
if (label->offset != kInvalidOffset) {
assert(label->offset <= offset_);
A = label->offset - offset_;
- CHECK(A != 0);
- CHECK((A >> 16) == 0xffff); // TODO: out of range!
+ SLICER_CHECK(A != 0);
+ SLICER_CHECK((A >> 16) == 0xffff); // TODO: out of range!
} else {
fixups_.push_back(LabelFixup(offset_, label, true));
}
@@ -223,7 +223,7 @@
case dex::kFmt30t: // op +AAAAAAAA
{
- CHECK(bytecode->operands.size() == 1);
+ SLICER_CHECK(bytecode->operands.size() == 1);
auto label = bytecode->CastOperand<CodeLocation>(0)->label;
dex::u4 A = 0;
if (label->offset != kInvalidOffset) {
@@ -240,15 +240,15 @@
case dex::kFmt21t: // op vAA, +BBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
auto label = bytecode->CastOperand<CodeLocation>(1)->label;
dex::u4 B = 0;
if (label->offset != kInvalidOffset) {
assert(label->offset <= offset_);
B = label->offset - offset_;
- CHECK(B != 0);
- CHECK((B >> 16) == 0xffff); // TODO: out of range!
+ SLICER_CHECK(B != 0);
+ SLICER_CHECK((B >> 16) == 0xffff); // TODO: out of range!
} else {
fixups_.push_back(LabelFixup(offset_, label, true));
}
@@ -258,7 +258,7 @@
case dex::kFmt22t: // op vA, vB, +CCCC
{
- CHECK(bytecode->operands.size() == 3);
+ SLICER_CHECK(bytecode->operands.size() == 3);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
auto label = bytecode->CastOperand<CodeLocation>(2)->label;
@@ -266,8 +266,8 @@
if (label->offset != kInvalidOffset) {
assert(label->offset <= offset_);
C = label->offset - offset_;
- CHECK(C != 0);
- CHECK((C >> 16) == 0xffff); // TODO: out of range!
+ SLICER_CHECK(C != 0);
+ SLICER_CHECK((C >> 16) == 0xffff); // TODO: out of range!
} else {
fixups_.push_back(LabelFixup(offset_, label, true));
}
@@ -277,14 +277,14 @@
case dex::kFmt31t: // op vAA, +BBBBBBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
auto label = bytecode->CastOperand<CodeLocation>(1)->label;
dex::u4 B = 0;
if (label->offset != kInvalidOffset) {
assert(label->offset <= offset_);
B = label->offset - offset_;
- CHECK(B != 0);
+ SLICER_CHECK(B != 0);
} else {
fixups_.push_back(LabelFixup(offset_, label, false));
}
@@ -295,7 +295,7 @@
case dex::kFmt23x: // op vAA, vBB, vCC
{
- CHECK(bytecode->operands.size() == 3);
+ SLICER_CHECK(bytecode->operands.size() == 3);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
dex::u4 vC = GetRegC(bytecode, 2);
@@ -305,7 +305,7 @@
case dex::kFmt22b: // op vAA, vBB, #+CC
{
- CHECK(bytecode->operands.size() == 3);
+ SLICER_CHECK(bytecode->operands.size() == 3);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
dex::u4 C = Trim_S1(bytecode->CastOperand<Const32>(2)->u.u4_value);
@@ -315,7 +315,7 @@
case dex::kFmt22s: // op vA, vB, #+CCCC
{
- CHECK(bytecode->operands.size() == 3);
+ SLICER_CHECK(bytecode->operands.size() == 3);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
dex::u4 C = Trim_S2(bytecode->CastOperand<Const32>(2)->u.u4_value);
@@ -325,7 +325,7 @@
case dex::kFmt22c: // op vA, vB, thing@CCCC
{
- CHECK(bytecode->operands.size() == 3);
+ SLICER_CHECK(bytecode->operands.size() == 3);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 vB = GetRegB(bytecode, 1);
dex::u4 C = bytecode->CastOperand<IndexedOperand>(2)->index;
@@ -335,7 +335,7 @@
case dex::kFmt21c: // op vAA, thing@BBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
@@ -344,7 +344,7 @@
case dex::kFmt31c: // op vAA, string@BBBBBBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
@@ -354,7 +354,7 @@
case dex::kFmt35c: // op {vC,vD,vE,vF,vG}, thing@BBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
const auto& regs = bytecode->CastOperand<VRegList>(0)->registers;
dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
dex::u4 A = regs.size();
@@ -375,7 +375,7 @@
case dex::kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
auto vreg_range = bytecode->CastOperand<VRegRange>(0);
dex::u4 A = vreg_range->count;
dex::u4 B = bytecode->CastOperand<IndexedOperand>(1)->index;
@@ -392,7 +392,7 @@
case dex::kFmt51l: // op vAA, #+BBBBBBBBBBBBBBBB
{
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
dex::u4 vA = GetRegA(bytecode, 0);
dex::u8 B = bytecode->CastOperand<Const64>(1)->u.u8_value;
bytecode_.Push<dex::u2>(Pack_8_8(vA, opcode));
@@ -403,7 +403,7 @@
} break;
case dex::kFmt21h: // op vAA, #+BBBB0000[00000000]
- CHECK(bytecode->operands.size() == 2);
+ SLICER_CHECK(bytecode->operands.size() == 2);
switch (opcode) {
case dex::OP_CONST_HIGH16: {
dex::u4 vA = GetRegA(bytecode, 0);
@@ -420,26 +420,26 @@
} break;
default:
- FATAL("Unexpected fmt21h opcode: 0x%02x", opcode);
+ SLICER_FATAL("Unexpected fmt21h opcode: 0x%02x", opcode);
}
break;
default:
- FATAL("Unexpected format: 0x%02x", format);
+ SLICER_FATAL("Unexpected format: 0x%02x", format);
}
- CHECK(bytecode_.size() - buff_offset == 2 * GetWidthFromOpcode(opcode));
+ SLICER_CHECK(bytecode_.size() - buff_offset == 2 * GetWidthFromOpcode(opcode));
offset_ += GetWidthFromOpcode(opcode);
return true;
}
bool BytecodeEncoder::Visit(PackedSwitchPayload* packed_switch) {
- CHECK(offset_ % 2 == 0);
+ SLICER_CHECK(offset_ % 2 == 0);
// keep track of the switches
packed_switch->offset = offset_;
auto& instr = packed_switches_[offset_];
- CHECK(instr == nullptr);
+ SLICER_CHECK(instr == nullptr);
instr = packed_switch;
// we're going to fix up the offsets in a later pass
@@ -458,12 +458,12 @@
}
bool BytecodeEncoder::Visit(SparseSwitchPayload* sparse_switch) {
- CHECK(offset_ % 2 == 0);
+ SLICER_CHECK(offset_ % 2 == 0);
// keep track of the switches
sparse_switch->offset = offset_;
auto& instr = sparse_switches_[offset_];
- CHECK(instr == nullptr);
+ SLICER_CHECK(instr == nullptr);
instr = sparse_switch;
// we're going to fix up the offsets in a later pass
@@ -482,7 +482,7 @@
}
bool BytecodeEncoder::Visit(ArrayData* array_data) {
- CHECK(offset_ % 2 == 0);
+ SLICER_CHECK(offset_ % 2 == 0);
array_data->offset = offset_;
auto orig_size = bytecode_.size();
@@ -539,20 +539,20 @@
FixupSparseSwitch(offset, offset + dex::s4(dex_instr.vB));
}
auto isize = dex::GetWidthFromBytecode(ptr);
- CHECK(isize > 0);
+ SLICER_CHECK(isize > 0);
ptr += isize;
}
- CHECK(ptr == end);
+ SLICER_CHECK(ptr == end);
}
void BytecodeEncoder::FixupPackedSwitch(dex::u4 base_offset,
dex::u4 payload_offset) {
auto instr = packed_switches_[payload_offset];
- CHECK(instr != nullptr);
+ SLICER_CHECK(instr != nullptr);
auto payload = bytecode_.ptr<dex::PackedSwitchPayload>(payload_offset * 2);
- CHECK(payload->ident == dex::kPackedSwitchSignature);
- CHECK(reinterpret_cast<dex::u1*>(payload->targets + payload->size) <=
+ SLICER_CHECK(payload->ident == dex::kPackedSwitchSignature);
+ SLICER_CHECK(reinterpret_cast<dex::u1*>(payload->targets + payload->size) <=
bytecode_.data() + bytecode_.size());
for (int i = 0; i < payload->size; ++i) {
@@ -565,13 +565,13 @@
void BytecodeEncoder::FixupSparseSwitch(dex::u4 base_offset,
dex::u4 payload_offset) {
auto instr = sparse_switches_[payload_offset];
- CHECK(instr != nullptr);
+ SLICER_CHECK(instr != nullptr);
auto payload = bytecode_.ptr<dex::SparseSwitchPayload>(payload_offset * 2);
- CHECK(payload->ident == dex::kSparseSwitchSignature);
+ SLICER_CHECK(payload->ident == dex::kSparseSwitchSignature);
dex::s4* const targets = payload->data + payload->size;
- CHECK(reinterpret_cast<dex::u1*>(targets + payload->size) <=
+ SLICER_CHECK(reinterpret_cast<dex::u1*>(targets + payload->size) <=
bytecode_.data() + bytecode_.size());
for (int i = 0; i < payload->size; ++i) {
@@ -587,7 +587,7 @@
assert(label_offset != kInvalidOffset);
assert(label_offset > fixup.offset);
dex::u4 rel_offset = label_offset - fixup.offset;
- CHECK(rel_offset != 0);
+ SLICER_CHECK(rel_offset != 0);
dex::u2* instr = bytecode_.ptr<dex::u2>(fixup.offset * 2);
if (fixup.short_fixup) {
// TODO: explicit out-of-range check
@@ -603,9 +603,9 @@
}
void BytecodeEncoder::Encode(ir::Code* ir_code, std::shared_ptr<ir::DexFile> dex_ir) {
- CHECK(bytecode_.empty());
- CHECK(offset_ == 0);
- CHECK(outs_count_ == 0);
+ SLICER_CHECK(bytecode_.empty());
+ SLICER_CHECK(offset_ == 0);
+ SLICER_CHECK(outs_count_ == 0);
packed_switches_.clear();
sparse_switches_.clear();
diff --git a/slicer/code_ir.cc b/slicer/code_ir.cc
index 7a880c8..3434ca6 100644
--- a/slicer/code_ir.cc
+++ b/slicer/code_ir.cc
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#include "code_ir.h"
-#include "common.h"
-#include "dex_bytecode.h"
-#include "dex_format.h"
-#include "dex_ir.h"
-#include "dex_leb128.h"
-#include "bytecode_encoder.h"
-#include "debuginfo_encoder.h"
-#include "tryblocks_encoder.h"
+#include "slicer/common.h"
+#include "slicer/code_ir.h"
+#include "slicer/dex_bytecode.h"
+#include "slicer/dex_format.h"
+#include "slicer/dex_ir.h"
+#include "slicer/dex_leb128.h"
+#include "slicer/bytecode_encoder.h"
+#include "slicer/debuginfo_encoder.h"
+#include "slicer/tryblocks_encoder.h"
#include <assert.h>
#include <string.h>
@@ -35,7 +35,7 @@
void CodeIr::Assemble() {
auto ir_code = ir_method->code;
- CHECK(ir_code != nullptr);
+ SLICER_CHECK(ir_code != nullptr);
// new .dex bytecode
//
@@ -78,7 +78,7 @@
// type
dex::u4 type_index = dex::ReadULeb128(&ptr);
handler.ir_type = dex_ir->types_map[type_index];
- CHECK(handler.ir_type != nullptr);
+ SLICER_CHECK(handler.ir_type != nullptr);
// address
dex::u4 address = dex::ReadULeb128(&ptr);
@@ -98,7 +98,7 @@
}
// we should have at least one handler
- CHECK(!try_block_end->handlers.empty() ||
+ SLICER_CHECK(!try_block_end->handlers.empty() ||
try_block_end->catch_all != nullptr);
try_begins_.push_back(try_block_begin);
@@ -156,7 +156,7 @@
case dex::DBG_ADVANCE_LINE:
// line_diff
line += dex::ReadSLeb128(&ptr);
- WEAK_CHECK(line > 0);
+ SLICER_WEAK_CHECK(line > 0);
break;
case dex::DBG_START_LOCAL: {
@@ -223,7 +223,7 @@
int adjusted_opcode = opcode - dex::DBG_FIRST_SPECIAL;
line += dex::DBG_LINE_BASE + (adjusted_opcode % dex::DBG_LINE_RANGE);
address += (adjusted_opcode / dex::DBG_LINE_RANGE);
- WEAK_CHECK(line > 0);
+ SLICER_WEAK_CHECK(line > 0);
annotation = Alloc<DbgInfoAnnotation>(dex::DBG_ADVANCE_LINE);
annotation->operands.push_back(Alloc<LineNumber>(line));
} break;
@@ -243,7 +243,7 @@
while (ptr < end) {
auto isize = dex::GetWidthFromBytecode(ptr);
- CHECK(isize > 0);
+ SLICER_CHECK(isize > 0);
dex::u4 offset = ptr - begin;
@@ -270,7 +270,7 @@
instructions.push_back(instr);
ptr += isize;
}
- CHECK(ptr == end);
+ SLICER_CHECK(ptr == end);
}
void CodeIr::FixupSwitches() {
@@ -294,7 +294,7 @@
static void MergeInstructions(I_LIST& instructions, const E_LIST& extra) {
// the extra instructins must be sorted by offset
- CHECK(std::is_sorted(extra.begin(), extra.end(),
+ SLICER_CHECK(std::is_sorted(extra.begin(), extra.end(),
[](const Instruction* a, const Instruction* b) {
return a->offset < b->offset;
}));
@@ -360,19 +360,19 @@
// actual decoding is delayed to FixupPackedSwitch()
// (since the label offsets are relative to the referring
// instruction, not the switch data)
- CHECK(offset % 2 == 0);
+ SLICER_CHECK(offset % 2 == 0);
auto& instr = packed_switches_[offset].instr;
- CHECK(instr == nullptr);
+ SLICER_CHECK(instr == nullptr);
instr = Alloc<PackedSwitchPayload>();
return instr;
}
void CodeIr::FixupPackedSwitch(PackedSwitchPayload* instr, dex::u4 base_offset,
const dex::u2* ptr) {
- CHECK(instr->targets.empty());
+ SLICER_CHECK(instr->targets.empty());
auto dex_packed_switch = reinterpret_cast<const dex::PackedSwitchPayload*>(ptr);
- CHECK(dex_packed_switch->ident == dex::kPackedSwitchSignature);
+ SLICER_CHECK(dex_packed_switch->ident == dex::kPackedSwitchSignature);
instr->first_key = dex_packed_switch->first_key;
for (dex::u2 i = 0; i < dex_packed_switch->size; ++i) {
@@ -386,19 +386,19 @@
// actual decoding is delayed to FixupSparseSwitch()
// (since the label offsets are relative to the referring
// instruction, not the switch data)
- CHECK(offset % 2 == 0);
+ SLICER_CHECK(offset % 2 == 0);
auto& instr = sparse_switches_[offset].instr;
- CHECK(instr == nullptr);
+ SLICER_CHECK(instr == nullptr);
instr = Alloc<SparseSwitchPayload>();
return instr;
}
void CodeIr::FixupSparseSwitch(SparseSwitchPayload* instr, dex::u4 base_offset,
const dex::u2* ptr) {
- CHECK(instr->switch_cases.empty());
+ SLICER_CHECK(instr->switch_cases.empty());
auto dex_sparse_switch = reinterpret_cast<const dex::SparseSwitchPayload*>(ptr);
- CHECK(dex_sparse_switch->ident == dex::kSparseSwitchSignature);
+ SLICER_CHECK(dex_sparse_switch->ident == dex::kSparseSwitchSignature);
auto& data = dex_sparse_switch->data;
auto& size = dex_sparse_switch->size;
@@ -413,8 +413,8 @@
ArrayData* CodeIr::DecodeArrayData(const dex::u2* ptr, dex::u4 offset) {
auto dex_array_data = reinterpret_cast<const dex::ArrayData*>(ptr);
- CHECK(dex_array_data->ident == dex::kArrayDataSignature);
- CHECK(offset % 2 == 0);
+ SLICER_CHECK(dex_array_data->ident == dex::kArrayDataSignature);
+ SLICER_CHECK(offset % 2 == 0);
auto instr = Alloc<ArrayData>();
instr->data = slicer::MemView(ptr, dex::GetWidthFromBytecode(ptr) * 2);
@@ -497,12 +497,12 @@
if (dex_instr.opcode == dex::OP_PACKED_SWITCH) {
label->aligned = true;
dex::u4& base_offset = packed_switches_[targetOffset].base_offset;
- CHECK(base_offset == kInvalidOffset);
+ SLICER_CHECK(base_offset == kInvalidOffset);
base_offset = offset;
} else if (dex_instr.opcode == dex::OP_SPARSE_SWITCH) {
label->aligned = true;
dex::u4& base_offset = sparse_switches_[targetOffset].base_offset;
- CHECK(base_offset == kInvalidOffset);
+ SLICER_CHECK(base_offset == kInvalidOffset);
base_offset = offset;
} else if (dex_instr.opcode == dex::OP_FILL_ARRAY_DATA) {
label->aligned = true;
@@ -544,7 +544,7 @@
case dex::kFmt35c: // op {vC,vD,vE,vF,vG}, thing@BBBB
{
- CHECK(dex_instr.vA <= 5);
+ SLICER_CHECK(dex_instr.vA <= 5);
auto vreg_list = Alloc<VRegList>();
for (dex::u4 i = 0; i < dex_instr.vA; ++i) {
vreg_list->registers.push_back(dex_instr.arg[i]);
@@ -573,7 +573,7 @@
break;
default:
- FATAL("Unexpected opcode 0x%02x", dex_instr.opcode);
+ SLICER_FATAL("Unexpected opcode 0x%02x", dex_instr.opcode);
}
break;
@@ -583,7 +583,7 @@
break;
default:
- FATAL("Unexpected bytecode format (opcode 0x%02x)", dex_instr.opcode);
+ SLICER_FATAL("Unexpected bytecode format (opcode 0x%02x)", dex_instr.opcode);
}
return instr;
@@ -593,7 +593,7 @@
// (index must be valid != kNoIndex)
IndexedOperand* CodeIr::GetIndexedOperand(dex::InstructionIndexType index_type,
dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
switch (index_type) {
case dex::kIndexStringRef:
return Alloc<String>(dex_ir->strings_map[index], index);
@@ -608,7 +608,7 @@
return Alloc<Method>(dex_ir->methods_map[index], index);
default:
- FATAL("Unexpected index type 0x%02x", index_type);
+ SLICER_FATAL("Unexpected index type 0x%02x", index_type);
}
}
diff --git a/slicer/common.cc b/slicer/common.cc
index 994d945..c504390 100644
--- a/slicer/common.cc
+++ b/slicer/common.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "common.h"
+#include "slicer/common.h"
#include <stdio.h>
#include <stdlib.h>
@@ -24,23 +24,23 @@
namespace slicer {
-// Helper for the default CHECK() policy
+// Helper for the default SLICER_CHECK() policy
void _checkFailed(const char* expr, int line, const char* file) {
- printf("\nCHECK failed [%s] at %s:%d\n\n", expr, file, line);
+ printf("\nSLICER_CHECK failed [%s] at %s:%d\n\n", expr, file, line);
abort();
}
// keep track of the failures we already saw to avoid spamming with duplicates
thread_local std::set<std::pair<int, const char*>> weak_failures;
-// Helper for the default WEAK_CHECK() policy
+// Helper for the default SLICER_WEAK_CHECK() policy
//
// TODO: implement a modal switch (abort/continue)
//
void _weakCheckFailed(const char* expr, int line, const char* file) {
auto failure_id = std::make_pair(line, file);
if (weak_failures.find(failure_id) == weak_failures.end()) {
- printf("\nWEAK_CHECK failed [%s] at %s:%d\n\n", expr, file, line);
+ printf("\nSLICER_WEAK_CHECK failed [%s] at %s:%d\n\n", expr, file, line);
weak_failures.insert(failure_id);
}
}
diff --git a/slicer/control_flow_graph.cc b/slicer/control_flow_graph.cc
index 7da7413..dc7b386 100644
--- a/slicer/control_flow_graph.cc
+++ b/slicer/control_flow_graph.cc
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "control_flow_graph.h"
-#include "chronometer.h"
+#include "slicer/control_flow_graph.h"
+#include "slicer/chronometer.h"
namespace lir {
@@ -30,8 +30,8 @@
// have labels, annotations, directives, etc. For example it's possible to have
// debug annotations (.line, .endlocal, ...) after the last bytecode.
//
- WEAK_CHECK(state_ == State::Outside);
- CHECK(state_ != State::BlockBody);
+ SLICER_WEAK_CHECK(state_ == State::Outside);
+ SLICER_CHECK(state_ != State::BlockBody);
current_block_.region = {};
state_ = State::Outside;
return std::move(basic_blocks_);
diff --git a/slicer/debuginfo_encoder.cc b/slicer/debuginfo_encoder.cc
index cbd9ed8..c99c65d 100644
--- a/slicer/debuginfo_encoder.cc
+++ b/slicer/debuginfo_encoder.cc
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "debuginfo_encoder.h"
-#include "chronometer.h"
-#include "common.h"
+#include "slicer/common.h"
+#include "slicer/debuginfo_encoder.h"
+#include "slicer/chronometer.h"
#include <assert.h>
@@ -31,7 +31,7 @@
bool DebugInfoEncoder::Visit(DbgInfoAnnotation* dbg_annotation) {
// keep the address in sync
if (last_address_ != dbg_annotation->offset) {
- CHECK(dbg_annotation->offset > last_address_);
+ SLICER_CHECK(dbg_annotation->offset > last_address_);
dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_PC);
dbginfo_.PushULeb128(dbg_annotation->offset - last_address_);
last_address_ = dbg_annotation->offset;
@@ -49,10 +49,10 @@
// it's not perfectly clear from the .dex specification
// if initial line == 0 is valid, but a number of existing
// .dex files do this so we have to support it
- CHECK(line >= 0);
+ SLICER_CHECK(line >= 0);
line_start_ = line;
} else {
- WEAK_CHECK(line > 0);
+ SLICER_WEAK_CHECK(line > 0);
int delta = line - last_line_;
int adj_opcode = delta - dex::DBG_LINE_BASE;
// out of range for special opcode?
@@ -112,7 +112,7 @@
} break;
default:
- FATAL("Unexpected debug info opcode: 0x%02x", dbg_annotation->dbg_opcode);
+ SLICER_FATAL("Unexpected debug info opcode: 0x%02x", dbg_annotation->dbg_opcode);
}
return true;
@@ -121,12 +121,12 @@
void DebugInfoEncoder::Encode(ir::EncodedMethod* ir_method, std::shared_ptr<ir::DexFile> dex_ir) {
auto ir_debug_info = ir_method->code->debug_info;
- CHECK(dbginfo_.empty());
- CHECK(param_names_ == nullptr);
- CHECK(line_start_ == 0);
- CHECK(last_line_ == 0);
- CHECK(last_address_ == 0);
- CHECK(source_file_ == nullptr);
+ SLICER_CHECK(dbginfo_.empty());
+ SLICER_CHECK(param_names_ == nullptr);
+ SLICER_CHECK(line_start_ == 0);
+ SLICER_CHECK(last_line_ == 0);
+ SLICER_CHECK(last_address_ == 0);
+ SLICER_CHECK(source_file_ == nullptr);
// generate new debug info
source_file_ = ir_method->decl->parent->class_def->source_file;
@@ -136,7 +136,7 @@
dbginfo_.Push<dex::u1>(dex::DBG_END_SEQUENCE);
dbginfo_.Seal(1);
- CHECK(!dbginfo_.empty());
+ SLICER_CHECK(!dbginfo_.empty());
// update ir::DebugInfo
ir_debug_info->line_start = line_start_;
diff --git a/slicer/dex_bytecode.cc b/slicer/dex_bytecode.cc
index 2449425..7a97f28 100644
--- a/slicer/dex_bytecode.cc
+++ b/slicer/dex_bytecode.cc
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "dex_bytecode.h"
-#include "common.h"
+#include "slicer/dex_bytecode.h"
+#include "slicer/common.h"
#include <assert.h>
#include <array>
@@ -24,7 +24,7 @@
Opcode OpcodeFromBytecode(u2 bytecode) {
Opcode opcode = Opcode(bytecode & 0xff);
- CHECK(opcode != OP_UNUSED_FF);
+ SLICER_CHECK(opcode != OP_UNUSED_FF);
return opcode;
}
@@ -194,7 +194,7 @@
/* CONST_CLASS */ kInstrCanContinue|kInstrCanThrow,
/* MONITOR_ENTER */ kInstrCanContinue|kInstrCanThrow,
/* MONITOR_EXIT */ kInstrCanContinue|kInstrCanThrow,
- /* CHECK_CAST */ kInstrCanContinue|kInstrCanThrow,
+ /* SLICER_CHECK_CAST */ kInstrCanContinue|kInstrCanThrow,
/* INSTANCE_OF */ kInstrCanContinue|kInstrCanThrow,
/* ARRAY_LENGTH */ kInstrCanContinue|kInstrCanThrow,
/* NEW_INSTANCE */ kInstrCanContinue|kInstrCanThrow,
@@ -849,7 +849,7 @@
switch (dec.vA) {
case 5:
// A fifth arg is verboten for inline invokes
- CHECK(format != kFmt35mi);
+ SLICER_CHECK(format != kFmt35mi);
// Per note at the top of this format decoder, the
// fifth argument comes from the A field in the
@@ -872,7 +872,7 @@
// Valid, but no need to do anything
break;
default:
- CHECK(!"Invalid arg count in 35c/35ms/35mi");
+ SLICER_CHECK(!"Invalid arg count in 35c/35ms/35mi");
break;
}
} break;
@@ -888,7 +888,7 @@
dec.vB_wide = FetchU8(bytecode + 1);
break;
default:
- FATAL("Can't decode unexpected format 0x%02x", format);
+ SLICER_FATAL("Can't decode unexpected format 0x%02x", format);
}
return dec;
diff --git a/slicer/dex_format.cc b/slicer/dex_format.cc
index f2abb3c..7dbc762 100644
--- a/slicer/dex_format.cc
+++ b/slicer/dex_format.cc
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "dex_format.h"
-#include "common.h"
+#include "slicer/dex_format.h"
+#include "slicer/common.h"
#include <zlib.h>
#include <sstream>
@@ -46,7 +46,7 @@
case 'V': return "void";
case 'Z': return "boolean";
}
- CHECK(!"unexpected type");
+ SLICER_CHECK(!"unexpected type");
return nullptr;
}
@@ -64,14 +64,14 @@
if (*descriptor == 'L') {
for (++descriptor; *descriptor != ';'; ++descriptor) {
- CHECK(*descriptor != '\0');
+ SLICER_CHECK(*descriptor != '\0');
ss << (*descriptor == '/' ? '.' : *descriptor);
}
} else {
ss << PrimitiveTypeName(*descriptor);
}
- CHECK(descriptor[1] == '\0');
+ SLICER_CHECK(descriptor[1] == '\0');
// add the array brackets
for (int i = 0; i < array_dimensions; ++i) {
@@ -95,11 +95,11 @@
if (short_descriptor == 'L') {
// skip the full class name
for(; *descriptor && *descriptor != ';'; ++descriptor);
- CHECK(*descriptor == ';');
+ SLICER_CHECK(*descriptor == ';');
}
- CHECK(descriptor[1] == '\0');
- CHECK(short_descriptor == 'L' || PrimitiveTypeName(short_descriptor) != nullptr);
+ SLICER_CHECK(descriptor[1] == '\0');
+ SLICER_CHECK(short_descriptor == 'L' || PrimitiveTypeName(short_descriptor) != nullptr);
return array_dimensions > 0 ? 'L' : short_descriptor;
}
diff --git a/slicer/dex_ir.cc b/slicer/dex_ir.cc
index 9c16139..0ab1726 100644
--- a/slicer/dex_ir.cc
+++ b/slicer/dex_ir.cc
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "dex_ir.h"
-#include "chronometer.h"
-#include "dex_utf8.h"
-#include "dex_format.h"
+#include "slicer/dex_ir.h"
+#include "slicer/chronometer.h"
+#include "slicer/dex_utf8.h"
+#include "slicer/dex_format.h"
#include <algorithm>
#include <cstdint>
@@ -140,7 +140,7 @@
}
}
- CHECK(*nextIndex < classes.size());
+ SLICER_CHECK(*nextIndex < classes.size());
irClass->index = (*nextIndex)++;
}
}
@@ -162,7 +162,7 @@
static void SortEncodedFields(std::vector<EncodedField*>* fields) {
std::sort(fields->begin(), fields->end(),
[](const EncodedField* a, const EncodedField* b) {
- CHECK(a->decl->index != b->decl->index || a == b);
+ SLICER_CHECK(a->decl->index != b->decl->index || a == b);
return a->decl->index < b->decl->index;
});
}
@@ -171,7 +171,7 @@
static void SortEncodedMethods(std::vector<EncodedMethod*>* methods) {
std::sort(methods->begin(), methods->end(),
[](const EncodedMethod* a, const EncodedMethod* b) {
- CHECK(a->decl->index != b->decl->index || a == b);
+ SLICER_CHECK(a->decl->index != b->decl->index || a == b);
return a->decl->index < b->decl->index;
});
}
@@ -256,9 +256,9 @@
SortClassIndexes();
IndexItems(classes, [&](const own<Class>& a, const own<Class>& b) {
- CHECK(a->index < classes.size());
- CHECK(b->index < classes.size());
- CHECK(a->index != b->index || a == b);
+ SLICER_CHECK(a->index < classes.size());
+ SLICER_CHECK(b->index < classes.size());
+ SLICER_CHECK(a->index != b->index || a == b);
return a->index < b->index;
});
diff --git a/slicer/dex_ir_builder.cc b/slicer/dex_ir_builder.cc
index b6ee716..a078a62 100644
--- a/slicer/dex_ir_builder.cc
+++ b/slicer/dex_ir_builder.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "dex_ir_builder.h"
+#include "slicer/dex_ir_builder.h"
#include <sstream>
#include <string.h>
@@ -78,7 +78,7 @@
// update the index -> ir node map
auto new_index = dex_ir_->strings_indexes.AllocateIndex();
auto& ir_node = dex_ir_->strings_map[new_index];
- CHECK(ir_node == nullptr);
+ SLICER_CHECK(ir_node == nullptr);
ir_node = ir_string;
ir_string->orig_index = new_index;
@@ -106,7 +106,7 @@
// update the index -> ir node map
auto new_index = dex_ir_->types_indexes.AllocateIndex();
auto& ir_node = dex_ir_->types_map[new_index];
- CHECK(ir_node == nullptr);
+ SLICER_CHECK(ir_node == nullptr);
ir_node = ir_type;
ir_type->orig_index = new_index;
@@ -165,7 +165,7 @@
// update the index -> ir node map
auto new_index = dex_ir_->protos_indexes.AllocateIndex();
auto& ir_node = dex_ir_->protos_map[new_index];
- CHECK(ir_node == nullptr);
+ SLICER_CHECK(ir_node == nullptr);
ir_node = ir_proto;
ir_proto->orig_index = new_index;
@@ -194,7 +194,7 @@
// update the index -> ir node map
auto new_index = dex_ir_->fields_indexes.AllocateIndex();
auto& ir_node = dex_ir_->fields_map[new_index];
- CHECK(ir_node == nullptr);
+ SLICER_CHECK(ir_node == nullptr);
ir_node = ir_field;
ir_field->orig_index = new_index;
@@ -220,7 +220,7 @@
// update the index -> ir node map
auto new_index = dex_ir_->methods_indexes.AllocateIndex();
auto& ir_node = dex_ir_->methods_map[new_index];
- CHECK(ir_node == nullptr);
+ SLICER_CHECK(ir_node == nullptr);
ir_node = ir_method;
ir_method->orig_index = new_index;
diff --git a/slicer/dex_utf8.cc b/slicer/dex_utf8.cc
index a30adaf..c174626 100644
--- a/slicer/dex_utf8.cc
+++ b/slicer/dex_utf8.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "dex_format.h"
+#include "slicer/dex_format.h"
namespace dex {
diff --git a/slicer/arrayview.h b/slicer/export/slicer/arrayview.h
similarity index 97%
rename from slicer/arrayview.h
rename to slicer/export/slicer/arrayview.h
index 527a3bb..53c624c 100644
--- a/slicer/arrayview.h
+++ b/slicer/export/slicer/arrayview.h
@@ -39,7 +39,7 @@
T* data() const { return begin_; }
T& operator[](size_t i) const {
- CHECK(i < size());
+ SLICER_CHECK(i < size());
return *(begin_ + i);
}
diff --git a/slicer/buffer.h b/slicer/export/slicer/buffer.h
similarity index 94%
rename from slicer/buffer.h
rename to slicer/export/slicer/buffer.h
index f98f617..d20324d 100644
--- a/slicer/buffer.h
+++ b/slicer/export/slicer/buffer.h
@@ -60,7 +60,7 @@
public:
// Align the total size and prevent further changes
size_t Seal(size_t alignment) {
- CHECK(!sealed_);
+ SLICER_CHECK(!sealed_);
Align(alignment);
sealed_ = true;
return size();
@@ -73,7 +73,7 @@
//
template <class T>
T* ptr(size_t offset) {
- CHECK(offset + sizeof(T) <= size_);
+ SLICER_CHECK(offset + sizeof(T) <= size_);
return reinterpret_cast<T*>(buff_ + offset);
}
@@ -115,7 +115,7 @@
}
size_t Push(const Buffer& buff) {
- CHECK(&buff != this);
+ SLICER_CHECK(&buff != this);
return Push(buff.data(), buff.size());
}
@@ -153,17 +153,17 @@
}
const dex::u1* data() const {
- CHECK(buff_ != nullptr);
+ SLICER_CHECK(buff_ != nullptr);
return buff_;
}
private:
void Expand(size_t size) {
- CHECK(!sealed_);
+ SLICER_CHECK(!sealed_);
if (size_ + size > capacity_) {
capacity_ = std::max(size_t(capacity_ * 1.5), size_ + size);
buff_ = static_cast<dex::u1*>(::realloc(buff_, capacity_));
- CHECK(buff_ != nullptr);
+ SLICER_CHECK(buff_ != nullptr);
}
size_ += size;
}
diff --git a/slicer/bytecode_encoder.h b/slicer/export/slicer/bytecode_encoder.h
similarity index 100%
rename from slicer/bytecode_encoder.h
rename to slicer/export/slicer/bytecode_encoder.h
diff --git a/slicer/chronometer.h b/slicer/export/slicer/chronometer.h
similarity index 100%
rename from slicer/chronometer.h
rename to slicer/export/slicer/chronometer.h
diff --git a/slicer/code_ir.h b/slicer/export/slicer/code_ir.h
similarity index 98%
rename from slicer/code_ir.h
rename to slicer/export/slicer/code_ir.h
index 916d282..2d028b9 100644
--- a/slicer/code_ir.h
+++ b/slicer/export/slicer/code_ir.h
@@ -242,7 +242,7 @@
template<class T>
T* CastOperand(int index) const {
T* operand = dynamic_cast<T*>(operands[index]);
- CHECK(operand != nullptr);
+ SLICER_CHECK(operand != nullptr);
return operand;
}
@@ -312,7 +312,7 @@
int line = 0;
LineNumber(int line) : line(line) {
- WEAK_CHECK(line > 0);
+ SLICER_WEAK_CHECK(line > 0);
}
virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); }
@@ -327,7 +327,7 @@
template<class T>
T* CastOperand(int index) const {
T* operand = dynamic_cast<T*>(operands[index]);
- CHECK(operand != nullptr);
+ SLICER_CHECK(operand != nullptr);
return operand;
}
diff --git a/slicer/common.h b/slicer/export/slicer/common.h
similarity index 75%
rename from slicer/common.h
rename to slicer/export/slicer/common.h
index 693ccb3..4c2554c 100644
--- a/slicer/common.h
+++ b/slicer/export/slicer/common.h
@@ -21,27 +21,27 @@
// Encapsulate the runtime check and error reporting policy.
// (currently a simple fail-fast but the the intention is to allow customization)
void _checkFailed(const char* expr, int line, const char* file) __attribute__((noreturn));
-#define CHECK(expr) do { if(!(expr)) slicer::_checkFailed(#expr, __LINE__, __FILE__); } while(false)
+#define SLICER_CHECK(expr) do { if(!(expr)) slicer::_checkFailed(#expr, __LINE__, __FILE__); } while(false)
-// A modal check: if the strict mode is enabled, it behaves as a CHECK,
+// A modal check: if the strict mode is enabled, it behaves as a SLICER_CHECK,
// otherwise it will only log a warning and continue
//
-// NOTE: we use WEAK_CHECK for .dex format validations that are frequently
+// NOTE: we use SLICER_WEAK_CHECK for .dex format validations that are frequently
// violated by existing apps. So we need to be able to annotate these common
// problems and potentially ignoring them for parity with the Android runtime.
//
void _weakCheckFailed(const char* expr, int line, const char* file);
-#define WEAK_CHECK(expr) do { if(!(expr)) slicer::_weakCheckFailed(#expr, __LINE__, __FILE__); } while(false)
+#define SLICER_WEAK_CHECK(expr) do { if(!(expr)) slicer::_weakCheckFailed(#expr, __LINE__, __FILE__); } while(false)
// Report a fatal condition with a printf-formatted message
void _fatal(const char* format, ...) __attribute__((noreturn));
-#define FATAL(format, ...) slicer::_fatal("\nFATAL: " format "\n\n", ##__VA_ARGS__);
+#define SLICER_FATAL(format, ...) slicer::_fatal("\nSLICER_FATAL: " format "\n\n", ##__VA_ARGS__);
// Annotation customization point for extra validation / state.
#ifdef NDEBUG
-#define EXTRA(x)
+#define SLICER_EXTRA(x)
#else
-#define EXTRA(x) x
+#define SLICER_EXTRA(x) x
#endif
} // namespace slicer
diff --git a/slicer/control_flow_graph.h b/slicer/export/slicer/control_flow_graph.h
similarity index 100%
rename from slicer/control_flow_graph.h
rename to slicer/export/slicer/control_flow_graph.h
diff --git a/slicer/debuginfo_encoder.h b/slicer/export/slicer/debuginfo_encoder.h
similarity index 100%
rename from slicer/debuginfo_encoder.h
rename to slicer/export/slicer/debuginfo_encoder.h
diff --git a/slicer/dex_bytecode.h b/slicer/export/slicer/dex_bytecode.h
similarity index 100%
rename from slicer/dex_bytecode.h
rename to slicer/export/slicer/dex_bytecode.h
diff --git a/slicer/dex_format.h b/slicer/export/slicer/dex_format.h
similarity index 100%
rename from slicer/dex_format.h
rename to slicer/export/slicer/dex_format.h
diff --git a/slicer/dex_ir.h b/slicer/export/slicer/dex_ir.h
similarity index 94%
rename from slicer/dex_ir.h
rename to slicer/export/slicer/dex_ir.h
index 67e5d11..1d5dc3c 100644
--- a/slicer/dex_ir.h
+++ b/slicer/export/slicer/dex_ir.h
@@ -40,11 +40,11 @@
// it's expected to construct the IR for the single modified class only
// (and include only the nodes referenced from that class)
-#define IR_TYPE \
+#define SLICER_IR_TYPE \
using Node::Node; \
friend struct DexFile;
-#define IR_INDEXED_TYPE \
+#define SLICER_IR_INDEXED_TYPE \
using IndexedNode::IndexedNode; \
friend struct DexFile;
@@ -114,7 +114,7 @@
// TODO: consider moving the indexing to the writer.
//
struct IndexedNode : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
// this is the index in the generated image
// (not the original index)
@@ -126,7 +126,7 @@
};
struct EncodedValue : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
dex::u1 type;
union {
@@ -147,17 +147,17 @@
bool bool_value;
} u;
- EXTRA(slicer::MemView original);
+ SLICER_EXTRA(slicer::MemView original);
};
struct EncodedArray : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
std::vector<EncodedValue*> values;
};
struct String : public IndexedNode {
- IR_INDEXED_TYPE;
+ SLICER_IR_INDEXED_TYPE;
// opaque DEX "string_data_item"
slicer::MemView data;
@@ -170,7 +170,7 @@
};
struct Type : public IndexedNode {
- IR_INDEXED_TYPE;
+ SLICER_IR_INDEXED_TYPE;
enum class Category { Void, Scalar, WideScalar, Reference };
@@ -182,13 +182,13 @@
};
struct TypeList : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
std::vector<Type*> types;
};
struct Proto : public IndexedNode {
- IR_INDEXED_TYPE;
+ SLICER_IR_INDEXED_TYPE;
String* shorty;
Type* return_type;
@@ -198,7 +198,7 @@
};
struct FieldDecl : public IndexedNode {
- IR_INDEXED_TYPE;
+ SLICER_IR_INDEXED_TYPE;
String* name;
Type* type;
@@ -206,14 +206,14 @@
};
struct EncodedField : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
FieldDecl* decl;
dex::u4 access_flags;
};
struct DebugInfo : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
dex::u4 line_start;
std::vector<String*> param_names;
@@ -224,7 +224,7 @@
};
struct Code : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
dex::u2 registers;
dex::u2 ins_count;
@@ -236,7 +236,7 @@
};
struct MethodDecl : public IndexedNode {
- IR_INDEXED_TYPE;
+ SLICER_IR_INDEXED_TYPE;
String* name;
Proto* prototype;
@@ -244,7 +244,7 @@
};
struct EncodedMethod : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
MethodDecl* decl;
Code* code;
@@ -252,14 +252,14 @@
};
struct AnnotationElement : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
String* name;
EncodedValue* value;
};
struct Annotation : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
Type* type;
std::vector<AnnotationElement*> elements;
@@ -267,40 +267,40 @@
};
struct AnnotationSet : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
std::vector<Annotation*> annotations;
};
struct AnnotationSetRefList : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
std::vector<AnnotationSet*> annotations;
};
struct FieldAnnotation : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
FieldDecl* field_decl;
AnnotationSet* annotations;
};
struct MethodAnnotation : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
MethodDecl* method_decl;
AnnotationSet* annotations;
};
struct ParamAnnotation : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
MethodDecl* method_decl;
AnnotationSetRefList* annotations;
};
struct AnnotationsDirectory : public Node {
- IR_TYPE;
+ SLICER_IR_TYPE;
AnnotationSet* class_annotation;
std::vector<FieldAnnotation*> field_annotations;
@@ -309,7 +309,7 @@
};
struct Class : public IndexedNode {
- IR_INDEXED_TYPE;
+ SLICER_IR_INDEXED_TYPE;
Type* type;
dex::u4 access_flags;
@@ -471,5 +471,5 @@
} // namespace ir
-#undef IR_TYPE
-#undef IR_INDEXED_TYPE
+#undef SLICER_IR_TYPE
+#undef SLICER_IR_INDEXED_TYPE
diff --git a/slicer/dex_ir_builder.h b/slicer/export/slicer/dex_ir_builder.h
similarity index 100%
rename from slicer/dex_ir_builder.h
rename to slicer/export/slicer/dex_ir_builder.h
diff --git a/slicer/dex_leb128.h b/slicer/export/slicer/dex_leb128.h
similarity index 100%
rename from slicer/dex_leb128.h
rename to slicer/export/slicer/dex_leb128.h
diff --git a/slicer/dex_utf8.h b/slicer/export/slicer/dex_utf8.h
similarity index 100%
rename from slicer/dex_utf8.h
rename to slicer/export/slicer/dex_utf8.h
diff --git a/slicer/hash_table.h b/slicer/export/slicer/hash_table.h
similarity index 97%
rename from slicer/hash_table.h
rename to slicer/export/slicer/hash_table.h
index c68eaca..7eca41a 100644
--- a/slicer/hash_table.h
+++ b/slicer/export/slicer/hash_table.h
@@ -124,7 +124,7 @@
//
template<class Key, class T, class Hash>
bool HashTable<Key, T, Hash>::Partition::Insert(T* value) {
- CHECK(value != nullptr);
+ SLICER_CHECK(value != nullptr);
// overflow?
if (buckets_.size() + 1 > buckets_.capacity()) {
return false;
@@ -163,7 +163,7 @@
void HashTable<Key, T, Hash>::Partition::InsertAll(const Partition& src) {
for (const auto& bucket : src.buckets_) {
if (bucket.value != nullptr) {
- CHECK(Insert(bucket.value));
+ SLICER_CHECK(Insert(bucket.value));
}
}
}
@@ -180,7 +180,7 @@
if (full_table_) {
new_hash_table->InsertAll(*full_table_);
}
- CHECK(new_hash_table->Insert(value));
+ SLICER_CHECK(new_hash_table->Insert(value));
full_table_ = std::move(insertion_table_);
insertion_table_ = std::move(new_hash_table);
}
@@ -211,7 +211,7 @@
++used_buckets;
int chain_length = 0;
for (Index ci = i; buckets_[ci].next != kInvalidIndex; ci = buckets_[ci].next) {
- CHECK(buckets_[ci].value != nullptr);
+ SLICER_CHECK(buckets_[ci].value != nullptr);
++chain_length;
if (verbose) printf("*");
}
diff --git a/slicer/index_map.h b/slicer/export/slicer/index_map.h
similarity index 96%
rename from slicer/index_map.h
rename to slicer/export/slicer/index_map.h
index 46600d0..b7fa1c3 100644
--- a/slicer/index_map.h
+++ b/slicer/export/slicer/index_map.h
@@ -39,7 +39,7 @@
if (index >= indexes_map_.size()) {
indexes_map_.resize(index + 1);
}
- CHECK(!indexes_map_[index]);
+ SLICER_CHECK(!indexes_map_[index]);
indexes_map_[index] = true;
}
diff --git a/slicer/instrumentation.h b/slicer/export/slicer/instrumentation.h
similarity index 72%
rename from slicer/instrumentation.h
rename to slicer/export/slicer/instrumentation.h
index eae4517..c6ad454 100644
--- a/slicer/instrumentation.h
+++ b/slicer/export/slicer/instrumentation.h
@@ -46,7 +46,7 @@
: hook_method_id_(hook_method_id),
use_object_type_for_this_argument_(use_object_type_for_this_argument) {
// hook method signature is generated automatically
- CHECK(hook_method_id_.signature == nullptr);
+ SLICER_CHECK(hook_method_id_.signature == nullptr);
}
virtual bool Apply(lir::CodeIr* code_ir) override;
@@ -66,7 +66,7 @@
public:
explicit ExitHook(const ir::MethodId& hook_method_id) : hook_method_id_(hook_method_id) {
// hook method signature is generated automatically
- CHECK(hook_method_id_.signature == nullptr);
+ SLICER_CHECK(hook_method_id_.signature == nullptr);
}
virtual bool Apply(lir::CodeIr* code_ir) override;
@@ -75,24 +75,52 @@
ir::MethodId hook_method_id_;
};
-// Replace every invoke-virtual[/range] to the a specified method with
-// a invoke-static[/range] to the detour method. The detour is a static
-// method which takes the same arguments as the original method plus
-// an explicit "this" argument, and returns the same type as the original method
-class DetourVirtualInvoke : public Transformation {
+// Base class for detour hooks. Replace every occurrence of specific opcode with
+// something else. The detour is a static method which takes the same arguments
+// as the original method plus an explicit "this" argument and returns the same
+// type as the original method. Derived classes must implement GetNewOpcode.
+class DetourHook : public Transformation {
public:
- DetourVirtualInvoke(const ir::MethodId& orig_method_id, const ir::MethodId& detour_method_id)
- : orig_method_id_(orig_method_id), detour_method_id_(detour_method_id) {
+ DetourHook(const ir::MethodId& orig_method_id,
+ const ir::MethodId& detour_method_id)
+ : orig_method_id_(orig_method_id), detour_method_id_(detour_method_id) {
// detour method signature is automatically created
// to match the original method and must not be explicitly specified
- CHECK(detour_method_id_.signature == nullptr);
+ SLICER_CHECK(detour_method_id_.signature == nullptr);
}
virtual bool Apply(lir::CodeIr* code_ir) override;
- private:
+ protected:
ir::MethodId orig_method_id_;
ir::MethodId detour_method_id_;
+
+ // Returns a new opcode to replace the desired opcode or OP_NOP otherwise.
+ virtual dex::Opcode GetNewOpcode(dex::Opcode opcode) = 0;
+};
+
+// Replace every invoke-virtual[/range] to the a specified method with
+// a invoke-static[/range] to the detour method.
+class DetourVirtualInvoke : public DetourHook {
+ public:
+ DetourVirtualInvoke(const ir::MethodId& orig_method_id,
+ const ir::MethodId& detour_method_id)
+ : DetourHook(orig_method_id, detour_method_id) {}
+
+ protected:
+ virtual dex::Opcode GetNewOpcode(dex::Opcode opcode) override;
+};
+
+// Replace every invoke-interface[/range] to the a specified method with
+// a invoke-static[/range] to the detour method.
+class DetourInterfaceInvoke : public DetourHook {
+ public:
+ DetourInterfaceInvoke(const ir::MethodId& orig_method_id,
+ const ir::MethodId& detour_method_id)
+ : DetourHook(orig_method_id, detour_method_id) {}
+
+ protected:
+ virtual dex::Opcode GetNewOpcode(dex::Opcode opcode) override;
};
// Allocates scratch registers without doing a full register allocation
@@ -100,13 +128,13 @@
public:
explicit AllocateScratchRegs(int allocate_count, bool allow_renumbering = true)
: allocate_count_(allocate_count), allow_renumbering_(allow_renumbering) {
- CHECK(allocate_count > 0);
+ SLICER_CHECK(allocate_count > 0);
}
virtual bool Apply(lir::CodeIr* code_ir) override;
const std::set<dex::u4>& ScratchRegs() const {
- CHECK(scratch_regs_.size() == static_cast<size_t>(allocate_count_));
+ SLICER_CHECK(scratch_regs_.size() == static_cast<size_t>(allocate_count_));
return scratch_regs_;
}
@@ -134,7 +162,7 @@
// slicer::MethodInstrumenter mi(dex_ir);
// mi.AddTransformation<slicer::EntryHook>(ir::MethodId("LTracer;", "OnEntry"));
// mi.AddTransformation<slicer::ExitHook>(ir::MethodId("LTracer;", "OnExit"));
-// CHECK(mi.InstrumentMethod(ir::MethodId("LHello;", "Test", "(I)I")));
+// SLICER_CHECK(mi.InstrumentMethod(ir::MethodId("LHello;", "Test", "(I)I")));
// ...
//
class MethodInstrumenter {
diff --git a/slicer/intrusive_list.h b/slicer/export/slicer/intrusive_list.h
similarity index 98%
rename from slicer/intrusive_list.h
rename to slicer/export/slicer/intrusive_list.h
index 855f422..67408ae 100644
--- a/slicer/intrusive_list.h
+++ b/slicer/export/slicer/intrusive_list.h
@@ -114,7 +114,7 @@
}
void Remove(T* pos) {
- CHECK(pos != end_);
+ SLICER_CHECK(pos != end_);
if (pos->prev != nullptr) {
assert(pos != begin_);
pos->prev->next = pos->next;
diff --git a/slicer/memview.h b/slicer/export/slicer/memview.h
similarity index 100%
rename from slicer/memview.h
rename to slicer/export/slicer/memview.h
diff --git a/slicer/reader.h b/slicer/export/slicer/reader.h
similarity index 97%
rename from slicer/reader.h
rename to slicer/export/slicer/reader.h
index 668eb2b..4e08f52 100644
--- a/slicer/reader.h
+++ b/slicer/export/slicer/reader.h
@@ -104,7 +104,7 @@
// Convert a file pointer (absolute offset) to an in-memory pointer
template <class T>
const T* ptr(int offset) const {
- CHECK(offset >= 0 && offset + sizeof(T) <= size_);
+ SLICER_CHECK(offset >= 0 && offset + sizeof(T) <= size_);
return reinterpret_cast<const T*>(image_ + offset);
}
@@ -112,7 +112,7 @@
// (offset should be inside the data section)
template <class T>
const T* dataPtr(int offset) const {
- CHECK(offset >= header_->data_off && offset + sizeof(T) <= size_);
+ SLICER_CHECK(offset >= header_->data_off && offset + sizeof(T) <= size_);
return reinterpret_cast<const T*>(image_ + offset);
}
diff --git a/slicer/scopeguard.h b/slicer/export/slicer/scopeguard.h
similarity index 83%
rename from slicer/scopeguard.h
rename to slicer/export/slicer/scopeguard.h
index fe20b9b..28e3bc9 100644
--- a/slicer/scopeguard.h
+++ b/slicer/export/slicer/scopeguard.h
@@ -24,7 +24,7 @@
// Here is how it's used:
//
// FILE* file = std::fopen(...);
-// SCOPE_EXIT {
+// SLICER_SCOPE_EXIT {
// std::fclose(file);
// };
//
@@ -65,12 +65,12 @@
}
};
-#define SG_MACRO_CONCAT2(a, b) a ## b
-#define SG_MACRO_CONCAT(a, b) SG_MACRO_CONCAT2(a, b)
-#define SG_ANONYMOUS(prefix) SG_MACRO_CONCAT(prefix, __COUNTER__)
+#define SLICER_SG_MACRO_CONCAT2(a, b) a ## b
+#define SLICER_SG_MACRO_CONCAT(a, b) SLICER_SG_MACRO_CONCAT2(a, b)
+#define SLICER_SG_ANONYMOUS(prefix) SLICER_SG_MACRO_CONCAT(prefix, __COUNTER__)
-#define SCOPE_EXIT \
- auto SG_ANONYMOUS(_scope_guard_) = slicer::ScopeGuardHelper() << [&]()
+#define SLICER_SCOPE_EXIT \
+ auto SLICER_SG_ANONYMOUS(_scope_guard_) = slicer::ScopeGuardHelper() << [&]()
} // namespace slicer
diff --git a/slicer/tryblocks_encoder.h b/slicer/export/slicer/tryblocks_encoder.h
similarity index 100%
rename from slicer/tryblocks_encoder.h
rename to slicer/export/slicer/tryblocks_encoder.h
diff --git a/slicer/writer.h b/slicer/export/slicer/writer.h
similarity index 96%
rename from slicer/writer.h
rename to slicer/export/slicer/writer.h
index 4a3f08f..00a04ce 100644
--- a/slicer/writer.h
+++ b/slicer/export/slicer/writer.h
@@ -39,18 +39,18 @@
Section& operator=(const Section&) = delete;
void SetOffset(dex::u4 offset) {
- CHECK(offset > 0 && offset % 4 == 0);
+ SLICER_CHECK(offset > 0 && offset % 4 == 0);
offset_ = offset;
}
dex::u4 SectionOffset() const {
- CHECK(offset_ > 0 && offset_ % 4 == 0);
+ SLICER_CHECK(offset_ > 0 && offset_ % 4 == 0);
return ItemsCount() > 0 ? offset_ : 0;
}
dex::u4 AbsoluteOffset(dex::u4 itemOffset) const {
- CHECK(offset_ > 0);
- CHECK(itemOffset < size());
+ SLICER_CHECK(offset_ > 0);
+ SLICER_CHECK(itemOffset < size());
return offset_ + itemOffset;
}
@@ -96,7 +96,7 @@
}
dex::u4 SectionOffset() const {
- CHECK(offset_ > 0 && offset_ % 4 == 0);
+ SLICER_CHECK(offset_ > 0 && offset_ % 4 == 0);
return ItemsCount() > 0 ? offset_ : 0;
}
@@ -110,7 +110,7 @@
dex::u4 size() const { return count_ * sizeof(T); }
T& operator[](int i) {
- CHECK(i >= 0 && i < count_);
+ SLICER_CHECK(i >= 0 && i < count_);
return values_[i];
}
diff --git a/slicer/instrumentation.cc b/slicer/instrumentation.cc
index 89dcb3a..59a8473 100644
--- a/slicer/instrumentation.cc
+++ b/slicer/instrumentation.cc
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "instrumentation.h"
-#include "dex_ir_builder.h"
+#include "slicer/instrumentation.h"
+#include "slicer/dex_ir_builder.h"
namespace slicer {
@@ -107,22 +107,22 @@
switch (bytecode->opcode) {
case dex::OP_RETURN_VOID:
- CHECK(return_void);
+ SLICER_CHECK(return_void);
break;
case dex::OP_RETURN:
- CHECK(!return_void);
+ SLICER_CHECK(!return_void);
move_result_opcode = dex::OP_MOVE_RESULT;
reg = bytecode->CastOperand<lir::VReg>(0)->reg;
reg_count = 1;
break;
case dex::OP_RETURN_OBJECT:
- CHECK(!return_void);
+ SLICER_CHECK(!return_void);
move_result_opcode = dex::OP_MOVE_RESULT_OBJECT;
reg = bytecode->CastOperand<lir::VReg>(0)->reg;
reg_count = 1;
break;
case dex::OP_RETURN_WIDE:
- CHECK(!return_void);
+ SLICER_CHECK(!return_void);
move_result_opcode = dex::OP_MOVE_RESULT_WIDE;
reg = bytecode->CastOperand<lir::VRegPair>(0)->base_reg;
reg_count = 2;
@@ -158,7 +158,7 @@
return true;
}
-bool DetourVirtualInvoke::Apply(lir::CodeIr* code_ir) {
+bool DetourHook::Apply(lir::CodeIr* code_ir) {
ir::Builder builder(code_ir->dex_ir);
// search for matching invoke-virtual[/range] bytecodes
@@ -168,19 +168,10 @@
continue;
}
- dex::Opcode new_call_opcode = dex::OP_NOP;
- switch (bytecode->opcode) {
- case dex::OP_INVOKE_VIRTUAL:
- new_call_opcode = dex::OP_INVOKE_STATIC;
- break;
- case dex::OP_INVOKE_VIRTUAL_RANGE:
- new_call_opcode = dex::OP_INVOKE_STATIC_RANGE;
- break;
- default:
- // skip instruction ...
- continue;
+ dex::Opcode new_call_opcode = GetNewOpcode(bytecode->opcode);
+ if (new_call_opcode == dex::OP_NOP) {
+ continue;
}
- assert(new_call_opcode != dex::OP_NOP);
auto orig_method = bytecode->CastOperand<lir::Method>(1)->ir_method;
if (!orig_method_id_.Match(orig_method)) {
@@ -194,7 +185,8 @@
param_types.push_back(orig_method->parent);
if (orig_method->prototype->param_types != nullptr) {
const auto& orig_param_types = orig_method->prototype->param_types->types;
- param_types.insert(param_types.end(), orig_param_types.begin(), orig_param_types.end());
+ param_types.insert(param_types.end(), orig_param_types.begin(),
+ orig_param_types.end());
}
auto ir_proto = builder.GetProto(orig_method->prototype->return_type,
@@ -204,7 +196,8 @@
builder.GetAsciiString(detour_method_id_.method_name), ir_proto,
builder.GetType(detour_method_id_.class_descriptor));
- auto detour_method = code_ir->Alloc<lir::Method>(ir_method_decl, ir_method_decl->orig_index);
+ auto detour_method =
+ code_ir->Alloc<lir::Method>(ir_method_decl, ir_method_decl->orig_index);
// We mutate the original invoke bytecode in-place: this is ok
// because lir::Instructions can't be shared (referenced multiple times)
@@ -217,12 +210,36 @@
return true;
}
+dex::Opcode DetourVirtualInvoke::GetNewOpcode(dex::Opcode opcode) {
+ switch (opcode) {
+ case dex::OP_INVOKE_VIRTUAL:
+ return dex::OP_INVOKE_STATIC;
+ case dex::OP_INVOKE_VIRTUAL_RANGE:
+ return dex::OP_INVOKE_STATIC_RANGE;
+ default:
+ // skip instruction ...
+ return dex::OP_NOP;
+ }
+}
+
+dex::Opcode DetourInterfaceInvoke::GetNewOpcode(dex::Opcode opcode) {
+ switch (opcode) {
+ case dex::OP_INVOKE_INTERFACE:
+ return dex::OP_INVOKE_STATIC;
+ case dex::OP_INVOKE_INTERFACE_RANGE:
+ return dex::OP_INVOKE_STATIC_RANGE;
+ default:
+ // skip instruction ...
+ return dex::OP_NOP;
+ }
+}
+
// Register re-numbering visitor
// (renumbers vN to vN+shift)
class RegsRenumberVisitor : public lir::Visitor {
public:
RegsRenumberVisitor(int shift) : shift_(shift) {
- CHECK(shift > 0);
+ SLICER_CHECK(shift > 0);
}
private:
@@ -272,7 +289,7 @@
// make existing bytecodes "unencodable" (if they have 4 bit reg fields)
//
void AllocateScratchRegs::RegsRenumbering(lir::CodeIr* code_ir) {
- CHECK(left_to_allocate_ > 0);
+ SLICER_CHECK(left_to_allocate_ > 0);
int delta = std::min(left_to_allocate_,
16 - static_cast<int>(code_ir->ir_method->code->registers));
if (delta < 1) {
@@ -301,8 +318,8 @@
//
void AllocateScratchRegs::ShiftParams(lir::CodeIr* code_ir) {
const auto ir_method = code_ir->ir_method;
- CHECK(ir_method->code->ins_count > 0);
- CHECK(left_to_allocate_ > 0);
+ SLICER_CHECK(ir_method->code->ins_count > 0);
+ SLICER_CHECK(left_to_allocate_ > 0);
// build a param list with the explicit "this" argument for non-static methods
std::vector<ir::Type*> param_types;
@@ -321,7 +338,7 @@
const dex::u4 regs = ir_method->code->registers;
const dex::u4 ins_count = ir_method->code->ins_count;
- CHECK(regs >= ins_count);
+ SLICER_CHECK(regs >= ins_count);
// generate the args "relocation" instructions
auto first_instr = code_ir->instructions.begin();
@@ -348,7 +365,7 @@
reg += 2;
break;
case ir::Type::Category::Void:
- FATAL("void parameter type");
+ SLICER_FATAL("void parameter type");
}
code_ir->instructions.insert(first_instr, move);
}
@@ -356,11 +373,11 @@
// Mark [first_reg, first_reg + count) as scratch registers
void AllocateScratchRegs::Allocate(lir::CodeIr* code_ir, dex::u4 first_reg, int count) {
- CHECK(count > 0 && count <= left_to_allocate_);
+ SLICER_CHECK(count > 0 && count <= left_to_allocate_);
code_ir->ir_method->code->registers += count;
left_to_allocate_ -= count;
for (int i = 0; i < count; ++i) {
- CHECK(scratch_regs_.insert(first_reg + i).second);
+ SLICER_CHECK(scratch_regs_.insert(first_reg + i).second);
}
}
@@ -374,7 +391,7 @@
bool AllocateScratchRegs::Apply(lir::CodeIr* code_ir) {
const auto code = code_ir->ir_method->code;
// .dex bytecode allows up to 64k vregs
- CHECK(code->registers + allocate_count_ <= (1 << 16));
+ SLICER_CHECK(code->registers + allocate_count_ <= (1 << 16));
scratch_regs_.clear();
left_to_allocate_ = allocate_count_;
@@ -402,7 +419,7 @@
}
bool MethodInstrumenter::InstrumentMethod(ir::EncodedMethod* ir_method) {
- CHECK(ir_method != nullptr);
+ SLICER_CHECK(ir_method != nullptr);
if (ir_method->code == nullptr) {
// can't instrument abstract methods
return false;
diff --git a/slicer/reader.cc b/slicer/reader.cc
index 8f23b72..1c547af 100644
--- a/slicer/reader.cc
+++ b/slicer/reader.cc
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "reader.h"
-#include "dex_bytecode.h"
-#include "chronometer.h"
-#include "dex_leb128.h"
+#include "slicer/reader.h"
+#include "slicer/dex_bytecode.h"
+#include "slicer/chronometer.h"
+#include "slicer/dex_leb128.h"
#include <assert.h>
#include <string.h>
@@ -88,7 +88,7 @@
void Reader::CreateClassIr(dex::u4 index) {
auto ir_class = GetClass(index);
- CHECK(ir_class != nullptr);
+ SLICER_CHECK(ir_class != nullptr);
}
// Returns the index of the class with the specified
@@ -119,102 +119,102 @@
// (we use the dummy value to guard against this too)
//
ir::Class* Reader::GetClass(dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
auto& p = dex_ir_->classes_map[index];
auto dummy = reinterpret_cast<ir::Class*>(1);
if (p == nullptr) {
p = dummy;
auto newClass = ParseClass(index);
- CHECK(p == dummy);
+ SLICER_CHECK(p == dummy);
p = newClass;
dex_ir_->classes_indexes.MarkUsedIndex(index);
}
- CHECK(p != dummy);
+ SLICER_CHECK(p != dummy);
return p;
}
// map a .dex index to corresponding .dex IR node
// (see the Reader::GetClass() comments)
ir::Type* Reader::GetType(dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
auto& p = dex_ir_->types_map[index];
auto dummy = reinterpret_cast<ir::Type*>(1);
if (p == nullptr) {
p = dummy;
auto newType = ParseType(index);
- CHECK(p == dummy);
+ SLICER_CHECK(p == dummy);
p = newType;
dex_ir_->types_indexes.MarkUsedIndex(index);
}
- CHECK(p != dummy);
+ SLICER_CHECK(p != dummy);
return p;
}
// map a .dex index to corresponding .dex IR node
// (see the Reader::GetClass() comments)
ir::FieldDecl* Reader::GetFieldDecl(dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
auto& p = dex_ir_->fields_map[index];
auto dummy = reinterpret_cast<ir::FieldDecl*>(1);
if (p == nullptr) {
p = dummy;
auto newField = ParseFieldDecl(index);
- CHECK(p == dummy);
+ SLICER_CHECK(p == dummy);
p = newField;
dex_ir_->fields_indexes.MarkUsedIndex(index);
}
- CHECK(p != dummy);
+ SLICER_CHECK(p != dummy);
return p;
}
// map a .dex index to corresponding .dex IR node
// (see the Reader::GetClass() comments)
ir::MethodDecl* Reader::GetMethodDecl(dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
auto& p = dex_ir_->methods_map[index];
auto dummy = reinterpret_cast<ir::MethodDecl*>(1);
if (p == nullptr) {
p = dummy;
auto newMethod = ParseMethodDecl(index);
- CHECK(p == dummy);
+ SLICER_CHECK(p == dummy);
p = newMethod;
dex_ir_->methods_indexes.MarkUsedIndex(index);
}
- CHECK(p != dummy);
+ SLICER_CHECK(p != dummy);
return p;
}
// map a .dex index to corresponding .dex IR node
// (see the Reader::GetClass() comments)
ir::Proto* Reader::GetProto(dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
auto& p = dex_ir_->protos_map[index];
auto dummy = reinterpret_cast<ir::Proto*>(1);
if (p == nullptr) {
p = dummy;
auto newProto = ParseProto(index);
- CHECK(p == dummy);
+ SLICER_CHECK(p == dummy);
p = newProto;
dex_ir_->protos_indexes.MarkUsedIndex(index);
}
- CHECK(p != dummy);
+ SLICER_CHECK(p != dummy);
return p;
}
// map a .dex index to corresponding .dex IR node
// (see the Reader::GetClass() comments)
ir::String* Reader::GetString(dex::u4 index) {
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
auto& p = dex_ir_->strings_map[index];
auto dummy = reinterpret_cast<ir::String*>(1);
if (p == nullptr) {
p = dummy;
auto newString = ParseString(index);
- CHECK(p == dummy);
+ SLICER_CHECK(p == dummy);
p = newString;
dex_ir_->strings_indexes.MarkUsedIndex(index);
}
- CHECK(p != dummy);
+ SLICER_CHECK(p != dummy);
return p;
}
@@ -282,7 +282,7 @@
return nullptr;
}
- CHECK(offset % 4 == 0);
+ SLICER_CHECK(offset % 4 == 0);
// first check if we already extracted the same "annotations_directory_item"
auto& ir_annotations = annotations_directories_[offset];
@@ -312,7 +312,7 @@
}
ir::Annotation* Reader::ExtractAnnotationItem(dex::u4 offset) {
- CHECK(offset != 0);
+ SLICER_CHECK(offset != 0);
// first check if we already extracted the same "annotation_item"
auto& ir_annotation = annotations_[offset];
@@ -330,7 +330,7 @@
return nullptr;
}
- CHECK(offset % 4 == 0);
+ SLICER_CHECK(offset % 4 == 0);
// first check if we already extracted the same "annotation_set_item"
auto& ir_annotation_set = annotation_sets_[offset];
@@ -348,7 +348,7 @@
}
ir::AnnotationSetRefList* Reader::ExtractAnnotationSetRefList(dex::u4 offset) {
- CHECK(offset % 4 == 0);
+ SLICER_CHECK(offset % 4 == 0);
auto dex_annotation_set_ref_list = dataPtr<dex::AnnotationSetRefList>(offset);
auto ir_annotation_set_ref_list = dex_ir_->Alloc<ir::AnnotationSetRefList>();
@@ -357,7 +357,7 @@
dex::u4 entry_offset = dex_annotation_set_ref_list->list[i].annotations_off;
if (entry_offset != 0) {
auto ir_annotation_set = ExtractAnnotationSet(entry_offset);
- CHECK(ir_annotation_set != nullptr);
+ SLICER_CHECK(ir_annotation_set != nullptr);
ir_annotation_set_ref_list->annotations.push_back(ir_annotation_set);
}
}
@@ -373,7 +373,7 @@
ir_field_annotation->annotations =
ExtractAnnotationSet(dex_field_annotation->annotations_off);
- CHECK(ir_field_annotation->annotations != nullptr);
+ SLICER_CHECK(ir_field_annotation->annotations != nullptr);
*pptr += sizeof(dex::FieldAnnotationsItem);
return ir_field_annotation;
@@ -388,7 +388,7 @@
ir_method_annotation->annotations =
ExtractAnnotationSet(dex_method_annotation->annotations_off);
- CHECK(ir_method_annotation->annotations != nullptr);
+ SLICER_CHECK(ir_method_annotation->annotations != nullptr);
*pptr += sizeof(dex::MethodAnnotationsItem);
return ir_method_annotation;
@@ -403,7 +403,7 @@
ir_param_annotation->annotations =
ExtractAnnotationSetRefList(dex_param_annotation->annotations_off);
- CHECK(ir_param_annotation->annotations != nullptr);
+ SLICER_CHECK(ir_param_annotation->annotations != nullptr);
*pptr += sizeof(dex::ParameterAnnotationsItem);
return ir_param_annotation;
@@ -413,9 +413,9 @@
auto ir_encoded_field = dex_ir_->Alloc<ir::EncodedField>();
auto field_index = dex::ReadULeb128(pptr);
- CHECK(field_index != dex::kNoIndex);
+ SLICER_CHECK(field_index != dex::kNoIndex);
if (*base_index != dex::kNoIndex) {
- CHECK(field_index != 0);
+ SLICER_CHECK(field_index != 0);
field_index += *base_index;
}
*base_index = field_index;
@@ -432,8 +432,8 @@
static T ParseIntValue(const dex::u1** pptr, size_t size) {
static_assert(std::is_integral<T>::value, "must be an integral type");
- CHECK(size > 0);
- CHECK(size <= sizeof(T));
+ SLICER_CHECK(size > 0);
+ SLICER_CHECK(size <= sizeof(T));
T value = 0;
for (int i = 0; i < size; ++i) {
@@ -453,8 +453,8 @@
// (zero-extend to the right)
template <class T>
static T ParseFloatValue(const dex::u1** pptr, size_t size) {
- CHECK(size > 0);
- CHECK(size <= sizeof(T));
+ SLICER_CHECK(size > 0);
+ SLICER_CHECK(size <= sizeof(T));
T value = 0;
int start_byte = sizeof(T) - size;
@@ -468,7 +468,7 @@
ir::EncodedValue* Reader::ParseEncodedValue(const dex::u1** pptr) {
auto ir_encoded_value = dex_ir_->Alloc<ir::EncodedValue>();
- EXTRA(auto base_ptr = *pptr);
+ SLICER_EXTRA(auto base_ptr = *pptr);
dex::u1 header = *(*pptr)++;
dex::u1 type = header & dex::kEncodedValueTypeMask;
@@ -531,29 +531,29 @@
} break;
case dex::kEncodedArray:
- CHECK(arg == 0);
+ SLICER_CHECK(arg == 0);
ir_encoded_value->u.array_value = ParseEncodedArray(pptr);
break;
case dex::kEncodedAnnotation:
- CHECK(arg == 0);
+ SLICER_CHECK(arg == 0);
ir_encoded_value->u.annotation_value = ParseAnnotation(pptr);
break;
case dex::kEncodedNull:
- CHECK(arg == 0);
+ SLICER_CHECK(arg == 0);
break;
case dex::kEncodedBoolean:
- CHECK(arg < 2);
+ SLICER_CHECK(arg < 2);
ir_encoded_value->u.bool_value = (arg == 1);
break;
default:
- CHECK(!"unexpected value type");
+ SLICER_CHECK(!"unexpected value type");
}
- EXTRA(ir_encoded_value->original = slicer::MemView(base_ptr, *pptr - base_ptr));
+ SLICER_EXTRA(ir_encoded_value->original = slicer::MemView(base_ptr, *pptr - base_ptr));
return ir_encoded_value;
}
@@ -703,7 +703,7 @@
return nullptr;
}
- CHECK(offset % 4 == 0);
+ SLICER_CHECK(offset % 4 == 0);
auto dex_code = dataPtr<dex::Code>(offset);
auto ir_code = dex_ir_->Alloc<ir::Code>();
@@ -738,7 +738,7 @@
auto ptr = handlers_list;
dex::u4 handlers_count = dex::ReadULeb128(&ptr);
- WEAK_CHECK(handlers_count <= dex_code->tries_size);
+ SLICER_WEAK_CHECK(handlers_count <= dex_code->tries_size);
for (dex::u4 handler_index = 0; handler_index < handlers_count; ++handler_index) {
int catch_count = dex::ReadSLeb128(&ptr);
@@ -769,9 +769,9 @@
auto ir_encoded_method = dex_ir_->Alloc<ir::EncodedMethod>();
auto method_index = dex::ReadULeb128(pptr);
- CHECK(method_index != dex::kNoIndex);
+ SLICER_CHECK(method_index != dex::kNoIndex);
if (*base_index != dex::kNoIndex) {
- CHECK(method_index != 0);
+ SLICER_CHECK(method_index != 0);
method_index += *base_index;
}
*base_index = method_index;
@@ -833,7 +833,7 @@
ir_type_list = dex_ir_->Alloc<ir::TypeList>();
auto dex_type_list = dataPtr<dex::TypeList>(offset);
- WEAK_CHECK(dex_type_list->size > 0);
+ SLICER_WEAK_CHECK(dex_type_list->size > 0);
for (dex::u4 i = 0; i < dex_type_list->size; ++i) {
ir_type_list->types.push_back(GetType(dex_type_list->list[i].type_idx));
@@ -920,59 +920,59 @@
}
auto isize = dex::GetWidthFromBytecode(ptr);
- CHECK(isize > 0);
+ SLICER_CHECK(isize > 0);
ptr += isize;
}
- CHECK(ptr == code.end());
+ SLICER_CHECK(ptr == code.end());
}
// Basic .dex header structural checks
void Reader::ValidateHeader() {
- CHECK(size_ > sizeof(dex::Header));
+ SLICER_CHECK(size_ > sizeof(dex::Header));
// Known issue: For performance reasons the initial size_ passed to jvmti events might be an
// estimate. b/72402467
- CHECK(header_->file_size <= size_);
- CHECK(header_->header_size == sizeof(dex::Header));
- CHECK(header_->endian_tag == dex::kEndianConstant);
- CHECK(header_->data_size % 4 == 0);
+ SLICER_CHECK(header_->file_size <= size_);
+ SLICER_CHECK(header_->header_size == sizeof(dex::Header));
+ SLICER_CHECK(header_->endian_tag == dex::kEndianConstant);
+ SLICER_CHECK(header_->data_size % 4 == 0);
// Known issue: The fields might be slighly corrupted b/65452964
- // CHECK(header_->data_off + header_->data_size <= size_);
+ // SLICER_CHECK(header_->data_off + header_->data_size <= size_);
- CHECK(header_->string_ids_off % 4 == 0);
- CHECK(header_->type_ids_size < 65536);
- CHECK(header_->type_ids_off % 4 == 0);
- CHECK(header_->proto_ids_size < 65536);
- CHECK(header_->proto_ids_off % 4 == 0);
- CHECK(header_->field_ids_off % 4 == 0);
- CHECK(header_->method_ids_off % 4 == 0);
- CHECK(header_->class_defs_off % 4 == 0);
- CHECK(header_->map_off >= header_->data_off && header_->map_off < size_);
- CHECK(header_->link_size == 0);
- CHECK(header_->link_off == 0);
- CHECK(header_->data_off % 4 == 0);
- CHECK(header_->map_off % 4 == 0);
+ SLICER_CHECK(header_->string_ids_off % 4 == 0);
+ SLICER_CHECK(header_->type_ids_size < 65536);
+ SLICER_CHECK(header_->type_ids_off % 4 == 0);
+ SLICER_CHECK(header_->proto_ids_size < 65536);
+ SLICER_CHECK(header_->proto_ids_off % 4 == 0);
+ SLICER_CHECK(header_->field_ids_off % 4 == 0);
+ SLICER_CHECK(header_->method_ids_off % 4 == 0);
+ SLICER_CHECK(header_->class_defs_off % 4 == 0);
+ SLICER_CHECK(header_->map_off >= header_->data_off && header_->map_off < size_);
+ SLICER_CHECK(header_->link_size == 0);
+ SLICER_CHECK(header_->link_off == 0);
+ SLICER_CHECK(header_->data_off % 4 == 0);
+ SLICER_CHECK(header_->map_off % 4 == 0);
// we seem to have .dex files with extra bytes at the end ...
// Known issue: For performance reasons the initial size_ passed to jvmti events might be an
// estimate. b/72402467
- WEAK_CHECK(header_->data_off + header_->data_size <= size_);
+ SLICER_WEAK_CHECK(header_->data_off + header_->data_size <= size_);
// but we should still have the whole data section
// Known issue: The fields might be slighly corrupted b/65452964
// Known issue: For performance reasons the initial size_ passed to jvmti events might be an
// estimate. b/72402467
- // CHECK(header_->data_off + header_->data_size <= size_);
+ // SLICER_CHECK(header_->data_off + header_->data_size <= size_);
// validate the map
// (map section size = sizeof(MapList::size) + sizeof(MapList::list[size])
auto map_list = ptr<dex::MapList>(header_->map_off);
- CHECK(map_list->size > 0);
+ SLICER_CHECK(map_list->size > 0);
auto map_section_size =
sizeof(dex::u4) + sizeof(dex::MapItem) * map_list->size;
- CHECK(header_->map_off + map_section_size <= size_);
+ SLICER_CHECK(header_->map_off + map_section_size <= size_);
}
} // namespace dex
diff --git a/slicer/tryblocks_encoder.cc b/slicer/tryblocks_encoder.cc
index b1c9a8e..547e9d0 100644
--- a/slicer/tryblocks_encoder.cc
+++ b/slicer/tryblocks_encoder.cc
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "tryblocks_encoder.h"
-#include "chronometer.h"
-#include "common.h"
+#include "slicer/tryblocks_encoder.h"
+#include "slicer/chronometer.h"
+#include "slicer/common.h"
#include <assert.h>
@@ -25,8 +25,8 @@
bool TryBlocksEncoder::Visit(TryBlockEnd* try_end) {
const dex::u4 begin_offset = try_end->try_begin->offset;
const dex::u4 end_offset = try_end->offset;
- CHECK(end_offset > begin_offset);
- CHECK(end_offset - begin_offset < (1 << 16));
+ SLICER_CHECK(end_offset > begin_offset);
+ SLICER_CHECK(end_offset - begin_offset < (1 << 16));
// generate the "try_item"
dex::TryBlock try_block = {};
@@ -43,12 +43,12 @@
// type_idx
handlers_.PushULeb128(handler.ir_type->orig_index);
// address
- CHECK(handler.label->offset != kInvalidOffset);
+ SLICER_CHECK(handler.label->offset != kInvalidOffset);
handlers_.PushULeb128(handler.label->offset);
}
if (try_end->catch_all != nullptr) {
// address
- CHECK(try_end->catch_all->offset != kInvalidOffset);
+ SLICER_CHECK(try_end->catch_all->offset != kInvalidOffset);
handlers_.PushULeb128(try_end->catch_all->offset);
}
@@ -56,8 +56,8 @@
}
void TryBlocksEncoder::Encode(ir::Code* ir_code, std::shared_ptr<ir::DexFile> dex_ir) {
- CHECK(handlers_.empty());
- CHECK(tries_.empty());
+ SLICER_CHECK(handlers_.empty());
+ SLICER_CHECK(tries_.empty());
// first, count the number of try blocks
int tries_count = 0;
@@ -66,7 +66,7 @@
++tries_count;
}
}
- CHECK(tries_count < (1 << 16));
+ SLICER_CHECK(tries_count < (1 << 16));
// no try blocks?
if (tries_count == 0) {
@@ -91,8 +91,8 @@
for (auto instr : instructions_) {
instr->Accept(this);
}
- CHECK(!tries_.empty());
- CHECK(!handlers_.empty());
+ SLICER_CHECK(!tries_.empty());
+ SLICER_CHECK(!handlers_.empty());
tries_.Seal(1);
handlers_.Seal(1);
diff --git a/slicer/writer.cc b/slicer/writer.cc
index 1b55577..3361c70 100644
--- a/slicer/writer.cc
+++ b/slicer/writer.cc
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include "writer.h"
-#include "common.h"
-#include "scopeguard.h"
-#include "dex_bytecode.h"
-#include "dex_format.h"
-#include "dex_ir.h"
-#include "dex_leb128.h"
+#include "slicer/writer.h"
+#include "slicer/common.h"
+#include "slicer/scopeguard.h"
+#include "slicer/dex_bytecode.h"
+#include "slicer/dex_format.h"
+#include "slicer/dex_ir.h"
+#include "slicer/dex_leb128.h"
#include <assert.h>
#include <type_traits>
@@ -99,7 +99,7 @@
// "encoded_value"
static void WriteEncodedValue(const ir::EncodedValue* ir_value, Section& data) {
- EXTRA(auto offset = data.size());
+ SLICER_EXTRA(auto offset = data.size());
dex::u1 type = ir_value->type;
switch (type) {
@@ -171,12 +171,12 @@
} break;
default:
- CHECK(!"unexpected value type");
+ SLICER_CHECK(!"unexpected value type");
}
// optionally check the encoding against the original one
// (if possible, some of the values contain relocated indexes)
- EXTRA({
+ SLICER_EXTRA({
switch (type) {
case dex::kEncodedByte:
case dex::kEncodedShort:
@@ -189,8 +189,8 @@
case dex::kEncodedBoolean:
auto ptr = data.ptr<const dex::u1>(offset);
auto size = data.size() - offset;
- CHECK(size == ir_value->original.size());
- CHECK(memcmp(ptr, ir_value->original.ptr(), size) == 0);
+ SLICER_CHECK(size == ir_value->original.size());
+ SLICER_CHECK(memcmp(ptr, ir_value->original.ptr(), size) == 0);
break;
}
});
@@ -219,15 +219,15 @@
template <class T>
static void CopySection(const T& section, dex::u1* image, dex::u4 image_size) {
if (section.size() == 0) {
- CHECK(section.ItemsCount() == 0);
+ SLICER_CHECK(section.ItemsCount() == 0);
return;
}
- CHECK(section.ItemsCount() > 0);
+ SLICER_CHECK(section.ItemsCount() > 0);
dex::u4 offset = section.SectionOffset();
dex::u4 size = section.size();
- CHECK(offset >= sizeof(dex::Header));
- CHECK(offset + size <= image_size);
+ SLICER_CHECK(offset >= sizeof(dex::Header));
+ SLICER_CHECK(offset + size <= image_size);
::memcpy(image + offset, section.data(), size);
}
@@ -238,7 +238,7 @@
// create a new DexImage
dex_.reset(new DexImage);
- SCOPE_EXIT {
+ SLICER_SCOPE_EXIT {
dex_.reset();
};
@@ -260,7 +260,7 @@
offset += dex_->class_defs.Init(offset, dex_ir_->classes.size());
// the base offset for the "data" meta-section
- CHECK(offset % 4 == 0);
+ SLICER_CHECK(offset % 4 == 0);
const dex::u4 data_offset = offset;
// we must create the sections in a very specific
@@ -285,7 +285,7 @@
FillClassDefs();
// allocate the final buffer for the .dex image
- CHECK(offset % 4 == 0);
+ SLICER_CHECK(offset % 4 == 0);
const dex::u4 image_size = offset;
dex::u1* image = static_cast<dex::u1*>(allocator->Allocate(image_size));
if (image == nullptr) {
@@ -295,7 +295,7 @@
memset(image, 0, image_size);
// finally, back-fill the header
- CHECK(image_size > sizeof(dex::Header));
+ SLICER_CHECK(image_size > sizeof(dex::Header));
dex::Header* header = reinterpret_cast<dex::Header*>(image + 0);
@@ -374,7 +374,7 @@
template <class T>
static void AddMapItem(const T& section, std::vector<dex::MapItem>& items) {
if (section.ItemsCount() > 0) {
- CHECK(section.SectionOffset() >= sizeof(dex::Header));
+ SLICER_CHECK(section.SectionOffset() >= sizeof(dex::Header));
dex::MapItem map_item = {};
map_item.type = section.MapEntryType();
map_item.size = section.ItemsCount();
@@ -417,7 +417,7 @@
std::sort(map_items.begin(), map_items.end(),
[](const dex::MapItem& a, const dex::MapItem& b) {
- CHECK(a.offset != b.offset);
+ SLICER_CHECK(a.offset != b.offset);
return a.offset < b.offset;
});
@@ -434,7 +434,7 @@
if (ir_node->visibility != dex::kVisibilityEncoded) {
// TODO: factor out the node_offset_ updating
dex::u4& offset = node_offset_[ir_node.get()];
- CHECK(offset == 0);
+ SLICER_CHECK(offset == 0);
offset = WriteAnnotationItem(ir_node.get());
}
}
@@ -448,7 +448,7 @@
for (const auto& ir_node : dex_ir_->annotation_sets) {
dex::u4& offset = node_offset_[ir_node.get()];
- CHECK(offset == 0);
+ SLICER_CHECK(offset == 0);
offset = WriteAnnotationSet(ir_node.get());
}
@@ -461,7 +461,7 @@
for (const auto& ir_node : dex_ir_->annotation_set_ref_lists) {
dex::u4& offset = node_offset_[ir_node.get()];
- CHECK(offset == 0);
+ SLICER_CHECK(offset == 0);
offset = WriteAnnotationSetRefList(ir_node.get());
}
@@ -474,7 +474,7 @@
for (const auto& ir_type_list : dex_ir_->type_lists) {
dex::u4& offset = node_offset_[ir_type_list.get()];
- CHECK(offset == 0);
+ SLICER_CHECK(offset == 0);
offset = WriteTypeList(ir_type_list->types);
}
@@ -487,7 +487,7 @@
for (const auto& ir_node : dex_ir_->code) {
dex::u4& offset = node_offset_[ir_node.get()];
- CHECK(offset == 0);
+ SLICER_CHECK(offset == 0);
offset = WriteCode(ir_node.get());
}
@@ -501,7 +501,7 @@
for (const auto& ir_node : dex_ir_->debug_info) {
dex::u4& offset = node_offset_[ir_node.get()];
- CHECK(offset == 0);
+ SLICER_CHECK(offset == 0);
offset = WriteDebugInfo(ir_node.get());
}
@@ -637,7 +637,7 @@
// "annotation_item"
dex::u4 Writer::WriteAnnotationItem(const ir::Annotation* ir_annotation) {
- CHECK(ir_annotation->visibility != dex::kVisibilityEncoded);
+ SLICER_CHECK(ir_annotation->visibility != dex::kVisibilityEncoded);
auto& data = dex_->ann_items;
dex::u4 offset = data.AddItem();
@@ -648,7 +648,7 @@
// "annotation_set_item"
dex::u4 Writer::WriteAnnotationSet(const ir::AnnotationSet* ir_annotation_set) {
- CHECK(ir_annotation_set != nullptr);
+ SLICER_CHECK(ir_annotation_set != nullptr);
const auto& annotations = ir_annotation_set->annotations;
@@ -664,7 +664,7 @@
// "annotation_set_ref_list"
dex::u4 Writer::WriteAnnotationSetRefList(
const ir::AnnotationSetRefList* ir_annotation_set_ref_list) {
- CHECK(ir_annotation_set_ref_list != nullptr);
+ SLICER_CHECK(ir_annotation_set_ref_list != nullptr);
const auto& annotations = ir_annotation_set_ref_list->annotations;
@@ -740,7 +740,7 @@
// "debug_info_item"
dex::u4 Writer::WriteDebugInfo(const ir::DebugInfo* ir_debug_info) {
- CHECK(ir_debug_info != nullptr);
+ SLICER_CHECK(ir_debug_info != nullptr);
auto& data = dex_->debug_info;
dex::u4 offset = data.AddItem();
@@ -813,7 +813,7 @@
// instruction[] array
void Writer::WriteInstructions(slicer::ArrayView<const dex::u2> instructions) {
- CHECK(!instructions.empty());
+ SLICER_CHECK(!instructions.empty());
auto offset = dex_->code.Push(instructions);
dex::u2* ptr = dex_->code.ptr<dex::u2>(offset);
@@ -846,39 +846,39 @@
switch (dex::GetIndexTypeFromOpcode(opcode)) {
case dex::kIndexStringRef:
if (index32 != nullptr) {
- CHECK(index16 == nullptr);
+ SLICER_CHECK(index16 == nullptr);
dex::u4 new_index = MapStringIndex(*index32);
- CHECK(new_index != dex::kNoIndex);
+ SLICER_CHECK(new_index != dex::kNoIndex);
*index32 = new_index;
} else {
dex::u4 new_index = MapStringIndex(*index16);
- CHECK(new_index != dex::kNoIndex);
- CHECK(dex::u2(new_index) == new_index);
+ SLICER_CHECK(new_index != dex::kNoIndex);
+ SLICER_CHECK(dex::u2(new_index) == new_index);
*index16 = dex::u2(new_index);
}
break;
case dex::kIndexTypeRef: {
- CHECK(index32 == nullptr);
+ SLICER_CHECK(index32 == nullptr);
dex::u4 new_index = MapTypeIndex(*index16);
- CHECK(new_index != dex::kNoIndex);
- CHECK(dex::u2(new_index) == new_index);
+ SLICER_CHECK(new_index != dex::kNoIndex);
+ SLICER_CHECK(dex::u2(new_index) == new_index);
*index16 = dex::u2(new_index);
} break;
case dex::kIndexFieldRef: {
- CHECK(index32 == nullptr);
+ SLICER_CHECK(index32 == nullptr);
dex::u4 new_index = MapFieldIndex(*index16);
- CHECK(new_index != dex::kNoIndex);
- CHECK(dex::u2(new_index) == new_index);
+ SLICER_CHECK(new_index != dex::kNoIndex);
+ SLICER_CHECK(dex::u2(new_index) == new_index);
*index16 = dex::u2(new_index);
} break;
case dex::kIndexMethodRef: {
- CHECK(index32 == nullptr);
+ SLICER_CHECK(index32 == nullptr);
dex::u4 new_index = MapMethodIndex(*index16);
- CHECK(new_index != dex::kNoIndex);
- CHECK(dex::u2(new_index) == new_index);
+ SLICER_CHECK(new_index != dex::kNoIndex);
+ SLICER_CHECK(dex::u2(new_index) == new_index);
*index16 = dex::u2(new_index);
} break;
@@ -887,15 +887,15 @@
}
auto isize = dex::GetWidthFromBytecode(ptr);
- CHECK(isize > 0);
+ SLICER_CHECK(isize > 0);
ptr += isize;
}
- CHECK(ptr == end);
+ SLICER_CHECK(ptr == end);
}
// "try_item[] + encoded_catch_handler_list"
void Writer::WriteTryBlocks(const ir::Code* irCode) {
- CHECK(!irCode->try_blocks.empty());
+ SLICER_CHECK(!irCode->try_blocks.empty());
// use a temporary buffer to build the "encoded_catch_handler_list"
slicer::Buffer handlers_list;
@@ -941,14 +941,14 @@
for (dex::TryBlock& dex_try : slicer::ArrayView<dex::TryBlock>(
data.ptr<dex::TryBlock>(tries_offset), irCode->try_blocks.size())) {
dex::u2 new_Handler_offset = handlers_offset_map[dex_try.handler_off];
- CHECK(new_Handler_offset != 0);
+ SLICER_CHECK(new_Handler_offset != 0);
dex_try.handler_off = new_Handler_offset;
}
}
// "code_item"
dex::u4 Writer::WriteCode(const ir::Code* irCode) {
- CHECK(irCode != nullptr);
+ SLICER_CHECK(irCode != nullptr);
dex::Code dex_code = {};
dex_code.registers_size = irCode->registers;
@@ -973,9 +973,9 @@
void Writer::WriteEncodedField(const ir::EncodedField* ir_encoded_field,
dex::u4* base_index) {
dex::u4 index_delta = ir_encoded_field->decl->index;
- CHECK(index_delta != dex::kNoIndex);
+ SLICER_CHECK(index_delta != dex::kNoIndex);
if (*base_index != dex::kNoIndex) {
- CHECK(index_delta > *base_index);
+ SLICER_CHECK(index_delta > *base_index);
index_delta = index_delta - *base_index;
}
*base_index = ir_encoded_field->decl->index;
@@ -989,9 +989,9 @@
void Writer::WriteEncodedMethod(const ir::EncodedMethod* ir_encoded_method,
dex::u4* base_index) {
dex::u4 index_delta = ir_encoded_method->decl->index;
- CHECK(index_delta != dex::kNoIndex);
+ SLICER_CHECK(index_delta != dex::kNoIndex);
if (*base_index != dex::kNoIndex) {
- CHECK(index_delta > *base_index);
+ SLICER_CHECK(index_delta > *base_index);
index_delta = index_delta - *base_index;
}
*base_index = ir_encoded_method->decl->index;
@@ -1062,7 +1062,7 @@
dex::u4 Writer::MapStringIndex(dex::u4 index) const {
if (index != dex::kNoIndex) {
index = dex_ir_->strings_map.at(index)->index;
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
}
return index;
}
@@ -1071,7 +1071,7 @@
dex::u4 Writer::MapTypeIndex(dex::u4 index) const {
if (index != dex::kNoIndex) {
index = dex_ir_->types_map.at(index)->index;
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
}
return index;
}
@@ -1080,7 +1080,7 @@
dex::u4 Writer::MapFieldIndex(dex::u4 index) const {
if (index != dex::kNoIndex) {
index = dex_ir_->fields_map.at(index)->index;
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
}
return index;
}
@@ -1089,7 +1089,7 @@
dex::u4 Writer::MapMethodIndex(dex::u4 index) const {
if (index != dex::kNoIndex) {
index = dex_ir_->methods_map.at(index)->index;
- CHECK(index != dex::kNoIndex);
+ SLICER_CHECK(index != dex::kNoIndex);
}
return index;
}
@@ -1100,9 +1100,9 @@
return 0;
}
auto it = node_offset_.find(ir_node);
- CHECK(it != node_offset_.end());
+ SLICER_CHECK(it != node_offset_.end());
dex::u4 offset = it->second;
- CHECK(offset > 0);
+ SLICER_CHECK(offset > 0);
return offset;
}
diff --git a/testdata/expected/entry_hooks.mi b/testdata/expected/entry_hooks.mi
deleted file mode 100644
index 0e18d35..0000000
--- a/testdata/expected/entry_hooks.mi
+++ /dev/null
@@ -1,523 +0,0 @@
-
-method Base.<init>():void
-{
- .src "entryHooks.java"
- .line 27
- .prologue_end
- .line 27
- 0| move-object v0, v2
- .local v0, "this", Base
- 1| move-object v1, v0
- 2| invoke-direct {v1}, java.lang.Object.<init>():void
- 5| return-void
-}
-
-method Base.foo(int, java.lang.String):int
-{
- .params "?", "?"
- .src "entryHooks.java"
- .line 31
- .prologue_end
- .line 31
- 0| move-object v0, v10
- .local v0, "this", Base
- 1| move v1, v11
- .local v1, "x", int
- 2| move-object v2, v12
- .local v2, "msg", java.lang.String
- 3| sget-object v3, java.lang.System.out
- 5| const-string v4, "Base.foo(%d, '%s')\n"
- 7| const/4 v5, #+2 (0x00000002 | 2.80260e-45)
- 8| new-array v5, v5, java.lang.Object[]
- 10| move-object v9, v5
- 11| move-object v5, v9
- 12| move-object v6, v9
- 13| const/4 v7, #+0 (0x00000000 | 0.00000)
- 14| move v8, v1
- 15| invoke-static {v8}, java.lang.Integer.valueOf(int):java.lang.Integer
- 18| move-result-object v8
- 19| aput-object v8, v6, v7
- 21| move-object v9, v5
- 22| move-object v5, v9
- 23| move-object v6, v9
- 24| const/4 v7, #+1 (0x00000001 | 1.40130e-45)
- 25| move-object v8, v2
- 26| aput-object v8, v6, v7
- 28| invoke-virtual {v3,v4,v5}, java.io.PrintStream.printf(java.lang.String, java.lang.Object[]):java.io.PrintStream
- 31| move-result-object v3
- .line 32
- 32| move v3, v1
- 33| move v0, v3
- .end_local v0
- 34| return v0
-}
-
-method Derived.<init>():void
-{
- .src "entryHooks.java"
- .line 36
- .prologue_end
- .line 36
- 0| move-object v0, v2
- .local v0, "this", Derived
- 1| move-object v1, v0
- 2| invoke-direct {v1}, Base.<init>():void
- 5| return-void
-}
-
-method Derived.foo(int, java.lang.String):int
-{
- .params "?", "?"
- .src "entryHooks.java"
- .line 40
- .prologue_end
- .line 40
- 0| move-object v0, v10
- .local v0, "this", Derived
- 1| move v1, v11
- .local v1, "x", int
- 2| move-object v2, v12
- .local v2, "msg", java.lang.String
- 3| sget-object v3, java.lang.System.out
- 5| const-string v4, "Derived.foo(%d, '%s')\n"
- 7| const/4 v5, #+2 (0x00000002 | 2.80260e-45)
- 8| new-array v5, v5, java.lang.Object[]
- 10| move-object v9, v5
- 11| move-object v5, v9
- 12| move-object v6, v9
- 13| const/4 v7, #+0 (0x00000000 | 0.00000)
- 14| move v8, v1
- 15| invoke-static {v8}, java.lang.Integer.valueOf(int):java.lang.Integer
- 18| move-result-object v8
- 19| aput-object v8, v6, v7
- 21| move-object v9, v5
- 22| move-object v5, v9
- 23| move-object v6, v9
- 24| const/4 v7, #+1 (0x00000001 | 1.40130e-45)
- 25| move-object v8, v2
- 26| aput-object v8, v6, v7
- 28| invoke-virtual {v3,v4,v5}, java.io.PrintStream.printf(java.lang.String, java.lang.Object[]):java.io.PrintStream
- 31| move-result-object v3
- .line 41
- 32| move v3, v1
- 33| const/4 v4, #+2 (0x00000002 | 2.80260e-45)
- 34| mul-int/lit8 v3, v3, #+2 (0x00000002 | 2.80260e-45)
- 36| move v0, v3
- .end_local v0
- 37| return v0
-}
-
-method Target.<init>():void
-{
- .src "entryHooks.java"
- .line 45
- .prologue_end
- .line 45
- 0| move-object v0, v2
- .local v0, "this", Target
- 1| move-object v1, v0
- 2| invoke-direct {v1}, java.lang.Object.<init>():void
- 5| return-void
-}
-
-method Target.main(java.lang.String[]):void
-{
- .params "?"
- .src "entryHooks.java"
- .line 51
- .prologue_end
- .line 51
- 0| move-object v0, v8
- .local v0, "args", java.lang.String[]
- 1| sget-object v1, java.lang.System.out
- 3| const-string v2, "Hello, world!"
- 5| invoke-virtual {v1,v2}, java.io.PrintStream.println(java.lang.String):void
- .line 52
- 8| sget-object v1, java.lang.System.out
- 10| const-string v2, "final = %d\n"
- 12| const/4 v3, #+1 (0x00000001 | 1.40130e-45)
- 13| new-array v3, v3, java.lang.Object[]
- 15| move-object v7, v3
- 16| move-object v3, v7
- 17| move-object v4, v7
- 18| const/4 v5, #+0 (0x00000000 | 0.00000)
- 19| invoke-static {}, Target.test():int
- 22| move-result v6
- 23| invoke-static {v6}, java.lang.Integer.valueOf(int):java.lang.Integer
- 26| move-result-object v6
- 27| aput-object v6, v4, v5
- 29| invoke-virtual {v1,v2,v3}, java.io.PrintStream.printf(java.lang.String, java.lang.Object[]):java.io.PrintStream
- 32| move-result-object v1
- .line 53
- 33| sget-object v1, java.lang.System.out
- 35| const-string v2, "Good bye!"
- 37| invoke-virtual {v1,v2}, java.io.PrintStream.println(java.lang.String):void
- .line 54
- 40| return-void
-}
-
-method Target.test():int
-{
- .src "entryHooks.java"
- .line 58
- .prologue_end
- .line 58
- 0| new-instance v1, Target
- 2| move-object v4, v1
- 3| move-object v1, v4
- 4| move-object v2, v4
- 5| invoke-direct {v2}, Target.<init>():void
- 8| move-object v0, v1
- .line 59
- .local v0, "obj", Target
- 9| move-object v1, v0
- 10| new-instance v2, Derived
- 12| move-object v4, v2
- 13| move-object v2, v4
- 14| move-object v3, v4
- 15| invoke-direct {v3}, Derived.<init>():void
- 18| iput-object v2, v1, Target.test
- .line 60
- 20| move-object v1, v0
- 21| const/4 v2, #+3 (0x00000003 | 4.20390e-45)
- 22| const-string v3, "Testing..."
- 24| invoke-virtual {v1,v2,v3}, Target.foo(int, java.lang.String):int
- 27| move-result v1
- 28| move v0, v1
- .end_local v0
- 29| return v0
-}
-
-method Target.foo(int):int
-{
- .params "?"
- .src "entryHooks.java"
- .line 74
- .prologue_end
- .line 74
- 0| move-object v0, v3
- .local v0, "this", Target
- 1| move v1, v4
- .local v1, "x", int
- 2| const/4 v2, #+1 (0x00000001 | 1.40130e-45)
- 3| move v0, v2
- .end_local v0
- 4| return v0
-}
-
-method Target.foo(int, int):int
-{
- .params "?", "?"
- .src "entryHooks.java"
- .line 75
- .prologue_end
- .line 75
- 0| move-object v0, v4
- .local v0, "this", Target
- 1| move v1, v5
- .local v1, "x", int
- 2| move v2, v6
- .local v2, "y", int
- 3| const/4 v3, #+2 (0x00000002 | 2.80260e-45)
- 4| move v0, v3
- .end_local v0
- 5| return v0
-}
-
-method Target.foo(int, java.lang.String):int
-{
- .params "?", "?"
- .src "entryHooks.java"
- .line 65
- .prologue_end
- .line 65
- 0| invoke-static/range {v9..v11}, Tracer.onFooEntry(Target, int, java.lang.String):void
- 3| invoke-static/range {v9..v11}, Tracer.onFooEntry(java.lang.Object, int, java.lang.String):void
- 6| move-object v0, v9
- .local v0, "this", Target
- 7| move v1, v10
- .local v1, "x", int
- 8| move-object v2, v11
- .local v2, "msg", java.lang.String
- 9| const/4 v5, #+0 (0x00000000 | 0.00000)
- 10| move v3, v5
- .line 66
- .local v3, "sum", int
- 11| const/4 v5, #+0 (0x00000000 | 0.00000)
- 12| move v4, v5
-Label_1:
- .local v4, "i", int
- 13| move v5, v4
- 14| move v6, v1
- 15| if-ge v5, v6, Label_2
- .line 68
- 17| move v5, v3
- 18| move-object v6, v0
- 19| iget-object v6, v6, Target.test
- 21| move v7, v4
- 22| move-object v8, v2
- 23| invoke-static {v6,v7,v8}, Tracer.wrapFoo(Base, int, java.lang.String):int
- 26| move-result v6
- 27| add-int/2addr v5, v6
- 28| move v3, v5
- .line 66
- 29| add-int/lit8 v4, v4, #+1 (0x00000001 | 1.40130e-45)
- 31| goto/16 Label_1
-Label_2:
- .line 70
- 33| move v5, v3
- 34| move v0, v5
- .end_local v0
- 35| invoke-static/range {v0..v0}, Tracer.onFooExit(int):int
- 38| move-result v0
- 39| return v0
-}
-
-method Target.foo(int, java.lang.String, java.lang.String):int
-{
- .params "?", "?", "?"
- .src "entryHooks.java"
- .line 76
- .prologue_end
- .line 76
- 0| move-object v0, v5
- .local v0, "this", Target
- 1| move v1, v6
- .local v1, "x", int
- 2| move-object v2, v7
- .local v2, "msg", java.lang.String
- 3| move-object v3, v8
- .local v3, "msg2", java.lang.String
- 4| const/4 v4, #+3 (0x00000003 | 4.20390e-45)
- 5| move v0, v4
- .end_local v0
- 6| return v0
-}
-
-method Target.foo(int, java.lang.String[]):int
-{
- .params "?", "?"
- .src "entryHooks.java"
- .line 77
- .prologue_end
- .line 77
- 0| move-object v0, v4
- .local v0, "this", Target
- 1| move v1, v5
- .local v1, "x", int
- 2| move-object v2, v6
- .local v2, "msgs", java.lang.String[]
- 3| const/4 v3, #+4 (0x00000004 | 5.60519e-45)
- 4| move v0, v3
- .end_local v0
- 5| return v0
-}
-
-method Target.foo(int, java.lang.String[][]):java.lang.Integer
-{
- .params "?", "?"
- .src "entryHooks.java"
- .line 78
- .prologue_end
- .line 78
- 0| invoke-static/range {v4..v6}, Tracer.onFooEntry(Target, int, java.lang.String[][]):void
- 3| invoke-static/range {v4..v6}, Tracer.onFooEntry(java.lang.Object, int, java.lang.String[][]):void
- 6| move-object v0, v4
- .local v0, "this", Target
- 7| move v1, v5
- .local v1, "x", int
- 8| move-object v2, v6
- .local v2, "msgs", java.lang.String[][]
- 9| const/4 v3, #+5 (0x00000005 | 7.00649e-45)
- 10| invoke-static {v3}, java.lang.Integer.valueOf(int):java.lang.Integer
- 13| move-result-object v3
- 14| move-object v0, v3
- .end_local v0
- 15| invoke-static/range {v0..v0}, Tracer.onFooExit(java.lang.Integer):java.lang.Integer
- 18| move-result-object v0
- 19| return-object v0
-}
-
-method Target.foo():void
-{
- .src "entryHooks.java"
- .line 73
- .prologue_end
- .line 73
- 0| return-void
-}
-
-method Tracer.<init>():void
-{
- .src "entryHooks.java"
- .line 2
- .prologue_end
- .line 2
- 0| move-object v0, v2
- .local v0, "this", Tracer
- 1| move-object v1, v0
- 2| invoke-direct {v1}, java.lang.Object.<init>():void
- 5| return-void
-}
-
-method Tracer.onEntry(java.lang.String):void
-{
- .params "?"
- .src "entryHooks.java"
- .line 6
- .prologue_end
- .line 6
- 0| move-object v0, v5
- .local v0, "methodName", java.lang.String
- 1| sget-object v1, java.lang.System.out
- 3| new-instance v2, java.lang.StringBuilder
- 5| move-object v4, v2
- 6| move-object v2, v4
- 7| move-object v3, v4
- 8| invoke-direct {v3}, java.lang.StringBuilder.<init>():void
- 11| const-string v3, "OnEntry("
- 13| invoke-virtual {v2,v3}, java.lang.StringBuilder.append(java.lang.String):java.lang.StringBuilder
- 16| move-result-object v2
- 17| move-object v3, v0
- 18| invoke-virtual {v2,v3}, java.lang.StringBuilder.append(java.lang.String):java.lang.StringBuilder
- 21| move-result-object v2
- 22| const-string v3, ")"
- 24| invoke-virtual {v2,v3}, java.lang.StringBuilder.append(java.lang.String):java.lang.StringBuilder
- 27| move-result-object v2
- 28| invoke-virtual {v2}, java.lang.StringBuilder.toString():java.lang.String
- 31| move-result-object v2
- 32| invoke-virtual {v1,v2}, java.io.PrintStream.println(java.lang.String):void
- .line 7
- 35| return-void
-}
-
-method Tracer.onFooEntry(Target, int, java.lang.String):void
-{
- .params "?", "?", "?"
- .src "entryHooks.java"
- .line 11
- .prologue_end
- .line 11
- 0| move-object v0, v10
- .local v0, "__this", Target
- 1| move v1, v11
- .local v1, "x", int
- 2| move-object v2, v12
- .local v2, "msg", java.lang.String
- 3| sget-object v3, java.lang.System.out
- 5| const-string v4, ">>> onFooEntry(%s, %d, %s)\n"
- 7| const/4 v5, #+3 (0x00000003 | 4.20390e-45)
- 8| new-array v5, v5, java.lang.Object[]
- 10| move-object v9, v5
- 11| move-object v5, v9
- 12| move-object v6, v9
- 13| const/4 v7, #+0 (0x00000000 | 0.00000)
- 14| move-object v8, v0
- 15| aput-object v8, v6, v7
- 17| move-object v9, v5
- 18| move-object v5, v9
- 19| move-object v6, v9
- 20| const/4 v7, #+1 (0x00000001 | 1.40130e-45)
- 21| move v8, v1
- 22| invoke-static {v8}, java.lang.Integer.valueOf(int):java.lang.Integer
- 25| move-result-object v8
- 26| aput-object v8, v6, v7
- 28| move-object v9, v5
- 29| move-object v5, v9
- 30| move-object v6, v9
- 31| const/4 v7, #+2 (0x00000002 | 2.80260e-45)
- 32| move-object v8, v2
- 33| aput-object v8, v6, v7
- 35| invoke-virtual {v3,v4,v5}, java.io.PrintStream.printf(java.lang.String, java.lang.Object[]):java.io.PrintStream
- 38| move-result-object v3
- .line 12
- 39| return-void
-}
-
-method Tracer.onFooExit(int):int
-{
- .params "?"
- .src "entryHooks.java"
- .line 16
- .prologue_end
- .line 16
- 0| move v0, v8
- .local v0, "retValue", int
- 1| sget-object v1, java.lang.System.out
- 3| const-string v2, ">>> onFooExit(%d)\n"
- 5| const/4 v3, #+1 (0x00000001 | 1.40130e-45)
- 6| new-array v3, v3, java.lang.Object[]
- 8| move-object v7, v3
- 9| move-object v3, v7
- 10| move-object v4, v7
- 11| const/4 v5, #+0 (0x00000000 | 0.00000)
- 12| move v6, v0
- 13| invoke-static {v6}, java.lang.Integer.valueOf(int):java.lang.Integer
- 16| move-result-object v6
- 17| aput-object v6, v4, v5
- 19| invoke-virtual {v1,v2,v3}, java.io.PrintStream.printf(java.lang.String, java.lang.Object[]):java.io.PrintStream
- 22| move-result-object v1
- .line 17
- 23| move v1, v0
- 24| const/16 v2, #+100 (0x00000064 | 1.40130e-43)
- 26| add-int/lit8 v1, v1, #+100 (0x00000064 | 1.40130e-43)
- 28| move v0, v1
- .end_local v0
- 29| return v0
-}
-
-method Tracer.wrapFoo(Base, int, java.lang.String):int
-{
- .params "?", "?", "?"
- .src "entryHooks.java"
- .line 22
- .prologue_end
- .line 22
- 0| move-object v0, v10
- .local v0, "_this", Base
- 1| move v1, v11
- .local v1, "x", int
- 2| move-object v2, v12
- .local v2, "msg", java.lang.String
- 3| sget-object v3, java.lang.System.out
- 5| const-string v4, ">>> %s.test(%d, %s)\n"
- 7| const/4 v5, #+3 (0x00000003 | 4.20390e-45)
- 8| new-array v5, v5, java.lang.Object[]
- 10| move-object v9, v5
- 11| move-object v5, v9
- 12| move-object v6, v9
- 13| const/4 v7, #+0 (0x00000000 | 0.00000)
- 14| move-object v8, v0
- 15| invoke-virtual {v8}, java.lang.Object.getClass():java.lang.Class
- 18| move-result-object v8
- 19| invoke-virtual {v8}, java.lang.Class.getName():java.lang.String
- 22| move-result-object v8
- 23| aput-object v8, v6, v7
- 25| move-object v9, v5
- 26| move-object v5, v9
- 27| move-object v6, v9
- 28| const/4 v7, #+1 (0x00000001 | 1.40130e-45)
- 29| move v8, v1
- 30| invoke-static {v8}, java.lang.Integer.valueOf(int):java.lang.Integer
- 33| move-result-object v8
- 34| aput-object v8, v6, v7
- 36| move-object v9, v5
- 37| move-object v5, v9
- 38| move-object v6, v9
- 39| const/4 v7, #+2 (0x00000002 | 2.80260e-45)
- 40| move-object v8, v2
- 41| aput-object v8, v6, v7
- 43| invoke-virtual {v3,v4,v5}, java.io.PrintStream.printf(java.lang.String, java.lang.Object[]):java.io.PrintStream
- 46| move-result-object v3
- .line 23
- 47| move-object v3, v0
- 48| move v4, v1
- 49| move-object v5, v2
- 50| invoke-virtual {v3,v4,v5}, Base.foo(int, java.lang.String):int
- 53| move-result v3
- 54| const/16 v4, #+10 (0x0000000a | 1.40130e-44)
- 56| add-int/lit8 v3, v3, #+10 (0x0000000a | 1.40130e-44)
- 58| move v0, v3
- .end_local v0
- 59| return v0
-}
diff --git a/testdata/expected/mi.asm b/testdata/expected/mi.asm
new file mode 100644
index 0000000..aa56a6d
--- /dev/null
+++ b/testdata/expected/mi.asm
@@ -0,0 +1,77 @@
+
+method Base.<init>():void
+{
+ .src "Target.java"
+ .line 1
+ .prologue_end
+ .line 1
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ 3| return-void
+}
+
+method Base.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ .prologue_end
+ .line 3
+ 0| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 1| return v0
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ .prologue_end
+ .line 15
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ .line 16
+ 3| iput-object v1, v0, Target.base
+ .line 17
+ 5| iput-object v2, v0, Target.iBase
+ .line 18
+ 7| return-void
+}
+
+method Target.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ .prologue_end
+ .line 21
+ 0| iget-object v0, v2, Target.base
+ 2| invoke-virtual {v0,v3,v4}, Base.foo(int, java.lang.String):int
+ 5| move-result v0
+ .line 22
+ 6| iget-object v1, v2, Target.iBase
+ 8| invoke-interface {v1,v4}, IBase.bar(java.lang.String):void
+ .line 23
+ 11| return v0
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ .prologue_end
+ .line 27
+ 0| iget-object v0, v2, Target.base
+ 2| const-string v1, "foo"
+ 4| invoke-virtual {v0,v3,v1}, Base.foo(int, java.lang.String):int
+ .line 28
+ 7| iget-object v0, v2, Target.iBase
+ 9| const-string v1, "bar"
+ 11| invoke-interface {v0,v1}, IBase.bar(java.lang.String):void
+ .line 29
+ 14| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 15| return-object v0
+}
diff --git a/testdata/expected/mi.code_coverage b/testdata/expected/mi.code_coverage
new file mode 100644
index 0000000..3e62d18
--- /dev/null
+++ b/testdata/expected/mi.code_coverage
@@ -0,0 +1,134 @@
+ 1: mi=0 s=0 e=0
+ 2: mi=0 s=3 e=3
+ 3: mi=1 s=0 e=1
+ 4: mi=3 s=0 e=0
+ 5: mi=3 s=3 e=3
+ 6: mi=3 s=5 e=5
+ 7: mi=3 s=7 e=7
+ 8: mi=4 s=0 e=0
+ 9: mi=4 s=2 e=2
+ 10: mi=4 s=5 e=6
+ 11: mi=4 s=8 e=8
+ 12: mi=4 s=11 e=11
+ 13: mi=5 s=0 e=0
+ 14: mi=5 s=2 e=2
+ 15: mi=5 s=4 e=4
+ 16: mi=5 s=7 e=7
+ 17: mi=5 s=9 e=9
+ 18: mi=5 s=11 e=11
+ 19: mi=5 s=14 e=15
+
+method Base.<init>():void
+{
+ .src "Target.java"
+ .line 1
+ .prologue_end
+ .line 1
+ 0| const v0, #+1 (0x00000001 | 1.40130e-45)
+ 3| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 6| invoke-direct {v1}, java.lang.Object.<init>():void
+ 9| const v0, #+2 (0x00000002 | 2.80260e-45)
+ 12| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 15| return-void
+}
+
+method Base.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ .prologue_end
+ .line 3
+ 0| const v0, #+3 (0x00000003 | 4.20390e-45)
+ 3| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 6| const/4 v1, #+0 (0x00000000 | 0.00000)
+ 7| return v1
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ .prologue_end
+ .line 15
+ 0| const v0, #+4 (0x00000004 | 5.60519e-45)
+ 3| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 6| invoke-direct {v1}, java.lang.Object.<init>():void
+ .line 16
+ 9| const v0, #+5 (0x00000005 | 7.00649e-45)
+ 12| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 15| iput-object v2, v1, Target.base
+ .line 17
+ 17| const v0, #+6 (0x00000006 | 8.40779e-45)
+ 20| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 23| iput-object v3, v1, Target.iBase
+ .line 18
+ 25| const v0, #+7 (0x00000007 | 9.80909e-45)
+ 28| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 31| return-void
+}
+
+method Target.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ .prologue_end
+ .line 21
+ 0| const v0, #+8 (0x00000008 | 1.12104e-44)
+ 3| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 6| iget-object v1, v3, Target.base
+ 8| const v0, #+9 (0x00000009 | 1.26117e-44)
+ 11| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 14| invoke-virtual {v1,v4,v5}, Base.foo(int, java.lang.String):int
+ 17| move-result v1
+ 18| const v0, #+10 (0x0000000a | 1.40130e-44)
+ 21| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ .line 22
+ 24| iget-object v2, v3, Target.iBase
+ 26| const v0, #+11 (0x0000000b | 1.54143e-44)
+ 29| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 32| invoke-interface {v2,v5}, IBase.bar(java.lang.String):void
+ .line 23
+ 35| const v0, #+12 (0x0000000c | 1.68156e-44)
+ 38| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 41| return v1
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ .prologue_end
+ .line 27
+ 0| const v0, #+13 (0x0000000d | 1.82169e-44)
+ 3| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 6| iget-object v1, v3, Target.base
+ 8| const v0, #+14 (0x0000000e | 1.96182e-44)
+ 11| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 14| const-string v2, "foo"
+ 16| const v0, #+15 (0x0000000f | 2.10195e-44)
+ 19| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 22| invoke-virtual {v1,v4,v2}, Base.foo(int, java.lang.String):int
+ .line 28
+ 25| const v0, #+16 (0x00000010 | 2.24208e-44)
+ 28| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 31| iget-object v1, v3, Target.iBase
+ 33| const v0, #+17 (0x00000011 | 2.38221e-44)
+ 36| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 39| const-string v2, "bar"
+ 41| const v0, #+18 (0x00000012 | 2.52234e-44)
+ 44| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 47| invoke-interface {v1,v2}, IBase.bar(java.lang.String):void
+ .line 29
+ 50| const v0, #+19 (0x00000013 | 2.66247e-44)
+ 53| invoke-static/range {v0..v0}, CodeCoverage.TraceBasicBlock(int):void
+ 56| const/4 v1, #+0 (0x00000000 | 0.00000)
+ 57| return-object v1
+}
diff --git a/testdata/expected/mi.compact_cfg b/testdata/expected/mi.compact_cfg
new file mode 100644
index 0000000..89f860a
--- /dev/null
+++ b/testdata/expected/mi.compact_cfg
@@ -0,0 +1,87 @@
+
+method Base.<init>():void
+{
+............................. begin block 1 .............................
+ .src "Target.java"
+ .line 1
+ .prologue_end
+ .line 1
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ 3| return-void
+.............................. end block 1 ..............................
+}
+
+method Base.foo(int, java.lang.String):int
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ .prologue_end
+ .line 3
+ 0| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 1| return v0
+.............................. end block 1 ..............................
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ .prologue_end
+ .line 15
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ .line 16
+ 3| iput-object v1, v0, Target.base
+ .line 17
+ 5| iput-object v2, v0, Target.iBase
+ .line 18
+ 7| return-void
+.............................. end block 1 ..............................
+}
+
+method Target.foo(int, java.lang.String):int
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ .prologue_end
+ .line 21
+ 0| iget-object v0, v2, Target.base
+ 2| invoke-virtual {v0,v3,v4}, Base.foo(int, java.lang.String):int
+ 5| move-result v0
+ .line 22
+ 6| iget-object v1, v2, Target.iBase
+ 8| invoke-interface {v1,v4}, IBase.bar(java.lang.String):void
+ .line 23
+ 11| return v0
+.............................. end block 1 ..............................
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ .prologue_end
+ .line 27
+ 0| iget-object v0, v2, Target.base
+ 2| const-string v1, "foo"
+ 4| invoke-virtual {v0,v3,v1}, Base.foo(int, java.lang.String):int
+ .line 28
+ 7| iget-object v0, v2, Target.iBase
+ 9| const-string v1, "bar"
+ 11| invoke-interface {v0,v1}, IBase.bar(java.lang.String):void
+ .line 29
+ 14| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 15| return-object v0
+.............................. end block 1 ..............................
+}
diff --git a/testdata/expected/mi.map b/testdata/expected/mi.map
new file mode 100644
index 0000000..898d7ce
--- /dev/null
+++ b/testdata/expected/mi.map
@@ -0,0 +1,15 @@
+
+Sections summary: name, offset, size [count]
+ HeaderItem : 0, 70 [1]
+ StringIdItem : 70, 4c [19]
+ TypeIdItem : bc, 24 [9]
+ ProtoIdItem : e0, 3c [5]
+ FieldIdItem : 11c, 10 [2]
+ MethodIdItem : 12c, 38 [7]
+ ClassDefItem : 164, 60 [3]
+ CodeItem : 1c4, a4 [5]
+ TypeList : 268, 1e [4]
+ StringDataItem : 286, b3 [19]
+ DebugInfoItem : 339, 28 [5]
+ ClassDataItem : 361, 2f [3]
+ MapList : 390, a0 [1]
diff --git a/testdata/expected/mi.mi b/testdata/expected/mi.mi
new file mode 100644
index 0000000..dd61327
--- /dev/null
+++ b/testdata/expected/mi.mi
@@ -0,0 +1,85 @@
+
+method Base.<init>():void
+{
+ .src "Target.java"
+ .line 1
+ .prologue_end
+ .line 1
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ 3| return-void
+}
+
+method Base.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ .prologue_end
+ .line 3
+ 0| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 1| return v0
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ .prologue_end
+ .line 15
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ .line 16
+ 3| iput-object v1, v0, Target.base
+ .line 17
+ 5| iput-object v2, v0, Target.iBase
+ .line 18
+ 7| return-void
+}
+
+method Target.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ .prologue_end
+ .line 21
+ 0| invoke-static/range {v2..v4}, Tracer.onFooEntry(Target, int, java.lang.String):void
+ 3| invoke-static/range {v2..v4}, Tracer.onFooEntry(java.lang.Object, int, java.lang.String):void
+ 6| iget-object v0, v2, Target.base
+ 8| invoke-static {v0,v3,v4}, Tracer.wrapFoo(Base, int, java.lang.String):int
+ 11| move-result v0
+ .line 22
+ 12| iget-object v1, v2, Target.iBase
+ 14| invoke-static {v1,v4}, Tracer.wrapBar(IBase, java.lang.String):void
+ .line 23
+ 17| invoke-static/range {v0..v0}, Tracer.onFooExit(int):int
+ 20| move-result v0
+ 21| return v0
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ .prologue_end
+ .line 27
+ 0| invoke-static/range {v2..v4}, Tracer.onFooEntry(Target, int, java.lang.String[][]):void
+ 3| invoke-static/range {v2..v4}, Tracer.onFooEntry(java.lang.Object, int, java.lang.String[][]):void
+ 6| iget-object v0, v2, Target.base
+ 8| const-string v1, "foo"
+ 10| invoke-static {v0,v3,v1}, Tracer.wrapFoo(Base, int, java.lang.String):int
+ .line 28
+ 13| iget-object v0, v2, Target.iBase
+ 15| const-string v1, "bar"
+ 17| invoke-static {v0,v1}, Tracer.wrapBar(IBase, java.lang.String):void
+ .line 29
+ 20| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 21| invoke-static/range {v0..v0}, Tracer.onFooExit(java.lang.Integer):java.lang.Integer
+ 24| move-result-object v0
+ 25| return-object v0
+}
diff --git a/testdata/expected/mi.regs_usage b/testdata/expected/mi.regs_usage
new file mode 100644
index 0000000..cb1b4b8
--- /dev/null
+++ b/testdata/expected/mi.regs_usage
@@ -0,0 +1,19 @@
+
+Histogram: Method registers [max_count=2]
+
+ 1 [ 1 ] ***************************************************
+ 1 [ 3 ] ***************************************************
+ 1 [ 4 ] ***************************************************
+ 2 [ 5 ] *****************************************************************************************************
+
+Histogram: Method parameter registers [max_count=4]
+
+ 1 [ 1 ] **************************
+ 4 [ 3 ] *****************************************************************************************************
+
+Histogram: Method extra registers (total - parameters) [max_count=2]
+
+ 1 [ 1 ] ***************************************************
+ 1 [ 3 ] ***************************************************
+ 1 [ 4 ] ***************************************************
+ 2 [ 5 ] *****************************************************************************************************
diff --git a/testdata/expected/mi.rewrite b/testdata/expected/mi.rewrite
new file mode 100644
index 0000000..aa56a6d
--- /dev/null
+++ b/testdata/expected/mi.rewrite
@@ -0,0 +1,77 @@
+
+method Base.<init>():void
+{
+ .src "Target.java"
+ .line 1
+ .prologue_end
+ .line 1
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ 3| return-void
+}
+
+method Base.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ .prologue_end
+ .line 3
+ 0| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 1| return v0
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ .prologue_end
+ .line 15
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+ .line 16
+ 3| iput-object v1, v0, Target.base
+ .line 17
+ 5| iput-object v2, v0, Target.iBase
+ .line 18
+ 7| return-void
+}
+
+method Target.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ .prologue_end
+ .line 21
+ 0| iget-object v0, v2, Target.base
+ 2| invoke-virtual {v0,v3,v4}, Base.foo(int, java.lang.String):int
+ 5| move-result v0
+ .line 22
+ 6| iget-object v1, v2, Target.iBase
+ 8| invoke-interface {v1,v4}, IBase.bar(java.lang.String):void
+ .line 23
+ 11| return v0
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ .prologue_end
+ .line 27
+ 0| iget-object v0, v2, Target.base
+ 2| const-string v1, "foo"
+ 4| invoke-virtual {v0,v3,v1}, Base.foo(int, java.lang.String):int
+ .line 28
+ 7| iget-object v0, v2, Target.iBase
+ 9| const-string v1, "bar"
+ 11| invoke-interface {v0,v1}, IBase.bar(java.lang.String):void
+ .line 29
+ 14| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 15| return-object v0
+}
diff --git a/testdata/expected/mi.scratch_regs b/testdata/expected/mi.scratch_regs
new file mode 100644
index 0000000..4618658
--- /dev/null
+++ b/testdata/expected/mi.scratch_regs
@@ -0,0 +1,116 @@
+
+method Base.<init>():void
+{
+ .src "Target.java"
+ .line 1
+ 0| move-object/16 v15, v23
+ 3| move-object/16 v14, v15
+ 6| move-object/16 v13, v14
+ .prologue_end
+ .line 1
+ 9| invoke-direct {v13}, java.lang.Object.<init>():void
+ 12| return-void
+}
+
+method Base.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ 0| move-object/16 v13, v24
+ 3| move/16 v14, v25
+ 6| move-object/16 v15, v26
+ 9| move-object/16 v12, v13
+ 12| move/16 v13, v14
+ 15| move-object/16 v14, v15
+ 18| move-object/16 v11, v12
+ 21| move/16 v12, v13
+ 24| move-object/16 v13, v14
+ .prologue_end
+ .line 3
+ 27| const/4 v10, #+0 (0x00000000 | 0.00000)
+ 28| return v10
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ 0| move-object/16 v13, v23
+ 3| move-object/16 v14, v24
+ 6| move-object/16 v15, v25
+ 9| move-object/16 v12, v13
+ 12| move-object/16 v13, v14
+ 15| move-object/16 v14, v15
+ 18| move-object/16 v11, v12
+ 21| move-object/16 v12, v13
+ 24| move-object/16 v13, v14
+ .prologue_end
+ .line 15
+ 27| invoke-direct {v11}, java.lang.Object.<init>():void
+ .line 16
+ 30| iput-object v12, v11, Target.base
+ .line 17
+ 32| iput-object v13, v11, Target.iBase
+ .line 18
+ 34| return-void
+}
+
+method Target.foo(int, java.lang.String):int
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ 0| move-object/16 v13, v25
+ 3| move/16 v14, v26
+ 6| move-object/16 v15, v27
+ 9| move-object/16 v12, v13
+ 12| move/16 v13, v14
+ 15| move-object/16 v14, v15
+ 18| move-object/16 v11, v12
+ 21| move/16 v12, v13
+ 24| move-object/16 v13, v14
+ .prologue_end
+ .line 21
+ 27| iget-object v9, v11, Target.base
+ 29| invoke-virtual {v9,v12,v13}, Base.foo(int, java.lang.String):int
+ 32| move-result v9
+ .line 22
+ 33| iget-object v10, v11, Target.iBase
+ 35| invoke-interface {v10,v13}, IBase.bar(java.lang.String):void
+ .line 23
+ 38| return v9
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ 0| move-object/16 v13, v25
+ 3| move/16 v14, v26
+ 6| move-object/16 v15, v27
+ 9| move-object/16 v12, v13
+ 12| move/16 v13, v14
+ 15| move-object/16 v14, v15
+ 18| move-object/16 v11, v12
+ 21| move/16 v12, v13
+ 24| move-object/16 v13, v14
+ .prologue_end
+ .line 27
+ 27| iget-object v9, v11, Target.base
+ 29| const-string v10, "foo"
+ 31| invoke-virtual {v9,v12,v10}, Base.foo(int, java.lang.String):int
+ .line 28
+ 34| iget-object v9, v11, Target.iBase
+ 36| const-string v10, "bar"
+ 38| invoke-interface {v9,v10}, IBase.bar(java.lang.String):void
+ .line 29
+ 41| const/4 v9, #+0 (0x00000000 | 0.00000)
+ 42| return-object v9
+}
diff --git a/testdata/expected/mi.stats b/testdata/expected/mi.stats
new file mode 100644
index 0000000..e93aaf7
--- /dev/null
+++ b/testdata/expected/mi.stats
@@ -0,0 +1,37 @@
+
+.dex file statistics:
+ file_size : 1072
+ data_size : 620
+ link_size : 0
+ class_defs_size : 3
+ string_ids_size : 19
+ type_ids_size : 9
+ proto_ids_size : 5
+ field_ids_size : 2
+ method_ids_size : 7
+ map_list_size : 13
+
+
+.dex IR statistics:
+ strings : 19
+ types : 9
+ protos : 5
+ fields : 2
+ encoded_fields : 2
+ methods : 7
+ encoded_methods : 6
+ classes : 3
+ type_lists : 4
+ code : 5
+ debug_info : 5
+ encoded_values : 0
+ encoded_arrays : 0
+ annotations : 0
+ annotation_elements : 0
+ annotation_sets : 0
+ annotation_set_ref_lists : 0
+ annotations_directories : 0
+ field_annotations : 0
+ method_annotations : 0
+ param_annotations : 0
+
diff --git a/testdata/expected/mi.verbose_cfg b/testdata/expected/mi.verbose_cfg
new file mode 100644
index 0000000..45032a9
--- /dev/null
+++ b/testdata/expected/mi.verbose_cfg
@@ -0,0 +1,115 @@
+
+method Base.<init>():void
+{
+............................. begin block 1 .............................
+ .src "Target.java"
+ .line 1
+ .prologue_end
+ .line 1
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+.............................. end block 1 ..............................
+............................. begin block 2 .............................
+ 3| return-void
+.............................. end block 2 ..............................
+}
+
+method Base.foo(int, java.lang.String):int
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 3
+ .prologue_end
+ .line 3
+ 0| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 1| return v0
+.............................. end block 1 ..............................
+}
+
+method IBase.bar(java.lang.String):void
+{
+}
+
+method Target.<init>(Base, IBase):void
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 15
+ .prologue_end
+ .line 15
+ 0| invoke-direct {v0}, java.lang.Object.<init>():void
+.............................. end block 1 ..............................
+............................. begin block 2 .............................
+ .line 16
+ 3| iput-object v1, v0, Target.base
+.............................. end block 2 ..............................
+............................. begin block 3 .............................
+ .line 17
+ 5| iput-object v2, v0, Target.iBase
+.............................. end block 3 ..............................
+............................. begin block 4 .............................
+ .line 18
+ 7| return-void
+.............................. end block 4 ..............................
+}
+
+method Target.foo(int, java.lang.String):int
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 21
+ .prologue_end
+ .line 21
+ 0| iget-object v0, v2, Target.base
+.............................. end block 1 ..............................
+............................. begin block 2 .............................
+ 2| invoke-virtual {v0,v3,v4}, Base.foo(int, java.lang.String):int
+.............................. end block 2 ..............................
+............................. begin block 3 .............................
+ 5| move-result v0
+ .line 22
+ 6| iget-object v1, v2, Target.iBase
+.............................. end block 3 ..............................
+............................. begin block 4 .............................
+ 8| invoke-interface {v1,v4}, IBase.bar(java.lang.String):void
+.............................. end block 4 ..............................
+............................. begin block 5 .............................
+ .line 23
+ 11| return v0
+.............................. end block 5 ..............................
+}
+
+method Target.foo(int, java.lang.String[][]):java.lang.Integer
+{
+............................. begin block 1 .............................
+ .params "?", "?"
+ .src "Target.java"
+ .line 27
+ .prologue_end
+ .line 27
+ 0| iget-object v0, v2, Target.base
+.............................. end block 1 ..............................
+............................. begin block 2 .............................
+ 2| const-string v1, "foo"
+.............................. end block 2 ..............................
+............................. begin block 3 .............................
+ 4| invoke-virtual {v0,v3,v1}, Base.foo(int, java.lang.String):int
+.............................. end block 3 ..............................
+............................. begin block 4 .............................
+ .line 28
+ 7| iget-object v0, v2, Target.iBase
+.............................. end block 4 ..............................
+............................. begin block 5 .............................
+ 9| const-string v1, "bar"
+.............................. end block 5 ..............................
+............................. begin block 6 .............................
+ 11| invoke-interface {v0,v1}, IBase.bar(java.lang.String):void
+.............................. end block 6 ..............................
+............................. begin block 7 .............................
+ .line 29
+ 14| const/4 v0, #+0 (0x00000000 | 0.00000)
+ 15| return-object v0
+.............................. end block 7 ..............................
+}
diff --git a/testdata/mi.dex b/testdata/mi.dex
new file mode 100644
index 0000000..a00abb3
--- /dev/null
+++ b/testdata/mi.dex
Binary files differ