diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index a19322ff1e263..f31b56b9f81e6 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -918,6 +918,11 @@ ConstString ObjectFileMachO::GetSectionNameEHFrame() { return g_section_name_eh_frame; } +ConstString ObjectFileMachO::GetSectionNameLLDBNoNlist() { + static ConstString g_section_name_lldb_no_nlist("__lldb_no_nlist"); + return g_section_name_lldb_no_nlist; +} + bool ObjectFileMachO::MagicBytesMatch(DataBufferSP data_sp, lldb::addr_t data_offset, lldb::addr_t data_length) { @@ -2394,8 +2399,39 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) { uint32_t memory_module_load_level = eMemoryModuleLoadLevelComplete; bool is_shared_cache_image = IsSharedCacheBinary(); bool is_local_shared_cache_image = is_shared_cache_image && !IsInMemory(); + + ConstString g_segment_name_TEXT = GetSegmentNameTEXT(); + ConstString g_segment_name_DATA = GetSegmentNameDATA(); + ConstString g_segment_name_DATA_DIRTY = GetSegmentNameDATA_DIRTY(); + ConstString g_segment_name_DATA_CONST = GetSegmentNameDATA_CONST(); + ConstString g_segment_name_OBJC = GetSegmentNameOBJC(); + ConstString g_section_name_eh_frame = GetSectionNameEHFrame(); + ConstString g_section_name_lldb_no_nlist = GetSectionNameLLDBNoNlist(); + SectionSP text_section_sp( + section_list->FindSectionByName(g_segment_name_TEXT)); + SectionSP data_section_sp( + section_list->FindSectionByName(g_segment_name_DATA)); SectionSP linkedit_section_sp( section_list->FindSectionByName(GetSegmentNameLINKEDIT())); + SectionSP data_dirty_section_sp( + section_list->FindSectionByName(g_segment_name_DATA_DIRTY)); + SectionSP data_const_section_sp( + section_list->FindSectionByName(g_segment_name_DATA_CONST)); + SectionSP objc_section_sp( + section_list->FindSectionByName(g_segment_name_OBJC)); + SectionSP eh_frame_section_sp; + SectionSP lldb_no_nlist_section_sp; + if (text_section_sp.get()) { + eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName( + g_section_name_eh_frame); + lldb_no_nlist_section_sp = text_section_sp->GetChildren().FindSectionByName( + g_section_name_lldb_no_nlist); + } else { + eh_frame_section_sp = + section_list->FindSectionByName(g_section_name_eh_frame); + lldb_no_nlist_section_sp = + section_list->FindSectionByName(g_section_name_lldb_no_nlist); + } if (process && m_header.filetype != llvm::MachO::MH_OBJECT && !is_local_shared_cache_image) { @@ -2403,6 +2439,14 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) { memory_module_load_level = target.GetMemoryModuleLoadLevel(); + // If __TEXT,__lldb_no_nlist section is present in this binary, + // and we're reading it out of memory, do not read any of the + // nlist entries. They are not needed in lldb and it may be + // expensive to load these. This is to handle a dylib consisting + // of only metadata, no code, but it has many nlist entries. + if (lldb_no_nlist_section_sp) + memory_module_load_level = eMemoryModuleLoadLevelMinimal; + // Reading mach file from memory in a process or core file... if (linkedit_section_sp) { @@ -2526,30 +2570,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) { const bool have_strtab_data = strtab_data.GetByteSize() > 0; - ConstString g_segment_name_TEXT = GetSegmentNameTEXT(); - ConstString g_segment_name_DATA = GetSegmentNameDATA(); - ConstString g_segment_name_DATA_DIRTY = GetSegmentNameDATA_DIRTY(); - ConstString g_segment_name_DATA_CONST = GetSegmentNameDATA_CONST(); - ConstString g_segment_name_OBJC = GetSegmentNameOBJC(); - 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 data_dirty_section_sp( - section_list->FindSectionByName(g_segment_name_DATA_DIRTY)); - SectionSP data_const_section_sp( - section_list->FindSectionByName(g_segment_name_DATA_CONST)); - 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); - const bool is_arm = (m_header.cputype == llvm::MachO::CPU_TYPE_ARM); const bool always_thumb = GetArchitecture().IsAlwaysThumbInstructions(); diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index 27b2078b5a3fc..7f67f5e04f1d6 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -286,6 +286,7 @@ class ObjectFileMachO : public lldb_private::ObjectFile { static lldb_private::ConstString GetSegmentNameDWARF(); static lldb_private::ConstString GetSegmentNameLLVM_COV(); static lldb_private::ConstString GetSectionNameEHFrame(); + static lldb_private::ConstString GetSectionNameLLDBNoNlist(); llvm::MachO::dysymtab_command m_dysymtab; std::vector m_mach_sections; diff --git a/lldb/test/API/macosx/no-nlist-memory-module/Makefile b/lldb/test/API/macosx/no-nlist-memory-module/Makefile new file mode 100644 index 0000000000000..8271c3165ef07 --- /dev/null +++ b/lldb/test/API/macosx/no-nlist-memory-module/Makefile @@ -0,0 +1,19 @@ +C_SOURCES := main.c +LD_EXTRAS = -Wl,-rpath "-Wl,$(shell pwd)" -L. -lno-nlists -lhas-nlists + +.PHONY: build-libno-nlists build-libhas-nlists +all: build-libno-nlists build-libhas-nlists a.out + +include Makefile.rules + +build-libno-nlists: no-nlists.c no-nlist-sect.s + $(CC) $(CFLAGS) -c -o no-nlists.o $( +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int get_return_value(); +int get_return_value2(); + +// Create \a file_name with the c-string of our +// pid in it. Initially open & write the contents +// to a temporary file, then move it to the actual +// filename once writing is completed. +bool writePid(const char *file_name, const pid_t pid) { + char *tmp_file_name = (char *)malloc(strlen(file_name) + 16); + strcpy(tmp_file_name, file_name); + strcat(tmp_file_name, "_tmp"); + int fd = open(tmp_file_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) { + fprintf(stderr, "open(%s) failed: %s\n", tmp_file_name, strerror(errno)); + free(tmp_file_name); + return false; + } + char buffer[64]; + snprintf(buffer, sizeof(buffer), "%ld", (long)pid); + bool res = true; + if (write(fd, buffer, strlen(buffer)) == -1) { + fprintf(stderr, "write(%s) failed: %s\n", buffer, strerror(errno)); + res = false; + } + close(fd); + + if (rename(tmp_file_name, file_name) == -1) { + fprintf(stderr, "rename(%s, %s) failed: %s\n", tmp_file_name, file_name, + strerror(errno)); + res = false; + } + free(tmp_file_name); + + return res; +} + +int main(int argc, char **argv) { + if (writePid(argv[1], getpid())) { + // we've signaled lldb we are ready to be attached to, + // this sleep() call will be interrupted when lldb + // attaches. + sleep(200); + } else { + printf("Error writing pid to '%s', exiting.\n", argv[1]); + exit(3); + } + + int retval = get_return_value(); + return retval + get_return_value2(); +} diff --git a/lldb/test/API/macosx/no-nlist-memory-module/no-nlist-sect.s b/lldb/test/API/macosx/no-nlist-memory-module/no-nlist-sect.s new file mode 100644 index 0000000000000..0a7c974f9362c --- /dev/null +++ b/lldb/test/API/macosx/no-nlist-memory-module/no-nlist-sect.s @@ -0,0 +1,3 @@ + .section __TEXT,__lldb_no_nlist,regular,pure_instructions + .p2align 2 + .byte 0x10 diff --git a/lldb/test/API/macosx/no-nlist-memory-module/no-nlists.c b/lldb/test/API/macosx/no-nlist-memory-module/no-nlists.c new file mode 100644 index 0000000000000..ff81940087ab7 --- /dev/null +++ b/lldb/test/API/macosx/no-nlist-memory-module/no-nlists.c @@ -0,0 +1 @@ +int get_return_value() { return 10; }