lkml.org 
[lkml]   [2022]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 208/234] faddr2line: Fix overlapping text section failures, the sequel
    Date
    From: Josh Poimboeuf <jpoimboe@kernel.org>

    [ Upstream commit dcea997beed694cbd8705100ca1a6eb0d886de69 ]

    If a function lives in a section other than .text, but .text also exists
    in the object, faddr2line may wrongly assume .text. This can result in
    comically wrong output. For example:

    $ scripts/faddr2line vmlinux.o enter_from_user_mode+0x1c
    enter_from_user_mode+0x1c/0x30:
    find_next_bit at /home/jpoimboe/git/linux/./include/linux/find.h:40
    (inlined by) perf_clear_dirty_counters at /home/jpoimboe/git/linux/arch/x86/events/core.c:2504

    Fix it by passing the section name to addr2line, unless the object file
    is vmlinux, in which case the symbol table uses absolute addresses.

    Fixes: 1d1a0e7c5100 ("scripts/faddr2line: Fix overlapping text section failures")
    Reported-by: Peter Zijlstra <peterz@infradead.org>
    Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
    Link: https://lore.kernel.org/r/7d25bc1408bd3a750ac26e60d2f2815a5f4a8363.1654130536.git.jpoimboe@kernel.org
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    scripts/faddr2line | 45 ++++++++++++++++++++++++++++++++++-----------
    1 file changed, 34 insertions(+), 11 deletions(-)

    diff --git a/scripts/faddr2line b/scripts/faddr2line
    index 226c3f559dc5..2571caac3156 100755
    --- a/scripts/faddr2line
    +++ b/scripts/faddr2line
    @@ -95,17 +95,25 @@ __faddr2line() {
    local print_warnings=$4

    local sym_name=${func_addr%+*}
    - local offset=${func_addr#*+}
    - offset=${offset%/*}
    + local func_offset=${func_addr#*+}
    + func_offset=${func_offset%/*}
    local user_size=
    + local file_type
    + local is_vmlinux=0
    [[ $func_addr =~ "/" ]] && user_size=${func_addr#*/}

    - if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then
    + if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then
    warn "bad func+offset $func_addr"
    DONE=1
    return
    fi

    + # vmlinux uses absolute addresses in the section table rather than
    + # section offsets.
    + local file_type=$(${READELF} --file-header $objfile |
    + ${AWK} '$1 == "Type:" { print $2; exit }')
    + [[ $file_type = "EXEC" ]] && is_vmlinux=1
    +
    # Go through each of the object's symbols which match the func name.
    # In rare cases there might be duplicates, in which case we print all
    # matches.
    @@ -114,9 +122,11 @@ __faddr2line() {
    local sym_addr=0x${fields[1]}
    local sym_elf_size=${fields[2]}
    local sym_sec=${fields[6]}
    + local sec_size
    + local sec_name

    # Get the section size:
    - local sec_size=$(${READELF} --section-headers --wide $objfile |
    + sec_size=$(${READELF} --section-headers --wide $objfile |
    sed 's/\[ /\[/' |
    ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }')

    @@ -126,6 +136,17 @@ __faddr2line() {
    return
    fi

    + # Get the section name:
    + sec_name=$(${READELF} --section-headers --wide $objfile |
    + sed 's/\[ /\[/' |
    + ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }')
    +
    + if [[ -z $sec_name ]]; then
    + warn "bad section name: section: $sym_sec"
    + DONE=1
    + return
    + fi
    +
    # Calculate the symbol size.
    #
    # Unfortunately we can't use the ELF size, because kallsyms
    @@ -174,10 +195,10 @@ __faddr2line() {

    sym_size=0x$(printf %x $sym_size)

    - # Calculate the section address from user-supplied offset:
    - local addr=$(($sym_addr + $offset))
    + # Calculate the address from user-supplied offset:
    + local addr=$(($sym_addr + $func_offset))
    if [[ -z $addr ]] || [[ $addr = 0 ]]; then
    - warn "bad address: $sym_addr + $offset"
    + warn "bad address: $sym_addr + $func_offset"
    DONE=1
    return
    fi
    @@ -191,9 +212,9 @@ __faddr2line() {
    fi

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

    @@ -202,11 +223,13 @@ __faddr2line() {
    [[ $FIRST = 0 ]] && echo
    FIRST=0

    - echo "$sym_name+$offset/$sym_size:"
    + echo "$sym_name+$func_offset/$sym_size:"

    # Pass section address to addr2line and strip absolute paths
    # from the output:
    - local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;")
    + local args="--functions --pretty-print --inlines --exe=$objfile"
    + [[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name"
    + local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;")
    [[ -z $output ]] && continue

    # Default output (non --list):
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-06-23 20:18    [W:4.142 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site