1. http://www.oracle.com/technetwork/server-storage/solarisstudio/documentation/amd64-dbx-364568.html
  2.  
  3. AMD64 Instruction-Level Debugging With dbx
  4. By Nasser Nouri, May , Revised April
  5.  
  6. Debugging at the machine-instruction level in the Solaris Studio dbx command-line debugger environment becomes very handy when a software bug cannot be found easily. Usually, programs are written in high-level languages such as C, C++, or Fortran, and most of the software defects can be debugged in the dbx environment at the same high level.
  7.  
  8. However, having some knowledge of the machine-instruction level of the system on which the program is running, and using the right tool, such as dbx, can shorten the time to identify the culprit and come up with the optimal solution to fix the defect.
  9.  
  10. This article describes how to use the dbx debugger efficiently on the AMD64 architecture. It describes how to display the contents of memory at specified addresses, and how to display machine instructions. Use the regs command to print out the contents of machine registers or the print command to print out individual registers. Use the nexti, stepi, stopi, and tracei commands to debug at AMD64 machine-instruction level.
  11.  
  12. AMD64 Architecture
  13.  
  14. dbx Commands
  15.  
  16. The Problem Statement
  17.  
  18. The dbx Failure
  19.  
  20. The Debugging Session
  21.  
  22. In Conclusion
  23.  
  24. AMD64 Architecture
  25. First let's review briefly the AMD64 architecture and see how it is different from the 32-bit x86 architecture. I describe only the materials that are relevant to this article. For an in-depth understanding of AMD64 architecture, please refer to AMD64 manuals (http://developer.amd.com) and AMD64 Application Binary Interface (ABI) (http://www.x86-64.org).
  26.  
  27. The AMD64 architecture has sixteen -bit general purpose registers (GPRs): RAX, RBX, RCX, RDX, RBP, RSI, RDI, RSP, R8, R9, R10, R11, R12, R13, R14, and R15. Compared to the x86 architecture, the AMD64 architecture has eight new GPRs.
  28.  
  29. The RAX, RBX, RCX, RDX, RBP, RSI, RDI, and RSP registers are used by both -bit and -bit binaries. However, in -bit mode, only the low bits of these registers are accessible by -bit binaries. In the x86 architecture, these registers are EAX, EBX, ECX, EDX, EBP, ESI, EDI, and ESP, respectively.
  30.  
  31. The AMD64 architecture provides sixteen -bit XMM registers XMM0 through XMM15. Registers XMM0 through XMM7 are used for passing float and double parameters. The long double type is passed in memory. A long double in AMD64 architecture is bytes long compared to bytes in the x86 architecture. The long double type is implemented based on -bit extended (IEEE) standard.
  32.  
  33. The AMD64 architecture also provides eight x87 floating point registers, MMX0/FPR0 through MMX7/FPR7, each bits wide.
  34.  
  35. In contrast to the -bit architecture in which the function parameters are passed on the stack, the -bit architecture has six registers available for integer parameter passing. If the number of integer parameters is more than six, the remaining parameters are passed on the stack.
  36.  
  37. The bool, char, short, int, long, long long, and pointer types are classified as integer class. For passing parameters of the integer class, the next available register of the sequence RDI, RSI, RDX, RCX, R8, and R9 is used.
  38.  
  39. Registers RBP, RBX, and R12 through R15 belong to the calling function, and the called function is required to preserve their values.
  40.  
  41. The RIP register is the instruction pointer register. In -bit mode, the RIP register is extended to bits to support -bit offsets. In -bit x86 architecture, the instruction pointer register is the EIP register.
  42.  
  43. The return value of a function is classified based on the rules that are specified in AMD64 ABI. For instance, if the return value needs to be passed in memory, then the caller provides space for the return value and passes the address of this storage in the RDI register as if it were the first argument to the function. On return, the RAX register contains the address that has been passed by the caller in the RDI register.
  44.  
  45. Similarly, if the return type is integer, the next available register of the sequence RAX, RDX is used.
  46.  
  47. In addition to registers, each function has a frame on the run-time stack. The run-time stack grows downwards from a high address. Table shows the stack organization.
  48.  
  49. Table Stack Frame With Base Pointer
  50. Position
  51. Contents
  52. Frame
  53.  
  54. 8n+ (%rbp)
  55.  
  56. ...
  57.  
  58. (%rbp)
  59.  
  60. (%rbp)
  61.  
  62. (%rbp)
  63. argument #n
  64.  
  65. ...
  66.  
  67. argument #
  68.  
  69. argument #
  70.  
  71. argument #
  72. High address
  73.  
  74. Previous frame
  75.  
  76. (%rbp)
  77. return address
  78. Current frame
  79.  
  80. (%rbp)
  81. previous %rbp value
  82. Current frame
  83.  
  84. - (%rbp)
  85.  
  86. - (%rbp)
  87.  
  88. ...
  89.  
  90. (%rsp)
  91. local variable #
  92.  
  93. local variable #
  94.  
  95. ...
  96.  
  97. local variable #n
  98. Current frame
  99.  
  100. Low address
  101.  
  102. - (%rsp)
  103. red zone
  104.  
  105. The RSP register is the stack pointer register and the RBP register is the frame pointer register. Stack operations make implicit use of the RSP register, and in some cases, the RBP register. The RSP register is decremented when items are pushed onto the stack, and incremented when they are popped off the stack. The RBP register points to the lowest address of the data structure that is passed from one function to another.
  106.  
  107. The -byte area beyond the location pointed to by the RSP register is known as red zone and is considered to be reserved. Functions can use this area for temporary data that is not needed across function calls. In particular, leaf functions can use this area for their entire stack frames, rather than adjusting the stack pointer in the prologue and the epilogue.
  108.  
  109. prologue:
  110. pushq %rbp / save frame pointer
  111. movq %rsp,%rbp / set new frame pointer
  112. subq $,%rsp / allocate stack space
  113. movq %rbx,-(%rbp) / save callee-saved registers
  114. movq %r12,-(%rbp)
  115. movq %r13,-(%rbp)
  116. movq %r14,-(%rbp)
  117. movq %r15,-(%rbp)
  118. There is no need to adjust the RSP stack pointer register if the red zone area is used. In other words, the subq $,%rsp instruction is not needed in function prologue if the red zone area is used.
  119.  
  120. epilogue:
  121. movl -(%rbp), %eax / set up return value
  122. movq -(%rbp),%rbx / restore callee-saved registers
  123. movq -(%rbp),%r12
  124. movq -(%rbp),%r13
  125. movq -(%rbp),%r14
  126. movq -(%rbp),%r15
  127. leave
  128. retThe C++ language has its own Application Binary Interface (ABI). The C++ ABI has well-defined rules for function parameter passing and return values. The C++ ABI rules supplement the AMD64 ABI rules; the C++ compiler has to use the C++ ABI rules for function parameter passing in addition to the AMD64 ABI rules.
  129.  
  130. dbx Commands
  131. The following commands are documented in Solaris Studio 12.2: Debugging a Program With dbx for machine-instruction level debugging.
  132.  
  133. examine [ address ] [ / [ count ] [format ] ]
  134. Display the contents of memory starting at address for count items in format format
  135.  
  136. stepi
  137. Single step one machine instruction (step into calls)
  138.  
  139. nexti
  140. Step one machine instruction (step over calls)
  141.  
  142. listi
  143. Intermix source lines and assembly code
  144.  
  145. tracei
  146. Tracing at the machine-instruction level
  147.  
  148. stopi
  149. Set breakpoints at the machine-instruction level
  150.  
  151. dis
  152. Disassemble instructions, starting at the value of `+'
  153.  
  154. print expression, ...
  155. Print the value of one or more expressions expression, ...
  156.  
  157. regs [-f] [F]
  158. Print value of registers
  159.  
  160. -f: include floating-point registers (single precision)
  161.  
  162. -F: Include floating-point registers (double precision)
  163.  
  164. The Problem Statement
  165. To demonstrate machine-instruction level debugging, let's use a real bug report that was filed against the 64-bit dbx on the AMD64 platform, including a test case. The bug report says “
  166.  
  167. On AMD64 dbx prints hex values instead of letters after strchr call:
  168.  
  169. (dbx) print strchr("hello", 'l') = 0xfffffd7fffdff742 "\xdf\xff^?\xfd\xff\xff^D"Here is the test case:
  170.  
  171. char *b = "hello";
  172. printf("%s\n", b);
  173. printf("%s\n", strchr("hello", 'l'));
  174. }
  175. There is nothing wrong with the program. The bug is in dbx.
  176.  
  177. The dbx Failure
  178. First let's observe the normal flow of the program in the dbx environment by just stepping through the test case code.
  179.  
  180. % dbx a.out
  181. Reading a.out
  182. Reading ld.so.
  183. Reading libc.so.
  184. (dbx) stop in main
  185. () stop in main
  186. (dbx) run
  187.  
  188. Running: a.out
  189. (process id )
  190. stopped in main at line in file "1.c"
  191. char *b = "hello";
  192. (dbx) next
  193. stopped in main at line in file "1.c"
  194. printf("%s\n", b);
  195. (dbx) next
  196. hello
  197. stopped in main at line in file "1.c"
  198. printf("%s\n", strchr("hello", 'l'));
  199. (dbx) next
  200. llo
  201. stopped in main at line in file "1.c"
  202. }
  203. (dbx) next
  204. execution completed, exit code is
  205. The print statement at line calls the strchr() function with two parameters. The strchr() function searches through the first parameter hello and returns a pointer to the first occurrence of the l character. Hence, the llo character string is displayed correctly by the printf statement.
  206.  
  207. Now let's reproduce the failure by calling the strchr() function directly from the dbx command line using the print command. The call command in dbx can also be used to call the strchr() function from the command line.
  208.  
  209. % dbx a.out
  210.  
  211. Reading a.out
  212. Reading ld.so.
  213. Reading libc.so.
  214. (dbx) stop in main
  215. () stop in main
  216. (dbx) run
  217. Running: a.out (process id )
  218. stopped in main at line in file "1.c"<
  219. char *b = "hello";
  220. (dbx) next stopped in main at line in file "1.c"
  221. printf("%s\n", b);
  222. (dbx) next hello
  223. stopped in main at line in file "1.c"
  224. printf("%s\n", strchr("hello", 'l'));
  225. (dbx) print strchr("hello", 'l')strchr("hello", 'l') = 0xfffffd7fffdff742 "\xdf\xff^?\xfd\xff\xff^D"
  226. dbx prints incorrect output when the strchr() function is called by the print command. dbx should display the llo string instead of hex characters, since the call to the strchr() function is supposed to return a pointer to the first occurrence of the l character in the string hello.
  227.  
  228. The Debugging Session
  229. Let's run the debugger with the a.out executable and stop right before the printf statement. The strchr() function is defined in the libc library and most likely is not compiled with the -g option. So there is no debugging information and we have to rely on the assembly code only.
  230.  
  231. The stopi command is used to set a breakpoint at the first machine instruction of the strchr() function.
  232.  
  233. % dbx a.out
  234.  
  235. Reading a.out
  236. Reading ld.so.
  237. Reading libc.so.
  238. (dbx) stop in main
  239. () stop in main
  240. (dbx) run
  241. Running: a.out (process id )
  242. stopped in main at line in file "1.c"
  243. char *b = "hello";
  244. (dbx) next
  245. stopped in main at line in file "1.c"
  246. printf("%s\n", b);
  247. (dbx) next
  248. hello
  249. stopped in main at line in file "1.c"
  250. printf("%s\n", strchr("hello", 'l'));
  251. (dbx) stopi at strchr
  252. () stopi at &strchr
  253. (dbx) print strchr("hello", 'l')stopped in strchr at 0xfffffd7fff307910
  254. 0xfffffd7fff307910: strchr : movb& (%rdi),%dl
  255. dbx stops at the first instruction of the strchr() function after the strchr() function is called from the dbx command line using the print command.
  256.  
  257. The dis command can be used to display the first portion of machine instructions for the strchr() function.
  258.  
  259. (dbx) dis strchr
  260.  
  261. 0xfffffd7fff307910: strchr : movb (%rdi),%dl
  262. 0xfffffd7fff307912: strchr+0x0002: cmpb %dh,%dl
  263. 0xfffffd7fff307915: strchr+0x0005: je strchr+0x3f [0xfffffd7fff30794f, .+0x3a ]
  264. 0xfffffd7fff307917: strchr+0x0007: testb %dl,%dl
  265. 0xfffffd7fff307919: strchr+0x0009: je strchr+0x33 [0xfffffd7fff307943, .+0x2a ]
  266. 0xfffffd7fff30791b: strchr+0x000b: movb 0x0000000000000001(%rdi),%dl
  267. 0xfffffd7fff30791e: strchr+0x000e: mpb %dh,%dl
  268. 0xfffffd7fff307921: strchr+0x0011: je strchr+0x3c [0xfffffd7fff30794c, .+0x2b ]
  269. 0xfffffd7fff307923: strchr+0x0013: testb %dl,%dl
  270. 0xfffffd7fff307925: strchr+0x0015: je strchr+0x33 [0xfffffd7fff307943, .+0x1e ]
  271. The first instruction of the strchr() function is movb (%rdi),%dl, which moves the contents of the memory location pointed to by the %rdi register to the low eight bits of the %rdi register itself. The first instruction is not the pushq %rbp instruction, which means the strchr() function has no prologue. It is not a defect that the function does not have a prologue.
  272.  
  273. The debugger is stopped at the first instruction, which is the right place in the program to verify whether the input parameters are being passed correctly to the strchr() function. The strchr() function has two parameters. The first parameter is a pointer to the memory location that contains the hello character string and the second parameter is the character l. Based on the AMD64 ABI, the first and second parameters are assigned to the %rdi and %rsi registers in sequence. There are two ways to display the content of the %rdi and %rsi registers.
  274.  
  275. You can use the print command to print the contents of the individual registers. The -flx options force dbx to display the contents of the %rdi and %rsi registers in long-hex format.
  276.  
  277. (dbx) print -flx $rdi
  278.  
  279. $rdi = 0xfffffd7fffdff740
  280. (dbx) print -flx $rsi
  281. $rsi = 0x6cYou can use the regs command to display the contents of all of the AMD64 registers.
  282.  
  283. (dbx) regs
  284. current frame: []
  285. r15 0x0000000000000000
  286. r14 0x0000000000000000
  287. r13 0x0000000000000000
  288. r12 0x0000000000000000
  289. r11 0xfffffd7fff307910
  290. r10 0x0000000000000000
  291. r9 0x0000000000010000
  292. r8 0xfefeff6e6b6b6467
  293. rdi 0xfffffd7fffdff740
  294. rsi 0x000000000000006c
  295. rbp 0xfffffd7fffdff810
  296. rbx 0xfffffd7fff3fb190
  297. rdx 0x0000000000000000
  298. rcx 0x000000003f570d87
  299. rax 0x0000000000000000
  300. trapno 0x0000000000000003
  301. err 0x0000000000000000
  302. rip 0xfffffd7fff307910:strchr movb (%rdi),%dl
  303. cs 0x000000000000004b
  304. eflags 0x0000000000000282
  305. rsp 0xfffffd7fffdff738
  306. ss 0x0000000000000043
  307. fs 0x00000000000001bb
  308. gs 0x0000000000000000
  309. es 0x0000000000000000
  310. ds 0x0000000000000000
  311. fsbase 0xfffffd7fff3a2000
  312. gsbase& 0xffffffff80000000
  313. The %rdi register contains a pointer to the memory location 0xfffffd7fffdff740, which is allocated on the stack. In the normal program flow, the %rdi register contains a pointer to the memory location in the data segment. However, when dbx is asked to call a function (strchr()), dbx copies the memory location in the data segment onto the stack and passes the stack address to the %rdi register.
  314.  
  315. The contents of the memory location 0xfffffd7fffdff740 can be verified by using the examine command. The memory location should contain the hello character string.
  316.  
  317. (dbx) examine 0xfffffd7fffdff740 / 20xfffffd7fffdff740: 0x6c6c6568 0x0000006fBy looking up the ASCII table, we can verify that indeed the memory location 0xfffffd7fffdff740 contains the hello character string. The hex number stands for the character h, stands for the character e, 6c stands for the character l, and 6f stands for the character o.
  318.  
  319. You can use the examine command directly to display the contents of the memory location 0xfffffd7fffdff740 as a character string without referring to the ASCII table .
  320.  
  321. (dbx) examine 0xfffffd7fffdff740 / 6c0xfffffd7fffdff740: 'h' 'e' 'l' 'l' 'o' '\0'The %rsi register contains the hex number 6c, which stands for the l character.
  322.  
  323. The other two important registers are the %rsp (the stack pointer) and %rbp (the frame pointer). The %rsp register is pointing to the top of the stack and its value is 0xfffffd7fffdff738. As you can see, this value is very close to the contents of the %rdi register, which is pointing to the memory location on the stack that contains the hello character string.
  324.  
  325. The %rbp register is the frame pointer and contains 0xfffffd7fffdff81 value. The %rbp register is not used in the strchr() function.
  326.  
  327. The contents of the run-time stack can be displayed using the examine command.
  328.  
  329. (dbx) examine 0xfffffd7fffdff738 / lx
  330. 0xfffffd7fffdff738: 0xfffffd7fff220004 0x0000006f6c6c6568
  331. 0xfffffd7fffdff748: 0x0000000000000000 0x0000000000000000
  332. 0xfffffd7fffdff758: 0x0000000000000000 0xfffffd7fffdff7b0
  333. 0xfffffd7fffdff768: 0xfffffd7fff3c7e50 0x0000000000010000
  334. 0xfffffd7fffdff778: 0x0000000000000000 0x0000000000410c50
  335. 0xfffffd7fffdff788: 0x0000000000000000 0xfffffd7fffdff848
  336. 0xfffffd7fffdff798: 0x0000000000410c50 0x0000000000410c58
  337. 0xfffffd7fffdff7a8: 0xfffffd7fff3fb190 0x0000000000000000
  338. 0xfffffd7fffdff7b8: 0x0000000000000000 0xfffffd7fffdff810
  339. 0xfffffd7fffdff7c8: 0x000000000040099d 0x0000000000000000
  340. 0xfffffd7fffdff7d8: 0x0000000000000000 0x0000000000000000
  341. 0xfffffd7fffdff7e8: 0x0000000000000000 0x0000000000000000
  342. 0xfffffd7fffdff7f8: 0xfffffd7fff3fb190 0x0000000000410c50
  343. 0xfffffd7fffdff808: 0xfffffd7fffdff838 0xfffffd7fffdff820
  344. 0xfffffd7fffdff818: 0x000000000040080c 0x0000000000000000
  345. 0xfffffd7fffdff828: 0x0000000000000000 0x0000000000000001
  346. In fact, we can unwind the run-time stack by following the principles that we learned in the previous section (see Table ) about the stack frame with the base pointer. For instance, the hex number 0x40080c is the address of next instruction after the callq instruction. The main function is called from the _start() function using the callq instruction.
  347.  
  348. The hex number 0x40080c is the return address that is pushed onto the stack before the call to the main() function. The instruction at address 0x40080c, push %rax, will be executed upon the completion of the main() function. In other words, the address 0x40080c will be loaded into the program counter, the %rip register, once the main function returns.
  349.  
  350. You can use the objdump utility program to dump the text section of an executable.
  351.  
  352. objdump -S a.out
  353.  
  354. 00000000004007a0 <_start>:
  355.  
  356. 4007a0: 6a pushq $0x0
  357. 4007a2: 6a pushq $0x0
  358. 4007a4: 8b ec mov %rsp,%rbp
  359. 4007a7: 8b fa mov %rdx,%rdi
  360. 4007aa: c7 c0 0a mov $0x410a80,%rax
  361. ...
  362.  
  363. : pop %rcx
  364. : e8 callq <main>
  365. 40080c: push %rax
  366. 40080d: push %rax
  367. ...
  368. The first instruction of the main function is push %rbp. Hence, the previous frame pointer (0xfffffd7fffdff820) is pushed onto the stack right after the return address. Similarly, the return address (0x40099d) is pushed onto the stack when the strchr() function is called from the command line.
  369.  
  370. <main>
  371. : push
  372. : 8b mov %rsp,%rbp
  373. : ec sub $0x40,%rsp
  374. ...
  375.  
  376. 40099d: b8 6c mov $0x6c,%eax
  377. 4009a2: 0f be f0 movsbl %al,%esi
  378. 4009a5: c7 c7 0c mov $0x410c68,%rdi
  379. 4009ac: b8 mov $0x0,%eaxHowever, the strchr() function does not have a function prologue, so the content of %rbp register stays the same when the strchr() function is called from the main() function. The content of %rbp register is the hex value 0xfffffd7fffdff810 and in turn the content of the 0xfffffd7fffdff810 address points to the previous frame pointer 0xfffffd7fffdff820.
  380.  
  381. (dbx) examine 0xfffffd7fffdff810
  382. 0xfffffd7fffdff810: 0xfffffd7fffdff820
  383. Going forward, we single step through the machine instructions using the nexti command until we get to the instruction that returns the return value in the %rax register. We can use the dis command to display the last portion of machine instructions for the strchr() function.
  384.  
  385. (dbx) dis
  386.  
  387. 0xfffffd7fff307941: strchr+0x0031: jne strchr [0xfffffd7fff307910, .-0x31 ]
  388. 0xfffffd7fff307943: strchr+0x0033: xorl %eax,%eax
  389. 0xfffffd7fff307945: strchr+0x0035: ret
  390. 0xfffffd7fff307946: strchr+0x0036: incq %rdi
  391. 0xfffffd7fff307949: strchr+0x0039: incq %rdi
  392. 0xfffffd7fff30794c: strchr+0x003c: incq %rdi
  393. 0xfffffd7fff30794f: strchr+0x003f: movq %rdi,%rax
  394. 0xfffffd7fff307952: strchr+0x0042: ret
  395. 0xfffffd7fff307953: strchr+0x0043: addb %al,(%rax)
  396. (dbx) nexti
  397. stopped in strchr at 0xfffffd7fff307949
  398. 0xfffffd7fff307949:
  399. strchr+0x0039:
  400. incq %rdi
  401. (dbx) nexti
  402. stopped in strchr at 0xfffffd7fff30794c
  403. 0xfffffd7fff30794c: strchr+0x003c: incq %rdi
  404. (dbx) nexti
  405. stopped in strchr at 0xfffffd7fff30794f
  406. 0xfffffd7fff30794f: strchr+0x003f: movq %rdi,%rax
  407. (dbx) nexti
  408. stopped in strchr at 0xfffffd7fff307952
  409. 0xfffffd7fff307952: strchr+0x0042: ret
  410. Based on the description of the strchr() function, at the end it is supposed to return a pointer to the first occurrence of the l character in the string hello. We can verify the correctness of the strchr() function by examining the contents of the %rax register.
  411.  
  412. (dbx) examine $rax / 4c0xfffffd7fffdff742: 'l' 'l' 'o' '\0'
  413. Indeed, the value of the %rax register is a pointer to the memory location 0xfffffd7fffdff742, which is allocated on the stack and contains the llo character string.
  414.  
  415. We have verified that the strchr() function works correctly and returns a pointer to the llo character string in the %rax register. So the problem must be with what dbx does internally after it finishes calling the strchr() function. Fast forward, after calling a user function, dbx always calls the fflush() function to flush the output stream. The fflush() function takes one parameter, which is a pointer to the FILE data structure.
  416.  
  417. fflush - flush a stream
  418. #include <stdio.h>
  419. int fflush(FILE *stream);
  420. You can use the dis command to display the machine instructions for the fflush function.
  421.  
  422. (dbx) dis fflush
  423.  
  424. 0xfffffd7fff33dca0: fflush: pushq %rbp
  425. 0xfffffd7fff33dca1: fflush+0x0001: movq %rsp,%rbp
  426. 0xfffffd7fff33dca4: fflush+0x0004: movq %rbx,0xfffffffffffffff0(%rbp)
  427. 0xfffffd7fff33dca8: fflush+0x0008: movq %r12,0xfffffffffffffff8(%rbp)
  428. 0xfffffd7fff33dcac: fflush+0x000c: subq $0x0000000000000010,%rsp
  429. 0xfffffd7fff33dcb0: fflush+0x0010: testq %rdi,%rdi
  430. 0xfffffd7fff33dcb3: fflush+0x0013: movq %rdi,%rbxLet's go over the fflush function prologue:
  431.  
  432. pushq %rbp
  433. Store the previous frame pointer on the stack.
  434.  
  435. movq %rsp, %rbp
  436. Store the value of the %rsp register or the previous stack pointer into the %rbp register. This value is the new frame pointer for the fflush() function.
  437.  
  438. movq %rbx,0xfffffffffffffff0(%rbp)
  439. movq %r12,0xfffffffffffffff8(%rbp)
  440. The %rbx register and the %r12 register are callee-saved registers. The fflush() function must preserve the contents of these registers on the stack for the caller function so they can be restored later in the function epilogue just before exiting the function.
  441.  
  442. sub $0x0000000000000010,%rsp
  443. Adjust the stack pointer for the fflush() function.
  444.  
  445. The stopi command is used to stop at the first instruction of fflush() function.
  446.  
  447. (dbx) stopi at fflush
  448. (dbx) cont
  449. dbx: Call to 'strchr' completed. Going back to previous command
  450. interpreter
  451. stopped in fflush at 0xfffffd7fff33dca0
  452.  
  453. 0xfffffd7fff33dca0: fflush: pushq %rbp
  454.  
  455. dbx stops at the first instruction of the fflush
  456. Let's display the %rdi, %rbp, and %rspregisters. The %rdi register contains a pointer to the FILE data structure.
  457.  
  458. (dbx) print -flx $rdi
  459.  
  460. $rdi = 0xfffffd7fff37f0a0
  461. (dbx) print -flx $rbp
  462. $rbp = 0xfffffd7fffdff810
  463. (dbx) print -flx $rsp
  464. $rsp = 0xfffffd7fffdff748
  465. We step through the function prologue and print the %rsp and %rbp registers again.
  466.  
  467. (dbx) stepi
  468.  
  469. stopped in fflush at 0xfffffd7fff33dca1
  470. 0xfffffd7fff33dca1: fflush+0x0001: movq %rsp,%rbp
  471. (dbx) stepi
  472. stopped in fflush at 0xfffffd7fff33dca4
  473. 0xfffffd7fff33dca4: fflush+0x0004: movq %rbx,0xfffffffffffffff0(%rbp)
  474. (dbx) stepi
  475. stopped in fflush at 0xfffffd7fff33dca8
  476. 0xfffffd7fff33dca8: fflush+0x0008: movq %r12,0xfffffffffffffff8(%rbp)
  477. (dbx) stepi
  478. stopped in fflush at 0xfffffd7fff33dcac
  479. 0xfffffd7fff33dcac: fflush+0x000c: subq $0x0000000000000010,%rsp
  480. (dbx) stepi
  481. stopped in fflush at 0xfffffd7fff33dcb0
  482. 0xfffffd7fff33dcb0: fflush+0x0010: testq %rdi,%rdi
  483. (dbx) print -flx $rbp
  484. $rbp = 0xfffffd7fffdff740
  485. (dbx) print -flx $rsp
  486.  
  487. $rsp = 0xfffffd7fffdff730
  488. If you can recall from previous section, the run-time stack grows downwards from high address. By careful examination of the %rsp register and comparing its value (0xfffffd7fffdff730) with the last value of the %rsp register (0xfffffd7fffdff738) in the strchr() function, it becomes obvious that the space that is allocated on the stack for the fflush() function overlaps with the space for the strchr() function.
  489.  
  490. The 0xfffffd7fffdff738 value is right between the value of the %rbp register (0xfffffd7fffdff740) and the value of the %rsp register (0xfffffd7fffdff730) of the fflush() function. Therefore, the fflush() function overwrites the contents of the run-time stack for the strchr() function, which explains why the print strchr("hello", 'l') command displays garbage instead of the llo character string.
  491.  
  492. The fix for the dbx debugger is to preserve the contents of the run-time stack just before the call to the fflush() function and restore it just before returning to the print command.
  493.  
  494. In Conclusion
  495. In general, low-level debugging requires the user to have some kind of knowledge about the system on which the program is executing. But once necessary knowledge is learned, even the most difficult bugs can be detected using the low-level debugging techniques and using the right tool, such as dbx
  496.  
  497. You can learn more about the x86 assembly language by referring to the article Assembly Language Techniques for Oracle Solaris x86 Platforms

AMD64 Instruction-Level Debugging With dbx的更多相关文章

  1. debugging books

    https://blogs.msdn.microsoft.com/debuggingtoolbox/2007/06/08/recommended-books-how-to-acquire-or-imp ...

  2. How to Acquire or Improve Debugging Skills

    http://blogs.msdn.com/b/debuggingtoolbox/archive/2007/06/08/recommended-books-how-to-acquire-or-impr ...

  3. linux cpuInfo

    转自:http://blog.csdn.net/lgstudyvc/article/details/7889364   /proc/cpuinfo文件分析 在Linux系统中,提供了proc文件系统显 ...

  4. [转]linux /proc/cpuinfo 文件分析

    在Linux系统中,提供了proc文件系统显示系统的软硬件信息.如果想了解系统中CPU的提供商和相关配置信息,则可以通过/proc/cpuinfo文件得到.本文章针对该文件进行简单的总结. 基于不同指 ...

  5. /proc/cpuinfo zz

    /proc/cpuinfo文件分析 在Linux系统中,提供了proc文件系统显示系统的软硬件信息.如果想了解系统中CPU的提供商和相关配置信息,则可以通过/proc/cpuinfo文件得到.本文章针 ...

  6. Debian 常用命令

    换源 用中科大的比较快 deb http://mirrors.ustc.edu.cn/debian jessie main contrib non-free deb-src http://mirror ...

  7. linux下cpu物理个数、多核、超线程判断解析

    在Linux体系中,供给了proc文件体系显示体系的软硬件信息.若是想懂得体系中CPU的供给商和相干设备信息,则可以经由过程/proc/cpuinfo文件获得.本文章针对该文件进行简单的总结. 基于指 ...

  8. linux系统下cpu信息的查看

    在Linux系统中,提供了proc文件系统显示系统的软硬件信息. 如果想了解系统中CPU的提供商和相关配置信息,则可以通过/proc/cpuinfo文件得到. 基于不同指令集(ISA)的CPU产生的/ ...

  9. 对/proc/cpuinfo文件下的各个参数的说明及实践

    我们通常要检查系统的cpu的相关信息,之前在进行查看cpu的信息的时候,我最长用的方式 是,直接将/etc/cpuinfo下的所有的内容进行显示,然后通过对全部文件的查看,来提取我们需要的信息,虽然查 ...

随机推荐

  1. 基于gRpc的远程服务框架

    作为一个新搭建的软件团队,底层技术尤为重要.为了以后更好的面向不同的项目需求,满足不断变化的需求,决定着手搭建一套RPC系统.为了更好的兼容以后部门其他语言的使用,选择了开源框架gRpc. gRpc ...

  2. set,list,map分析

    想了下集合,列表,映射三者关系 set,list,map ArrayList采用数组方式存储数据,继承List; LinkedList采用链表方式存储数据,继承List; 所以数组方式都有下表,以及每 ...

  3. 从源码分析StringUtils包

    今天用到StringUtils.join方法,闲来无聊,看了下源码 当然不可能自己分析,你傻啊,在这里推荐一个别人分析的; http://blog.csdn.net/baidu_31071595/ar ...

  4. java 内部类的继承

    因为内部类的构造器必须连接到指向其外部类对象的引用. 因为在继承内部类的时候那个指向外部类对象的"秘密的"引用必须被初始化,而在导出类中不再存在可连接的默认对象,要解决这个问题必须 ...

  5. (一) solr的安装与配置

    载solr文件压缩包,并解压 ,要运行solr服务之前需要先安装jdk,具体安装过程可以参看下面这篇文章: http://www.cnblogs.com/xiazh/archive/2012/05/2 ...

  6. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  7. Centos6.5安装步骤(U盘安装)

    https://blog.csdn.net/hochoy/article/details/80697454

  8. IIS部署asp.net MVC 出现错误 403.14-Forbidden解决办法

    可能性一: <system.webServer>   <validationvalidateIntegratedModeConfiguration="false" ...

  9. USACO 5.1 Musical Themes(哈希+二分)

    Musical ThemesBrian Dean A musical melody is represented as a sequence of N (1 <= N <= 5000) n ...

  10. 基于 SSH 框架的 Criteria 和 DetachedCriteria 多条件查询

    Hibernate 定义了 CriteriaSpecification 接口规范用来完成面向对象的条件查询,Criteria 和 DetachedCriteria 就是 CriteriaSpecifi ...