summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-02-24 15:50:19 -0800
committerAndreas Gampe <agampe@google.com>2015-02-24 22:30:47 -0800
commita6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128 (patch)
tree2b07c1cc94212963ec38a2c0a784a26fe1522194
parent96ac49a260223dc00291116daa63d7489c52bb0f (diff)
downloadart-a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128.tar.gz
art-a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128.tar.bz2
art-a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128.zip
ART: Print maps directly to log
Do not read proc maps into a string before printing them later back to the log. In low-memory situations this can cause a bad_alloc. External bug: http://b.android.com/153990 Bug: 19494774 Change-Id: Ie63d8788afe8c9da65b30b2f89c50d3dbb820755
-rw-r--r--runtime/mem_map.cc39
-rw-r--r--runtime/oat_file.cc8
-rw-r--r--runtime/utils.cc59
-rw-r--r--runtime/utils.h1
4 files changed, 77 insertions, 30 deletions
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index a722813867..4b85469fdf 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -152,11 +152,9 @@ static bool ContainedWithinExistingMap(uintptr_t begin,
return true;
}
}
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
*error_msg = StringPrintf("Requested region 0x%08" PRIxPTR "-0x%08" PRIxPTR " does not overlap "
- "any existing map:\n%s\n",
- begin, end, maps.c_str());
+ "any existing map. See process maps in the log.", begin, end);
return false;
}
@@ -375,12 +373,11 @@ MemMap* MemMap::MapAnonymous(const char* name, uint8_t* expected_ptr, size_t byt
#endif
if (actual == MAP_FAILED) {
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
- *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s\n%s",
- expected_ptr, page_aligned_byte_count, prot, flags, fd.get(),
- strerror(saved_errno), maps.c_str());
+ *error_msg = StringPrintf("Failed anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0): %s. See process "
+ "maps in the log.", expected_ptr, page_aligned_byte_count, prot,
+ flags, fd.get(), strerror(saved_errno));
return nullptr;
}
std::ostringstream check_map_request_error_msg;
@@ -435,14 +432,13 @@ MemMap* MemMap::MapFileAtAddress(uint8_t* expected_ptr, size_t byte_count, int p
if (actual == MAP_FAILED) {
auto saved_errno = errno;
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
*error_msg = StringPrintf("mmap(%p, %zd, 0x%x, 0x%x, %d, %" PRId64
- ") of file '%s' failed: %s\n%s",
+ ") of file '%s' failed: %s. See process maps in the log.",
page_aligned_expected, page_aligned_byte_count, prot, flags, fd,
static_cast<int64_t>(page_aligned_offset), filename,
- strerror(saved_errno), maps.c_str());
+ strerror(saved_errno));
return nullptr;
}
std::ostringstream check_map_request_error_msg;
@@ -544,11 +540,9 @@ MemMap* MemMap::RemapAtEnd(uint8_t* new_end, const char* tail_name, int tail_pro
// Unmap/map the tail region.
int result = munmap(tail_base_begin, tail_base_size);
if (result == -1) {
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
- *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'\n%s",
- tail_base_begin, tail_base_size, name_.c_str(),
- maps.c_str());
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
+ *error_msg = StringPrintf("munmap(%p, %zd) failed for '%s'. See process maps in the log.",
+ tail_base_begin, tail_base_size, name_.c_str());
return nullptr;
}
// Don't cause memory allocation between the munmap and the mmap
@@ -558,11 +552,10 @@ MemMap* MemMap::RemapAtEnd(uint8_t* new_end, const char* tail_name, int tail_pro
uint8_t* actual = reinterpret_cast<uint8_t*>(mmap(tail_base_begin, tail_base_size, tail_prot,
flags, fd.get(), 0));
if (actual == MAP_FAILED) {
- std::string maps;
- ReadFileToString("/proc/self/maps", &maps);
- *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed\n%s",
- tail_base_begin, tail_base_size, tail_prot, flags, fd.get(),
- maps.c_str());
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
+ *error_msg = StringPrintf("anonymous mmap(%p, %zd, 0x%x, 0x%x, %d, 0) failed. See process "
+ "maps in the log.", tail_base_begin, tail_base_size, tail_prot, flags,
+ fd.get());
return nullptr;
}
return new MemMap(tail_name, actual, tail_size, actual, tail_base_size, tail_prot, false);
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 9061bb3d55..ae09c6d385 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -171,10 +171,10 @@ bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
return false;
}
if (requested_base != NULL && begin_ != requested_base) {
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
*error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
- "oatdata=%p != expected=%p /proc/self/maps:\n",
+ "oatdata=%p != expected=%p. See process maps in the log.",
begin_, requested_base);
- ReadFileToString("/proc/self/maps", error_msg);
return false;
}
end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatlastword"));
@@ -209,10 +209,10 @@ bool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file
return false;
}
if (requested_base != NULL && begin_ != requested_base) {
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
*error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
- "oatdata=%p != expected=%p /proc/self/maps:\n",
+ "oatdata=%p != expected=%p. See process maps in the log.",
begin_, requested_base);
- ReadFileToString("/proc/self/maps", error_msg);
return false;
}
end_ = elf_file_->FindDynamicSymbolAddress("oatlastword");
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 85c9340d02..2123753de7 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -133,14 +133,14 @@ void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size, siz
}
bool ReadFileToString(const std::string& file_name, std::string* result) {
- std::unique_ptr<File> file(new File);
- if (!file->Open(file_name, O_RDONLY)) {
+ File file;
+ if (!file.Open(file_name, O_RDONLY)) {
return false;
}
std::vector<char> buf(8 * KB);
while (true) {
- int64_t n = TEMP_FAILURE_RETRY(read(file->Fd(), &buf[0], buf.size()));
+ int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
if (n == -1) {
return false;
}
@@ -151,6 +151,59 @@ bool ReadFileToString(const std::string& file_name, std::string* result) {
}
}
+bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
+ File file;
+ if (!file.Open(file_name, O_RDONLY)) {
+ return false;
+ }
+
+ constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
+ char buf[kBufSize + 1]; // +1 for terminator.
+ size_t filled_to = 0;
+ while (true) {
+ DCHECK_LT(filled_to, kBufSize);
+ int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
+ if (n <= 0) {
+ // Print the rest of the buffer, if it exists.
+ if (filled_to > 0) {
+ buf[filled_to] = 0;
+ LOG(level) << buf;
+ }
+ return n == 0;
+ }
+ // Scan for '\n'.
+ size_t i = filled_to;
+ bool found_newline = false;
+ for (; i < filled_to + n; ++i) {
+ if (buf[i] == '\n') {
+ // Found a line break, that's something to print now.
+ buf[i] = 0;
+ LOG(level) << buf;
+ // Copy the rest to the front.
+ if (i + 1 < filled_to + n) {
+ memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
+ filled_to = filled_to + n - i - 1;
+ } else {
+ filled_to = 0;
+ }
+ found_newline = true;
+ break;
+ }
+ }
+ if (found_newline) {
+ continue;
+ } else {
+ filled_to += n;
+ // Check if we must flush now.
+ if (filled_to == kBufSize) {
+ buf[kBufSize] = 0;
+ LOG(level) << buf;
+ filled_to = 0;
+ }
+ }
+ }
+}
+
std::string GetIsoDate() {
time_t now = time(NULL);
tm tmbuf;
diff --git a/runtime/utils.h b/runtime/utils.h
index 3191e7d305..698d686afd 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -410,6 +410,7 @@ std::string JniLongName(mirror::ArtMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool ReadFileToString(const std::string& file_name, std::string* result);
+bool PrintFileToLog(const std::string& file_name, LogSeverity level);
// Returns the current date in ISO yyyy-mm-dd hh:mm:ss format.
std::string GetIsoDate();