<div dir="ltr">Michael,<div><br></div><div>This patch doesn't seem to compile with Clang on Linux.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jul 8, 2015 at 5:21 PM, Michael J. Spencer <span dir="ltr"><<a href="mailto:bigcheesegs@gmail.com" target="_blank">bigcheesegs@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: mspencer<br>
Date: Wed Jul  8 19:21:06 2015<br>
New Revision: 241765<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D241765-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=1FBznK-Q1_Dsjl1Tbyli0BS3KpMlzW8XnIIMbqtdFvw&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=241765&view=rev</a><br>
Log:<br>
[Object][ELF] Support dumping hash-tables from files with no section table.<br>
<br>
Added:<br>
    llvm/trunk/test/Object/Inputs/no-section-table.so<br>
    llvm/trunk/test/Object/no-section-table.test<br>
Modified:<br>
    llvm/trunk/include/llvm/Object/ELF.h<br>
    llvm/trunk/include/llvm/Object/ELFTypes.h<br>
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp<br>
    llvm/trunk/tools/llvm-readobj/ObjDumper.h<br>
    llvm/trunk/tools/llvm-readobj/StreamWriter.h<br>
    llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Object/ELF.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_include_llvm_Object_ELF.h-3Frev-3D241765-26r1-3D241764-26r2-3D241765-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=KiGAoAr94U0SRGWNlnpW54oDPoq-wGim8Ubl4pqiWZQ&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=241765&r1=241764&r2=241765&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Object/ELF.h (original)<br>
+++ llvm/trunk/include/llvm/Object/ELF.h Wed Jul  8 19:21:06 2015<br>
@@ -16,6 +16,7 @@<br>
<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/IntervalMap.h"<br>
 #include "llvm/ADT/PointerIntPair.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/ADT/StringSwitch.h"<br>
@@ -139,6 +140,7 @@ public:<br>
   typedef Elf_Verneed_Impl<ELFT> Elf_Verneed;<br>
   typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux;<br>
   typedef Elf_Versym_Impl<ELFT> Elf_Versym;<br>
+  typedef Elf_Hash<ELFT> Elf_Hash;<br>
   typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter;<br>
   typedef iterator_range<Elf_Dyn_Iter> Elf_Dyn_Range;<br>
   typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter;<br>
@@ -176,6 +178,7 @@ private:<br>
   const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section.<br>
   StringRef DynSymStrTab;                   // Dynnamic symbol string table.<br>
   const Elf_Shdr *DotDynSymSec = nullptr;   // Dynamic symbol table section.<br>
+  const Elf_Hash *HashTable = nullptr;<br>
<br>
   const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr;<br>
   DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable;<br>
@@ -229,6 +232,8 @@ private:<br>
   void LoadVersionNeeds(const Elf_Shdr *ec) const;<br>
   void LoadVersionMap() const;<br>
<br>
+  void scanDynamicTable();<br>
+<br>
 public:<br>
   template<typename T><br>
   const T        *getEntry(uint32_t Section, uint32_t Entry) const;<br>
@@ -237,6 +242,7 @@ public:<br>
<br>
   const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; }<br>
   const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }<br>
+  const Elf_Hash *getHashTable() const { return HashTable; }<br>
<br>
   ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const;<br>
   const char *getDynamicString(uintX_t Offset) const;<br>
@@ -578,8 +584,10 @@ ELFFile<ELFT>::ELFFile(StringRef Object,<br>
<br>
   Header = reinterpret_cast<const Elf_Ehdr *>(base());<br>
<br>
-  if (Header->e_shoff == 0)<br>
+  if (Header->e_shoff == 0) {<br>
+    scanDynamicTable();<br>
     return;<br>
+  }<br>
<br>
   const uint64_t SectionTableOffset = Header->e_shoff;<br>
<br>
@@ -604,6 +612,13 @@ ELFFile<ELFT>::ELFFile(StringRef Object,<br>
<br>
   for (const Elf_Shdr &Sec : sections()) {<br>
     switch (Sec.sh_type) {<br>
+    case ELF::SHT_HASH:<br>
+      if (HashTable) {<br>
+        EC = object_error::parse_failed;<br>
+        return;<br>
+      }<br>
+      HashTable = reinterpret_cast<const Elf_Hash *>(base() + Sec.sh_offset);<br>
+      break;<br>
     case ELF::SHT_SYMTAB_SHNDX:<br>
       if (SymbolTableSectionHeaderIndex) {<br>
         // More than one .symtab_shndx!<br>
@@ -701,7 +716,21 @@ ELFFile<ELFT>::ELFFile(StringRef Object,<br>
     }<br>
   }<br>
<br>
-  // Scan program headers.<br>
+  scanDynamicTable();<br>
+<br>
+  EC = std::error_code();<br>
+}<br>
+<br>
+template <class ELFT><br>
+void ELFFile<ELFT>::scanDynamicTable() {<br>
+  // Build load-address to file-offset map.<br>
+  typedef typename IntervalMap<<br>
+      uintX_t, uintptr_t,<br>
+      IntervalMapImpl::NodeSizer<uintX_t, uintptr_t>::LeafSize,<br>
+      IntervalMapHalfOpenInfo<uintX_t>> LoadMapT;<br>
+  LoadMapT::Allocator Alloc;<br>
+  LoadMapT LoadMap(Alloc);<br>
+<br>
   for (Elf_Phdr_Iter PhdrI = program_header_begin(),<br>
                      PhdrE = program_header_end();<br>
        PhdrI != PhdrE; ++PhdrI) {<br>
@@ -709,34 +738,36 @@ ELFFile<ELFT>::ELFFile(StringRef Object,<br>
       DynamicRegion.Addr = base() + PhdrI->p_offset;<br>
       DynamicRegion.Size = PhdrI->p_filesz;<br>
       DynamicRegion.EntSize = sizeof(Elf_Dyn);<br>
-      break;<br>
+      continue;<br>
     }<br>
+    if (PhdrI->p_type != ELF::PT_LOAD)<br>
+      continue;<br>
+    if (PhdrI->p_filesz == 0)<br>
+      continue;<br>
+    LoadMap.insert(PhdrI->p_vaddr, PhdrI->p_vaddr + PhdrI->p_filesz,<br>
+                   PhdrI->p_offset);<br>
   }<br>
<br>
-  // Scan dynamic table.<br>
+  auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {<br>
+    auto I = LoadMap.find(VAddr);<br>
+    if (I == LoadMap.end())<br>
+      return nullptr;<br>
+    return base() + I.value() + (VAddr - I.start());<br>
+  };<br>
+<br>
   for (Elf_Dyn_Iter DynI = dynamic_table_begin(), DynE = dynamic_table_end();<br>
        DynI != DynE; ++DynI) {<br>
     switch (DynI->d_tag) {<br>
-    case ELF::DT_RELA: {<br>
-      uint64_t VBase = 0;<br>
-      const uint8_t *FBase = nullptr;<br>
-      for (Elf_Phdr_Iter PhdrI = program_header_begin(),<br>
-                         PhdrE = program_header_end();<br>
-           PhdrI != PhdrE; ++PhdrI) {<br>
-        if (PhdrI->p_type != ELF::PT_LOAD)<br>
-          continue;<br>
-        if (DynI->getPtr() >= PhdrI->p_vaddr &&<br>
-            DynI->getPtr() < PhdrI->p_vaddr + PhdrI->p_memsz) {<br>
-          VBase = PhdrI->p_vaddr;<br>
-          FBase = base() + PhdrI->p_offset;<br>
-          break;<br>
-        }<br>
-      }<br>
-      if (!VBase)<br>
-        return;<br>
-      DynRelaRegion.Addr = FBase + DynI->getPtr() - VBase;<br>
+    case ELF::DT_HASH:<br>
+      if (HashTable)<br>
+        continue;<br>
+      HashTable =<br>
+          reinterpret_cast<const Elf_Hash *>(toMappedAddr(DynI->getPtr()));<br>
+      break;<br>
+    case ELF::DT_RELA:<br>
+      if (!DynRelaRegion.Addr)<br>
+        DynRelaRegion.Addr = toMappedAddr(DynI->getPtr());<br>
       break;<br>
-    }<br>
     case ELF::DT_RELASZ:<br>
       DynRelaRegion.Size = DynI->getVal();<br>
       break;<br>
@@ -744,8 +775,6 @@ ELFFile<ELFT>::ELFFile(StringRef Object,<br>
       DynRelaRegion.EntSize = DynI->getVal();<br>
     }<br>
   }<br>
-<br>
-  EC = std::error_code();<br>
 }<br>
<br>
 template <class ELFT><br>
<br>
Modified: llvm/trunk/include/llvm/Object/ELFTypes.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_include_llvm_Object_ELFTypes.h-3Frev-3D241765-26r1-3D241764-26r2-3D241765-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=_yh5en8nTmmaIfjM8kXBfoKHgVP7RP46UdSJBXFH3LQ&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFTypes.h?rev=241765&r1=241764&r2=241765&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Object/ELFTypes.h (original)<br>
+++ llvm/trunk/include/llvm/Object/ELFTypes.h Wed Jul  8 19:21:06 2015<br>
@@ -10,6 +10,7 @@<br>
 #ifndef LLVM_OBJECT_ELFTYPES_H<br>
 #define LLVM_OBJECT_ELFTYPES_H<br>
<br>
+#include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/Object/Error.h"<br>
 #include "llvm/Support/DataTypes.h"<br>
 #include "llvm/Support/ELF.h"<br>
@@ -463,6 +464,23 @@ struct Elf_Phdr_Impl<ELFType<TargetEndia<br>
   Elf_Xword p_align;  // Segment alignment constraint<br>
 };<br>
<br>
+// ELFT needed for endianess.<br>
+template <class ELFT><br>
+struct Elf_Hash {<br>
+  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT);<br>
+  Elf_Word nbucket;<br>
+  Elf_Word nchain;<br>
+<br>
+  ArrayRef<const Elf_Word> buckets() const {<br>
+    return ArrayRef<const Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket);<br>
+  }<br>
+<br>
+  ArrayRef<const Elf_Word> chains() const {<br>
+    return ArrayRef<const Elf_Word>(&nbucket + 2 + nbucket,<br>
+                                    &nbucket + 2 + nbucket + nchain);<br>
+  }<br>
+};<br>
+<br>
 // MIPS .reginfo section<br>
 template <class ELFT><br>
 struct Elf_Mips_RegInfo;<br>
<br>
Added: llvm/trunk/test/Object/Inputs/no-section-table.so<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Object_Inputs_no-2Dsection-2Dtable.so-3Frev-3D241765-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=UfqoLNQO11n-3se3pjPMidT_u_YKjsUTSf6QcEJLvAo&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/no-section-table.so?rev=241765&view=auto</a><br>
==============================================================================<br>
Binary files llvm/trunk/test/Object/Inputs/no-section-table.so (added) and llvm/trunk/test/Object/Inputs/no-section-table.so Wed Jul  8 19:21:06 2015 differ<br>
<br>
Added: llvm/trunk/test/Object/no-section-table.test<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Object_no-2Dsection-2Dtable.test-3Frev-3D241765-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=uQbu5aYZgLJ1P23Bq5xAHgV_uk_xdayG1_JWS9xw-f4&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/no-section-table.test?rev=241765&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Object/no-section-table.test (added)<br>
+++ llvm/trunk/test/Object/no-section-table.test Wed Jul  8 19:21:06 2015<br>
@@ -0,0 +1,8 @@<br>
+RUN: llvm-readobj %p/Inputs/no-section-table.so -hash-table | FileCheck %s<br>
+<br>
+CHECK: HashTable {<br>
+CHECK:   Num Buckets: 3<br>
+CHECK:   Num Chains: 13<br>
+CHECK:   Buckets: [12, 10, 11]<br>
+CHECK:   Chains: [0, 0, 0, 0, 2, 3, 4, 0, 7, 5, 6, 8, 9]<br>
+CHECK: }<br>
<br>
Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2Dreadobj_ELFDumper.cpp-3Frev-3D241765-26r1-3D241764-26r2-3D241765-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=zbXhwSeW1eTP0vQboSjP2sj-VA4PcxLluvMJwbe2XHw&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=241765&r1=241764&r2=241765&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)<br>
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Wed Jul  8 19:21:06 2015<br>
@@ -56,6 +56,7 @@ public:<br>
   void printDynamicTable() override;<br>
   void printNeededLibraries() override;<br>
   void printProgramHeaders() override;<br>
+  void printHashTable() override;<br>
<br>
   void printAttributes() override;<br>
   void printMipsPLTGOT() override;<br>
@@ -1119,6 +1120,18 @@ void ELFDumper<ELFT>::printProgramHeader<br>
   }<br>
 }<br>
<br>
+template <typename ELFT><br>
+void ELFDumper<ELFT>::printHashTable() {<br>
+  DictScope D(W, "HashTable");<br>
+  auto HT = Obj->getHashTable();<br>
+  if (!HT)<br>
+    return;<br>
+  W.printNumber("Num Buckets", HT->nbucket);<br>
+  W.printNumber("Num Chains", HT->nchain);<br>
+  W.printList("Buckets", HT->buckets());<br>
+  W.printList("Chains", HT->chains());<br>
+}<br>
+<br>
 template <class ELFT><br>
 void ELFDumper<ELFT>::printAttributes() {<br>
   W.startLine() << "Attributes not implemented.\n";<br>
<br>
Modified: llvm/trunk/tools/llvm-readobj/ObjDumper.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2Dreadobj_ObjDumper.h-3Frev-3D241765-26r1-3D241764-26r2-3D241765-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=TRvhhClXhJiU8e46dRlctaho7yftLo0y07w2yDYxh30&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ObjDumper.h?rev=241765&r1=241764&r2=241765&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-readobj/ObjDumper.h (original)<br>
+++ llvm/trunk/tools/llvm-readobj/ObjDumper.h Wed Jul  8 19:21:06 2015<br>
@@ -37,6 +37,7 @@ public:<br>
   virtual void printDynamicTable() { }<br>
   virtual void printNeededLibraries() { }<br>
   virtual void printProgramHeaders() { }<br>
+  virtual void printHashTable() { }<br>
<br>
   // Only implemented for ARM ELF at this time.<br>
   virtual void printAttributes() { }<br>
<br>
Modified: llvm/trunk/tools/llvm-readobj/StreamWriter.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2Dreadobj_StreamWriter.h-3Frev-3D241765-26r1-3D241764-26r2-3D241765-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=LM4ZL2T8BH_8R6wQKMZxTGpbOYIrOl-fwJmQezDWUmk&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/StreamWriter.h?rev=241765&r1=241764&r2=241765&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-readobj/StreamWriter.h (original)<br>
+++ llvm/trunk/tools/llvm-readobj/StreamWriter.h Wed Jul  8 19:21:06 2015<br>
@@ -181,8 +181,8 @@ public:<br>
     startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';<br>
   }<br>
<br>
-  template <typename T_><br>
-  void printList(StringRef Label, const SmallVectorImpl<T_> &List) {<br>
+  template <typename T><br>
+  void printList(StringRef Label, const T &List) {<br>
     startLine() << Label << ": [";<br>
     bool Comma = false;<br>
     for (const auto &Item : List) {<br>
<br>
Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_tools_llvm-2Dreadobj_llvm-2Dreadobj.cpp-3Frev-3D241765-26r1-3D241764-26r2-3D241765-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=UtQxE0-VNFK75WWnQdSO4HpXT1LjCGDOo_9WnJrGFGw&s=1intY3JBekeiZCDA7jrlI5B0y8Goi1XJeQyDpIkm-wA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=241765&r1=241764&r2=241765&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)<br>
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Wed Jul  8 19:21:06 2015<br>
@@ -127,6 +127,10 @@ namespace opts {<br>
   cl::opt<bool> ProgramHeaders("program-headers",<br>
     cl::desc("Display ELF program headers"));<br>
<br>
+  // -hash-table<br>
+  cl::opt<bool> HashTable("hash-table",<br>
+    cl::desc("Display ELF hash table"));<br>
+<br>
   // -expand-relocs<br>
   cl::opt<bool> ExpandRelocs("expand-relocs",<br>
     cl::desc("Expand each shown relocation to multiple lines"));<br>
@@ -300,6 +304,8 @@ static void dumpObject(const ObjectFile<br>
     Dumper->printNeededLibraries();<br>
   if (opts::ProgramHeaders)<br>
     Dumper->printProgramHeaders();<br>
+  if (opts::HashTable)<br>
+    Dumper->printHashTable();<br>
   if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())<br>
     if (opts::ARMAttributes)<br>
       Dumper->printAttributes();<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>