Skip to content

Commit

Permalink
Add support to ProcessMachCore::DoLoadCore to handle an EFI UUID str.
Browse files Browse the repository at this point in the history
If a core file has an EFI version string which includes a UUID
(similar to what it returns for the kdp KDP_KERNELVERSION packet)
in the LC_IDENT or LC_NOTE 'kern ver str' load command.  In that
case, we should try to find the binary and dSYM for the UUID
listed.  The dSYM may have python code which knows how to relocate
the binary to the correct address in lldb's target section load
list and loads other ancillary binaries.

The test case is a little involved,

1. it compiles an inferior hello world apple (a.out),
2. it compiles a program which can create a corefile manually
   with a specific binary's UUID encoded in it,
3. it gets the UUID of the a.out binary,
4. it creates a shell script, dsym-for-uuid.sh, which will
   return the full path to the a.out + a.out.dSYM when called
   with teh correct UUID,
5. it sets the LLDB_APPLE_DSYMFORUUID_EXECUTABLE env var before
   creating the lldb target, to point to this dsym-for-uuid.sh,
6. runs the create-corefile binary we compiled in step rust-lang#2,
7. loads the corefile from step rust-lang#6 into lldb,
8. verifies that lldb loaded a.out by reading the LC_NOTE
   load command from the corefile, calling dsym-for-uuid.sh with
   that UUID, got back the path to a.out and loaded it.

whew!

<rdar://problem/47562911>

llvm-svn: 366378
  • Loading branch information
jasonmolenda committed Jul 17, 2019
1 parent d0ac007 commit be4be61
Show file tree
Hide file tree
Showing 6 changed files with 497 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
LEVEL = ../../../make

MAKE_DSYM := NO

C_SOURCES := main.c

all: a.out create-empty-corefile

create-empty-corefile:
$(MAKE) VPATH=$(VPATH) -f $(SRCDIR)/create-empty-corefile.mk

clean::
$(MAKE) -f create-empty-corefile.mk clean

include $(LEVEL)/Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Test that corefiles with an LC_NOTE "kern ver str" load command is used."""

from __future__ import print_function


import os
import re
import subprocess
import sys

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class TestKernVerStrLCNOTE(TestBase):

mydir = TestBase.compute_mydir(__file__)

@skipIf(debug_info=no_match(["dsym"]), bugnumber="This test is looking explicitly for a dSYM")
@skipIfDarwinEmbedded
@skipUnlessDarwin
def test_lc_note(self):
self.build()
self.test_exe = self.getBuildArtifact("a.out")
self.create_corefile = self.getBuildArtifact("create-empty-corefile")
self.dsym_for_uuid = self.getBuildArtifact("dsym-for-uuid.sh")
self.corefile = self.getBuildArtifact("core")

## We can hook in our dsym-for-uuid shell script to lldb with this env
## var instead of requiring a defaults write.
os.environ['LLDB_APPLE_DSYMFORUUID_EXECUTABLE'] = self.dsym_for_uuid
self.addTearDownHook(lambda: os.environ.pop('LLDB_APPLE_DSYMFORUUID_EXECUTABLE', None))

dwarfdump_uuid_regex = re.compile(
'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*')
dwarfdump_cmd_output = subprocess.check_output(
('/usr/bin/dwarfdump --uuid "%s"' % self.test_exe), shell=True).decode("utf-8")
aout_uuid = None
for line in dwarfdump_cmd_output.splitlines():
match = dwarfdump_uuid_regex.search(line)
if match:
aout_uuid = match.group(1)
self.assertNotEqual(aout_uuid, None, "Could not get uuid of built a.out")

### Create our dsym-for-uuid shell script which returns self.test_exe
### and its dSYM when given self.test_exe's UUID.
shell_cmds = [
'#! /bin/sh',
'ret=0',
'echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>"',
'echo "<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">"',
'date >> /tmp/log',
'echo "<plist version=\\"1.0\\">"',
'',
'# the last arugment is probably the uuid',
'while [ $# -gt 1 ]',
'do',
' shift',
'done',
'echo "<dict><key>$1</key><dict>"',
'',
'if [ "$1" = "%s" ]' % aout_uuid,
'then',
' echo "<key>DBGArchitecture</key><string>x86_64</string>"',
' echo "<key>DBGDSYMPath</key><string>%s.dSYM/Contents/Resources/DWARF/%s</string>"' % (self.test_exe, os.path.basename(self.test_exe)),
' echo "<key>DBGSymbolRichExecutable</key><string>%s</string>"' % self.test_exe,
'else',
' echo "<key>DBGError</key><string>not found</string>"',
' ret=1',
'fi',
'echo "</dict></dict></plist>"',
'exit $ret'
]

with open(self.dsym_for_uuid, "w") as writer:
for l in shell_cmds:
writer.write(l + '\n')

os.chmod(self.dsym_for_uuid, 0o755)

### Create our corefile
retcode = call(self.create_corefile + " " + self.corefile + " " + self.test_exe, shell=True)

### Now run lldb on the corefile
### which will give us a UUID
### which we call dsym-for-uuid.sh with
### which gives us a binary and dSYM
### which lldb should load!


self.target = self.dbg.CreateTarget('')
err = lldb.SBError()
self.process = self.target.LoadCore(self.corefile)
self.assertEqual(self.process.IsValid(), True)
if self.TraceOn():
self.runCmd("image list")
self.assertEqual(self.target.GetNumModules(), 1)
fspec = self.target.GetModuleAtIndex(0).GetFileSpec()
filepath = fspec.GetDirectory() + "/" + fspec.GetFilename()
self.assertEqual(filepath, self.test_exe)
Loading

0 comments on commit be4be61

Please sign in to comment.