diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index 03594fe..4874f95 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -5,6 +5,7 @@
  * Functions for error handling.
  */
 
+use Drupal\Core\Utility\Error;
 use Drupal\Component\Utility\String;
 use Symfony\Component\HttpFoundation\Response;
 
@@ -87,44 +88,11 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c
  *
  * @return
  *   An error in the format expected by _drupal_log_error().
+ *
+ * @deprecated Use \Drupal\Core\Utility\Error::decodeException() instead.
  */
 function _drupal_decode_exception($exception) {
-  $message = $exception->getMessage();
-
-  $backtrace = $exception->getTrace();
-  // Add the line throwing the exception to the backtrace.
-  array_unshift($backtrace, array('line' => $exception->getLine(), 'file' => $exception->getFile()));
-
-  // For PDOException errors, we try to return the initial caller,
-  // skipping internal functions of the database layer.
-  if ($exception instanceof PDOException) {
-    // The first element in the stack is the call, the second element gives us the caller.
-    // We skip calls that occurred in one of the classes of the database layer
-    // or in one of its global functions.
-    $db_functions = array('db_query',  'db_query_range');
-    while (!empty($backtrace[1]) && ($caller = $backtrace[1]) &&
-        ((isset($caller['class']) && (strpos($caller['class'], 'Query') !== FALSE || strpos($caller['class'], 'Database') !== FALSE || strpos($caller['class'], 'PDO') !== FALSE)) ||
-        in_array($caller['function'], $db_functions))) {
-      // We remove that call.
-      array_shift($backtrace);
-    }
-    if (isset($exception->query_string, $exception->args)) {
-      $message .= ": " . $exception->query_string . "; " . print_r($exception->args, TRUE);
-    }
-  }
-  $caller = _drupal_get_last_caller($backtrace);
-
-  return array(
-    '%type' => get_class($exception),
-    // The standard PHP exception handler considers that the exception message
-    // is plain-text. We mimick this behavior here.
-    '!message' => String::checkPlain($message),
-    '%function' => $caller['function'],
-    '%file' => $caller['file'],
-    '%line' => $caller['line'],
-    'severity_level' => WATCHDOG_ERROR,
-    'backtrace' => $backtrace,
-  );
+  return Error::decodeException($exception);
 }
 
 /**
@@ -135,11 +103,11 @@ function _drupal_decode_exception($exception) {
  *
  * @return
  *   An error message.
+ *
+ * @deprecated Use \Drupal\Core\Utility\Error::renderExceptionSafe() instead.
  */
 function _drupal_render_exception_safe($exception) {
-  $decode = _drupal_decode_exception($exception);
-  unset($decode['backtrace']);
-  return String::checkPlain(strtr('%type: !message in %function (line %line of %file).', $decode));
+  return Error::renderExceptionSafe($exception);
 }
 
 /**
@@ -320,33 +288,11 @@ function _drupal_get_error_level() {
  *
  * @return
  *   An associative array with keys 'file', 'line' and 'function'.
+ *
+ * @deprecated Use \Drupal\Core\Utility\Error::getLastCaller() instead.
  */
 function _drupal_get_last_caller(&$backtrace) {
-  // Errors that occur inside PHP internal functions do not generate
-  // information about file and line. Ignore black listed functions.
-  $blacklist = array('debug', '_drupal_error_handler', '_drupal_exception_handler');
-  while (($backtrace && !isset($backtrace[0]['line'])) ||
-         (isset($backtrace[1]['function']) && in_array($backtrace[1]['function'], $blacklist))) {
-    array_shift($backtrace);
-  }
-
-  // The first trace is the call itself.
-  // It gives us the line and the file of the last call.
-  $call = $backtrace[0];
-
-  // The second call give us the function where the call originated.
-  if (isset($backtrace[1])) {
-    if (isset($backtrace[1]['class'])) {
-      $call['function'] = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()';
-    }
-    else {
-      $call['function'] = $backtrace[1]['function'] . '()';
-    }
-  }
-  else {
-    $call['function'] = 'main()';
-  }
-  return $call;
+  return Error::getLastCaller($backtrace);
 }
 
 /**
@@ -359,31 +305,9 @@ function _drupal_get_last_caller(&$backtrace) {
  *
  * @return string
  *   A plain-text line-wrapped string ready to be put inside <pre>.
+ *
+ * @deprecated Use \Drupal\Core\Utility\Error::formatBacktrace() instead.
  */
 function format_backtrace(array $backtrace) {
-  $return = '';
-  foreach ($backtrace as $trace) {
-    $call = array('function' => '', 'args' => array());
-    if (isset($trace['class'])) {
-      $call['function'] = $trace['class'] . $trace['type'] . $trace['function'];
-    }
-    elseif (isset($trace['function'])) {
-      $call['function'] = $trace['function'];
-    }
-    else {
-      $call['function'] = 'main';
-    }
-    if (isset($trace['args'])) {
-      foreach ($trace['args'] as $arg) {
-        if (is_scalar($arg)) {
-          $call['args'][] = is_string($arg) ? '\'' . filter_xss($arg) . '\'' : $arg;
-        }
-        else {
-          $call['args'][] = ucfirst(gettype($arg));
-        }
-      }
-    }
-    $return .= $call['function'] . '(' . implode(', ', $call['args']) . ")\n";
-  }
-  return $return;
+  return Error::formatBacktrace($backtrace);
 }
diff --git a/core/lib/Drupal/Core/Utility/Error.php b/core/lib/Drupal/Core/Utility/Error.php
new file mode 100644
index 0000000..6cdc7e3
--- /dev/null
+++ b/core/lib/Drupal/Core/Utility/Error.php
@@ -0,0 +1,178 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Utility\Error.
+ */
+
+namespace Drupal\Core\Utility;
+
+use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\Xss;
+
+/**
+ * Drupal error utility class.
+ */
+class Error {
+
+  /**
+   * The error severity level.
+   *
+   * @var int
+   */
+  const ERROR = 3;
+
+  /**
+   * An array of blacklisted functions.
+   *
+   * @var array
+   */
+  protected static $blacklistFunctions = array('debug', '_drupal_error_handler', '_drupal_exception_handler');
+
+  /**
+   * Decodes an exception and retrieves the correct caller.
+   *
+   * @param \Exception $exception
+   *   The exception object that was thrown.
+   *
+   * @return array
+   *   An error in the format expected by _drupal_log_error().
+   */
+  public static function decodeException(\Exception $exception) {
+    $message = $exception->getMessage();
+
+    $backtrace = $exception->getTrace();
+    // Add the line throwing the exception to the backtrace.
+    array_unshift($backtrace, array('line' => $exception->getLine(), 'file' => $exception->getFile()));
+
+    // For PDOException errors, we try to return the initial caller,
+    // skipping internal functions of the database layer.
+    if ($exception instanceof \PDOException) {
+      // The first element in the stack is the call, the second element gives us
+      // the caller. We skip calls that occurred in one of the classes of the
+      // database layer or in one of its global functions.
+      $db_functions = array('db_query',  'db_query_range');
+      while (!empty($backtrace[1]) && ($caller = $backtrace[1]) &&
+        ((isset($caller['class']) && (strpos($caller['class'], 'Query') !== FALSE || strpos($caller['class'], 'Database') !== FALSE || strpos($caller['class'], 'PDO') !== FALSE)) ||
+          in_array($caller['function'], $db_functions))) {
+        // We remove that call.
+        array_shift($backtrace);
+      }
+      if (isset($exception->query_string, $exception->args)) {
+        $message .= ": " . $exception->query_string . "; " . print_r($exception->args, TRUE);
+      }
+    }
+
+    $caller = static::getLastCaller($backtrace);
+
+    return array(
+      '%type' => get_class($exception),
+      // The standard PHP exception handler considers that the exception message
+      // is plain-text. We mimic this behavior here.
+      '!message' => String::checkPlain($message),
+      '%function' => $caller['function'],
+      '%file' => $caller['file'],
+      '%line' => $caller['line'],
+      'severity_level' => static::ERROR,
+      'backtrace' => $backtrace,
+    );
+  }
+
+  /**
+   * Renders an exception error message without further exceptions.
+   *
+   * @param \Exception $exception
+   *   The exception object that was thrown.
+   *
+   * @return string
+   *   An error message.
+   */
+  public static function renderExceptionSafe(\Exception $exception) {
+    $decode = static::decodeException($exception);
+    unset($decode['backtrace']);
+
+    return String::format('%type: !message in %function (line %line of %file).', $decode);
+  }
+
+  /**
+   * Gets the last caller from a backtrace.
+   *
+   * @param array $backtrace
+   *   A standard PHP backtrace. Passed by reference.
+   *
+   * @return array
+   *   An associative array with keys 'file', 'line' and 'function'.
+   */
+  public static function getLastCaller(array &$backtrace) {
+    // Errors that occur inside PHP internal functions do not generate
+    // information about file and line. Ignore black listed functions.
+    while (($backtrace && !isset($backtrace[0]['line'])) ||
+      (isset($backtrace[1]['function']) && in_array($backtrace[1]['function'], static::$blacklistFunctions))) {
+      array_shift($backtrace);
+    }
+
+    // The first trace is the call itself.
+    // It gives us the line and the file of the last call.
+    $call = $backtrace[0];
+
+    // The second call gives us the function where the call originated.
+    if (isset($backtrace[1])) {
+      if (isset($backtrace[1]['class'])) {
+        $call['function'] = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()';
+      }
+      else {
+        $call['function'] = $backtrace[1]['function'] . '()';
+      }
+    }
+    else {
+      $call['function'] = 'main()';
+    }
+
+    return $call;
+  }
+
+  /**
+   * Formats a backtrace into a plain-text string.
+   *
+   * The calls show values for scalar arguments and type names for complex ones.
+   *
+   * @param array $backtrace
+   *   A standard PHP backtrace.
+   *
+   * @return string
+   *   A plain-text line-wrapped string ready to be put inside <pre>.
+   */
+  public static function formatBacktrace(array $backtrace) {
+    $return = '';
+
+    foreach ($backtrace as $trace) {
+      $call = array('function' => '', 'args' => array());
+
+      if (isset($trace['class'])) {
+        $call['function'] = $trace['class'] . $trace['type'] . $trace['function'];
+      }
+      elseif (isset($trace['function'])) {
+        $call['function'] = $trace['function'];
+      }
+      else {
+        $call['function'] = 'main';
+      }
+
+      if (isset($trace['args'])) {
+        foreach ($trace['args'] as $arg) {
+          if (is_scalar($arg)) {
+            $call['args'][] = is_string($arg) ? '\'' . Xss::filter($arg) . '\'' : $arg;
+          }
+          else {
+            $call['args'][] = ucfirst(gettype($arg));
+          }
+        }
+      }
+
+      $return .= $call['function'] . '(' . implode(', ', $call['args']) . ")\n";
+    }
+
+    return $return;
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/ShutdownFunctionsTest.php b/core/modules/system/lib/Drupal/system/Tests/System/ShutdownFunctionsTest.php
index d3a160e..bec5fa8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/ShutdownFunctionsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/ShutdownFunctionsTest.php
@@ -41,6 +41,6 @@ function testShutdownFunctions() {
 
     // Make sure exceptions displayed through _drupal_render_exception_safe()
     // are correctly escaped.
-    $this->assertRaw('Drupal is &amp;lt;blink&amp;gt;awesome&amp;lt;/blink&amp;gt;.');
+    $this->assertRaw('Drupal is &lt;blink&gt;awesome&lt;/blink&gt;.');
   }
 }
diff --git a/core/tests/Drupal/Tests/Core/Utility/ErrorTest.php b/core/tests/Drupal/Tests/Core/Utility/ErrorTest.php
new file mode 100644
index 0000000..bb3fa1f
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Utility/ErrorTest.php
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Utility\ErrorTest.
+ */
+
+namespace Drupal\Tests\Core\Utility;
+
+use Drupal\Tests\UnitTestCase;
+use Drupal\Core\Utility\Error;
+
+/**
+ * Tests the Error class.
+ *
+ * @group Drupal
+ *
+ * @see \Drupal\Core\Utility\Error
+ */
+class ErrorTest extends UnitTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Error',
+      'description' => 'Tests the Error utility class.',
+      'group' => 'Common',
+    );
+  }
+
+  /**
+   * Tests the getLastCaller() method.
+   *
+   * @param array $backtrace
+   *   The test backtrace array.
+   * @param array $expected
+   *   The expected return array.
+   *
+   * @dataProvider providerTestGetLastCaller
+   *
+   */
+  public function testGetLastCaller($backtrace, $expected) {
+    $this->assertSame($expected, Error::getLastCaller($backtrace));
+  }
+
+  /**
+   * Data provider for testGetLastCaller.
+   *
+   * @return array
+   *   An array of parameter data.
+   */
+  public function providerTestGetLastCaller() {
+    $data = array();
+
+    // Test with just one item. This should default to the function being
+    // main().
+    $single_item = array($this->createBacktraceItem());
+    $data[] = array($single_item, $this->createBacktraceItem('main()'));
+
+    // Add a second item, without a class.
+    $two_items = $single_item;
+    $two_items[] = $this->createBacktraceItem('test_function_two');
+    $data[] = array($two_items, $this->createBacktraceItem('test_function_two()'));
+
+    // Add a second item, with a class.
+    $two_items = $single_item;
+    $two_items[] = $this->createBacktraceItem('test_function_two', 'TestClass');
+    $data[] = array($two_items, $this->createBacktraceItem('TestClass->test_function_two()'));
+
+    // Add blacklist functions to backtrace. They should get removed.
+    foreach (array('debug', '_drupal_error_handler', '_drupal_exception_handler') as $function) {
+      $two_items = $single_item;
+      // Push to the start of the backtrace.
+      array_unshift($two_items, $this->createBacktraceItem($function));
+      $data[] = array($single_item, $this->createBacktraceItem('main()'));
+    }
+
+    return $data;
+  }
+
+  /**
+   * Tests the formatBacktrace() method.
+   *
+   * @param array $backtrace
+   *   The test backtrace array.
+   * @param array $expected
+   *   The expected return array.
+   *
+   * @dataProvider providerTestFormatBacktrace
+   */
+  public function testFormatBacktrace($backtrace, $expected) {
+    $this->assertSame($expected, Error::formatBacktrace($backtrace));
+  }
+
+  /**
+   * Data provider for testFormatBacktrace.
+   *
+   * @return array
+   */
+  public function providerTestFormatBacktrace() {
+    $data = array();
+
+    // Test with no function, main should be in the backtrace.
+    $data[] = array(array($this->createBacktraceItem(NULL, NULL)), "main()\n");
+
+    $base = array($this->createBacktraceItem());
+    $data[] = array($base, "test_function()\n");
+
+    // Add a second item.
+    $second_item = $base;
+    $second_item[] = $this->createBacktraceItem('test_function_2');
+
+    $data[] = array($second_item, "test_function()\ntest_function_2()\n");
+
+    // Add a second item, with a class.
+    $second_item_class = $base;
+    $second_item_class[] = $this->createBacktraceItem('test_function_2', 'TestClass');
+
+    $data[] = array($second_item_class, "test_function()\nTestClass->test_function_2()\n");
+
+    // Add a second item, with a class.
+    $second_item_args = $base;
+    $second_item_args[] = $this->createBacktraceItem('test_function_2', NULL, array('string', 10, new \stdClass()));
+
+    $data[] = array($second_item_args, "test_function()\ntest_function_2('string', 10, Object)\n");
+
+    return $data;
+  }
+
+  /**
+   * Creates a mock backtrace item.
+   *
+   * @param string|NULL $function
+   *   (optional) The function name to use in the backtrace item.
+   * @param string $class
+   *   (optional) The class to use in the backtrace item.
+   * @param array $args
+   *   (optional) An array of function arguments to add to the backtrace item.
+   *
+   * @return array
+   *   A backtrace array item.
+   */
+  protected function createBacktraceItem($function = 'test_function', $class = NULL, array $args = array()) {
+    $backtrace = array(
+      'file' => 'test_file',
+      'line' => 10,
+      'function' => $function,
+      'args' => array(),
+    );
+
+    if (isset($class)) {
+      $backtrace['class'] = $class;
+      $backtrace['type'] = '->';
+    }
+
+    if (!empty($args)) {
+      $backtrace['args'] = $args;
+    }
+
+    return $backtrace;
+  }
+
+}
