|
@@ -178,8 +178,7 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6
|
178
|
178
|
pageOffsetPpc64 = 0xc000000000000000
|
179
|
179
|
)
|
180
|
180
|
|
181
|
|
- if start == 0 && offset == 0 &&
|
182
|
|
- (limit == ^uint64(0) || limit == 0) {
|
|
181
|
+ if start == 0 && offset == 0 && (limit == ^uint64(0) || limit == 0) {
|
183
|
182
|
// Some tools may introduce a fake mapping that spans the entire
|
184
|
183
|
// address space. Assume that the address has already been
|
185
|
184
|
// adjusted, so no additional base adjustment is necessary.
|
|
@@ -189,9 +188,21 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6
|
189
|
188
|
switch fh.Type {
|
190
|
189
|
case elf.ET_EXEC:
|
191
|
190
|
if loadSegment == nil {
|
192
|
|
- // Fixed-address executable, no adjustment.
|
|
191
|
+ // Assume fixed-address executable and so no adjustment.
|
193
|
192
|
return 0, nil
|
194
|
193
|
}
|
|
194
|
+ if stextOffset == nil && start > 0 && start < 0x8000000000000000 {
|
|
195
|
+ // A regular user-mode executable. Compute the base offset using same
|
|
196
|
+ // arithmetics as in ET_DYN case below, see the explanation there.
|
|
197
|
+ // Ideally, the condition would just be "stextOffset == nil" as that
|
|
198
|
+ // represents the address of _stext symbol in the vmlinux image. Alas,
|
|
199
|
+ // the caller may skip reading it from the binary (it's expensive to scan
|
|
200
|
+ // all the symbols) and so it may be nil even for the kernel executable.
|
|
201
|
+ // So additionally check that the start is within the user-mode half of
|
|
202
|
+ // the 64-bit address space.
|
|
203
|
+ return start - offset + loadSegment.Off - loadSegment.Vaddr, nil
|
|
204
|
+ }
|
|
205
|
+ // Various kernel heuristics and cases follow.
|
195
|
206
|
if start == 0 && limit != 0 {
|
196
|
207
|
// ChromeOS remaps its kernel to 0. Nothing else should come
|
197
|
208
|
// down this path. Empirical values:
|
|
@@ -202,12 +213,6 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6
|
202
|
213
|
}
|
203
|
214
|
return -loadSegment.Vaddr, nil
|
204
|
215
|
}
|
205
|
|
- if loadSegment.Vaddr-loadSegment.Off == start-offset {
|
206
|
|
- return offset, nil
|
207
|
|
- }
|
208
|
|
- if loadSegment.Vaddr == start-offset {
|
209
|
|
- return offset, nil
|
210
|
|
- }
|
211
|
216
|
if start >= loadSegment.Vaddr && limit > start && (offset == 0 || offset == pageOffsetPpc64 || offset == start) {
|
212
|
217
|
// Some kernels look like:
|
213
|
218
|
// VADDR=0xffffffff80200000
|
|
@@ -230,7 +235,7 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6
|
230
|
235
|
// start=0x198 limit=0x2f9fffff offset=0
|
231
|
236
|
// VADDR=0xffffffff81000000
|
232
|
237
|
// stextOffset=0xffffffff81000198
|
233
|
|
- return -(*stextOffset - start), nil
|
|
238
|
+ return start - *stextOffset, nil
|
234
|
239
|
}
|
235
|
240
|
|
236
|
241
|
return 0, fmt.Errorf("Don't know how to handle EXEC segment: %v start=0x%x limit=0x%x offset=0x%x", *loadSegment, start, limit, offset)
|