+2015-03-30  Jing Yu  <jingyu@google.com>
+
+       * aarch64-reloc.def: New TLSLD_ADD_DTPREL_HI12,
+       TLSLD_ADD_DTPREL_LO12_NC.
+       * aarch64.cc (Target_aarch64::define_tls_base_symbol): Always let
+       _TLS_MODULE_BASE_ point to the start of tls segment.
+       (Target_aarch64::optimize_tls_reloc): Add cases for
+       R_AARCH64_TLSLD_ADD_DTPREL_HI12 and
+       R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC.
+       (Target_aarch64::Scan::local): Likewise.
+       (Target_aarch64::Scan::global): Likewise.
+       (Target_aarch64::Relocate::relocate): Likewise.
+       (Target_aarch64::Relocate::relocate_tls): Likewise. And remove
+       subtracting tls segment size from symbol value for TLSLD_*_DTPREL
+       relocations.
+
 2015-03-27  Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
 
        * merge.cc (Object_merge_map::add_mapping): call
 
 ARD(TLSLD_ADD_LO12_NC            , STATIC ,  AARCH64    ,   Y,  -1,    0,0                ,    0,11 , Symbol::TLS_REF ,                              ADD   )
 ARD(TLSLD_MOVW_DTPREL_G1         , STATIC ,  AARCH64    ,   Y,   1,   32,32               ,   16,31 , Symbol::TLS_REF ,                              ADRP  )
 ARD(TLSLD_MOVW_DTPREL_G0_NC      , STATIC ,  AARCH64    ,   Y,   0,    0,0                ,    0,15 , Symbol::TLS_REF ,                              MOVW  )
+ARD(TLSLD_ADD_DTPREL_HI12        , STATIC ,  AARCH64    ,   Y,  -1,    0,24               ,   12,23 , Symbol::TLS_REF ,                              ADD   )
+ARD(TLSLD_ADD_DTPREL_LO12_NC     , STATIC ,  AARCH64    ,   Y,  -1,    0,0                ,    0,11 , Symbol::TLS_REF ,                              ADD   )
 // Above is from Table 4-16, Local Dynamic TLS relocations, 517-573.
 
 ARD(TLSIE_MOVW_GOTTPREL_G1       , STATIC ,  AARCH64    ,   N,  -1,   32,32               ,   16,31 , Symbol::TLS_REF ,                              MOVW  )
 
   Output_segment* tls_segment = layout->tls_segment();
   if (tls_segment != NULL)
     {
-      bool is_exec = parameters->options().output_is_executable();
+      // _TLS_MODULE_BASE_ always points to the beginning of tls segment.
       symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL,
                                       Symbol_table::PREDEFINED,
                                       tls_segment, 0, 0,
                                       elfcpp::STT_TLS,
                                       elfcpp::STB_LOCAL,
                                       elfcpp::STV_HIDDEN, 0,
-                                      (is_exec
-                                       ? Symbol::SEGMENT_END
-                                       : Symbol::SEGMENT_START),
+                                      Symbol::SEGMENT_START,
                                       true);
     }
   this->tls_base_symbol_defined_ = true;
     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
       // These are Local-Dynamic, which refer to local symbols in the
       // dynamic TLS block. Since we know that we generating an
       // executable, we can switch to Local-Exec.
 
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
       break;
 
     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
       break;
 
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
-    case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:  // Other local dynamic
+    case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:  // Other local dynamic
       break;
 
     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
     case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
       break;
 
     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
-    case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:  // Other local-dynamic
+    case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
+    case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:  // Other local-dynamic
       {
        AArch64_address value = psymval->value(object, 0);
        if (tlsopt == tls::TLSOPT_TO_LE)
                            || issue_undefined_symbol_error(gsym));
                return aarch64_reloc_funcs::STATUS_BAD_RELOC;
              }
-         // If building executable, _TLS_MODULE_BASE_ points to segment
-         // end. Thus we must subtract it from value.
-         value -= tls_segment->memsz();
          }
        switch (r_type)
          {
            break;
 
          case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
+         case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
+         case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
            return aarch64_reloc_funcs::template rela_general<32>(
                view, value, addend, reloc_property);
            break;