xref: /llvm-project/lldb/test/API/lang/c/tls_globals/TestTlsGlobals.py (revision d93a126090b6e772d3b96f201cdd44ea0d6360ef)
1"""Test that thread-local storage can be read correctly."""
2
3
4import os
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import lldbutil
9
10
11class TlsGlobalTestCase(TestBase):
12    def setUp(self):
13        TestBase.setUp(self)
14
15        if self.getPlatform() == "freebsd" or self.getPlatform() == "linux":
16            # LD_LIBRARY_PATH must be set so the shared libraries are found on
17            # startup
18            if "LD_LIBRARY_PATH" in os.environ:
19                self.runCmd(
20                    "settings set target.env-vars "
21                    + self.dylibPath
22                    + "="
23                    + os.environ["LD_LIBRARY_PATH"]
24                    + ":"
25                    + self.getBuildDir()
26                )
27            else:
28                self.runCmd(
29                    "settings set target.env-vars "
30                    + self.dylibPath
31                    + "="
32                    + self.getBuildDir()
33                )
34            self.addTearDownHook(
35                lambda: self.runCmd("settings remove target.env-vars " + self.dylibPath)
36            )
37
38    # TLS works differently on Windows, this would need to be implemented
39    # separately.
40    @skipIfWindows
41    @skipIf(oslist=["linux"], archs=["arm", "aarch64"])
42    @skipIf(oslist=no_match([lldbplatformutil.getDarwinOSTriples(), "linux"]))
43    @expectedFailureIf(lldbplatformutil.xcode15LinkerBug())
44    def test(self):
45        """Test thread-local storage."""
46        self.build()
47        exe = self.getBuildArtifact("a.out")
48        target = self.dbg.CreateTarget(exe)
49        if self.platformIsDarwin():
50            self.registerSharedLibrariesWithTarget(target, ["liba.dylib"])
51
52        line1 = line_number("main.c", "// thread breakpoint")
53        lldbutil.run_break_set_by_file_and_line(
54            self, "main.c", line1, num_expected_locations=1, loc_exact=True
55        )
56        self.runCmd("run", RUN_SUCCEEDED)
57
58        # The stop reason of the thread should be breakpoint.
59        self.runCmd("process status", "Get process status")
60        self.expect(
61            "thread list",
62            STOPPED_DUE_TO_BREAKPOINT,
63            substrs=["stopped", "stop reason = breakpoint"],
64        )
65
66        # BUG: sometimes lldb doesn't change threads to the stopped thread.
67        # (unrelated to this test).
68        self.runCmd("thread select 2", "Change thread")
69
70        # Check that TLS evaluates correctly within the thread.
71        self.expect(
72            "expr var_static",
73            VARIABLES_DISPLAYED_CORRECTLY,
74            patterns=["\(int\) \$.* = 88"],
75        )
76        self.expect(
77            "expr var_shared",
78            VARIABLES_DISPLAYED_CORRECTLY,
79            patterns=["\(int\) \$.* = 66"],
80        )
81
82        # Continue on the main thread
83        line2 = line_number("main.c", "// main breakpoint")
84        lldbutil.run_break_set_by_file_and_line(
85            self, "main.c", line2, num_expected_locations=1, loc_exact=True
86        )
87        self.runCmd("continue", RUN_SUCCEEDED)
88
89        # The stop reason of the thread should be breakpoint.
90        self.runCmd("process status", "Get process status")
91        self.expect(
92            "thread list",
93            STOPPED_DUE_TO_BREAKPOINT,
94            substrs=["stopped", "stop reason = breakpoint"],
95        )
96
97        # BUG: sometimes lldb doesn't change threads to the stopped thread.
98        # (unrelated to this test).
99        self.runCmd("thread select 1", "Change thread")
100
101        # Check that TLS evaluates correctly within the main thread.
102        self.expect(
103            "expr var_static",
104            VARIABLES_DISPLAYED_CORRECTLY,
105            patterns=["\(int\) \$.* = 44"],
106        )
107        self.expect(
108            "expr var_shared",
109            VARIABLES_DISPLAYED_CORRECTLY,
110            patterns=["\(int\) \$.* = 33"],
111        )
112