Chromium Code Reviews| Index: src/trusted/gdb_rsp/host_mock.cc |
| =================================================================== |
| --- src/trusted/gdb_rsp/host_mock.cc (revision 0) |
| +++ src/trusted/gdb_rsp/host_mock.cc (revision 0) |
| @@ -0,0 +1,240 @@ |
| +/* |
| + * Copyright 2010 The Native Client Authors. All rights reserved. |
| + * Use of this source code is governed by a BSD-style license that can |
| + * be found in the LICENSE file. |
| + */ |
| + |
| +#include <assert.h> |
| +#include <string.h> |
| +#include <stdlib.h> |
| +#include <stdio.h> |
|
mmortensen
2010/12/07 22:53:58
Minor nit: we could use C++ style headers here, s
mlinck
2010/12/10 21:10:27
I'm leaning towards leaving these since they're wo
|
| + |
| +#include "native_client/src/trusted/gdb_rsp/abi.h" |
| +#include "native_client/src/trusted/gdb_rsp/host.h" |
| +#include "native_client/src/trusted/gdb_rsp/host_mock.h" |
| +#include "native_client/src/trusted/gdb_rsp/packet.h" |
| +#include "native_client/src/trusted/gdb_rsp/session.h" |
| +#include "native_client/src/trusted/gdb_rsp/util.h" |
| + |
| +#include "native_client/src/trusted/port/std_types.h" |
| +#include "native_client/src/trusted/port/platform.h" |
| + |
| +#ifdef WIN32 |
| +#define snprintf sprintf_s |
| +#endif |
| + |
| + |
| +using std::string; |
| +using port::IPlatform; |
| + |
| +namespace gdb_rsp { |
| + |
| + |
| +// Construct unitialzied |
| +HostMock::HostMock() : Host(0) { } |
|
noelallen_use_chromium
2010/12/07 23:04:44
http://www.corp.google.com/eng/doc/cppguide.xml#0_
|
| + |
| +HostMock::~HostMock() { |
| + while (!signals_.empty()) { |
| + SignalMock* sig = signals_.front(); |
| + signals_.pop_front(); |
| + delete sig; |
| + } |
| + |
| + while (!memory_.empty()) { |
| + delete[] memory_.begin()->second; |
| + memory_.erase(memory_.begin()); |
| + } |
| +} |
| + |
| +bool HostMock::Init() { |
| + string reply; |
| + |
| + properties_.clear(); |
| + properties_["PacketSize"] = "3fa"; |
| + |
| + SetRequest("qExecPath", "nullptr.nexe"); |
| + SetRequest("qExecArgs", ""); |
| + SetRequest("qExecEnvs", ""); |
| + |
| + abi_ = Abi::Find("i386:x86-64"); |
| + |
| + status_ = HS_STOPPED; |
| + return true; |
| +} |
| + |
| +bool HostMock::Step() { |
| + // We can only step if we are stopped |
| + if (HS_STOPPED != status_) return false; |
| + |
| + status_ = HS_RUNNING; |
| + return true; |
| +} |
| + |
| +bool HostMock::Continue() { |
| + // We can only step if we are stopped |
| + if (HS_STOPPED != status_) return false; |
| + |
| + status_ = HS_RUNNING; |
| + return true; |
| +} |
| + |
| + |
| +bool HostMock::Break() { |
| + char brk[2] = { 0x03, 0x00 }; |
|
noelallen_use_chromium
2010/12/07 23:04:44
Where is this used? This should have generated a
|
| + |
| + // We can only break if running |
| + if (HS_RUNNING != status_) return false; |
| + |
| + status_ = HS_STOPPING; |
| + |
| + SignalMock* sig = new SignalMock; |
|
noelallen_use_chromium
2010/12/07 23:04:44
While this is not REALLY trusted code, since it wi
mlinck
2010/12/10 21:10:27
There's a separate target for these called gdb_rsp
|
| + sig->sig = 5; |
| + sig->thread = 0; |
| + sig->rel = true; |
| + sig->ip = 0; |
| + |
| + signals_.push_front(sig); |
| + return true; |
| +} |
| + |
| +bool HostMock::Detach() { |
| + // We can only detach if stopped |
| + if (HS_STOPPED != status_) return false; |
| + return true; |
| +} |
| + |
| +#define MEMBLOCKSIZE 65536 |
| +bool HostMock::GetMemory(void *dst, uint64_t addr, uint32_t size) { |
| + char *out = reinterpret_cast<char *>(dst); |
| + |
| + while (size) { |
| + uint64_t key = addr & ~(MEMBLOCKSIZE - 1); |
| + uint64_t offs = addr & (MEMBLOCKSIZE - 1); |
| + uint32_t max = static_cast<uint32_t>(MEMBLOCKSIZE - offs); |
| + char *data = memory_[key]; |
| + |
| + /* Truncate this iteration */ |
| + if (max > size) max = size; |
| + |
| + /* Check if block is availible */ |
|
noelallen_use_chromium
2010/12/07 23:04:44
Misleading:
Fail if block does not exist.
|
| + if (NULL == data) return false; |
| + |
| + /* Copy it out. */ |
| + memcpy(out, &data[addr - key], max); |
| + size -= max; |
| + out += max; |
|
noelallen_use_chromium
2010/12/07 23:04:44
Does this actually work? Addr does not appear to
|
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool HostMock::SetMemory(const void *src, uint64_t addr, uint32_t size) { |
| + const char *in = reinterpret_cast<const char *>(src); |
| + |
| + while (size) { |
|
noelallen_use_chromium
2010/12/07 23:04:44
Same as above.
|
| + uint64_t key = addr & ~(MEMBLOCKSIZE - 1); |
| + uint64_t offs = addr & (MEMBLOCKSIZE - 1); |
| + uint32_t max = static_cast<uint32_t>(MEMBLOCKSIZE - offs); |
| + char *data = memory_[key]; |
| + |
| + /* Truncate this iteration */ |
| + if (max > size) max = size; |
| + |
| + /* Check if block is availible, if not allocate */ |
| + if (NULL == data) { |
| + data = new char[MEMBLOCKSIZE]; |
| + memory_[key] = data; |
| + } |
| + |
| + /* Copy it out. */ |
| + memcpy(&data[addr - key], in, max); |
| + size -= max; |
| + in += max; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool HostMock::Request(const std::string &req, std::string *resp) { |
| + std::map<string, string>::const_iterator itr; |
| + itr = requests_.find(req); |
| + |
| + if (requests_.end() == itr) return false; |
| + |
| + *resp = itr->second; |
| + return true; |
| +} |
| + |
| +void HostMock::SetRequest(const std::string &req, const std::string &resp) { |
| + requests_[req] = resp; |
| +} |
| + |
| + |
|
noelallen_use_chromium
2010/12/07 23:04:44
Either the source or the header should describe th
|
| +void HostMock::AddSignal(int32_t signal, uint32_t thread) { |
| + SignalMock* sig = new SignalMock; |
| + sig->sig = signal; |
| + sig->thread = thread; |
| + sig->rel = true; |
| + sig->ip = 0; |
| + |
| + signals_.push_back(sig); |
| +} |
| + |
| +void HostMock::AddSignalAbs(int32_t signal, uint32_t thread, uint64_t ip) { |
| + SignalMock* sig = new SignalMock; |
| + sig->sig = signal; |
| + sig->thread = thread; |
| + sig->rel = false; |
| + sig->ip = ip; |
| + |
| + signals_.push_back(sig); |
| +} |
| + |
| +void HostMock::AddSignalDelta(int32_t signal, uint32_t thread, int64_t delta) { |
| + SignalMock* sig = new SignalMock; |
| + sig->sig = signal; |
| + sig->thread = thread; |
| + sig->rel = true; |
| + sig->ip = delta; |
| + |
| + signals_.push_back(sig); |
| +} |
| + |
| +// Wait to see if we receive a break |
| +bool HostMock::WaitForBreak() { |
| + if (signals_.empty()) return false; |
| + |
| + SignalMock* sig = signals_.front(); |
| + signals_.pop_front(); |
| + |
| + Thread* thread = GetThread(sig->thread); |
| + if (thread) { |
| + const Abi *abi = thread->GetAbi(); |
| + const Abi::RegDef *def = abi->GetRegisterType(Abi::INST_PTR); |
| + uint64_t ip; |
| + |
| + if (sig->rel) { |
| + thread->GetRegister(def->index_, &ip); |
| + sig->ip += ip; |
|
noelallen_use_chromium
2010/12/07 23:04:44
Should this be
ip += sig->ip
|
| + } else { |
| + ip = sig->ip; |
| + } |
| + |
| + /* Update the current thread's IP */ |
| + thread->SetRegister(def->index_, &ip); |
| + } |
| + |
| + /* Generate a "signal" packet */ |
| + char tmp[64]; |
| + snprintf(tmp, "S%02d", sig->sig, 63); |
|
noelallen_use_chromium
2010/12/07 23:04:44
should use sizeof(tmp) instead of 63 in case the s
|
| + ParseStopPacket(tmp); |
| + |
| + delete sig; |
| + return true; |
| +} |
| + |
| + |
| + |
| +} // namespace gdb_rsp |
| + |
| + |
| Property changes on: src\trusted\gdb_rsp\host_mock.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |