1 //===- SymbolSize.cpp -----------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Object/SymbolSize.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Object/COFF.h"
13 #include "llvm/Object/ELFObjectFile.h"
14 #include "llvm/Object/MachO.h"
17 using namespace object
;
19 // Orders increasingly by (SectionID, Address).
20 int llvm::object::compareAddress(const SymEntry
*A
, const SymEntry
*B
) {
21 if (A
->SectionID
!= B
->SectionID
)
22 return A
->SectionID
< B
->SectionID
? -1 : 1;
23 if (A
->Address
!= B
->Address
)
24 return A
->Address
< B
->Address
? -1 : 1;
28 static unsigned getSectionID(const ObjectFile
&O
, SectionRef Sec
) {
29 if (auto *M
= dyn_cast
<MachOObjectFile
>(&O
))
30 return M
->getSectionID(Sec
);
31 return cast
<COFFObjectFile
>(O
).getSectionID(Sec
);
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
);
40 std::vector
<std::pair
<SymbolRef
, uint64_t>>
41 llvm::object::computeSymbolSizes(const ObjectFile
&O
) {
42 std::vector
<std::pair
<SymbolRef
, uint64_t>> Ret
;
44 if (const auto *E
= dyn_cast
<ELFObjectFileBase
>(&O
)) {
45 auto Syms
= E
->symbols();
46 if (Syms
.begin() == Syms
.end())
47 Syms
= E
->getDynamicSymbolIterators();
48 for (ELFSymbolRef Sym
: Syms
)
49 Ret
.push_back({Sym
, Sym
.getSize()});
53 // Collect sorted symbol addresses. Include dummy addresses for the end
55 std::vector
<SymEntry
> Addresses
;
57 for (symbol_iterator I
= O
.symbol_begin(), E
= O
.symbol_end(); I
!= E
; ++I
) {
59 uint64_t Value
= Sym
.getValue();
60 Addresses
.push_back({I
, Value
, SymNum
, getSymbolSectionID(O
, Sym
)});
63 for (SectionRef Sec
: O
.sections()) {
64 uint64_t Address
= Sec
.getAddress();
65 uint64_t Size
= Sec
.getSize();
67 {O
.symbol_end(), Address
+ Size
, 0, getSectionID(O
, Sec
)});
70 if (Addresses
.empty())
73 array_pod_sort(Addresses
.begin(), Addresses
.end(), compareAddress
);
75 // Compute the size as the gap to the next symbol
76 for (unsigned I
= 0, N
= Addresses
.size() - 1; I
< N
; ++I
) {
77 auto &P
= Addresses
[I
];
78 if (P
.I
== O
.symbol_end())
81 // If multiple symbol have the same address, give both the same size.
82 unsigned NextI
= I
+ 1;
83 while (NextI
< N
&& Addresses
[NextI
].Address
== P
.Address
)
86 uint64_t Size
= Addresses
[NextI
].Address
- P
.Address
;
90 // Assign the sorted symbols in the original order.
92 for (SymEntry
&P
: Addresses
) {
93 if (P
.I
== O
.symbol_end())
95 Ret
[P
.Number
] = {*P
.I
, P
.Address
};