[lld-macho] Parse & emit the N_ARM_THUMB_DEF symbol flag
authorJez Ng <jezng@fb.com>
Fri, 30 Apr 2021 20:17:26 +0000 (16:17 -0400)
committerJez Ng <jezng@fb.com>
Fri, 30 Apr 2021 20:17:26 +0000 (16:17 -0400)
Eventually we'll use this flag to properly handle bl/blx
opcodes.

Reviewed By: #lld-macho, gkm

Differential Revision: https://reviews.llvm.org/D101558

lld/MachO/Driver.cpp
lld/MachO/InputFiles.cpp
lld/MachO/SymbolTable.cpp
lld/MachO/SymbolTable.h
lld/MachO/Symbols.h
lld/MachO/SyntheticSections.cpp
lld/MachO/UnwindInfoSection.cpp
lld/test/MachO/weak-def-thumb-conflict.s [new file with mode: 0644]

index 0b59397..dafd914 100644 (file)
@@ -553,7 +553,8 @@ static void replaceCommonSymbols() {
     replaceSymbol<Defined>(sym, sym->getName(), isec->file, isec, /*value=*/0,
                            /*size=*/0,
                            /*isWeakDef=*/false,
-                           /*isExternal=*/true, common->privateExtern);
+                           /*isExternal=*/true, common->privateExtern,
+                           /*isThumb=*/false);
   }
 }
 
index bff7f35..a553754 100644 (file)
@@ -467,14 +467,16 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
       isPrivateExtern = true;
 
     return symtab->addDefined(name, isec->file, isec, value, size,
-                              sym.n_desc & N_WEAK_DEF, isPrivateExtern);
+                              sym.n_desc & N_WEAK_DEF, isPrivateExtern,
+                              sym.n_desc & N_ARM_THUMB_DEF);
   }
 
   assert(!isWeakDefCanBeHidden &&
          "weak_def_can_be_hidden on already-hidden symbol?");
   return make<Defined>(name, isec->file, isec, value, size,
                        sym.n_desc & N_WEAK_DEF,
-                       /*isExternal=*/false, /*isPrivateExtern=*/false);
+                       /*isExternal=*/false, /*isPrivateExtern=*/false,
+                       sym.n_desc & N_ARM_THUMB_DEF);
 }
 
 // Absolute symbols are defined symbols that do not have an associated
@@ -485,11 +487,13 @@ static macho::Symbol *createAbsolute(const NList &sym, InputFile *file,
   if (sym.n_type & (N_EXT | N_PEXT)) {
     assert((sym.n_type & N_EXT) && "invalid input");
     return symtab->addDefined(name, file, nullptr, sym.n_value, /*size=*/0,
-                              /*isWeakDef=*/false, sym.n_type & N_PEXT);
+                              /*isWeakDef=*/false, sym.n_type & N_PEXT,
+                              sym.n_desc & N_ARM_THUMB_DEF);
   }
   return make<Defined>(name, file, nullptr, sym.n_value, /*size=*/0,
                        /*isWeakDef=*/false,
-                       /*isExternal=*/false, /*isPrivateExtern=*/false);
+                       /*isExternal=*/false, /*isPrivateExtern=*/false,
+                       sym.n_desc & N_ARM_THUMB_DEF);
 }
 
 template <class NList>
@@ -988,7 +992,8 @@ static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
   }
 
   return symtab->addDefined(name, &file, /*isec=*/nullptr, /*value=*/0,
-                            /*size=*/0, objSym.isWeak(), isPrivateExtern);
+                            /*size=*/0, objSym.isWeak(), isPrivateExtern,
+                            /*isThumb=*/false);
 }
 
 BitcodeFile::BitcodeFile(MemoryBufferRef mbref)
index 1fd7704..51b11a0 100644 (file)
@@ -45,7 +45,7 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
 Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
                                  InputSection *isec, uint64_t value,
                                  uint64_t size, bool isWeakDef,
-                                 bool isPrivateExtern) {
+                                 bool isPrivateExtern, bool isThumb) {
   Symbol *s;
   bool wasInserted;
   bool overridesWeakDef = false;
@@ -73,7 +73,7 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
 
   Defined *defined =
       replaceSymbol<Defined>(s, name, file, isec, value, size, isWeakDef,
-                             /*isExternal=*/true, isPrivateExtern);
+                             /*isExternal=*/true, isPrivateExtern, isThumb);
   defined->overridesWeakDef = overridesWeakDef;
   return defined;
 }
@@ -167,7 +167,8 @@ Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
                                    uint64_t value, bool isPrivateExtern,
                                    bool includeInSymtab) {
   Defined *s = addDefined(name, nullptr, isec, value, /*size=*/0,
-                          /*isWeakDef=*/false, isPrivateExtern);
+                          /*isWeakDef=*/false, isPrivateExtern,
+                          /*isThumb=*/false);
   s->includeInSymtab = includeInSymtab;
   return s;
 }
index 10d17f6..611eb8b 100644 (file)
@@ -39,7 +39,7 @@ class SymbolTable {
 public:
   Defined *addDefined(StringRef name, InputFile *, InputSection *,
                       uint64_t value, uint64_t size, bool isWeakDef,
-                      bool isPrivateExtern);
+                      bool isPrivateExtern, bool isThumb);
 
   Symbol *addUndefined(StringRef name, InputFile *, bool isWeakRef);
 
index 962aad3..c6375e1 100644 (file)
@@ -101,10 +101,12 @@ public:
 class Defined : public Symbol {
 public:
   Defined(StringRefZ name, InputFile *file, InputSection *isec, uint64_t value,
-          uint64_t size, bool isWeakDef, bool isExternal, bool isPrivateExtern)
+          uint64_t size, bool isWeakDef, bool isExternal, bool isPrivateExtern,
+          bool isThumb)
       : Symbol(DefinedKind, name, file), isec(isec), value(value), size(size),
         overridesWeakDef(false), privateExtern(isPrivateExtern),
-        includeInSymtab(true), weakDef(isWeakDef), external(isExternal) {}
+        includeInSymtab(true), thumb(isThumb), weakDef(isWeakDef),
+        external(isExternal) {}
 
   bool isWeakDef() const override { return weakDef; }
   bool isExternalWeakDef() const {
@@ -134,6 +136,8 @@ public:
   bool privateExtern : 1;
   // Whether this symbol should appear in the output symbol table.
   bool includeInSymtab : 1;
+  // Only relevant when compiling for Thumb-supporting arm32 archs.
+  bool thumb : 1;
 
 private:
   const bool weakDef : 1;
index 4ea3091..cc595b3 100644 (file)
@@ -483,7 +483,8 @@ void StubHelperSection::setup() {
   dyldPrivate =
       make<Defined>("__dyld_private", nullptr, in.imageLoaderCache, 0, 0,
                     /*isWeakDef=*/false,
-                    /*isExternal=*/false, /*isPrivateExtern=*/false);
+                    /*isExternal=*/false, /*isPrivateExtern=*/false,
+                    /*isThumb=*/false);
 }
 
 ImageLoaderCacheSection::ImageLoaderCacheSection() {
@@ -865,6 +866,7 @@ template <class LP> void SymtabSectionImpl<LP>::writeTo(uint8_t *buf) const {
         // For the N_SECT symbol type, n_value is the address of the symbol
         nList->n_value = defined->getVA();
       }
+      nList->n_desc |= defined->thumb ? N_ARM_THUMB_DEF : 0;
       nList->n_desc |= defined->isExternalWeakDef() ? N_WEAK_DEF : 0;
     } else if (auto *dysym = dyn_cast<DylibSymbol>(entry.sym)) {
       uint16_t n_desc = nList->n_desc;
index 5148206..370e140 100644 (file)
@@ -182,7 +182,8 @@ void UnwindInfoSectionImpl<Ptr>::prepareRelocations(InputSection *isec) {
       if (s == nullptr) {
         s = make<Defined>("<internal>", /*file=*/nullptr, referentIsec,
                           r.addend, /*size=*/0, /*isWeakDef=*/false,
-                          /*isExternal=*/false, /*isPrivateExtern=*/false);
+                          /*isExternal=*/false, /*isPrivateExtern=*/false,
+                          /*isThumb=*/false);
         in.got->addEntry(s);
       }
       r.referent = s;
diff --git a/lld/test/MachO/weak-def-thumb-conflict.s b/lld/test/MachO/weak-def-thumb-conflict.s
new file mode 100644 (file)
index 0000000..4f6c604
--- /dev/null
@@ -0,0 +1,28 @@
+# REQUIRES: arm
+# RUN: rm -rf %t; split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=armv7-apple-watchos %t/thumb-foo.s -o %t/thumb-foo.o
+# RUN: llvm-mc -filetype=obj -triple=armv7-apple-watchos %t/arm-foo.s -o %t/arm-foo.o
+# RUN: %lld-watchos -arch armv7 -dylib %t/arm-foo.o %t/thumb-foo.o -o %t/arm-foo
+# RUN: %lld-watchos -arch armv7 -dylib %t/thumb-foo.o %t/arm-foo.o -o %t/thumb-foo
+# RUN: llvm-nm -m %t/arm-foo | FileCheck %s --check-prefix=ARM
+# RUN: llvm-nm -m %t/thumb-foo | FileCheck %s --check-prefix=THUMB
+
+## Check that we preserve the .thumb_def flag if we pick the thumb definition of
+## _foo.
+# ARM:   (__TEXT,arm)   weak external         _foo
+# THUMB: (__TEXT,thumb) weak external [Thumb] _foo
+
+#--- thumb-foo.s
+.section __TEXT,thumb
+.globl _foo
+.weak_definition _foo
+.thumb_func _foo
+.p2align 2
+_foo:
+
+#--- arm-foo.s
+.section __TEXT,arm
+.globl _foo
+.weak_definition _foo
+.p2align 2
+_foo: