eh_frame.h
Go to the documentation of this file.
1 //
2 // Bareflank Unwind Library
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #ifndef EH_FRAME_H
23 #define EH_FRAME_H
24 
25 #include <stdint.h>
26 #include <constants.h>
27 #include <eh_frame_list.h>
28 #include <registers_intel_x64.h>
29 
30 class common_entry;
31 class ci_entry;
32 class fd_entry;
33 
34 // -----------------------------------------------------------------------------
35 // Overview
36 // -----------------------------------------------------------------------------
37 //
38 // Exception Handling Framework (eh_frame) is based on the DWARF specification.
39 // This implementation uses the DWARF 4 specification, but the actual format
40 // is defined here (as there are some differences):
41 //
42 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic.pdf
43 //
44 // In addition to the above specification, Ian Lance Taylor has a great
45 // explanation of this section on his blog:
46 //
47 // http://www.airs.com/blog/archives/460
48 // http://www.airs.com/blog/archives/462
49 // http://www.airs.com/blog/archives/464
50 //
51 // and there is another good explanation of this information here:
52 //
53 // http://www.deadp0rk.com/2013/09/22/base_abi/
54 //
55 // Notes:
56 //
57 // - This implementation is not optimized for performance. Exception handling
58 // in bareflank should not be used for flow control, but rather for error
59 // handling (which should not happen often)
60 //
61 // - The specification is written for 32bit and 64bit. This implementation
62 // only supports 64bit.
63 //
64 // - readelf can be used to parse the .eh_frame section, and provide all of
65 // the information that this code should be capable of parsing. Use the
66 // --debug-dump=frames flag with a binary or shared module.
67 //
68 // - If you see a function that takes a char **addr, it will use the addr and
69 // then advance the addr based on the operation performed. This is because
70 // the way this spec is written, decoding everything is done in a linear
71 // fashion, and each operation is compressed, so you don't know how much to
72 // advance the pointer until you decode the operation.
73 //
74 // In addition to this implementation, there are two other implementations that
75 // could provide useful information:
76 //
77 // http://www.nongnu.org/libunwind/
78 // https://github.com/llvm-mirror/libunwind
79 //
80 
81 // -----------------------------------------------------------------------------
82 // DWARF Extensions (section 10.5)
83 // -----------------------------------------------------------------------------
84 //
85 // The Exception Handler Framework in our version of the LSB uses the DWARF 4
86 // spec, but does so by applying the following extensions
87 //
88 
89 // -----------------------------------------------------------------------------
90 // DWARF Exception Header Encoding (section 10.5.1)
91 // -----------------------------------------------------------------------------
92 //
93 // An EH encoding is a byte, with the lower 4 bits describing the format of the
94 // pointer, and the upper 4 bits describing how the pointer should be applied.
95 //
96 
97 // Data Format
98 #define DW_EH_PE_absptr 0x00
99 #define DW_EH_PE_uleb128 0x01
100 #define DW_EH_PE_udata2 0x02
101 #define DW_EH_PE_udata4 0x03
102 #define DW_EH_PE_udata8 0x04
103 #define DW_EH_PE_sleb128 0x09
104 #define DW_EH_PE_sdata2 0x0A
105 #define DW_EH_PE_sdata4 0x0B
106 #define DW_EH_PE_sdata8 0x0C
107 
108 // Data Application
109 #define DW_EH_PE_pcrel 0x10
110 #define DW_EH_PE_textrel 0x20
111 #define DW_EH_PE_datarel 0x30
112 #define DW_EH_PE_funcrel 0x40
113 #define DW_EH_PE_aligned 0x50
114 
115 // Special
116 #define DW_EH_PE_omit 0xFF
117 
137 uint64_t decode_pointer(char **addr, uint64_t encoding);
138 
139 // -----------------------------------------------------------------------------
140 // DWARF Call Frame Instruction (CFI) Extensions (section 10.5.2)
141 // -----------------------------------------------------------------------------
142 //
143 // These extend the call frame instructions that are defined in the DWARF 4
144 // specification.
145 //
146 
147 #define DW_CFA_GNU_args_size 0x2E
148 #define DW_CFA_GNU_negative_offset_extended 0x2F
149 
150 // -----------------------------------------------------------------------------
151 // .eh_frame Section (section 10.6.1)
152 // -----------------------------------------------------------------------------
153 //
154 // The .eh_frame section is located in each compiled unit (binary or shared
155 // module). It contains one or more Call Frame Information structures (not
156 // to be confusd with the Call Frame Instructions which are defined in the
157 // DWARF portion of this code). The CFI structures have the following format:
158 //
159 // CFI
160 // ---------------------
161 // - CIE -
162 // - FDE -
163 // - FDE -
164 // ---------------------
165 // - CIE -
166 // - FDE -
167 // - ... -
168 // ---------------------
169 //
170 // The size of the .eh_frame section dictates the number of CIEs in the CFI,
171 // which means that both the starting address of the .eh_frame section, and
172 // it's size must be available. The best way to view the difference between
173 // the CIE and the FDE is, the FDE contains the information needed to unwind
174 // the stack for a given program counter (PC), and the CIE contains the
175 // information for an FDE that just do happens to be shared with other FDEs.
176 // For this reason, when looking for the FDE associated with your PC, you
177 // basically scan looking for FDEs, and just ignore an entry if it happens to
178 // be a CIE instead of an FDE. Once you find the FDE you care about, you can
179 // use the CIE offset stored in the FDE to find the CIE associated with that
180 // FDE. It probably would have made sense for GCC to place the all of the CIEs
181 // at the end of the list to make scanning easier, but that's not the case.
182 //
183 // Both the CIE and the FDE's have some fields that are encoded using both
184 // signed and unsigned LEB128 format. What this means is the value could be
185 // 8bits, or even 64bits, it all depends on how many bits are needed to encode
186 // the value, which provides a means to compress the information in each CIE
187 // and FDE. For example, a length field my contain the value 0x40, which only
188 // takes up a byte. The length could also be 0x4000000. The problem is, in a
189 // lot of cases, len might end up being small most of the time, but because
190 // it could be larger, 64bits would need to be allocated every time. To
191 // prevent this, LEB128 breaks up the number in a way that allows it to be
192 // encoded in a compressed form, thus taking up less space. In our code, when
193 // you see a LEB128, we store the decoded values as 64bits. There is a really
194 // good explanation of this here:
195 //
196 // https://en.wikipedia.org/wiki/LEB128
197 
205 class eh_frame
206 {
207 public:
208  static fd_entry find_fde(register_state *state);
209 };
210 
220 {
221 public:
222 
227  common_entry();
228 
234  explicit common_entry(const eh_frame_t &eh_frame);
235 
238  virtual ~common_entry() = default;
239 
242  common_entry(common_entry &&) noexcept = default;
243 
246  common_entry(const common_entry &) = default;
247 
251 
254  common_entry &operator=(const common_entry &) = default;
255 
266 
271  operator bool() const
272  { return m_entry_start != nullptr; }
273 
278  bool is_cie() const
279  { return m_is_cie; }
280 
285  bool is_fde() const
286  { return !m_is_cie; }
287 
292  char *entry_start() const
293  { return m_entry_start; }
294 
299  char *entry_end() const
300  { return m_entry_end; }
301 
307  char *payload_start() const
308  { return m_payload_start; }
309 
316  char *payload_end() const
317  { return m_payload_end; }
318 
324  { return m_eh_frame; }
325 
326 protected:
327  virtual void parse(char *addr) = 0;
328  void non_virtual_parse(char *addr);
329 
330 protected:
331  bool m_is_cie;
332 
334  char *m_entry_end;
335 
338 
340 };
341 
342 // -----------------------------------------------------------------------------
343 // Common Information Entry (CIE) Format (section 10.6.1.1)
344 // -----------------------------------------------------------------------------
345 //
346 
360 class ci_entry : public common_entry
361 {
362 public:
363 
368  ci_entry();
369 
375  explicit ci_entry(const eh_frame_t &eh_frame);
376 
382  explicit ci_entry(const eh_frame_t &eh_frame, void *addr);
383 
386  ~ci_entry() override = default;
387 
390  ci_entry(ci_entry &&) noexcept = default;
391 
394  ci_entry(const ci_entry &) = default;
395 
398  ci_entry &operator=(ci_entry &&) noexcept = default;
399 
402  ci_entry &operator=(const ci_entry &) = default;
403 
415  char augmentation_string(uint64_t index) const
416  { return m_augmentation_string[index]; }
417 
423  uint64_t code_alignment() const
424  { return m_code_alignment; }
425 
432  int64_t data_alignment() const
433  { return m_data_alignment; }
434 
440  uint64_t return_address_reg() const
441  { return m_return_address_reg; }
442 
449  uint64_t pointer_encoding() const
450  { return m_pointer_encoding; }
451 
456  uint64_t lsda_encoding() const
457  { return m_lsda_encoding; }
458 
463  uint64_t personality_encoding() const
464  { return m_personality_encoding; }
465 
472  uint64_t personality_function() const
473  { return m_personality_function; }
474 
480  char *initial_instructions() const
481  { return m_initial_instructions; }
482 
483 protected:
484  void parse(char *addr) override;
485  void non_virtual_parse(char *addr);
486 
487 public:
493  uint64_t m_lsda_encoding;
497 };
498 
499 // -----------------------------------------------------------------------------
500 // Frame Description Entry (FDE) (section 10.6.1.2)
501 // -----------------------------------------------------------------------------
502 
510 class fd_entry : public common_entry
511 {
512 public:
513 
518  fd_entry();
519 
525  explicit fd_entry(const eh_frame_t &eh_frame);
526 
532  explicit fd_entry(const eh_frame_t &eh_frame, void *addr);
533 
536  ~fd_entry() override = default;
537 
540  fd_entry(fd_entry &&) noexcept = default;
541 
544  fd_entry(const fd_entry &) = default;
545 
548  fd_entry &operator=(fd_entry &&) noexcept = default;
549 
552  fd_entry &operator=(const fd_entry &) = default;
553 
566  bool is_in_range(uint64_t pc) const
567  { return (pc > m_pc_begin) && (pc <= m_pc_begin + m_pc_range); }
568 
573  uint64_t pc_begin() const
574  { return m_pc_begin; }
575 
580  uint64_t pc_range() const
581  { return m_pc_range; }
582 
588  uint64_t lsda() const
589  { return m_lsda; }
590 
596  char *instructions() const
597  { return m_instructions; }
598 
603  const ci_entry &cie() const
604  { return m_cie; }
605 
606 protected:
607  void parse(char *addr) override;
608  void non_virtual_parse(char *addr);
609 
610 private:
611  uint64_t m_pc_begin;
612  uint64_t m_pc_range;
613  uint64_t m_lsda;
614  char *m_instructions;
615 
616  ci_entry m_cie;
617 };
618 
619 #endif
void parse(char *addr) override
Definition: eh_frame.cpp:351
char augmentation_string(uint64_t index) const
Definition: eh_frame.h:415
void non_virtual_parse(char *addr)
Definition: eh_frame.cpp:164
const ci_entry & cie() const
Definition: eh_frame.h:603
char * m_entry_end
Definition: eh_frame.h:334
uint64_t m_personality_function
Definition: eh_frame.h:495
uint64_t m_return_address_reg
Definition: eh_frame.h:491
uint64_t pc_begin() const
Definition: eh_frame.h:573
uint64_t pointer_encoding() const
Definition: eh_frame.h:449
char * m_payload_start
Definition: eh_frame.h:336
int64_t m_data_alignment
Definition: eh_frame.h:490
char * entry_end() const
Definition: eh_frame.h:299
uint64_t m_pointer_encoding
Definition: eh_frame.h:492
uint64_t lsda() const
Definition: eh_frame.h:588
bool m_is_cie
Definition: eh_frame.h:331
Definition: eh_frame.h:360
fd_entry & operator=(fd_entry &&) noexcept=default
char * initial_instructions() const
Definition: eh_frame.h:480
~fd_entry() override=default
char * m_initial_instructions
Definition: eh_frame.h:496
void parse(char *addr) override
Definition: eh_frame.cpp:256
void non_virtual_parse(char *addr)
Definition: eh_frame.cpp:262
char * payload_end() const
Definition: eh_frame.h:316
bool is_fde() const
Definition: eh_frame.h:285
void uint64_t uint64_t uint64_t *rdx noexcept
auto index(const T virt, const F from)
constexpr const auto addr
Definition: cpuid_x64.h:80
uint64_t personality_encoding() const
Definition: eh_frame.h:463
static fd_entry find_fde(register_state *state)
Definition: eh_frame.cpp:408
uint64_t decode_pointer(char **addr, uint64_t encoding)
Definition: eh_frame.cpp:33
~ci_entry() override=default
uint64_t code_alignment() const
Definition: eh_frame.h:423
char * payload_start() const
Definition: eh_frame.h:307
uint64_t m_code_alignment
Definition: eh_frame.h:489
ci_entry()
Definition: eh_frame.cpp:210
ci_entry & operator=(ci_entry &&) noexcept=default
bool is_cie() const
Definition: eh_frame.h:278
void non_virtual_parse(char *addr)
Definition: eh_frame.cpp:357
uint64_t pc_range() const
Definition: eh_frame.h:580
char * entry_start() const
Definition: eh_frame.h:292
bool is_in_range(uint64_t pc) const
Definition: eh_frame.h:566
virtual ~common_entry()=default
fd_entry()
Definition: eh_frame.cpp:320
uint64_t return_address_reg() const
Definition: eh_frame.h:440
common_entry & operator++()
Definition: eh_frame.cpp:150
virtual void parse(char *addr)=0
common_entry()
Definition: eh_frame.cpp:130
eh_frame_t m_eh_frame
Definition: eh_frame.h:339
char * instructions() const
Definition: eh_frame.h:596
const char * m_augmentation_string
Definition: eh_frame.h:488
common_entry & operator=(common_entry &&) noexcept=default
uint64_t personality_function() const
Definition: eh_frame.h:472
char * m_payload_end
Definition: eh_frame.h:337
Definition: eh_frame.h:219
Definition: eh_frame.h:510
int64_t data_alignment() const
Definition: eh_frame.h:432
char * m_entry_start
Definition: eh_frame.h:333
eh_frame_t eh_frame() const
Definition: eh_frame.h:323
uint64_t lsda_encoding() const
Definition: eh_frame.h:456
uint64_t m_personality_encoding
Definition: eh_frame.h:494
uint64_t m_lsda_encoding
Definition: eh_frame.h:493