platform_system_core/debuggerd/test/BacktraceMock.h
Christopher Ferris 456abbabf2 Dump memory going from unreadable to readable.
If the first read when dumping memory returns no data, skip ahead to
the next page boundary and try and read from there. This fixes a case
where the address at which to start dumping memory is unreadable, but
crosses back into readable memory.

Bug: 22234753
Change-Id: Ie28d5c027013577ca06f5396aba498366a3b6749
2015-07-09 15:35:47 -07:00

106 lines
2.7 KiB
C++

/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _DEBUGGERD_TEST_BACKTRACE_MOCK_H
#define _DEBUGGERD_TEST_BACKTRACE_MOCK_H
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ucontext.h>
#include <string>
#include <vector>
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
class BacktraceMapMock : public BacktraceMap {
public:
BacktraceMapMock() : BacktraceMap(0) {}
virtual ~BacktraceMapMock() {}
void AddMap(backtrace_map_t& map) {
maps_.push_back(map);
}
};
class BacktraceMock : public Backtrace {
public:
BacktraceMock(BacktraceMapMock* map) : Backtrace(0, 0, map) {
if (map_ == nullptr) {
abort();
}
}
virtual ~BacktraceMock() {}
virtual bool Unwind(size_t, ucontext_t*) { return false; }
virtual bool ReadWord(uintptr_t, word_t*) { return false;}
virtual std::string GetFunctionNameRaw(uintptr_t, uintptr_t*) { return ""; }
virtual size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
size_t offset = 0;
if (last_read_addr_ > 0) {
offset = addr - last_read_addr_;
}
size_t bytes_available = buffer_.size() - offset;
if (do_partial_read_) {
// Do a partial read.
if (bytes > bytes_partial_read_) {
bytes = bytes_partial_read_;
}
bytes_partial_read_ -= bytes;
// Only support a single partial read.
do_partial_read_ = false;
} else if (bytes > bytes_available) {
bytes = bytes_available;
}
if (bytes > 0) {
memcpy(buffer, buffer_.data() + offset, bytes);
}
last_read_addr_ = addr;
return bytes;
}
void SetReadData(uint8_t* buffer, size_t bytes) {
buffer_.resize(bytes);
memcpy(buffer_.data(), buffer, bytes);
bytes_partial_read_ = 0;
do_partial_read_ = false;
last_read_addr_ = 0;
}
void SetPartialReadAmount(size_t bytes) {
if (bytes > buffer_.size()) {
abort();
}
bytes_partial_read_ = bytes;
do_partial_read_ = true;
}
private:
std::vector<uint8_t> buffer_;
size_t bytes_partial_read_ = 0;
uintptr_t last_read_addr_ = 0;
bool do_partial_read_ = false;
};
#endif // _DEBUGGERD_TEST_BACKTRACE_MOCK_H