diff options
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 1601 |
1 files changed, 871 insertions, 730 deletions
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index ac03b177c1b..479d0d82878 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1142,887 +1142,1028 @@ ObjectFileMachO::ParseSymtab (bool minimize) Timer scoped_timer(__PRETTY_FUNCTION__, "ObjectFileMachO::ParseSymtab () module = %s", m_file.GetFilename().AsCString("")); - struct symtab_command symtab_load_command; + ModuleSP module_sp (GetModule()); + if (!module_sp) + return 0; + + struct symtab_command symtab_load_command = { 0, 0, 0, 0, 0, 0 }; + struct linkedit_data_command function_starts_load_command = { 0, 0, 0, 0 }; + typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts; + FunctionStarts function_starts; uint32_t offset = MachHeaderSizeFromMagic(m_header.magic); uint32_t i; - + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); for (i=0; i<m_header.ncmds; ++i) { const uint32_t cmd_offset = offset; // Read in the load command and load command size - if (m_data.GetU32(&offset, &symtab_load_command, 2) == NULL) + struct load_command lc; + if (m_data.GetU32(&offset, &lc, 2) == NULL) break; // Watch for the symbol table load command - if (symtab_load_command.cmd == LoadCommandSymtab) + switch (lc.cmd) { + case LoadCommandSymtab: + symtab_load_command.cmd = lc.cmd; + symtab_load_command.cmdsize = lc.cmdsize; // Read in the rest of the symtab load command - if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4)) // fill in symoff, nsyms, stroff, strsize fields + if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4) == 0) // fill in symoff, nsyms, stroff, strsize fields + return 0; + if (symtab_load_command.symoff == 0) { - if (symtab_load_command.symoff == 0) - { - if (log) - GetModule()->LogMessage(log.get(), "LC_SYMTAB.symoff == 0"); - return 0; - } - - if (symtab_load_command.stroff == 0) - { - if (log) - GetModule()->LogMessage(log.get(), "LC_SYMTAB.stroff == 0"); - return 0; - } - - if (symtab_load_command.nsyms == 0) - { - if (log) - GetModule()->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0"); - return 0; - } - - if (symtab_load_command.strsize == 0) - { - if (log) - GetModule()->LogMessage(log.get(), "LC_SYMTAB.strsize == 0"); - return 0; - } + if (log) + module_sp->LogMessage(log.get(), "LC_SYMTAB.symoff == 0"); + return 0; + } - Symtab *symtab = m_symtab_ap.get(); - SectionList *section_list = GetSectionList(); - if (section_list == NULL) - return 0; + if (symtab_load_command.stroff == 0) + { + if (log) + module_sp->LogMessage(log.get(), "LC_SYMTAB.stroff == 0"); + return 0; + } + + if (symtab_load_command.nsyms == 0) + { + if (log) + module_sp->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0"); + return 0; + } + + if (symtab_load_command.strsize == 0) + { + if (log) + module_sp->LogMessage(log.get(), "LC_SYMTAB.strsize == 0"); + return 0; + } + break; - ProcessSP process_sp (m_process_wp.lock()); + case LoadCommandFunctionStarts: + function_starts_load_command.cmd = lc.cmd; + function_starts_load_command.cmdsize = lc.cmdsize; + if (m_data.GetU32(&offset, &function_starts_load_command.dataoff, 2) == NULL) // fill in symoff, nsyms, stroff, strsize fields + bzero (&function_starts_load_command, sizeof(function_starts_load_command)); + break; - const size_t addr_byte_size = m_data.GetAddressByteSize(); - bool bit_width_32 = addr_byte_size == 4; - const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64); + default: + break; + } + offset = cmd_offset + lc.cmdsize; + } - DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize()); - DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize()); + if (symtab_load_command.cmd) + { + Symtab *symtab = m_symtab_ap.get(); + SectionList *section_list = GetSectionList(); + if (section_list == NULL) + return 0; - 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; - if (process_sp) - { - Target &target = process_sp->GetTarget(); - SectionSP linkedit_section_sp(section_list->FindSectionByName(GetSegmentNameLINKEDIT())); - // Reading mach file from memory in a process or core file... + ProcessSP process_sp (m_process_wp.lock()); - if (linkedit_section_sp) - { - const addr_t linkedit_load_addr = linkedit_section_sp->GetLoadBaseAddress(&target); - const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset(); - const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset; - const addr_t stroff_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset; - 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, stroff_addr, strtab_data_byte_size)); - if (strtab_data_sp) - strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); - } - } - else - { - nlist_data.SetData (m_data, - symtab_load_command.symoff, - nlist_data_byte_size); - strtab_data.SetData (m_data, - symtab_load_command.stroff, - strtab_data_byte_size); + const size_t addr_byte_size = m_data.GetAddressByteSize(); + bool bit_width_32 = addr_byte_size == 4; + const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64); - } + DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize()); + DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize()); + DataExtractor function_starts_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize()); + + 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; + if (process_sp) + { + Target &target = process_sp->GetTarget(); + SectionSP linkedit_section_sp(section_list->FindSectionByName(GetSegmentNameLINKEDIT())); + // Reading mach file from memory in a process or core file... - if (nlist_data.GetByteSize() == 0) + if (linkedit_section_sp) + { + const addr_t linkedit_load_addr = linkedit_section_sp->GetLoadBaseAddress(&target); + const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset(); + const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset; + const addr_t stroff_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset; + 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, stroff_addr, strtab_data_byte_size)); + if (strtab_data_sp) + strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); + if (function_starts_load_command.cmd) { - if (log) - GetModule()->LogMessage(log.get(), "failed to read nlist data"); - return 0; + 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()); } + } + } + else + { + nlist_data.SetData (m_data, + symtab_load_command.symoff, + nlist_data_byte_size); + strtab_data.SetData (m_data, + symtab_load_command.stroff, + strtab_data_byte_size); + if (function_starts_load_command.cmd) + { + function_starts_data.SetData (m_data, + function_starts_load_command.dataoff, + function_starts_load_command.datasize); + } + } + if (nlist_data.GetByteSize() == 0) + { + if (log) + module_sp->LogMessage(log.get(), "failed to read nlist data"); + return 0; + } - if (strtab_data.GetByteSize() == 0) - { - if (log) - GetModule()->LogMessage(log.get(), "failed to read strtab data"); - return 0; - } - const ConstString &g_segment_name_TEXT = GetSegmentNameTEXT(); - const ConstString &g_segment_name_DATA = GetSegmentNameDATA(); - const ConstString &g_segment_name_OBJC = GetSegmentNameOBJC(); - const ConstString &g_section_name_eh_frame = GetSectionNameEHFrame(); - SectionSP text_section_sp(section_list->FindSectionByName(g_segment_name_TEXT)); - SectionSP data_section_sp(section_list->FindSectionByName(g_segment_name_DATA)); - SectionSP objc_section_sp(section_list->FindSectionByName(g_segment_name_OBJC)); - SectionSP eh_frame_section_sp; - if (text_section_sp.get()) - eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName (g_section_name_eh_frame); - else - eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame); - - uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection; - - uint32_t nlist_data_offset = 0; - - uint32_t N_SO_index = UINT32_MAX; - - MachSymtabSectionInfo section_info (section_list); - std::vector<uint32_t> N_FUN_indexes; - std::vector<uint32_t> N_NSYM_indexes; - std::vector<uint32_t> N_INCL_indexes; - std::vector<uint32_t> N_BRAC_indexes; - std::vector<uint32_t> N_COMM_indexes; - typedef std::map <uint64_t, uint32_t> ValueToSymbolIndexMap; - typedef std::map <uint32_t, uint32_t> NListIndexToSymbolIndexMap; - ValueToSymbolIndexMap N_FUN_addr_to_sym_idx; - ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx; - // Any symbols that get merged into another will get an entry - // in this map so we know - NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx; - uint32_t nlist_idx = 0; - Symbol *symbol_ptr = NULL; - - uint32_t sym_idx = 0; - Symbol *sym = symtab->Resize (symtab_load_command.nsyms + m_dysymtab.nindirectsyms); - uint32_t num_syms = symtab->GetNumSymbols(); - - //symtab->Reserve (symtab_load_command.nsyms + m_dysymtab.nindirectsyms); - for (nlist_idx = 0; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) + if (strtab_data.GetByteSize() == 0) + { + if (log) + module_sp->LogMessage(log.get(), "failed to read strtab data"); + return 0; + } + + const ConstString &g_segment_name_TEXT = GetSegmentNameTEXT(); + const ConstString &g_segment_name_DATA = GetSegmentNameDATA(); + const ConstString &g_segment_name_OBJC = GetSegmentNameOBJC(); + const ConstString &g_section_name_eh_frame = GetSectionNameEHFrame(); + SectionSP text_section_sp(section_list->FindSectionByName(g_segment_name_TEXT)); + SectionSP data_section_sp(section_list->FindSectionByName(g_segment_name_DATA)); + SectionSP objc_section_sp(section_list->FindSectionByName(g_segment_name_OBJC)); + SectionSP eh_frame_section_sp; + if (text_section_sp.get()) + eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName (g_section_name_eh_frame); + else + eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame); + + + if (text_section_sp && function_starts_data.GetByteSize()) + { + FunctionStarts::Entry function_start_entry; + function_start_entry.data = false; + uint32_t function_start_offset = 0; + function_start_entry.addr = text_section_sp->GetFileAddress(); + uint64_t delta; + while ((delta = function_starts_data.GetULEB128(&function_start_offset)) > 0) + { + // Now append the current entry + function_start_entry.addr += delta; + function_starts.Append(function_start_entry); + } + } + + const uint32_t function_starts_count = function_starts.GetSize(); + + uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection; + + uint32_t nlist_data_offset = 0; + + uint32_t N_SO_index = UINT32_MAX; + + MachSymtabSectionInfo section_info (section_list); + std::vector<uint32_t> N_FUN_indexes; + std::vector<uint32_t> N_NSYM_indexes; + std::vector<uint32_t> N_INCL_indexes; + std::vector<uint32_t> N_BRAC_indexes; + std::vector<uint32_t> N_COMM_indexes; + typedef std::map <uint64_t, uint32_t> ValueToSymbolIndexMap; + typedef std::map <uint32_t, uint32_t> NListIndexToSymbolIndexMap; + ValueToSymbolIndexMap N_FUN_addr_to_sym_idx; + ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx; + // Any symbols that get merged into another will get an entry + // in this map so we know + NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx; + uint32_t nlist_idx = 0; + Symbol *symbol_ptr = NULL; + + uint32_t sym_idx = 0; + Symbol *sym = symtab->Resize (symtab_load_command.nsyms + m_dysymtab.nindirectsyms); + uint32_t num_syms = symtab->GetNumSymbols(); + + //symtab->Reserve (symtab_load_command.nsyms + m_dysymtab.nindirectsyms); + for (nlist_idx = 0; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) + { + 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 = strtab_data.PeekCStr(nlist.n_strx); + 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/%s, ignoring symbol\n", + nlist_idx, + nlist.n_strx, + module_sp->GetFileSpec().GetDirectory().GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); + continue; + } + const char *symbol_name_non_abi_mangled = NULL; + + if (symbol_name[0] == '\0') + symbol_name = NULL; + SectionSP symbol_section; + uint32_t symbol_byte_size = 0; + bool add_nlist = true; + bool is_debug = ((nlist.n_type & NlistMaskStab) != 0); + + assert (sym_idx < num_syms); + + sym[sym_idx].SetDebug (is_debug); + + if (is_debug) + { + switch (nlist.n_type) { - struct nlist_64 nlist; - if (!nlist_data.ValidOffsetForDataOfSize(nlist_data_offset, nlist_byte_size)) - break; + 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 + { + sym[sym_idx].SetExternal(true); + if (nlist.n_value != 0) + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + type = eSymbolTypeData; + } + 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); + case StabFunctionName: + // N_FNAME -- procedure name (f77 kludge): name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - SymbolType type = eSymbolTypeInvalid; - const char *symbol_name = strtab_data.PeekCStr(nlist.n_strx); - if (symbol_name == NULL) + 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); + + 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 { - ModuleSP module_sp (GetModule()); - // No symbol should be NULL, even the symbols with no - // string values should have an offset zero which points - // to an empty C-string - if (module_sp) + type = eSymbolTypeCompiler; + + if ( !N_FUN_indexes.empty() ) { - Host::SystemLog (Host::eSystemLogError, - "error: symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n", - nlist_idx, - nlist.n_strx, - module_sp->GetFileSpec().GetDirectory().GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); + // 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 + if (minimize) + add_nlist = false; } - continue; } - const char *symbol_name_non_abi_mangled = NULL; + break; - if (symbol_name[0] == '\0') - symbol_name = NULL; - SectionSP symbol_section; - bool add_nlist = true; - bool is_debug = ((nlist.n_type & NlistMaskStab) != 0); + 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; - assert (sym_idx < num_syms); + 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; - sym[sym_idx].SetDebug (is_debug); + 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 + if (minimize) + { + // Skip these if we want minimal symbol tables + add_nlist = false; + } + else + { + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + N_NSYM_indexes.push_back(sym_idx); + type = eSymbolTypeScopeBegin; + } + break; - if (is_debug) + 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 + if (minimize) { - switch (nlist.n_type) + // Skip these if we want minimal symbol tables + add_nlist = false; + } + else + { + if ( !N_NSYM_indexes.empty() ) { - 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 - { - 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; + symbol_ptr = symtab->SymbolAtIndex(N_NSYM_indexes.back()); + symbol_ptr->SetByteSize(sym_idx + 1); + symbol_ptr->SetSizeIsSibling(true); + N_NSYM_indexes.pop_back(); + } + type = eSymbolTypeScopeEnd; + } + break; - 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); - - 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 - { - type = eSymbolTypeCompiler; - 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 - if (minimize) - add_nlist = false; - } - } - break; + case StabSourceFileOptions: + // N_OPT - emitted with gcc2_compiled and in gcc source + type = eSymbolTypeCompiler; + 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 StabRegisterSymbol: + // N_RSYM - register sym: name,,NO_SECT,type,register + type = eSymbolTypeVariable; + 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 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 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 - if (minimize) - { - // Skip these if we want minimal symbol tables - add_nlist = false; - } - else - { - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - N_NSYM_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - } - break; + case StabStructureType: + // N_SSYM - structure elt: name,,NO_SECT,type,struct_offset + type = eSymbolTypeVariableType; + 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 + case StabSourceFileName: + // N_SO - source file name + type = eSymbolTypeSourceFile; + if (symbol_name == NULL) + { + if (minimize) + 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 - if (minimize) + symbol_ptr = symtab->SymbolAtIndex(N_SO_index); + symbol_ptr->SetByteSize(sym_idx + (minimize ? 0 : 1)); + 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 + if (symbol_name[0] == '/') + N_SO_index = sym_idx; + else if (minimize && (N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) + { + const char *so_path = sym[sym_idx - 1].GetMangled().GetDemangledName().AsCString(); + if (so_path && so_path[0]) { - // Skip these if we want minimal symbol tables + std::string full_so_path (so_path); + if (*full_so_path.rbegin() != '/') + full_so_path += '/'; + full_so_path += symbol_name; + sym[sym_idx - 1].GetMangled().SetValue(full_so_path.c_str(), false); add_nlist = false; + m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; } - else - { - if ( !N_NSYM_indexes.empty() ) - { - symbol_ptr = symtab->SymbolAtIndex(N_NSYM_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_NSYM_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - } - 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 StabSourceLine: - // N_SLINE - src line: 0,,n_sect,linenumber,address - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; + } + } + + break; - case StabStructureType: - // N_SSYM - structure elt: name,,NO_SECT,type,struct_offset - type = eSymbolTypeVariableType; - break; + case StabObjectFileName: + // N_OSO - object file name: name,,0,0,st_mtime + type = eSymbolTypeObjectFile; + break; - case StabSourceFileName: - // N_SO - source file name - type = eSymbolTypeSourceFile; - if (symbol_name == NULL) - { - if (minimize) - 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 + (minimize ? 0 : 1)); - 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 - if (symbol_name[0] == '/') - N_SO_index = sym_idx; - else if (minimize && (N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) - { - const char *so_path = sym[sym_idx - 1].GetMangled().GetDemangledName().AsCString(); - if (so_path && so_path[0]) - { - std::string full_so_path (so_path); - if (*full_so_path.rbegin() != '/') - full_so_path += '/'; - full_so_path += symbol_name; - sym[sym_idx - 1].GetMangled().SetValue(full_so_path.c_str(), false); - add_nlist = false; - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; - } - } - } - - break; + case StabLocalSymbol: + // N_LSYM - local sym: name,,NO_SECT,type,offset + type = eSymbolTypeLocal; + break; - case StabObjectFileName: - // N_OSO - object file name: name,,0,0,st_mtime - type = eSymbolTypeObjectFile; - 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 StabLocalSymbol: - // N_LSYM - local sym: name,,NO_SECT,type,offset - type = eSymbolTypeLocal; - 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; - //---------------------------------------------------------------------- - // 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 StabIncludeFileName: + // N_SOL - #included file name: name,,n_sect,0,address + type = eSymbolTypeHeaderFile; - 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; + // We currently don't use the header files on darwin + if (minimize) + add_nlist = false; + break; - case StabIncludeFileName: - // N_SOL - #included file name: name,,n_sect,0,address - type = eSymbolTypeHeaderFile; + case StabCompilerParameters: + // N_PARAMS - compiler parameters: name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - // We currently don't use the header files on darwin - if (minimize) - add_nlist = false; - break; + case StabCompilerVersion: + // N_VERSION - compiler version: name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - case StabCompilerParameters: - // N_PARAMS - compiler parameters: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; + case StabCompilerOptLevel: + // N_OLEVEL - compiler -O level: name,,NO_SECT,0,0 + type = eSymbolTypeCompiler; + break; - case StabCompilerVersion: - // N_VERSION - compiler version: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; + case StabParameter: + // N_PSYM - parameter: name,,NO_SECT,type,offset + type = eSymbolTypeVariable; + break; - case StabCompilerOptLevel: - // N_OLEVEL - compiler -O level: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - 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 StabParameter: - // N_PSYM - parameter: name,,NO_SECT,type,offset - type = eSymbolTypeVariable; - 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 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 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; - //---------------------------------------------------------------------- - // 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 StabDeletedIncludeFile: + // N_EXCL - deleted include file: name,,NO_SECT,0,sum + type = eSymbolTypeHeaderFile; + 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; + //---------------------------------------------------------------------- + // 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 StabDeletedIncludeFile: - // N_EXCL - deleted include file: name,,NO_SECT,0,sum - type = eSymbolTypeHeaderFile; - 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; - //---------------------------------------------------------------------- - // 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 StabLength: + // N_LENG - second stab entry with length information + type = eSymbolTypeAdditional; + 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 + 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); - 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; + switch (n_type) + { + case NListTypeIndirect: // N_INDR - Fall through + case NListTypePreboundUndefined:// N_PBUD - Fall through + case NListTypeUndefined: // N_UNDF + type = eSymbolTypeUndefined; + break; - case StabLength: - // N_LENG - second stab entry with length information - type = eSymbolTypeAdditional; - break; + case NListTypeAbsolute: // N_ABS + type = eSymbolTypeAbsolute; + break; - default: break; - } - } - else + case NListTypeSection: // N_SECT { - //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); + symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - switch (n_type) + if (symbol_section == NULL) { - 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; + // TODO: warn about this? + add_nlist = false; break; + } - case NListTypeSection: // N_SECT - symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); + if (TEXT_eh_frame_sectID == nlist.n_sect) + { + type = eSymbolTypeException; + } + else + { + uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType; - if (symbol_section == NULL) + switch (section_type) { - // TODO: warn about this? - add_nlist = false; - break; + 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; } - if (TEXT_eh_frame_sectID == nlist.n_sect) + if (type == eSymbolTypeInvalid) { - type = eSymbolTypeException; - } - else - { - uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType; - - switch (section_type) + const char *symbol_sect_name = symbol_section->GetName().AsCString(); + if (symbol_section->IsDescendant (text_section_sp.get())) { - 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; + if (symbol_section->IsClear(SectionAttrUserPureInstructions | + SectionAttrUserSelfModifyingCode | + SectionAttrSytemSomeInstructions)) + type = eSymbolTypeData; + else + type = eSymbolTypeCode; } - - if (type == eSymbolTypeInvalid) + else + if (symbol_section->IsDescendant(data_section_sp.get())) { - const char *symbol_sect_name = symbol_section->GetName().AsCString(); - if (symbol_section->IsDescendant (text_section_sp.get())) + if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name) { - 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) - { - type = eSymbolTypeRuntime; + type = eSymbolTypeRuntime; - if (symbol_name && - symbol_name[0] == '_' && - symbol_name[1] == 'O' && - symbol_name[2] == 'B') + if (symbol_name && + symbol_name[0] == '_' && + symbol_name[1] == 'O' && + symbol_name[2] == 'B') + { + 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)) { - 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; - } - 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; - } - 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; - } + symbol_name_non_abi_mangled = symbol_name + 1; + symbol_name = symbol_name + g_objc_v2_prefix_class.size(); + type = eSymbolTypeObjCClass; + } + 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; + } + 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; } - } - 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, "__IMPORT") == symbol_sect_name) + if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name) { - type = eSymbolTypeTrampoline; + type = eSymbolTypeException; } else - if (symbol_section->IsDescendant(objc_section_sp.get())) { - type = eSymbolTypeRuntime; - if (symbol_name && symbol_name[0] == '.') + 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)) { - 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; - } + symbol_name_non_abi_mangled = symbol_name; + symbol_name = symbol_name + g_objc_v1_prefix_class.size(); + type = eSymbolTypeObjCClass; } } } } - break; - } + } } + break; + } + } + + if (add_nlist) + { + uint64_t symbol_value = nlist.n_value; + bool symbol_name_is_mangled = false; - if (add_nlist) + if (symbol_name_non_abi_mangled) + { + sym[sym_idx].GetMangled().SetMangledName (symbol_name_non_abi_mangled); + sym[sym_idx].GetMangled().SetDemangledName (symbol_name); + } + else + { + if (symbol_name && symbol_name[0] == '_') { - uint64_t symbol_value = nlist.n_value; - bool symbol_name_is_mangled = false; + symbol_name_is_mangled = symbol_name[1] == '_'; + symbol_name++; // Skip the leading underscore + } - if (symbol_name_non_abi_mangled) - { - sym[sym_idx].GetMangled().SetMangledName (symbol_name_non_abi_mangled); - sym[sym_idx].GetMangled().SetDemangledName (symbol_name); - } - else + if (symbol_name) + { + sym[sym_idx].GetMangled().SetValue(symbol_name, symbol_name_is_mangled); + } + } + + if (is_debug == false) + { + if (type == eSymbolTypeCode) + { + // 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 (symbol_name && symbol_name[0] == '_') + if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) || + (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName())) { - symbol_name_is_mangled = symbol_name[1] == '_'; - symbol_name++; // Skip the leading underscore + 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 (symbol_name) + } + } + 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()) + { + if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) || + (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName())) { - sym[sym_idx].GetMangled().SetValue(symbol_name, symbol_name_is_mangled); + 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 (is_debug == false) + } + } + if (symbol_section) + { + const addr_t section_file_addr = symbol_section->GetFileAddress(); + if (symbol_byte_size == 0 && function_starts_count > 0) + { + FunctionStarts::Entry *func_start_entry = function_starts.FindEntry(nlist.n_value, true); + if (func_start_entry) { - if (type == eSymbolTypeCode) + func_start_entry->data = true; + 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) { - // 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 ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) || - (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName())) - { - 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; - } - } + symbol_byte_size = std::min<lldb::addr_t>(next_func_start_entry->addr - func_start_entry->addr, section_end_file_addr - func_start_entry->addr); } - else if (type == eSymbolTypeData) + else { - // 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()) - { - if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) || - (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName())) - { - 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; - } - } + symbol_byte_size = section_end_file_addr - func_start_entry->addr; } } - if (symbol_section != NULL) - symbol_value -= symbol_section->GetFileAddress(); + } + symbol_value -= section_file_addr; + } - 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); - ++sym_idx; - } - else + if (symbol_byte_size > 0) + sym[sym_idx].SetByteSize(symbol_byte_size); + + ++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. + + 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) + { + std::vector<uint32_t> indexes; + if (symtab->AppendSymbolIndexesWithName (global_symbol->GetMangled().GetName(), indexes) > 0) + { + std::vector<uint32_t>::const_iterator pos; + std::vector<uint32_t>::const_iterator end = indexes.end(); + for (pos = indexes.begin(); pos != end; ++pos) { - sym[sym_idx].Clear(); + symbol_ptr = symtab->SymbolAtIndex(*pos); + if (symbol_ptr != global_symbol && symbol_ptr->IsDebug() == false) + { + global_symbol->GetAddress() = symbol_ptr->GetAddress(); + break; + } } - } + } + } + + uint32_t synthetic_sym_id = symtab_load_command.nsyms; - // 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 (function_starts_count > 0) + { + char synthetic_function_symbol[PATH_MAX]; + uint32_t num_synthetic_function_symbols = 0; + for (i=0; i<function_starts_count; ++i) + { + if (function_starts.GetEntryRef (i).data == false) + ++num_synthetic_function_symbols; + } + + if (num_synthetic_function_symbols > 0) + { + if (num_syms < sym_idx + num_synthetic_function_symbols) { - if (global_symbol->GetAddress().GetFileAddress() == 0) + num_syms = sym_idx + num_synthetic_function_symbols; + sym = symtab->Resize (num_syms); + } + uint32_t synthetic_function_symbol_idx = 0; + for (i=0; i<function_starts_count; ++i) + { + const FunctionStarts::Entry *func_start_entry = function_starts.GetEntryAtIndex (i); + if (func_start_entry->data == false) { - std::vector<uint32_t> indexes; - if (symtab->AppendSymbolIndexesWithName (global_symbol->GetMangled().GetName(), indexes) > 0) + Address symbol_addr; + if (module_sp->ResolveFileAddress (func_start_entry->addr, symbol_addr)) { - std::vector<uint32_t>::const_iterator pos; - std::vector<uint32_t>::const_iterator end = indexes.end(); - for (pos = indexes.begin(); pos != end; ++pos) + SectionSP symbol_section (symbol_addr.GetSection()); + uint32_t symbol_byte_size = 0; + if (symbol_section) { - symbol_ptr = symtab->SymbolAtIndex(*pos); - if (symbol_ptr != global_symbol && symbol_ptr->IsDebug() == false) + const addr_t section_file_addr = symbol_section->GetFileAddress(); + 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) + { + symbol_byte_size = std::min<lldb::addr_t>(next_func_start_entry->addr - func_start_entry->addr, section_end_file_addr - func_start_entry->addr); + } + else { - global_symbol->GetAddress() = symbol_ptr->GetAddress(); - break; + symbol_byte_size = section_end_file_addr - func_start_entry->addr; } + snprintf (synthetic_function_symbol, + sizeof(synthetic_function_symbol), + "___lldb_unnamed_function%u$$%s", + ++synthetic_function_symbol_idx, + module_sp->GetFileSpec().GetFilename().GetCString()); + sym[sym_idx].SetID (synthetic_sym_id++); + sym[sym_idx].GetMangled().SetDemangledName(synthetic_function_symbol); + sym[sym_idx].SetType (eSymbolTypeCode); + sym[sym_idx].SetIsSynthetic (true); + sym[sym_idx].GetAddress() = symbol_addr; + if (symbol_byte_size) + sym[sym_idx].SetByteSize (symbol_byte_size); + ++sym_idx; } } } } + } + } - // Trim our symbols down to just what we ended up with after - // removing any symbols. - if (sym_idx < num_syms) - { - num_syms = sym_idx; - sym = symtab->Resize (num_syms); - } + // Trim our symbols down to just what we ended up with after + // removing any symbols. + if (sym_idx < num_syms) + { + num_syms = sym_idx; + sym = symtab->Resize (num_syms); + } - // Now synthesize indirect symbols - if (m_dysymtab.nindirectsyms != 0) - { - DataExtractor indirect_symbol_index_data (m_data, m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4); + // Now synthesize indirect symbols + if (m_dysymtab.nindirectsyms != 0) + { + DataExtractor indirect_symbol_index_data (m_data, m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4); - if (indirect_symbol_index_data.GetByteSize()) + if (indirect_symbol_index_data.GetByteSize()) + { + NListIndexToSymbolIndexMap::const_iterator end_index_pos = m_nlist_idx_to_sym_idx.end(); + + for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size(); ++sect_idx) + { + if ((m_mach_sections[sect_idx].flags & SectionFlagMaskSectionType) == SectionTypeSymbolStubs) { - NListIndexToSymbolIndexMap::const_iterator end_index_pos = m_nlist_idx_to_sym_idx.end(); + uint32_t symbol_stub_byte_size = m_mach_sections[sect_idx].reserved2; + if (symbol_stub_byte_size == 0) + continue; - for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size(); ++sect_idx) - { - if ((m_mach_sections[sect_idx].flags & SectionFlagMaskSectionType) == SectionTypeSymbolStubs) - { - uint32_t symbol_stub_byte_size = m_mach_sections[sect_idx].reserved2; - if (symbol_stub_byte_size == 0) - continue; + const uint32_t num_symbol_stubs = m_mach_sections[sect_idx].size / symbol_stub_byte_size; - const uint32_t num_symbol_stubs = m_mach_sections[sect_idx].size / symbol_stub_byte_size; + if (num_symbol_stubs == 0) + continue; - if (num_symbol_stubs == 0) + const uint32_t symbol_stub_index_offset = m_mach_sections[sect_idx].reserved1; + for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; ++stub_idx) + { + const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx; + const lldb::addr_t symbol_stub_addr = m_mach_sections[sect_idx].addr + (stub_idx * symbol_stub_byte_size); + uint32_t symbol_stub_offset = symbol_stub_index * 4; + if (indirect_symbol_index_data.ValidOffsetForDataOfSize(symbol_stub_offset, 4)) + { + const uint32_t stub_sym_id = indirect_symbol_index_data.GetU32 (&symbol_stub_offset); + if (stub_sym_id & (IndirectSymbolAbsolute | IndirectSymbolLocal)) continue; - const uint32_t symbol_stub_index_offset = m_mach_sections[sect_idx].reserved1; - uint32_t synthetic_stub_sym_id = symtab_load_command.nsyms; - for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; ++stub_idx) + NListIndexToSymbolIndexMap::const_iterator index_pos = m_nlist_idx_to_sym_idx.find (stub_sym_id); + Symbol *stub_symbol = NULL; + if (index_pos != end_index_pos) { - const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx; - const lldb::addr_t symbol_stub_addr = m_mach_sections[sect_idx].addr + (stub_idx * symbol_stub_byte_size); - uint32_t symbol_stub_offset = symbol_stub_index * 4; - if (indirect_symbol_index_data.ValidOffsetForDataOfSize(symbol_stub_offset, 4)) - { - const uint32_t stub_sym_id = indirect_symbol_index_data.GetU32 (&symbol_stub_offset); - if (stub_sym_id & (IndirectSymbolAbsolute | IndirectSymbolLocal)) - continue; - - NListIndexToSymbolIndexMap::const_iterator index_pos = m_nlist_idx_to_sym_idx.find (stub_sym_id); - Symbol *stub_symbol = NULL; - if (index_pos != end_index_pos) - { - // We have a remapping from the original nlist index to - // a current symbol index, so just look this up by index - stub_symbol = symtab->SymbolAtIndex (index_pos->second); - } - else - { - // We need to lookup a symbol using the original nlist - // symbol index since this index is coming from the - // S_SYMBOL_STUBS - stub_symbol = symtab->FindSymbolByID (stub_sym_id); - } + // We have a remapping from the original nlist index to + // a current symbol index, so just look this up by index + stub_symbol = symtab->SymbolAtIndex (index_pos->second); + } + else + { + // We need to lookup a symbol using the original nlist + // symbol index since this index is coming from the + // S_SYMBOL_STUBS + stub_symbol = symtab->FindSymbolByID (stub_sym_id); + } - assert (stub_symbol); - if (stub_symbol) - { - Address so_addr(symbol_stub_addr, section_list); + assert (stub_symbol); + if (stub_symbol) + { + Address so_addr(symbol_stub_addr, section_list); - if (stub_symbol->GetType() == eSymbolTypeUndefined) - { - // Change the external symbol into a trampoline that makes sense - // These symbols were N_UNDF N_EXT, and are useless to us, so we - // can re-use them so we don't have to make up a synthetic symbol - // for no good reason. - stub_symbol->SetType (eSymbolTypeTrampoline); - stub_symbol->SetExternal (false); - stub_symbol->GetAddress() = so_addr; - stub_symbol->SetByteSize (symbol_stub_byte_size); - } - else - { - // Make a synthetic symbol to describe the trampoline stub - if (sym_idx >= num_syms) - sym = symtab->Resize (++num_syms); - sym[sym_idx].SetID (synthetic_stub_sym_id++); - sym[sym_idx].GetMangled() = stub_symbol->GetMangled(); - sym[sym_idx].SetType (eSymbolTypeTrampoline); - sym[sym_idx].SetIsSynthetic (true); - sym[sym_idx].GetAddress() = so_addr; - sym[sym_idx].SetByteSize (symbol_stub_byte_size); - ++sym_idx; - } - } + if (stub_symbol->GetType() == eSymbolTypeUndefined) + { + // Change the external symbol into a trampoline that makes sense + // These symbols were N_UNDF N_EXT, and are useless to us, so we + // can re-use them so we don't have to make up a synthetic symbol + // for no good reason. + stub_symbol->SetType (eSymbolTypeTrampoline); + stub_symbol->SetExternal (false); + stub_symbol->GetAddress() = so_addr; + stub_symbol->SetByteSize (symbol_stub_byte_size); + } + else + { + // Make a synthetic symbol to describe the trampoline stub + if (sym_idx >= num_syms) + sym = symtab->Resize (++num_syms); + sym[sym_idx].SetID (synthetic_sym_id++); + sym[sym_idx].GetMangled() = stub_symbol->GetMangled(); + sym[sym_idx].SetType (eSymbolTypeTrampoline); + sym[sym_idx].SetIsSynthetic (true); + sym[sym_idx].GetAddress() = so_addr; + sym[sym_idx].SetByteSize (symbol_stub_byte_size); + ++sym_idx; } } } } } } - return symtab->GetNumSymbols(); } } - offset = cmd_offset + symtab_load_command.cmdsize; + return symtab->GetNumSymbols(); } return 0; } |