Change AutoRemoteSyscalls::infallible_mmap_syscall to infallible_mmap_syscall_if_alive
diff --git a/src/AddressSpace.cc b/src/AddressSpace.cc
index e3fea9e..b31fef5 100644
--- a/src/AddressSpace.cc
+++ b/src/AddressSpace.cc
@@ -314,11 +314,11 @@
int child_fd = remote.infallible_send_fd_if_alive(page.get());
if (child_fd >= 0) {
if (t->session().is_recording()) {
- remote.infallible_mmap_syscall(rr_page_start() - offset_bytes, offset_bytes, prot, flags,
- child_fd, 0);
+ remote.infallible_mmap_syscall_if_alive(rr_page_start() - offset_bytes, offset_bytes, prot, flags,
+ child_fd, 0);
}
- remote.infallible_mmap_syscall(rr_page_start(), rr_page_size(), prot, flags,
- child_fd, offset_pages);
+ remote.infallible_mmap_syscall_if_alive(rr_page_start(), rr_page_size(), prot, flags,
+ child_fd, offset_pages);
struct stat fstat = t->stat_fd(child_fd);
file_name = t->file_name_of_fd(child_fd);
@@ -1546,7 +1546,7 @@
t->read_bytes_helper(mapping.map.start(), buffer.size(), buffer.data());
{
AutoRemoteSyscalls remote(t);
- remote.infallible_mmap_syscall(mapping.map.start(), buffer.size(),
+ remote.infallible_mmap_syscall_if_alive(mapping.map.start(), buffer.size(),
mapping.map.prot(), mapping.map.flags() | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
}
t->write_bytes_helper(mapping.map.start(), buffer.size(), buffer.data());
diff --git a/src/AutoRemoteSyscalls.cc b/src/AutoRemoteSyscalls.cc
index f9670d5..6d695b5 100644
--- a/src/AutoRemoteSyscalls.cc
+++ b/src/AutoRemoteSyscalls.cc
@@ -186,10 +186,12 @@
if (found_stack.start().is_null()) {
AutoRemoteSyscalls remote(t, DISABLE_MEMORY_PARAMS);
found_stack =
- MemoryRange(remote.infallible_mmap_syscall(
+ MemoryRange(remote.infallible_mmap_syscall_if_alive(
remote_ptr<void>(), 4096, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0),
4096);
+ ASSERT(t, !found_stack.start().is_null())
+ << "Tracee unexpectedly died here";
scratch_mem_was_mapped = true;
}
@@ -581,7 +583,7 @@
}
}
-remote_ptr<void> AutoRemoteSyscalls::infallible_mmap_syscall(
+remote_ptr<void> AutoRemoteSyscalls::infallible_mmap_syscall_if_alive(
remote_ptr<void> addr, size_t length, int prot, int flags, int child_fd,
uint64_t offset_pages) {
// The first syscall argument is called "arg 1", so
@@ -589,13 +591,13 @@
// with "1".
remote_ptr<void> ret =
has_mmap2_syscall(arch())
- ? infallible_syscall_ptr(syscall_number_for_mmap2(arch()), addr,
- length, prot, flags, child_fd,
- (off_t)offset_pages)
- : infallible_syscall_ptr(syscall_number_for_mmap(arch()), addr,
- length, prot, flags, child_fd,
- offset_pages * page_size());
- if (flags & MAP_FIXED) {
+ ? infallible_syscall_ptr_if_alive(syscall_number_for_mmap2(arch()), addr,
+ length, prot, flags, child_fd,
+ (off_t)offset_pages)
+ : infallible_syscall_ptr_if_alive(syscall_number_for_mmap(arch()), addr,
+ length, prot, flags, child_fd,
+ offset_pages * page_size());
+ if (ret && (flags & MAP_FIXED)) {
ASSERT(t, addr == ret) << "MAP_FIXED at " << addr << " but got " << ret;
}
return ret;
@@ -663,7 +665,7 @@
backing_file_open_flags);
}
/* And mmap that file. */
- infallible_mmap_syscall(rec_addr, length,
+ infallible_mmap_syscall_if_alive(rec_addr, length,
/* (We let SHARED|WRITEABLE
* mappings go through while
* they're not handled properly,
diff --git a/src/AutoRemoteSyscalls.h b/src/AutoRemoteSyscalls.h
index 6560011..66f8edb 100644
--- a/src/AutoRemoteSyscalls.h
+++ b/src/AutoRemoteSyscalls.h
@@ -176,23 +176,23 @@
return ret;
}
- /** TODO replace with infallible_syscall_ptr_if_alive */
+ /** Returns null if the tracee is dead */
template <typename... Rest>
- remote_ptr<void> infallible_syscall_ptr(int syscallno, Rest... args) {
+ remote_ptr<void> infallible_syscall_ptr_if_alive(int syscallno, Rest... args) {
Registers callregs = regs();
long ret = syscall_helper<1>(syscallno, callregs, args...);
- check_syscall_result(ret, syscallno, false);
- return ret;
+ check_syscall_result(ret, syscallno);
+ return ret == -ESRCH ? 0 : ret;
}
/**
* Remote mmap syscalls are common and non-trivial due to the need to
* select either mmap2 or mmap.
- * TODO replace with infallble_mmap_syscall_if_alive
+ * Returns null if the process dies or has died.
*/
- remote_ptr<void> infallible_mmap_syscall(remote_ptr<void> addr, size_t length,
- int prot, int flags, int child_fd,
- uint64_t offset_pages);
+ remote_ptr<void> infallible_mmap_syscall_if_alive(remote_ptr<void> addr, size_t length,
+ int prot, int flags, int child_fd,
+ uint64_t offset_pages);
/** TODO replace with infallible_lseek_syscall_if_alive */
int64_t infallible_lseek_syscall(int fd, int64_t offset, int whence);
diff --git a/src/Monkeypatcher.cc b/src/Monkeypatcher.cc
index f3214e0..4fcc92b 100644
--- a/src/Monkeypatcher.cc
+++ b/src/Monkeypatcher.cc
@@ -219,7 +219,11 @@
AutoRemoteSyscalls remote(t);
int prot = PROT_READ | PROT_EXEC;
int flags = MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE;
- remote.infallible_mmap_syscall(addr, page_size(), prot, flags, -1, 0);
+ auto ret = remote.infallible_mmap_syscall_if_alive(addr, page_size(), prot, flags, -1, 0);
+ if (!ret) {
+ /* Tracee died */
+ return nullptr;
+ }
KernelMapping recorded(addr, addr + page_size(), string(),
KernelMapping::NO_DEVICE, KernelMapping::NO_INODE,
prot, flags);
diff --git a/src/ReplaySession.cc b/src/ReplaySession.cc
index dd0f61f..0a3cc87 100644
--- a/src/ReplaySession.cc
+++ b/src/ReplaySession.cc
@@ -138,7 +138,6 @@
// Check that sizes and offsets of supported XSAVE areas area all identical.
// An Intel employee promised this on a mailing list...
// https://lists.xen.org/archives/html/xen-devel/2013-09/msg00484.html
- // His promise isn't binding on AMD though.
for (int feature = 2; feature <= 63; ++feature) {
if (!(tracee_xcr0 & our_xcr0 & (uint64_t(1) << feature))) {
continue;
@@ -150,10 +149,8 @@
record->out.ebx != data.ebx ||
(check_alignment && (record->out.ecx & 2) != (data.ecx & 2))) {
CLEAN_FATAL()
- << "XSAVE offset/size/alignment differs for feature " << feature << "\n"
- << "Expected " << record->out.eax << " == " << data.eax << " && "
- << record->out.ebx << " == " << data.ebx << " && (!" << check_alignment
- << " || " << (record->out.ecx & 2) << " == " << (data.ecx & 2) << ")";
+ << "XSAVE offset/size/alignment differs for feature " << feature
+ << "; H. Peter Anvin said this would never happen!";
}
}
}
@@ -1467,8 +1464,8 @@
}
AutoRemoteSyscalls remote(t);
ASSERT(t, km.flags() & MAP_ANONYMOUS);
- remote.infallible_mmap_syscall(km.start(), km.size(), km.prot(),
- km.flags() | MAP_FIXED, -1, 0);
+ remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),
+ km.flags() | MAP_FIXED, -1, 0);
t->vm()->map(t, km.start(), km.size(), km.prot(), km.flags(), 0, string(),
KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,
&km);
diff --git a/src/Session.cc b/src/Session.cc
index b5f1680..59d4b42 100644
--- a/src/Session.cc
+++ b/src/Session.cc
@@ -411,14 +411,20 @@
struct stat real_file = remote.task()->stat_fd(remote_fd);
string real_file_name = remote.task()->file_name_of_fd(remote_fd);
// XXX this condition is x86/x64-specific, I imagine.
- remote.infallible_mmap_syscall(m.map.start(), m.map.size(), m.map.prot(),
- // The remapped segment *must* be
- // remapped at the same address,
- // or else many things will go
- // haywire.
- (m.map.flags() & ~MAP_ANONYMOUS) | MAP_FIXED,
- remote_fd,
- m.map.file_offset_bytes() / page_size());
+ // The remapped segment *must* be remapped at the same address,
+ // or else many things will go haywire.
+ auto ret = remote.infallible_mmap_syscall_if_alive(m.map.start(), m.map.size(), m.map.prot(),
+ (m.map.flags() & ~MAP_ANONYMOUS) | MAP_FIXED,
+ remote_fd,
+ m.map.file_offset_bytes() / page_size());
+ if (!ret) {
+ if (remote.task()->vm()->task_set().size() > remote.task()->thread_group()->task_set().size()) {
+ // XXX not sure how to handle the case where the tracee died after
+ // we unmapped the area
+ FATAL() << "Unexpected task death leaving this address space in a bad state";
+ }
+ return;
+ }
// We update the AddressSpace mapping too, since that tracks the real file
// name and we need to update that.
@@ -453,21 +459,26 @@
if (child_shmem_fd < 0) {
return km;
}
- resize_shmem_segment(shmem_fd, size);
LOG(debug) << "created shmem segment " << path;
// Map the segment in ours and the tracee's address spaces.
void* map_addr;
int flags = MAP_SHARED;
- if ((void*)-1 == (map_addr = mmap(nullptr, size, PROT_READ | PROT_WRITE,
- flags, shmem_fd, 0))) {
- FATAL() << "Failed to mmap shmem region";
- }
if (!map_hint.is_null()) {
flags |= MAP_FIXED;
}
- remote_ptr<void> child_map_addr = remote.infallible_mmap_syscall(
+ remote_ptr<void> child_map_addr = remote.infallible_mmap_syscall_if_alive(
map_hint, size, tracee_prot, flags, child_shmem_fd, 0);
+ if (!child_map_addr) {
+ // tracee unexpectedly died
+ return km;
+ }
+
+ if ((void*)-1 == (map_addr = mmap(nullptr, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, shmem_fd, 0))) {
+ FATAL() << "Failed to mmap shmem region";
+ }
+ resize_shmem_segment(shmem_fd, size);
struct stat st;
ASSERT(remote.task(), 0 == ::fstat(shmem_fd, &st));
diff --git a/src/Task.cc b/src/Task.cc
index c8686c3..9ac8b63 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -3498,14 +3498,17 @@
dev_t device = KernelMapping::NO_DEVICE;
ino_t inode = KernelMapping::NO_INODE;
if (km.is_real_device() && !file_was_deleted(km.fsname())) {
- struct stat real_file; string real_file_name;
+ struct stat real_file;
+ string real_file_name;
remote.finish_direct_mmap(km.start(), km.size(), km.prot(), km.flags(),
km.fsname(), O_RDONLY, km.file_offset_bytes()/page_size(),
real_file, real_file_name);
} else {
- remote.infallible_mmap_syscall(km.start(), km.size(), km.prot(),
- km.flags() | MAP_FIXED | MAP_ANONYMOUS, -1,
- 0);
+ auto ret = remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),
+ km.flags() | MAP_FIXED | MAP_ANONYMOUS, -1,
+ 0);
+ ASSERT(t, ret || t->vm()->task_set().size() == t->thread_group()->task_set().size())
+ << "Not handling shared address spaces where one threadgroup unexpectedly dies";
}
t->vm()->map(t, km.start(), km.size(), km.prot(), km.flags(), km.file_offset_bytes(),
real_file_name, device, inode, nullptr, &km);
diff --git a/src/record_signal.cc b/src/record_signal.cc
index edff7a3..0fdde53 100644
--- a/src/record_signal.cc
+++ b/src/record_signal.cc
@@ -203,7 +203,7 @@
{
AutoRemoteSyscalls remote(t, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);
- remote.infallible_mmap_syscall(
+ remote.infallible_mmap_syscall_if_alive(
new_start, it->map.start() - new_start, it->map.prot(),
(it->map.flags() & ~MAP_GROWSDOWN) | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
}
diff --git a/src/record_syscall.cc b/src/record_syscall.cc
index 17867cb..5e43720 100644
--- a/src/record_syscall.cc
+++ b/src/record_syscall.cc
@@ -3137,12 +3137,12 @@
AutoRemoteSyscalls remote(t);
if (addr_type == DYNAMIC_ADDRESS) {
- t->scratch_ptr = remote.infallible_mmap_syscall(remote_ptr<void>(), sz,
- prot, flags, -1, 0);
+ t->scratch_ptr = remote.infallible_mmap_syscall_if_alive(remote_ptr<void>(), sz,
+ prot, flags, -1, 0);
} else {
t->scratch_ptr =
- remote.infallible_mmap_syscall(remote_ptr<void>(FIXED_SCRATCH_PTR),
- sz, prot, flags | MAP_FIXED, -1, 0);
+ remote.infallible_mmap_syscall_if_alive(remote_ptr<void>(FIXED_SCRATCH_PTR),
+ sz, prot, flags | MAP_FIXED, -1, 0);
}
t->scratch_size = scratch_size;
}
@@ -5406,8 +5406,8 @@
remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),
km.start() - page_size(), page_size());
}
- remote.infallible_mmap_syscall(km.start(), km.size(), km.prot(), flags,
- -1, 0);
+ remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(), flags,
+ -1, 0);
t->write_mem(km.start().cast<uint8_t>(), buf.data(), buf.size());
}
}
diff --git a/src/replay_syscall.cc b/src/replay_syscall.cc
index f0202ce..33f73bd 100644
--- a/src/replay_syscall.cc
+++ b/src/replay_syscall.cc
@@ -87,8 +87,8 @@
{
AutoRemoteSyscalls remote(t);
- remote.infallible_mmap_syscall(t->scratch_ptr, sz, km.prot(),
- km.flags() | MAP_FIXED, -1, 0);
+ remote.infallible_mmap_syscall_if_alive(t->scratch_ptr, sz, km.prot(),
+ km.flags() | MAP_FIXED, -1, 0);
t->vm()->map(t, t->scratch_ptr, sz, km.prot(), km.flags(), 0, string(),
KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,
&km);
@@ -342,9 +342,9 @@
case TraceReader::SOURCE_TRACE:
case TraceReader::SOURCE_ZERO:
flags |= MAP_ANONYMOUS;
- remote.infallible_mmap_syscall(km.start(), km.size(), km.prot(),
- (flags & ~MAP_GROWSDOWN) | MAP_FIXED, -1,
- 0);
+ remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),
+ (flags & ~MAP_GROWSDOWN) | MAP_FIXED, -1,
+ 0);
// The data, if any, will be written back by
// ReplayTask::apply_all_data_records_from_trace
break;
@@ -513,9 +513,9 @@
if (km.flags()) {
AutoRemoteSyscalls remote(t);
ASSERT(t, data.source == TraceReader::SOURCE_ZERO);
- remote.infallible_mmap_syscall(km.start(), km.size(), km.prot(),
- MAP_ANONYMOUS | MAP_FIXED | km.flags(), -1,
- 0);
+ remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),
+ MAP_ANONYMOUS | MAP_FIXED | km.flags(), -1,
+ 0);
t->vm()->map(t, km.start(), km.size(), km.prot(),
MAP_ANONYMOUS | km.flags(), 0, "[heap]",
KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,
@@ -538,10 +538,10 @@
KernelMapping recorded_km = t->trace_reader().read_mapped_region(&data);
EmuFile::shr_ptr emu_file;
if (!(flags & MAP_SHARED)) {
- remote.infallible_mmap_syscall(rec_addr, length, prot,
- // Tell the kernel to take |rec_addr|
- // seriously.
- (flags & ~MAP_GROWSDOWN) | MAP_FIXED, -1, 0);
+ remote.infallible_mmap_syscall_if_alive(rec_addr, length, prot,
+ // Tell the kernel to take |rec_addr|
+ // seriously.
+ (flags & ~MAP_GROWSDOWN) | MAP_FIXED, -1, 0);
} else {
ASSERT(remote.task(), data.source == TraceReader::SOURCE_ZERO);
emu_file = t->session().emufs().get_or_create(recorded_km);
@@ -636,7 +636,7 @@
TraceReader::MappedData& data) {
LOG(debug) << " finishing private mmap of " << km.fsname();
- remote.infallible_mmap_syscall(
+ remote.infallible_mmap_syscall_if_alive(
rec_addr, length, prot,
// Tell the kernel to take |rec_addr| seriously.
(flags & ~MAP_GROWSDOWN) | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
@@ -835,15 +835,15 @@
if (new_addr == old_addr) {
// Non-moving mremap. Don't pass MREMAP_FIXED or MREMAP_MAYMOVE
// since that triggers EINVAL when the new map overlaps the old map.
- remote.infallible_syscall_ptr(trace_regs.original_syscallno(), new_addr,
- old_size, new_size, 0);
+ remote.infallible_syscall_if_alive(trace_regs.original_syscallno(), new_addr,
+ old_size, new_size, 0);
} else {
// Force the mremap to use the destination address from recording.
// XXX could the new mapping overlap the old, with different start
// addresses? Hopefully the kernel doesn't do that to us!!!
- remote.infallible_syscall_ptr(trace_regs.original_syscallno(), old_addr,
- old_size, new_size,
- MREMAP_MAYMOVE | MREMAP_FIXED, new_addr);
+ remote.infallible_syscall_if_alive(trace_regs.original_syscallno(), old_addr,
+ old_size, new_size,
+ MREMAP_MAYMOVE | MREMAP_FIXED, new_addr);
}
remote.regs().set_syscall_result(new_addr);
@@ -873,8 +873,8 @@
// Shared non-EmuFs mappings must be of immutable files so it's OK to
// just copy the file data into a private mapping here.
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
- remote.infallible_mmap_syscall(new_addr, new_size, mapping.map.prot(),
- map_flags, -1, 0);
+ remote.infallible_mmap_syscall_if_alive(new_addr, new_size, mapping.map.prot(),
+ map_flags, -1, 0);
t->vm()->unmap(t, new_addr, new_size);
t->vm()->map(t, new_addr, new_size, mapping.map.prot(), map_flags,
mapping.map.file_offset_bytes(), string(),