summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note')
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/Makefile11
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py99
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp315
-rw-r--r--gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/main.c2
4 files changed, 427 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/Makefile b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/Makefile
new file mode 100644
index 00000000000..ad37346bbeb
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/Makefile
@@ -0,0 +1,11 @@
+MAKE_DSYM := NO
+
+C_SOURCES := main.c
+
+all: a.out create-empty-corefile
+
+create-empty-corefile:
+ $(MAKE) -f $(MAKEFILE_RULES) EXE=create-empty-corefile \
+ C_SOURCES=create-empty-corefile.c
+
+include Makefile.rules
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py
new file mode 100644
index 00000000000..80007438add
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py
@@ -0,0 +1,99 @@
+"""Test that corefiles with an LC_NOTE "kern ver str" load command is used."""
+
+
+
+import os
+import re
+import subprocess
+
+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\\">"',
+ '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)
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp
new file mode 100644
index 00000000000..8a8115af967
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp
@@ -0,0 +1,315 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/loader.h>
+#include <vector>
+#include <string>
+#include <mach/thread_status.h>
+#include <string.h>
+#include <uuid/uuid.h>
+
+// Create an empty corefile with a "kern ver str" LC_NOTE.
+// If an existing binary is given as an optional 2nd argument on the cmd line,
+// the UUID from that binary will be encoded in the corefile.
+// Otherwise a pre-set UUID will be put in the corefile that
+// is created.
+
+
+union uint32_buf {
+ uint8_t bytebuf[4];
+ uint32_t val;
+};
+
+union uint64_buf {
+ uint8_t bytebuf[8];
+ uint64_t val;
+};
+
+void
+add_uint64(std::vector<uint8_t> &buf, uint64_t val)
+{
+ uint64_buf conv;
+ conv.val = val;
+ for (int i = 0; i < 8; i++)
+ buf.push_back(conv.bytebuf[i]);
+}
+
+void
+add_uint32(std::vector<uint8_t> &buf, uint32_t val)
+{
+ uint32_buf conv;
+ conv.val = val;
+ for (int i = 0; i < 4; i++)
+ buf.push_back(conv.bytebuf[i]);
+}
+
+std::vector<uint8_t>
+x86_lc_thread_load_command ()
+{
+ std::vector<uint8_t> data;
+ add_uint32 (data, LC_THREAD); // thread_command.cmd
+ add_uint32 (data, 184); // thread_command.cmdsize
+ add_uint32 (data, x86_THREAD_STATE64); // thread_command.flavor
+ add_uint32 (data, x86_THREAD_STATE64_COUNT); // thread_command.count
+ add_uint64 (data, 0x0000000000000000); // rax
+ add_uint64 (data, 0x0000000000000400); // rbx
+ add_uint64 (data, 0x0000000000000000); // rcx
+ add_uint64 (data, 0x0000000000000000); // rdx
+ add_uint64 (data, 0x0000000000000000); // rdi
+ add_uint64 (data, 0x0000000000000000); // rsi
+ add_uint64 (data, 0xffffff9246e2ba20); // rbp
+ add_uint64 (data, 0xffffff9246e2ba10); // rsp
+ add_uint64 (data, 0x0000000000000000); // r8
+ add_uint64 (data, 0x0000000000000000); // r9
+ add_uint64 (data, 0x0000000000000000); // r10
+ add_uint64 (data, 0x0000000000000000); // r11
+ add_uint64 (data, 0xffffff7f96ce5fe1); // r12
+ add_uint64 (data, 0x0000000000000000); // r13
+ add_uint64 (data, 0x0000000000000000); // r14
+ add_uint64 (data, 0xffffff9246e2bac0); // r15
+ add_uint64 (data, 0xffffff8015a8f6d0); // rip
+ add_uint64 (data, 0x0000000000011111); // rflags
+ add_uint64 (data, 0x0000000000022222); // cs
+ add_uint64 (data, 0x0000000000033333); // fs
+ add_uint64 (data, 0x0000000000044444); // gs
+ return data;
+}
+
+void
+add_lc_note_kern_ver_str_load_command (std::vector<std::vector<uint8_t> > &loadcmds,
+ std::vector<uint8_t> &payload,
+ int payload_file_offset,
+ std::string ident)
+{
+ std::vector<uint8_t> loadcmd_data;
+
+ add_uint32 (loadcmd_data, LC_NOTE); // note_command.cmd
+ add_uint32 (loadcmd_data, 40); // note_command.cmdsize
+ char lc_note_name[16];
+ memset (lc_note_name, 0, 16);
+ strcpy (lc_note_name, "kern ver str");
+
+ // lc_note.data_owner
+ for (int i = 0; i < 16; i++)
+ loadcmd_data.push_back (lc_note_name[i]);
+
+ // we start writing the payload at payload_file_offset to leave
+ // room at the start for the header & the load commands.
+ uint64_t current_payload_offset = payload.size() + payload_file_offset;
+
+ add_uint64 (loadcmd_data, current_payload_offset); // note_command.offset
+ add_uint64 (loadcmd_data, 4 + ident.size() + 1); // note_command.size
+
+ loadcmds.push_back (loadcmd_data);
+
+ add_uint32 (payload, 1); // kerneL_version_string.version
+ for (int i = 0; i < ident.size() + 1; i++)
+ {
+ payload.push_back (ident[i]);
+ }
+}
+
+void
+add_lc_segment (std::vector<std::vector<uint8_t> > &loadcmds,
+ std::vector<uint8_t> &payload,
+ int payload_file_offset)
+{
+ std::vector<uint8_t> loadcmd_data;
+ struct segment_command_64 seg;
+ seg.cmd = LC_SEGMENT_64;
+ seg.cmdsize = sizeof (struct segment_command_64); // no sections
+ memset (seg.segname, 0, 16);
+ seg.vmaddr = 0xffffff7f96400000;
+ seg.vmsize = 4096;
+ seg.fileoff = payload.size() + payload_file_offset;
+ seg.filesize = 0;
+ seg.maxprot = 1;
+ seg.initprot = 1;
+ seg.nsects = 0;
+ seg.flags = 0;
+
+ uint8_t *p = (uint8_t*) &seg;
+ for (int i = 0; i < sizeof (struct segment_command_64); i++)
+ {
+ loadcmd_data.push_back (*(p + i));
+ }
+ loadcmds.push_back (loadcmd_data);
+}
+
+std::string
+get_uuid_from_binary (const char *fn)
+{
+ FILE *f = fopen(fn, "r");
+ if (f == nullptr)
+ {
+ fprintf (stderr, "Unable to open binary '%s' to get uuid\n", fn);
+ exit(1);
+ }
+ uint32_t num_of_load_cmds = 0;
+ uint32_t size_of_load_cmds = 0;
+ std::string uuid;
+ off_t file_offset = 0;
+
+ uint8_t magic[4];
+ if (::fread (magic, 1, 4, f) != 4)
+ {
+ fprintf (stderr, "Failed to read magic number from input file %s\n", fn);
+ exit (1);
+ }
+ uint8_t magic_32_be[] = {0xfe, 0xed, 0xfa, 0xce};
+ uint8_t magic_32_le[] = {0xce, 0xfa, 0xed, 0xfe};
+ uint8_t magic_64_be[] = {0xfe, 0xed, 0xfa, 0xcf};
+ uint8_t magic_64_le[] = {0xcf, 0xfa, 0xed, 0xfe};
+
+ if (memcmp (magic, magic_32_be, 4) == 0 || memcmp (magic, magic_64_be, 4) == 0)
+ {
+ fprintf (stderr, "big endian corefiles not supported\n");
+ exit (1);
+ }
+
+ ::fseeko (f, 0, SEEK_SET);
+ if (memcmp (magic, magic_32_le, 4) == 0)
+ {
+ struct mach_header mh;
+ if (::fread (&mh, 1, sizeof (mh), f) != sizeof (mh))
+ {
+ fprintf (stderr, "error reading mach header from input file\n");
+ exit (1);
+ }
+ if (mh.cputype != CPU_TYPE_X86_64)
+ {
+ fprintf (stderr, "This tool creates an x86_64 corefile but "
+ "the supplied binary '%s' is cputype 0x%x\n",
+ fn, (uint32_t) mh.cputype);
+ exit (1);
+ }
+ num_of_load_cmds = mh.ncmds;
+ size_of_load_cmds = mh.sizeofcmds;
+ file_offset += sizeof (struct mach_header);
+ }
+ else
+ {
+ struct mach_header_64 mh;
+ if (::fread (&mh, 1, sizeof (mh), f) != sizeof (mh))
+ {
+ fprintf (stderr, "error reading mach header from input file\n");
+ exit (1);
+ }
+ if (mh.cputype != CPU_TYPE_X86_64)
+ {
+ fprintf (stderr, "This tool creates an x86_64 corefile but "
+ "the supplied binary '%s' is cputype 0x%x\n",
+ fn, (uint32_t) mh.cputype);
+ exit (1);
+ }
+ num_of_load_cmds = mh.ncmds;
+ size_of_load_cmds = mh.sizeofcmds;
+ file_offset += sizeof (struct mach_header_64);
+ }
+
+ off_t load_cmds_offset = file_offset;
+
+ for (int i = 0; i < num_of_load_cmds && (file_offset - load_cmds_offset) < size_of_load_cmds; i++)
+ {
+ ::fseeko (f, file_offset, SEEK_SET);
+ uint32_t cmd;
+ uint32_t cmdsize;
+ ::fread (&cmd, sizeof (uint32_t), 1, f);
+ ::fread (&cmdsize, sizeof (uint32_t), 1, f);
+ if (cmd == LC_UUID)
+ {
+ struct uuid_command uuidcmd;
+ ::fseeko (f, file_offset, SEEK_SET);
+ if (::fread (&uuidcmd, 1, sizeof (uuidcmd), f) != sizeof (uuidcmd))
+ {
+ fprintf (stderr, "Unable to read LC_UUID load command.\n");
+ exit (1);
+ }
+ uuid_string_t uuidstr;
+ uuid_unparse (uuidcmd.uuid, uuidstr);
+ uuid = uuidstr;
+ break;
+ }
+ file_offset += cmdsize;
+ }
+ return uuid;
+}
+
+int main (int argc, char **argv)
+{
+ if (argc != 2 && argc != 3)
+ {
+ fprintf (stderr, "usage: create-empty-corefile <output-core-name> [binary-to-copy-uuid-from]\n");
+ fprintf (stderr, "Create a Mach-O corefile with an LC_NOTE 'kern ver str' load command/payload\n");
+ fprintf (stderr, "If a binary is given as a second argument, the Mach-O UUID of that file will\n");
+ fprintf (stderr, "be read and used in the corefile's LC_NOTE payload.\n");
+ exit (1);
+ }
+
+ std::string ident = "EFI UUID=3F9BA21F-55EA-356A-A349-BBA6F51FE8B1";
+ if (argc == 3)
+ {
+ std::string uuid_from_file = get_uuid_from_binary (argv[2]);
+ if (!uuid_from_file.empty())
+ {
+ ident = "EFI UUID=";
+ ident += uuid_from_file;
+ }
+ }
+
+ // An array of load commands (in the form of byte arrays)
+ std::vector<std::vector<uint8_t> > load_commands;
+
+ // An array of corefile contents (page data, lc_note data, etc)
+ std::vector<uint8_t> payload;
+
+ // First add all the load commands / payload so we can figure out how large
+ // the load commands will actually be.
+ load_commands.push_back (x86_lc_thread_load_command());
+ add_lc_note_kern_ver_str_load_command (load_commands, payload, 0, ident);
+ add_lc_segment (load_commands, payload, 0);
+
+ int size_of_load_commands = 0;
+ for (const auto &lc : load_commands)
+ size_of_load_commands += lc.size();
+
+ int header_and_load_cmd_room = sizeof (struct mach_header_64) + size_of_load_commands;
+
+ // Erease the load commands / payload now that we know how much space is needed,
+ // redo it.
+ load_commands.clear();
+ payload.clear();
+
+ load_commands.push_back (x86_lc_thread_load_command());
+ add_lc_note_kern_ver_str_load_command (load_commands, payload, header_and_load_cmd_room, ident);
+ add_lc_segment (load_commands, payload, header_and_load_cmd_room);
+
+ struct mach_header_64 mh;
+ mh.magic = MH_MAGIC_64;
+ mh.cputype = CPU_TYPE_X86_64;
+ mh.cpusubtype = CPU_SUBTYPE_X86_64_ALL;
+ mh.filetype = MH_CORE;
+ mh.ncmds = load_commands.size();
+ mh.sizeofcmds = size_of_load_commands;
+ mh.flags = 0;
+ mh.reserved = 0;
+
+
+ FILE *f = fopen (argv[1], "w");
+
+ if (f == nullptr)
+ {
+ fprintf (stderr, "Unable to open file %s for writing\n", argv[1]);
+ exit (1);
+ }
+
+ fwrite (&mh, sizeof (struct mach_header_64), 1, f);
+
+ for (const auto &lc : load_commands)
+ fwrite (lc.data(), lc.size(), 1, f);
+
+ fseek (f, header_and_load_cmd_room, SEEK_SET);
+
+ fwrite (payload.data(), payload.size(), 1, f);
+
+ fclose (f);
+}
diff --git a/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/main.c b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/main.c
new file mode 100644
index 00000000000..70a72e0b80b
--- /dev/null
+++ b/gnu/llvm/lldb/packages/Python/lldbsuite/test/macosx/lc-note/kern-ver-str/main.c
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int main () { puts ("this is the lc-note test program."); }