replaceSymbol<Defined>(sym, sym->getName(), isec->file, isec, /*value=*/0,
/*size=*/0,
/*isWeakDef=*/false,
- /*isExternal=*/true, common->privateExtern);
+ /*isExternal=*/true, common->privateExtern,
+ /*isThumb=*/false);
}
}
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
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>
}
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)
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;
Defined *defined =
replaceSymbol<Defined>(s, name, file, isec, value, size, isWeakDef,
- /*isExternal=*/true, isPrivateExtern);
+ /*isExternal=*/true, isPrivateExtern, isThumb);
defined->overridesWeakDef = overridesWeakDef;
return defined;
}
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;
}
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);
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 {
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;
dyldPrivate =
make<Defined>("__dyld_private", nullptr, in.imageLoaderCache, 0, 0,
/*isWeakDef=*/false,
- /*isExternal=*/false, /*isPrivateExtern=*/false);
+ /*isExternal=*/false, /*isPrivateExtern=*/false,
+ /*isThumb=*/false);
}
ImageLoaderCacheSection::ImageLoaderCacheSection() {
// 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;
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;
--- /dev/null
+# 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: