Skip to content

Commit 05e32ba

Browse files
committed
Revert "Revert "Implement xfer:libraries-svr4:read packet""
This reverts commit 08c38f7. llvm-svn: 366847
1 parent cbbdc41 commit 05e32ba

16 files changed

+366
-5
lines changed

lldb/include/lldb/Host/common/NativeProcessProtocol.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ namespace lldb_private {
3232
class MemoryRegionInfo;
3333
class ResumeActionList;
3434

35+
struct SVR4LibraryInfo {
36+
std::string name;
37+
lldb::addr_t link_map;
38+
lldb::addr_t base_addr;
39+
lldb::addr_t ld_addr;
40+
lldb::addr_t next;
41+
};
42+
3543
// NativeProcessProtocol
3644
class NativeProcessProtocol {
3745
public:
@@ -86,6 +94,12 @@ class NativeProcessProtocol {
8694

8795
virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0;
8896

97+
virtual llvm::Expected<std::vector<SVR4LibraryInfo>>
98+
GetLoadedSVR4Libraries() {
99+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
100+
"Not implemented");
101+
}
102+
89103
virtual bool IsAlive() const;
90104

91105
virtual size_t UpdateThreads() = 0;

lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,8 @@ def prep_debug_monitor_and_inferior(
513513
self,
514514
inferior_args=None,
515515
inferior_sleep_seconds=3,
516-
inferior_exe_path=None):
516+
inferior_exe_path=None,
517+
inferior_env=None):
517518
"""Prep the debug monitor, the inferior, and the expected packet stream.
518519
519520
Handle the separate cases of using the debug monitor in attach-to-inferior mode
@@ -576,6 +577,9 @@ def prep_debug_monitor_and_inferior(
576577

577578
# Build the expected protocol stream
578579
self.add_no_ack_remote_stream()
580+
if inferior_env:
581+
for name, value in inferior_env.items():
582+
self.add_set_environment_packets(name, value)
579583
if self._inferior_startup == self._STARTUP_LAUNCH:
580584
self.add_verified_launch_packets(launch_args)
581585

@@ -656,6 +660,12 @@ def add_process_info_collection_packets(self):
656660
{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$", "capture": {1: "process_info_raw"}}],
657661
True)
658662

663+
def add_set_environment_packets(self, name, value):
664+
self.test_sequence.add_log_lines(
665+
["read packet: $QEnvironment:" + name + "=" + value + "#00",
666+
"send packet: $OK#00",
667+
], True)
668+
659669
_KNOWN_PROCESS_INFO_KEYS = [
660670
"pid",
661671
"parent-pid",
@@ -816,6 +826,7 @@ def parse_memory_region_packet(self, context):
816826
"error"])
817827
self.assertIsNotNone(val)
818828

829+
mem_region_dict["name"] = seven.unhexlify(mem_region_dict.get("name", ""))
819830
# Return the dictionary of key-value pairs for the memory region.
820831
return mem_region_dict
821832

@@ -1000,6 +1011,22 @@ def run_process_then_stop(self, run_seconds=1):
10001011

10011012
return context
10021013

1014+
def continue_process_and_wait_for_stop(self):
1015+
self.test_sequence.add_log_lines(
1016+
[
1017+
"read packet: $vCont;c#a8",
1018+
{
1019+
"direction": "send",
1020+
"regex": r"^\$T([0-9a-fA-F]{2})(.*)#[0-9a-fA-F]{2}$",
1021+
"capture": {1: "stop_signo", 2: "stop_key_val_text"},
1022+
},
1023+
],
1024+
True,
1025+
)
1026+
context = self.expect_gdbremote_sequence()
1027+
self.assertIsNotNone(context)
1028+
return self.parse_interrupt_packets(context)
1029+
10031030
def select_modifiable_register(self, reg_infos):
10041031
"""Find a register that can be read/written freely."""
10051032
PREFERRED_REGISTER_NAMES = set(["rax", ])
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
LEVEL = ../../../make
2+
3+
LIB_PREFIX := svr4lib
4+
LD_EXTRAS := -L. -l$(LIB_PREFIX)_a -l$(LIB_PREFIX)_b\"
5+
CXX_SOURCES := main.cpp
6+
USE_LIBDL := 1
7+
MAKE_DSYM := NO
8+
9+
include $(LEVEL)/Makefile.rules
10+
11+
a.out: $(LIB_PREFIX)_a $(LIB_PREFIX)_b_quote
12+
13+
svr4lib_%:
14+
$(MAKE) VPATH=$(SRCDIR) -I $(SRCDIR) -f "$(SRCDIR)/$(LIB_PREFIX)_$*.mk"
15+
16+
clean::
17+
$(MAKE) -f $(SRCDIR)/$(LIB_PREFIX)_a.mk clean
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import xml.etree.ElementTree as ET
2+
3+
import gdbremote_testcase
4+
from lldbsuite.test.decorators import *
5+
from lldbsuite.test.lldbtest import *
6+
7+
8+
class TestGdbRemoteLibrariesSvr4Support(gdbremote_testcase.GdbRemoteTestCaseBase):
9+
10+
mydir = TestBase.compute_mydir(__file__)
11+
12+
FEATURE_NAME = "qXfer:libraries-svr4:read"
13+
14+
def setup_test(self):
15+
self.init_llgs_test()
16+
self.build()
17+
self.set_inferior_startup_launch()
18+
env = {}
19+
env[self.dylibPath] = self.getBuildDir()
20+
self.prep_debug_monitor_and_inferior(inferior_env=env)
21+
self.continue_process_and_wait_for_stop()
22+
23+
def get_expected_libs(self):
24+
return ["libsvr4lib_a.so", 'libsvr4lib_b".so']
25+
26+
def has_libraries_svr4_support(self):
27+
self.add_qSupported_packets()
28+
context = self.expect_gdbremote_sequence()
29+
self.assertIsNotNone(context)
30+
features = self.parse_qSupported_response(context)
31+
return self.FEATURE_NAME in features and features[self.FEATURE_NAME] == "+"
32+
33+
def get_libraries_svr4_data(self):
34+
# Start up llgs and inferior, and check for libraries-svr4 support.
35+
if not self.has_libraries_svr4_support():
36+
self.skipTest("libraries-svr4 not supported")
37+
38+
# Grab the libraries-svr4 data.
39+
self.reset_test_sequence()
40+
self.test_sequence.add_log_lines(
41+
[
42+
"read packet: $qXfer:libraries-svr4:read::0,ffff:#00",
43+
{
44+
"direction": "send",
45+
"regex": re.compile(
46+
r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL
47+
),
48+
"capture": {1: "response_type", 2: "content_raw"},
49+
},
50+
],
51+
True,
52+
)
53+
54+
context = self.expect_gdbremote_sequence()
55+
self.assertIsNotNone(context)
56+
57+
# Ensure we end up with all libraries-svr4 data in one packet.
58+
self.assertEqual(context.get("response_type"), "l")
59+
60+
# Decode binary data.
61+
content_raw = context.get("content_raw")
62+
self.assertIsNotNone(content_raw)
63+
return content_raw
64+
65+
def get_libraries_svr4_xml(self):
66+
libraries_svr4 = self.get_libraries_svr4_data()
67+
xml_root = None
68+
try:
69+
xml_root = ET.fromstring(libraries_svr4)
70+
except xml.etree.ElementTree.ParseError:
71+
pass
72+
self.assertIsNotNone(xml_root, "Malformed libraries-svr4 XML")
73+
return xml_root
74+
75+
def libraries_svr4_well_formed(self):
76+
xml_root = self.get_libraries_svr4_xml()
77+
self.assertEqual(xml_root.tag, "library-list-svr4")
78+
for child in xml_root:
79+
self.assertEqual(child.tag, "library")
80+
self.assertItemsEqual(child.attrib.keys(), ["name", "lm", "l_addr", "l_ld"])
81+
82+
def libraries_svr4_has_correct_load_addr(self):
83+
xml_root = self.get_libraries_svr4_xml()
84+
for child in xml_root:
85+
name = child.attrib.get("name")
86+
base_name = os.path.basename(name)
87+
if os.path.basename(name) not in self.get_expected_libs():
88+
continue
89+
load_addr = int(child.attrib.get("l_addr"), 16)
90+
self.reset_test_sequence()
91+
self.add_query_memory_region_packets(load_addr)
92+
context = self.expect_gdbremote_sequence()
93+
mem_region = self.parse_memory_region_packet(context)
94+
self.assertEqual(load_addr, int(mem_region.get("start", 0), 16))
95+
self.assertEqual(
96+
os.path.realpath(name), os.path.realpath(mem_region.get("name", ""))
97+
)
98+
99+
def libraries_svr4_libs_present(self):
100+
xml_root = self.get_libraries_svr4_xml()
101+
libraries_svr4_names = []
102+
for child in xml_root:
103+
name = child.attrib.get("name")
104+
libraries_svr4_names.append(os.path.realpath(name))
105+
for lib in self.get_expected_libs():
106+
self.assertIn(self.getBuildDir() + "/" + lib, libraries_svr4_names)
107+
108+
@llgs_test
109+
@skipUnlessPlatform(["linux", "android", "netbsd"])
110+
def test_supports_libraries_svr4(self):
111+
self.setup_test()
112+
self.assertTrue(self.has_libraries_svr4_support())
113+
114+
@llgs_test
115+
@skipUnlessPlatform(["linux", "android", "netbsd"])
116+
def test_libraries_svr4_well_formed(self):
117+
self.setup_test()
118+
self.libraries_svr4_well_formed()
119+
120+
@llgs_test
121+
@skipUnlessPlatform(["linux", "android", "netbsd"])
122+
def test_libraries_svr4_load_addr(self):
123+
self.setup_test()
124+
self.libraries_svr4_has_correct_load_addr()
125+
126+
@llgs_test
127+
@skipUnlessPlatform(["linux", "android", "netbsd"])
128+
def test_libraries_svr4_libs_present(self):
129+
self.setup_test()
130+
self.libraries_svr4_libs_present()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
int main(int argc, char **argv) {
10+
// Perform a null pointer access.
11+
int *const null_int_ptr = nullptr;
12+
*null_int_ptr = 0xDEAD;
13+
14+
return 0;
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
int svr4lib_a() { return 42; }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
LEVEL = ../../../make
2+
3+
LIB_PREFIX := svr4lib
4+
5+
DYLIB_NAME := $(LIB_PREFIX)_a
6+
DYLIB_CXX_SOURCES := $(LIB_PREFIX)_a.cpp
7+
DYLIB_ONLY := YES
8+
9+
include $(LEVEL)/Makefile.rules
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
int svr4lib_b_quote() { return 42; }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
LEVEL = ../../../make
2+
3+
LIB_PREFIX := svr4lib
4+
5+
DYLIB_NAME := $(LIB_PREFIX)_b\"
6+
DYLIB_CXX_SOURCES := $(LIB_PREFIX)_b_quote.cpp
7+
DYLIB_ONLY := YES
8+
9+
include $(LEVEL)/Makefile.rules

lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2076,4 +2076,4 @@ Status NativeProcessLinux::StopProcessorTracingOnThread(lldb::user_id_t traceid,
20762076
m_processor_trace_monitor.erase(iter);
20772077

20782078
return error;
2079-
}
2079+
}

0 commit comments

Comments
 (0)