object_t *createCOFFEntity(StringRef Name, list_t &List);
void defineSection(MCSectionCOFF const &Sec);
+
+ COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
const MCAsmLayout &Layout);
return Res;
}
+COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
+ if (!Symbol.isVariable())
+ return nullptr;
+
+ const MCSymbolRefExpr *SymRef =
+ dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
+ if (!SymRef)
+ return nullptr;
+
+ const MCSymbol &Aliasee = SymRef->getSymbol();
+ if (!Aliasee.isUndefined())
+ return nullptr;
+ return GetOrCreateCOFFSymbol(&Aliasee);
+}
+
/// This function takes a symbol data object from the assembler
/// and creates the associated COFF symbol staging object.
void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
report_fatal_error("conflicting sections for symbol");
}
+ COFFSymbol *Local = nullptr;
if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
- if (Symbol.isVariable()) {
- const MCSymbolRefExpr *SymRef =
- dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
-
- if (!SymRef)
- report_fatal_error("Weak externals may only alias symbols");
-
- coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol());
- } else {
+ COFFSymbol *WeakDefault = getLinkedSymbol(Symbol);
+ if (!WeakDefault) {
std::string WeakName = (".weak." + Symbol.getName() + ".default").str();
- COFFSymbol *WeakDefault = createSymbol(WeakName);
-
+ WeakDefault = createSymbol(WeakName);
if (!Sec)
WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
else
WeakDefault->Section = Sec;
-
- WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL;
- WeakDefault->Data.Type = 0;
- WeakDefault->Data.Value = getSymbolValue(Symbol, Layout);
- coff_symbol->Other = WeakDefault;
+ Local = WeakDefault;
}
+ coff_symbol->Other = WeakDefault;
+
// Setup the Weak External auxiliary symbol.
coff_symbol->Aux.resize(1);
memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
-
- coff_symbol->MC = &Symbol;
} else {
- coff_symbol->Data.Value = getSymbolValue(Symbol, Layout);
+ if (!Base)
+ coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+ else
+ coff_symbol->Section = Sec;
+ Local = coff_symbol;
+ }
+
+ if (Local) {
+ Local->Data.Value = getSymbolValue(Symbol, Layout);
const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol);
- coff_symbol->Data.Type = SymbolCOFF.getType();
- coff_symbol->Data.StorageClass = SymbolCOFF.getClass();
+ Local->Data.Type = SymbolCOFF.getType();
+ Local->Data.StorageClass = SymbolCOFF.getClass();
// If no storage class was specified in the streamer, define it here.
- if (coff_symbol->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
+ if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
bool IsExternal = Symbol.isExternal() ||
(!Symbol.getFragment() && !Symbol.isVariable());
- coff_symbol->Data.StorageClass = IsExternal
- ? COFF::IMAGE_SYM_CLASS_EXTERNAL
- : COFF::IMAGE_SYM_CLASS_STATIC;
+ Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
+ : COFF::IMAGE_SYM_CLASS_STATIC;
}
-
- if (!Base)
- coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
- else
- coff_symbol->Section = Sec;
-
- coff_symbol->MC = &Symbol;
}
+
+ coff_symbol->MC = &Symbol;
}
// Maximum offsets for different string table entry encodings.
--- /dev/null
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s -o %t.o
+// RUN: llvm-readobj -t %t.o | FileCheck %s
+
+// test that we create an external symbol for a to point to.
+
+ .data
+ .long 123
+b:
+ .long 42
+ .weak a
+a=b
+
+// CHECK: Symbol {
+// CHECK: Name: b
+// CHECK-NEXT: Value: 4
+// CHECK-NEXT: Section: .data (2)
+// CHECK-NEXT: BaseType: Null (0x0)
+// CHECK-NEXT: ComplexType: Null (0x0)
+// CHECK-NEXT: StorageClass: Static (0x3)
+// CHECK-NEXT: AuxSymbolCount: 0
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: a
+// CHECK-NEXT: Value: 0
+// CHECK-NEXT: Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT: BaseType: Null (0x0)
+// CHECK-NEXT: ComplexType: Null (0x0)
+// CHECK-NEXT: StorageClass: WeakExternal (0x69)
+// CHECK-NEXT: AuxSymbolCount: 1
+// CHECK-NEXT: AuxWeakExternal {
+// CHECK-NEXT: Linked: .weak.a.default (9)
+// CHECK-NEXT: Search: Library (0x2)
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: .weak.a.default
+// CHECK-NEXT: Value: 4
+// CHECK-NEXT: Section: .data (2)
+// CHECK-NEXT: BaseType: Null (0x0)
+// CHECK-NEXT: ComplexType: Null (0x0)
+// CHECK-NEXT: StorageClass: External (0x2)
+// CHECK-NEXT: AuxSymbolCount: 0
+// CHECK-NEXT: }
// CHECK: Symbols [
// CHECK: Symbol {
+// CHECK: Name: _main
+// CHECK-NEXT: Value: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: BaseType: Null
+// CHECK-NEXT: ComplexType: Function
+// CHECK-NEXT: StorageClass: External
+// CHECK-NEXT: AuxSymbolCount: 0
+// CHECK-NEXT: }
+
+// CHECK: Symbol {
// CHECK: Name: _test_weak
// CHECK-NEXT: Value: 0
// CHECK-NEXT: Section: IMAGE_SYM_UNDEFINED (0)
// CHECK-NEXT: StorageClass: WeakExternal
// CHECK-NEXT: AuxSymbolCount: 1
// CHECK-NEXT: AuxWeakExternal {
-// CHECK-NEXT: Linked: _main
+// CHECK-NEXT: Linked: .weak._test_weak_alias.default
// CHECK-NEXT: Search: Library
// CHECK-NEXT: }
// CHECK-NEXT: }
+
+// CHECK: Symbol {
+// CHECK: Name: .weak._test_weak_alias.default
+// CHECK-NEXT: Value: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: BaseType: Null
+// CHECK-NEXT: ComplexType: Null
+// CHECK-NEXT: StorageClass: External
+// CHECK-NEXT: AuxSymbolCount: 0
+// CHECK-NEXT: }