| 125 | } |
| 126 | |
| 127 | bool SharedCacheController::ApplyRegion(BinaryView& view, const CacheRegion& region) |
| 128 | { |
| 129 | std::unique_lock<std::shared_mutex> lock(m_loadMutex); |
| 130 | // Loads the given region into the BinaryView and marks it as loaded. |
| 131 | // First check to make sure we haven't already loaded the region. |
| 132 | if (m_loadedRegions.find(region.start) != m_loadedRegions.end()) |
| 133 | return false; |
| 134 | |
| 135 | // Skip filtered regions, this defaults to just LINKEDIT regions. |
| 136 | if (std::regex_match(region.name, m_regionFilter)) |
| 137 | { |
| 138 | m_logger->LogDebug("Skipping filtered region at %llx", region.start); |
| 139 | return false; |
| 140 | } |
| 141 | |
| 142 | auto vm = m_cache.GetVirtualMemory(); |
| 143 | DataBuffer buffer = {}; |
| 144 | try |
| 145 | { |
| 146 | buffer = vm->ReadBuffer(region.start, region.size); |
| 147 | } |
| 148 | catch (std::exception& e) |
| 149 | { |
| 150 | // This happens if we have not mapped in all the relevant entries. |
| 151 | m_logger->LogError("Failed to read region: %s", e.what()); |
| 152 | return false; |
| 153 | } |
| 154 | |
| 155 | // Unique memory region name so that we don't cause collisions. |
| 156 | // TODO: Better name? I dont really think so... |
| 157 | const auto memoryRegionName = fmt::format("{}_0x{:x}", region.name, region.start); |
| 158 | |
| 159 | // NOTE: Adding a data memory region will store the entire contents of the region in the BNDB. |
| 160 | // TODO: We can use the AddRemoteMemoryRegion if we want to reload on view init. |
| 161 | // TODO: ^ The above is only useful if we assume that all files will be available across database loads. |
| 162 | // TODO: we might allow a user to select non-persisted memory regions as an option. |
| 163 | view.GetMemoryMap()->AddDataMemoryRegion(memoryRegionName, region.start, buffer, region.flags); |
| 164 | // TODO: We might want to make this auto if we decide to "reload" all loaded region in view init. |
| 165 | // If we are not associated with an image we can create a section here to set the semantics. |
| 166 | // This is important for stub regions, as they will deref non image data that we want to retrieve the value of. |
| 167 | if (region.type != CacheRegionType::Image) |
| 168 | { |
| 169 | // Adding a user section will mark all functions for updates unless we disable this. |
| 170 | // Because images are known separate compilation units, we have a real reason to make sure we don't mark all previously |
| 171 | // analyzed functions as updated. |
| 172 | auto prevDisabledState = view.GetFunctionAnalysisUpdateDisabled(); |
| 173 | view.SetFunctionAnalysisUpdateDisabled(true); |
| 174 | view.AddUserSection(memoryRegionName, region.start, region.size, region.SectionSemanticsForRegion()); |
| 175 | view.SetFunctionAnalysisUpdateDisabled(prevDisabledState); |
| 176 | } |
| 177 | |
| 178 | m_loadedRegions.insert(region.start); |
| 179 | |
| 180 | // TODO: This needs to be done in a "database save" callback. |
| 181 | view.StoreMetadata(METADATA_KEY, GetMetadata()); |
| 182 | |
| 183 | return true; |
| 184 | } |
no test coverage detected