service/dap: limit disassembly range (#3045)
Due to dyanmically loaded libraries there could be aribitrarily large gaps in the address space, between functions. Limit the memory size we are willing to disassemble. Fixes #3040
This commit is contained in:
parent
6f34add5db
commit
059406e74f
14
_fixtures/cgodisass.go
Normal file
14
_fixtures/cgodisass.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
int a(int v) {
|
||||||
|
return 0xff + v;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("aaa")
|
||||||
|
print(C.a(11))
|
||||||
|
}
|
@ -3151,6 +3151,10 @@ func alignPCs(bi *proc.BinaryInfo, start, end uint64) (uint64, uint64) {
|
|||||||
return end < fn.Entry
|
return end < fn.Entry
|
||||||
})
|
})
|
||||||
end = bi.Functions[i].Entry
|
end = bi.Functions[i].Entry
|
||||||
|
const limit = 10 * 1024
|
||||||
|
if end-start > limit {
|
||||||
|
end = start + limit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return start, end
|
return start, end
|
||||||
|
@ -55,24 +55,24 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
// name is for _fixtures/<name>.go
|
// name is for _fixtures/<name>.go
|
||||||
func runTest(t *testing.T, name string, test func(c *daptest.Client, f protest.Fixture)) {
|
func runTest(t *testing.T, name string, test func(c *daptest.Client, f protest.Fixture)) {
|
||||||
runTestBuildFlags(t, name, test, protest.AllNonOptimized)
|
runTestBuildFlags(t, name, test, protest.AllNonOptimized, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name is for _fixtures/<name>.go
|
// name is for _fixtures/<name>.go
|
||||||
func runTestBuildFlags(t *testing.T, name string, test func(c *daptest.Client, f protest.Fixture), buildFlags protest.BuildFlags) {
|
func runTestBuildFlags(t *testing.T, name string, test func(c *daptest.Client, f protest.Fixture), buildFlags protest.BuildFlags, defaultDebugInfoDirs bool) {
|
||||||
fixture := protest.BuildFixture(name, buildFlags)
|
fixture := protest.BuildFixture(name, buildFlags)
|
||||||
|
|
||||||
// Start the DAP server.
|
// Start the DAP server.
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
client := startDAPServerWithClient(t, serverStopped)
|
client := startDAPServerWithClient(t, defaultDebugInfoDirs, serverStopped)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
test(client, fixture)
|
test(client, fixture)
|
||||||
<-serverStopped
|
<-serverStopped
|
||||||
}
|
}
|
||||||
|
|
||||||
func startDAPServerWithClient(t *testing.T, serverStopped chan struct{}) *daptest.Client {
|
func startDAPServerWithClient(t *testing.T, defaultDebugInfoDirs bool, serverStopped chan struct{}) *daptest.Client {
|
||||||
server, _ := startDAPServer(t, serverStopped)
|
server, _ := startDAPServer(t, defaultDebugInfoDirs, serverStopped)
|
||||||
client := daptest.NewClient(server.config.Listener.Addr().String())
|
client := daptest.NewClient(server.config.Listener.Addr().String())
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
@ -80,16 +80,21 @@ func startDAPServerWithClient(t *testing.T, serverStopped chan struct{}) *daptes
|
|||||||
// Starts an empty server and a stripped down config just to establish a client connection.
|
// Starts an empty server and a stripped down config just to establish a client connection.
|
||||||
// To mock a server created by dap.NewServer(config) or serving dap.NewSession(conn, config, debugger)
|
// To mock a server created by dap.NewServer(config) or serving dap.NewSession(conn, config, debugger)
|
||||||
// set those arg fields manually after the server creation.
|
// set those arg fields manually after the server creation.
|
||||||
func startDAPServer(t *testing.T, serverStopped chan struct{}) (server *Server, forceStop chan struct{}) {
|
func startDAPServer(t *testing.T, defaultDebugInfoDirs bool, serverStopped chan struct{}) (server *Server, forceStop chan struct{}) {
|
||||||
// Start the DAP server.
|
// Start the DAP server.
|
||||||
listener, err := net.Listen("tcp", ":0")
|
listener, err := net.Listen("tcp", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
debugInfoDirs := []string{}
|
||||||
|
if defaultDebugInfoDirs {
|
||||||
|
debugInfoDirs = []string{"/usr/lib/debug/.build-id"}
|
||||||
|
}
|
||||||
disconnectChan := make(chan struct{})
|
disconnectChan := make(chan struct{})
|
||||||
server = NewServer(&service.Config{
|
server = NewServer(&service.Config{
|
||||||
Listener: listener,
|
Listener: listener,
|
||||||
DisconnectChan: disconnectChan,
|
DisconnectChan: disconnectChan,
|
||||||
|
Debugger: debugger.Config{DebugInfoDirectories: debugInfoDirs},
|
||||||
})
|
})
|
||||||
server.Run()
|
server.Run()
|
||||||
// Give server time to start listening for clients
|
// Give server time to start listening for clients
|
||||||
@ -158,7 +163,7 @@ func TestStopNoClient(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
server, forceStop := startDAPServer(t, serverStopped)
|
server, forceStop := startDAPServer(t, false, serverStopped)
|
||||||
triggerStop(server, forceStop)
|
triggerStop(server, forceStop)
|
||||||
<-serverStopped
|
<-serverStopped
|
||||||
verifyServerStopped(t, server)
|
verifyServerStopped(t, server)
|
||||||
@ -174,7 +179,7 @@ func TestStopNoTarget(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
server, forceStop := startDAPServer(t, serverStopped)
|
server, forceStop := startDAPServer(t, false, serverStopped)
|
||||||
client := daptest.NewClient(server.config.Listener.Addr().String())
|
client := daptest.NewClient(server.config.Listener.Addr().String())
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
@ -201,7 +206,7 @@ func TestStopWithTarget(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
server, forceStop := startDAPServer(t, serverStopped)
|
server, forceStop := startDAPServer(t, false, serverStopped)
|
||||||
client := daptest.NewClient(server.config.Listener.Addr().String())
|
client := daptest.NewClient(server.config.Listener.Addr().String())
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
@ -304,7 +309,7 @@ func TestSessionStop(t *testing.T) {
|
|||||||
|
|
||||||
func TestForceStopWhileStopping(t *testing.T) {
|
func TestForceStopWhileStopping(t *testing.T) {
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
server, forceStop := startDAPServer(t, serverStopped)
|
server, forceStop := startDAPServer(t, false, serverStopped)
|
||||||
client := daptest.NewClient(server.config.Listener.Addr().String())
|
client := daptest.NewClient(server.config.Listener.Addr().String())
|
||||||
|
|
||||||
client.InitializeRequest()
|
client.InitializeRequest()
|
||||||
@ -1950,7 +1955,7 @@ func TestScopesRequestsOptimized(t *testing.T) {
|
|||||||
disconnect: false,
|
disconnect: false,
|
||||||
}})
|
}})
|
||||||
},
|
},
|
||||||
protest.EnableOptimization)
|
protest.EnableOptimization, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestVariablesLoading exposes test cases where variables might be partially or
|
// TestVariablesLoading exposes test cases where variables might be partially or
|
||||||
@ -5407,7 +5412,7 @@ func TestNoDebug_AcceptNoRequestsButDisconnect(t *testing.T) {
|
|||||||
|
|
||||||
func TestLaunchRequestWithRelativeBuildPath(t *testing.T) {
|
func TestLaunchRequestWithRelativeBuildPath(t *testing.T) {
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
client := startDAPServerWithClient(t, serverStopped)
|
client := startDAPServerWithClient(t, false, serverStopped)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
fixdir := protest.FindFixturesDir()
|
fixdir := protest.FindFixturesDir()
|
||||||
@ -5506,7 +5511,7 @@ func TestLaunchTestRequest(t *testing.T) {
|
|||||||
defer os.Chdir(orgWD)
|
defer os.Chdir(orgWD)
|
||||||
}
|
}
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
client := startDAPServerWithClient(t, serverStopped)
|
client := startDAPServerWithClient(t, false, serverStopped)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
runDebugSessionWithBPs(t, client, "launch",
|
runDebugSessionWithBPs(t, client, "launch",
|
||||||
@ -5637,7 +5642,7 @@ func TestLaunchRequestWithEnv(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
client := startDAPServerWithClient(t, serverStopped)
|
client := startDAPServerWithClient(t, false, serverStopped)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
runDebugSessionWithBPs(t, client, "launch", func() { // launch
|
runDebugSessionWithBPs(t, client, "launch", func() { // launch
|
||||||
@ -6547,7 +6552,7 @@ func attachDebuggerWithTargetHalted(t *testing.T, fixture string) (*exec.Cmd, *d
|
|||||||
// process is halted or debug session never launched.)
|
// process is halted or debug session never launched.)
|
||||||
func runTestWithDebugger(t *testing.T, dbg *debugger.Debugger, test func(c *daptest.Client)) {
|
func runTestWithDebugger(t *testing.T, dbg *debugger.Debugger, test func(c *daptest.Client)) {
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
server, _ := startDAPServer(t, serverStopped)
|
server, _ := startDAPServer(t, false, serverStopped)
|
||||||
client := daptest.NewClient(server.listener.Addr().String())
|
client := daptest.NewClient(server.listener.Addr().String())
|
||||||
time.Sleep(100 * time.Millisecond) // Give time for connection to be set as dap.Session
|
time.Sleep(100 * time.Millisecond) // Give time for connection to be set as dap.Session
|
||||||
server.sessionMu.Lock()
|
server.sessionMu.Lock()
|
||||||
@ -6676,7 +6681,7 @@ type MultiClientCloseServerMock struct {
|
|||||||
func NewMultiClientCloseServerMock(t *testing.T, fixture string) *MultiClientCloseServerMock {
|
func NewMultiClientCloseServerMock(t *testing.T, fixture string) *MultiClientCloseServerMock {
|
||||||
var s MultiClientCloseServerMock
|
var s MultiClientCloseServerMock
|
||||||
s.stopped = make(chan struct{})
|
s.stopped = make(chan struct{})
|
||||||
s.impl, s.forceStop = startDAPServer(t, s.stopped)
|
s.impl, s.forceStop = startDAPServer(t, false, s.stopped)
|
||||||
_, s.debugger = launchDebuggerWithTargetHalted(t, "http_server")
|
_, s.debugger = launchDebuggerWithTargetHalted(t, "http_server")
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
@ -6817,7 +6822,7 @@ func TestBadInitializeRequest(t *testing.T) {
|
|||||||
// Only one initialize request is allowed, so use a new server
|
// Only one initialize request is allowed, so use a new server
|
||||||
// for each test.
|
// for each test.
|
||||||
serverStopped := make(chan struct{})
|
serverStopped := make(chan struct{})
|
||||||
client := startDAPServerWithClient(t, serverStopped)
|
client := startDAPServerWithClient(t, false, serverStopped)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
client.InitializeRequestWithArgs(args)
|
client.InitializeRequestWithArgs(args)
|
||||||
@ -7310,3 +7315,37 @@ func TestFindInstructions(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDisassembleCgo(t *testing.T) {
|
||||||
|
// Test that disassembling a program containing cgo code does not create problems.
|
||||||
|
// See issue #3040
|
||||||
|
runTestBuildFlags(t, "cgodisass", func(client *daptest.Client, fixture protest.Fixture) {
|
||||||
|
runDebugSessionWithBPs(t, client, "launch",
|
||||||
|
// Launch
|
||||||
|
func() {
|
||||||
|
client.LaunchRequest("exec", fixture.Path, !stopOnEntry)
|
||||||
|
},
|
||||||
|
// Set breakpoints
|
||||||
|
fixture.Source, []int{11},
|
||||||
|
[]onBreakpoint{{
|
||||||
|
execute: func() {
|
||||||
|
checkStop(t, client, 1, "main.main", 11)
|
||||||
|
|
||||||
|
client.StackTraceRequest(1, 0, 1)
|
||||||
|
st := client.ExpectStackTraceResponse(t)
|
||||||
|
if len(st.Body.StackFrames) < 1 {
|
||||||
|
t.Fatalf("\ngot %#v\nwant len(stackframes) => 1", st)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request the single instruction that the program is stopped at.
|
||||||
|
pc := st.Body.StackFrames[0].InstructionPointerReference
|
||||||
|
|
||||||
|
client.DisassembleRequest(pc, -200, 400)
|
||||||
|
client.ExpectDisassembleResponse(t)
|
||||||
|
},
|
||||||
|
disconnect: true,
|
||||||
|
}},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
protest.AllNonOptimized, true)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user