Trunk merge.
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 78ddf7e..2365f0a 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -44,7 +44,7 @@
 :class:`Bytecode` object that provides easy access to details of the
 compiled code.
 
-.. class:: Bytecode(x, *, first_line=None)
+.. class:: Bytecode(x, *, first_line=None, current_offset=None)
 
    Analyse the bytecode corresponding to a function, method, string of
    source code, or a code object (as returned by :func:`compile`).
@@ -59,6 +59,16 @@
    Otherwise, the source line information (if any) is taken directly from
    the disassembled code object.
 
+   If *current_offset* is not None, it refers to an instruction offset
+   in the disassembled code. Setting this means :meth:`dis` will display
+   a "current instruction" marker against the specified opcode.
+
+   .. classmethod:: from_traceback(tb)
+
+      Construct a :class:`Bytecode` instance from the given traceback,
+      setting *current_offset* to the instruction responsible for the
+      exception.
+
    .. data:: codeobj
 
       The compiled code object.
diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst
index 22d168e..6db3d63 100644
--- a/Doc/whatsnew/3.4.rst
+++ b/Doc/whatsnew/3.4.rst
@@ -385,7 +385,8 @@
 inspecting bytecode, both in human-readable form and for iterating over
 instructions.
 
-(Contributed by Nick Coghlan, Ryan Kelly and Thomas Kluyver in :issue:`11816`)
+(Contributed by Nick Coghlan, Ryan Kelly and Thomas Kluyver in :issue:`11816`
+and Claudiu Popa in :issue:`17916`)
 
 
 doctest
diff --git a/Lib/dis.py b/Lib/dis.py
index 1fafcc5..81cbe7f 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -406,7 +406,7 @@
 
     Iterating over this yields the bytecode operations as Instruction instances.
     """
-    def __init__(self, x, *, first_line=None):
+    def __init__(self, x, *, first_line=None, current_offset=None):
         self.codeobj = co = _get_code_object(x)
         if first_line is None:
             self.first_line = co.co_firstlineno
@@ -417,6 +417,7 @@
         self._cell_names = co.co_cellvars + co.co_freevars
         self._linestarts = dict(findlinestarts(co))
         self._original_object = x
+        self.current_offset = current_offset
 
     def __iter__(self):
         co = self.codeobj
@@ -429,6 +430,13 @@
         return "{}({!r})".format(self.__class__.__name__,
                                  self._original_object)
 
+    @classmethod
+    def from_traceback(cls, tb):
+        """ Construct a Bytecode from the given traceback """
+        while tb.tb_next:
+            tb = tb.tb_next
+        return cls(tb.tb_frame.f_code, current_offset=tb.tb_lasti)
+
     def info(self):
         """Return formatted information about the code object."""
         return _format_code_info(self.codeobj)
@@ -436,13 +444,18 @@
     def dis(self):
         """Return a formatted view of the bytecode operations."""
         co = self.codeobj
+        if self.current_offset is not None:
+            offset = self.current_offset
+        else:
+            offset = -1
         with io.StringIO() as output:
             _disassemble_bytes(co.co_code, varnames=co.co_varnames,
                                names=co.co_names, constants=co.co_consts,
                                cells=self._cell_names,
                                linestarts=self._linestarts,
                                line_offset=self._line_offset,
-                               file=output)
+                               file=output,
+                               lasti=offset)
             return output.getvalue()
 
 
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 2b54678..94d6be7 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -10,6 +10,21 @@
 import types
 import contextlib
 
+def get_tb():
+    def _error():
+        try:
+            1 / 0
+        except Exception as e:
+            tb = e.__traceback__
+        return tb
+
+    tb = _error()
+    while tb.tb_next:
+        tb = tb.tb_next
+    return tb
+
+TRACEBACK_CODE = get_tb().tb_frame.f_code
+
 class _C:
     def __init__(self, x):
         self.x = x == 1
@@ -174,6 +189,46 @@
              25 RETURN_VALUE
 """
 
+dis_traceback = """\
+ %-4d         0 SETUP_EXCEPT            12 (to 15)
+
+ %-4d         3 LOAD_CONST               1 (1)
+              6 LOAD_CONST               2 (0)
+    -->       9 BINARY_TRUE_DIVIDE
+             10 POP_TOP
+             11 POP_BLOCK
+             12 JUMP_FORWARD            46 (to 61)
+
+ %-4d   >>   15 DUP_TOP
+             16 LOAD_GLOBAL              0 (Exception)
+             19 COMPARE_OP              10 (exception match)
+             22 POP_JUMP_IF_FALSE       60
+             25 POP_TOP
+             26 STORE_FAST               0 (e)
+             29 POP_TOP
+             30 SETUP_FINALLY           14 (to 47)
+
+ %-4d        33 LOAD_FAST                0 (e)
+             36 LOAD_ATTR                1 (__traceback__)
+             39 STORE_FAST               1 (tb)
+             42 POP_BLOCK
+             43 POP_EXCEPT
+             44 LOAD_CONST               0 (None)
+        >>   47 LOAD_CONST               0 (None)
+             50 STORE_FAST               0 (e)
+             53 DELETE_FAST              0 (e)
+             56 END_FINALLY
+             57 JUMP_FORWARD             1 (to 61)
+        >>   60 END_FINALLY
+
+ %-4d   >>   61 LOAD_FAST                1 (tb)
+             64 RETURN_VALUE
+""" % (TRACEBACK_CODE.co_firstlineno + 1,
+       TRACEBACK_CODE.co_firstlineno + 2,
+       TRACEBACK_CODE.co_firstlineno + 3,
+       TRACEBACK_CODE.co_firstlineno + 4,
+       TRACEBACK_CODE.co_firstlineno + 5)
+
 class DisTests(unittest.TestCase):
 
     def get_disassembly(self, func, lasti=-1, wrapper=True):
@@ -758,6 +813,17 @@
         actual = dis.Bytecode(_f).dis()
         self.assertEqual(actual, dis_f)
 
+    def test_from_traceback(self):
+        tb = get_tb()
+        b = dis.Bytecode.from_traceback(tb)
+        while tb.tb_next: tb = tb.tb_next
+
+        self.assertEqual(b.current_offset, tb.tb_lasti)
+
+    def test_from_traceback_dis(self):
+        tb = get_tb()
+        b = dis.Bytecode.from_traceback(tb)
+        self.assertEqual(b.dis(), dis_traceback)
 
 def test_main():
     run_unittest(DisTests, DisWithFileTests, CodeInfoTests,
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 4ebc4b0..7374327 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -536,21 +536,22 @@
         self.assertRaises(TypeError, ssl.enum_certificates)
         self.assertRaises(WindowsError, ssl.enum_certificates, "")
 
-        names = set()
-        ca = ssl.enum_certificates("CA")
-        self.assertIsInstance(ca, list)
-        for element in ca:
-            self.assertIsInstance(element, tuple)
-            self.assertEqual(len(element), 3)
-            cert, enc, trust = element
-            self.assertIsInstance(cert, bytes)
-            self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
-            self.assertIsInstance(trust, (set, bool))
-            if isinstance(trust, set):
-                names.update(trust)
+        trust_oids = set()
+        for storename in ("CA", "ROOT"):
+            store = ssl.enum_certificates(storename)
+            self.assertIsInstance(store, list)
+            for element in store:
+                self.assertIsInstance(element, tuple)
+                self.assertEqual(len(element), 3)
+                cert, enc, trust = element
+                self.assertIsInstance(cert, bytes)
+                self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
+                self.assertIsInstance(trust, (set, bool))
+                if isinstance(trust, set):
+                    trust_oids.update(trust)
 
         serverAuth = "1.3.6.1.5.5.7.3.1"
-        self.assertIn(serverAuth, names)
+        self.assertIn(serverAuth, trust_oids)
 
     @unittest.skipUnless(sys.platform == "win32", "Windows specific")
     def test_enum_crls(self):
@@ -584,7 +585,8 @@
         self.assertEqual(val, expected)
         self.assertIsInstance(val, ssl._ASN1Object)
         self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1)
-        self.assertRaises(ValueError, ssl._ASN1Object.fromnid, 100000)
+        with self.assertRaisesRegex(ValueError, "unknown NID 100000"):
+            ssl._ASN1Object.fromnid(100000)
         for i in range(1000):
             try:
                 obj = ssl._ASN1Object.fromnid(i)
@@ -602,7 +604,8 @@
         self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected)
         self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'),
                          expected)
-        self.assertRaises(ValueError, ssl._ASN1Object.fromname, 'serverauth')
+        with self.assertRaisesRegex(ValueError, "unknown object 'serverauth'"):
+            ssl._ASN1Object.fromname('serverauth')
 
 
 class ContextTests(unittest.TestCase):
diff --git a/Misc/NEWS b/Misc/NEWS
index 24ca366..35bca00 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -65,6 +65,10 @@
 Library
 -------
 
+- Issue #17916: Added dis.Bytecode.from_traceback() and
+  dis.Bytecode.current_offset to easily display "current instruction"
+  markers in the new disassembly API (Patch by Claudiu Popa).
+
 - Issue #19552: venv now supports bootstrapping pip into virtual environments
 
 - Issue #17134: Finalize interface to Windows' certificate store. Cert and
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index f32d180..180355b 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -3387,7 +3387,7 @@
     }
     obj = OBJ_txt2obj(txt, name ? 0 : 1);
     if (obj == NULL) {
-        PyErr_Format(PyExc_ValueError, "Unknown object");
+        PyErr_Format(PyExc_ValueError, "unknown object '%.100s'", txt);
         return NULL;
     }
     result = asn1obj2py(obj);
@@ -3411,12 +3411,12 @@
         return NULL;
     }
     if (nid < NID_undef) {
-        PyErr_Format(PyExc_ValueError, "NID must be positive.");
+        PyErr_SetString(PyExc_ValueError, "NID must be positive.");
         return NULL;
     }
     obj = OBJ_nid2obj(nid);
     if (obj == NULL) {
-        PyErr_Format(PyExc_ValueError, "Unknown NID");
+        PyErr_Format(PyExc_ValueError, "unknown NID %i", nid);
         return NULL;
     }
     result = asn1obj2py(obj);