| @@ -95,17 +95,25 @@ __faddr2line() { · 94 unmodified lines |
| 95 | 95 | local print_warnings=$4 |
| 96 | 96 | |
| 97 | 97 | local sym_name=${func_addr%+*} |
| 98 | | − local offset=${func_addr#*+} |
| 99 | | − offset=${offset%/*} |
| 98 | + local func_offset=${func_addr#*+} |
| 99 | + func_offset=${func_offset%/*} |
| 100 | 100 | local user_size= |
| 101 | + local file_type |
| 102 | + local is_vmlinux=0 |
| 101 | 103 | [[ $func_addr =~ "/" ]] && user_size=${func_addr#*/} |
| 102 | 104 | |
| 103 | | − if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then |
| 105 | + if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then |
| 104 | 106 | warn "bad func+offset $func_addr" |
| 105 | 107 | DONE=1 |
| 106 | 108 | return |
| 107 | 109 | fi |
| 108 | 110 | |
| 111 | + # vmlinux uses absolute addresses in the section table rather than |
| 112 | + # section offsets. |
| 113 | + local file_type=$(${READELF} --file-header $objfile | |
| 114 | + ${AWK} '$1 == "Type:" { print $2; exit }') |
| 115 | + [[ $file_type = "EXEC" ]] && is_vmlinux=1 |
| 116 | + |
| 109 | 117 | # Go through each of the object's symbols which match the func name. |
| 110 | 118 | # In rare cases there might be duplicates, in which case we print all |
| 111 | 119 | # matches. |
| @@ -114,9 +122,11 @@ __faddr2line() { · 2 unmodified lines |
| 114 | 122 | local sym_addr=0x${fields[1]} |
| 115 | 123 | local sym_elf_size=${fields[2]} |
| 116 | 124 | local sym_sec=${fields[6]} |
| 125 | + local sec_size |
| 126 | + local sec_name |
| 117 | 127 | |
| 118 | 128 | # Get the section size: |
| 119 | | − local sec_size=$(${READELF} --section-headers --wide $objfile | |
| 129 | + sec_size=$(${READELF} --section-headers --wide $objfile | |
| 120 | 130 | sed 's/\[ /\[/' | |
| 121 | 131 | ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }') |
| 122 | 132 | |
| @@ -126,6 +136,17 @@ __faddr2line() { · 3 unmodified lines |
| 126 | 136 | return |
| 127 | 137 | fi |
| 128 | 138 | |
| 139 | + # Get the section name: |
| 140 | + sec_name=$(${READELF} --section-headers --wide $objfile | |
| 141 | + sed 's/\[ /\[/' | |
| 142 | + ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }') |
| 143 | + |
| 144 | + if [[ -z $sec_name ]]; then |
| 145 | + warn "bad section name: section: $sym_sec" |
| 146 | + DONE=1 |
| 147 | + return |
| 148 | + fi |
| 149 | + |
| 129 | 150 | # Calculate the symbol size. |
| 130 | 151 | # |
| 131 | 152 | # Unfortunately we can't use the ELF size, because kallsyms |
| @@ -174,10 +195,10 @@ __faddr2line() { · 42 unmodified lines |
| 174 | 195 | |
| 175 | 196 | sym_size=0x$(printf %x $sym_size) |
| 176 | 197 | |
| 177 | | − # Calculate the section address from user-supplied offset: |
| 178 | | − local addr=$(($sym_addr + $offset)) |
| 198 | + # Calculate the address from user-supplied offset: |
| 199 | + local addr=$(($sym_addr + $func_offset)) |
| 179 | 200 | if [[ -z $addr ]] || [[ $addr = 0 ]]; then |
| 180 | | − warn "bad address: $sym_addr + $offset" |
| 201 | + warn "bad address: $sym_addr + $func_offset" |
| 181 | 202 | DONE=1 |
| 182 | 203 | return |
| 183 | 204 | fi |
| @@ -191,9 +212,9 @@ __faddr2line() { · 7 unmodified lines |
| 191 | 212 | fi |
| 192 | 213 | |
| 193 | 214 | # Make sure the provided offset is within the symbol's range: |
| 194 | | − if [[ $offset -gt $sym_size ]]; then |
| 215 | + if [[ $func_offset -gt $sym_size ]]; then |
| 195 | 216 | [[ $print_warnings = 1 ]] && |
| 196 | | − echo "skipping $sym_name address at $addr due to size mismatch ($offset > $sym_size)" |
| 217 | + echo "skipping $sym_name address at $addr due to size mismatch ($func_offset > $sym_size)" |
| 197 | 218 | continue |
| 198 | 219 | fi |
| 199 | 220 | |
| @@ -202,11 +223,13 @@ __faddr2line() { · 2 unmodified lines |
| 202 | 223 | [[ $FIRST = 0 ]] && echo |
| 203 | 224 | FIRST=0 |
| 204 | 225 | |
| 205 | | − echo "$sym_name+$offset/$sym_size:" |
| 226 | + echo "$sym_name+$func_offset/$sym_size:" |
| 206 | 227 | |
| 207 | 228 | # Pass section address to addr2line and strip absolute paths |
| 208 | 229 | # from the output: |
| 209 | | − local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;") |
| 230 | + local args="--functions --pretty-print --inlines --exe=$objfile" |
| 231 | + [[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name" |
| 232 | + local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;") |
| 210 | 233 | [[ -z $output ]] && continue |
| 211 | 234 | |
| 212 | 235 | # Default output (non --list): |