djtodoro created this revision. djtodoro added reviewers: labath, JDevlieghere. djtodoro added a project: LLDB. Herald added a subscriber: pengfei. djtodoro requested review of this revision. Herald added a subscriber: lldb-commits.
This patch tries to improve memory-read from core files (in order to improve disassembly functionality). I am using RHEL 7.7 (linux kernel 3.10) and for a lot of cases, I was not able to disassemble some functions from backtrace when debugging crashes from core files. It outputs some dummy code as following: (lldb) disassemble example`fn: 0x55deb51866b0 <+0>: addb %al, (%rax) 0x55deb51866b2 <+2>: addb %al, (%rax) 0x55deb51866b4 <+4>: addb %al, (%rax) 0x55deb51866b6 <+6>: addb %al, (%rax) .... The cause of the problem was the fact we are returning all the zeros from `ProcessElfCore::ReadMemory()` that is being called within `Disassembler::ParseInstructions()` and it disassembles some dummy opcodes from the buffer returned. If we are about to fill the buffer with all zeros, I guess it is safe to just return zero, and to proceed with reading from file itself (using the `ReadMemoryFromFileCache()`) (an alternative is to force/prefer `ReadMemoryFromFileCache()` by settimg `prefer_file_cache` to true before calling `ReadMemory()`). Before this patch (simple example that has been attached into the test): $ lldb lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-for-disassemble.out -c lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-for-disassemble.core (lldb) f 4 frame #4: 0x00007f1d2f862545 libc.so.6`__libc_start_main + 245 libc.so.6`__libc_start_main: -> 0x7f1d2f862545 <+245>: addb %al, (%rax) 0x7f1d2f862547 <+247>: addb %al, (%rax) 0x7f1d2f862549 <+249>: addb %al, (%rax) 0x7f1d2f86254b <+251>: addb %al, (%rax) After this patch applied: (lldb) f 4 frame #4: 0x00007f1d2f862545 libc.so.6`__libc_start_main + 245 libc.so.6`__libc_start_main: -> 0x7f1d2f862545 <+245>: movl %eax, %edi 0x7f1d2f862547 <+247>: callq 0x39d10 ; exit 0x7f1d2f86254c <+252>: xorl %edx, %edx 0x7f1d2f86254e <+254>: jmp 0x22489 ; <+57> GDB was able to disassemble all the functions from core file. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D93939 Files: lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-for-disassemble.core lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-for-disassemble.out Index: lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -155,6 +155,37 @@ self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions, "a.out") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + @skipIfWindows + @skipIfReproducer + def test_frame_disassemble(self): + """Test that we are able to disassemble all the frames""" + disasmtarget = self.dbg.CreateTarget("linux-x86_64-for-disassemble.out") + disasmprocess = disasmtarget.LoadCore("linux-x86_64-for-disassemble.core") + self.assertTrue(disasmprocess, PROCESS_IS_VALID) + + disasmthread = disasmprocess.GetSelectedThread() + framenum = disasmthread.GetNumFrames() + for i in range(framenum): + frame = disasmthread.GetFrameAtIndex(i) + disassembly = frame.Disassemble() + self.assertNotEqual(disassembly, "") + self.assertNotIn("error", disassembly) + # Make sure we don't have some dummy disassembly. + # Each function should start with: + # pushq %rbp + # ... + # Sometimes it just prints some dummy code as: + # addb %al, (%rax) + # addb %al, (%rax) + # ... + pushrbpinstr = disassembly.splitlines()[1] + self.assertNotIn("addb %al, (%rax)", pushrbpinstr) + + self.dbg.DeleteTarget(disasmtarget) + @skipIf(triple='^mips') @skipIfLLVMTargetMissing("X86") def test_FPR_SSE(self): Index: lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp =================================================================== --- lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -384,6 +384,11 @@ if (zero_fill_size) memset(((char *)buf) + bytes_copied, 0, zero_fill_size); + // No data found in the core file, so the buffer contains + // all zeros. + if (zero_fill_size == size) + return 0; + return bytes_copied + zero_fill_size; }
Index: lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -155,6 +155,37 @@ self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions, "a.out") + + @skipIf(triple='^mips') + @skipIfLLVMTargetMissing("X86") + @skipIfWindows + @skipIfReproducer + def test_frame_disassemble(self): + """Test that we are able to disassemble all the frames""" + disasmtarget = self.dbg.CreateTarget("linux-x86_64-for-disassemble.out") + disasmprocess = disasmtarget.LoadCore("linux-x86_64-for-disassemble.core") + self.assertTrue(disasmprocess, PROCESS_IS_VALID) + + disasmthread = disasmprocess.GetSelectedThread() + framenum = disasmthread.GetNumFrames() + for i in range(framenum): + frame = disasmthread.GetFrameAtIndex(i) + disassembly = frame.Disassemble() + self.assertNotEqual(disassembly, "") + self.assertNotIn("error", disassembly) + # Make sure we don't have some dummy disassembly. + # Each function should start with: + # pushq %rbp + # ... + # Sometimes it just prints some dummy code as: + # addb %al, (%rax) + # addb %al, (%rax) + # ... + pushrbpinstr = disassembly.splitlines()[1] + self.assertNotIn("addb %al, (%rax)", pushrbpinstr) + + self.dbg.DeleteTarget(disasmtarget) + @skipIf(triple='^mips') @skipIfLLVMTargetMissing("X86") def test_FPR_SSE(self): Index: lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp =================================================================== --- lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -384,6 +384,11 @@ if (zero_fill_size) memset(((char *)buf) + bytes_copied, 0, zero_fill_size); + // No data found in the core file, so the buffer contains + // all zeros. + if (zero_fill_size == size) + return 0; + return bytes_copied + zero_fill_size; }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits