Browse Source

Handle shared libraries with nonzero program headers. (#119)

Generalize GetBase for shared libraries to handle cases when both process
mapping offset and program header addresses are non-zero.

Based on process mapping information, a sample at a virtual address x maps to
a file offset fx = x - map_start + map_offset.

The program header for the segment with the .text section may have non-zero
mapping information. Thus, a file offset fx maps to a symbol address
sx = fx - ph_offset + ph_virt_addr.

Thus, sx = x - map_start + map_offset - ph_offset + ph_virt_addr, and the base
address for symbolization is map_start - map_offset + ph_offset - ph_virt_addr.
gmarin13 8 years ago
parent
commit
a613757740
2 changed files with 16 additions and 10 deletions
  1. 14
    9
      internal/elfexec/elfexec.go
  2. 2
    1
      internal/elfexec/elfexec_test.go

+ 14
- 9
internal/elfexec/elfexec.go View File

240
 		}
240
 		}
241
 		return start, nil
241
 		return start, nil
242
 	case elf.ET_DYN:
242
 	case elf.ET_DYN:
243
-		if offset != 0 {
244
-			if loadSegment == nil || loadSegment.Vaddr == 0 {
245
-				return start - offset, nil
246
-			}
247
-			return 0, fmt.Errorf("Don't know how to handle mapping. Offset=%x, vaddr=%x",
248
-				offset, loadSegment.Vaddr)
249
-		}
243
+		// The process mapping information, start = start of virtual address range,
244
+		// and offset = offset in the executable file of the start address, tells us
245
+		// that a runtime virtual address x maps to a file offset
246
+		// fx = x - start + offset.
250
 		if loadSegment == nil {
247
 		if loadSegment == nil {
251
-			return start, nil
248
+			return start - offset, nil
252
 		}
249
 		}
253
-		return start - loadSegment.Vaddr, nil
250
+		// The program header, if not nil, indicates the offset in the file where
251
+		// the executable segment is located (loadSegment.Off), and the base virtual
252
+		// address where the first byte of the segment is loaded
253
+		// (loadSegment.Vaddr). A file offset fx maps to a virtual (symbol) address
254
+		// sx = fx - loadSegment.Off + loadSegment.Vaddr.
255
+		//
256
+		// Thus, a runtime virtual address x maps to a symbol address
257
+		// sx = x - start + offset - loadSegment.Off + loadSegment.Vaddr.
258
+		return start - offset + loadSegment.Off - loadSegment.Vaddr, nil
254
 	}
259
 	}
255
 	return 0, fmt.Errorf("Don't know how to handle FileHeader.Type %v", fh.Type)
260
 	return 0, fmt.Errorf("Don't know how to handle FileHeader.Type %v", fh.Type)
256
 }
261
 }

+ 2
- 1
internal/elfexec/elfexec_test.go View File

62
 		{"exec chromeos kernel 4", fhExec, kernelHeader, uint64p(0xffffffff81200198), 0x198, 0x100000, 0, 0x7ee00000, false},
62
 		{"exec chromeos kernel 4", fhExec, kernelHeader, uint64p(0xffffffff81200198), 0x198, 0x100000, 0, 0x7ee00000, false},
63
 		{"exec chromeos kernel unremapped", fhExec, kernelHeader, uint64p(0xffffffff810001c8), 0xffffffff834001c8, 0xffffffffc0000000, 0xffffffff834001c8, 0x2400000, false},
63
 		{"exec chromeos kernel unremapped", fhExec, kernelHeader, uint64p(0xffffffff810001c8), 0xffffffff834001c8, 0xffffffffc0000000, 0xffffffff834001c8, 0x2400000, false},
64
 		{"dyn", fhDyn, nil, nil, 0x200000, 0x300000, 0, 0x200000, false},
64
 		{"dyn", fhDyn, nil, nil, 0x200000, 0x300000, 0, 0x200000, false},
65
-		{"dyn offset", fhDyn, lsOffset, nil, 0x0, 0x300000, 0, 0xFFFFFFFFFFC00000, false},
65
+		{"dyn map", fhDyn, lsOffset, nil, 0x0, 0x300000, 0, 0xFFFFFFFFFFE00000, false},
66
 		{"dyn nomap", fhDyn, nil, nil, 0x0, 0x0, 0, 0, false},
66
 		{"dyn nomap", fhDyn, nil, nil, 0x0, 0x0, 0, 0, false},
67
+		{"dyn map+offset", fhDyn, lsOffset, nil, 0x900000, 0xa00000, 0x200000, 0x500000, false},
67
 		{"rel", fhRel, nil, nil, 0x2000000, 0x3000000, 0, 0x2000000, false},
68
 		{"rel", fhRel, nil, nil, 0x2000000, 0x3000000, 0, 0x2000000, false},
68
 		{"rel nomap", fhRel, nil, nil, 0x0, ^uint64(0), 0, 0, false},
69
 		{"rel nomap", fhRel, nil, nil, 0x0, ^uint64(0), 0, 0, false},
69
 		{"rel offset", fhRel, nil, nil, 0x100000, 0x200000, 0x1, 0, true},
70
 		{"rel offset", fhRel, nil, nil, 0x100000, 0x200000, 0x1, 0, true},