# This awk script expects to get command-line files that are each # the output of 'readelf -WSdr' on a single shared object, and named # .../NAME.jmprel where NAME is the unadorned file name of the shared object. # It writes "NAME: SYMBOL" for each PLT entry in NAME that refers to a # symbol defined in the same object. BEGIN { result = 0 } FILENAME != lastfile { if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0) { print FILENAME ": *** failed to find expected output (readelf -WSdr)"; result = 2; } lastfile = FILENAME; jmprel_offset = 0; rela_offset = 0; rel_offset = 0; delete section_offset_by_address; } /^Section Headers:/ { in_shdrs = 1; next } in_shdrs && !/^ +\[/ { in_shdrs = 0 } in_shdrs && /^ +\[/ { sub(/\[ +/, "[") } in_shdrs { address = strtonum("0x" $4); offset = strtonum("0x" $5); section_offset_by_address[address] = offset; } in_shdrs { next } $1 == "Offset" && $2 == "Info" { in_relocs = 1; next } NF == 0 { in_relocs = 0 } in_relocs && relocs_offset == jmprel_offset && NF >= 5 { # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal # value, but rather as the resolver symbol followed by (). if ($4 ~ /\(\)/) { print whatfile, gensub(/@.*/, "", "g", $5) } else { symval = strtonum("0x" $4); if (symval != 0) print whatfile, gensub(/@.*/, "", "g", $5) } } in_relocs && relocs_offset == rela_offset && NF >= 5 { # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal # value, but rather as the resolver symbol followed by (). if ($4 ~ /\(\)/) { print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3 } else { symval = strtonum("0x" $4); if (symval != 0) print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3 } } in_relocs && relocs_offset == rel_offset && NF >= 5 { # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal # value, but rather as the resolver symbol followed by (). if ($4 ~ /\(\)/) { print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3 } else { symval = strtonum("0x" $4); if (symval != 0) print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3 } } in_relocs { next } $1 == "Relocation" && $2 == "section" && $5 == "offset" { relocs_offset = strtonum($6); whatfile = gensub(/^.*\/([^/]+)\.jmprel$/, "\\1:", 1, FILENAME); next } $2 == "(JMPREL)" { jmprel_addr = strtonum($3); if (jmprel_addr in section_offset_by_address) { jmprel_offset = section_offset_by_address[jmprel_addr]; } else { print FILENAME ": *** DT_JMPREL does not match any section's address"; result = 2; } next } $2 == "(RELA)" { rela_addr = strtonum($3); if (rela_addr in section_offset_by_address) { rela_offset = section_offset_by_address[rela_addr]; } else { print FILENAME ": *** DT_RELA does not match any section's address"; result = 2; } next } $2 == "(REL)" { rel_addr = strtonum($3); if (rel_addr in section_offset_by_address) { rel_offset = section_offset_by_address[rel_addr]; } else { print FILENAME ": *** DT_REL does not match any section's address"; result = 2; } next } END { exit(result) }