diff options
Diffstat (limited to 'lldb')
-rwxr-xr-x | lldb/examples/python/types.py | 212 | ||||
-rw-r--r-- | lldb/include/lldb/API/SBType.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Core/Flags.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Core/ModuleChild.h | 4 | ||||
-rw-r--r-- | lldb/include/lldb/Core/Section.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Core/UserID.h | 7 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/ClangASTType.h | 9 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/Symbol.h | 4 | ||||
-rw-r--r-- | lldb/scripts/Python/interface/SBType.i | 3 | ||||
-rw-r--r-- | lldb/scripts/Python/python-extensions.swig | 4 | ||||
-rw-r--r-- | lldb/source/API/SBType.cpp | 12 | ||||
-rw-r--r-- | lldb/source/Core/Section.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Core/UserID.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTType.cpp | 30 | ||||
-rw-r--r-- | lldb/source/Symbol/Symbol.cpp | 28 |
15 files changed, 293 insertions, 37 deletions
diff --git a/lldb/examples/python/types.py b/lldb/examples/python/types.py new file mode 100755 index 00000000000..83ebbe6e4e1 --- /dev/null +++ b/lldb/examples/python/types.py @@ -0,0 +1,212 @@ +#!/usr/bin/python + +#---------------------------------------------------------------------- +# Be sure to add the python path that points to the LLDB shared library. +# +# # To use this in the embedded python interpreter using "lldb" just +# import it with the full path using the "command script import" +# command +# (lldb) command script import /path/to/cmdtemplate.py +#---------------------------------------------------------------------- + +import commands +import platform +import os +import sys + +try: + # Just try for LLDB in case PYTHONPATH is already correctly setup + import lldb +except ImportError: + lldb_python_dirs = list() + # lldb is not in the PYTHONPATH, try some defaults for the current platform + platform_system = platform.system() + if platform_system == 'Darwin': + # On Darwin, try the currently selected Xcode directory + xcode_dir = commands.getoutput("xcode-select --print-path") + if xcode_dir: + lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python')) + lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') + lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') + success = False + for lldb_python_dir in lldb_python_dirs: + if os.path.exists(lldb_python_dir): + if not (sys.path.__contains__(lldb_python_dir)): + sys.path.append(lldb_python_dir) + try: + import lldb + except ImportError: + pass + else: + print 'imported lldb from: "%s"' % (lldb_python_dir) + success = True + break + if not success: + print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" + sys.exit(1) + +import commands +import optparse +import shlex +import time + +def create_types_options(): + usage = "usage: %prog [options]" + description='''This command will help you verify that types in your program +are packed efficiently by showing all types and their sizes and showing the +padding bytes that waste space. +''' + parser = optparse.OptionParser(description=description, prog='framestats',usage=usage) + parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None) + parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name') + parser.add_option('-m', '--module', action='append', type='string', metavar='MODULE', dest='modules', help='Specify one or more modules which will be used to verify the types.', default=[]) + parser.add_option('-t', '--type', action='append', type='string', metavar='TYPENAME', dest='typenames', help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.', default=[]) + parser.add_option('-d', '--debug', action='store_true', dest='debug', help='Pause 10 seconds to wait for a debugger to attach.', default=False) + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False) + return parser + +def verify_type (target, type): + print type + typename = type.GetName() + # print 'type: %s' % (typename) + (end_offset, padding) = verify_type_recursive (target, type, None, 0, 0, 0) + byte_size = type.GetByteSize() + # if end_offset < byte_size: + # last_member_padding = byte_size - end_offset + # print '%+4u <%u> padding' % (end_offset, last_member_padding) + # padding += last_member_padding + print 'Total byte size: %u' % (byte_size) + print 'Total pad bytes: %u' % (padding) + if padding > 0: + print 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0) + + +def verify_type_recursive (target, type, member_name, depth, base_offset, padding): + prev_end_offset = base_offset + typename = type.GetName() + byte_size = type.GetByteSize() + if member_name and member_name != typename: + print '%+4u <%3u> %s%s %s;' % (base_offset, type.GetByteSize(), ' ' * depth, typename, member_name) + else: + print '%+4u <%3u> %s%s' % (base_offset, type.GetByteSize(), ' ' * depth, typename) + + members = type.members + if members: + for member_idx, member in enumerate(members): + member_type = member.GetType() + member_canonical_type = member_type.GetCanonicalType() + member_type_class = member_canonical_type.GetTypeClass() + member_name = member.GetName() + member_offset = member.GetOffsetInBytes() + member_total_offset = member_offset + base_offset + member_byte_size = member_type.GetByteSize() + is_class_or_struct = False + if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass: + is_class_or_struct = True + if member_idx == 0 and member_offset == target.GetAddressByteSize() and type.IsPolymorphicClass(): + ptr_size = target.GetAddressByteSize() + print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1)) + prev_end_offset = ptr_size + else: + if prev_end_offset < member_total_offset: + member_padding = member_total_offset - prev_end_offset + padding = padding + member_padding + print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, ' ' * (depth + 1)) + + if is_class_or_struct: + (prev_end_offset, padding) = verify_type_recursive (target, member_canonical_type, member_name, depth + 1, member_total_offset, padding) + else: + prev_end_offset = member_total_offset + member_byte_size + if member.IsBitfield(): + print '%+4u <%3u> %s%s:%u %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_type.GetName(), member.GetBitfieldSizeInBits(), member_name) + else: + print '%+4u <%3u> %s%s %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_type.GetName(), member_name) + + if prev_end_offset < byte_size: + last_member_padding = byte_size - prev_end_offset + print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, last_member_padding, ' ' * (depth + 1)) + padding += last_member_padding + else: + if type.IsPolymorphicClass(): + ptr_size = target.GetAddressByteSize() + print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1)) + prev_end_offset = ptr_size + prev_end_offset = base_offset + type.GetByteSize() + + return (prev_end_offset, padding) + +def types_command (debugger, command, result, dict): + # Use the Shell Lexer to properly parse up command options just like a + # shell would + command_args = shlex.split(command) + verify_types(debugger, command_args) + +def verify_types (debugger, command_args): + + parser = create_types_options() + try: + (options, args) = parser.parse_args(command_args) + except: + # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit + # (courtesy of OptParse dealing with argument errors by throwing SystemExit) + result.SetStatus (lldb.eReturnStatusFailed) + return "option parsing failed" # returning a string is the same as returning an error whose description is the string + + if options.debug: + print 'Waiting for debugger to attach...' + for i in range(10): + time.sleep(1) + print '.' + + for path in args: + # in a command - the lldb.* convenience variables are not to be used + # and their values (if any) are undefined + # this is the best practice to access those objects from within a command + error = lldb.SBError() + target = debugger.CreateTarget (path, + options.arch, + options.platform, + True, + error) + if error.Fail(): + print error.GetCString() + continue + + print target + modules = list() + if len(options.modules) == 0: + # Append just the main executable if nothing was specified + module = target.modules[0] + if module: + modules.append(module) + else: + for module_name in options.modules: + module = lldb.target.module[module_name] + if module: + modules.append(module) + + if modules: + for module in modules: + print 'module: %s' % (module.file) + if options.typenames: + for typename in options.typenames: + print typename + types = module.FindTypes(typename) + if types.GetSize(): + for type in types: + verify_type (target, type) + else: + print 'error: no type matches "%s"' % (typename) + else: + types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct) + for type in types: + verify_type (target, type) + else: + print 'error: no modules' + +if __name__ == '__main__': + debugger = lldb.SBDebugger.Create() + verify_types (debugger, sys.argv[1:]) +elif getattr(lldb, 'debugger', None): + lldb.debugger.HandleCommand('command script add -f types.types_command types') + print '"types" command installed, use the "--help" option for detailed help'
\ No newline at end of file diff --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h index 78c8f8d3ab4..e08c1aeeaed 100644 --- a/lldb/include/lldb/API/SBType.h +++ b/lldb/include/lldb/API/SBType.h @@ -93,6 +93,9 @@ public: bool IsFunctionType (); + bool + IsPolymorphicClass (); + lldb::SBType GetPointerType(); diff --git a/lldb/include/lldb/Core/Flags.h b/lldb/include/lldb/Core/Flags.h index e5702e45a6d..233f098ead2 100644 --- a/lldb/include/lldb/Core/Flags.h +++ b/lldb/include/lldb/Core/Flags.h @@ -61,10 +61,7 @@ public: //---------------------------------------------------------------------- /// Destructor. - /// - /// The destructor is virtual in case this class is subclassed. //---------------------------------------------------------------------- - virtual ~Flags () { } diff --git a/lldb/include/lldb/Core/ModuleChild.h b/lldb/include/lldb/Core/ModuleChild.h index d12059d9ba4..d2a6fb0c3bc 100644 --- a/lldb/include/lldb/Core/ModuleChild.h +++ b/lldb/include/lldb/Core/ModuleChild.h @@ -41,11 +41,7 @@ public: //------------------------------------------------------------------ /// Destructor. - /// - /// The destructor is virtual since this class is designed to be - /// inherited from. //------------------------------------------------------------------ - virtual ~ModuleChild(); //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h index 02d40e9b074..a8747aeff73 100644 --- a/lldb/include/lldb/Core/Section.h +++ b/lldb/include/lldb/Core/Section.h @@ -31,7 +31,6 @@ public: SectionList(); - virtual ~SectionList(); size_t @@ -274,9 +273,9 @@ public: protected: + lldb::SectionType m_type; // The type of this section lldb::SectionWP m_parent_wp; // Weak pointer to parent section ConstString m_name; // Name of this section - lldb::SectionType m_type; // The type of this section lldb::addr_t m_file_addr; // The absolute file virtual address range of this section if m_parent == NULL, // offset from parent file virtual address if m_parent != NULL lldb::addr_t m_byte_size; // Size in bytes that this section will occupy in memory at runtime diff --git a/lldb/include/lldb/Core/UserID.h b/lldb/include/lldb/Core/UserID.h index e4ceb8bcf19..ea6af74759b 100644 --- a/lldb/include/lldb/Core/UserID.h +++ b/lldb/include/lldb/Core/UserID.h @@ -39,11 +39,10 @@ struct UserID //------------------------------------------------------------------ /// Destructor. - /// - /// The destructor is virtual in case this class is subclassed. //------------------------------------------------------------------ - virtual - ~UserID (); + ~UserID () + { + } //------------------------------------------------------------------ /// Clears the object state. diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index 019641471c5..63a2e1e6f55 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -152,6 +152,15 @@ public: return GetTypeClass (GetASTContext(), GetOpaqueQualType()); } + bool + IsPolymorphicClass () + { + return IsPolymorphicClass(GetASTContext(), GetOpaqueQualType()); + } + + static bool + IsPolymorphicClass (clang::ASTContext *ast_context, lldb::clang_type_t clang_type); + ClangASTType GetFullyUnqualifiedType (); diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h index 95b5c7269f5..97182700a76 100644 --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -291,7 +291,6 @@ public: protected: uint32_t m_uid; // User ID (usually the original symbol table index) - Mangled m_mangled; // uniqued symbol name/mangled name pair uint16_t m_type_data; // data specific to m_type uint16_t m_type_data_resolved:1, // True if the data in m_type_data has already been calculated m_is_synthetic:1, // non-zero if this symbol is not actually in the symbol table, but synthesized from other info in the object file. @@ -302,8 +301,9 @@ protected: m_calculated_size:1, m_demangled_is_synthesized:1, // The demangled name was created should not be used for expressions or other lookups m_type:8; - uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these + Mangled m_mangled; // uniqued symbol name/mangled name pair AddressRange m_addr_range; // Contains the value, or the section offset address when the value is an address in a section, and the size (if any) + uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these }; } // namespace lldb_private diff --git a/lldb/scripts/Python/interface/SBType.i b/lldb/scripts/Python/interface/SBType.i index c4d40f76091..fbeed3efd66 100644 --- a/lldb/scripts/Python/interface/SBType.i +++ b/lldb/scripts/Python/interface/SBType.i @@ -165,6 +165,9 @@ public: bool IsFunctionType (); + bool + IsPolymorphicClass (); + lldb::SBType GetPointerType(); diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig index a6ca497bdb5..14dc044856e 100644 --- a/lldb/scripts/Python/python-extensions.swig +++ b/lldb/scripts/Python/python-extensions.swig @@ -759,7 +759,7 @@ %pythoncode %{ def command(*args, **kwargs): - from lldb import debugger + import lldb """A decorator function that registers an LLDB command line command that is bound to the function it is attached to.""" class obj(object): @@ -769,7 +769,7 @@ def command(*args, **kwargs): if doc: function.__doc__ = doc command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) - debugger.HandleCommand(command) + lldb.debugger.HandleCommand(command) self.function = function def __call__(self, *args, **kwargs): self.function(*args, **kwargs) diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index d5027d90c52..f6d2fc5568a 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -231,6 +231,18 @@ SBType::IsFunctionType () return false; } +bool +SBType::IsPolymorphicClass () +{ + if (IsValid()) + { + return ClangASTType::IsPolymorphicClass (m_opaque_sp->GetASTContext(), m_opaque_sp->GetOpaqueQualType()); + } + return false; +} + + + lldb::SBType SBType::GetFunctionReturnType () { diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 0d924a34a65..203a6daf5cc 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -27,9 +27,9 @@ Section::Section (const ModuleSP &module_sp, ModuleChild (module_sp), UserID (sect_id), Flags (flags), + m_type (sect_type), m_parent_wp (), m_name (name), - m_type (sect_type), m_file_addr (file_addr), m_byte_size (byte_size), m_file_offset (file_offset), @@ -56,9 +56,9 @@ Section::Section (const lldb::SectionSP &parent_section_sp, ModuleChild (module_sp), UserID (sect_id), Flags (flags), + m_type (sect_type), m_parent_wp (), m_name (name), - m_type (sect_type), m_file_addr (file_addr), m_byte_size (byte_size), m_file_offset (file_offset), diff --git a/lldb/source/Core/UserID.cpp b/lldb/source/Core/UserID.cpp index 57ffce9cfff..f3d6e5b2218 100644 --- a/lldb/source/Core/UserID.cpp +++ b/lldb/source/Core/UserID.cpp @@ -15,10 +15,6 @@ using namespace lldb; using namespace lldb_private; -UserID::~UserID () -{ -} - Stream& lldb_private::operator << (Stream& strm, const UserID& uid) { diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index db8d3146622..c6c5c05838a 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -234,6 +234,36 @@ ClangASTType::GetMinimumLanguage () m_type); } +bool +ClangASTType::IsPolymorphicClass (clang::ASTContext *ast_context, lldb::clang_type_t clang_type) +{ + if (clang_type) + { + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type).getCanonicalType()); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Record: + if (ClangASTContext::GetCompleteType (ast_context, clang_type)) + { + const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) + { + const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) + return cxx_record_decl->isPolymorphic(); + } + } + break; + + default: + break; + } + } + return false; +} + lldb::TypeClass ClangASTType::GetTypeClass (clang::ASTContext *ast_context, lldb::clang_type_t clang_type) { diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index 63551d25e60..905b6cb93bc 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -24,7 +24,6 @@ using namespace lldb_private; Symbol::Symbol() : SymbolContextScope (), m_uid (UINT32_MAX), - m_mangled (), m_type_data (0), m_type_data_resolved (false), m_is_synthetic (false), @@ -35,8 +34,9 @@ Symbol::Symbol() : m_calculated_size (false), m_demangled_is_synthesized (false), m_type (eSymbolTypeInvalid), - m_flags (), - m_addr_range () + m_mangled (), + m_addr_range (), + m_flags () { } @@ -58,7 +58,6 @@ Symbol::Symbol ) : SymbolContextScope (), m_uid (symID), - m_mangled (ConstString(name), name_is_mangled), m_type_data (0), m_type_data_resolved (false), m_is_synthetic (is_artificial), @@ -69,8 +68,9 @@ Symbol::Symbol m_calculated_size (size_is_valid || size > 0), m_demangled_is_synthesized (false), m_type (type), - m_flags (flags), - m_addr_range (section_sp, offset, size) + m_mangled (ConstString(name), name_is_mangled), + m_addr_range (section_sp, offset, size), + m_flags (flags) { } @@ -90,7 +90,6 @@ Symbol::Symbol ) : SymbolContextScope (), m_uid (symID), - m_mangled (ConstString(name), name_is_mangled), m_type_data (0), m_type_data_resolved (false), m_is_synthetic (is_artificial), @@ -101,15 +100,15 @@ Symbol::Symbol m_calculated_size (size_is_valid || range.GetByteSize() > 0), m_demangled_is_synthesized (false), m_type (type), - m_flags (flags), - m_addr_range (range) + m_mangled (ConstString(name), name_is_mangled), + m_addr_range (range), + m_flags (flags) { } Symbol::Symbol(const Symbol& rhs): SymbolContextScope (rhs), m_uid (rhs.m_uid), - m_mangled (rhs.m_mangled), m_type_data (rhs.m_type_data), m_type_data_resolved (rhs.m_type_data_resolved), m_is_synthetic (rhs.m_is_synthetic), @@ -120,8 +119,9 @@ Symbol::Symbol(const Symbol& rhs): m_calculated_size (rhs.m_calculated_size), m_demangled_is_synthesized (rhs.m_demangled_is_synthesized), m_type (rhs.m_type), - m_flags (rhs.m_flags), - m_addr_range (rhs.m_addr_range) + m_mangled (rhs.m_mangled), + m_addr_range (rhs.m_addr_range), + m_flags (rhs.m_flags) { } @@ -132,7 +132,6 @@ Symbol::operator= (const Symbol& rhs) { SymbolContextScope::operator= (rhs); m_uid = rhs.m_uid; - m_mangled = rhs.m_mangled; m_type_data = rhs.m_type_data; m_type_data_resolved = rhs.m_type_data_resolved; m_is_synthetic = rhs.m_is_synthetic; @@ -143,8 +142,9 @@ Symbol::operator= (const Symbol& rhs) m_calculated_size = rhs.m_calculated_size; m_demangled_is_synthesized = rhs.m_demangled_is_synthesized; m_type = rhs.m_type; - m_flags = rhs.m_flags; + m_mangled = rhs.m_mangled; m_addr_range = rhs.m_addr_range; + m_flags = rhs.m_flags; } return *this; } |