(
&mut self,
endian: P::Endian,
in_segments: &[P]
)
| 359 | } |
| 360 | |
| 361 | fn associate_mem_ranges<P: ProgramHeader<Word = u64>>( |
| 362 | &mut self, |
| 363 | endian: P::Endian, |
| 364 | in_segments: &[P] |
| 365 | ) -> Result<()> { |
| 366 | let headers = in_segments |
| 367 | .iter() |
| 368 | .enumerate() |
| 369 | .filter(|(_, h)| h.p_type(endian) == PT_LOAD) |
| 370 | .filter(|(_, h)| h.p_paddr(endian) != u64::MAX) |
| 371 | .filter(|(_, h)| h.p_vaddr(endian) != 0) |
| 372 | .map(|(_, h)| h); |
| 373 | |
| 374 | let mut out_file_off = 0; |
| 375 | for h in headers { |
| 376 | // This should always be true. |
| 377 | assert_eq!(h.p_filesz(endian), h.p_memsz(endian)); |
| 378 | |
| 379 | // NOTE: There is an issue on Amazon Linux and Ubuntu VMs where physaddr |
| 380 | // is null when looking at "readelf -l /proc/kcore" |
| 381 | // We retrieve the physical offset from /proc/iomem using the segment sizes. |
| 382 | for mem_range in &self.iomem_ranges { |
| 383 | debug!("mem_range: {:#X?}", mem_range); |
| 384 | if h.p_paddr(endian) == mem_range.start_phys_addr || |
| 385 | (h.p_paddr(endian) == 0 && h.p_filesz(endian) == mem_range.memsz) || |
| 386 | (h.p_paddr(endian) >= mem_range.start_phys_addr && h.p_paddr(endian) < mem_range.end_phys_addr) { |
| 387 | |
| 388 | let delta = h.p_paddr(endian) - mem_range.start_phys_addr; |
| 389 | let is_virtual = delta > 0; |
| 390 | |
| 391 | let start_phys_addr = mem_range.start_phys_addr + delta; |
| 392 | let memsz = h.p_filesz(endian); |
| 393 | assert_eq!(h.p_filesz(endian), h.p_memsz(endian)); |
| 394 | if !is_virtual { |
| 395 | if memsz != mem_range.memsz { |
| 396 | log::warn!("Mismatch between /proc/iomem segment size ({:#X}) and /proc/kcore segment size ({:#X}). Dumping {:#X} bytes.", mem_range.memsz, memsz, max(memsz, mem_range.memsz)); |
| 397 | } |
| 398 | } |
| 399 | let end_phys_addr = start_phys_addr + memsz; |
| 400 | let virt_addr = h.p_vaddr(endian); |
| 401 | let kcore_file_off = h.p_offset(endian); |
| 402 | |
| 403 | self.mem_ranges.push(MemoryRange { |
| 404 | start_phys_addr, |
| 405 | end_phys_addr, |
| 406 | memsz: max(memsz, mem_range.memsz), |
| 407 | virt_addr, |
| 408 | kcore_file_off, |
| 409 | out_file_off, |
| 410 | is_virtual, |
| 411 | p_flags: h.p_flags(endian) |
| 412 | }); |
| 413 | |
| 414 | if is_virtual == false { |
| 415 | out_file_off += memsz; |
| 416 | } |
| 417 | |
| 418 | debug!("0x{:x}-0x{:x} va=0x{:x} kfo=0x{:x}", |
no test coverage detected