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: sample output:
.... ....
instruction count all: 1833863 instructions 1833863
entry address: 0x1000000 entry_address 0x1000000
instruction count firmware: 20708 instructions_firmware 20708
.... ....
gem5: 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. 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: * 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 ./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.
.... The command is also saved to a file for convenience:
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:
.... ....
cat "$(./getvar -a arm run_cmd_file)" 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: 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 ./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. 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) parser.set_defaults(**defaults)
return parser 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): def get_stats(stat_re=None, stats_file=None):
global this global this
if stat_re is None: 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: if kernel_cli_extra_after_dash:
kernel_cli_extra += " -{}".format(kernel_cli_extra_after_dash) kernel_cli_extra += " -{}".format(kernel_cli_extra_after_dash)
extra_env = {} extra_env = {}
if args.trace is None:
# A dummy value that is already turned on by default and does not produce large output, do_trace = False
# just to prevent QEMU from emitting a warning that '' is not valid. # A dummy value that is already turned on by default and does not produce large output,
trace_type = 'pr_manager_run' # 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: if args.gem5:
memory = '{}B'.format(args.memory) memory = '{}B'.format(args.memory)
gem5_exe_args = shlex.split(args.gem5_exe_args) gem5_exe_args = shlex.split(args.gem5_exe_args)
if args.trace is not None: if do_trace:
gem5_exe_args.append('--debug-flags={}'.format(args.trace)) gem5_exe_args.append('--debug-flags={}'.format(trace_type))
extra_env['M5_PATH'] = common.gem5_system_dir extra_env['M5_PATH'] = common.gem5_system_dir
cmd = ( cmd = (
debug_vm + debug_vm +

View File

@@ -2,8 +2,6 @@
import imp import imp
import os import os
import subprocess
import re
import common import common
rungdb = imp.load_source('rungdb', os.path.join(common.root_dir, 'rungdb')) rungdb = imp.load_source('rungdb', os.path.join(common.root_dir, 'rungdb'))
@@ -25,19 +23,9 @@ parser.add_argument(
nargs='?' nargs='?'
) )
args = common.setup(parser) args = common.setup(parser)
readelf_header = subprocess.check_output([ addr = common.get_elf_entry(os.path.join(common.build_dir, args.executable))
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)
extra_args = {} 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: # Or else lx-symbols throws for arm:
# gdb.MemoryError: Cannot access memory at address 0xbf0040cc # gdb.MemoryError: Cannot access memory at address 0xbf0040cc
# TODO understand better. # TODO understand better.

View File

@@ -36,11 +36,28 @@ else:
}) })
run.main(args, extra_args) run.main(args, extra_args)
qemu_trace2txt.main() qemu_trace2txt.main()
## Instruction count. # Instruction count.
## We could put this on a separate script, but it just adds more arch boilerplate to a new script. # 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. # 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)" kernel_entry_addr = hex(common.get_elf_entry(common.vmlinux))
#entry_addr=$("${common_root_dir}/runtc" readelf -h "${common_build_dir}/linux-custom/vmlinux" | grep 'Entry point address' | sed -E 's/.*: *//') nlines = 0
#echo "entry_address ${entry_addr}" nlines_firmware = 0
#sed "/${entry_addr}/q" "${common_trace_txt_file}" >"${common_qemu_run_dir}/trace-boot.txt" with open(common.qemu_trace_txt_file, 'r') as trace_file:
#echo "instructions_firmware $(wc -l "${common_qemu_run_dir}/trace-boot.txt" | cut -d' ' -f1)" 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
))