This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rG223e8ca02616: Set a default number of address bits on Darwin 
arm64 systems (authored by jasonmolenda).

Changed prior to commit:
  https://reviews.llvm.org/D115431?vs=393213&id=393378#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115431/new/

https://reviews.llvm.org/D115431

Files:
  lldb/source/DataFormatters/CXXFunctionPointer.cpp
  lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Utility/ArchSpec.cpp
  lldb/test/API/macosx/corefile-default-ptrauth/Makefile
  lldb/test/API/macosx/corefile-default-ptrauth/TestCorefileDefaultPtrauth.py
  lldb/test/API/macosx/corefile-default-ptrauth/create-corefile.c
  lldb/test/API/macosx/corefile-default-ptrauth/main.c

Index: lldb/test/API/macosx/corefile-default-ptrauth/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/corefile-default-ptrauth/main.c
@@ -0,0 +1,6 @@
+int main();
+int (*fmain)() = main;
+int main () {
+  return fmain();
+}
+
Index: lldb/test/API/macosx/corefile-default-ptrauth/create-corefile.c
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/corefile-default-ptrauth/create-corefile.c
@@ -0,0 +1,131 @@
+#include <mach-o/loader.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach/machine.h>
+#include <string.h>
+#include <mach/machine/thread_state.h>
+#include <inttypes.h>
+#include <sys/syslimits.h>
+
+// Given an executable binary with 
+//   "fmain" (a function pointer to main)
+//   "main"
+// symbols, create a fake arm64e corefile that
+// contains a memory segment for the fmain 
+// function pointer, with the value of the 
+// address of main() with ptrauth bits masked on.
+//
+// The corefile does not include the "addrable bits"
+// LC_NOTE, so lldb will need to fall back on its 
+// default value from the Darwin arm64 ABI.
+
+int main(int argc, char **argv)
+{
+  if (argc != 3) {
+    fprintf (stderr, "usage: %s executable-binary output-file\n", argv[0]);
+    exit(1);
+  }
+  FILE *exe = fopen(argv[1], "r");
+  if (!exe) {
+    fprintf (stderr, "Unable to open executable %s for reading\n", argv[1]);
+    exit(1);
+  }
+  FILE *out = fopen(argv[2], "w");
+  if (!out) {
+    fprintf (stderr, "Unable to open %s for writing\n", argv[2]);
+    exit(1);
+  }
+
+  char buf[PATH_MAX + 6];
+  sprintf (buf, "nm '%s'", argv[1]);
+  FILE *nm = popen(buf, "r");
+  if (!nm) {
+    fprintf (stderr, "Unable to run nm on '%s'", argv[1]);
+    exit (1);
+  }
+  uint64_t main_addr = 0;
+  uint64_t fmain_addr = 0;
+  while (fgets (buf, sizeof(buf), nm)) {
+    if (strstr (buf, "_fmain")) {
+      fmain_addr = strtoul (buf, NULL, 16);
+    }
+    if (strstr (buf, "_main")) {
+      main_addr = strtoul (buf, NULL, 16);
+    }
+  }
+  pclose (nm);
+
+  if (main_addr == 0 || fmain_addr == 0) {
+    fprintf(stderr, "Unable to find address of main or fmain in %s.\n",
+        argv[1]);
+    exit (1);
+  }
+
+  // Write out a corefile with contents in this order:
+  //    1. mach header
+  //    2. LC_THREAD load command
+  //    3. LC_SEGMENT_64 load command
+  //    4. memory segment contents
+
+  // struct thread_command {
+  //       uint32_t        cmd;    
+  //       uint32_t        cmdsize;
+  //       uint32_t flavor      
+  //       uint32_t count       
+  //       struct XXX_thread_state state
+  int size_of_thread_cmd = 4 + 4 + 4 + 4 + sizeof (arm_thread_state64_t);
+
+  struct mach_header_64 mh;
+  mh.magic = 0xfeedfacf;
+  mh.cputype = CPU_TYPE_ARM64;
+  mh.cpusubtype = CPU_SUBTYPE_ARM64E;
+  mh.filetype = MH_CORE;
+  mh.ncmds = 2; // LC_THREAD, LC_SEGMENT_64
+  mh.sizeofcmds = size_of_thread_cmd + sizeof(struct segment_command_64);
+  mh.flags = 0;
+  mh.reserved = 0;
+
+  fwrite(&mh, sizeof (mh), 1, out);
+
+  struct segment_command_64 seg;
+  seg.cmd = LC_SEGMENT_64;
+  seg.cmdsize = sizeof(seg);
+  memset (&seg.segname, 0, 16);
+  seg.vmaddr = fmain_addr;
+  seg.vmsize = 8;
+  // Offset to segment contents
+  seg.fileoff = sizeof (mh) + size_of_thread_cmd + sizeof(seg);
+  seg.filesize = 8;
+  seg.maxprot = 3;
+  seg.initprot = 3;
+  seg.nsects = 0;
+  seg.flags = 0;
+
+  fwrite (&seg, sizeof (seg), 1, out);
+
+  uint32_t cmd = LC_THREAD;
+  fwrite (&cmd, sizeof (cmd), 1, out);
+  uint32_t cmdsize = size_of_thread_cmd;
+  fwrite (&cmdsize, sizeof (cmdsize), 1, out);
+  uint32_t flavor = ARM_THREAD_STATE64;
+  fwrite (&flavor, sizeof (flavor), 1, out);
+  // count is number of uint32_t's of the register context
+  uint32_t count = sizeof (arm_thread_state64_t) / 4;
+  fwrite (&count, sizeof (count), 1, out);
+  arm_thread_state64_t regstate;
+  memset (&regstate, 0, sizeof (regstate));
+  fwrite (&regstate, sizeof (regstate), 1, out);
+
+
+  // Or together a random PAC value from a system using 39 bits 
+  // of addressing with the address of main().  lldb will need
+  // to correctly strip off the high bits to find the address of
+  // main.
+  uint64_t segment_contents = 0xe46bff0000000000 | main_addr;
+
+  fwrite (&segment_contents, sizeof (segment_contents), 1, out);
+
+  fclose (out);
+
+  exit (0);
+}
Index: lldb/test/API/macosx/corefile-default-ptrauth/TestCorefileDefaultPtrauth.py
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/corefile-default-ptrauth/TestCorefileDefaultPtrauth.py
@@ -0,0 +1,50 @@
+"""Test that lldb has a default mask for addressable bits on Darwin arm64 ABI"""
+
+
+import os
+import re
+import subprocess
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestCorefileDefaultPtrauth(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipIf(debug_info=no_match(["dsym"]), bugnumber="This test is looking explicitly for a dSYM")
+    @skipIf(archs=no_match(['arm64','arm64e']))
+    @skipUnlessDarwin
+    def test_lc_note(self):
+        self.build()
+        self.test_exe = self.getBuildArtifact("a.out")
+        self.create_corefile = self.getBuildArtifact("create-corefile")
+        self.corefile = self.getBuildArtifact("core")
+
+        ### Create our corefile
+        retcode = call(self.create_corefile + " " +  self.test_exe + " " + self.corefile, shell=True)
+
+        ## This corefile has no metadata telling us how many bits are
+        ## used for ptrauth signed function pointers.  We will need lldb
+        ## to fall back on its old default value for Darwin arm64 ABIs
+        ## to correctly strip the bits.
+
+        self.target = self.dbg.CreateTarget('')
+        err = lldb.SBError()
+        self.process = self.target.LoadCore(self.corefile)
+        self.assertEqual(self.process.IsValid(), True)
+        modspec = lldb.SBModuleSpec()
+        modspec.SetFileSpec(lldb.SBFileSpec(self.test_exe, True))
+        m = self.target.AddModule(modspec)
+        self.assertTrue(m.IsValid())
+        self.target.SetModuleLoadAddress (m, 0)
+        
+        # target variable should show us both the actual function
+        # pointer with ptrauth bits and the symbol it resolves to,
+        # with the ptrauth bits stripped, e.g.
+        #  (int (*)(...)) fmain = 0xe46bff0100003f90 (actual=0x0000000100003f90 a.out`main at main.c:3)
+
+        self.expect("target variable fmain", substrs=['fmain = 0x', '(actual=0x', 'main at main.c'])
Index: lldb/test/API/macosx/corefile-default-ptrauth/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/corefile-default-ptrauth/Makefile
@@ -0,0 +1,12 @@
+C_SOURCES := main.c
+
+# compile a.out and create-corefile
+# create-corefile will create a custom corefile using the symbols
+# addresses from the a.out binary.
+all: a.out create-corefile
+
+create-corefile:
+	$(MAKE) -f $(MAKEFILE_RULES) EXE=create-corefile \
+		C_SOURCES=create-corefile.c
+
+include Makefile.rules
Index: lldb/source/Utility/ArchSpec.cpp
===================================================================
--- lldb/source/Utility/ArchSpec.cpp
+++ lldb/source/Utility/ArchSpec.cpp
@@ -859,6 +859,7 @@
         m_triple.setArchName(llvm::StringRef(core_def->name));
         if (arch_type == eArchTypeMachO) {
           m_triple.setVendor(llvm::Triple::Apple);
+          m_triple.setObjectFormat(llvm::Triple::MachO);
 
           // Don't set the OS.  It could be simulator, macosx, ios, watchos,
           // tvos, bridgeos.  We could get close with the cpu type - but we
Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -5154,17 +5154,7 @@
   }
 
   if (!found_any) {
-    if (header.filetype == MH_KEXT_BUNDLE) {
-      base_triple.setVendor(llvm::Triple::Apple);
-      add_triple(base_triple);
-    } else {
-      // We didn't find a LC_VERSION_MIN load command and this isn't a KEXT
-      // so lets not say our Vendor is Apple, leave it as an unspecified
-      // unknown.
-      base_triple.setVendor(llvm::Triple::UnknownVendor);
-      base_triple.setVendorName(llvm::StringRef());
-      add_triple(base_triple);
-    }
+    add_triple(base_triple);
   }
 }
 
Index: lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
===================================================================
--- lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
@@ -817,6 +817,16 @@
 
 lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) {
   lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;
+  // Darwin systems originally couldn't determine the proper value
+  // dynamically, so the most common value was hardcoded.  This has
+  // largely been cleaned up, but there are still a handful of
+  // environments that assume the default value is set to this value
+  // and there's no dynamic value to correct it.
+  // When no mask is specified, set it to 39 bits of addressing (0..38).
+  if (mask == 0) {
+    // ~((1ULL<<39)-1)
+    mask = 0xffffff8000000000;
+  }
   return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
 }
 
Index: lldb/source/DataFormatters/CXXFunctionPointer.cpp
===================================================================
--- lldb/source/DataFormatters/CXXFunctionPointer.cpp
+++ lldb/source/DataFormatters/CXXFunctionPointer.cpp
@@ -9,6 +9,7 @@
 #include "lldb/DataFormatters/CXXFunctionPointer.h"
 
 #include "lldb/Core/ValueObject.h"
+#include "lldb/Target/ABI.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/Stream.h"
@@ -38,8 +39,34 @@
       Address so_addr;
       Target *target = exe_ctx.GetTargetPtr();
       if (target && !target->GetSectionLoadList().IsEmpty()) {
-        if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address,
-                                                            so_addr)) {
+        target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address,
+                                                        so_addr);
+        if (so_addr.GetSection() == nullptr) {
+          // If we have an address that doesn't correspond to any symbol,
+          // it might have authentication bits.  Strip them & see if it
+          // now points to a symbol -- if so, do the SymbolContext lookup
+          // based on the stripped address.
+          // If we find a symbol with the ptrauth bits stripped, print the
+          // raw value into the stream, and replace the Address with the
+          // one that points to a symbol for a fuller description.
+          if (Process *process = exe_ctx.GetProcessPtr()) {
+            if (ABISP abi_sp = process->GetABI()) {
+              addr_t fixed_addr = abi_sp->FixCodeAddress(func_ptr_address);
+              if (fixed_addr != func_ptr_address) {
+                Address test_address;
+                test_address.SetLoadAddress(fixed_addr, target);
+                if (test_address.GetSection() != nullptr) {
+                  int addrsize = target->GetArchitecture().GetAddressByteSize();
+                  sstr.Printf("actual=0x%*.*" PRIx64 " ", addrsize * 2,
+                              addrsize * 2, fixed_addr);
+                  so_addr = test_address;
+                }
+              }
+            }
+          }
+        }
+
+        if (so_addr.IsValid()) {
           so_addr.Dump(&sstr, exe_ctx.GetBestExecutionContextScope(),
                        Address::DumpStyleResolvedDescription,
                        Address::DumpStyleSectionNameOffset);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to