ProgramHeadersForMapping returns the program segment headers that overlap the runtime mapping with file offset mapOff and memory size mapSz. We skip over segments zero file size because their file offset values are unreliable. Even if overlapping, a segment is not selected if its aligned file offset
(phdrs []elf.ProgHeader, mapOff, mapSz uint64)
| 308 | // The function returns a slice of pointers to the headers in the input |
| 309 | // slice, which are valid only while phdrs is not modified or discarded. |
| 310 | func ProgramHeadersForMapping(phdrs []elf.ProgHeader, mapOff, mapSz uint64) []*elf.ProgHeader { |
| 311 | const ( |
| 312 | // pageSize defines the virtual memory page size used by the loader. This |
| 313 | // value is dependent on the memory management unit of the CPU. The page |
| 314 | // size is 4KB virtually on all the architectures that we care about, so we |
| 315 | // define this metric as a constant. If we encounter architectures where |
| 316 | // page size is not 4KB, we must try to guess the page size on the system |
| 317 | // where the profile was collected, possibly using the architecture |
| 318 | // specified in the ELF file header. |
| 319 | pageSize = 4096 |
| 320 | ) |
| 321 | mapLimit := mapOff + mapSz |
| 322 | var headers []*elf.ProgHeader |
| 323 | for i := range phdrs { |
| 324 | p := &phdrs[i] |
| 325 | // Skip over segments with zero file size. Their file offsets can have |
| 326 | // arbitrary values, see b/195427553. |
| 327 | if p.Filesz == 0 { |
| 328 | continue |
| 329 | } |
| 330 | segLimit := p.Off + p.Memsz |
| 331 | // The segment must overlap the mapping. |
| 332 | if p.Type == elf.PT_LOAD && mapOff < segLimit && p.Off < mapLimit { |
| 333 | // If the mapping offset is strictly less than the segment offset aligned |
| 334 | // to the segment p_align value then this mapping comes from a different |
| 335 | // segment, fixes b/179920361. |
| 336 | alignedSegOffset := uint64(0) |
| 337 | if p.Off > (p.Vaddr & (p.Align - 1)) { |
| 338 | alignedSegOffset = p.Off - (p.Vaddr & (p.Align - 1)) |
| 339 | } |
| 340 | if mapOff < alignedSegOffset { |
| 341 | continue |
| 342 | } |
| 343 | // If the mapping starts in the middle of the segment, it covers less than |
| 344 | // one page of the segment, and it extends at least one page past the |
| 345 | // segment, then this mapping comes from a different segment. |
| 346 | if mapOff > p.Off && (segLimit < mapOff+pageSize) && (mapLimit >= segLimit+pageSize) { |
| 347 | continue |
| 348 | } |
| 349 | headers = append(headers, p) |
| 350 | } |
| 351 | } |
| 352 | return headers |
| 353 | } |
| 354 | |
| 355 | // HeaderForFileOffset attempts to identify a unique program header that |
| 356 | // includes the given file offset. It returns an error if it cannot identify a |
no outgoing calls
searching dependent graphs…