Signed-off-by: Denys Vlasenko dvlasenk@redhat.com --- src/plugins/abrt-gdb-exploitable | 60 ++++++++++++++++++++++++++++++++++++++-- tests/abrt-exploitable/Makefile | 4 +-- 2 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/src/plugins/abrt-gdb-exploitable b/src/plugins/abrt-gdb-exploitable index f33ec45..1f33061 100755 --- a/src/plugins/abrt-gdb-exploitable +++ b/src/plugins/abrt-gdb-exploitable @@ -371,6 +371,62 @@ class SignalAndInsn: self.instruction_is_store = self.x86_instruction_is_store()
+ def ppc_get_instruction(self): + try: + # just "disassemble $pc" won't work if $pc doesn't point + # inside a known function + raw_instructions = gdb.execute("disassemble $pc,$pc+32", to_string=True) + except gdb.error: + # For example, if tracee already exited normally. + # Another observed case is if $pc points to unmapped area. + # We get "Python Exception <class 'gdb.error'> No registers" + return + + instructions = [] + current = None + for line in raw_instructions.split("\n"): + # line can be: + # "Dump of assembler code from 0xAAAA to 0xBBBB:" + # "[=>] 0x00000000004004dc[ <+0>]: push %rbp" + # (" <+0>" part is present when we run on a live process, + # on coredump it is absent) + # "End of assembler dump." + # "" (empty line) + if line.startswith("=>"): + line = line[2:] + current = len(instructions) + line = line.split(":", 1) + if len(line) < 2: # no ":"? + continue + line = line[1] # drop "foo:" + line = line.strip() # drop leading/trailing whitespace + if line: + instructions.append(line) + if current == None: + # we determined that $pc points to a bad address, + # which is an interesting fact. + return + + # There can be a disasm comment: "insn op,op,op # comment"; + # strip it, and whitespace on both ends: + t = instructions[current].split("#", 1)[0].strip() + self.current_instruction = t + # Split it into mnemonic and operands + t = t.split(None, 1) + self.mnemonic = t[0] + if len(t) > 1: + self.operands = t[1] + + self.instruction_is_store = self.mnemonic.startswith("st") + self.instruction_is_branch = self.mnemonic.startswith("b") + self.instruction_is_pushing = (self.instruction_is_store and "(r1)" in self.operands) + # Looks like div[o] insns on ppc don't cause exceptions + # (need to check whether, and how, FPE is generated) + #self.instruction_is_division = + # On ppc, return insn is b[cond]lr. TODO: is cond form ever used by gcc? + self.instruction_is_return = (self.mnemonic == "blr") + + def get_instruction(self): self.current_instruction = None self.mnemonic = None @@ -388,8 +444,8 @@ class SignalAndInsn: # The target architecture is set automatically (currently powerpc:common64) if " i386" in arch: return self.x86_get_instruction() - #if " powerpc" in arch: - # return self.ppc_get_instruction() + if " powerpc" in arch: + return self.ppc_get_instruction() except gdb.error: return
diff --git a/tests/abrt-exploitable/Makefile b/tests/abrt-exploitable/Makefile index 6672fe3..9df463c 100644 --- a/tests/abrt-exploitable/Makefile +++ b/tests/abrt-exploitable/Makefile @@ -34,7 +34,7 @@ all: $(TESTS) clean: rm -f $(TESTS)
-testlive: +testlive: all for t in $(TESTS); do \ echo "====="; \ echo "Test: $$t"; \ @@ -48,7 +48,7 @@ testlive: ./$$t; \ done 2>&1 | tee testlive.log
-testcore: +testcore: all rm ./core* 2>/dev/null; \ ulimit -c unlimited; \ for t in $(TESTS); do \