get_elf_entry

trace2txt fully ported
This commit is contained in:
Ciro Santilli
2018-09-05 08:03:48 +01:00
parent 1ff6a95ab3
commit 485c071a4d
5 changed files with 69 additions and 61 deletions

View File

@@ -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.

View File

@@ -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
View File

@@ -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 +

View File

@@ -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.

View File

@@ -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
))