| 136 | } |
| 137 | |
| 138 | void ProcessReaderLinux::Thread::InitializeStackFromSP( |
| 139 | ProcessReaderLinux* reader, |
| 140 | LinuxVMAddress stack_pointer) { |
| 141 | const MemoryMap* memory_map = reader->GetMemoryMap(); |
| 142 | |
| 143 | // If we can't find the mapping, it's probably a bad stack pointer |
| 144 | const MemoryMap::Mapping* mapping = memory_map->FindMapping(stack_pointer); |
| 145 | if (!mapping) { |
| 146 | LOG(WARNING) << "no stack mapping"; |
| 147 | return; |
| 148 | } |
| 149 | LinuxVMAddress stack_region_start = |
| 150 | reader->Memory()->PointerToAddress(stack_pointer); |
| 151 | |
| 152 | // We've hit what looks like a guard page; skip to the end and check for a |
| 153 | // mapped stack region. |
| 154 | if (!mapping->readable) { |
| 155 | stack_region_start = mapping->range.End(); |
| 156 | mapping = memory_map->FindMapping(stack_region_start); |
| 157 | if (!mapping) { |
| 158 | LOG(WARNING) << "no stack mapping"; |
| 159 | return; |
| 160 | } |
| 161 | } else { |
| 162 | #if defined(ARCH_CPU_X86_FAMILY) |
| 163 | // Adjust start address to include the red zone |
| 164 | if (reader->Is64Bit()) { |
| 165 | constexpr LinuxVMSize kRedZoneSize = 128; |
| 166 | LinuxVMAddress red_zone_base = |
| 167 | stack_region_start - std::min(kRedZoneSize, stack_region_start); |
| 168 | |
| 169 | // Only include the red zone if it is part of a valid mapping |
| 170 | if (red_zone_base >= mapping->range.Base()) { |
| 171 | stack_region_start = red_zone_base; |
| 172 | } else { |
| 173 | const MemoryMap::Mapping* rz_mapping = |
| 174 | memory_map->FindMapping(red_zone_base); |
| 175 | if (rz_mapping && ShouldMergeStackMappings(*mapping, *rz_mapping)) { |
| 176 | stack_region_start = red_zone_base; |
| 177 | } else { |
| 178 | stack_region_start = mapping->range.Base(); |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | #endif |
| 183 | } |
| 184 | stack_region_address = stack_region_start; |
| 185 | |
| 186 | // If there are more mappings at the end of this one, they may be a |
| 187 | // continuation of the stack. |
| 188 | LinuxVMAddress stack_end = mapping->range.End(); |
| 189 | const MemoryMap::Mapping* next_mapping; |
| 190 | while ((next_mapping = memory_map->FindMapping(stack_end)) && |
| 191 | ShouldMergeStackMappings(*mapping, *next_mapping)) { |
| 192 | stack_end = next_mapping->range.End(); |
| 193 | } |
| 194 | |
| 195 | // The main thread should have an entry in the maps file just for its stack, |
no test coverage detected