Index: lld/trunk/ELF/Config.h
===================================================================
--- lld/trunk/ELF/Config.h
+++ lld/trunk/ELF/Config.h
@@ -45,6 +45,9 @@
 // For --sort-section and linkerscript sorting rules.
 enum class SortSectionPolicy { Default, None, Alignment, Name, Priority };
 
+// For --target2
+enum class Target2Policy { Abs, Rel, GotRel };
+
 struct SymbolVersion {
   llvm::StringRef Name;
   bool IsExternCpp;
@@ -131,6 +134,7 @@
   SortSectionPolicy SortSection;
   StripPolicy Strip = StripPolicy::None;
   UnresolvedPolicy UnresolvedSymbols;
+  Target2Policy Target2 = Target2Policy::GotRel;
   BuildIdKind BuildId = BuildIdKind::None;
   ELFKind EKind = ELFNoneKind;
   uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
Index: lld/trunk/ELF/Driver.cpp
===================================================================
--- lld/trunk/ELF/Driver.cpp
+++ lld/trunk/ELF/Driver.cpp
@@ -345,6 +345,20 @@
   return UnresolvedPolicy::ReportError;
 }
 
+static Target2Policy getTarget2Option(opt::InputArgList &Args) {
+  if (auto *Arg = Args.getLastArg(OPT_target2)) {
+    StringRef S = Arg->getValue();
+    if (S == "rel")
+      return Target2Policy::Rel;
+    if (S == "abs")
+      return Target2Policy::Abs;
+    if (S == "got-rel")
+      return Target2Policy::GotRel;
+    error("unknown --target2 option: " + S);
+  }
+  return Target2Policy::GotRel;
+}
+
 static bool isOutputFormatBinary(opt::InputArgList &Args) {
   if (auto *Arg = Args.getLastArg(OPT_oformat)) {
     StringRef S = Arg->getValue();
@@ -550,6 +564,8 @@
 
   Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args);
 
+  Config->Target2 = getTarget2Option(Args);
+
   if (auto *Arg = Args.getLastArg(OPT_dynamic_list))
     if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
       parseDynamicList(*Buffer);
Index: lld/trunk/ELF/Options.td
===================================================================
--- lld/trunk/ELF/Options.td
+++ lld/trunk/ELF/Options.td
@@ -177,6 +177,8 @@
 
 def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">;
 
+def target2: J<"target2=">, MetaVarName<"<type>">, HelpText<"Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel.">;
+
 def threads: F<"threads">, HelpText<"Enable use of threads">;
 
 def trace: F<"trace">, HelpText<"Print the names of the input files">;
Index: lld/trunk/ELF/Target.cpp
===================================================================
--- lld/trunk/ELF/Target.cpp
+++ lld/trunk/ELF/Target.cpp
@@ -1554,6 +1554,12 @@
     return R_GOT_PC;
   case R_ARM_TARGET1:
     return Config->Target1Rel ? R_PC : R_ABS;
+  case R_ARM_TARGET2:
+    if (Config->Target2 == Target2Policy::Rel)
+      return R_PC;
+    if (Config->Target2 == Target2Policy::Abs)
+      return R_ABS;
+    return R_GOT_PC;
   case R_ARM_TLS_GD32:
     return R_TLSGD_PC;
   case R_ARM_TLS_LDM32:
@@ -1660,6 +1666,7 @@
   case R_ARM_GOT_PREL:
   case R_ARM_REL32:
   case R_ARM_TARGET1:
+  case R_ARM_TARGET2:
   case R_ARM_TLS_GD32:
   case R_ARM_TLS_IE32:
   case R_ARM_TLS_LDM32:
@@ -1789,6 +1796,7 @@
   case R_ARM_GOT_PREL:
   case R_ARM_REL32:
   case R_ARM_TARGET1:
+  case R_ARM_TARGET2:
   case R_ARM_TLS_GD32:
   case R_ARM_TLS_LDM32:
   case R_ARM_TLS_LDO32:
Index: lld/trunk/test/ELF/arm-target2.s
===================================================================
--- lld/trunk/test/ELF/arm-target2.s
+++ lld/trunk/test/ELF/arm-target2.s
@@ -0,0 +1,60 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -o %t 2>&1
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t | FileCheck %s
+// RUN: ld.lld %t.o --target2=got-rel -o %t2 2>&1
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// RUN: ld.lld %t.o --target2=abs -o %t3 2>&1
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-ABS %s
+// RUN: ld.lld %t.o --target2=rel -o %t4 2>&1
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-REL %s
+// REQUIRES: arm
+
+// The R_ARM_TARGET2 is present in .ARM.extab sections. It can be handled as
+// either R_ARM_ABS32, R_ARM_REL32 or R_ARM_GOT_PREL. For ARM linux the default
+// is R_ARM_GOT_PREL. The other two options are primarily used for bare-metal,
+// they can be selected with the --target2=abs or --target2=rel option.
+ .syntax unified
+ .text
+ .globl _start
+ .align 2
+_start:
+ .type function, %function
+ .fnstart
+ bx lr
+ .personality   __gxx_personality_v0
+ .handlerdata
+ .word  _ZTIi(TARGET2)
+ .text
+ .fnend
+ .global __gxx_personality_v0
+ .type function, %function
+__gxx_personality_v0:
+ bx lr
+
+ .rodata
+_ZTIi:  .word 0
+
+// CHECK: Contents of section .ARM.extab:
+// 1011c + 1ee4 = 12000 = .got
+// CHECK-NEXT:  10114 f00e0000 b0b0b000 e41e0000
+
+// CHECK-ABS: Contents of section .ARM.extab:
+// 100e8 = .rodata
+// CHECK-ABS-NEXT: 100d4 300f0000 b0b0b000 e8000100
+
+// CHECK-REL: Contents of section .ARM.extab:
+// 100dc + c = 100e8 = .rodata
+// CHECK-REL-NEXT: 100d4 300f0000 b0b0b000 0c000000
+
+// CHECK: Contents of section .rodata:
+// CHECK-NEXT: 10128 00000000
+
+// CHECK-ABS: Contents of section .rodata:
+// CHECK-ABS-NEXT: 100e8 00000000
+
+// CHECK-REL: Contents of section .rodata:
+// CHECK-REL-NEXT: 100e8 00000000
+
+// CHECK: Contents of section .got:
+// 10128 = _ZTIi
+// CHECK-NEXT: 12000 28010100