Skip to content

Commit

Permalink
scripts/faddr2line: Fix "size mismatch" error
Browse files Browse the repository at this point in the history
I'm not sure how we missed this problem before.  When I take a function
address and size from an oops and give it to faddr2line, it usually
complains about a size mismatch:

  $ scripts/faddr2line ~/k/vmlinux write_sysrq_trigger+0x51/0x60
  skipping write_sysrq_trigger address at 0xffffffff815731a1 due to size mismatch (0x60 != 83)
  no match for write_sysrq_trigger+0x51/0x60

The problem is caused by differences in how kallsyms and faddr2line
determine a function's size.

kallsyms calculates a function's size by parsing the output of 'nm -n'
and subtracting the next function's address from the current function's
address.  This means that nop instructions after the end of the function
are included in the size.

In contrast, faddr2line reads the size from the symbol table, which does
*not* include the ending nops in the function's size.

Change faddr2line to calculate the size from the output of 'nm -n' to be
consistent with kallsyms and oops outputs.

Signed-off-by: Josh Poimboeuf <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Denys Vlasenko <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/bd313ed7c4003f6b1fda63e825325c44a9d837de.1477405374.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
jpoimboe authored and Ingo Molnar committed Oct 25, 2016
1 parent 5e25d5b commit efdb416
Showing 1 changed file with 21 additions and 12 deletions.
33 changes: 21 additions & 12 deletions scripts/faddr2line
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,18 @@ __faddr2line() {
# In rare cases there might be duplicates.
while read symbol; do
local fields=($symbol)
local sym_base=0x${fields[1]}
local sym_size=${fields[2]}
local sym_type=${fields[3]}
local sym_base=0x${fields[0]}
local sym_type=${fields[1]}
local sym_end=0x${fields[3]}

# calculate the size
local sym_size=$(($sym_end - $sym_base))
if [[ -z $sym_size ]] || [[ $sym_size -le 0 ]]; then
warn "bad symbol size: base: $sym_base end: $sym_end"
DONE=1
return
fi
sym_size=0x$(printf %x $sym_size)

# calculate the address
local addr=$(($sym_base + $offset))
Expand All @@ -116,39 +125,39 @@ __faddr2line() {
DONE=1
return
fi
local hexaddr=0x$(printf %x $addr)
addr=0x$(printf %x $addr)

# weed out non-function symbols
if [[ $sym_type != "FUNC" ]]; then
if [[ $sym_type != t ]] && [[ $sym_type != T ]]; then
[[ $print_warnings = 1 ]] &&
echo "skipping $func address at $hexaddr due to non-function symbol"
echo "skipping $func address at $addr due to non-function symbol of type '$sym_type'"
continue
fi

# if the user provided a size, make sure it matches the symbol's size
if [[ -n $size ]] && [[ $size -ne $sym_size ]]; then
[[ $print_warnings = 1 ]] &&
echo "skipping $func address at $hexaddr due to size mismatch ($size != $sym_size)"
echo "skipping $func address at $addr due to size mismatch ($size != $sym_size)"
continue;
fi

# make sure the provided offset is within the symbol's range
if [[ $offset -gt $sym_size ]]; then
[[ $print_warnings = 1 ]] &&
echo "skipping $func address at $hexaddr due to size mismatch ($offset > $sym_size)"
echo "skipping $func address at $addr due to size mismatch ($offset > $sym_size)"
continue
fi

# separate multiple entries with a blank line
[[ $FIRST = 0 ]] && echo
FIRST=0

local hexsize=0x$(printf %x $sym_size)
echo "$func+$offset/$hexsize:"
addr2line -fpie $objfile $hexaddr | sed "s; $dir_prefix\(\./\)*; ;"
# pass real address to addr2line
echo "$func+$offset/$sym_size:"
addr2line -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;"
DONE=1

done < <(readelf -sW $objfile | awk -v f=$func '$8 == f {print}')
done < <(nm -n $objfile | awk -v fn=$func '$3 == fn { found=1; line=$0; start=$1; next } found == 1 { found=0; print line, $1 }')
}

[[ $# -lt 2 ]] && usage
Expand Down

0 comments on commit efdb416

Please sign in to comment.