1 //===- SymbolSize.cpp -----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
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"
16 using namespace object
;
18 // Orders increasingly by (SectionID, Address).
19 int llvm::object::compareAddress(const SymEntry
*A
, const SymEntry
*B
) {
20 if (A
->SectionID
!= B
->SectionID
)
21 return A
->SectionID
< B
->SectionID
? -1 : 1;
22 if (A
->Address
!= B
->Address
)
23 return A
->Address
< B
->Address
? -1 : 1;
27 static unsigned getSectionID(const ObjectFile
&O
, SectionRef Sec
) {
28 if (auto *M
= dyn_cast
<MachOObjectFile
>(&O
))
29 return M
->getSectionID(Sec
);
30 return cast
<COFFObjectFile
>(O
).getSectionID(Sec
);
33 static unsigned getSymbolSectionID(const ObjectFile
&O
, SymbolRef Sym
) {
34 if (auto *M
= dyn_cast
<MachOObjectFile
>(&O
))
35 return M
->getSymbolSectionID(Sym
);
36 return cast
<COFFObjectFile
>(O
).getSymbolSectionID(Sym
);
39 std::vector
<std::pair
<SymbolRef
, uint64_t>>
40 llvm::object::computeSymbolSizes(const ObjectFile
&O
) {
41 std::vector
<std::pair
<SymbolRef
, uint64_t>> Ret
;
43 if (const auto *E
= dyn_cast
<ELFObjectFileBase
>(&O
)) {
44 auto Syms
= E
->symbols();
45 if (Syms
.begin() == Syms
.end())
46 Syms
= E
->getDynamicSymbolIterators();
47 for (ELFSymbolRef Sym
: Syms
)
48 Ret
.push_back({Sym
, Sym
.getSize()});
52 // Collect sorted symbol addresses. Include dummy addresses for the end
54 std::vector
<SymEntry
> Addresses
;
56 for (symbol_iterator I
= O
.symbol_begin(), E
= O
.symbol_end(); I
!= E
; ++I
) {
58 uint64_t Value
= Sym
.getValue();
59 Addresses
.push_back({I
, Value
, SymNum
, getSymbolSectionID(O
, Sym
)});
62 for (SectionRef Sec
: O
.sections()) {
63 uint64_t Address
= Sec
.getAddress();
64 uint64_t Size
= Sec
.getSize();
66 {O
.symbol_end(), Address
+ Size
, 0, getSectionID(O
, Sec
)});
69 if (Addresses
.empty())
72 array_pod_sort(Addresses
.begin(), Addresses
.end(), compareAddress
);
74 // Compute the size as the gap to the next symbol
75 for (unsigned I
= 0, N
= Addresses
.size() - 1; I
< N
; ++I
) {
76 auto &P
= Addresses
[I
];
77 if (P
.I
== O
.symbol_end())
80 // If multiple symbol have the same address, give both the same size.
81 unsigned NextI
= I
+ 1;
82 while (NextI
< N
&& Addresses
[NextI
].Address
== P
.Address
)
85 uint64_t Size
= Addresses
[NextI
].Address
- P
.Address
;
89 // Assign the sorted symbols in the original order.
91 for (SymEntry
&P
: Addresses
) {
92 if (P
.I
== O
.symbol_end())
94 Ret
[P
.Number
] = {*P
.I
, P
.Address
};