예제 #1
0
//------------------------------------------------------------------------------
// Name: resolve_function_call
// Desc:
//------------------------------------------------------------------------------
Result<QString> CommentServer::resolve_function_call(QHexView::address_t address) const {
	
	// ok, we now want to locate the instruction before this one
	// so we need to look back a few bytes
	quint8 buffer[edb::Instruction::MAX_SIZE];

	// TODO(eteran): portability warning, makes assumptions on the size of a call
	if(IProcess *process = edb::v1::debugger_core->process()) {
		if(process->read_bytes(address - CALL_MAX_SIZE, buffer, sizeof(buffer))) {
			for(int i = (CALL_MAX_SIZE - CALL_MIN_SIZE); i >= 0; --i) {
				edb::Instruction inst(buffer + i, buffer + sizeof(buffer), 0);
				if(is_call(inst)) {
					const QString symname = edb::v1::find_function_symbol(address);
					
					if(!symname.isEmpty()) {
						return edb::v1::make_result(tr("return to %1 <%2>").arg(edb::v1::format_pointer(address)).arg(symname));
					} else {
						return edb::v1::make_result(tr("return to %1").arg(edb::v1::format_pointer(address)));
					}
				}
			}
		}
	}

	return Result<QString>(tr("Failed to resolve function call"), tr(""));
}
예제 #2
0
//------------------------------------------------------------------------------
// Name: get_call_stack
// Desc: Gets the state of the call stack at the time the object is created.
//------------------------------------------------------------------------------
void CallStack::get_call_stack() {
	/*
	 * Is rbp a pointer somewhere in the stack?
	 * Is the value below rbp a ret addr?
	 * Are we still scanning within the stack region?
	 */

	//Get the frame & stack pointers.
	State state;
	edb::v1::debugger_core->get_state(&state);
	edb::address_t rbp = state.frame_pointer();
	edb::address_t rsp = state.stack_pointer();

	//Check the alignment.  rbp and rsp should be aligned to the stack.
	if (rbp % edb::v1::pointer_size() != 0 ||
			rsp % edb::v1::pointer_size() != 0)
	{
		return;
	}

	//Make sure frame pointer is pointing in the same region as stack pointer.
	//If not, then it's being used as a GPR, and we don't have enough info.
	//This assumes the stack pointer is always pointing somewhere in the stack.
	IRegion::pointer region_rsp, region_rbp;
	edb::v1::memory_regions().sync();
	region_rsp = edb::v1::memory_regions().find_region(rsp);
	region_rbp = edb::v1::memory_regions().find_region(rbp);
	if (!region_rsp || !region_rbp || (region_rbp != region_rsp) ) {
		return;
	}

	//But if we're good, then scan from rbp downward and look for return addresses.
	//Code is largely from CommentServer.cpp.  Makes assumption of size of call.
	const quint8 CALL_MIN_SIZE = 2, CALL_MAX_SIZE = 7;
	quint8 buffer[edb::Instruction::MAX_SIZE];
	for (edb::address_t addr = rbp; region_rbp->contains(addr); addr += edb::v1::pointer_size()) {

		//Get the stack value so that we can see if it's a pointer
		bool ok;
		ExpressionError err;
		edb::address_t possible_ret = edb::v1::get_value(addr, &ok, &err);

		if(IProcess *process = edb::v1::debugger_core->process()) {
			if(process->read_bytes(possible_ret - CALL_MAX_SIZE, buffer, sizeof(buffer))) {	//0xfffff... if not a ptr.
				for(int i = (CALL_MAX_SIZE - CALL_MIN_SIZE); i >= 0; --i) {
					edb::Instruction inst(buffer + i, buffer + sizeof(buffer), 0);

					//If it's a call, then make a frame
					if(is_call(inst)) {
						stack_frame frame;
						frame.ret = possible_ret;
						frame.caller = possible_ret - CALL_MAX_SIZE + i;
						stack_frames_.append(frame);
						break;
					}
				}
			}
		}
	}
}
void Relocation::pd_set_call_destination(address x) {
  assert(is_call(), "should be a call here");
  if (NativeCall::is_call_at(addr())) {
    address trampoline = nativeCall_at(addr())->get_trampoline();
    if (trampoline) {
      nativeCall_at(addr())->set_destination_mt_safe(x, /* assert_lock */false);
      return;
    }
  }
  MacroAssembler::pd_patch_instruction(addr(), x);
  assert(pd_call_destination(addr()) == x, "fail in reloc");
}
address Relocation::pd_call_destination(address orig_addr) {
  assert(is_call(), "should be a call here");
  if (NativeCall::is_call_at(addr())) {
    address trampoline = nativeCall_at(addr())->get_trampoline();
    if (trampoline) {
      return nativeCallTrampolineStub_at(trampoline)->destination();
    }
  }
  if (orig_addr != NULL) {
    address new_addr = MacroAssembler::pd_call_destination(orig_addr);
    // If call is branch to self, don't try to relocate it, just leave it
    // as branch to self. This happens during code generation if the code
    // buffer expands. It will be relocated to the trampoline above once
    // code generation is complete.
    new_addr = (new_addr == orig_addr) ? addr() : new_addr;
    return new_addr;
  }
  return MacroAssembler::pd_call_destination(addr());
}
예제 #5
0
static ssize_t
tnt_rpc_base(struct tnt_stream *s, const char *proc, size_t proc_len,
	     struct tnt_stream *args, enum tnt_request_t op)
{
	if (!proc || proc_len == 0)
		return -1;
	if (tnt_object_verify(args, MP_ARRAY))
		return -1;
	uint32_t fld = (is_call(op) ? TNT_FUNCTION : TNT_EXPRESSION);
	struct tnt_iheader hdr;
	struct iovec v[6]; int v_sz = 6;
	char *data = NULL, *body_start = NULL;
	encode_header(&hdr, op, s->reqid++);
	v[1].iov_base = (void *)hdr.header;
	v[1].iov_len  = hdr.end - hdr.header;
	char body[64]; body_start = body; data = body;

	data = mp_encode_map(data, 2);
	data = mp_encode_uint(data, fld);
	data = mp_encode_strl(data, proc_len);
	v[2].iov_base = body_start;
	v[2].iov_len  = data - body_start;
	v[3].iov_base = (void *)proc;
	v[3].iov_len  = proc_len;
	body_start = data;
	data = mp_encode_uint(data, TNT_TUPLE);
	v[4].iov_base = body_start;
	v[4].iov_len  = data - body_start;
	v[5].iov_base = TNT_SBUF_DATA(args);
	v[5].iov_len  = TNT_SBUF_SIZE(args);

	size_t package_len = 0;
	for (int i = 1; i < v_sz; ++i)
		package_len += v[i].iov_len;
	char len_prefix[9];
	char *len_end = mp_encode_luint32(len_prefix, package_len);
	v[0].iov_base = len_prefix;
	v[0].iov_len = len_end - len_prefix;
	return s->writev(s, v, v_sz);
}
예제 #6
0
	vector<PointerAccess> get_pointer_accesses(const Instruction *ins) {
		vector<PointerAccess> result;
		if (const StoreInst *si = dyn_cast<StoreInst>(ins)) {
			result.push_back(PointerAccess(si, si->getPointerOperand(), true));
		} else if (const LoadInst *li = dyn_cast<LoadInst>(ins)) {
			result.push_back(PointerAccess(li, li->getPointerOperand(), false));
		} else if (is_call(ins)) {
			CallSite cs(const_cast<Instruction *>(ins));
			Function *callee = cs.getCalledFunction();
			if (callee) {
				if (callee->getName() == "read") {
					result.push_back(PointerAccess(ins, cs.getArgument(1), true));
				}
				if (callee->getName() == "write") {
					result.push_back(PointerAccess(ins, cs.getArgument(1), false));
				}
				if (callee->getName() == "BZ2_bzBuffToBuffDecompress") {
					result.push_back(PointerAccess(ins, cs.getArgument(0), true));
				}
			}
		}
		return result;
	}
예제 #7
0
//------------------------------------------------------------------------------
// Name: do_find
// Desc:
//------------------------------------------------------------------------------
void DialogReferences::do_find() {
	bool ok = false;
	edb::address_t address;
	const edb::address_t page_size = edb::v1::debugger_core->page_size();
	
	const QString text = ui->txtAddress->text();
	if(!text.isEmpty()) {
		ok = edb::v1::eval_expression(text, &address);
	}	
	

	if(ok) {
		edb::v1::memory_regions().sync();
		const QList<IRegion::pointer> regions = edb::v1::memory_regions().regions();

		int i = 0;
		for(const IRegion::pointer &region: regions) {
			// a short circut for speading things up
			if(region->accessible() || !ui->chkSkipNoAccess->isChecked()) {

				const edb::address_t page_count = region->size() / page_size;
				const QVector<quint8> pages = edb::v1::read_pages(region->start(), page_count);

				if(!pages.isEmpty()) {
					const quint8 *p = &pages[0];
					const quint8 *const pages_end = &pages[0] + region->size();

					while(p != pages_end) {

						if(pages_end - p < edb::v1::pointer_size()) {
							break;
						}

						const edb::address_t addr = p - &pages[0] + region->start();

						edb::address_t test_address(0);
						memcpy(&test_address, p, edb::v1::pointer_size());

						if(test_address == address) {
							auto item = new QListWidgetItem(edb::v1::format_pointer(addr));
							item->setData(TypeRole, 'D');
							item->setData(AddressRole, addr);
							ui->listWidget->addItem(item);
						}

						edb::Instruction inst(p, pages_end, addr);

						if(inst) {
							switch(inst.operation()) {
							case edb::Instruction::Operation::X86_INS_MOV:
								// instructions of the form: mov [ADDR], 0xNNNNNNNN
								Q_ASSERT(inst.operand_count() == 2);

								if(inst.operands()[0].general_type() == edb::Operand::TYPE_EXPRESSION) {
									if(inst.operands()[1].general_type() == edb::Operand::TYPE_IMMEDIATE && static_cast<edb::address_t>(inst.operands()[1].immediate()) == address) {
										auto item = new QListWidgetItem(edb::v1::format_pointer(addr));
										item->setData(TypeRole, 'C');
										item->setData(AddressRole, addr);
										ui->listWidget->addItem(item);
									}
								}

								break;
							case edb::Instruction::Operation::X86_INS_PUSH:
								// instructions of the form: push 0xNNNNNNNN
								Q_ASSERT(inst.operand_count() == 1);

								if(inst.operands()[0].general_type() == edb::Operand::TYPE_IMMEDIATE && static_cast<edb::address_t>(inst.operands()[0].immediate()) == address) {
									auto item = new QListWidgetItem(edb::v1::format_pointer(addr));
									item->setData(TypeRole, 'C');
									item->setData(AddressRole, addr);
									ui->listWidget->addItem(item);
								}
								break;
							default:
								if(is_jump(inst) || is_call(inst)) {
									if(inst.operands()[0].general_type() == edb::Operand::TYPE_REL) {
										if(inst.operands()[0].relative_target() == address) {
											auto item = new QListWidgetItem(edb::v1::format_pointer(addr));
											item->setData(TypeRole, 'C');
											item->setData(AddressRole, addr);
											ui->listWidget->addItem(item);
										}
									}								
								}
								break;
							}
						}

						Q_EMIT updateProgress(util::percentage(i, regions.size(), p - &pages[0], region->size()));
						++p;
					}
				}

			} else {
				Q_EMIT updateProgress(util::percentage(i, regions.size()));
			}
			++i;
		}
	}
}