process to inspect generated assembly of a function
Nicholas Mc Guire
der.herr at hofr.at
Fri Jun 6 13:26:34 EDT 2014
n Fri, 06 Jun 2014, Valdis.Kletnieks at vt.edu wrote:
> On Fri, 06 Jun 2014 12:23:35 -0400, Andev said:
>
> > I am trying to inspect the generated assembly for a function in the
> > kernel. Are there any documents explaining how to do this? I want to
> > see how it changes when I change the function body.
>
> The same exact way you'd do it for any .o file for userspace.
>
> objdump and gdb are your friends.
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
More information about the Kernelnewbies
mailing list