-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Debuginfod Testing & fixes: 3rd times the charm? (#87676)
I believe I've got the tests properly configured to only run on Linux x86(_64), as I don't have a Linux AArch64/Arm device to diagnose what's going wrong with the tests (I suspect there's some issue with generating `.note.gnu.build-id` sections...) The actual code fixes have now been reviewed 3 times: #79181 (moved shell tests to API tests), #85693 (Changed some of the testing infra), and #86812 (didn't get the tests configured quite right). The Debuginfod integration for symbol acquisition in LLDB now works with the `executable` and `debuginfo` Debuginfod network requests working properly for normal, `objcopy --only-keep-debug` stripped, split-dwarf, and `objcopy --only-keep-debug` stripped *plus* split-dwarf symbols/binaries. The reasons for the multiple attempts have been tests on platforms I don't have access to (Linux AArch64/Arm + MacOS x86_64). I believe I've got the tests properly disabled for everything except for Linux x86(_64) now. I've built & tested on MacOS AArch64 and Linux x86_64. --------- Co-authored-by: Kevin Frei <[email protected]>
- Loading branch information
Showing
10 changed files
with
515 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
# Order matters here: the first symbol locator prevents further searching. | ||
# For DWARF binaries that are both stripped and split, the Default plugin | ||
# will return the stripped binary when asked for the ObjectFile, which then | ||
# prevents an unstripped binary from being requested from the Debuginfod | ||
# provider. | ||
add_subdirectory(Debuginfod) | ||
add_subdirectory(Default) | ||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin") | ||
add_subdirectory(DebugSymbols) | ||
endif() | ||
add_subdirectory(Debuginfod) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
C_SOURCES := main.c | ||
|
||
# For normal (non DWP) Debuginfod tests, we need: | ||
|
||
# * The full binary: a.out.unstripped | ||
# Produced by Makefile.rules with SAVE_FULL_DEBUG_BINARY set to YES and | ||
# SPLIT_DEBUG_SYMBOLS set to YES | ||
|
||
# * The stripped binary (a.out) | ||
# Produced by Makefile.rules with SPLIT_DEBUG_SYMBOLS set to YES | ||
|
||
# * The 'only-keep-debug' binary (a.out.debug) | ||
# Produced below | ||
|
||
SPLIT_DEBUG_SYMBOLS := YES | ||
SAVE_FULL_DEBUG_BINARY := YES | ||
GEN_GNU_BUILD_ID := YES | ||
|
||
include Makefile.rules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
import os | ||
import shutil | ||
import tempfile | ||
|
||
import lldb | ||
from lldbsuite.test.decorators import * | ||
import lldbsuite.test.lldbutil as lldbutil | ||
from lldbsuite.test.lldbtest import * | ||
|
||
|
||
""" | ||
Test support for the DebugInfoD network symbol acquisition protocol. | ||
This one is for simple / no split-dwarf scenarios. | ||
For no-split-dwarf scenarios, there are 2 variations: | ||
1 - A stripped binary with it's corresponding unstripped binary: | ||
2 - A stripped binary with a corresponding --only-keep-debug symbols file | ||
""" | ||
|
||
|
||
# It looks like Linux-AArch64 doesn't support build-id's on the LLDB builtbots | ||
class DebugInfodTests(TestBase): | ||
# No need to try every flavor of debug inf. | ||
NO_DEBUG_INFO_TESTCASE = True | ||
|
||
@skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) | ||
def test_normal_no_symbols(self): | ||
""" | ||
Validate behavior with no symbols or symbol locator. | ||
('baseline negative' behavior) | ||
""" | ||
test_root = self.config_test(["a.out"]) | ||
self.try_breakpoint(False) | ||
|
||
@skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) | ||
def test_normal_default(self): | ||
""" | ||
Validate behavior with symbols, but no symbol locator. | ||
('baseline positive' behavior) | ||
""" | ||
test_root = self.config_test(["a.out", "a.out.debug"]) | ||
self.try_breakpoint(True) | ||
|
||
@skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) | ||
def test_debuginfod_symbols(self): | ||
""" | ||
Test behavior with the full binary available from Debuginfod as | ||
'debuginfo' from the plug-in. | ||
""" | ||
test_root = self.config_test(["a.out"], "a.out.unstripped") | ||
self.try_breakpoint(True) | ||
|
||
@skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) | ||
def test_debuginfod_executable(self): | ||
""" | ||
Test behavior with the full binary available from Debuginfod as | ||
'executable' from the plug-in. | ||
""" | ||
test_root = self.config_test(["a.out"], None, "a.out.unstripped") | ||
self.try_breakpoint(True) | ||
|
||
@skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) | ||
def test_debuginfod_okd_symbols(self): | ||
""" | ||
Test behavior with the 'only-keep-debug' symbols available from Debuginfod. | ||
""" | ||
test_root = self.config_test(["a.out"], "a.out.debug") | ||
self.try_breakpoint(True) | ||
|
||
def try_breakpoint(self, should_have_loc): | ||
""" | ||
This function creates a target from self.aout, sets a function-name | ||
breakpoint, and checks to see if we have a file/line location, | ||
as a way to validate that the symbols have been loaded. | ||
should_have_loc specifies if we're testing that symbols have or | ||
haven't been loaded. | ||
""" | ||
target = self.dbg.CreateTarget(self.aout) | ||
self.assertTrue(target and target.IsValid(), "Target is valid") | ||
|
||
bp = target.BreakpointCreateByName("func") | ||
self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid") | ||
self.assertEqual(bp.GetNumLocations(), 1) | ||
|
||
loc = bp.GetLocationAtIndex(0) | ||
self.assertTrue(loc and loc.IsValid(), "Location is valid") | ||
addr = loc.GetAddress() | ||
self.assertTrue(addr and addr.IsValid(), "Loc address is valid") | ||
line_entry = addr.GetLineEntry() | ||
self.assertEqual( | ||
should_have_loc, | ||
line_entry != None and line_entry.IsValid(), | ||
"Loc line entry is valid", | ||
) | ||
if should_have_loc: | ||
self.assertEqual(line_entry.GetLine(), 4) | ||
self.assertEqual( | ||
line_entry.GetFileSpec().GetFilename(), | ||
self.main_source_file.GetFilename(), | ||
) | ||
self.dbg.DeleteTarget(target) | ||
shutil.rmtree(self.tmp_dir) | ||
|
||
def config_test(self, local_files, debuginfo=None, executable=None): | ||
""" | ||
Set up a test with local_files[] copied to a different location | ||
so that we control which files are, or are not, found in the file system. | ||
Also, create a stand-alone file-system 'hosted' debuginfod server with the | ||
provided debuginfo and executable files (if they exist) | ||
Make the filesystem look like: | ||
/tmp/<tmpdir>/test/[local_files] | ||
/tmp/<tmpdir>/cache (for lldb to use as a temp cache) | ||
/tmp/<tmpdir>/buildid/<uuid>/executable -> <executable> | ||
/tmp/<tmpdir>/buildid/<uuid>/debuginfo -> <debuginfo> | ||
Returns the /tmp/<tmpdir> path | ||
""" | ||
|
||
self.build() | ||
|
||
uuid = self.getUUID("a.out") | ||
if not uuid: | ||
self.fail("Could not get UUID for a.out") | ||
return | ||
self.main_source_file = lldb.SBFileSpec("main.c") | ||
self.tmp_dir = tempfile.mkdtemp() | ||
test_dir = os.path.join(self.tmp_dir, "test") | ||
os.makedirs(test_dir) | ||
|
||
self.aout = "" | ||
# Copy the files used by the test: | ||
for f in local_files: | ||
shutil.copy(self.getBuildArtifact(f), test_dir) | ||
# The first item is the binary to be used for the test | ||
if self.aout == "": | ||
self.aout = os.path.join(test_dir, f) | ||
|
||
use_debuginfod = debuginfo != None or executable != None | ||
|
||
# Populated the 'file://... mocked' Debuginfod server: | ||
if use_debuginfod: | ||
os.makedirs(os.path.join(self.tmp_dir, "cache")) | ||
uuid_dir = os.path.join(self.tmp_dir, "buildid", uuid) | ||
os.makedirs(uuid_dir) | ||
if debuginfo: | ||
shutil.copy( | ||
self.getBuildArtifact(debuginfo), | ||
os.path.join(uuid_dir, "debuginfo"), | ||
) | ||
if executable: | ||
shutil.copy( | ||
self.getBuildArtifact(executable), | ||
os.path.join(uuid_dir, "executable"), | ||
) | ||
|
||
# Configure LLDB for the test: | ||
self.runCmd( | ||
"settings set symbols.enable-external-lookup %s" | ||
% str(use_debuginfod).lower() | ||
) | ||
self.runCmd("settings clear plugin.symbol-locator.debuginfod.server-urls") | ||
if use_debuginfod: | ||
self.runCmd( | ||
"settings set plugin.symbol-locator.debuginfod.cache-path %s/cache" | ||
% self.tmp_dir | ||
) | ||
self.runCmd( | ||
"settings insert-before plugin.symbol-locator.debuginfod.server-urls 0 file://%s" | ||
% self.tmp_dir | ||
) | ||
|
||
def getUUID(self, filename): | ||
try: | ||
target = self.dbg.CreateTarget(self.getBuildArtifact(filename)) | ||
module = target.GetModuleAtIndex(0) | ||
uuid = module.GetUUIDString().replace("-", "").lower() | ||
self.dbg.DeleteTarget(target) | ||
return uuid if len(uuid) == 40 else None | ||
except: | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// This is a dump little pair of test files | ||
|
||
int func(int argc, const char *argv[]) { | ||
return (argc + 1) * (argv[argc][0] + 2); | ||
} | ||
|
||
int main(int argc, const char *argv[]) { return func(0, argv); } |
Oops, something went wrong.