Added support for accessing and loading our new .debug_names and .debug_types

DWARF accelerator table sections to the DWARF parser. These sections are similar
to the .debug_pubnames and .debug_pubtypes, but they are designed to be hash tables
that are saved to disc in a way that the sections can just be loaded into memory
and used without any work on the debugger side. The .debug_pubnames and .debug_pubtypes
sections are not ordered, contain a copy of the name in the section itself which
makes these sections quite large, they only include publicly exported names (so no
static functions, no types defined inside functions), many compilers put different
information in them making them very unreliable so most debugger ignore these sections
and parse the DWARF on their own. The tables must also be parsed and sorted in order 
to be used effectively. The new sections can be quickly loaded and very efficiently be used 
to do name to DIE lookups with very little up front work. The format of these new
sections will be changing while we work out the bugs, but we hope to have really 
fast name to DIE lookups soon.

llvm-svn: 138979
This commit is contained in:
Greg Clayton 2011-09-01 23:16:13 +00:00
parent 5d7a6f31f7
commit f9eec20bd3
9 changed files with 278 additions and 35 deletions

View File

@ -468,6 +468,8 @@ namespace lldb {
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugNames,
eSectionTypeDWARFDebugTypes,
eSectionTypeEHFrame,
eSectionTypeOther

View File

@ -340,6 +340,7 @@
26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */; };
26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */; };
2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */; };
26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A0DA4C140F721D006DA411 /* HashedNameToDIE.cpp */; };
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C6886E137880C400407EDF /* RegisterValue.cpp */; };
26A7A035135E6E4200FB369E /* NamedOptionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */; };
26B1FA1413380E61002886E2 /* LLDBWrapPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */; };
@ -729,6 +730,8 @@
269FF08112494FC200225026 /* UnwindTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindTable.h; path = include/lldb/Symbol/UnwindTable.h; sourceTree = "<group>"; };
26A0604711A5BC7A00F75969 /* Baton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Baton.h; path = include/lldb/Core/Baton.h; sourceTree = "<group>"; };
26A0604811A5D03C00F75969 /* Baton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Baton.cpp; path = source/Core/Baton.cpp; sourceTree = "<group>"; };
26A0DA4C140F721D006DA411 /* HashedNameToDIE.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HashedNameToDIE.cpp; sourceTree = "<group>"; };
26A0DA4D140F721D006DA411 /* HashedNameToDIE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashedNameToDIE.h; sourceTree = "<group>"; };
26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerBSDArchive.cpp; sourceTree = "<group>"; };
26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerBSDArchive.h; sourceTree = "<group>"; };
26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
@ -1559,6 +1562,8 @@
260C89D610F57C5600BB2B04 /* DWARFLocationDescription.h */,
260C89D710F57C5600BB2B04 /* DWARFLocationList.cpp */,
260C89D810F57C5600BB2B04 /* DWARFLocationList.h */,
26A0DA4C140F721D006DA411 /* HashedNameToDIE.cpp */,
26A0DA4D140F721D006DA411 /* HashedNameToDIE.h */,
2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */,
2618D957124056C700F2B8FE /* NameToDIE.h */,
260C89D910F57C5600BB2B04 /* SymbolFileDWARF.cpp */,
@ -3307,7 +3312,7 @@
9470A8F01402DFFB0056FF61 /* DataVisualization.cpp in Sources */,
26274FA214030EEF006BA130 /* OperatingSystemDarwinKernel.cpp in Sources */,
26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */,
268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */,
26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -255,6 +255,8 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr)
case eSectionTypeDWARFDebugPubTypes: return eAddressClassDebug;
case eSectionTypeDWARFDebugRanges: return eAddressClassDebug;
case eSectionTypeDWARFDebugStr: return eAddressClassDebug;
case eSectionTypeDWARFDebugNames: return eAddressClassDebug;
case eSectionTypeDWARFDebugTypes: return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeOther: return eAddressClassUnknown;
}
@ -505,6 +507,8 @@ ObjectFileMachO::ParseSections ()
static ConstString g_sect_name_dwarf_debug_pubtypes ("__debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges ("__debug_ranges");
static ConstString g_sect_name_dwarf_debug_str ("__debug_str");
static ConstString g_sect_name_dwarf_debug_names ("__debug_names");
static ConstString g_sect_name_dwarf_debug_types ("__debug_types");
static ConstString g_sect_name_eh_frame ("__eh_frame");
static ConstString g_sect_name_DATA ("__DATA");
static ConstString g_sect_name_TEXT ("__TEXT");
@ -533,6 +537,10 @@ ObjectFileMachO::ParseSections ()
sect_type = eSectionTypeDWARFDebugRanges;
else if (section_name == g_sect_name_dwarf_debug_str)
sect_type = eSectionTypeDWARFDebugStr;
else if (section_name == g_sect_name_dwarf_debug_names)
sect_type = eSectionTypeDWARFDebugNames;
else if (section_name == g_sect_name_dwarf_debug_types)
sect_type = eSectionTypeDWARFDebugTypes;
else if (section_name == g_sect_name_objc_selrefs)
sect_type = eSectionTypeDataCStringPointers;
else if (section_name == g_sect_name_objc_msgrefs)

View File

@ -9,17 +9,27 @@
#include "NameToDIE.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Symbol/ObjectFile.h"
#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
#include "SymbolFileDWARF.h"
using namespace lldb;
using namespace lldb_private;
void
NameToDIE::Insert (const lldb_private::ConstString& name, const Info &info)
NameToDIE::Insert (const ConstString& name, const Info &info)
{
m_collection.insert (std::make_pair(name.AsCString(), info));
}
size_t
NameToDIE::Find (const lldb_private::ConstString &name, std::vector<Info> &info_array) const
NameToDIE::Find (const ConstString &name, std::vector<Info> &info_array) const
{
const char *name_cstr = name.AsCString();
const size_t initial_info_array_size = info_array.size();
@ -32,7 +42,7 @@ NameToDIE::Find (const lldb_private::ConstString &name, std::vector<Info> &info_
}
size_t
NameToDIE::Find (const lldb_private::RegularExpression& regex, std::vector<Info> &info_array) const
NameToDIE::Find (const RegularExpression& regex, std::vector<Info> &info_array) const
{
const size_t initial_info_array_size = info_array.size();
collection::const_iterator pos, end = m_collection.end();
@ -58,7 +68,7 @@ NameToDIE::FindAllEntriesForCompileUnitWithIndex (const uint32_t cu_idx, std::ve
}
void
NameToDIE::Dump (lldb_private::Stream *s)
NameToDIE::Dump (Stream *s)
{
collection::const_iterator pos, end = m_collection.end();
for (pos = m_collection.begin(); pos != end; ++pos)
@ -85,13 +95,88 @@ struct HashEntry
uint32_t cu_idx;
uint32_t die_idx;
const char *name;
bool
operator < (const HashEntry &rhs) const
{
return hash < rhs.hash;
}
};
struct HashHeader
{
uint32_t version;
uint32_t bucket_info_size; // The fixed data associated with this bucket
uint32_t bucket_count;
uint32_t flags;
};
struct HashBucketInfo
{
uint32_t offset; // Offset to the data for each bucket
};
struct HashBucketEntryStrp
{
HashBucketEntryStrp () :
str_offset (0)
{
}
HashBucketEntryStrp (uint32_t s, uint32_t d) :
str_offset (s)
{
}
uint32_t
GetByteSize ()
{
return sizeof(uint32_t) + // String offset in .debug_str
sizeof(uint32_t) + // Number of dies
die_array.size() * sizeof(uint32_t);
}
uint32_t str_offset;
std::vector<dw_offset_t> die_array;
};
typedef std::vector<dw_offset_t> DIEArray;
typedef std::map<const char *, DIEArray> NameToDIEArrayMap;
struct HashBucketEntryCStr
{
uint32_t
GetByteSize () const
{
uint32_t byte_size = 0;
NameToDIEArrayMap::const_iterator pos, end = name_to_die.end();
for (pos = name_to_die.begin(); pos != end; ++pos)
{
// Include the size of the and a length for the dies, and all dies
byte_size += sizeof(uint32_t) + sizeof(uint32_t) * (pos->second.size() + 1);
}
return byte_size;
}
NameToDIEArrayMap name_to_die;
};
static uint32_t
closest_power_2_less_than_n (uint32_t n)
{
if (n)
return 0x80000000u >> __builtin_clz (n);
return 0;
}
typedef struct HashEntry HashEntryType;
void
NameToDIE::Hash (lldb_private::Stream *s)
NameToDIE::Hash (Stream *s, SymbolFileDWARF *dwarf)
{
if (m_collection.empty())
return;
typedef std::vector<HashEntryType> hash_collection;
hash_collection hash_entries;
collection::const_iterator pos, end = m_collection.end();
@ -101,42 +186,160 @@ NameToDIE::Hash (lldb_private::Stream *s)
hash_entries.push_back (entry);
}
// const DataExtractor &debug_str_data = dwarf->get_debug_str_data();
const uint32_t hash_entries_size = hash_entries.size();
uint32_t i;
DWARFDebugInfo *debug_info = dwarf->DebugInfo();
for (uint32_t power_2 = 0x10; power_2 <= hash_entries_size; power_2 <<= 1)
uint32_t num_buckets;
if (hash_entries_size > 1024)
num_buckets = closest_power_2_less_than_n (hash_entries_size/16);
else if (hash_entries_size > 128)
num_buckets = closest_power_2_less_than_n (hash_entries_size/8);
else
num_buckets = closest_power_2_less_than_n (hash_entries_size/4);
if (num_buckets == 0)
num_buckets = 1;
//for (uint32_t power_2 = 0x10; power_2 <= hash_entries_size; power_2 <<= 1)
{
const uint32_t size = power_2 - 1;
if (size > 0x10 && size > hash_entries_size)
break;
// if (num_buckets > 0x10 && num_buckets > hash_entries_size)
// break;
s->Printf ("\nTrying size of %u for %u items:\n", size, hash_entries_size);
std::vector<uint32_t> indexes(size, 0);
typedef std::vector<uint32_t> uint32_array;
typedef std::map<uint32_t, HashBucketEntryCStr> HashBucketEntryMap;
std::vector<HashBucketEntryMap> hash_buckets;
hash_buckets.resize(num_buckets);
uint32_t bucket_entry_empties = 0;
uint32_t bucket_entry_single = 0;
uint32_t bucket_entry_collisions = 0;
uint32_t names_entry_single = 0;
uint32_t names_entry_collisions = 0;
//StreamString hash_file_data(Stream::eBinary, dwarf->GetObjectFile()->GetAddressByteSize(), dwarf->GetObjectFile()->GetByteSize());
// Write hash table header
// hash_file_data.PutHex32 (1); // Version
// hash_file_data.PutHex32 (4); // Sizeof bucket data
// hash_file_data.PutHex32 (num_buckets);
// hash_file_data.PutHex32 (0); // Flags
s->Printf("HashHeader = { version = %u, bucket_info_size = %u, bucket_count = %u, flags = 0x%8.8x }\n", 1, (uint32_t)sizeof(HashBucketInfo), num_buckets, 0);
for (i=0; i<hash_entries_size; ++i)
{
indexes[hash_entries[i].hash % size]++;
uint32_t hash = hash_entries[i].hash;
uint32_t bucket_idx = hash_entries[i].hash % num_buckets;
DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex (hash_entries[i].cu_idx);
cu->ExtractDIEsIfNeeded(false);
DWARFDebugInfoEntry *die = cu->GetDIEAtIndexUnchecked(hash_entries[i].die_idx);
hash_buckets[bucket_idx][hash].name_to_die[hash_entries[i].name].push_back(die->GetOffset());
}
const uint32_t indexes_size = indexes.size();
uint32_t empties = 0;
uint32_t good = 0;
uint32_t collisions = 0;
uint64_t total = 0;
for (i=0; i<indexes_size; ++i)
uint32_t byte_size = sizeof(HashHeader); // Header
uint32_t data_offset = 0;
uint32_t num_bucket_entries;
uint32_t bucket_data_size;
// Now for each bucket we write the offset to the data for each bucket
// The offset is currently a zero based offset from the end of this table
// which is header.num_buckets * sizeof(uint32_t) long.
for (i=0; i<num_buckets; ++i)
{
uint32_t c = indexes[i];
total += c;
if (c == 0)
++empties;
else if (c == 1)
++good;
byte_size += sizeof(HashBucketInfo);
HashBucketEntryMap &bucket_entry = hash_buckets[i];
bucket_data_size = 0;
HashBucketEntryMap::const_iterator pos, end = bucket_entry.end();
for (pos = bucket_entry.begin(); pos != end; ++pos)
{
bucket_data_size += sizeof(pos->first) + pos->second.GetByteSize();
}
if (bucket_data_size > 0)
{
// Offset to bucket data
// hash_file_data.PutHex32 (data_offset);
s->Printf("bucket[%u] {0x%8.8x}\n", i, data_offset);
data_offset += bucket_data_size;
}
else
++collisions;
{
// Invalid offset that indicates an empty bucket
// hash_file_data.PutHex32 (UINT32_MAX);
s->Printf("bucket[%u] {0xFFFFFFFF}\n", i);
++bucket_entry_empties;
}
}
s->Printf ("good = %u\n", good);
s->Printf ("empties = %u\n", empties);
s->Printf ("collisions = %u\n", collisions);
s->Printf ("avg count = %llu\n", total / indexes_size);
// Now we write the bucket data for each bucket that corresponds to each bucket
// offset from above.
data_offset = 0;
uint32_t total_num_name_entries = 0;
uint32_t total_num_bucket_entries = 0;
uint32_t total_non_empty_buckets = 0;
for (i=0; i<num_buckets; ++i)
{
HashBucketEntryMap &bucket_entry = hash_buckets[i];
bucket_data_size = 0;
if (bucket_entry.empty())
continue;
++total_non_empty_buckets;
s->Printf("0x%8.8x: BucketEntry:\n", data_offset, num_bucket_entries);
bucket_data_size = 0;
uint32_t num_bucket_entries = 0;
HashBucketEntryMap::const_iterator pos, end = bucket_entry.end();
for (pos = bucket_entry.begin(); pos != end; ++pos)
{
++num_bucket_entries;
uint32_t hash_data_len = pos->second.GetByteSize();
s->Printf(" hash = 0x%8.8x, length = 0x%8.8x:\n", pos->first, hash_data_len);
// hash_file_data.PutHex32 (pos->first); // Write the hash
// hash_file_data.PutHex32 (hash_data_len); // The length of the data for this hash not including the length itself
const HashBucketEntryCStr &hash_entry = pos->second;
uint32_t num_name_entries = 0;
NameToDIEArrayMap::const_iterator name_pos, name_end = hash_entry.name_to_die.end();
for (name_pos = hash_entry.name_to_die.begin(); name_pos != name_end; ++name_pos)
{
++num_name_entries;
++total_num_name_entries;
s->Printf(" name = %p '%s'\n", name_pos->first, name_pos->first);
// hash_file_data.PutHex32 (pos->first); // Write the hash
// hash_file_data.PutHex32 (hash_data_len); // The length of the data for this hash not including the length itself
const uint32_t num_dies = name_pos->second.size();
s->Printf(" dies[%u] = { ", num_dies);
for (uint32_t j=0; j < num_dies; ++j)
s->Printf("0x%8.8x ", name_pos->second[j]);
s->PutCString("}\n");
}
if (num_name_entries == 1)
++names_entry_single;
else if (num_name_entries > 1)
++names_entry_collisions;
bucket_data_size += sizeof(pos->first) + hash_data_len;
}
data_offset += bucket_data_size;
byte_size += bucket_data_size;
total_num_bucket_entries += num_bucket_entries;
if (num_bucket_entries == 1)
++bucket_entry_single;
else if (num_bucket_entries > 1)
++bucket_entry_collisions;
}
s->Printf ("Trying size of %u buckets, %u items:\n", num_buckets, hash_entries_size);
s->Printf ("buckets: empty = %u (%%%f)\n", bucket_entry_empties, ((float)bucket_entry_empties/(float)num_buckets) * 100.0f);
s->Printf ("buckets: single = %u\n", bucket_entry_single);
s->Printf ("buckets: multiple = %u (avg = %f entries/bucket, avg = %f entries/non-empty bucket)\n",
bucket_entry_collisions,
(float)total_num_bucket_entries / (float)num_buckets,
(float)total_num_bucket_entries / (float)total_non_empty_buckets);
s->Printf ("names : single = %u of %u\n", names_entry_single, total_num_name_entries);
s->Printf ("names : multiple = %u of %u\n", names_entry_collisions, total_num_name_entries);
s->Printf ("total byte size = %u\n", byte_size);
s->PutCString ("\n----------------------------------------------------------------------\n\n");
}
}

View File

@ -14,6 +14,8 @@
#include <vector>
#include "lldb/lldb-defines.h"
class SymbolFileDWARF;
class NameToDIE
{
public:
@ -52,7 +54,7 @@ public:
std::vector<Info> &info_array) const;
void
Hash (lldb_private::Stream *s);
Hash (lldb_private::Stream *s, SymbolFileDWARF *dwarf);
protected:
typedef std::multimap<const char *, Info> collection;

View File

@ -168,6 +168,8 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_data_debug_loc(),
m_data_debug_ranges(),
m_data_debug_str(),
m_data_debug_names (),
m_data_debug_types (),
m_abbr(),
m_aranges(),
m_info(),
@ -441,6 +443,18 @@ SymbolFileDWARF::get_debug_str_data()
return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
}
const DataExtractor&
SymbolFileDWARF::get_debug_names_data()
{
return GetCachedSectionData (flagsGotDebugNamesData, eSectionTypeDWARFDebugNames, m_data_debug_names);
}
const DataExtractor&
SymbolFileDWARF::get_debug_types_data()
{
return GetCachedSectionData (flagsGotDebugTypesData, eSectionTypeDWARFDebugTypes, m_data_debug_types);
}
DWARFDebugAbbrev*
SymbolFileDWARF::DebugAbbrev()
@ -1945,8 +1959,7 @@ SymbolFileDWARF::Index ()
#if defined (ENABLE_DEBUG_PRINTF)
StreamFile s(stdout, false);
s.Printf ("DWARF index for (%s) '%s/%s':",
GetObjectFile()->GetModule()->GetArchitecture().AsCString(),
s.Printf ("DWARF index for '%s/%s':",
GetObjectFile()->GetFileSpec().GetDirectory().AsCString(),
GetObjectFile()->GetFileSpec().GetFilename().AsCString());
s.Printf("\nFunction basenames:\n"); m_function_basename_index.Dump (&s);

View File

@ -162,6 +162,8 @@ public:
const lldb_private::DataExtractor& get_debug_loc_data();
const lldb_private::DataExtractor& get_debug_ranges_data();
const lldb_private::DataExtractor& get_debug_str_data();
const lldb_private::DataExtractor& get_debug_names_data();
const lldb_private::DataExtractor& get_debug_types_data();
DWARFDebugAbbrev* DebugAbbrev();
const DWARFDebugAbbrev* DebugAbbrev() const;
@ -229,7 +231,9 @@ protected:
flagsGotDebugPubNamesData = (1 << 7),
flagsGotDebugPubTypesData = (1 << 8),
flagsGotDebugRangesData = (1 << 9),
flagsGotDebugStrData = (1 << 10)
flagsGotDebugStrData = (1 << 10),
flagsGotDebugNamesData = (1 << 11),
flagsGotDebugTypesData = (1 << 12),
};
DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
@ -371,6 +375,8 @@ protected:
lldb_private::DataExtractor m_data_debug_loc;
lldb_private::DataExtractor m_data_debug_ranges;
lldb_private::DataExtractor m_data_debug_str;
lldb_private::DataExtractor m_data_debug_names;
lldb_private::DataExtractor m_data_debug_types;
// The auto_ptr items below are generated on demand if and when someone accesses
// them through a non const version of this class.

View File

@ -146,6 +146,8 @@ ObjectFile::GetAddressClass (lldb::addr_t file_addr)
case eSectionTypeDWARFDebugPubTypes: return eAddressClassDebug;
case eSectionTypeDWARFDebugRanges: return eAddressClassDebug;
case eSectionTypeDWARFDebugStr: return eAddressClassDebug;
case eSectionTypeDWARFDebugNames: return eAddressClassDebug;
case eSectionTypeDWARFDebugTypes: return eAddressClassDebug;
case eSectionTypeEHFrame: return eAddressClassRuntime;
case eSectionTypeOther: return eAddressClassUnknown;
}

View File

@ -258,6 +258,8 @@ lldb_private::GetSectionTypeAsCString (SectionType sect_type)
case eSectionTypeDWARFDebugPubTypes: return "dwarf-pubtypes";
case eSectionTypeDWARFDebugRanges: return "dwarf-ranges";
case eSectionTypeDWARFDebugStr: return "dwarf-str";
case eSectionTypeDWARFDebugNames: return "dwarf-names";
case eSectionTypeDWARFDebugTypes: return "dwarf-types";
case eSectionTypeEHFrame: return "eh-frame";
case eSectionTypeOther: return "regular";
}