-
Notifications
You must be signed in to change notification settings - Fork 148
/
Object-elf.h
508 lines (425 loc) · 17.3 KB
/
Object-elf.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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
/*
* See the dyninst/COPYRIGHT file for copyright information.
*
* We provide the Paradyn Tools (below described as "Paradyn")
* on an AS IS basis, and do not warrant its validity or performance.
* We reserve the right to update, modify, or discontinue this
* software at any time. We shall have no obligation to supply such
* updates or modifications or any other form of support to you.
*
* By your use of Paradyn, you understand and agree that we (or any
* other person or entity with proprietary rights in Paradyn) are
* under no obligation to provide either maintenance services,
* update services, notices of latent defects, or correction of
* defects for Paradyn.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/************************************************************************
* $Id: Object-elf.h,v 1.21 2008/06/23 18:45:42 legendre Exp $
* Object-elf.h: Object class for ELF file format
************************************************************************/
#if !defined(_Object_elf_h_)
#define _Object_elf_h_
#if defined(cap_dwarf)
//#include "dwarf.h"
#include "elfutils/libdw.h"
#include "dwarfHandle.h"
#endif
#include <assert.h>
#include <ostream>
#include <map>
#include <stddef.h>
#include <unordered_map>
#include <utility>
#include <vector>
#include "headers.h"
#include "MappedFile.h"
#include "IntervalTree.h"
#include "Module.h"
#include <elf.h>
#include <libelf.h>
#include <string>
#include "Elf_X.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <set>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
namespace Dyninst{
namespace DwarfDyninst {
class DwarfFrameParser;
typedef boost::shared_ptr<DwarfFrameParser> DwarfFrameParserPtr;
}
namespace SymtabAPI{
class pdElfShdr;
class Symtab;
class Region;
class Object;
class InlinedFunction;
class open_statement {
public:
open_statement() { reset(); }
open_statement(const open_statement&) = default;
Dwarf_Addr noAddress() { return (Dwarf_Addr) ~0; }
bool uninitialized() {
return start_addr == noAddress();
}
void reset() {
string_table_index = -1;
start_addr = noAddress();
end_addr = noAddress();
line_number = 0;
column_number = 0;
context = nullptr;
funcname = nullptr;
}
bool sameFileLineColumn(const open_statement &rhs) {
return ((string_table_index == rhs.string_table_index) &&
(line_number == rhs.line_number) &&
(column_number == rhs.column_number));
}
void operator=(const open_statement &rhs) {
string_table_index = rhs.string_table_index;
start_addr = rhs.start_addr;
end_addr = rhs.end_addr;
line_number = rhs.line_number;
column_number = rhs.column_number;
context = rhs.context;
funcname = rhs.funcname;
}
friend std::ostream& operator<<(std::ostream& os, const open_statement& st)
{
st.dump(os, true);
return os;
}
void dump(std::ostream& os, bool addrRange) const {
// to facilitate comparison with nvdisasm output, where each function starts at 0,
// set o to an offset that makes a function of interest report addresses that
// match its unrelocated offsets reported by nvdisasm
unsigned int o = 0;
if (addrRange) os << "[" << std::hex << start_addr - o << ", " << end_addr - o << "]";
else os << " inlined at";
os << " file:" << string_table_index;
os << " line:" << std::dec << line_number;
os << " col:" << column_number;
if (context != nullptr) {
os << " context " << context;
os << " function name " << funcname;
}
os << std::endl;
}
public:
Dwarf_Word string_table_index;
Dwarf_Addr start_addr;
Dwarf_Addr end_addr;
int line_number;
int column_number;
Dwarf_Line* context;
const char* funcname;
};
class Object : public AObject
{
friend class Module;
// declared but not implemented; no copying allowed
Object(const Object &);
const Object& operator=(const Object &);
public:
Object(MappedFile *, bool, void (*)(const char *) = log_msg, bool alloc_syms = true, Symtab* st = NULL);
virtual ~Object();
bool emitDriver(std::string fName, std::set<Symbol *> &allSymbols, unsigned flag);
bool hasDwarfInfo() const { return dwarvenDebugInfo; }
void getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs);
void parseFileLineInfo();
void parseTypeInfo();
void addModule(SymtabAPI::Module* m) override;
bool needs_function_binding() const { return (plt_addr_ > 0); }
bool get_func_binding_table(std::vector<relocationEntry> &fbt) const;
bool get_func_binding_table_ptr(const std::vector<relocationEntry> *&fbt) const;
void getDependencies(std::vector<std::string> &deps);
std::vector<std::string> &libsRMd();
bool addRelocationEntry(relocationEntry &re);
//getLoadAddress may return 0 on shared objects
Offset getLoadAddress() const { return loadAddress_; }
Offset getEntryAddress() const { return entryAddress_; }
// To be changed later - Giri
Offset getBaseAddress() const { return 0; }
static bool truncateLineFilenames;
void insertPrereqLibrary(std::string libname);
bool removePrereqLibrary(std::string libname);
void insertDynamicEntry(long name, long value);
virtual char *mem_image() const
{
assert(mf);
return (char *)mf->base_addr();
}
SYMTAB_EXPORT ObjectType objType() const;
const char *interpreter_name() const;
// On most platforms, the TOC offset doesn't exist and is thus null.
// On PPC64, it varies _by function_ and is used to point into the GOT,
// a big data table. We can look it up by parsing the OPD, a function
// descriptor table.
Offset getTOCoffset(Offset off) const;
// This is an override for the whole thing; we could do per-function but
// we're missing a _lot_ of hardware for that.
void setTOCoffset(Offset off);
const std::ostream &dump_state_info(std::ostream &s);
bool isEEL() { return EEL; }
//to determine if a mutation falls in the text section of
// a shared library
bool isinText(Offset addr, Offset baseaddr) const {
if(addr > text_addr_ + baseaddr &&
addr < text_addr_ + baseaddr + text_size_ ) {
return true;
}
return false;
}
// to determine where in the .plt this function is listed
// returns an offset from the base address of the object
// so the entry can easily be located in memory
Offset getPltSlot(std::string funcName) const ;
bool isText( Offset addr ) const
{
if( addr >= text_addr_ && addr <= text_addr_ + text_size_ )
return true;
return false;
}
Dyninst::Architecture getArch() const;
bool isBigEndianDataEncoding() const;
bool getABIVersion(int &major, int &minor) const;
bool is_offset_in_plt(Offset offset) const;
Elf_X_Shdr *getRegionHdrByAddr(Offset addr);
int getRegionHdrIndexByAddr(Offset addr);
Elf_X_Shdr *getRegionHdrByIndex(unsigned index);
bool isRegionPresent(Offset segmentStart, Offset segmentSize, unsigned newPerms);
bool getRegValueAtFrame(Address pc,
Dyninst::MachRegister reg,
Dyninst::MachRegisterVal ®_result,
MemRegReader *reader);
bool hasFrameDebugInfo();
bool convertDebugOffset(Offset off, Offset &new_off);
std::vector< std::vector<Offset> > getMoveSecAddrRange() const {return moveSecAddrRange;}
dyn_hash_map<int, Region*> getTagRegionMapping() const { return secTagRegionMapping;}
bool hasReldyn() const {return hasReldyn_;}
bool hasReladyn() const {return hasReladyn_;}
bool hasRelplt() const {return hasRelplt_;}
bool hasRelaplt() const {return hasRelaplt_;}
bool hasNoteSection() const {return hasNoteSection_;}
Region::RegionType getRelType() const { return relType_; }
Offset getTextAddr() const {return text_addr_;}
Offset getSymtabAddr() const {return symtab_addr_;}
Offset getStrtabAddr() const {return strtab_addr_;}
Offset getDynamicAddr() const {return dynamic_addr_;}
Offset getDynsymSize() const {return dynsym_size_;}
Offset getElfHashAddr() const {return elf_hash_addr_;}
Offset getGnuHashAddr() const {return gnu_hash_addr_;}
Offset getRelPLTAddr() const { return rel_plt_addr_; }
Offset getRelPLTSize() const { return rel_plt_size_; }
Offset getRelDynAddr() const { return rel_addr_; }
Offset getRelDynSize() const { return rel_size_; }
const char* getSoname() const { return soname_; }
bool hasPieFlag() const { return hasPieFlag_; }
bool hasProgramLoad() const { return hasProgramLoad_; }
bool hasDtDebug() const { return hasDtDebug_; }
bool hasBitsAlloc() const { return hasBitsAlloc_; }
bool hasDebugSections() const { return hasDebugSections_; }
bool hasModinfo() const { return hasModinfo_; }
bool hasGnuLinkonceThisModule() const { return hasGnuLinkonceThisModule_; }
bool isLoadable() const;
SYMTAB_EXPORT bool isOnlyExecutable() const;
SYMTAB_EXPORT bool isExecutable() const;
SYMTAB_EXPORT bool isSharedLibrary() const;
SYMTAB_EXPORT bool isOnlySharedLibrary() const;
SYMTAB_EXPORT bool isDebugOnly() const;
SYMTAB_EXPORT bool isLinuxKernelModule() const;
std::vector<relocationEntry> &getPLTRelocs() { return fbt_; }
std::vector<relocationEntry> &getDynRelocs() { return relocation_table_; }
Offset getInitAddr() const {return init_addr_; }
Offset getFiniAddr() const { return fini_addr_; }
virtual void setTruncateLinePaths(bool value);
virtual bool getTruncateLinePaths();
Elf_X * getElfHandle() { return elfHdr; }
unsigned gotSize() const { return got_size_; }
Offset gotAddr() const { return got_addr_; }
SYMTAB_EXPORT virtual void getSegmentsSymReader(std::vector<SymSegment> &segs);
private:
std::vector<std::vector<boost::shared_ptr<void> > > freeList;
static void log_elferror (void (*)(const char *), const char *);
Elf_X *elfHdr;
std::vector< std::vector<Offset> > moveSecAddrRange;
dyn_hash_map<Offset, int> secAddrTagMapping;
dyn_hash_map<int, unsigned long> secTagSizeMapping;
dyn_hash_map<int, Region*> secTagRegionMapping;
bool hasReldyn_;
bool hasReladyn_;
bool hasRelplt_;
bool hasRelaplt_;
Region::RegionType relType_;
bool hasNoteSection_;
Offset elf_hash_addr_; //.hash section
Offset gnu_hash_addr_; //.gnu.hash section
Offset dynamic_offset_;
size_t dynamic_size_;
size_t dynsym_size_;
Offset init_addr_;
Offset fini_addr_;
Offset text_addr_; //.text section
Offset text_size_; //.text section size
Offset symtab_addr_;
Offset strtab_addr_;
Offset dynamic_addr_; //.dynamic section
Offset dynsym_addr_; // .dynsym section
Offset dynstr_addr_; // .dynstr section
Offset got_addr_; // global offset table
unsigned got_size_; // global offset table
Offset plt_addr_; // procedure linkage table
unsigned plt_size_; // procedure linkage table
unsigned plt_entry_size_; // procedure linkage table
Offset rel_plt_addr_; // .rel[a].plt section
unsigned rel_plt_size_; // .rel[a].plt section
unsigned rel_plt_entry_size_; // .rel[a].plt section
Offset rel_addr_;
unsigned rel_size_; // DT_REL/DT_RELA in dynamic section
unsigned rel_entry_size_; // DT_REL/DT_RELA in dynamic section
Offset opd_addr_;
unsigned opd_size_;
bool dwarvenDebugInfo; // is DWARF debug info present?
Offset loadAddress_; // The object may specify a load address
// Set to 0 if it may load anywhere
Offset entryAddress_;
char *interpreter_name_;
bool hasPieFlag_;
bool hasDtDebug_;
bool hasProgramLoad_;
bool hasBitsAlloc_;
bool hasDebugSections_;
bool hasModinfo_;
bool hasGnuLinkonceThisModule_;
bool isStripped;
std::map<Offset, Offset> TOC_table_;
public:
Dyninst::DwarfDyninst::DwarfHandle::ptr dwarf;
private:
bool EEL; // true if EEL rewritten
bool did_open; // true if the file has been mmapped
ObjectType obj_type_;
// for sparc-solaris this is a table of PLT entry addr, function_name
// for x86-solaris this is a table of GOT entry addr, function_name
// on sparc-solaris the runtime linker modifies the PLT entry when it
// binds a function, on X86 the PLT entry is not modified, but it uses
// an indirect jump to a GOT entry that is modified when the function
// is bound....is this correct???? or should it be <PLTentry_addr, name>
// for both?
std::vector<relocationEntry> relocation_table_;
std::vector<relocationEntry> fbt_;
// all section headers, sorted by address
// we use these to do a better job of finding the end of symbols
std::vector<Elf_X_Shdr*> allRegionHdrs;
std::vector<Elf_X_Shdr*> allRegionHdrsByShndx;
// Symbol version mappings. used to store symbol version names.
dyn_hash_map<unsigned, std::vector<std::string> >versionMapping;
dyn_hash_map<unsigned, std::string> versionFileNameMapping;
std::vector<std::string> deps_;
std::vector<std::string> rmd_deps;
bool loaded_elf( Offset &, Offset &,
Elf_X_Shdr* &,
Elf_X_Shdr* &, Elf_X_Shdr* &,
Elf_X_Shdr*& rel_plt_scnp, Elf_X_Shdr*& plt_scnp,
Elf_X_Shdr*& got_scnp, Elf_X_Shdr*& dynsym_scnp,
Elf_X_Shdr*& dynstr_scnp, Elf_X_Shdr*& dynamic_scnp, Elf_X_Shdr*& eh_frame,
Elf_X_Shdr*& gcc_except, Elf_X_Shdr *& interp_scnp,
Elf_X_Shdr *&opd_scnp, Elf_X_Shdr*& symtab_shndx_scnp,
bool a_out=false);
Symbol *handle_opd_symbol(Region *opd, Symbol *sym);
void handle_opd_relocations();
void parse_opd(Elf_X_Shdr *);
public:
void parseDwarfFileLineInfo();
void parseLineInfoForAddr(Offset addr_to_find);
bool hasDebugInfo();
private:
void parseLineInfoForCU(Offset offset, LineInformation* li);
void recordLine(
Region *debug_str,
open_statement &saved_statement,
std::vector<open_statement> &inline_context
);
InlinedFunction* recordAnInlinedFunction(
open_statement&,
open_statement&,
StringTablePtr,
FunctionBase*,
Dwarf_Addr,
Dwarf_Addr
);
void lookupInlinedContext( std::vector<open_statement> &, open_statement &);
LineInformation* li_for_object;
LineInformation* parseLineInfoForObject(StringTablePtr strings);
void parseDwarfTypes(Symtab *obj);
void load_object(bool);
// initialize relocation_table_ from .rel[a].plt section entries
bool get_relocation_entries(Elf_X_Shdr *&rel_plt_scnp,
Elf_X_Shdr *&dynsym_scnp,
Elf_X_Shdr *&dynstr_scnp);
bool get_relocationDyn_entries( unsigned rel_index,
Elf_X_Shdr *&dynsym_scnp,
Elf_X_Shdr *&dynstr_scnp );
// Parses sections with relocations and links these relocations to
// existing symbols
bool parse_all_relocations(Elf_X_Shdr *, Elf_X_Shdr *,
Elf_X_Shdr *, Elf_X_Shdr *);
void parseDynamic(Elf_X_Shdr *& dyn_scnp, Elf_X_Shdr *&dynsym_scnp,
Elf_X_Shdr *&dynstr_scnp);
bool parse_symbols(Elf_X_Data &symdata, Elf_X_Data &strdata,
Elf_X_Shdr* bssscnp,
Elf_X_Shdr* symscnp,
Elf_X_Shdr* symtab_shndx_scnp,
bool shared_library);
void parse_dynamicSymbols( Elf_X_Shdr *& dyn_scnp, Elf_X_Data &symdata,
Elf_X_Data &strdata, bool shared_library);
void find_code_and_data(Elf_X &elf,
Offset txtaddr, Offset dataddr);
bool fix_global_symbol_modules_static_dwarf();
void get_valid_memory_areas(Elf_X &elf);
bool find_catch_blocks(Elf_X_Shdr *eh_frame, Elf_X_Shdr *except_scn,
Address textaddr, Address dataaddr,
std::vector<ExceptionBlock> &catch_addrs);
// Line info: CUs to skip
std::set<std::string> modules_parsed_for_line_info;
public:
struct DbgAddrConversion_t {
DbgAddrConversion_t() : dbg_offset(0x0), dbg_size(0x0), orig_offset(0x0) {}
std::string name;
Offset dbg_offset;
unsigned dbg_size;
Offset orig_offset;
};
private:
bool DbgSectionMapSorted;
dyn_mutex dsm_lock;
std::vector<DbgAddrConversion_t> DebugSectionMap;
public:
std::set<std::string> prereq_libs;
std::vector<std::pair<long, long> > new_dynamic_entries;
private:
const char* soname_;
Function* containingFunc;
std::unordered_map<void*, std::vector<open_statement> > contextMap;
};
}//namespace SymtabAPI
}//namespace Dyninst
#endif /* !defined(_Object_elf_h_) */