Parcourir la 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 il y a 8 ans
Parent
révision
a613757740
2 fichiers modifiés avec 16 ajouts et 10 suppressions
  1. 14
    9
      internal/elfexec/elfexec.go
  2. 2
    1
      internal/elfexec/elfexec_test.go

+ 14
- 9
internal/elfexec/elfexec.go Voir le fichier

@@ -240,17 +240,22 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6
240 240
 		}
241 241
 		return start, nil
242 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 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 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 Voir le fichier

@@ -62,8 +62,9 @@ func TestGetBase(t *testing.T) {
62 62
 		{"exec chromeos kernel 4", fhExec, kernelHeader, uint64p(0xffffffff81200198), 0x198, 0x100000, 0, 0x7ee00000, false},
63 63
 		{"exec chromeos kernel unremapped", fhExec, kernelHeader, uint64p(0xffffffff810001c8), 0xffffffff834001c8, 0xffffffffc0000000, 0xffffffff834001c8, 0x2400000, false},
64 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 66
 		{"dyn nomap", fhDyn, nil, nil, 0x0, 0x0, 0, 0, false},
67
+		{"dyn map+offset", fhDyn, lsOffset, nil, 0x900000, 0xa00000, 0x200000, 0x500000, false},
67 68
 		{"rel", fhRel, nil, nil, 0x2000000, 0x3000000, 0, 0x2000000, false},
68 69
 		{"rel nomap", fhRel, nil, nil, 0x0, ^uint64(0), 0, 0, false},
69 70
 		{"rel offset", fhRel, nil, nil, 0x100000, 0x200000, 0x1, 0, true},