Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 59 additions & 5 deletions pkg/symbolize/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,31 @@ func (d *driverStore) resolve(addr va.Address) *sys.Driver {
// driver already cached?
d.mux.RLock()
dev, isCached := d.drivers[addr]
var (
base va.Address
size uint64
)
if isCached {
base = va.Address(dev.Base)
size = uint64(dev.Size)
}
d.mux.RUnlock()

if isCached {
return dev
if addr >= base && addr < base.Inc(size) {
// entry is still valid
return dev
}
// evict the stale cache entry so that subsequent calls for
// the same address do not keep hitting the validation path
d.mux.Lock()
// recheck under write lock in case if another goroutine may
// have already evicted or refreshed the entry while we were
// upgrading the lock
if current, still := d.drivers[addr]; still && current == dev {
delete(d.drivers, addr)
}
d.mux.Unlock()
}

d.mux.Lock()
Expand All @@ -67,15 +89,12 @@ func (d *driverStore) resolve(addr va.Address) *sys.Driver {
}

func (d *driverStore) addDriver(base va.Address, size uint64, path string) {
d.mux.Lock()
defer d.mux.Unlock()

dev := sys.Driver{
Path: path,
Base: base.Uintptr(),
Size: uint32(size),
}
d.devs = append(d.devs, dev)
d.addDev(dev)
}

func (d *driverStore) removeDriver(base va.Address, size uint64) {
Expand All @@ -95,3 +114,38 @@ func (d *driverStore) removeDriver(base va.Address, size uint64) {
}
}
}

func (d *driverStore) addDev(drv sys.Driver) {
d.mux.Lock()
defer d.mux.Unlock()

var (
exists = false
base = va.Address(drv.Base)
size = uint64(drv.Size)
)

for i, dev := range d.devs {
switch {
case dev.Base == drv.Base && dev.Path != drv.Path:
// different driver has reloaded at the same base address.
// Evict all cached addresses that still point at the old
// driver so that resolve() cannot return a stale pointer
// for the new occupant.
for addr := range d.drivers {
if addr >= base && addr < base.Inc(size) {
delete(d.drivers, addr)
}
}
d.devs = append(d.devs[:i], d.devs[i+1:]...)
case dev.Base == drv.Base && dev.Path == drv.Path:
// driver exists at identical base address and
// device path. Nothing to do
exists = true
}
}

if !exists {
d.devs = append(d.devs, drv)
}
}
22 changes: 22 additions & 0 deletions pkg/symbolize/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,25 @@ func TestAddRemoveRoundTrip(t *testing.T) {
t.Error("driver must be gone after round-trip removal")
}
}

func TestAddNewDriverSameBase(t *testing.T) {
ds := makeStore(realDrivers())

const base va.Address = 0xFFFFF80010000000
const size uint64 = 0x50000

ds.addDriver(base, size, `\Driver\fileinfo.sys`)
if len(ds.devs) != 3 {
t.Error("must be 3 drivers in the store")
}

ds.addDriver(base, size, `\Driver\FLTMGR.SYS.sys`)
if len(ds.devs) != 3 {
t.Error("must be 3 drivers in the store")
}

drv := ds.resolve(base)
if drv.Path != `\Driver\FLTMGR.SYS.sys` {
t.Error("unexpected driver resolved")
}
}
Loading