mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-26 11:41:35 +01:00
get_elf_entry
trace2txt fully ported
This commit is contained in:
51
README.adoc
51
README.adoc
@@ -5288,9 +5288,9 @@ QEMU:
|
||||
sample output:
|
||||
|
||||
....
|
||||
instruction count all: 1833863
|
||||
entry address: 0x1000000
|
||||
instruction count firmware: 20708
|
||||
instructions 1833863
|
||||
entry_address 0x1000000
|
||||
instructions_firmware 20708
|
||||
....
|
||||
|
||||
gem5:
|
||||
@@ -5328,7 +5328,7 @@ It only appears once on every log I've seen so far, checked with `grep 0x1000000
|
||||
+
|
||||
Then when we count the instructions that run before the kernel entry point, there is only about 100k instructions, which is insignificant compared to the kernel boot itself.
|
||||
+
|
||||
TODO `-a arm` and `-a aarch64` does not count firmware instructions properly because the entry point address of the ELF file does not show up on the trace at all.
|
||||
TODO `-a arm` and `-a aarch64` does not count firmware instructions properly because the entry point address of the ELF file (`ffffff8008080000` for `aarch64`) does not show up on the trace at all. Tested on link:http://github.com/cirosantilli/linux-kernel-module-cheat/commit/f8c0502bb2680f2dbe7c1f3d7958f60265347005[f8c0502bb2680f2dbe7c1f3d7958f60265347005].
|
||||
* We can also discount the instructions after `init` runs by using `readelf` to get the initial address of `init`. One easy way to do that now is to just run:
|
||||
+
|
||||
....
|
||||
@@ -9046,42 +9046,19 @@ So for example when you run:
|
||||
./run -a arm
|
||||
....
|
||||
|
||||
Stdout shows a line with the full command of type:
|
||||
the very first stdout output of that script is the actual QEMU command that is being run.
|
||||
|
||||
....
|
||||
time \
|
||||
/home/ciro/bak/git/linux-kernel-module-cheat/out/arm/buildroot/build/host-qemu-custom.default/arm-softmmu/qemu-system-arm \
|
||||
-device rtl8139,netdev=net0 \
|
||||
-gdb 'tcp::45457' \
|
||||
-kernel '/home/ciro/bak/git/linux-kernel-module-cheat/out/arm/buildroot/build/linux-custom.default/arch/arm/boot/zImage' \
|
||||
-m '256M' \
|
||||
-monitor 'telnet::45454,server,nowait' \
|
||||
-netdev 'user,hostfwd=tcp::45455-:45455,hostfwd=tcp::45456-:22,id=net0' \
|
||||
-no-reboot \
|
||||
-serial mon:stdio \
|
||||
-smp '1' \
|
||||
-trace 'enable=pr_manager_run,file=/home/ciro/bak/git/linux-kernel-module-cheat/out/arm/qemu/0/trace.bin' \
|
||||
-virtfs 'local,path=/home/ciro/bak/git/linux-kernel-module-cheat/data/9p,mount_tag=host_scratch,security_model=mapped,id=host_scratch' \
|
||||
-virtfs 'local,path=/home/ciro/bak/git/linux-kernel-module-cheat/out/arm/buildroot/build,mount_tag=host_out,security_model=mapped,id=host_out' \
|
||||
-M virt,highmem=off \
|
||||
-append 'root=/dev/vda console_msg_format=syslog nokaslr norandmaps panic=-1 printk.devkmsg=on printk.time=y' \
|
||||
-cpu cortex-a15 \
|
||||
-device virtio-gpu-pci \
|
||||
-nographic \
|
||||
-drive 'file=/home/ciro/bak/git/linux-kernel-module-cheat/out/arm/buildroot/images/rootfs.ext2.qcow2,format=qcow2,if=virtio,snapshot' \
|
||||
|& tee >(ts -s %.s > /home/ciro/bak/git/linux-kernel-module-cheat/out/arm/qemu/0/termout.txt)
|
||||
....
|
||||
|
||||
and this line is also saved to a file for convenience:
|
||||
The command is also saved to a file for convenience:
|
||||
|
||||
....
|
||||
cat "$(./getvar -a arm run_cmd_file)"
|
||||
....
|
||||
|
||||
or for gem5:
|
||||
which you can manually modify and execute during your experiments later:
|
||||
|
||||
....
|
||||
cat "$(./getvar -a arm -g run_cmd_file)"
|
||||
vim "$(./getvar -a arm run_cmd_file)"
|
||||
./"$(./getvar -a arm run_cmd_file)"
|
||||
....
|
||||
|
||||
Next, you will also want to give the relevant images to save them time. Zip the images with:
|
||||
@@ -9091,7 +9068,15 @@ Next, you will also want to give the relevant images to save them time. Zip the
|
||||
./zip-img
|
||||
....
|
||||
|
||||
and then upload the `out/lkmc-*.zip` file somewhere, e.g. GitHub release assets as in https://github.com/cirosantilli/linux-kernel-module-cheat/releases/tag/test-replay-arm
|
||||
Source: link:zip-img[]
|
||||
|
||||
This generates a zip file:
|
||||
|
||||
....
|
||||
out/lkmc-*.zip
|
||||
....
|
||||
|
||||
which you can then upload somewhere, e.g. GitHub release assets as in https://github.com/cirosantilli/linux-kernel-module-cheat/releases/tag/test-replay-arm
|
||||
|
||||
Finally, do a clone of the relevant repository out of tree and reproduce the bug there, to be 100% sure that it is an actual upstream bug, and to provide developers with the cleanest possible commands.
|
||||
|
||||
|
||||
14
common.py
14
common.py
@@ -133,6 +133,20 @@ around when you checkout between branches.
|
||||
parser.set_defaults(**defaults)
|
||||
return parser
|
||||
|
||||
def get_elf_entry(elf_file_path):
|
||||
global this
|
||||
readelf_header = subprocess.check_output([
|
||||
this.get_toolchain_tool('readelf'),
|
||||
'-h',
|
||||
elf_file_path
|
||||
])
|
||||
for line in readelf_header.decode().split('\n'):
|
||||
split = line.split()
|
||||
if line.startswith(' Entry point address:'):
|
||||
addr = line.split()[-1]
|
||||
break
|
||||
return int(addr, 0)
|
||||
|
||||
def get_stats(stat_re=None, stats_file=None):
|
||||
global this
|
||||
if stat_re is None:
|
||||
|
||||
16
run
16
run
@@ -84,16 +84,20 @@ def main(args, extra_args=None):
|
||||
if kernel_cli_extra_after_dash:
|
||||
kernel_cli_extra += " -{}".format(kernel_cli_extra_after_dash)
|
||||
extra_env = {}
|
||||
|
||||
# A dummy value that is already turned on by default and does not produce large output,
|
||||
# just to prevent QEMU from emitting a warning that '' is not valid.
|
||||
trace_type = 'pr_manager_run'
|
||||
if args.trace is None:
|
||||
do_trace = False
|
||||
# A dummy value that is already turned on by default and does not produce large output,
|
||||
# just to prevent QEMU from emitting a warning that '' is not valid.
|
||||
trace_type = 'pr_manager_run'
|
||||
else:
|
||||
do_trace = True
|
||||
trace_type = args.trace
|
||||
|
||||
if args.gem5:
|
||||
memory = '{}B'.format(args.memory)
|
||||
gem5_exe_args = shlex.split(args.gem5_exe_args)
|
||||
if args.trace is not None:
|
||||
gem5_exe_args.append('--debug-flags={}'.format(args.trace))
|
||||
if do_trace:
|
||||
gem5_exe_args.append('--debug-flags={}'.format(trace_type))
|
||||
extra_env['M5_PATH'] = common.gem5_system_dir
|
||||
cmd = (
|
||||
debug_vm +
|
||||
|
||||
16
rungdb-user
16
rungdb-user
@@ -2,8 +2,6 @@
|
||||
|
||||
import imp
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
import common
|
||||
rungdb = imp.load_source('rungdb', os.path.join(common.root_dir, 'rungdb'))
|
||||
@@ -25,19 +23,9 @@ parser.add_argument(
|
||||
nargs='?'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
readelf_header = subprocess.check_output([
|
||||
common.get_toolchain_tool('readelf'),
|
||||
'-h',
|
||||
os.path.join(common.build_dir, args.executable),
|
||||
])
|
||||
for line in readelf_header.decode().split('\n'):
|
||||
split = line.split()
|
||||
if line.startswith(' Entry point address:'):
|
||||
addr = line.split()[-1]
|
||||
break
|
||||
print(addr)
|
||||
addr = common.get_elf_entry(os.path.join(common.build_dir, args.executable))
|
||||
extra_args = {}
|
||||
extra_args['before'] = '-ex \"add-symbol-file {} {}\"'.format(args.executable, addr)
|
||||
extra_args['before'] = '-ex \"add-symbol-file {} {}\"'.format(args.executable, hex(addr))
|
||||
# Or else lx-symbols throws for arm:
|
||||
# gdb.MemoryError: Cannot access memory at address 0xbf0040cc
|
||||
# TODO understand better.
|
||||
|
||||
33
trace-boot
33
trace-boot
@@ -36,11 +36,28 @@ else:
|
||||
})
|
||||
run.main(args, extra_args)
|
||||
qemu_trace2txt.main()
|
||||
## Instruction count.
|
||||
## We could put this on a separate script, but it just adds more arch boilerplate to a new script.
|
||||
## So let's just leave it here for now since it did not add a significant processing time.
|
||||
#echo "instructions $(wc -l "${common_trace_txt_file}" | cut -d' ' -f1)"
|
||||
#entry_addr=$("${common_root_dir}/runtc" readelf -h "${common_build_dir}/linux-custom/vmlinux" | grep 'Entry point address' | sed -E 's/.*: *//')
|
||||
#echo "entry_address ${entry_addr}"
|
||||
#sed "/${entry_addr}/q" "${common_trace_txt_file}" >"${common_qemu_run_dir}/trace-boot.txt"
|
||||
#echo "instructions_firmware $(wc -l "${common_qemu_run_dir}/trace-boot.txt" | cut -d' ' -f1)"
|
||||
# Instruction count.
|
||||
# We could put this on a separate script, but it just adds more arch boilerplate to a new script.
|
||||
# So let's just leave it here for now since it did not add a significant processing time.
|
||||
kernel_entry_addr = hex(common.get_elf_entry(common.vmlinux))
|
||||
nlines = 0
|
||||
nlines_firmware = 0
|
||||
with open(common.qemu_trace_txt_file, 'r') as trace_file:
|
||||
in_firmware = True
|
||||
for line in trace_file:
|
||||
line = line.rstrip()
|
||||
nlines += 1
|
||||
pc = line.split('=')[-1]
|
||||
if pc == kernel_entry_addr:
|
||||
in_firmware = False
|
||||
if in_firmware:
|
||||
nlines_firmware += 1
|
||||
print('''\
|
||||
instructions {}
|
||||
entry_address {}
|
||||
instructions_firmware {}\
|
||||
'''.format(
|
||||
nlines,
|
||||
kernel_entry_addr,
|
||||
nlines_firmware
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user