-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[lldb][Mach-O] Don't read symbol table of specially marked binary #129967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
6e258eb
350c01d
ae9d9e3
ac2a8e8
1b2b904
ad20aa2
3807c1b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 $(<D)/no-nlists.c | ||
| $(CC) $(CFLAGS) -c -o no-nlist-sect.o $(<D)/no-nlist-sect.s | ||
| $(LD) -dynamiclib -o libno-nlists.dylib no-nlists.o no-nlist-sect.o -install_name "@executable_path/libno-nlists.dylib" | ||
|
|
||
| build-libhas-nlists: has-nlists.c | ||
| $(CC) $(CFLAGS) -c -o has-nlists.o $(<D)/has-nlists.c | ||
| $(LD) -dynamiclib -o libhas-nlists.dylib has-nlists.o -install_name "@executable_path/libhas-nlists.dylib" | ||
|
|
||
| clean:: | ||
| rm -rf has-nlists.o no-nlists.o no-nlist-sect.o main.o main.s a.out a.out.dSYM libno-nlists.dylib libno-nlists.dylib.dSYM libhas-nlists.dylib libhas-nlists.dylib.dSYM | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| """ | ||
| Test that we read don't read the nlist symbols for a specially marked dylib | ||
| when read from memory. | ||
| """ | ||
|
|
||
| import lldb | ||
| from lldbsuite.test.decorators import * | ||
| from lldbsuite.test.lldbtest import * | ||
| from lldbsuite.test import lldbutil | ||
| from time import sleep | ||
|
|
||
|
|
||
| class NoNlistsTestCase(TestBase): | ||
| NO_DEBUG_INFO_TESTCASE = True | ||
|
|
||
| @skipIfRemote | ||
| @skipUnlessDarwin | ||
| def test_no_nlist_symbols(self): | ||
| self.build() | ||
|
|
||
| exe = os.path.realpath(self.getBuildArtifact("a.out")) | ||
|
|
||
| popen = self.spawnSubprocess(exe) | ||
| pid = popen.pid | ||
|
|
||
| self.dbg.SetAsync(False) | ||
|
|
||
| m_no_nlist = lldb.SBModule() | ||
| m_has_nlist = lldb.SBModule() | ||
| target = lldb.SBTarget() | ||
| process = lldb.SBProcess() | ||
| reattach_count = 0 | ||
|
|
||
| # Attach to the process, see if we have a memory module | ||
| # for libno-nlists.dylib and libhas-nlists.dylib. | ||
| # If not, detach, delete the Target, and flush the orphaned | ||
| # modules from the Debugger so we don't hold on to a reference | ||
| # of the on-disk binary. | ||
|
|
||
| # If we haven't succeeded after ten attemps of attaching and | ||
|
||
| # detaching, fail the test. | ||
| while (not m_no_nlist.IsValid() or m_no_nlist.IsFileBacked()) and ( | ||
| not m_has_nlist.IsValid() or m_has_nlist.IsFileBacked() | ||
| ): | ||
| if process.IsValid(): | ||
| process.Detach() | ||
| self.dbg.DeleteTarget(target) | ||
| self.dbg.MemoryPressureDetected() | ||
| time.sleep(2) | ||
|
|
||
| self.runCmd("process attach -p " + str(pid)) | ||
| target = self.dbg.GetSelectedTarget() | ||
| process = target.GetProcess() | ||
| m_no_nlist = target.FindModule(lldb.SBFileSpec("libno-nlists.dylib")) | ||
| m_has_nlist = target.FindModule(lldb.SBFileSpec("libhas-nlists.dylib")) | ||
|
|
||
| reattach_count = reattach_count + 1 | ||
| if reattach_count > 10: | ||
| break | ||
|
|
||
| self.assertTrue(process, PROCESS_IS_VALID) | ||
|
|
||
| # Test that we found libno-nlists.dylib, it is a memory | ||
| # module, and that it has no symbols. | ||
| self.assertTrue(m_no_nlist.IsValid()) | ||
| self.assertFalse(m_no_nlist.IsFileBacked()) | ||
| self.assertEqual(m_no_nlist.GetNumSymbols(), 0) | ||
|
|
||
| # Test that we found libhas-nlists.dylib, it is a memory | ||
| # module, and that it has more than zero symbols. | ||
| self.assertTrue(m_has_nlist.IsValid()) | ||
| self.assertFalse(m_has_nlist.IsFileBacked()) | ||
| self.assertGreater(m_has_nlist.GetNumSymbols(), 0) | ||
|
|
||
| # And as a sanity check, get the main binary's module, | ||
| # test that it is file backed and that it has more than | ||
| # zero symbols. | ||
| m_exe = target.FindModule(lldb.SBFileSpec("a.out")) | ||
| self.assertTrue(m_exe.IsValid()) | ||
| self.assertTrue(m_exe.IsFileBacked()) | ||
| self.assertGreater(m_exe.GetNumSymbols(), 0) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| int get_return_value2() { return 20; } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| #include <libgen.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <sys/param.h> | ||
| #include <sys/stat.h> | ||
| #include <unistd.h> | ||
|
|
||
| int get_return_value(); | ||
| int get_return_value2(); | ||
|
|
||
| int main(int argc, char **argv) { | ||
|
|
||
| // Remove libno-nlists.dylib that we are linked against. | ||
| char executable_path[PATH_MAX]; | ||
| realpath(argv[0], executable_path); | ||
| executable_path[PATH_MAX - 1] = '\0'; | ||
|
|
||
| char *dir = dirname(executable_path); | ||
| char dylib_path[PATH_MAX]; | ||
| snprintf(dylib_path, PATH_MAX, "%s/%s", dir, "libno-nlists.dylib"); | ||
| dylib_path[PATH_MAX - 1] = '\0'; | ||
| struct stat sb; | ||
| if (stat(dylib_path, &sb) == -1) { | ||
| printf("Could not find dylib %s to remove it\n", dylib_path); | ||
| exit(1); | ||
| } | ||
| if (unlink(dylib_path) == -1) { | ||
| printf("Could not remove dylib %s\n", dylib_path); | ||
| exit(2); | ||
| } | ||
| snprintf(dylib_path, PATH_MAX, "%s/%s", dir, "libhas-nlists.dylib"); | ||
| dylib_path[PATH_MAX - 1] = '\0'; | ||
| if (stat(dylib_path, &sb) == -1) { | ||
| printf("Could not find dylib %s to remove it\n", dylib_path); | ||
| exit(1); | ||
| } | ||
| if (unlink(dylib_path) == -1) { | ||
| printf("Could not remove dylib %s\n", dylib_path); | ||
| exit(2); | ||
| } | ||
|
|
||
| // This sleep will exit as soon as lldb attaches | ||
| // and interrupts it. | ||
| sleep(200); | ||
|
|
||
| int retval = get_return_value(); | ||
| return retval + get_return_value2(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .section __TEXT,__lldb_no_nlist,regular,pure_instructions | ||
| .p2align 2 | ||
| .byte 0x10 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| int get_return_value() { return 10; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be easier to
rm -rf *.o *.dSYM *.dylib?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah tbh I don't think we ever even run the clean targets these days, I just stuck this in there out of habit. good suggestion.