-
Notifications
You must be signed in to change notification settings - Fork 0
/
elf_binary.h
182 lines (142 loc) · 6.04 KB
/
elf_binary.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright (C) 2021 The sold authors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include "hash.h"
#include "utils.h"
#include <cassert>
#include <limits>
#include <map>
#include <memory>
#include <set>
class ELFBinary {
public:
ELFBinary(const std::string& filename, int fd, char* head, size_t mapped_size, size_t filesize);
~ELFBinary();
static bool IsELF(const char* p);
const std::string& filename() const { return filename_; }
const Elf_Ehdr* ehdr() const { return ehdr_; }
const std::vector<Elf_Phdr*> phdrs() const { return phdrs_; }
std::vector<Elf_Phdr*> phdrs_mut() const { return phdrs_; }
const std::vector<Elf_Phdr*> loads() const { return loads_; }
const Elf_Phdr* dynamic() const { return dynamic_; }
const Elf_Phdr* tls() const { return tls_; }
const Elf_Phdr* gnu_stack() const { return gnu_stack_; }
const Elf_Phdr* gnu_relro() const { return gnu_relro_; }
const std::vector<std::string>& neededs() const { return neededs_; }
const std::string& soname() const { return soname_; }
const std::string& runpath() const { return runpath_; }
const std::string& rpath() const { return rpath_; }
const Elf_Sym* symtab() const { return symtab_; }
Elf_Sym* symtab_mut() const { return symtab_; }
const Elf_Verneed* verneed() const { return verneed_; }
Elf_Verneed* verneed_mut() const { return verneed_; }
const Elf_Versym* versym() const { return versym_; }
Elf_Xword verneednum() const { return verneednum_; }
const Elf_Rel* rel() const { return rel_; }
size_t num_rels() const { return num_rels_; }
const Elf_Rel* plt_rel() const { return plt_rel_; }
size_t num_plt_rels() const { return num_plt_rels_; }
const EHFrameHeader* eh_frame_header() const { return &eh_frame_header_; }
const char* strtab() const { return strtab_; }
size_t dt_strtab() const { return dt_strtab_; }
size_t strsz() const { return strsz_; }
const char* head() const { return head_; }
char* head_mut() const { return head_; }
size_t filesize() const { return filesize_; }
size_t mapped_size() const { return mapped_size_; }
const std::string& name() const { return name_; }
uintptr_t init() const { return init_; }
uintptr_t fini() const { return fini_; }
uintptr_t init_array_addr() const { return init_array_addr_; };
uintptr_t fini_array_addr() const { return fini_array_addr_; };
const std::vector<uintptr_t>& init_array() const { return init_array_; }
const std::vector<uintptr_t>& fini_array() const { return fini_array_; }
const std::vector<Syminfo>& GetSymbolMap() const { return syms_; }
Range GetRange() const;
bool IsAddrInInitarray(uintptr_t addr) const;
bool IsAddrInFiniarray(uintptr_t addr) const;
bool IsVaddrInTLSData(uintptr_t vaddr) const;
bool IsOffsetInTLSData(uintptr_t offset) const;
bool IsOffsetInTLSBSS(uintptr_t offset) const;
std::set<int> CollectSymbolsFromDynamic();
void ReadDynSymtab(const std::map<std::string, std::string>& filename_to_soname);
const char* Str(uintptr_t name) { return strtab_ + name; }
char* GetPtr(uintptr_t offset) { return head_ + OffsetFromAddr(offset); }
Elf_Phdr* FindPhdr(uint64_t type);
const Elf_Phdr& GetPhdr(uint64_t type);
void PrintVerneeds();
void PrintVersyms();
std::string ShowDynSymtab();
std::string ShowDtRela();
std::string ShowVersion();
std::string ShowTLS();
std::string ShowEHFrame();
std::pair<std::string, std::string> GetVersion(int index, const std::map<std::string, std::string>& filename_to_soname);
Elf_Addr OffsetFromAddr(const Elf_Addr addr) const;
Elf_Addr AddrFromOffset(const Elf_Addr offset) const;
private:
void ParsePhdrs();
void ParseEHFrameHeader(size_t off, size_t size);
void ParseDynamic(size_t off, size_t size);
void ParseFuncArray(uintptr_t* array, uintptr_t size, std::vector<uintptr_t>* out);
const std::string filename_;
int fd_;
char* head_;
size_t filesize_;
size_t mapped_size_;
Elf_Ehdr* ehdr_{nullptr};
std::vector<Elf_Phdr*> phdrs_;
std::vector<Elf_Phdr*> loads_;
Elf_Phdr* dynamic_{nullptr};
Elf_Phdr* tls_{nullptr};
Elf_Phdr* gnu_stack_{nullptr};
Elf_Phdr* gnu_relro_{nullptr};
const char* strtab_{nullptr};
size_t dt_strtab_{0}; // For delete_unused_DT_STRTAB option
size_t strsz_{0};
Elf_Sym* symtab_{nullptr};
EHFrameHeader eh_frame_header_;
std::vector<std::string> neededs_;
// This is the name specified in the DT_SONAME field.
std::string soname_;
std::string runpath_;
std::string rpath_;
Elf_Rel* rel_{nullptr};
size_t num_rels_{0};
Elf_Rel* plt_rel_{nullptr};
size_t num_plt_rels_{0};
Elf_GnuHash* gnu_hash_{nullptr};
Elf_Hash* hash_{nullptr};
uintptr_t* init_array_offset_{0};
uintptr_t init_arraysz_{0};
uintptr_t init_array_addr_{0};
uintptr_t* fini_array_offset_{0};
uintptr_t fini_array_addr_{0};
uintptr_t fini_arraysz_{0};
uintptr_t init_{0};
uintptr_t fini_{0};
std::vector<uintptr_t> init_array_;
std::vector<uintptr_t> fini_array_;
// This is the name on the filsysytem
std::string name_;
std::vector<Syminfo> syms_;
int nsyms_{0};
Elf_Versym* versym_{nullptr};
Elf_Verneed* verneed_{nullptr};
Elf_Verdef* verdef_{nullptr};
Elf_Xword verneednum_{0};
Elf_Xword verdefnum_{0};
};
std::unique_ptr<ELFBinary> ReadELF(const std::string& filename);