2
0

SymbolSize.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //===- SymbolSize.cpp -----------------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/Object/SymbolSize.h"
  10. #include "llvm/ADT/STLExtras.h"
  11. #include "llvm/Object/COFF.h"
  12. #include "llvm/Object/ELFObjectFile.h"
  13. #include "llvm/Object/MachO.h"
  14. using namespace llvm;
  15. using namespace object;
  16. namespace {
  17. struct SymEntry {
  18. symbol_iterator I;
  19. uint64_t Address;
  20. unsigned Number;
  21. unsigned SectionID;
  22. };
  23. }
  24. static int __cdecl compareAddress(const SymEntry *A, const SymEntry *B) {
  25. if (A->SectionID != B->SectionID)
  26. return A->SectionID - B->SectionID;
  27. return A->Address - B->Address;
  28. }
  29. static unsigned getSectionID(const ObjectFile &O, SectionRef Sec) {
  30. if (auto *M = dyn_cast<MachOObjectFile>(&O))
  31. return M->getSectionID(Sec);
  32. return cast<COFFObjectFile>(O).getSectionID(Sec);
  33. }
  34. static unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) {
  35. if (auto *M = dyn_cast<MachOObjectFile>(&O))
  36. return M->getSymbolSectionID(Sym);
  37. return cast<COFFObjectFile>(O).getSymbolSectionID(Sym);
  38. }
  39. std::vector<std::pair<SymbolRef, uint64_t>>
  40. llvm::object::computeSymbolSizes(const ObjectFile &O) {
  41. std::vector<std::pair<SymbolRef, uint64_t>> Ret;
  42. if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) {
  43. auto Syms = E->symbols();
  44. if (Syms.begin() == Syms.end())
  45. Syms = E->getDynamicSymbolIterators();
  46. for (ELFSymbolRef Sym : Syms)
  47. Ret.push_back({Sym, Sym.getSize()});
  48. return Ret;
  49. }
  50. // Collect sorted symbol addresses. Include dummy addresses for the end
  51. // of each section.
  52. std::vector<SymEntry> Addresses;
  53. unsigned SymNum = 0;
  54. for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) {
  55. SymbolRef Sym = *I;
  56. uint64_t Value = Sym.getValue();
  57. Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)});
  58. ++SymNum;
  59. }
  60. for (SectionRef Sec : O.sections()) {
  61. uint64_t Address = Sec.getAddress();
  62. uint64_t Size = Sec.getSize();
  63. Addresses.push_back(
  64. {O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)});
  65. }
  66. array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress);
  67. // Compute the size as the gap to the next symbol
  68. for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) {
  69. auto &P = Addresses[I];
  70. if (P.I == O.symbol_end())
  71. continue;
  72. // If multiple symbol have the same address, give both the same size.
  73. unsigned NextI = I + 1;
  74. while (NextI < N && Addresses[NextI].Address == P.Address)
  75. ++NextI;
  76. uint64_t Size = Addresses[NextI].Address - P.Address;
  77. P.Address = Size;
  78. }
  79. // Assign the sorted symbols in the original order.
  80. Ret.resize(SymNum);
  81. for (SymEntry &P : Addresses) {
  82. if (P.I == O.symbol_end())
  83. continue;
  84. Ret[P.Number] = {*P.I, P.Address};
  85. }
  86. return Ret;
  87. }