Figuring out confusing assembly instructions — Koszek trick #2
by Wojciech Adam Koszek ⋅ Jun 26, 2012 ⋅ East Palo Alto, CAUseful trick to get from C to assembly and attempt to identify which C parts mapped to which assembly fragments.
Today’s post will be very simple, maybe trivial. One of the hacks that I came up with, when I encountered confusing arcane of ANSI C, or when I played with assembly for fun and profit.
Problem: isolate ANSI C construct or in-line assembly block, so that upon a translation to intermediate assembly, block will be exposed more easily in a visual manner.
So imagine you want to isolate memory reference within ANSI C and figure out what the corresponding assembly line is. Assume given portion of the code:
``` [ptr.c]
#include <stdio.h>
int
main(int argc, char **argv)
{
const char *str = "example";
char c;
(void)argc;
(void)argv;
__asm__("/* -------- BEGIN ----------- */");
c = str[3];
__asm__("/* -------- END ----------- */");
printf("%c\n", c);
return 0;
} ```
Basically for a fixed literal string example
you fetch its character m
, which is held in variable c
. It doesn’t make too much sense and isn’t too useful, but the technique has by all means real-world application.
Right now you perform:
$ gcc -S ptr.c
And your created ptr.s
suddenly has:
.file "ptr.c" .section .rodata .LC0: .string "example" .LC1: .string "%c\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 subq $32, %rsp movl %edi, -20(%rbp) movq %rsi, -32(%rbp) movq $.LC0, -16(%rbp) #APP # 12 "ptr.c" 1 /* -------- BEGIN ----------- */ # 0 "" 2 #NO_APP movq -16(%rbp), %rax addq $3, %rax movzbl (%rax), %eax movb %al, -1(%rbp) #APP # 14 "ptr.c" 1 /* -------- END ----------- */ # 0 "" 2 #NO_APP movsbl -1(%rbp), %edx movl $.LC1, %eax movl %edx, %esi movq %rax, %rdi movl $0, %eax call printf movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2" .section .note.GNU-stack,"",@progbits
As you can see, the comments placed by us through __asm__
macro are preserved in the intermediate assembly file. Done!
If you have ever put a code, which has never been executed, or maybe even disappeared somewhere deep in the sea of stages of compilation, this technique should serve you well!