On Fri, Jun 6, 2014 at 1:26 PM, Nicholas Mc Guire <der.herr@hofr.at> 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@rtl27:~/linux-stable# make defconfig *** Default configuration is based on 'x86_64_defconfig' # # configuration written to .config # hofrat@rtl27:~/linux-stable# make kernel/mutex.lst scripts/kconfig/conf --silentoldconfig Kconfig ... HOSTCC scripts/conmakehash HOSTCC scripts/sortextable MKLST kernel/mutex.lst hofrat@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@rtl27:~/linux-stable# make kernel/mutex.s ... CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CC kernel/mutex.s hofrat@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@rtl27:~/linux-stable# make kernel/mutex.i hofrat@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