abilist.awk 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. # This awk script processes the output of objdump --dynamic-syms
  2. # into a simple format that should not change when the ABI is not changing.
  3. BEGIN {
  4. if (combine_fullname)
  5. combine = 1;
  6. if (combine)
  7. parse_names = 1;
  8. }
  9. # Per-file header.
  10. /[^ :]+\.so\.[0-9.]+:[ ]+.file format .*$/ {
  11. emit(0);
  12. seen_opd = 0;
  13. sofullname = $1;
  14. sub(/:$/, "", sofullname);
  15. soname = sofullname;
  16. sub(/^.*\//, "", soname);
  17. sub(/\.so\.[0-9.]+$/, "", soname);
  18. suppress = ((filename_regexp != "" && sofullname !~ filename_regexp) \
  19. || (libname_regexp != "" && soname !~ libname_regexp));
  20. next
  21. }
  22. suppress { next }
  23. # Normalize columns.
  24. /^[0-9a-fA-F]+ / { sub(/ /, " - ") }
  25. # Skip undefineds.
  26. $4 == "*UND*" { next }
  27. # Skip locals.
  28. $2 == "l" { next }
  29. # If the target uses ST_OTHER, it will be output before the symbol name.
  30. $2 == "g" || $2 == "w" && (NF == 7 || NF == 8) {
  31. type = $3;
  32. size = $5;
  33. sub(/^0*/, "", size);
  34. if (size == "") {
  35. size = " 0x0";
  36. } else {
  37. size = " 0x" size;
  38. }
  39. version = $6;
  40. symbol = $NF;
  41. gsub(/[()]/, "", version);
  42. # binutils versions up through at least 2.23 have some bugs that
  43. # caused STV_HIDDEN symbols to appear in .dynsym, though that is useless.
  44. if (NF > 7 && $7 == ".hidden") next;
  45. if (version ~ /^GLIBC_ABI_/ && !include_abi_version) next;
  46. if (version == "GLIBC_PRIVATE" && !include_private) next;
  47. desc = "";
  48. if (type == "D" && ($4 == ".tbss" || $4 == ".tdata")) {
  49. type = "T";
  50. }
  51. else if (type == "D" && $4 == ".opd") {
  52. type = "F";
  53. size = "";
  54. if (seen_opd < 0)
  55. type = "O";
  56. seen_opd = 1;
  57. }
  58. else if (type == "D" && NF == 8 && $7 == "0x80") {
  59. # Alpha functions avoiding plt entry in users
  60. type = "F";
  61. size = "";
  62. seen_opd = -1;
  63. }
  64. else if ($4 == "*ABS*") {
  65. next;
  66. }
  67. else if (type == "D") {
  68. # Accept unchanged.
  69. }
  70. else if (type == "DO") {
  71. type = "D";
  72. }
  73. else if (type == "DF") {
  74. if (symbol ~ /^\./ && seen_opd >= 0)
  75. next;
  76. seen_opd = -1;
  77. type = "F";
  78. size = "";
  79. }
  80. else if (type == "iD" && ($4 == ".text" || $4 == ".opd")) {
  81. # Indirect functions.
  82. type = "F";
  83. size = "";
  84. }
  85. else {
  86. print "ERROR: Unable to handle this type of symbol:", $0
  87. exit 1
  88. }
  89. if (desc == "")
  90. desc = symbol " " type size;
  91. if (combine)
  92. version = soname " " version (combine_fullname ? " " sofullname : "");
  93. # Append to the string which collects the results.
  94. descs = descs version " " desc "\n";
  95. next;
  96. }
  97. # Header crapola.
  98. NF == 0 || /DYNAMIC SYMBOL TABLE/ || /file format/ { next }
  99. {
  100. print "ERROR: Unable to interpret this line:", $0
  101. exit 1
  102. }
  103. function emit(end) {
  104. if (!end && (combine || ! parse_names || soname == ""))
  105. return;
  106. tofile = parse_names && !combine;
  107. if (tofile) {
  108. out = prefix soname ".symlist";
  109. if (soname in outfiles)
  110. out = out "." ++outfiles[soname];
  111. else
  112. outfiles[soname] = 1;
  113. outpipe = "LC_ALL=C sort -u > " out;
  114. } else {
  115. outpipe = "LC_ALL=C sort -u";
  116. }
  117. printf "%s", descs | outpipe;
  118. descs = "";
  119. if (tofile)
  120. print "wrote", out, "for", sofullname;
  121. }
  122. END {
  123. emit(1);
  124. }