mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-22 17:55:57 +01:00
disas works with the linux kernel, it's beautiful
This commit is contained in:
50
README.adoc
50
README.adoc
@@ -14756,19 +14756,17 @@ where 120 == 0x78 (it logs addresses in decimal? Really??) and the size 4 which
|
|||||||
|
|
||||||
Now that we are here, we might as well learn how to log the data that was fetched from DRAM.
|
Now that we are here, we might as well learn how to log the data that was fetched from DRAM.
|
||||||
|
|
||||||
Fist we determine the expected bytes from:
|
Fist we determine the expected bytes from the <<disas,disassembly>>:
|
||||||
|
|
||||||
....
|
....
|
||||||
./run-toolchain --arch aarch64 objdump -- \
|
./disas --arch aarch64 --userland userland/arch/aarch64/freestanding/linux/hello.S _start
|
||||||
-D "$(./getvar --arch aarch64 userland_build_dir)/arch/aarch64/freestanding/linux/hello.out"
|
|
||||||
....
|
....
|
||||||
|
|
||||||
which shows us the initial instruction encodings near the entry point `_start`:
|
which shows us the initial instruction encodings near the entry point `_start`:
|
||||||
|
|
||||||
....
|
....
|
||||||
0000000000400078 <_start>:
|
0x0000000000400078 <+0>: 20 00 80 d2 mov x0, #0x1 // #1
|
||||||
400078: d2800020 mov x0, #0x1 // #1
|
0x000000000040007c <+4>: e1 00 00 10 adr x1, 0x400098 <msg>
|
||||||
40007c: 100000e1 adr x1, 400098 <msg>
|
|
||||||
....
|
....
|
||||||
|
|
||||||
Now, TODO :-) The `DRAM` logs don't contain data. Maybe this can be done with https://github.com/gem5/gem5/blob/9fc9c67b4242c03f165951775be5cd0812f2a705/src/mem/comm_monitor.hh#L55[`CommMonitor`], but it is no exposed on fs.py
|
Now, TODO :-) The `DRAM` logs don't contain data. Maybe this can be done with https://github.com/gem5/gem5/blob/9fc9c67b4242c03f165951775be5cd0812f2a705/src/mem/comm_monitor.hh#L55[`CommMonitor`], but it is no exposed on fs.py
|
||||||
@@ -17874,16 +17872,10 @@ link:userland/c/atomic.c[]
|
|||||||
|
|
||||||
Demonstrates `atomic_int` and `thrd_create`.
|
Demonstrates `atomic_int` and `thrd_create`.
|
||||||
|
|
||||||
Disassembly with GDB at LKMC 619fef4b04bddc4a5a38aec5e207dd4d5a25d206 + 1:
|
<<disas,Disassembly with GDB>> at LKMC 619fef4b04bddc4a5a38aec5e207dd4d5a25d206 + 1:
|
||||||
|
|
||||||
....
|
....
|
||||||
./run-toolchain \
|
./disas --arch aarch64 --userland userland/c/atomic.c my_thread_main
|
||||||
--arch aarch64 gdb \
|
|
||||||
-- \
|
|
||||||
-batch \
|
|
||||||
-ex 'disas/rs my_thread_main' $(./getvar \
|
|
||||||
--arch aarch64 userland_build_dir)/c/atomic.out \
|
|
||||||
;
|
|
||||||
....
|
....
|
||||||
|
|
||||||
shows on ARM:
|
shows on ARM:
|
||||||
@@ -24499,10 +24491,10 @@ link:userland/gcc/busy_loop.c[]
|
|||||||
|
|
||||||
The hard part is how to prevent the compiler from optimizing it away: https://stackoverflow.com/questions/7083482/how-to-prevent-gcc-from-optimizing-out-a-busy-wait-loop/58758133#58758133
|
The hard part is how to prevent the compiler from optimizing it away: https://stackoverflow.com/questions/7083482/how-to-prevent-gcc-from-optimizing-out-a-busy-wait-loop/58758133#58758133
|
||||||
|
|
||||||
Disassembly analysis:
|
<<disas,Disassembly>> analysis:
|
||||||
|
|
||||||
....
|
....
|
||||||
./run-toolchain --arch aarch64 gdb -- -nh -batch -ex 'disas/rs busy_loop' "$(./getvar --arch aarch64 userland_build_dir)/gcc/busy_loop.out"
|
./disas --arch aarch64 --userland userland/gcc/busy_loop.out busy_loop
|
||||||
....
|
....
|
||||||
|
|
||||||
which contains at LKMC eb22fd3b6e7fff7e9ef946a88b208debf5b419d5:
|
which contains at LKMC eb22fd3b6e7fff7e9ef946a88b208debf5b419d5:
|
||||||
@@ -25362,6 +25354,14 @@ you can save some typing and get portability across directory structure changes
|
|||||||
./run-toolchain --arch aarch64 objdump -- -D a.out
|
./run-toolchain --arch aarch64 objdump -- -D a.out
|
||||||
....
|
....
|
||||||
|
|
||||||
|
This plays nicely with <<getvar>> e.g. you could disassembly link:userland/c/hello.c[] with:
|
||||||
|
|
||||||
|
....
|
||||||
|
./run-toolchain --arch aarch64 objdump -- -D $(./getvar --arch aarch64 userland_build_dir)/c/hello.out
|
||||||
|
....
|
||||||
|
|
||||||
|
however disassembly is such a common use case that we have a shortcut for it: <<disas>>.
|
||||||
|
|
||||||
Alternatively, if you just need a variable to feed into your own Build system, you can also use <<getvar>>:
|
Alternatively, if you just need a variable to feed into your own Build system, you can also use <<getvar>>:
|
||||||
|
|
||||||
....
|
....
|
||||||
@@ -25374,12 +25374,28 @@ which outputs as of LKMC b15a0e455d691afa49f3b813ad9b09394dfb02b7:
|
|||||||
/path/to/linux-kernel-module-cheat/out/buildroot/build/default/aarch64/host/usr/bin/aarch64-buildroot-linux-gnu
|
/path/to/linux-kernel-module-cheat/out/buildroot/build/default/aarch64/host/usr/bin/aarch64-buildroot-linux-gnu
|
||||||
....
|
....
|
||||||
|
|
||||||
Since disassembly of a single function with GDB is such a common use case https://stackoverflow.com/questions/22769246/how-to-disassemble-one-single-function-using-objdump[], we have a shortcut for it:
|
===== disas
|
||||||
|
|
||||||
|
Since disassembly of a single function of a LKMC executable with GDB is such a common use case for <<run-toolchain>> via https://stackoverflow.com/questions/22769246/how-to-disassemble-one-single-function-using-objdump[], we have this shortcut for it.
|
||||||
|
|
||||||
|
For example to disassemle a function from an <<userland-content,userland binary>>:
|
||||||
|
|
||||||
....
|
....
|
||||||
./disas --arch aarch64 --userland userland/c/hello.c main
|
./disas --arch aarch64 --userland userland/c/hello.c main
|
||||||
....
|
....
|
||||||
|
|
||||||
|
or to disassemble a function from the <<linux-kernel>>:
|
||||||
|
|
||||||
|
....
|
||||||
|
./disas --arch aarch64 start_kernel
|
||||||
|
....
|
||||||
|
|
||||||
|
and a <<baremetal-setup,baremetal>> executable:
|
||||||
|
|
||||||
|
....
|
||||||
|
./disas --arch aarch64 --baremetal baremetal/arch/aarch64/no_bootloader/exit.S _start
|
||||||
|
....
|
||||||
|
|
||||||
=== Rebuild Buildroot while running
|
=== Rebuild Buildroot while running
|
||||||
|
|
||||||
It is not possible to rebuild the root filesystem while running QEMU because QEMU holds the file qcow2 file:
|
It is not possible to rebuild the root filesystem while running QEMU because QEMU holds the file qcow2 file:
|
||||||
|
|||||||
@@ -1166,6 +1166,10 @@ Incompatible archs are skipped.
|
|||||||
# Image
|
# Image
|
||||||
if env['baremetal']:
|
if env['baremetal']:
|
||||||
env['image'] = self.resolve_baremetal_executable(env['baremetal'][0])
|
env['image'] = self.resolve_baremetal_executable(env['baremetal'][0])
|
||||||
|
# This is needed because the Linux kerne limage for certain emulators like QEMU
|
||||||
|
# might not be in plain ELF format, but rather some crazy compressed kernel format.
|
||||||
|
# https://cirosantilli.com/linux-kernel-module-cheat#vmlinux-vs-bzimage-vs-zimage-vs-image
|
||||||
|
env['image_elf'] = env['image']
|
||||||
source_path_noext = os.path.splitext(join(
|
source_path_noext = os.path.splitext(join(
|
||||||
env['root_dir'],
|
env['root_dir'],
|
||||||
env['image'][len(env['baremetal_build_dir']) + 1:]
|
env['image'][len(env['baremetal_build_dir']) + 1:]
|
||||||
@@ -1178,6 +1182,7 @@ Incompatible archs are skipped.
|
|||||||
break
|
break
|
||||||
elif env['userland']:
|
elif env['userland']:
|
||||||
env['image'] = self.resolve_userland_executable(env['userland'][0])
|
env['image'] = self.resolve_userland_executable(env['userland'][0])
|
||||||
|
env['image_elf'] = env['image']
|
||||||
source_path_noext = os.path.splitext(join(
|
source_path_noext = os.path.splitext(join(
|
||||||
env['userland_source_dir'],
|
env['userland_source_dir'],
|
||||||
env['image'][len(env['userland_build_dir']) + 1:]
|
env['image'][len(env['userland_build_dir']) + 1:]
|
||||||
@@ -1195,6 +1200,7 @@ Incompatible archs are skipped.
|
|||||||
else:
|
else:
|
||||||
if not env['_args_given']['linux_exec']:
|
if not env['_args_given']['linux_exec']:
|
||||||
env['image'] = env['linux_image']
|
env['image'] = env['linux_image']
|
||||||
|
env['image_elf'] = env['vmlinux']
|
||||||
if env['_args_given']['linux_exec']:
|
if env['_args_given']['linux_exec']:
|
||||||
env['image'] = env['linux_exec']
|
env['image'] = env['linux_exec']
|
||||||
if env['emulator'] == 'gem5':
|
if env['emulator'] == 'gem5':
|
||||||
|
|||||||
4
disas
4
disas
@@ -18,7 +18,7 @@ Disassemble one function of the given executable.
|
|||||||
https://cirosantilli.com/linux-kernel-module-cheat#run-toolchain
|
https://cirosantilli.com/linux-kernel-module-cheat#run-toolchain
|
||||||
''',
|
''',
|
||||||
)
|
)
|
||||||
self.add_argument('function', help='Which function to disassemble.')
|
self.add_argument('function', default='main', help='Which function to disassemble.')
|
||||||
|
|
||||||
def timed_main(self):
|
def timed_main(self):
|
||||||
lkmc.import_path.import_path_main('run-toolchain')(
|
lkmc.import_path.import_path_main('run-toolchain')(
|
||||||
@@ -28,7 +28,7 @@ https://cirosantilli.com/linux-kernel-module-cheat#run-toolchain
|
|||||||
'-batch',
|
'-batch',
|
||||||
'-ex',
|
'-ex',
|
||||||
'disas/rs {}'.format(self.env['function']),
|
'disas/rs {}'.format(self.env['function']),
|
||||||
self.env['image'],
|
self.env['image_elf'],
|
||||||
],
|
],
|
||||||
quiet=True,
|
quiet=True,
|
||||||
**self.get_common_args()
|
**self.get_common_args()
|
||||||
|
|||||||
5
run-gdb
5
run-gdb
@@ -171,17 +171,14 @@ by default due to --continue if this breakpoint is reached.
|
|||||||
else:
|
else:
|
||||||
break_at = []
|
break_at = []
|
||||||
if self.env['userland']:
|
if self.env['userland']:
|
||||||
image = self.env['image']
|
|
||||||
linux_full_system = False
|
linux_full_system = False
|
||||||
if self.env['gdbserver']:
|
if self.env['gdbserver']:
|
||||||
before.extend([
|
before.extend([
|
||||||
'-ex', 'set sysroot {}'.format(self.env['buildroot_staging_dir']),
|
'-ex', 'set sysroot {}'.format(self.env['buildroot_staging_dir']),
|
||||||
])
|
])
|
||||||
elif self.env['baremetal']:
|
elif self.env['baremetal']:
|
||||||
image = self.env['image']
|
|
||||||
linux_full_system = False
|
linux_full_system = False
|
||||||
else:
|
else:
|
||||||
image = self.env['vmlinux']
|
|
||||||
linux_full_system = True
|
linux_full_system = True
|
||||||
cmd = (
|
cmd = (
|
||||||
[self.env['gdb_path'], LF] +
|
[self.env['gdb_path'], LF] +
|
||||||
@@ -200,7 +197,7 @@ by default due to --continue if this breakpoint is reached.
|
|||||||
port = self.env['gdb_port']
|
port = self.env['gdb_port']
|
||||||
target = 'remote localhost:{}'.format(port)
|
target = 'remote localhost:{}'.format(port)
|
||||||
cmd.extend([
|
cmd.extend([
|
||||||
'-ex', 'file {}'.format(image), LF,
|
'-ex', 'file {}'.format(self.env['image_elf']), LF,
|
||||||
'-ex', 'target {}'.format(target), LF,
|
'-ex', 'target {}'.format(target), LF,
|
||||||
])
|
])
|
||||||
if not self.env['kgdb']:
|
if not self.env['kgdb']:
|
||||||
|
|||||||
Reference in New Issue
Block a user