Thread (4 messages) 4 messages, 3 authors, 2014-06-07

process to inspect generated assembly of a function

From: Andev <hidden>
Date: 2014-06-07 01:02:26

On Fri, Jun 6, 2014 at 1:26 PM, Nicholas Mc Guire [off-list ref] wrote:
in the kernel build system there is support for understanding assembler code
by generating the .lst files which include the decoded assembler interleaved
with the C source (roughly) making it easier to understand the code.
Also --verbose-asm used when generating .s files in the kernel helps as gcc
is creating variables that are not in your C-code and that can be confusing
to decode if one does not see it from the names.
finally looking at the source code can be challenging as there are many
macros and build dependencies so its probably easier to look at the
preprocessor output .i rather than the original C-source file.

for kernel sources its:

hofrat at rtl27:~/linux-stable# make defconfig
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#
hofrat at rtl27:~/linux-stable# make kernel/mutex.lst
scripts/kconfig/conf --silentoldconfig Kconfig
...
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/sortextable
  MKLST   kernel/mutex.lst
hofrat at rtl27:~/linux-stable# more kernel/mutex.lst
<snip>
void
__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
        atomic_set(&lock->count, 1);
        spin_lock_init(&lock->wait_lock);
   b:   66 c7 47 04 00 00       movw   $0x0,0x4(%rdi)
        lock->owner = current;
}
...
<snip>

hofrat at rtl27:~/linux-stable# make kernel/mutex.s
...
  CHK     include/generated/utsrelease.h
  CALL    scripts/checksyscalls.sh
  CC      kernel/mutex.s
hofrat at rtl27:~/linux-stable# more kernel/mutex.s
<snip>
...
        .text
        .p2align 4,,15
.globl __mutex_init
        .type   __mutex_init, @function
__mutex_init:
        pushq   %rbp    #
        leaq    8(%rdi), %rax   #, D.20779
        movl    $1, (%rdi)      #, <variable>.count.counter
        movw    $0, 4(%rdi)     #, <variable>.wait_lock.D.3891.rlock
        movq    $0, 24(%rdi)    #, <variable>.owner
        movq    %rsp, %rbp      #,
        movq    %rax, 8(%rdi)   # D.20779, <variable>.wait_list.next
        movq    %rax, 16(%rdi)  # D.20779, <variable>.wait_list.prev
        movq    $0, 32(%rdi)    #, <variable>.spin_mlock
        leave
        ret
 ...
<snip>

 The variables named D.# are those that gcc created.
 Note that the code looks different because of the #defines that were
 resolved and translated in .s case but not in the .lst case.

 having both the .s and the .lst file at hand along with the preprocessor
 output generated by


hofrat at rtl27:~/linux-stable# make kernel/mutex.i
hofrat at rtl27:~/linux-stable# more kernel/mutex.i
<snip>
 ...
void
__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
 atomic_set(&lock->count, 1);
 do { spinlock_check(&lock->wait_lock); do { *(&(&lock->wait_lock)->rlock) = (raw_spinlock_t) { .raw_lock = { { 0 } }, }; } while (0); } while (0);
 INIT_LIST_HEAD(&lock->wait_list);
 mutex_clear_owner(lock);

 lock->spin_mlock = ((void *)0);


 do { } while (0);
}
...
<snip>

 should allow you to figure out the details of what is going on in the assembler
 code of your functions.

thx!
hofrat
Thanks a lot Nicholas. This is the easiest way I've seen to far!


-- 
Andev
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help