1# This awk script expects to get command-line files that are each 2# the output of 'readelf -WSdr' on a single shared object, and named 3# .../NAME.jmprel where NAME is the unadorned file name of the shared object. 4# It writes "NAME: SYMBOL" for each PLT entry in NAME that refers to a 5# symbol defined in the same object. 6 7BEGIN { result = 0 } 8 9FILENAME != lastfile { 10 if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0) { 11 print FILENAME ": *** failed to find expected output (readelf -WSdr)"; 12 result = 2; 13 } 14 lastfile = FILENAME; 15 jmprel_offset = 0; 16 rela_offset = 0; 17 rel_offset = 0; 18 delete section_offset_by_address; 19} 20 21/^Section Headers:/ { in_shdrs = 1; next } 22in_shdrs && !/^ +\[/ { in_shdrs = 0 } 23 24in_shdrs && /^ +\[/ { sub(/\[ +/, "[") } 25in_shdrs { 26 address = strtonum("0x" $4); 27 offset = strtonum("0x" $5); 28 section_offset_by_address[address] = offset; 29} 30 31in_shdrs { next } 32 33$1 == "Offset" && $2 == "Info" { in_relocs = 1; next } 34NF == 0 { in_relocs = 0 } 35 36in_relocs && relocs_offset == jmprel_offset && NF >= 5 { 37 # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal 38 # value, but rather as the resolver symbol followed by (). 39 if ($4 ~ /\(\)/) { 40 print whatfile, gensub(/@.*/, "", "g", $5) 41 } else { 42 symval = strtonum("0x" $4); 43 if (symval != 0) 44 print whatfile, gensub(/@.*/, "", "g", $5) 45 } 46} 47 48in_relocs && relocs_offset == rela_offset && NF >= 5 { 49 # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal 50 # value, but rather as the resolver symbol followed by (). 51 if ($4 ~ /\(\)/) { 52 print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3 53 } else { 54 symval = strtonum("0x" $4); 55 if (symval != 0) 56 print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3 57 } 58} 59 60in_relocs && relocs_offset == rel_offset && NF >= 5 { 61 # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal 62 # value, but rather as the resolver symbol followed by (). 63 if ($4 ~ /\(\)/) { 64 print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3 65 } else { 66 symval = strtonum("0x" $4); 67 if (symval != 0) 68 print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3 69 } 70} 71 72in_relocs { next } 73 74$1 == "Relocation" && $2 == "section" && $5 == "offset" { 75 relocs_offset = strtonum($6); 76 whatfile = gensub(/^.*\/([^/]+)\.jmprel$/, "\\1:", 1, FILENAME); 77 next 78} 79 80$2 == "(JMPREL)" { 81 jmprel_addr = strtonum($3); 82 if (jmprel_addr in section_offset_by_address) { 83 jmprel_offset = section_offset_by_address[jmprel_addr]; 84 } else { 85 print FILENAME ": *** DT_JMPREL does not match any section's address"; 86 result = 2; 87 } 88 next 89} 90 91$2 == "(RELA)" { 92 rela_addr = strtonum($3); 93 if (rela_addr in section_offset_by_address) { 94 rela_offset = section_offset_by_address[rela_addr]; 95 } else { 96 print FILENAME ": *** DT_RELA does not match any section's address"; 97 result = 2; 98 } 99 next 100} 101 102$2 == "(REL)" { 103 rel_addr = strtonum($3); 104 if (rel_addr in section_offset_by_address) { 105 rel_offset = section_offset_by_address[rel_addr]; 106 } else { 107 print FILENAME ": *** DT_REL does not match any section's address"; 108 result = 2; 109 } 110 next 111} 112END { exit(result) } 113