ayermolo updated this revision to Diff 492841. ayermolo added a comment. addressed comments
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D138618/new/ https://reviews.llvm.org/D138618 Files: lldb/include/lldb/Core/dwarf.h lldb/include/lldb/Symbol/DWARFCallFrameInfo.h lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp lldb/source/Plugins/SymbolFile/DWARF/DIERef.h lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s lldb/unittests/Expression/DWARFExpressionTest.cpp lldb/unittests/SymbolFile/DWARF/DWARFIndexCachingTest.cpp
Index: lldb/unittests/SymbolFile/DWARF/DWARFIndexCachingTest.cpp =================================================================== --- lldb/unittests/SymbolFile/DWARF/DWARFIndexCachingTest.cpp +++ lldb/unittests/SymbolFile/DWARF/DWARFIndexCachingTest.cpp @@ -45,6 +45,26 @@ EncodeDecode(DIERef(200, DIERef::Section::DebugTypes, 0x11223344)); } +TEST(DWARFIndexCachingTest, DIERefEncodeDecodeMax) { + // Tests DIERef::Encode(...) and DIERef::Decode(...) + EncodeDecode(DIERef(llvm::None, DIERef::Section::DebugInfo, + DIERef::k_die_offset_mask)); + EncodeDecode(DIERef(llvm::None, DIERef::Section::DebugTypes, + DIERef::k_die_offset_mask)); + EncodeDecode( + DIERef(100, DIERef::Section::DebugInfo, DIERef::k_die_offset_mask)); + EncodeDecode( + DIERef(200, DIERef::Section::DebugTypes, DIERef::k_die_offset_mask)); + EncodeDecode(DIERef(DIERef::k_dwo_num_mask, DIERef::Section::DebugInfo, + DIERef::k_dwo_num_mask)); + EncodeDecode(DIERef(DIERef::k_dwo_num_mask, DIERef::Section::DebugTypes, + DIERef::k_dwo_num_mask)); + EncodeDecode( + DIERef(DIERef::k_dwo_num_mask, DIERef::Section::DebugInfo, 0x11223344)); + EncodeDecode( + DIERef(DIERef::k_dwo_num_mask, DIERef::Section::DebugTypes, 0x11223344)); +} + static void EncodeDecode(const NameToDIE &object, ByteOrder byte_order) { const uint8_t addr_size = 8; DataEncoder encoder(byte_order, addr_size); Index: lldb/unittests/Expression/DWARFExpressionTest.cpp =================================================================== --- lldb/unittests/Expression/DWARFExpressionTest.cpp +++ lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -713,7 +713,7 @@ // Entries: // - AbbrCode: 0x1 // Values: - // - Value: 0x01020304 + // - Value: 0x0120304 // - AbbrCode: 0x0 const char *dwo_yamldata = R"( --- !ELF @@ -750,7 +750,7 @@ auto dwo_module_sp = std::make_shared<Module>(dwo_file->moduleSpec()); SymbolFileDWARFDwo dwo_symfile( skeleton_symfile, dwo_module_sp->GetObjectFile()->shared_from_this(), - 0x01020304); + 0x0120304); auto *dwo_dwarf_unit = dwo_symfile.DebugInfo().GetUnitAtIndex(0); testExpressionVendorExtensions(dwo_module_sp, *dwo_dwarf_unit); Index: lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s =================================================================== --- lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s +++ lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s @@ -8,7 +8,7 @@ # RUN: -o exit | FileCheck %s # Failure was the block range 1..2 was not printed plus: -# error: DW_AT_range-DW_FORM_sec_offset.s.tmp {0x0000003f}: DIE has DW_AT_ranges(0xc) attribute, but range extraction failed (missing or invalid range list table), please file a bug and attach the file at the start of this error message +# error: DW_AT_range-DW_FORM_sec_offset.s.tmp {0x000000000000003f}: DIE has DW_AT_ranges(0xc) attribute, but range extraction failed (missing or invalid range list table), please file a bug and attach the file at the start of this error message # CHECK-LABEL: image lookup -v -s lookup_rnglists # CHECK: Function: id = {0x00000029}, name = "rnglists", range = [0x0000000000000000-0x0000000000000003) Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -41,7 +41,7 @@ DWARFDIE GetDIE(const DIERef &die_ref) override; - std::optional<uint32_t> GetDwoNum() override { return GetID() >> 32; } + std::optional<uint32_t> GetDwoNum() override { return GetID(); } lldb::offset_t GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -29,7 +29,7 @@ : SymbolFileDWARF(objfile, objfile->GetSectionList( /*update_module_section_list*/ false)), m_base_symbol_file(base_symbol_file) { - SetID(user_id_t(id) << 32); + SetID(user_id_t(id)); // Parsing of the dwarf unit index is not thread-safe, so we need to prime it // to enable subsequent concurrent lookups. @@ -42,7 +42,7 @@ if (auto *unit_contrib = entry->getContribution()) return llvm::dyn_cast_or_null<DWARFCompileUnit>( DebugInfo().GetUnitAtOffset(DIERef::Section::DebugInfo, - unit_contrib->getOffset32())); + unit_contrib->getOffset())); } return nullptr; } Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -587,6 +587,14 @@ } } + constexpr uint64_t MaxDebugInfoSize = (1ull) << DW_DIE_OFFSET_MAX_BITSIZE; + if (debug_info_file_size >= MaxDebugInfoSize) { + m_objfile_sp->GetModule()->ReportWarning( + "SymbolFileDWARF can't load this DWARF. It's larger then {0:x+16}", + MaxDebugInfoSize); + return 0; + } + if (debug_abbrev_file_size > 0 && debug_info_file_size > 0) abilities |= CompileUnits | Functions | Blocks | GlobalVariables | LocalVariables | VariableTypes; @@ -1400,10 +1408,7 @@ if (GetDebugMapSymfile()) return GetID() | ref.die_offset(); - lldbassert(GetDwoNum().value_or(0) <= 0x3fffffff); - return user_id_t(GetDwoNum().value_or(0)) << 32 | ref.die_offset() | - lldb::user_id_t(GetDwoNum().has_value()) << 62 | - lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63; + return DIERef(GetID(), ref.section(), ref.die_offset()).get_id(); } std::optional<SymbolFileDWARF::DecodedUID> @@ -1418,25 +1423,19 @@ // references to other DWARF objects and we must be ready to receive a // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF // instance. + DIERef die_ref(uid); if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) { SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex( debug_map->GetOSOIndexFromUserID(uid)); return DecodedUID{ - *dwarf, {std::nullopt, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; + *dwarf, + {std::nullopt, DIERef::Section::DebugInfo, die_ref.die_offset()}}; } - dw_offset_t die_offset = uid; - if (die_offset == DW_INVALID_OFFSET) - return std::nullopt; - - DIERef::Section section = - uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo; - std::optional<uint32_t> dwo_num; - bool dwo_valid = uid >> 62 & 1; - if (dwo_valid) - dwo_num = uid >> 32 & 0x3fffffff; + if (die_ref.die_offset() == DW_INVALID_OFFSET) + return std::nullopt; - return DecodedUID{*this, {dwo_num, section, die_offset}}; + return DecodedUID{*this, die_ref}; } DWARFDIE @@ -1694,7 +1693,7 @@ DWARFDIE SymbolFileDWARF::GetDIE(const DIERef &die_ref) { if (die_ref.dwo_num()) { - SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x3fffffff + SymbolFileDWARF *dwarf = *die_ref.dwo_num() == DIERef::k_dwo_num_mask ? m_dwp_symfile.get() : this->DebugInfo() .GetUnitAtIndex(*die_ref.dwo_num()) @@ -3184,7 +3183,7 @@ return 0; size_t functions_added = 0; - const dw_offset_t function_die_offset = func.GetID(); + const dw_offset_t function_die_offset = DIERef(func.GetID()).die_offset(); DWARFDIE function_die = dwarf_cu->GetNonSkeletonUnit().GetDIE(function_die_offset); if (function_die) { @@ -4160,8 +4159,8 @@ dwp_file_data_offset); if (!dwp_obj_file) return; - m_dwp_symfile = - std::make_shared<SymbolFileDWARFDwo>(*this, dwp_obj_file, 0x3fffffff); + m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>( + *this, dwp_obj_file, DIERef::k_dwo_num_mask); } }); return m_dwp_symfile; Index: lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -525,7 +525,10 @@ kDataIDEnd = 255u, }; -constexpr uint32_t CURRENT_CACHE_VERSION = 1; + +// Version 2 changes the encoding of DIERef objects used in the DWARF manual +// index name tables. See DIERef class for details. +constexpr uint32_t CURRENT_CACHE_VERSION = 2; bool ManualDWARFIndex::IndexSet::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr) { Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -341,7 +341,7 @@ if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { if (const auto *contribution = entry->getContribution(llvm::DW_SECT_STR_OFFSETS)) - baseOffset = contribution->getOffset32(); + baseOffset = contribution->getOffset(); else return; } @@ -489,7 +489,7 @@ *GetDWOId()); return; } - offset += contribution->getOffset32(); + offset += contribution->getOffset(); } m_loclists_base = loclists_base; @@ -527,7 +527,7 @@ if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { if (const auto *contribution = entry->getContribution( GetVersion() >= 5 ? llvm::DW_SECT_LOCLISTS : llvm::DW_SECT_EXT_LOC)) - return DWARFDataExtractor(data, contribution->getOffset32(), + return DWARFDataExtractor(data, contribution->getOffset(), contribution->getLength32()); return DWARFDataExtractor(); } @@ -540,7 +540,7 @@ if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { if (const auto *contribution = entry->getContribution(llvm::DW_SECT_RNGLISTS)) - return DWARFDataExtractor(data, contribution->getOffset32(), + return DWARFDataExtractor(data, contribution->getOffset(), contribution->getLength32()); GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( "Failed to find range list contribution for CU with signature {0:x16}", @@ -935,7 +935,7 @@ llvm::inconvertibleErrorCode(), "DWARF package index missing abbreviation column"); } - header.m_abbr_offset = abbr_entry->getOffset32(); + header.m_abbr_offset = abbr_entry->getOffset(); } bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -36,7 +36,8 @@ typedef collection::const_iterator const_iterator; DWARFDebugInfoEntry() - : m_offset(DW_INVALID_OFFSET), m_sibling_idx(0), m_has_children(false) {} + : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), + m_has_children(false) {} explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } bool operator==(const DWARFDebugInfoEntry &rhs) const; @@ -165,14 +166,16 @@ static DWARFDeclContext GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu); - dw_offset_t m_offset; // Offset within the .debug_info/.debug_types - uint32_t m_parent_idx = 0; // How many to subtract from "this" to get the - // parent. If zero this die has no parent - uint32_t m_sibling_idx : 31, // How many to add to "this" to get the sibling. - // If it is zero, then the DIE doesn't have children, or the - // DWARF claimed it had children but the DIE only contained - // a single NULL terminating child. - m_has_children : 1; + // Up to 2TB offset within the .debug_info/.debug_types + dw_offset_t m_offset : DW_DIE_OFFSET_MAX_BITSIZE; + // How many to subtract from "this" to get the parent. If zero this die has no + // parent + dw_offset_t m_parent_idx : 64 - DW_DIE_OFFSET_MAX_BITSIZE; + // How many to add to "this" to get the sibling. + // If it is zero, then the DIE doesn't have children, + // or the DWARF claimed it had children but the DIE + // only contained a single NULL terminating child. + uint32_t m_sibling_idx : 31, m_has_children : 1; uint16_t m_abbr_idx = 0; /// A copy of the DW_TAG value so we don't have to go through the compile /// unit abbrev table Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -64,7 +64,7 @@ "[{0:x16}]: invalid abbreviation code {1}, " "please file a bug and " "attach the file at the start of this error message", - m_offset, (unsigned)abbr_idx); + (uint64_t)m_offset, (unsigned)abbr_idx); // WE can't parse anymore if the DWARF is borked... *offset_ptr = UINT32_MAX; return false; @@ -195,7 +195,7 @@ "[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug " "and " "attach the file at the start of this error message", - m_offset, (unsigned)form); + (uint64_t)m_offset, (unsigned)form); *offset_ptr = m_offset; return false; } Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -136,7 +136,7 @@ }); uint32_t idx = std::distance(m_units.begin(), pos); if (idx == 0) - return DW_INVALID_OFFSET; + return DW_INVALID_INDEX; return idx - 1; } Index: lldb/source/Plugins/SymbolFile/DWARF/DIERef.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DIEREF_H #include "lldb/Core/dwarf.h" +#include "lldb/Utility/LLDBAssert.h" #include "llvm/Support/FormatProviders.h" #include <cassert> #include <optional> @@ -29,11 +30,26 @@ DIERef(std::optional<uint32_t> dwo_num, Section section, dw_offset_t die_offset) - : m_dwo_num(dwo_num.value_or(0)), m_dwo_num_valid(bool(dwo_num)), - m_section(section), m_die_offset(die_offset) { + : m_die_offset(die_offset), m_dwo_num(dwo_num.value_or(0)), + m_dwo_num_valid(dwo_num ? true : false), m_section(section) { assert(this->dwo_num() == dwo_num && "Dwo number out of range?"); } + explicit DIERef(lldb::user_id_t uid) { + m_die_offset = uid & k_die_offset_mask; + m_dwo_num_valid = (uid & k_dwo_num_valid_bit) != 0; + m_dwo_num = + m_dwo_num_valid ? (uid >> k_die_offset_bit_size) & k_dwo_num_mask : 0; + m_section = + (uid & k_section_bit) != 0 ? Section::DebugTypes : Section::DebugInfo; + } + + lldb::user_id_t get_id() const { + return lldb::user_id_t(dwo_num().value_or(0)) << k_die_offset_bit_size | + die_offset() | (m_dwo_num_valid ? k_dwo_num_valid_bit : 0) | + (section() == Section::DebugTypes ? k_section_bit : 0); + } + std::optional<uint32_t> dwo_num() const { if (m_dwo_num_valid) return m_dwo_num; @@ -85,11 +101,29 @@ /// void Encode(lldb_private::DataEncoder &encoder) const; + static constexpr uint64_t k_die_offset_bit_size = DW_DIE_OFFSET_MAX_BITSIZE; + static constexpr uint64_t k_dwo_num_bit_size = + 64 - DW_DIE_OFFSET_MAX_BITSIZE - /* size of control bits */ 2; + + static constexpr uint64_t k_dwo_num_valid_bit = + (1ull << (k_dwo_num_bit_size + k_die_offset_bit_size)); + static constexpr uint64_t k_section_bit = + (1ull << (k_dwo_num_bit_size + k_die_offset_bit_size + 1)); + + static constexpr uint64_t + k_dwo_num_mask = (~0ull) >> (64 - k_dwo_num_bit_size); // 0x1fffff; + static constexpr uint64_t k_die_offset_mask = (~0ull) >> + (64 - k_die_offset_bit_size); + private: - uint32_t m_dwo_num : 30; - uint32_t m_dwo_num_valid : 1; - uint32_t m_section : 1; - dw_offset_t m_die_offset; + // Allow 2TB of .debug_info/.debug_types offset + dw_offset_t m_die_offset : k_die_offset_bit_size; + // Used for DWO index or for .o file index on mac + dw_offset_t m_dwo_num : k_dwo_num_bit_size; + // Set to 1 if m_file_index is a DWO number + dw_offset_t m_dwo_num_valid : 1; + // Set to 0 for .debug_info 1 for .debug_types, + dw_offset_t m_section : 1; }; static_assert(sizeof(DIERef) == 8); Index: lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -23,34 +23,16 @@ OS << "/" << format_hex_no_prefix(ref.die_offset(), 8); } -constexpr uint32_t k_dwo_num_mask = 0x3FFFFFFF; -constexpr uint32_t k_dwo_num_valid_bitmask = (1u << 30); -constexpr uint32_t k_section_bitmask = (1u << 31); - std::optional<DIERef> DIERef::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr) { - const uint32_t bitfield_storage = data.GetU32(offset_ptr); - uint32_t dwo_num = bitfield_storage & k_dwo_num_mask; - bool dwo_num_valid = (bitfield_storage & (k_dwo_num_valid_bitmask)) != 0; - Section section = (Section)((bitfield_storage & (k_section_bitmask)) != 0); + DIERef die_ref(data.GetU64(offset_ptr)); + // DIE offsets can't be zero and if we fail to decode something from data, // it will return 0 - dw_offset_t die_offset = data.GetU32(offset_ptr); - if (die_offset == 0) + if (!die_ref.die_offset()) return std::nullopt; - if (dwo_num_valid) - return DIERef(dwo_num, section, die_offset); - else - return DIERef(std::nullopt, section, die_offset); -} -void DIERef::Encode(DataEncoder &encoder) const { - uint32_t bitfield_storage = m_dwo_num; - if (m_dwo_num_valid) - bitfield_storage |= k_dwo_num_valid_bitmask; - if (m_section) - bitfield_storage |= k_section_bitmask; - encoder.AppendU32(bitfield_storage); - static_assert(sizeof(m_die_offset) == 4, "m_die_offset must be 4 bytes"); - encoder.AppendU32(m_die_offset); + return die_ref; } + +void DIERef::Encode(DataEncoder &encoder) const { encoder.AppendU64(get_id()); } Index: lldb/include/lldb/Symbol/DWARFCallFrameInfo.h =================================================================== --- lldb/include/lldb/Symbol/DWARFCallFrameInfo.h +++ lldb/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -128,7 +128,7 @@ void GetFDEIndex(); - bool FDEToUnwindPlan(uint32_t offset, Address startaddr, + bool FDEToUnwindPlan(dw_offset_t offset, Address startaddr, UnwindPlan &unwind_plan); const CIE *GetCIE(dw_offset_t cie_offset); @@ -159,7 +159,7 @@ Type m_type; CIESP - ParseCIE(const uint32_t cie_offset); + ParseCIE(const dw_offset_t cie_offset); lldb::RegisterKind GetRegisterKind() const { return m_type == EH ? lldb::eRegisterKindEHFrame : lldb::eRegisterKindDWARF; Index: lldb/include/lldb/Core/dwarf.h =================================================================== --- lldb/include/lldb/Core/dwarf.h +++ lldb/include/lldb/Core/dwarf.h @@ -30,11 +30,12 @@ // any addresses in the compile units that get // parsed -typedef uint32_t dw_offset_t; // Dwarf Debug Information Entry offset for any +typedef uint64_t dw_offset_t; // Dwarf Debug Information Entry offset for any // offset into the file /* Constants */ -#define DW_INVALID_OFFSET (~(dw_offset_t)0) +#define DW_DIE_OFFSET_MAX_BITSIZE 40 +#define DW_INVALID_OFFSET (((uint64_t)1u << DW_DIE_OFFSET_MAX_BITSIZE) - 1) #define DW_INVALID_INDEX 0xFFFFFFFFul // #define DW_ADDR_none 0x0
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits