首页 > 其他分享 >0161-GDB 调试实模式

0161-GDB 调试实模式

时间:2023-01-31 16:57:31浏览次数:64  
标签:set end addr 0161 GDB eflags printf found 调试

环境

  • Time 2022-11-08
  • WSL-Ubuntu 22.04
  • QEMU 6.2.0
  • NASM 2.15.05

前言

说明

参考:《x86汇编语言:从实模式到保护模式》李忠
参考:https://astralvx.com/debugging-16-bit-in-qemu-with-gdb-on-windows/

目标

使用 GDB 调试十六位的汇编代码。

实模式

在 8086 CPU 加电执行完 ROM 之后,进入的是实模式。访问的内存地址对应真实的物理地址。
访问方式是通过段地址 * 16 + 偏移地址的方式来访问。不过 GDB 不支持段地址访问,所以需要特别适配。

下载需要的文件

一共需要下载三个文件,如果不能访问,附录中有原文:

  1. https://astralvx.com/storage/2021/05/gdb_init_real_mode.txt
  2. https://astralvx.com/storage/2021/05/target.xml
  3. https://astralvx.com/storage/2021/05/i386-32bit.xml

启动脚本

#! /usr/bin/bash

gdb -ix "gdb_init_real_mode.txt" \
    -ex "set tdesc filename target.xml" \
    -ex "target remote localhost:1234" \
    -ex "br *0x7c00" -ex "c"

这个脚本启动后,会自动切换到 16 位模式,并且打印各种寄存器的信息。
会自动跳转到 0x7c00 断点处。

调试实模式

mov al,4
mov ax,0x4444

times 510 - $ + $$ db 0
db 0x55
db 0xaa

调试实模式

总结

使用 GDB 来调试实模式,通过下载三个文件来完成配置,并显示出来各种寄存器的信息。

附录

target.xml

<?xml version="1.0"?><!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
    <architecture>i8086</architecture>
    <xi:include href="i386-32bit.xml"/>

i386-32bit.xml

<?xml version="1.0"?>
<!-- Copyright (C) 2010-2017 Free Software Foundation, Inc.

     Copying and distribution of this file, with or without modification,
     are permitted in any medium without royalty provided the copyright
     notice and this notice are preserved.  -->

<!-- I386 with SSE -->

<!DOCTYPE target SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.i386.core">
  <flags id="i386_eflags" size="4">
        <field name="" start="22" end="31"/>
        <field name="ID" start="21" end="21"/>
        <field name="VIP" start="20" end="20"/>
        <field name="VIF" start="19" end="19"/>
        <field name="AC" start="18" end="18"/>
        <field name="VM" start="17" end="17"/>
        <field name="RF" start="16" end="16"/>
        <field name="" start="15" end="15"/>
        <field name="NT" start="14" end="14"/>
        <field name="IOPL" start="12" end="13"/>
        <field name="OF" start="11" end="11"/>
        <field name="DF" start="10" end="10"/>
        <field name="IF" start="9" end="9"/>
        <field name="TF" start="8" end="8"/>
        <field name="SF" start="7" end="7"/>
        <field name="ZF" start="6" end="6"/>
        <field name="" start="5" end="5"/>
        <field name="AF" start="4" end="4"/>
        <field name="" start="3" end="3"/>
        <field name="PF" start="2" end="2"/>
        <field name="" start="1" end="1"/>
        <field name="CF" start="0" end="0"/>
  </flags>

  <reg name="eax" bitsize="32" type="int32" regnum="0"/>
  <reg name="ecx" bitsize="32" type="int32"/>
  <reg name="edx" bitsize="32" type="int32"/>
  <reg name="ebx" bitsize="32" type="int32"/>
  <reg name="esp" bitsize="32" type="data_ptr"/>
  <reg name="ebp" bitsize="32" type="data_ptr"/>
  <reg name="esi" bitsize="32" type="int32"/>
  <reg name="edi" bitsize="32" type="int32"/>

  <reg name="eip" bitsize="32" type="code_ptr"/>
  <reg name="eflags" bitsize="32" type="i386_eflags"/>

  <reg name="cs" bitsize="32" type="int32"/>
  <reg name="ss" bitsize="32" type="int32"/>
  <reg name="ds" bitsize="32" type="int32"/>
  <reg name="es" bitsize="32" type="int32"/>
  <reg name="fs" bitsize="32" type="int32"/>
  <reg name="gs" bitsize="32" type="int32"/>

  <!-- Segment descriptor caches and TLS base MSRs -->

  <!--reg name="cs_base" bitsize="32" type="int32"/>
  <reg name="ss_base" bitsize="32" type="int32"/>
  <reg name="ds_base" bitsize="32" type="int32"/>
  <reg name="es_base" bitsize="32" type="int32"/-->
  <reg name="fs_base" bitsize="32" type="int32"/>
  <reg name="gs_base" bitsize="32" type="int32"/>
  <reg name="k_gs_base" bitsize="32" type="int32"/>

  <flags id="i386_cr0" size="4">
        <field name="PG" start="31" end="31"/>
        <field name="CD" start="30" end="30"/>
        <field name="NW" start="29" end="29"/>
        <field name="AM" start="18" end="18"/>
        <field name="WP" start="16" end="16"/>
        <field name="NE" start="5" end="5"/>
        <field name="ET" start="4" end="4"/>
        <field name="TS" start="3" end="3"/>
        <field name="EM" start="2" end="2"/>
        <field name="MP" start="1" end="1"/>
        <field name="PE" start="0" end="0"/>
  </flags>

  <flags id="i386_cr3" size="4">
        <field name="PDBR" start="12" end="31"/>
        <!--field name="" start="3" end="11"/>
        <field name="WT" start="2" end="2"/>
        <field name="CD" start="1" end="1"/>
        <field name="" start="0" end="0"/-->
        <field name="PCID" start="0" end="11"/>
  </flags>

  <flags id="i386_cr4" size="4">
        <field name="VME" start="0" end="0"/>
        <field name="PVI" start="1" end="1"/>
        <field name="TSD" start="2" end="2"/>
        <field name="DE" start="3" end="3"/>
        <field name="PSE" start="4" end="4"/>
        <field name="PAE" start="5" end="5"/>
        <field name="MCE" start="6" end="6"/>
        <field name="PGE" start="7" end="7"/>
        <field name="PCE" start="8" end="8"/>
        <field name="OSFXSR" start="9" end="9"/>
        <field name="OSXMMEXCPT" start="10" end="10"/>
        <field name="UMIP" start="11" end="11"/>
        <field name="LA57" start="12" end="12"/>
        <field name="VMXE" start="13" end="13"/>
        <field name="SMXE" start="14" end="14"/>
        <field name="FSGSBASE" start="16" end="16"/>
        <field name="PCIDE" start="17" end="17"/>
        <field name="OSXSAVE" start="18" end="18"/>
        <field name="SMEP" start="20" end="20"/>
        <field name="SMAP" start="21" end="21"/>
        <field name="PKE" start="22" end="22"/>
  </flags>

  <flags id="i386_efer" size="8">
        <field name="TCE" start="15" end="15"/>
        <field name="FFXSR" start="14" end="14"/>
        <field name="LMSLE" start="13" end="13"/>
        <field name="SVME" start="12" end="12"/>
        <field name="NXE" start="11" end="11"/>
        <field name="LMA" start="10" end="10"/>
        <field name="LME" start="8" end="8"/>
        <field name="SCE" start="0" end="0"/>
  </flags>

  <reg name="cr0" bitsize="32" type="i386_cr0"/>
  <reg name="cr2" bitsize="32" type="int32"/>
  <reg name="cr3" bitsize="32" type="i386_cr3"/>
  <reg name="cr4" bitsize="32" type="i386_cr4"/>
  <reg name="cr8" bitsize="32" type="int32"/>
  <reg name="efer" bitsize="32" type="i386_efer"/>

  <reg name="st0" bitsize="80" type="i387_ext"/>
  <reg name="st1" bitsize="80" type="i387_ext"/>
  <reg name="st2" bitsize="80" type="i387_ext"/>
  <reg name="st3" bitsize="80" type="i387_ext"/>
  <reg name="st4" bitsize="80" type="i387_ext"/>
  <reg name="st5" bitsize="80" type="i387_ext"/>
  <reg name="st6" bitsize="80" type="i387_ext"/>
  <reg name="st7" bitsize="80" type="i387_ext"/>

  <reg name="fctrl" bitsize="32" type="int" group="float"/>
  <reg name="fstat" bitsize="32" type="int" group="float"/>
  <reg name="ftag" bitsize="32" type="int" group="float"/>
  <reg name="fiseg" bitsize="32" type="int" group="float"/>
  <reg name="fioff" bitsize="32" type="int" group="float"/>
  <reg name="foseg" bitsize="32" type="int" group="float"/>
  <reg name="fooff" bitsize="32" type="int" group="float"/>
  <reg name="fop" bitsize="32" type="int" group="float"/>
<!--/feature>
<feature name="org.gnu.gdb.i386.32bit.sse"-->
  <vector id="v4f" type="ieee_single" count="4"/>
  <vector id="v2d" type="ieee_double" count="2"/>
  <vector id="v16i8" type="int8" count="16"/>
  <vector id="v8i16" type="int16" count="8"/>
  <vector id="v4i32" type="int32" count="4"/>
  <vector id="v2i64" type="int64" count="2"/>
  <union id="vec128">
        <field name="v4_float" type="v4f"/>
        <field name="v2_double" type="v2d"/>
        <field name="v16_int8" type="v16i8"/>
        <field name="v8_int16" type="v8i16"/>
        <field name="v4_int32" type="v4i32"/>
        <field name="v2_int64" type="v2i64"/>
        <field name="uint128" type="uint128"/>
  </union>
  <flags id="i386_mxcsr" size="4">
        <field name="IE" start="0" end="0"/>
        <field name="DE" start="1" end="1"/>
        <field name="ZE" start="2" end="2"/>
        <field name="OE" start="3" end="3"/>
        <field name="UE" start="4" end="4"/>
        <field name="PE" start="5" end="5"/>
        <field name="DAZ" start="6" end="6"/>
        <field name="IM" start="7" end="7"/>
        <field name="DM" start="8" end="8"/>
        <field name="ZM" start="9" end="9"/>
        <field name="OM" start="10" end="10"/>
        <field name="UM" start="11" end="11"/>
        <field name="PM" start="12" end="12"/>
        <field name="FZ" start="15" end="15"/>
  </flags>

  <reg name="xmm0" bitsize="128" type="vec128"/>
  <reg name="xmm1" bitsize="128" type="vec128"/>
  <reg name="xmm2" bitsize="128" type="vec128"/>
  <reg name="xmm3" bitsize="128" type="vec128"/>
  <reg name="xmm4" bitsize="128" type="vec128"/>
  <reg name="xmm5" bitsize="128" type="vec128"/>
  <reg name="xmm6" bitsize="128" type="vec128"/>
  <reg name="xmm7" bitsize="128" type="vec128"/>

  <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/>

gdb_init_real_mode.txt

# Special mode for GDB that allows to debug/disassemble REAL MODE x86 code
#
# It has been designed to be used with QEMU or BOCHS gdb-stub
#
# 08/2011 Hugo Mercier - GPL v3 license
#
# Freely inspired from "A user-friendly gdb configuration file" widely available
# on the Internet

set confirm off
set verbose off
set prompt \033[31mreal-mode-gdb$ \033[0m

set output-radix 0d10
set input-radix 0d10

# These make gdb never pause in its output
set height 0
set width 0

# Intel syntax
set disassembly-flavor intel
# Real mode
#set architecture i8086

set $SHOW_CONTEXT = 1

set $REAL_MODE = 1

# By default A20 is present
set $ADDRESS_MASK = 0x1FFFFF

# nb of instructions to display
set $CODE_SIZE = 10

define enable-a20
  set $ADDRESS_MASK = 0x1FFFFF
end
define disable-a20
  set $ADDRESS_MASK = 0x0FFFFF
end

# convert segment:offset address to physical address
define r2p
  if $argc < 2
    printf "Arguments: segment offset\n"
  else
    set $ADDR = (((unsigned long)$arg0 & 0xFFFF) << 4) + (((unsigned long)$arg1 & 0xFFFF) & $ADDRESS_MASK)
    printf "0x%05X\n", $ADDR
  end
end
document r2p
Convert segment:offset address to physical address
Set the global variable $ADDR to the computed one
end

# get address of Interruption
define int_addr
  if $argc < 1
    printf "Argument: interruption_number\n"
  else
    set $offset = (unsigned short)*($arg0 * 4)
    set $segment = (unsigned short)*($arg0 * 4 + 2)
    r2p $segment $offset
    printf "%04X:%04X\n", $segment, $offset
  end
end
document int_addr
Get address of interruption
end

define compute_regs
  set $rax = ((unsigned long)$eax & 0xFFFF)
  set $rbx = ((unsigned long)$ebx & 0xFFFF)
  set $rcx = ((unsigned long)$ecx & 0xFFFF)
  set $rdx = ((unsigned long)$edx & 0xFFFF)
  set $rsi = ((unsigned long)$esi & 0xFFFF)
  set $rdi = ((unsigned long)$edi & 0xFFFF)
  set $rbp = ((unsigned long)$ebp & 0xFFFF)
  set $rsp = ((unsigned long)$esp & 0xFFFF)
  set $rcs = ((unsigned long)$cs & 0xFFFF)
  set $rds = ((unsigned long)$ds & 0xFFFF)
  set $res = ((unsigned long)$es & 0xFFFF)
  set $rss = ((unsigned long)$ss & 0xFFFF)
  set $rip = ((((unsigned long)$cs & 0xFFFF) << 4) + ((unsigned long)$eip & 0xFFFF)) & $ADDRESS_MASK
  set $r_ss_sp = ((((unsigned long)$ss & 0xFFFF) << 4) + ((unsigned long)$esp & 0xFFFF)) & $ADDRESS_MASK
  set $r_ss_bp = ((((unsigned long)$ss & 0xFFFF) << 4) + ((unsigned long)$ebp & 0xFFFF)) & $ADDRESS_MASK
end

define print_regs
  printf "AX: %04X BX: %04X ", $rax, $rbx
  printf "CX: %04X DX: %04X\n", $rcx, $rdx
  printf "SI: %04X DI: %04X ", $rsi, $rdi
  printf "SP: %04X BP: %04X\n", $rsp, $rbp
  printf "CS: %04X DS: %04X ", $rcs, $rds
  printf "ES: %04X SS: %04X\n", $res, $rss
  printf "\n"
  printf "IP: %04X EIP:%08X\n", ((unsigned short)$eip & 0xFFFF), $eip
  printf "CS:IP: %04X:%04X (0x%05X)\n", $rcs, ((unsigned short)$eip & 0xFFFF), $rip
  printf "SS:SP: %04X:%04X (0x%05X)\n", $rss, $rsp, $r_ss_sp
  printf "SS:BP: %04X:%04X (0x%05X)\n", $rss, $rbp, $r_ss_bp
end
document print_regs
Print CPU registers
end

define print_eflags
    printf "OF <%d>  DF <%d>  IF <%d>  TF <%d>",\
           (($eflags >> 0xB) & 1), (($eflags >> 0xA) & 1), \
           (($eflags >> 9) & 1), (($eflags >> 8) & 1)
    printf "  SF <%d>  ZF <%d>  AF <%d>  PF <%d>  CF <%d>\n",\
           (($eflags >> 7) & 1), (($eflags >> 6) & 1),\
           (($eflags >> 4) & 1), (($eflags >> 2) & 1), ($eflags & 1)
    printf "ID <%d>  VIP <%d> VIF <%d> AC <%d>",\
           (($eflags >> 0x15) & 1), (($eflags >> 0x14) & 1), \
           (($eflags >> 0x13) & 1), (($eflags >> 0x12) & 1)
    printf "  VM <%d>  RF <%d>  NT <%d>  IOPL <%d>\n",\
           (($eflags >> 0x11) & 1), (($eflags >> 0x10) & 1),\
           (($eflags >> 0xE) & 1), (($eflags >> 0xC) & 3)
end
document print_eflags
Print eflags register.
end

# dump content of bytes in memory
# arg0 : addr
# arg1 : nb of bytes
define _dump_memb
  if $argc < 2
    printf "Arguments: address number_of_bytes\n"
  else
    set $_nb = $arg1
    set $_i = 0
    set $_addr = $arg0
    while ($_i < $_nb)
      printf "%02X ", *((unsigned char*)$_addr + $_i)
      set $_i++
    end
  end
end

# dump content of memory in words
# arg0 : addr
# arg1 : nb of words
define _dump_memw
  if $argc < 2
    printf "Arguments: address number_of_words\n"
  else
    set $_nb = $arg1
    set $_i = 0
    set $_addr = $arg0
    while ($_i < $_nb)
      printf "%04X ", *((unsigned short*)$_addr + $_i)
      set $_i++
    end
  end
end

# display data at given address
define print_data
       if ($argc > 0)
          set $seg = $arg0
      set $off = $arg1
      set $raddr = ($arg0 << 16) + $arg1
      set $maddr = ($arg0 << 4) + $arg1

      set $w = 16
      set $i = (int)0
      while ($i < 4)
        printf "%08X: ", ($raddr + $i * $w)
        set $j = (int)0
        while ($j < $w)
              printf "%02X ", *(unsigned char*)($maddr + $i * $w + $j)
              set $j++
        end
        printf " "
        set $j = (int)0
        while ($j < $w)
              set $c = *(unsigned char*)($maddr + $i * $w + $j)
              if ($c > 32) && ($c < 128)
                 printf "%c", $c
              else
            printf "."
              end
              set $j++
        end
        printf "\n"
        set $i++
      end


       end
end

define context
  printf "---------------------------[ STACK ]---\n"
  _dump_memw $r_ss_sp 8
  printf "\n"
  set $_a = $r_ss_sp + 16
  _dump_memw $_a 8
  printf "\n"
  printf "---------------------------[ DS:SI ]---\n"
  print_data $ds $rsi
  printf "---------------------------[ ES:DI ]---\n"
  print_data $es $rdi

  printf "----------------------------[ CPU ]----\n"
  print_regs
  print_eflags
  printf "---------------------------[ CODE ]----\n"

  set $_code_size = $CODE_SIZE

  # disassemble
  # first call x/i with an address
  # subsequent calls to x/i will increment address
  if ($_code_size > 0)
    x /i $rip
    set $_code_size--
  end
  while ($_code_size > 0)
    x /i
    set $_code_size--
  end
end
document context
Print context window, i.e. regs, stack, ds:esi and disassemble cs:eip.
end

define hook-stop
  compute_regs
  if ($SHOW_CONTEXT > 0)
    context
  end
end
document hook-stop
!!! FOR INTERNAL USE ONLY - DO NOT CALL !!!
end

# add a breakpoint on an interrupt
define break_int
    set $offset = (unsigned short)*($arg0 * 4)
    set $segment = (unsigned short)*($arg0 * 4 + 2)

    break *$offset
end

define break_int_if_ah
  if ($argc < 2)
    printf "Arguments: INT_N AH\n"
  else
    set $addr = (unsigned short)*($arg0 * 4)
    set $segment = (unsigned short)*($arg0 * 4 + 2)
    break *$addr if ((unsigned long)$eax & 0xFF00) == ($arg1 << 8)
  end
end
document break_int_if_ah
Install a breakpoint on INT N only if AH is equal to the expected value
end

define break_int_if_ax
  if ($argc < 2)
    printf "Arguments: INT_N AX\n"
  else
    set $addr = (unsigned short)*($arg0 * 4)
    set $segment = (unsigned short)*($arg0 * 4 + 2)
    break *$addr if ((unsigned long)$eax & 0xFFFF) == $arg1
  end
end
document break_int_if_ax
Install a breakpoint on INT N only if AX is equal to the expected value
end

define stepo
  ## we know that an opcode starting by 0xE8 has a fixed length
  ## for the 0xFF opcodes, we can enumerate what is possible to have

  set $lip = $rip
  set $offset = 0

  # first, get rid of segment prefixes, if any
  set $_byte1 = *(unsigned char *)$rip
  # CALL DS:xx CS:xx, etc.
  if ($_byte1 == 0x3E || $_byte1 == 0x26 || $_byte1 == 0x2E || $_byte1 == 0x36 || $_byte1 == 0x3E || $_byte1 == 0x64 || $_byte1 == 0x65)
    set $lip = $rip + 1
    set $_byte1 = *(unsigned char*)$lip
    set $offset = 1
  end
  set $_byte2 = *(unsigned char *)($lip+1)
  set $_byte3 = *(unsigned char *)($lip+2)

  set $noffset = 0

  if ($_byte1 == 0xE8)
    # call near
    set $noffset = 3
  else
    if ($_byte1 == 0xFF)
      # A "ModR/M" byte follows
      set $_mod = ($_byte2 & 0xC0) >> 6
      set $_reg = ($_byte2 & 0x38) >> 3
      set $_rm  = ($_byte2 & 7)
      #printf "mod: %d reg: %d rm: %d\n", $_mod, $_reg, $_rm

      # only for CALL instructions
      if ($_reg == 2 || $_reg == 3)

    # default offset
    set $noffset = 2

    if ($_mod == 0)
      if ($_rm == 6)
        # a 16bit address follows
        set $noffset = 4
      end
    else
      if ($_mod == 1)
        # a 8bit displacement follows
        set $noffset = 3
      else
        if ($_mod == 2)
          # 16bit displacement
          set $noffset = 4
        end
      end
    end

      end
      # end of _reg == 2 or _reg == 3

    else
      # else byte1 != 0xff
      if ($_byte1 == 0x9A)
    # call far
    set $noffset = 5
      else
    if ($_byte1 == 0xCD)
      # INTERRUPT CASE
      set $noffset = 2
    end
      end

    end
    # end of byte1 == 0xff
  end
  # else byte1 != 0xe8

  # if we have found a call to bypass we set a temporary breakpoint on next instruction and continue
  if ($noffset != 0)
    set $_nextaddress = $eip + $offset + $noffset
    printf "Setting BP to %04X\n", $_nextaddress
    tbreak *$_nextaddress
    continue
    # else we just single step
  else
    nexti
  end
end
document stepo
Step over calls
This function will set a temporary breakpoint on next instruction after the call so the call will be bypassed
You can safely use it instead nexti since it will single step code if it's not a call instruction (unless you want to go into the call function)
end

define step_until_iret
  set $SHOW_CONTEXT=0
  set $_found = 0
  while (!$_found)
    if (*(unsigned char*)$rip == 0xCF)
      set $_found = 1
    else
      stepo
    end
  end
  set $SHOW_CONTEXT=1
  context
end

define step_until_ret
  set $SHOW_CONTEXT=0
  set $_found = 0
  while (!$_found)
    set $_p = *(unsigned char*)$rip
    if ($_p == 0xC3 || $_p == 0xCB || $_p == 0xC2 || $_p == 0xCA)
      set $_found = 1
    else
      stepo
    end
  end
  set $SHOW_CONTEXT=1
  context
end

define step_until_int
  set $SHOW_CONTEXT = 0

  while (*(unsigned char*)$rip != 0xCD)
    stepo
  end
  set $SHOW_CONTEXT = 1
  context
end

# Find a pattern in memory
# The pattern is given by a string as arg0
# If another argument is present it gives the starting address (0 otherwise)
define find_in_mem
  if ($argc >= 2)
    set $_addr = $arg1
  else
    set $_addr = 0
  end
  set $_found = 0
  set $_tofind = $arg0
  while ($_addr < $ADDRESS_MASK) && (!$_found)
    if ($_addr % 0x100 == 0)
      printf "%08X\n", $_addr
    end
    set $_i = 0
    set $_found = 1
    while ($_tofind[$_i] != 0 && $_found == 1)
      set $_b = *((char*)$_addr + $_i)
      set $_t = (char)$_tofind[$_i]
      if ($_t != $_b)
    set $_found = 0
      end
      set $_i++
    end
    if ($_found == 1)
      printf "Code found at 0x%05X\n", $_addr
    end
    set $_addr++
  end
end
document find_in_mem
 Find a pattern in memory
 The pattern is given by a string as arg0
 If another argument is present it gives the starting address (0 otherwise)
end


define step_until_code
  set $_tofind = $arg0
  set $SHOW_CONTEXT = 0

  set $_found = 0
  while (!$_found)
    set $_i = 0
    set $_found = 1

    while ($_tofind[$_i] != 0 && $_found == 1)
      set $_b = *((char*)$rip + $_i)
      set $_t = (char)$_tofind[$_i]
      if ($_t != $_b)
    set $_found = 0
      end
      set $_i++
    end

    if ($_found == 0)
      stepo
    end
  end

  set $SHOW_CONTEXT = 1
  context

标签:set,end,addr,0161,GDB,eflags,printf,found,调试
From: https://www.cnblogs.com/jiangbo4444/p/17079748.html

相关文章

  • 易灵思MIPI CSI 自环调试步骤
    转载自:易灵思MIPICSI自环调试步骤(qq.com)最近在帮助客户分析MIPI的问题,所以有此总结。第一次使用MIPI的人可能不知道怎么在易灵思平台上下手,今天我们来分享下MIPI的......
  • ubuntu18安装gdbm并使用
    查看系统默认的dbm函数接口(posix)$mandbm_open可以看到需要头文件ndbm.h,但到真正编译的时候,你就会发现没有此头文件的! 安装gdbm开发库(兼容dbm和ndbm)$su......
  • 微信小程序跳转到另一个小程序 wx.navigateToMiniProgram 方法,调试
    wx.navigateToMiniProgram(Objectobject)需要页面权限:小程序不能在插件页面中调用该接口,插件也不能在小程序页面中调用该接口打开另一个小程序wx.navigateToMiniPro......
  • 调试技巧
    firstactualcaseofbugbeingfound快捷键f9:设置/取消断点f5:启动调试,经常用于跳到下一个断点f10:逐过程调试,一个过程可以是一个函数,或是一个语句f11:逐语句调......
  • 使用GDB调试python调用的C++共享库
    目录1.首先编写python调用C++的demo2.gdb调试python程序3.全速运行程序4.查看堆栈信息当我们用Python调用C++的库,并且C++库中存在段错误崩溃时,首先想到的还是用gdb......
  • Python和C++联合调试
     python和c++分别在Linux和Windows下联合调试首先创建一个python测试项目和一个c++拓展项目一、在Windows下进行调试1.编译器安装2.C拓展模块安装3.调试......
  • python调用cpp 调试_python和C++联合调试
    python可以利用SO的方式去调用C++中的函数,但是需要一种调试方案来进行python和C++的联合调试,效果是直接在c++代码中打断点,然后python在进行c++so调用的时候,直接进入到断......
  • 一起调试 Python 和 C++
    大多数常规Python调试器支持仅调试Python代码。但是,实际上,Python结合C或C++一起使用时需要高性能或直接调用平台API的能力。(有关演练,请参阅创建适用于Pyth......
  • gdb同时调试python和c++
    说明:当我们的python程序的一些函数的后端实现为C++时(比如Pytorch,TensorFlow或tvm等)可以使用当前方法调试。有两种方式可以安装调试环境:一.搭建环境有两种方式搭建......
  • 深度学习基础课:重构并加入调试日志和测试代码
    大家好~我开设了“深度学习基础班”的线上课程,带领同学从0开始学习全连接和卷积神经网络,进行数学推导,并且实现可以运行的Demo程序线上课程资料:本节课录像回放加QQ群,获得......