Support read-only hardware watchpoints on x86 #510
Conversation
b35cb8f
to
c0c2ff3
Compare
}); | ||
if (loc == _locations.end()) { | ||
// exception. It isn't possible to hit at an address that isn't enabled | ||
return kErrorInvalidAddress; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if this is the right error to return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with a DS2ASSERT(loc != _locations.end());
std::vector<uint64_t> _locations; | ||
struct Location { | ||
Location() | ||
:address(0), value(0){} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to run clang-format on this. You can either:
- Install and run clang-format manually (I don't think this works on devservers)
- Look at the Travis "STYLE" failures and manually apply
- install clang-format and run: TARGET=Style ./Support/Testing/Travis/script.sh (see previous comment about no devservers, this will probably require temporarily changing script.sh to use an unversioned clang-format)
auto loc = std::find_if(_locations.begin(), _locations.end(), | ||
[address](const Location &l){ | ||
return l.address == address; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please factor out the comparator and pass around as a function pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean define a function like
inline bool addressInMap(const HardwareBreakpointManager::Location &location,
const u_int64_t address)
__attribute__((always_inline)) {
return location.address == address;
}
and use it everywhere like
std::find_if(_locations.begin(), _locations.end(),
[address](const Location &location) { return addressInMap(location, address); });
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I have a different idea. We could just use a std::map for _locations
, and remove the DS2ASSERT(_locations.size() == maxWatchpoints());
(since you can't fix the size of a map). we already check _sites.size() >= maxWatchpoints()
in HardwareBreakpointManager::add
, so there's really no reason to also restrict the size of _locations
. If you use <address, value> as <key, value> in a map, you don't need the find_if's anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thats great, I'll do that in a commit in the next hour or so :)
bool HardwareBreakpointManager::checkIfWrittenTo(Address const &address) { | ||
bool implemented = false; | ||
DS2ASSERT(implemented); | ||
return implemented; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just put a DS2BUG("not implemented") instead
@@ -35,6 +35,12 @@ size_t HardwareBreakpointManager::maxWatchpoints() { | |||
return _process->getMaxWatchpoints(); | |||
} | |||
|
|||
bool HardwareBreakpointManager::checkIfWrittenTo(Address const &address) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wasWritten()
@@ -102,6 +104,44 @@ ErrorCode HardwareBreakpointManager::disableLocation(Site const &site, | |||
return error; | |||
} | |||
|
|||
// workaround for hardware readonly watchpoints not being implememted in | |||
// hardware ¯\_(ツ)_/¯ https://github.com/facebook/ds2/issues/257 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this really qualifies as a workaround, since the lack of hardware implementation is an intentional feature. You could just say that this is a software implementation of read-only watchpoints or something.
@@ -102,6 +104,44 @@ ErrorCode HardwareBreakpointManager::disableLocation(Site const &site, | |||
return error; | |||
} | |||
|
|||
// workaround for hardware readonly watchpoints not being implememted in | |||
// hardware ¯\_(ツ)_/¯ https://github.com/facebook/ds2/issues/257 | |||
bool HardwareBreakpointManager::hardwareReadonlyWorkaround( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably just inline this function.
auto loc = std::find_if(_locations.begin(), _locations.end(), | ||
[address](const Location &l){ | ||
return l.address == address; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see previous comment about factoring this out.
@@ -113,7 +153,7 @@ int HardwareBreakpointManager::getAvailableLocation() { | |||
return l.address == 0; | |||
}); | |||
DS2ASSERT(it != _locations.end()); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: remove accidental whitespace change
@@ -32,6 +32,27 @@ size_t HardwareBreakpointManager::maxWatchpoints() { | |||
return 4; // dr0, dr1, dr2, dr3 | |||
} | |||
|
|||
bool HardwareBreakpointManager::checkIfWrittenTo(Address const &address) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wasWritten()
}); | ||
if (loc == _locations.end()) { | ||
// exception. It isn't possible to hit at an address that isn't enabled | ||
return kErrorInvalidAddress; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with a DS2ASSERT(loc != _locations.end());
@fjricci should I squash all/some of my commits? |
Stacked commits are good (much easier to review and understand than one big blob), but they should be stacked by functionality and not by time (so a commit like |
sounds good! I'll rebase functionally 😄 |
5d04c9c
to
72c604c
Compare
Pro tip: use |
@fjricci I'm currently failing on Travis for 2 reasons. One is related to STYLE, I'm using clang-format v5 on my machine, would it make sense to update Travis' version of clang format from 4 to 5 as well? For the second failure, I'll look at it closer once I fix the style issue. |
We like to keep our llvm tools all on the same version, and the stable version of llvm 5 hasn't been released yet (slated for next month I think). We should wait until then to update our clang-format. Do you have access to clang-format-4? |
I can build it 😄 |
Yeah, I mean, that's what I do. (I even have it as a command in my bashrc, which I find helpful: https://github.com/fjricci/configfiles/blob/1be83f5e813612d382c3c47d734d68efcc3c5d58/bash/bashrc#L28-L37) If you're going to be doing more toolchain work, you'll end up needing llvm builds anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of general comments on this PR before I do a real review:
- Please try to respect the commit message format of git as much as possible: https://chris.beams.io/posts/git-commit/#seven-rules
- Please make sure that each commit you submit is atomic and can be merged as-is when we're done with the review. For instance, the commit titled "address @fjricci's review comments" should be split squashed with previous commits in the branch where applicable.
@sas I'll try to clean up my commits & their messages today |
cf4001a
to
7bf2e61
Compare
What's the status of this? |
Bump. |
This flew under my radar. Checking this out now! TODO
|
😮 TIL about TODO lists on github 😮 |
49ae141
to
2d800ab
Compare
8209681
to
a2cb333
Compare
For the software implementation of readonly hardware breakpoints, we need to keep an up-to-date map of the values at memory addresses. That way when our read|write breakpoint is triggered, we can check to see if the value at that memory address has changed before deciding whether or not to halt at that watchpoint The downside with this approach is if one re-writes the existing value at one of these hardware readonly watchpoints, this implementation will halt there, thinking the value was read from (since the address was halted by our read|write breakpoint and the value is unchanged), instead of correctly ignoring that halt as a write.
So one can still run the travis script targeting STYlE even without having "clang-format-4.0" in one's PATH
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags: Blame Revision:
no say bone |
😱😥 |
No description provided.