Add support for gnu_indirect_function.
authorRoman Divacky <rdivacky@freebsd.org>
Mon, 12 Dec 2011 17:34:04 +0000 (17:34 +0000)
committerRoman Divacky <rdivacky@freebsd.org>
Mon, 12 Dec 2011 17:34:04 +0000 (17:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146377 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/ELF.h
lib/MC/MCELF.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCParser/ELFAsmParser.cpp
test/MC/ELF/type.s

index a81be552589a2e4c472a31a01492ff22f9d6dcbe..6dd76ea170da9e6762109c4a7e725b65f82de3fb 100644 (file)
@@ -888,6 +888,7 @@ enum {
   STT_TLS     = 6,   // Thread local data object
   STT_LOOS    = 7,   // Lowest operating system-specific symbol type
   STT_HIOS    = 8,   // Highest operating system-specific symbol type
+  STT_GNU_IFUNC = 10, // GNU indirect function
   STT_LOPROC  = 13,  // Lowest processor-specific symbol type
   STT_HIPROC  = 15   // Highest processor-specific symbol type
 };
index dad2e7ba987865c3bbe05c23f0acde4459074c69..f9f98e0f730e6b950bc3f88522394fb23918e1e3 100644 (file)
@@ -37,7 +37,7 @@ void MCELF::SetType(MCSymbolData &SD, unsigned Type) {
   assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT ||
          Type == ELF::STT_FUNC || Type == ELF::STT_SECTION ||
          Type == ELF::STT_FILE || Type == ELF::STT_COMMON ||
-         Type == ELF::STT_TLS);
+         Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC);
 
   uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift);
   SD.setFlags(OtherFlags | (Type << ELF_STT_Shift));
@@ -48,7 +48,7 @@ unsigned MCELF::GetType(const MCSymbolData &SD) {
   assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT ||
          Type == ELF::STT_FUNC || Type == ELF::STT_SECTION ||
          Type == ELF::STT_FILE || Type == ELF::STT_COMMON ||
-         Type == ELF::STT_TLS);
+         Type == ELF::STT_TLS || Type == ELF::STT_GNU_IFUNC);
   return Type;
 }
 
index 0ea3c64a284bd0b80d9cd976abf39a73e3b3f503..dcc4666a2665869bbb6f4add3014640a1eb706a7 100644 (file)
@@ -130,7 +130,6 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
   case MCSA_WeakDefinition:
   case MCSA_WeakDefAutoPrivate:
   case MCSA_Invalid:
-  case MCSA_ELF_TypeIndFunction:
   case MCSA_IndirectSymbol:
     assert(0 && "Invalid symbol attribute for ELF!");
     break;
@@ -162,6 +161,10 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
     MCELF::SetType(SD, ELF::STT_FUNC);
     break;
 
+  case MCSA_ELF_TypeIndFunction:
+    MCELF::SetType(SD, ELF::STT_GNU_IFUNC);
+    break;
+
   case MCSA_ELF_TypeObject:
     MCELF::SetType(SD, ELF::STT_OBJECT);
     break;
index d89112645cd8f41d5ff7ec8b8b1abf8577e45053..ffc400b203f956e30a3d74cebf03906a5c80e99a 100644 (file)
@@ -476,6 +476,7 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
     .Case("common", MCSA_ELF_TypeCommon)
     .Case("notype", MCSA_ELF_TypeNoType)
     .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
+    .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction)
     .Default(MCSA_Invalid);
 
   if (Attr == MCSA_Invalid)
index 2b25a6b69f69bcbc04e29034aec3180f74b9aec2..ec53e4ffa5245ffaef427bb0ecf7c02f0d57df05 100644 (file)
@@ -12,6 +12,10 @@ bar:
 // Test that gnu_unique_object is accepted.
         .type zed,@gnu_unique_object
 
+ifunc:
+        .global ifunc
+        .type ifunc,@gnu_indirect_function
+
 // CHECK:      # Symbol 4
 // CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
 // CHECK-NEXT:  ('st_bind', 0x1)
@@ -30,3 +34,13 @@ bar:
 // CHECK-NEXT:  ('st_value', 0x0000000000000000)
 // CHECK-NEXT:  ('st_size', 0x0000000000000000)
 // CHECK-NEXT: ),
+// CHECK-NEXT: # Symbol 6
+// CHECK-NEXT: (('st_name', 0x00000009) # 'ifunc'
+// CHECK-NEXT:  ('st_bind', 0x1)
+// CHECK-NEXT:  ('st_type', 0xa)
+// CHECK-NEXT:  ('st_other', 0x00)
+// CHECK-NEXT:  ('st_shndx', 0x0001)
+// CHECK-NEXT:  ('st_value', 0x0000000000000000)
+// CHECK-NEXT:  ('st_size', 0x0000000000000000)
+// CHECK-NEXT: ),
+