Skip to content

Commit b05bdac

Browse files
authored
Fix heuristic that discards segments when matching program segments to mappings. (#979)
Round down the segment file offset to a segment p_align alignment when comparing against the mapping file offset instead of using the system page size alignment in all cases.
1 parent 3d256cb commit b05bdac

File tree

2 files changed

+40
-16
lines changed

2 files changed

+40
-16
lines changed

internal/elfexec/elfexec.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,7 @@ func ProgramHeadersForMapping(phdrs []elf.ProgHeader, mapOff, mapSz uint64) []*e
316316
// page size is not 4KB, we must try to guess the page size on the system
317317
// where the profile was collected, possibly using the architecture
318318
// specified in the ELF file header.
319-
pageSize = 4096
320-
pageOffsetMask = pageSize - 1
319+
pageSize = 4096
321320
)
322321
mapLimit := mapOff + mapSz
323322
var headers []*elf.ProgHeader
@@ -331,12 +330,12 @@ func ProgramHeadersForMapping(phdrs []elf.ProgHeader, mapOff, mapSz uint64) []*e
331330
segLimit := p.Off + p.Memsz
332331
// The segment must overlap the mapping.
333332
if p.Type == elf.PT_LOAD && mapOff < segLimit && p.Off < mapLimit {
334-
// If the mapping offset is strictly less than the page aligned segment
335-
// offset, then this mapping comes from a different segment, fixes
336-
// b/179920361.
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.
337336
alignedSegOffset := uint64(0)
338-
if p.Off > (p.Vaddr & pageOffsetMask) {
339-
alignedSegOffset = p.Off - (p.Vaddr & pageOffsetMask)
337+
if p.Off > (p.Vaddr & (p.Align - 1)) {
338+
alignedSegOffset = p.Off - (p.Vaddr & (p.Align - 1))
340339
}
341340
if mapOff < alignedSegOffset {
342341
continue

internal/elfexec/elfexec_test.go

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,15 @@ func TestFindProgHeaderForMapping(t *testing.T) {
169169
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0xe10, Vaddr: 0x600e10, Paddr: 0x600e10, Filesz: 0x230, Memsz: 0x238, Align: 0x200000},
170170
}
171171
mediumHeaders := []elf.ProgHeader{
172-
{Type: elf.PT_PHDR, Flags: elf.PF_R, Off: 0x40, Vaddr: 0x40, Paddr: 0x40, Filesz: 0x268, Memsz: 0x268, Align: 8},
173-
{Type: elf.PT_INTERP, Flags: elf.PF_R, Off: 0x2a8, Vaddr: 0x2a8, Paddr: 0x2a8, Filesz: 0x28, Memsz: 0x28, Align: 1},
174-
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_X, Off: 0, Vaddr: 0, Paddr: 0, Filesz: 0x51800, Memsz: 0x51800, Align: 0x200000},
175-
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x51800, Vaddr: 0x251800, Paddr: 0x251800, Filesz: 0x24a8, Memsz: 0x24e8, Align: 0x200000},
176-
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x53d00, Vaddr: 0x453d00, Paddr: 0x453d00, Filesz: 0x13a58, Memsz: 0x91a198, Align: 0x200000},
177-
{Type: elf.PT_TLS, Flags: elf.PF_R, Off: 0x51800, Vaddr: 0x51800, Paddr: 0x51800, Filesz: 0x0, Memsz: 0x38, Align: 0x8},
178-
{Type: elf.PT_DYNAMIC, Flags: elf.PF_R | elf.PF_W, Off: 0x51d00, Vaddr: 0x251d00, Paddr: 0x251d00, Filesz: 0x1ef0, Memsz: 0x1ef0, Align: 8},
172+
{Type: elf.PT_PHDR, Flags: elf.PF_R, Off: 0x40, Vaddr: 0x40, Paddr: 0x40, Filesz: 0x2d8, Memsz: 0x2d8, Align: 8},
173+
{Type: elf.PT_INTERP, Flags: elf.PF_R, Off: 0x318, Vaddr: 0x318, Paddr: 0x318, Filesz: 0x28, Memsz: 0x28, Align: 1},
174+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_X, Off: 0, Vaddr: 0, Paddr: 0, Filesz: 0x354ca0, Memsz: 0x354ca0, Align: 0x200000},
175+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x400000, Vaddr: 600000, Paddr: 600000, Filesz: 0x0083b8, Memsz: 0x009000, Align: 0x200000},
176+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x600000, Vaddr: 0xa00000, Paddr: 0xa00000, Filesz: 0x007030, Memsz: 0x9cf090, Align: 0x200000},
177+
{Type: elf.PT_LOAD, Flags: elf.PF_R, Off: 0x7cf090, Vaddr: 0x15cf090, Paddr: 0x15cf090, Filesz: 0x028460, Memsz: 0x028460, Align: 0x200000},
178+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x7f7500, Vaddr: 0x17f7500, Paddr: 0x17f7500, Filesz: 0x001f80, Memsz: 0x5bdd9a0, Align: 0x200000},
179+
{Type: elf.PT_TLS, Flags: elf.PF_R, Off: 0x407740, Vaddr: 0x607740, Paddr: 0x607740, Filesz: 0x98, Memsz: 0x350, Align: 0x40},
180+
{Type: elf.PT_DYNAMIC, Flags: elf.PF_R | elf.PF_W, Off: 0x407920, Vaddr: 0x607920, Paddr: 0x607920, Filesz: 0x230, Memsz: 0x230, Align: 8},
179181
}
180182
largeHeaders := []elf.ProgHeader{
181183
{Type: elf.PT_PHDR, Flags: elf.PF_R, Off: 0x40, Vaddr: 0x40, Paddr: 0x40, Filesz: 0x268, Memsz: 0x268, Align: 8},
@@ -186,6 +188,19 @@ func TestFindProgHeaderForMapping(t *testing.T) {
186188
{Type: elf.PT_TLS, Flags: elf.PF_R, Off: 0x2ec5d2c0, Vaddr: 0x2ee5d2c0, Paddr: 0x2ee5d2c0, Filesz: 0x120, Memsz: 0x103f8, Align: 0x40},
187189
{Type: elf.PT_DYNAMIC, Flags: elf.PF_R | elf.PF_W, Off: 0x2ffbc9e0, Vaddr: 0x301bc9e0, Paddr: 0x301bc9e0, Filesz: 0x1f0, Memsz: 0x1f0, Align: 8},
188190
}
191+
largeHeadersWithRoSegment := []elf.ProgHeader{
192+
{Type: elf.PT_PHDR, Flags: elf.PF_R, Off: 0x40, Vaddr: 0x40, Paddr: 0x40, Filesz: 0x348, Memsz: 0x348, Align: 8},
193+
{Type: elf.PT_INTERP, Flags: elf.PF_R, Off: 0x388, Vaddr: 0x388, Paddr: 0x388, Filesz: 0x28, Memsz: 0x28, Align: 1},
194+
{Type: elf.PT_LOAD, Flags: elf.PF_R, Off: 0, Vaddr: 0, Paddr: 0, Filesz: 0x81c5628, Memsz: 0x81c5628, Align: 0x200000},
195+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x81c6000, Vaddr: 0x83c6000, Paddr: 0x83c6000, Filesz: 0x1af7fb0, Memsz: 0x1af7fb0, Align: 0x200000},
196+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_X, Off: 0x9cbdfc0, Vaddr: 0xa0bdfc0, Paddr: 0xa0bdfc0, Filesz: 0x16e68fc0, Memsz: 0x16e68fc0, Align: 0x200000},
197+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x20c00000, Vaddr: 0x21200000, Paddr: 0x21200000, Filesz: 0x1c602f8, Memsz: 0x1c61000, Align: 0x200000},
198+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x22a00000, Vaddr: 0x23200000, Paddr: 0x23200000, Filesz: 0x120ed30, Memsz: 0x1d2c2e0, Align: 0x200000},
199+
{Type: elf.PT_LOAD, Flags: elf.PF_R, Off: 0x23d2c2e0, Vaddr: 0x2512c2e0, Paddr: 0x2512c2e0, Filesz: 0x2cbc4dc, Memsz: 0x2cbc4dc, Align: 0x200000},
200+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x269e87c0, Vaddr: 0x27fe87c0, Paddr: 0x27fe87c0, Filesz: 0x6f43c8, Memsz: 0x736e00, Align: 0x200000},
201+
{Type: elf.PT_TLS, Flags: elf.PF_R, Off: 0x22840200, Vaddr: 0x22e40200, Paddr: 0x22e40200, Filesz: 0x298, Memsz: 0x5428, Align: 0x40},
202+
{Type: elf.PT_DYNAMIC, Flags: elf.PF_R | elf.PF_W, Off: 0x2285daa0, Vaddr: 0x22e5daa0, Paddr: 0x22e5daa0, Filesz: 0x250, Memsz: 0x250, Align: 8},
203+
}
189204
ffmpegHeaders := []elf.ProgHeader{
190205
{Type: elf.PT_PHDR, Flags: elf.PF_R, Off: 0x40, Vaddr: 0x200040, Paddr: 0x200040, Filesz: 0x1f8, Memsz: 0x1f8, Align: 8},
191206
{Type: elf.PT_INTERP, Flags: elf.PF_R, Off: 0x238, Vaddr: 0x200238, Paddr: 0x200238, Filesz: 0x28, Memsz: 0x28, Align: 1},
@@ -323,8 +338,8 @@ func TestFindProgHeaderForMapping(t *testing.T) {
323338
desc: "medium file large mapping that includes all address space matches executable segment, b/179920361",
324339
phdrs: mediumHeaders,
325340
pgoff: 0,
326-
memsz: 0xd6e000,
327-
wantHeaders: []*elf.ProgHeader{{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_X, Off: 0, Vaddr: 0, Paddr: 0, Filesz: 0x51800, Memsz: 0x51800, Align: 0x200000}},
341+
memsz: 0x73d5000,
342+
wantHeaders: []*elf.ProgHeader{{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_X, Off: 0, Vaddr: 0, Paddr: 0, Filesz: 0x354ca0, Memsz: 0x354ca0, Align: 0x200000}},
328343
},
329344
{
330345
desc: "large file executable mapping matches executable segment",
@@ -347,6 +362,16 @@ func TestFindProgHeaderForMapping(t *testing.T) {
347362
memsz: 0xb11000,
348363
wantHeaders: []*elf.ProgHeader{{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x2ffbe440, Vaddr: 0x303be440, Paddr: 0x303be440, Filesz: 0x4637c0, Memsz: 0xc91610, Align: 0x200000}},
349364
},
365+
{
366+
desc: "large file with RO segment executable mapping includes executable segment",
367+
phdrs: largeHeadersWithRoSegment,
368+
pgoff: 0x9c00000,
369+
memsz: 0x16f27000,
370+
wantHeaders: []*elf.ProgHeader{
371+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_W, Off: 0x81c6000, Vaddr: 0x83c6000, Paddr: 0x83c6000, Filesz: 0x1af7fb0, Memsz: 0x1af7fb0, Align: 0x200000},
372+
{Type: elf.PT_LOAD, Flags: elf.PF_R | elf.PF_X, Off: 0x9cbdfc0, Vaddr: 0xa0bdfc0, Paddr: 0xa0bdfc0, Filesz: 0x16e68fc0, Memsz: 0x16e68fc0, Align: 0x200000},
373+
},
374+
},
350375
{
351376
desc: "sentry headers, mapping for last page of executable segment matches executable segment",
352377
phdrs: sentryHeaders,

0 commit comments

Comments
 (0)