diff options
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 1287 |
1 files changed, 648 insertions, 639 deletions
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 179a455b867..ff66ba93faf 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1538,9 +1538,6 @@ ObjectFileMachO::ParseSymtab () if (section_list == NULL) return 0; - ProcessSP process_sp (m_process_wp.lock()); - Process *process = process_sp.get(); - const uint32_t addr_byte_size = m_data.GetAddressByteSize(); const ByteOrder byte_order = m_data.GetByteOrder(); bool bit_width_32 = addr_byte_size == 4; @@ -1554,9 +1551,16 @@ ObjectFileMachO::ParseSymtab () const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size; const addr_t strtab_data_byte_size = symtab_load_command.strsize; addr_t strtab_addr = LLDB_INVALID_ADDRESS; + + ProcessSP process_sp (m_process_wp.lock()); + Process *process = process_sp.get(); + if (process) { Target &target = process->GetTarget(); + + const uint32_t memory_module_load_level = target.GetMemoryModuleLoadLevel(); + SectionSP linkedit_section_sp(section_list->FindSectionByName(GetSegmentNameLINKEDIT())); // Reading mach file from memory in a process or core file... @@ -1616,25 +1620,34 @@ ObjectFileMachO::ParseSymtab () if (!data_was_read) { - DataBufferSP nlist_data_sp (ReadMemory (process_sp, symoff_addr, nlist_data_byte_size)); - if (nlist_data_sp) - nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize()); - //DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr, strtab_data_byte_size)); - //if (strtab_data_sp) - // strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); - if (m_dysymtab.nindirectsyms != 0) + if (memory_module_load_level == eMemoryModuleLoadLevelComplete) { - const addr_t indirect_syms_addr = linkedit_load_addr + m_dysymtab.indirectsymoff - linkedit_file_offset; - DataBufferSP indirect_syms_data_sp (ReadMemory (process_sp, indirect_syms_addr, m_dysymtab.nindirectsyms * 4)); - if (indirect_syms_data_sp) - indirect_symbol_index_data.SetData (indirect_syms_data_sp, 0, indirect_syms_data_sp->GetByteSize()); + DataBufferSP nlist_data_sp (ReadMemory (process_sp, symoff_addr, nlist_data_byte_size)); + if (nlist_data_sp) + nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize()); + // Load strings individually from memory when loading from memory since shared cache + // string tables contain strings for all symbols from all shared cached libraries + //DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr, strtab_data_byte_size)); + //if (strtab_data_sp) + // strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); + if (m_dysymtab.nindirectsyms != 0) + { + const addr_t indirect_syms_addr = linkedit_load_addr + m_dysymtab.indirectsymoff - linkedit_file_offset; + DataBufferSP indirect_syms_data_sp (ReadMemory (process_sp, indirect_syms_addr, m_dysymtab.nindirectsyms * 4)); + if (indirect_syms_data_sp) + indirect_symbol_index_data.SetData (indirect_syms_data_sp, 0, indirect_syms_data_sp->GetByteSize()); + } } - if (function_starts_load_command.cmd) + + if (memory_module_load_level >= eMemoryModuleLoadLevelPartial) { - const addr_t func_start_addr = linkedit_load_addr + function_starts_load_command.dataoff - linkedit_file_offset; - DataBufferSP func_start_data_sp (ReadMemory (process_sp, func_start_addr, function_starts_load_command.datasize)); - if (func_start_data_sp) - function_starts_data.SetData (func_start_data_sp, 0, func_start_data_sp->GetByteSize()); + if (function_starts_load_command.cmd) + { + const addr_t func_start_addr = linkedit_load_addr + function_starts_load_command.dataoff - linkedit_file_offset; + DataBufferSP func_start_data_sp (ReadMemory (process_sp, func_start_addr, function_starts_load_command.datasize)); + if (func_start_data_sp) + function_starts_data.SetData (func_start_data_sp, 0, func_start_data_sp->GetByteSize()); + } } } } @@ -1661,14 +1674,6 @@ ObjectFileMachO::ParseSymtab () } } - if (nlist_data.GetByteSize() == 0) - { - if (log) - module_sp->LogMessage(log, "failed to read nlist data"); - return 0; - } - - const bool have_strtab_data = strtab_data.GetByteSize() > 0; if (!have_strtab_data) { @@ -2701,761 +2706,765 @@ ObjectFileMachO::ParseSymtab () // Must reset this in case it was mutated above! nlist_data_offset = 0; #endif - - // If the sym array was not created while parsing the DSC unmapped - // symbols, create it now. - if (sym == NULL) - { - sym = symtab->Resize (symtab_load_command.nsyms + m_dysymtab.nindirectsyms); - num_syms = symtab->GetNumSymbols(); - } - - if (unmapped_local_symbols_found) - { - assert(m_dysymtab.ilocalsym == 0); - nlist_data_offset += (m_dysymtab.nlocalsym * nlist_byte_size); - nlist_idx = m_dysymtab.nlocalsym; - } - else - { - nlist_idx = 0; - } - - for (; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) + + if (nlist_data.GetByteSize() > 0) { - struct nlist_64 nlist; - if (!nlist_data.ValidOffsetForDataOfSize(nlist_data_offset, nlist_byte_size)) - break; - - nlist.n_strx = nlist_data.GetU32_unchecked(&nlist_data_offset); - nlist.n_type = nlist_data.GetU8_unchecked (&nlist_data_offset); - nlist.n_sect = nlist_data.GetU8_unchecked (&nlist_data_offset); - nlist.n_desc = nlist_data.GetU16_unchecked (&nlist_data_offset); - nlist.n_value = nlist_data.GetAddress_unchecked (&nlist_data_offset); - SymbolType type = eSymbolTypeInvalid; - const char *symbol_name = NULL; - - if (have_strtab_data) + // If the sym array was not created while parsing the DSC unmapped + // symbols, create it now. + if (sym == NULL) { - symbol_name = strtab_data.PeekCStr(nlist.n_strx); + sym = symtab->Resize (symtab_load_command.nsyms + m_dysymtab.nindirectsyms); + num_syms = symtab->GetNumSymbols(); + } - if (symbol_name == NULL) - { - // No symbol should be NULL, even the symbols with no - // string values should have an offset zero which points - // to an empty C-string - Host::SystemLog (Host::eSystemLogError, - "error: symbol[%u] has invalid string table offset 0x%x in %s, ignoring symbol\n", - nlist_idx, - nlist.n_strx, - module_sp->GetFileSpec().GetPath().c_str()); - continue; - } - if (symbol_name[0] == '\0') - symbol_name = NULL; + if (unmapped_local_symbols_found) + { + assert(m_dysymtab.ilocalsym == 0); + nlist_data_offset += (m_dysymtab.nlocalsym * nlist_byte_size); + nlist_idx = m_dysymtab.nlocalsym; } else { - const addr_t str_addr = strtab_addr + nlist.n_strx; - Error str_error; - if (process->ReadCStringFromMemory(str_addr, memory_symbol_name, str_error)) - symbol_name = memory_symbol_name.c_str(); + nlist_idx = 0; } - const char *symbol_name_non_abi_mangled = NULL; - SectionSP symbol_section; - lldb::addr_t symbol_byte_size = 0; - bool add_nlist = true; - bool is_gsym = false; - bool is_debug = ((nlist.n_type & NlistMaskStab) != 0); - bool demangled_is_synthesized = false; + for (; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) + { + struct nlist_64 nlist; + if (!nlist_data.ValidOffsetForDataOfSize(nlist_data_offset, nlist_byte_size)) + break; - assert (sym_idx < num_syms); + nlist.n_strx = nlist_data.GetU32_unchecked(&nlist_data_offset); + nlist.n_type = nlist_data.GetU8_unchecked (&nlist_data_offset); + nlist.n_sect = nlist_data.GetU8_unchecked (&nlist_data_offset); + nlist.n_desc = nlist_data.GetU16_unchecked (&nlist_data_offset); + nlist.n_value = nlist_data.GetAddress_unchecked (&nlist_data_offset); - sym[sym_idx].SetDebug (is_debug); + SymbolType type = eSymbolTypeInvalid; + const char *symbol_name = NULL; - if (is_debug) - { - switch (nlist.n_type) + if (have_strtab_data) { - case StabGlobalSymbol: - // N_GSYM -- global symbol: name,,NO_SECT,type,0 - // Sometimes the N_GSYM value contains the address. - - // FIXME: In the .o files, we have a GSYM and a debug symbol for all the ObjC data. They - // have the same address, but we want to ensure that we always find only the real symbol, - // 'cause we don't currently correctly attribute the GSYM one to the ObjCClass/Ivar/MetaClass - // symbol type. This is a temporary hack to make sure the ObjectiveC symbols get treated - // correctly. To do this right, we should coalesce all the GSYM & global symbols that have the - // same address. - - if (symbol_name && symbol_name[0] == '_' && symbol_name[1] == 'O' - && (strncmp (symbol_name, "_OBJC_IVAR_$_", strlen ("_OBJC_IVAR_$_")) == 0 - || strncmp (symbol_name, "_OBJC_CLASS_$_", strlen ("_OBJC_CLASS_$_")) == 0 - || strncmp (symbol_name, "_OBJC_METACLASS_$_", strlen ("_OBJC_METACLASS_$_")) == 0)) - add_nlist = false; - else + symbol_name = strtab_data.PeekCStr(nlist.n_strx); + + if (symbol_name == NULL) { - is_gsym = true; - sym[sym_idx].SetExternal(true); - if (nlist.n_value != 0) - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - type = eSymbolTypeData; + // No symbol should be NULL, even the symbols with no + // string values should have an offset zero which points + // to an empty C-string + Host::SystemLog (Host::eSystemLogError, + "error: symbol[%u] has invalid string table offset 0x%x in %s, ignoring symbol\n", + nlist_idx, + nlist.n_strx, + module_sp->GetFileSpec().GetPath().c_str()); + continue; } - break; + if (symbol_name[0] == '\0') + symbol_name = NULL; + } + else + { + const addr_t str_addr = strtab_addr + nlist.n_strx; + Error str_error; + if (process->ReadCStringFromMemory(str_addr, memory_symbol_name, str_error)) + symbol_name = memory_symbol_name.c_str(); + } + const char *symbol_name_non_abi_mangled = NULL; - case StabFunctionName: - // N_FNAME -- procedure name (f77 kludge): name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; + SectionSP symbol_section; + lldb::addr_t symbol_byte_size = 0; + bool add_nlist = true; + bool is_gsym = false; + bool is_debug = ((nlist.n_type & NlistMaskStab) != 0); + bool demangled_is_synthesized = false; - case StabFunction: - // N_FUN -- procedure: name,,n_sect,linenumber,address - if (symbol_name) - { - type = eSymbolTypeCode; - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + assert (sym_idx < num_syms); - N_FUN_addr_to_sym_idx[nlist.n_value] = sym_idx; - // We use the current number of symbols in the symbol table in lieu of - // using nlist_idx in case we ever start trimming entries out - N_FUN_indexes.push_back(sym_idx); - } - else + sym[sym_idx].SetDebug (is_debug); + + if (is_debug) + { + switch (nlist.n_type) { + case StabGlobalSymbol: + // N_GSYM -- global symbol: name,,NO_SECT,type,0 + // Sometimes the N_GSYM value contains the address. + + // FIXME: In the .o files, we have a GSYM and a debug symbol for all the ObjC data. They + // have the same address, but we want to ensure that we always find only the real symbol, + // 'cause we don't currently correctly attribute the GSYM one to the ObjCClass/Ivar/MetaClass + // symbol type. This is a temporary hack to make sure the ObjectiveC symbols get treated + // correctly. To do this right, we should coalesce all the GSYM & global symbols that have the + // same address. + + if (symbol_name && symbol_name[0] == '_' && symbol_name[1] == 'O' + && (strncmp (symbol_name, "_OBJC_IVAR_$_", strlen ("_OBJC_IVAR_$_")) == 0 + || strncmp (symbol_name, "_OBJC_CLASS_$_", strlen ("_OBJC_CLASS_$_")) == 0 + || strncmp (symbol_name, "_OBJC_METACLASS_$_", strlen ("_OBJC_METACLASS_$_")) == 0)) + add_nlist = false; + else + { + is_gsym = true; + sym[sym_idx].SetExternal(true); + if (nlist.n_value != 0) + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + type = eSymbolTypeData; + } + break; + + case StabFunctionName: + // N_FNAME -- procedure name (f77 kludge): name,,NO_SECT,0,0 type = eSymbolTypeCompiler; + break; - if ( !N_FUN_indexes.empty() ) + case StabFunction: + // N_FUN -- procedure: name,,n_sect,linenumber,address + if (symbol_name) { - // Copy the size of the function into the original STAB entry so we don't have - // to hunt for it later - symtab->SymbolAtIndex(N_FUN_indexes.back())->SetByteSize(nlist.n_value); - N_FUN_indexes.pop_back(); - // We don't really need the end function STAB as it contains the size which - // we already placed with the original symbol, so don't add it if we want a - // minimal symbol table - add_nlist = false; + type = eSymbolTypeCode; + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + + N_FUN_addr_to_sym_idx[nlist.n_value] = sym_idx; + // We use the current number of symbols in the symbol table in lieu of + // using nlist_idx in case we ever start trimming entries out + N_FUN_indexes.push_back(sym_idx); } - } - break; + else + { + type = eSymbolTypeCompiler; - case StabStaticSymbol: - // N_STSYM -- static symbol: name,,n_sect,type,address - N_STSYM_addr_to_sym_idx[nlist.n_value] = sym_idx; - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - type = eSymbolTypeData; - break; + if ( !N_FUN_indexes.empty() ) + { + // Copy the size of the function into the original STAB entry so we don't have + // to hunt for it later + symtab->SymbolAtIndex(N_FUN_indexes.back())->SetByteSize(nlist.n_value); + N_FUN_indexes.pop_back(); + // We don't really need the end function STAB as it contains the size which + // we already placed with the original symbol, so don't add it if we want a + // minimal symbol table + add_nlist = false; + } + } + break; - case StabLocalCommon: - // N_LCSYM -- .lcomm symbol: name,,n_sect,type,address - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - type = eSymbolTypeCommonBlock; - break; + case StabStaticSymbol: + // N_STSYM -- static symbol: name,,n_sect,type,address + N_STSYM_addr_to_sym_idx[nlist.n_value] = sym_idx; + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + type = eSymbolTypeData; + break; - case StabBeginSymbol: - // N_BNSYM - // We use the current number of symbols in the symbol table in lieu of - // using nlist_idx in case we ever start trimming entries out - // Skip these if we want minimal symbol tables - add_nlist = false; - break; + case StabLocalCommon: + // N_LCSYM -- .lcomm symbol: name,,n_sect,type,address + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + type = eSymbolTypeCommonBlock; + break; - case StabEndSymbol: - // N_ENSYM - // Set the size of the N_BNSYM to the terminating index of this N_ENSYM - // so that we can always skip the entire symbol if we need to navigate - // more quickly at the source level when parsing STABS - // Skip these if we want minimal symbol tables - add_nlist = false; - break; + case StabBeginSymbol: + // N_BNSYM + // We use the current number of symbols in the symbol table in lieu of + // using nlist_idx in case we ever start trimming entries out + // Skip these if we want minimal symbol tables + add_nlist = false; + break; + case StabEndSymbol: + // N_ENSYM + // Set the size of the N_BNSYM to the terminating index of this N_ENSYM + // so that we can always skip the entire symbol if we need to navigate + // more quickly at the source level when parsing STABS + // Skip these if we want minimal symbol tables + add_nlist = false; + break; - case StabSourceFileOptions: - // N_OPT - emitted with gcc2_compiled and in gcc source - type = eSymbolTypeCompiler; - break; - case StabRegisterSymbol: - // N_RSYM - register sym: name,,NO_SECT,type,register - type = eSymbolTypeVariable; - break; + case StabSourceFileOptions: + // N_OPT - emitted with gcc2_compiled and in gcc source + type = eSymbolTypeCompiler; + break; - case StabSourceLine: - // N_SLINE - src line: 0,,n_sect,linenumber,address - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; + case StabRegisterSymbol: + // N_RSYM - register sym: name,,NO_SECT,type,register + type = eSymbolTypeVariable; + break; - case StabStructureType: - // N_SSYM - structure elt: name,,NO_SECT,type,struct_offset - type = eSymbolTypeVariableType; - break; + case StabSourceLine: + // N_SLINE - src line: 0,,n_sect,linenumber,address + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + type = eSymbolTypeLineEntry; + break; - case StabSourceFileName: - // N_SO - source file name - type = eSymbolTypeSourceFile; - if (symbol_name == NULL) - { - add_nlist = false; - if (N_SO_index != UINT32_MAX) - { - // Set the size of the N_SO to the terminating index of this N_SO - // so that we can always skip the entire N_SO if we need to navigate - // more quickly at the source level when parsing STABS - symbol_ptr = symtab->SymbolAtIndex(N_SO_index); - symbol_ptr->SetByteSize(sym_idx); - symbol_ptr->SetSizeIsSibling(true); - } - N_NSYM_indexes.clear(); - N_INCL_indexes.clear(); - N_BRAC_indexes.clear(); - N_COMM_indexes.clear(); - N_FUN_indexes.clear(); - N_SO_index = UINT32_MAX; - } - else - { - // We use the current number of symbols in the symbol table in lieu of - // using nlist_idx in case we ever start trimming entries out - const bool N_SO_has_full_path = symbol_name[0] == '/'; - if (N_SO_has_full_path) + case StabStructureType: + // N_SSYM - structure elt: name,,NO_SECT,type,struct_offset + type = eSymbolTypeVariableType; + break; + + case StabSourceFileName: + // N_SO - source file name + type = eSymbolTypeSourceFile; + if (symbol_name == NULL) { - if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) - { - // We have two consecutive N_SO entries where the first contains a directory - // and the second contains a full path. - sym[sym_idx - 1].GetMangled().SetValue(ConstString(symbol_name), false); - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; - add_nlist = false; - } - else + add_nlist = false; + if (N_SO_index != UINT32_MAX) { - // This is the first entry in a N_SO that contains a directory or - // a full path to the source file - N_SO_index = sym_idx; + // Set the size of the N_SO to the terminating index of this N_SO + // so that we can always skip the entire N_SO if we need to navigate + // more quickly at the source level when parsing STABS + symbol_ptr = symtab->SymbolAtIndex(N_SO_index); + symbol_ptr->SetByteSize(sym_idx); + symbol_ptr->SetSizeIsSibling(true); } + N_NSYM_indexes.clear(); + N_INCL_indexes.clear(); + N_BRAC_indexes.clear(); + N_COMM_indexes.clear(); + N_FUN_indexes.clear(); + N_SO_index = UINT32_MAX; } - else if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) + else { - // This is usually the second N_SO entry that contains just the filename, - // so here we combine it with the first one if we are minimizing the symbol table - const char *so_path = sym[sym_idx - 1].GetMangled().GetDemangledName().AsCString(); - if (so_path && so_path[0]) + // We use the current number of symbols in the symbol table in lieu of + // using nlist_idx in case we ever start trimming entries out + const bool N_SO_has_full_path = symbol_name[0] == '/'; + if (N_SO_has_full_path) { - std::string full_so_path (so_path); - const size_t double_slash_pos = full_so_path.find("//"); - if (double_slash_pos != std::string::npos) + if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) + { + // We have two consecutive N_SO entries where the first contains a directory + // and the second contains a full path. + sym[sym_idx - 1].GetMangled().SetValue(ConstString(symbol_name), false); + m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; + add_nlist = false; + } + else { - // The linker has been generating bad N_SO entries with doubled up paths - // in the format "%s%s" where the first stirng in the DW_AT_comp_dir, - // and the second is the directory for the source file so you end up with - // a path that looks like "/tmp/src//tmp/src/" - FileSpec so_dir(so_path, false); - if (!so_dir.Exists()) + // This is the first entry in a N_SO that contains a directory or + // a full path to the source file + N_SO_index = sym_idx; + } + } + else if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) + { + // This is usually the second N_SO entry that contains just the filename, + // so here we combine it with the first one if we are minimizing the symbol table + const char *so_path = sym[sym_idx - 1].GetMangled().GetDemangledName().AsCString(); + if (so_path && so_path[0]) + { + std::string full_so_path (so_path); + const size_t double_slash_pos = full_so_path.find("//"); + if (double_slash_pos != std::string::npos) { - so_dir.SetFile(&full_so_path[double_slash_pos + 1], false); - if (so_dir.Exists()) + // The linker has been generating bad N_SO entries with doubled up paths + // in the format "%s%s" where the first stirng in the DW_AT_comp_dir, + // and the second is the directory for the source file so you end up with + // a path that looks like "/tmp/src//tmp/src/" + FileSpec so_dir(so_path, false); + if (!so_dir.Exists()) { - // Trim off the incorrect path - full_so_path.erase(0, double_slash_pos + 1); + so_dir.SetFile(&full_so_path[double_slash_pos + 1], false); + if (so_dir.Exists()) + { + // Trim off the incorrect path + full_so_path.erase(0, double_slash_pos + 1); + } } } + if (*full_so_path.rbegin() != '/') + full_so_path += '/'; + full_so_path += symbol_name; + sym[sym_idx - 1].GetMangled().SetValue(ConstString(full_so_path.c_str()), false); + add_nlist = false; + m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; } - if (*full_so_path.rbegin() != '/') - full_so_path += '/'; - full_so_path += symbol_name; - sym[sym_idx - 1].GetMangled().SetValue(ConstString(full_so_path.c_str()), false); - add_nlist = false; - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; + } + else + { + // This could be a relative path to a N_SO + N_SO_index = sym_idx; } } - else - { - // This could be a relative path to a N_SO - N_SO_index = sym_idx; - } - } - break; + break; - case StabObjectFileName: - // N_OSO - object file name: name,,0,0,st_mtime - type = eSymbolTypeObjectFile; - break; + case StabObjectFileName: + // N_OSO - object file name: name,,0,0,st_mtime + type = eSymbolTypeObjectFile; + break; - case StabLocalSymbol: - // N_LSYM - local sym: name,,NO_SECT,type,offset - type = eSymbolTypeLocal; - break; + case StabLocalSymbol: + // N_LSYM - local sym: name,,NO_SECT,type,offset + type = eSymbolTypeLocal; + break; - //---------------------------------------------------------------------- - // INCL scopes - //---------------------------------------------------------------------- - case StabBeginIncludeFileName: - // N_BINCL - include file beginning: name,,NO_SECT,0,sum - // We use the current number of symbols in the symbol table in lieu of - // using nlist_idx in case we ever start trimming entries out - N_INCL_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - break; + //---------------------------------------------------------------------- + // INCL scopes + //---------------------------------------------------------------------- + case StabBeginIncludeFileName: + // N_BINCL - include file beginning: name,,NO_SECT,0,sum + // We use the current number of symbols in the symbol table in lieu of + // using nlist_idx in case we ever start trimming entries out + N_INCL_indexes.push_back(sym_idx); + type = eSymbolTypeScopeBegin; + break; - case StabEndIncludeFile: - // N_EINCL - include file end: name,,NO_SECT,0,0 - // Set the size of the N_BINCL to the terminating index of this N_EINCL - // so that we can always skip the entire symbol if we need to navigate - // more quickly at the source level when parsing STABS - if ( !N_INCL_indexes.empty() ) - { - symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_INCL_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; + case StabEndIncludeFile: + // N_EINCL - include file end: name,,NO_SECT,0,0 + // Set the size of the N_BINCL to the terminating index of this N_EINCL + // so that we can always skip the entire symbol if we need to navigate + // more quickly at the source level when parsing STABS + if ( !N_INCL_indexes.empty() ) + { + symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back()); + symbol_ptr->SetByteSize(sym_idx + 1); + symbol_ptr->SetSizeIsSibling(true); + N_INCL_indexes.pop_back(); + } + type = eSymbolTypeScopeEnd; + break; - case StabIncludeFileName: - // N_SOL - #included file name: name,,n_sect,0,address - type = eSymbolTypeHeaderFile; + case StabIncludeFileName: + // N_SOL - #included file name: name,,n_sect,0,address + type = eSymbolTypeHeaderFile; - // We currently don't use the header files on darwin - add_nlist = false; - break; + // We currently don't use the header files on darwin + add_nlist = false; + break; - case StabCompilerParameters: - // N_PARAMS - compiler parameters: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; + case StabCompilerParameters: + // N_PARAMS - compiler parameters: name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - case StabCompilerVersion: - // N_VERSION - compiler version: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; + case StabCompilerVersion: + // N_VERSION - compiler version: name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - case StabCompilerOptLevel: - // N_OLEVEL - compiler -O level: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; + case StabCompilerOptLevel: + // N_OLEVEL - compiler -O level: name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - case StabParameter: - // N_PSYM - parameter: name,,NO_SECT,type,offset - type = eSymbolTypeVariable; - break; + case StabParameter: + // N_PSYM - parameter: name,,NO_SECT,type,offset + type = eSymbolTypeVariable; + break; - case StabAlternateEntry: - // N_ENTRY - alternate entry: name,,n_sect,linenumber,address - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; + case StabAlternateEntry: + // N_ENTRY - alternate entry: name,,n_sect,linenumber,address + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + type = eSymbolTypeLineEntry; + break; - //---------------------------------------------------------------------- - // Left and Right Braces - //---------------------------------------------------------------------- - case StabLeftBracket: - // N_LBRAC - left bracket: 0,,NO_SECT,nesting level,address - // We use the current number of symbols in the symbol table in lieu of - // using nlist_idx in case we ever start trimming entries out - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - N_BRAC_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - break; + //---------------------------------------------------------------------- + // Left and Right Braces + //---------------------------------------------------------------------- + case StabLeftBracket: + // N_LBRAC - left bracket: 0,,NO_SECT,nesting level,address + // We use the current number of symbols in the symbol table in lieu of + // using nlist_idx in case we ever start trimming entries out + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + N_BRAC_indexes.push_back(sym_idx); + type = eSymbolTypeScopeBegin; + break; - case StabRightBracket: - // N_RBRAC - right bracket: 0,,NO_SECT,nesting level,address - // Set the size of the N_LBRAC to the terminating index of this N_RBRAC - // so that we can always skip the entire symbol if we need to navigate - // more quickly at the source level when parsing STABS - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - if ( !N_BRAC_indexes.empty() ) - { - symbol_ptr = symtab->SymbolAtIndex(N_BRAC_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_BRAC_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; + case StabRightBracket: + // N_RBRAC - right bracket: 0,,NO_SECT,nesting level,address + // Set the size of the N_LBRAC to the terminating index of this N_RBRAC + // so that we can always skip the entire symbol if we need to navigate + // more quickly at the source level when parsing STABS + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + if ( !N_BRAC_indexes.empty() ) + { + symbol_ptr = symtab->SymbolAtIndex(N_BRAC_indexes.back()); + symbol_ptr->SetByteSize(sym_idx + 1); + symbol_ptr->SetSizeIsSibling(true); + N_BRAC_indexes.pop_back(); + } + type = eSymbolTypeScopeEnd; + break; - case StabDeletedIncludeFile: - // N_EXCL - deleted include file: name,,NO_SECT,0,sum - type = eSymbolTypeHeaderFile; - break; + case StabDeletedIncludeFile: + // N_EXCL - deleted include file: name,,NO_SECT,0,sum + type = eSymbolTypeHeaderFile; + break; - //---------------------------------------------------------------------- - // COMM scopes - //---------------------------------------------------------------------- - case StabBeginCommon: - // N_BCOMM - begin common: name,,NO_SECT,0,0 - // We use the current number of symbols in the symbol table in lieu of - // using nlist_idx in case we ever start trimming entries out - type = eSymbolTypeScopeBegin; - N_COMM_indexes.push_back(sym_idx); - break; + //---------------------------------------------------------------------- + // COMM scopes + //---------------------------------------------------------------------- + case StabBeginCommon: + // N_BCOMM - begin common: name,,NO_SECT,0,0 + // We use the current number of symbols in the symbol table in lieu of + // using nlist_idx in case we ever start trimming entries out + type = eSymbolTypeScopeBegin; + N_COMM_indexes.push_back(sym_idx); + break; - case StabEndCommonLocal: - // N_ECOML - end common (local name): 0,,n_sect,0,address - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - // Fall through - - case StabEndCommon: - // N_ECOMM - end common: name,,n_sect,0,0 - // Set the size of the N_BCOMM to the terminating index of this N_ECOMM/N_ECOML - // so that we can always skip the entire symbol if we need to navigate - // more quickly at the source level when parsing STABS - if ( !N_COMM_indexes.empty() ) - { - symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_COMM_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; + case StabEndCommonLocal: + // N_ECOML - end common (local name): 0,,n_sect,0,address + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + // Fall through + + case StabEndCommon: + // N_ECOMM - end common: name,,n_sect,0,0 + // Set the size of the N_BCOMM to the terminating index of this N_ECOMM/N_ECOML + // so that we can always skip the entire symbol if we need to navigate + // more quickly at the source level when parsing STABS + if ( !N_COMM_indexes.empty() ) + { + symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back()); + symbol_ptr->SetByteSize(sym_idx + 1); + symbol_ptr->SetSizeIsSibling(true); + N_COMM_indexes.pop_back(); + } + type = eSymbolTypeScopeEnd; + break; - case StabLength: - // N_LENG - second stab entry with length information - type = eSymbolTypeAdditional; - break; + case StabLength: + // N_LENG - second stab entry with length information + type = eSymbolTypeAdditional; + break; - default: break; + default: break; + } } - } - else - { - //uint8_t n_pext = NlistMaskPrivateExternal & nlist.n_type; - uint8_t n_type = NlistMaskType & nlist.n_type; - sym[sym_idx].SetExternal((NlistMaskExternal & nlist.n_type) != 0); - - switch (n_type) + else { - case NListTypeIndirect: // N_INDR - Fall through - case NListTypePreboundUndefined:// N_PBUD - Fall through - case NListTypeUndefined: // N_UNDF - type = eSymbolTypeUndefined; - break; - - case NListTypeAbsolute: // N_ABS - type = eSymbolTypeAbsolute; - break; + //uint8_t n_pext = NlistMaskPrivateExternal & nlist.n_type; + uint8_t n_type = NlistMaskType & nlist.n_type; + sym[sym_idx].SetExternal((NlistMaskExternal & nlist.n_type) != 0); - case NListTypeSection: // N_SECT + switch (n_type) { - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + case NListTypeIndirect: // N_INDR - Fall through + case NListTypePreboundUndefined:// N_PBUD - Fall through + case NListTypeUndefined: // N_UNDF + type = eSymbolTypeUndefined; + break; - if (!symbol_section) - { - // TODO: warn about this? - add_nlist = false; - break; - } + case NListTypeAbsolute: // N_ABS + type = eSymbolTypeAbsolute; + break; - if (TEXT_eh_frame_sectID == nlist.n_sect) - { - type = eSymbolTypeException; - } - else + case NListTypeSection: // N_SECT { - uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType; + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - switch (section_type) + if (!symbol_section) { - case SectionTypeRegular: break; // regular section - //case SectionTypeZeroFill: type = eSymbolTypeData; break; // zero fill on demand section - case SectionTypeCStringLiterals: type = eSymbolTypeData; break; // section with only literal C strings - case SectionType4ByteLiterals: type = eSymbolTypeData; break; // section with only 4 byte literals - case SectionType8ByteLiterals: type = eSymbolTypeData; break; // section with only 8 byte literals - case SectionTypeLiteralPointers: type = eSymbolTypeTrampoline; break; // section with only pointers to literals - case SectionTypeNonLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers - case SectionTypeLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers - case SectionTypeSymbolStubs: type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field - case SectionTypeModuleInitFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for initialization - case SectionTypeModuleTermFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for termination - //case SectionTypeCoalesced: type = eSymbolType; break; // section contains symbols that are to be coalesced - //case SectionTypeZeroFillLarge: type = eSymbolTypeData; break; // zero fill on demand section (that can be larger than 4 gigabytes) - case SectionTypeInterposing: type = eSymbolTypeTrampoline; break; // section with only pairs of function pointers for interposing - case SectionType16ByteLiterals: type = eSymbolTypeData; break; // section with only 16 byte literals - case SectionTypeDTraceObjectFormat: type = eSymbolTypeInstrumentation; break; - case SectionTypeLazyDylibSymbolPointers: type = eSymbolTypeTrampoline; break; - default: break; + // TODO: warn about this? + add_nlist = false; + break; } - if (type == eSymbolTypeInvalid) + if (TEXT_eh_frame_sectID == nlist.n_sect) + { + type = eSymbolTypeException; + } + else { - const char *symbol_sect_name = symbol_section->GetName().AsCString(); - if (symbol_section->IsDescendant (text_section_sp.get())) + uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType; + + switch (section_type) { - if (symbol_section->IsClear(SectionAttrUserPureInstructions | - SectionAttrUserSelfModifyingCode | - SectionAttrSytemSomeInstructions)) - type = eSymbolTypeData; - else - type = eSymbolTypeCode; + case SectionTypeRegular: break; // regular section + //case SectionTypeZeroFill: type = eSymbolTypeData; break; // zero fill on demand section + case SectionTypeCStringLiterals: type = eSymbolTypeData; break; // section with only literal C strings + case SectionType4ByteLiterals: type = eSymbolTypeData; break; // section with only 4 byte literals + case SectionType8ByteLiterals: type = eSymbolTypeData; break; // section with only 8 byte literals + case SectionTypeLiteralPointers: type = eSymbolTypeTrampoline; break; // section with only pointers to literals + case SectionTypeNonLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers + case SectionTypeLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers + case SectionTypeSymbolStubs: type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field + case SectionTypeModuleInitFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for initialization + case SectionTypeModuleTermFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for termination + //case SectionTypeCoalesced: type = eSymbolType; break; // section contains symbols that are to be coalesced + //case SectionTypeZeroFillLarge: type = eSymbolTypeData; break; // zero fill on demand section (that can be larger than 4 gigabytes) + case SectionTypeInterposing: type = eSymbolTypeTrampoline; break; // section with only pairs of function pointers for interposing + case SectionType16ByteLiterals: type = eSymbolTypeData; break; // section with only 16 byte literals + case SectionTypeDTraceObjectFormat: type = eSymbolTypeInstrumentation; break; + case SectionTypeLazyDylibSymbolPointers: type = eSymbolTypeTrampoline; break; + default: break; } - else - if (symbol_section->IsDescendant(data_section_sp.get())) + + if (type == eSymbolTypeInvalid) { - if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name) + const char *symbol_sect_name = symbol_section->GetName().AsCString(); + if (symbol_section->IsDescendant (text_section_sp.get())) { - type = eSymbolTypeRuntime; - - if (symbol_name && - symbol_name[0] == '_' && - symbol_name[1] == 'O' && - symbol_name[2] == 'B') + if (symbol_section->IsClear(SectionAttrUserPureInstructions | + SectionAttrUserSelfModifyingCode | + SectionAttrSytemSomeInstructions)) + type = eSymbolTypeData; + else + type = eSymbolTypeCode; + } + else + if (symbol_section->IsDescendant(data_section_sp.get())) + { + if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name) { - llvm::StringRef symbol_name_ref(symbol_name); - static const llvm::StringRef g_objc_v2_prefix_class ("_OBJC_CLASS_$_"); - static const llvm::StringRef g_objc_v2_prefix_metaclass ("_OBJC_METACLASS_$_"); - static const llvm::StringRef g_objc_v2_prefix_ivar ("_OBJC_IVAR_$_"); - if (symbol_name_ref.startswith(g_objc_v2_prefix_class)) - { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + g_objc_v2_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - } - else if (symbol_name_ref.startswith(g_objc_v2_prefix_metaclass)) - { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size(); - type = eSymbolTypeObjCMetaClass; - demangled_is_synthesized = true; - } - else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar)) + type = eSymbolTypeRuntime; + + if (symbol_name && + symbol_name[0] == '_' && + symbol_name[1] == 'O' && + symbol_name[2] == 'B') { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + g_objc_v2_prefix_ivar.size(); - type = eSymbolTypeObjCIVar; - demangled_is_synthesized = true; + llvm::StringRef symbol_name_ref(symbol_name); + static const llvm::StringRef g_objc_v2_prefix_class ("_OBJC_CLASS_$_"); + static const llvm::StringRef g_objc_v2_prefix_metaclass ("_OBJC_METACLASS_$_"); + static const llvm::StringRef g_objc_v2_prefix_ivar ("_OBJC_IVAR_$_"); + if (symbol_name_ref.startswith(g_objc_v2_prefix_class)) + { + symbol_name_non_abi_mangled = symbol_name + 1; + symbol_name = symbol_name + g_objc_v2_prefix_class.size(); + type = eSymbolTypeObjCClass; + demangled_is_synthesized = true; + } + else if (symbol_name_ref.startswith(g_objc_v2_prefix_metaclass)) + { + symbol_name_non_abi_mangled = symbol_name + 1; + symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size(); + type = eSymbolTypeObjCMetaClass; + demangled_is_synthesized = true; + } + else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar)) + { + symbol_name_non_abi_mangled = symbol_name + 1; + symbol_name = symbol_name + g_objc_v2_prefix_ivar.size(); + type = eSymbolTypeObjCIVar; + demangled_is_synthesized = true; + } } } + else + if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name) + { + type = eSymbolTypeException; + } + else + { + type = eSymbolTypeData; + } } else - if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name) + if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name) { - type = eSymbolTypeException; + type = eSymbolTypeTrampoline; } else + if (symbol_section->IsDescendant(objc_section_sp.get())) { - type = eSymbolTypeData; - } - } - else - if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name) - { - type = eSymbolTypeTrampoline; - } - else - if (symbol_section->IsDescendant(objc_section_sp.get())) - { - type = eSymbolTypeRuntime; - if (symbol_name && symbol_name[0] == '.') - { - llvm::StringRef symbol_name_ref(symbol_name); - static const llvm::StringRef g_objc_v1_prefix_class (".objc_class_name_"); - if (symbol_name_ref.startswith(g_objc_v1_prefix_class)) + type = eSymbolTypeRuntime; + if (symbol_name && symbol_name[0] == '.') { - symbol_name_non_abi_mangled = symbol_name; - symbol_name = symbol_name + g_objc_v1_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; + llvm::StringRef symbol_name_ref(symbol_name); + static const llvm::StringRef g_objc_v1_prefix_class (".objc_class_name_"); + if (symbol_name_ref.startswith(g_objc_v1_prefix_class)) + { + symbol_name_non_abi_mangled = symbol_name; + symbol_name = symbol_name + g_objc_v1_prefix_class.size(); + type = eSymbolTypeObjCClass; + demangled_is_synthesized = true; + } } } } } } + break; } - break; } - } - if (add_nlist) - { - uint64_t symbol_value = nlist.n_value; - - if (symbol_name_non_abi_mangled) - { - sym[sym_idx].GetMangled().SetMangledName (ConstString(symbol_name_non_abi_mangled)); - sym[sym_idx].GetMangled().SetDemangledName (ConstString(symbol_name)); - } - else + if (add_nlist) { - bool symbol_name_is_mangled = false; + uint64_t symbol_value = nlist.n_value; - if (symbol_name && symbol_name[0] == '_') + if (symbol_name_non_abi_mangled) { - symbol_name_is_mangled = symbol_name[1] == '_'; - symbol_name++; // Skip the leading underscore + sym[sym_idx].GetMangled().SetMangledName (ConstString(symbol_name_non_abi_mangled)); + sym[sym_idx].GetMangled().SetDemangledName (ConstString(symbol_name)); } - - if (symbol_name) + else { - ConstString const_symbol_name(symbol_name); - sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled); - if (is_gsym && is_debug) + bool symbol_name_is_mangled = false; + + if (symbol_name && symbol_name[0] == '_') { - N_GSYM_name_to_sym_idx[sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled).GetCString()] = sym_idx; + symbol_name_is_mangled = symbol_name[1] == '_'; + symbol_name++; // Skip the leading underscore } - } - } - if (symbol_section) - { - const addr_t section_file_addr = symbol_section->GetFileAddress(); - if (symbol_byte_size == 0 && function_starts_count > 0) - { - addr_t symbol_lookup_file_addr = nlist.n_value; - // Do an exact address match for non-ARM addresses, else get the closest since - // the symbol might be a thumb symbol which has an address with bit zero set - FunctionStarts::Entry *func_start_entry = function_starts.FindEntry (symbol_lookup_file_addr, !is_arm); - if (is_arm && func_start_entry) + + if (symbol_name) { - // Verify that the function start address is the symbol address (ARM) - // or the symbol address + 1 (thumb) - if (func_start_entry->addr != symbol_lookup_file_addr && - func_start_entry->addr != (symbol_lookup_file_addr + 1)) + ConstString const_symbol_name(symbol_name); + sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled); + if (is_gsym && is_debug) { - // Not the right entry, NULL it out... - func_start_entry = NULL; + N_GSYM_name_to_sym_idx[sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled).GetCString()] = sym_idx; } } - if (func_start_entry) + } + if (symbol_section) + { + const addr_t section_file_addr = symbol_section->GetFileAddress(); + if (symbol_byte_size == 0 && function_starts_count > 0) { - func_start_entry->data = true; - - addr_t symbol_file_addr = func_start_entry->addr; - if (is_arm) - symbol_file_addr &= 0xfffffffffffffffeull; - - const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry); - const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize(); - if (next_func_start_entry) + addr_t symbol_lookup_file_addr = nlist.n_value; + // Do an exact address match for non-ARM addresses, else get the closest since + // the symbol might be a thumb symbol which has an address with bit zero set + FunctionStarts::Entry *func_start_entry = function_starts.FindEntry (symbol_lookup_file_addr, !is_arm); + if (is_arm && func_start_entry) { - addr_t next_symbol_file_addr = next_func_start_entry->addr; - // Be sure the clear the Thumb address bit when we calculate the size - // from the current and next address - if (is_arm) - next_symbol_file_addr &= 0xfffffffffffffffeull; - symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr); + // Verify that the function start address is the symbol address (ARM) + // or the symbol address + 1 (thumb) + if (func_start_entry->addr != symbol_lookup_file_addr && + func_start_entry->addr != (symbol_lookup_file_addr + 1)) + { + // Not the right entry, NULL it out... + func_start_entry = NULL; + } } - else + if (func_start_entry) { - symbol_byte_size = section_end_file_addr - symbol_file_addr; + func_start_entry->data = true; + + addr_t symbol_file_addr = func_start_entry->addr; + if (is_arm) + symbol_file_addr &= 0xfffffffffffffffeull; + + const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry); + const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize(); + if (next_func_start_entry) + { + addr_t next_symbol_file_addr = next_func_start_entry->addr; + // Be sure the clear the Thumb address bit when we calculate the size + // from the current and next address + if (is_arm) + next_symbol_file_addr &= 0xfffffffffffffffeull; + symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr); + } + else + { + symbol_byte_size = section_end_file_addr - symbol_file_addr; + } } } + symbol_value -= section_file_addr; } - symbol_value -= section_file_addr; - } - if (is_debug == false) - { - if (type == eSymbolTypeCode) + if (is_debug == false) { - // See if we can find a N_FUN entry for any code symbols. - // If we do find a match, and the name matches, then we - // can merge the two into just the function symbol to avoid - // duplicate entries in the symbol table - ValueToSymbolIndexMap::const_iterator pos = N_FUN_addr_to_sym_idx.find (nlist.n_value); - if (pos != N_FUN_addr_to_sym_idx.end()) + if (type == eSymbolTypeCode) { - if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(Mangled::ePreferMangled)) + // See if we can find a N_FUN entry for any code symbols. + // If we do find a match, and the name matches, then we + // can merge the two into just the function symbol to avoid + // duplicate entries in the symbol table + ValueToSymbolIndexMap::const_iterator pos = N_FUN_addr_to_sym_idx.find (nlist.n_value); + if (pos != N_FUN_addr_to_sym_idx.end()) { - m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; - // We just need the flags from the linker symbol, so put these flags - // into the N_FUN flags to avoid duplicate symbols in the symbol table - sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc); - sym[sym_idx].Clear(); - continue; + if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(Mangled::ePreferMangled)) + { + m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; + // We just need the flags from the linker symbol, so put these flags + // into the N_FUN flags to avoid duplicate symbols in the symbol table + sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc); + sym[sym_idx].Clear(); + continue; + } } } - } - else if (type == eSymbolTypeData) - { - // See if we can find a N_STSYM entry for any data symbols. - // If we do find a match, and the name matches, then we - // can merge the two into just the Static symbol to avoid - // duplicate entries in the symbol table - ValueToSymbolIndexMap::const_iterator pos = N_STSYM_addr_to_sym_idx.find (nlist.n_value); - if (pos != N_STSYM_addr_to_sym_idx.end()) + else if (type == eSymbolTypeData) { - if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(Mangled::ePreferMangled)) + // See if we can find a N_STSYM entry for any data symbols. + // If we do find a match, and the name matches, then we + // can merge the two into just the Static symbol to avoid + // duplicate entries in the symbol table + ValueToSymbolIndexMap::const_iterator pos = N_STSYM_addr_to_sym_idx.find (nlist.n_value); + if (pos != N_STSYM_addr_to_sym_idx.end()) { - m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; - // We just need the flags from the linker symbol, so put these flags - // into the N_STSYM flags to avoid duplicate symbols in the symbol table - sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc); - sym[sym_idx].Clear(); - continue; + if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(Mangled::ePreferMangled)) + { + m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; + // We just need the flags from the linker symbol, so put these flags + // into the N_STSYM flags to avoid duplicate symbols in the symbol table + sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc); + sym[sym_idx].Clear(); + continue; + } } - } - else - { - // Combine N_GSYM stab entries with the non stab symbol - ConstNameToSymbolIndexMap::const_iterator pos = N_GSYM_name_to_sym_idx.find(sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled).GetCString()); - if (pos != N_GSYM_name_to_sym_idx.end()) + else { - const uint32_t GSYM_sym_idx = pos->second; - m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx; - // Copy the address, because often the N_GSYM address has an invalid address of zero - // when the global is a common symbol - sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section); - sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value); - // We just need the flags from the linker symbol, so put these flags - // into the N_STSYM flags to avoid duplicate symbols in the symbol table - sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); - sym[sym_idx].Clear(); - continue; + // Combine N_GSYM stab entries with the non stab symbol + ConstNameToSymbolIndexMap::const_iterator pos = N_GSYM_name_to_sym_idx.find(sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled).GetCString()); + if (pos != N_GSYM_name_to_sym_idx.end()) + { + const uint32_t GSYM_sym_idx = pos->second; + m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx; + // Copy the address, because often the N_GSYM address has an invalid address of zero + // when the global is a common symbol + sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section); + sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value); + // We just need the flags from the linker symbol, so put these flags + // into the N_STSYM flags to avoid duplicate symbols in the symbol table + sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); + sym[sym_idx].Clear(); + continue; + } } } } - } - sym[sym_idx].SetID (nlist_idx); - sym[sym_idx].SetType (type); - sym[sym_idx].GetAddress().SetSection (symbol_section); - sym[sym_idx].GetAddress().SetOffset (symbol_value); - sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); + sym[sym_idx].SetID (nlist_idx); + sym[sym_idx].SetType (type); + sym[sym_idx].GetAddress().SetSection (symbol_section); + sym[sym_idx].GetAddress().SetOffset (symbol_value); + sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc); - if (symbol_byte_size > 0) - sym[sym_idx].SetByteSize(symbol_byte_size); + if (symbol_byte_size > 0) + sym[sym_idx].SetByteSize(symbol_byte_size); - if (demangled_is_synthesized) - sym[sym_idx].SetDemangledNameIsSynthesized(true); + if (demangled_is_synthesized) + sym[sym_idx].SetDemangledNameIsSynthesized(true); - ++sym_idx; - } - else - { - sym[sym_idx].Clear(); - } + ++sym_idx; + } + else + { + sym[sym_idx].Clear(); + } - } + } - // STAB N_GSYM entries end up having a symbol type eSymbolTypeGlobal and when the symbol value - // is zero, the address of the global ends up being in a non-STAB entry. Try and fix up all - // such entries by figuring out what the address for the global is by looking up this non-STAB - // entry and copying the value into the debug symbol's value to save us the hassle in the - // debug symbol parser. + // STAB N_GSYM entries end up having a symbol type eSymbolTypeGlobal and when the symbol value + // is zero, the address of the global ends up being in a non-STAB entry. Try and fix up all + // such entries by figuring out what the address for the global is by looking up this non-STAB + // entry and copying the value into the debug symbol's value to save us the hassle in the + // debug symbol parser. - Symbol *global_symbol = NULL; - for (nlist_idx = 0; - nlist_idx < symtab_load_command.nsyms && (global_symbol = symtab->FindSymbolWithType (eSymbolTypeData, Symtab::eDebugYes, Symtab::eVisibilityAny, nlist_idx)) != NULL; - nlist_idx++) - { - if (global_symbol->GetAddress().GetFileAddress() == 0) + Symbol *global_symbol = NULL; + for (nlist_idx = 0; + nlist_idx < symtab_load_command.nsyms && (global_symbol = symtab->FindSymbolWithType (eSymbolTypeData, Symtab::eDebugYes, Symtab::eVisibilityAny, nlist_idx)) != NULL; + nlist_idx++) { - std::vector<uint32_t> indexes; - if (symtab->AppendSymbolIndexesWithName (global_symbol->GetMangled().GetName(), indexes) > 0) + if (global_symbol->GetAddress().GetFileAddress() == 0) { - std::vector<uint32_t>::const_iterator pos; - std::vector<uint32_t>::const_iterator end = indexes.end(); - for (pos = indexes.begin(); pos != end; ++pos) + std::vector<uint32_t> indexes; + if (symtab->AppendSymbolIndexesWithName (global_symbol->GetMangled().GetName(), indexes) > 0) { - symbol_ptr = symtab->SymbolAtIndex(*pos); - if (symbol_ptr != global_symbol && symbol_ptr->IsDebug() == false) + std::vector<uint32_t>::const_iterator pos; + std::vector<uint32_t>::const_iterator end = indexes.end(); + for (pos = indexes.begin(); pos != end; ++pos) { - global_symbol->GetAddress() = symbol_ptr->GetAddress(); - break; + symbol_ptr = symtab->SymbolAtIndex(*pos); + if (symbol_ptr != global_symbol && symbol_ptr->IsDebug() == false) + { + global_symbol->GetAddress() = symbol_ptr->GetAddress(); + break; + } } } } |