// Copyright 2018 The Crashpad Authors // // 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. #include "snapshot/fuchsia/memory_map_fuchsia.h" #include "base/fuchsia/fuchsia_logging.h" #include "util/numeric/checked_range.h" namespace crashpad { MemoryMapFuchsia::MemoryMapFuchsia() = default; MemoryMapFuchsia::~MemoryMapFuchsia() = default; bool MemoryMapFuchsia::Initialize(const zx::process& process) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); // There's no way to know what an appropriate buffer size is before starting. // Start at a size that should be more than enough for any reasonable process. map_entries_.resize(4096); // Retrieving the maps is racy with new mappings being created, so retry this // loop up to |tries| times until the number of actual mappings retrieved // matches those available. int tries = 5; for (;;) { size_t actual; size_t available; zx_status_t status = process.get_info(ZX_INFO_PROCESS_MAPS, &map_entries_[0], map_entries_.size() * sizeof(map_entries_[0]), &actual, &available); if (status != ZX_OK) { ZX_LOG(ERROR, status) << "zx_object_get_info ZX_INFO_PROCESS_MAPS"; map_entries_.clear(); return false; } if (actual < available && tries-- > 0) { // Make the buffer slightly larger than |available| to attempt to account // for the race between here and the next retrieval. map_entries_.resize(available + 20); continue; } map_entries_.resize(actual); INITIALIZATION_STATE_SET_VALID(initialized_); return true; } } bool MemoryMapFuchsia::FindMappingForAddress(zx_vaddr_t address, zx_info_maps_t* map) const { bool found = false; zx_info_maps_t result = {}; for (const auto& m : map_entries_) { CheckedRange range(m.base, m.size); if (range.ContainsValue(address)) { if (!found || m.depth > result.depth) { result = m; found = true; } } } if (found) { *map = result; } return found; } } // namespace crashpad