Skip to content

Commit

Permalink
check to see if resuming another trace inappropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewfl committed Aug 26, 2016
1 parent c18153f commit c11a7aa
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 82 deletions.
10 changes: 9 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ license: LGPLv3
build instructions:
pacman -S strace python2
git submodules update --init --recursive
./make release
./make release


build python:
cd cpython
ln -s ../redmagic/src/redmagic.h .
ln -s ../redmagic/build/libredmagic.so.* .
./configure --with-pydebug --prefix=/usr
make
5 changes: 5 additions & 0 deletions src/jit_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ namespace redmagic {
bool is_temp_disabled = false;
bool is_traced = false;
bool is_compiled = false;

// when this frame is poped if it should use the return address in the frame above it
// essentially if this frame was created from a tracer
bool return_to_trace_when_done = false;

int32_t frame_id = -1;


Expand Down
4 changes: 4 additions & 0 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ int main(int argc, char* argv[]) {

float a = 1.2;

redmagic_begin_branchable_frame(NULL);

while(1) {
switch(program[pc]) {
case PRINT_NUM:
Expand Down Expand Up @@ -102,6 +104,8 @@ int main(int argc, char* argv[]) {
}
}

redmagic_end_branchable_frame(NULL);


// redmagic_force_begin_trace((void*)123);

Expand Down
173 changes: 94 additions & 79 deletions src/manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,22 @@ extern "C" void* red_user_end_merge_block(void *_, void *ret_addr) {
extern "C" void* red_user_begin_branchable_frame(uint64_t *frame_id, void *ret_addr) {
UnprotectMalloc upm;
branchable_frame_id++;
#ifndef NDEBUG
if(frame_id != NULL) {
*frame_id = 0xdead0000 | branchable_frame_id;
}
#endif
return NULL;
}

extern "C" void* red_user_end_branchable_frame(uint64_t *frame_id, void *ret_addr, void **stack_ptr) {
UnprotectMalloc upm;
// TODO: less of a hack, issue when call multiple times in a row
#ifndef NDEBUG
if(frame_id != NULL && (void**)frame_id - stack_ptr > 0) {
assert(*frame_id == 0xdead0000 | branchable_frame_id);
}
#endif
return manager->end_branchable_frame(ret_addr, stack_ptr);
}

Expand Down Expand Up @@ -402,94 +406,97 @@ uint32_t Manager::get_thread_id() {

void* Manager::begin_trace(void *id, void *ret_addr) {
assert(0); // TODO: rewrite this method
return NULL;

branch_info *info = &branches[id];
if(info->disabled)
return NULL; // do not trace this loop

auto old_head = get_tracer_head();

void *trace_pc = ret_addr;

void *ret;
Tracer *l;
{
// assert(old_head->tracer == nullptr); // TODO: in the future allow for nesting tracers, since there might be an inner loop
if(old_head->tracer) {
if(old_head->tracer->did_abort) {
red_printf("won't subtrace since there was an abort\n");
} else {
assert(old_head->resume_addr == nullptr);
old_head->tracer->JumpToNestedLoop(id);
trace_pc = (void*)old_head->tracer->get_pc();
assert(old_head->resume_addr != nullptr);
}
}
auto new_head = push_tracer_stack();

//assert(tracer == nullptr);
assert(info->tracer == nullptr || info->tracer->did_abort);
assert(info->starting_point == nullptr);

//auto buff = make_shared<CodeBuffer>(4 * 1024 * 1024);
auto buff = CodeBuffer::CreateBuffer(1024 * 1024);
new_head->tracer = l = new Tracer(buff);
l->tracing_from = (mem_loc_t)trace_pc;
l->owning_thread = get_thread_id();
l->owning_frame_id = branchable_frame_id;
// int r = mprotect(this, 4*1024, PROT_READ | PROT_WRITE);
// assert(!r);
info->tracer = l;


// r = mprotect(this, 4*1024, PROT_NONE);
// assert(!r);

new_head->trace_id = id;
ret = l->Start(trace_pc);
new_head->is_traced = true;
assert(info->trace_loop_counter == nullptr);
info->starting_point = l->get_start_location();
info->trace_loop_counter = l->get_loop_counter();
}
//return NULL;
return ret;
// branch_info *info = &branches[id];
// if(info->disabled)
// return NULL; // do not trace this loop

// auto old_head = get_tracer_head();

// void *trace_pc = ret_addr;

// void *ret;
// Tracer *l;
// {
// // assert(old_head->tracer == nullptr); // TODO: in the future allow for nesting tracers, since there might be an inner loop
// if(old_head->tracer) {
// if(old_head->tracer->did_abort) {
// red_printf("won't subtrace since there was an abort\n");
// } else {
// assert(old_head->resume_addr == nullptr);
// old_head->tracer->JumpToNestedLoop(id);
// trace_pc = (void*)old_head->tracer->get_pc();
// assert(old_head->resume_addr != nullptr);
// }
// }
// auto new_head = push_tracer_stack();

// //assert(tracer == nullptr);
// assert(info->tracer == nullptr || info->tracer->did_abort);
// assert(info->starting_point == nullptr);

// //auto buff = make_shared<CodeBuffer>(4 * 1024 * 1024);
// auto buff = CodeBuffer::CreateBuffer(1024 * 1024);
// new_head->tracer = l = new Tracer(buff);
// l->tracing_from = (mem_loc_t)trace_pc;
// l->owning_thread = get_thread_id();
// l->owning_frame_id = branchable_frame_id;
// // int r = mprotect(this, 4*1024, PROT_READ | PROT_WRITE);
// // assert(!r);
// info->tracer = l;


// // r = mprotect(this, 4*1024, PROT_NONE);
// // assert(!r);

// new_head->trace_id = id;
// ret = l->Start(trace_pc);
// new_head->is_traced = true;
// assert(info->trace_loop_counter == nullptr);
// info->starting_point = l->get_start_location();
// info->trace_loop_counter = l->get_loop_counter();
// }
// //return NULL;
// return ret;
}

extern "C" void* red_end_trace(mem_loc_t);

void* Manager::end_trace(void *id, void *ret_addr) {
assert(0); // TODO: rewrite this method

void *ret;
Tracer *l;
auto head = get_tracer_head();
branch_info *info = &branches[id];
if(!head->tracer /*|| head->did_abort*/) {
// then we weren't actually running on the tracer
return red_end_trace((mem_loc_t)ret_addr);
}
assert(!info->disabled);
assert(head->trace_id == id);
assert(head->tracer == info->tracer);
l = head->tracer;

// poping of the head will tracer stack will be taken care of by the tracer
// ret is going to be the address of the normal execution
ret = l->EndTraceFallthrough();
//l->tracing_from.store(0); // not needed

info->tracer = head->tracer = nullptr;
return NULL;

Tracer *expected = nullptr;
if(!free_tracer_list.compare_exchange_strong(expected, l)) {
// failled to save the tracer to the free list head
delete l;
}
// void *ret;
// Tracer *l;
// auto head = get_tracer_head();
// branch_info *info = &branches[id];
// if(!head->tracer /*|| head->did_abort*/) {
// // then we weren't actually running on the tracer
// return red_end_trace((mem_loc_t)ret_addr);
// }
// assert(!info->disabled);
// assert(head->trace_id == id);
// assert(head->tracer == info->tracer);
// l = head->tracer;

// // poping of the head will tracer stack will be taken care of by the tracer
// // ret is going to be the address of the normal execution
// ret = l->EndTraceFallthrough();
// //l->tracing_from.store(0); // not needed

// info->tracer = head->tracer = nullptr;

// Tracer *expected = nullptr;
// if(!free_tracer_list.compare_exchange_strong(expected, l)) {
// // failled to save the tracer to the free list head
// delete l;
// }


//return NULL;
return ret;
// //return NULL;
// return ret;
}

void* Manager::jump_to_trace(void *id) {
Expand All @@ -503,6 +510,8 @@ void* Manager::backwards_branch(void *id, void *ret_addr) {
if(id == nullptr)
return NULL;

assert(branchable_frame_id >= 0);

tracer_stack_state* head = get_tracer_head();
tracer_stack_state* new_head = nullptr;
Tracer *l;
Expand Down Expand Up @@ -559,6 +568,9 @@ void* Manager::backwards_branch(void *id, void *ret_addr) {
}
new_head = push_tracer_stack();
head = &threadl_tracer_stack[threadl_tracer_stack.size() - 2];
if(head->tracer) {
new_head->return_to_trace_when_done = true;
}
new_head->trace_id = id;
if(info->starting_point) {
info->count++;
Expand Down Expand Up @@ -688,9 +700,10 @@ void* Manager::fellthrough_branch(void *id, void *ret_addr) {
assert(head->resume_addr == nullptr);
assert(head->is_temp_disabled == false);
// we have to pop this frame since we weren't being traced and there is nothing that will do it for us
pop_tracer_stack();
auto old_head = pop_tracer_stack();
auto new_head = get_tracer_head();
if(new_head->resume_addr) {
assert(old_head.return_to_trace_when_done);
if(new_head->tracer) {
// ret_addr will not be a traced address but a real normal address
// so we set that as the possible resume address if there is a tracer that we are going to be resuming
Expand Down Expand Up @@ -755,6 +768,7 @@ void* Manager::temp_enable(void *ret_addr) {
head->tracer->TempEnableTrace(ret_addr);
}
if(head->resume_addr != nullptr) {
assert(old_head.return_to_trace_when_done);
ret = head->resume_addr;
head->resume_addr = nullptr;
}
Expand Down Expand Up @@ -881,12 +895,13 @@ void* Manager::end_branchable_frame(void *ret_addr, void **stack_ptr) {
auto info = &branches[head->trace_id];
info->count_fellthrough++;
}
pop_tracer_stack();
auto old_head = pop_tracer_stack();
head = get_tracer_head();

if(head->resume_addr) {
// assert that this is a call instruction
assert(((uint8_t*)ret_addr)[-5] == 0xE8);
assert(old_head.return_to_trace_when_done);

if(head->tracer) {
head->tracer->JumpFromNestedLoop((uint8_t*)ret_addr - 5); // backup the pc to the call instruction
Expand Down
6 changes: 5 additions & 1 deletion src/tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ extern "C" void red_set_temp_resume(void *resume_addr) {
assert(head->resume_addr == nullptr);
head->resume_addr = resume_addr;
head->is_temp_disabled = true;
manager->push_tracer_stack();
auto new_head = manager->push_tracer_stack();
new_head->return_to_trace_when_done = true;
}

extern "C" void* red_end_trace(mem_loc_t normal_end_address) {
Expand All @@ -205,6 +206,7 @@ extern "C" void* red_end_trace(mem_loc_t normal_end_address) {
new_head->tracer->JumpFromNestedLoop((void*)normal_end_address);
}
if(new_head->resume_addr) {
assert(head.return_to_trace_when_done);
ret = new_head->resume_addr;
new_head->resume_addr = nullptr;
} else {
Expand Down Expand Up @@ -242,6 +244,8 @@ extern "C" void* red_branch_to_sub_trace(void *resume_addr, void *sub_trace_id,
protected_malloc = false;
void *ret = manager->backwards_branch(sub_trace_id, target_rip);
protected_malloc = true;
auto new_head = manager->get_tracer_head();
new_head->return_to_trace_when_done = true;
return ret;

}
Expand Down
2 changes: 1 addition & 1 deletion tools/gdb-helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def get_rip():
class LocateFirstValue(gdb.Command):

def __init__(self):
super().__init__("local-first-value", gdb.COMMAND_USER)
super().__init__("locate-first-value", gdb.COMMAND_USER)

def invoke(self, args, from_tty):
argv = gdb.string_to_argv(args)
Expand Down

0 comments on commit c11a7aa

Please sign in to comment.