summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adb/test_device.py56
-rw-r--r--libcutils/Android.bp26
-rw-r--r--libcutils/include/private/android_filesystem_config.h8
-rw-r--r--libcutils/uevent.cpp (renamed from libcutils/uevent.c)90
-rw-r--r--libunwindstack/Android.bp4
-rw-r--r--libunwindstack/DwarfDebugFrame.cpp316
-rw-r--r--libunwindstack/DwarfDebugFrame.h50
-rw-r--r--libunwindstack/DwarfEhFrame.h54
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.cpp (renamed from libunwindstack/DwarfEhFrame.cpp)30
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.h78
-rw-r--r--libunwindstack/DwarfSection.cpp304
-rw-r--r--libunwindstack/ElfInterface.cpp24
-rw-r--r--libunwindstack/include/unwindstack/DwarfSection.h32
-rw-r--r--libunwindstack/include/unwindstack/ElfInterface.h5
-rw-r--r--libunwindstack/tests/DwarfDebugFrameTest.cpp4
-rw-r--r--libunwindstack/tests/DwarfEhFrameTest.cpp517
-rw-r--r--libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp434
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp28
-rw-r--r--libunwindstack/tests/ElfInterfaceTest.cpp28
-rw-r--r--libvndksupport/linker.c34
-rw-r--r--logd/LogBuffer.cpp8
-rw-r--r--logd/LogListener.cpp10
22 files changed, 1348 insertions, 792 deletions
diff --git a/adb/test_device.py b/adb/test_device.py
index ddceda9d9..4cf2206f1 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -34,11 +34,8 @@ import tempfile
34import time 34import time
35import unittest 35import unittest
36 36
37import mock
38
39import adb 37import adb
40 38
41
42def requires_root(func): 39def requires_root(func):
43 def wrapper(self, *args): 40 def wrapper(self, *args):
44 if self.device.get_prop('ro.debuggable') != '1': 41 if self.device.get_prop('ro.debuggable') != '1':
@@ -76,59 +73,6 @@ def requires_non_root(func):
76 return wrapper 73 return wrapper
77 74
78 75
79class GetDeviceTest(unittest.TestCase):
80 def setUp(self):
81 self.android_serial = os.getenv('ANDROID_SERIAL')
82 if 'ANDROID_SERIAL' in os.environ:
83 del os.environ['ANDROID_SERIAL']
84
85 def tearDown(self):
86 if self.android_serial is not None:
87 os.environ['ANDROID_SERIAL'] = self.android_serial
88 else:
89 if 'ANDROID_SERIAL' in os.environ:
90 del os.environ['ANDROID_SERIAL']
91
92 @mock.patch('adb.device.get_devices')
93 def test_explicit(self, mock_get_devices):
94 mock_get_devices.return_value = ['foo', 'bar']
95 device = adb.get_device('foo')
96 self.assertEqual(device.serial, 'foo')
97
98 @mock.patch('adb.device.get_devices')
99 def test_from_env(self, mock_get_devices):
100 mock_get_devices.return_value = ['foo', 'bar']
101 os.environ['ANDROID_SERIAL'] = 'foo'
102 device = adb.get_device()
103 self.assertEqual(device.serial, 'foo')
104
105 @mock.patch('adb.device.get_devices')
106 def test_arg_beats_env(self, mock_get_devices):
107 mock_get_devices.return_value = ['foo', 'bar']
108 os.environ['ANDROID_SERIAL'] = 'bar'
109 device = adb.get_device('foo')
110 self.assertEqual(device.serial, 'foo')
111
112 @mock.patch('adb.device.get_devices')
113 def test_no_such_device(self, mock_get_devices):
114 mock_get_devices.return_value = ['foo', 'bar']
115 self.assertRaises(adb.DeviceNotFoundError, adb.get_device, ['baz'])
116
117 os.environ['ANDROID_SERIAL'] = 'baz'
118 self.assertRaises(adb.DeviceNotFoundError, adb.get_device)
119
120 @mock.patch('adb.device.get_devices')
121 def test_unique_device(self, mock_get_devices):
122 mock_get_devices.return_value = ['foo']
123 device = adb.get_device()
124 self.assertEqual(device.serial, 'foo')
125
126 @mock.patch('adb.device.get_devices')
127 def test_no_unique_device(self, mock_get_devices):
128 mock_get_devices.return_value = ['foo', 'bar']
129 self.assertRaises(adb.NoUniqueDeviceError, adb.get_device)
130
131
132class DeviceTest(unittest.TestCase): 76class DeviceTest(unittest.TestCase):
133 def setUp(self): 77 def setUp(self):
134 self.device = adb.get_device() 78 self.device = adb.get_device()
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index b30336ddd..8fb3a52d7 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -112,25 +112,34 @@ cc_library {
112 "properties.cpp", 112 "properties.cpp",
113 "qtaguid.cpp", 113 "qtaguid.cpp",
114 "trace-dev.c", 114 "trace-dev.c",
115 "uevent.c", 115 "uevent.cpp",
116 ], 116 ],
117 sanitize: {
118 misc_undefined: ["integer"],
119 },
120 }, 117 },
121 118
122 android_arm: { 119 android_arm: {
123 srcs: ["arch-arm/memset32.S"], 120 srcs: ["arch-arm/memset32.S"],
121 sanitize: {
122 misc_undefined: ["integer"],
123 },
124 }, 124 },
125 android_arm64: { 125 android_arm64: {
126 srcs: ["arch-arm64/android_memset.S"], 126 srcs: ["arch-arm64/android_memset.S"],
127 sanitize: {
128 misc_undefined: ["integer"],
129 },
127 }, 130 },
128 131
129 android_mips: { 132 android_mips: {
130 srcs: ["arch-mips/android_memset.c"], 133 srcs: ["arch-mips/android_memset.c"],
134 sanitize: {
135 misc_undefined: ["integer"],
136 },
131 }, 137 },
132 android_mips64: { 138 android_mips64: {
133 srcs: ["arch-mips/android_memset.c"], 139 srcs: ["arch-mips/android_memset.c"],
140 sanitize: {
141 misc_undefined: ["integer"],
142 },
134 }, 143 },
135 144
136 android_x86: { 145 android_x86: {
@@ -138,6 +147,12 @@ cc_library {
138 "arch-x86/android_memset16.S", 147 "arch-x86/android_memset16.S",
139 "arch-x86/android_memset32.S", 148 "arch-x86/android_memset32.S",
140 ], 149 ],
150 // TODO: This is to work around b/29412086.
151 // Remove once __mulodi4 is available and move the "sanitize" block
152 // to the android target.
153 sanitize: {
154 misc_undefined: [],
155 },
141 }, 156 },
142 157
143 android_x86_64: { 158 android_x86_64: {
@@ -145,6 +160,9 @@ cc_library {
145 "arch-x86_64/android_memset16.S", 160 "arch-x86_64/android_memset16.S",
146 "arch-x86_64/android_memset32.S", 161 "arch-x86_64/android_memset32.S",
147 ], 162 ],
163 sanitize: {
164 misc_undefined: ["integer"],
165 },
148 }, 166 },
149 }, 167 },
150 168
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 55ece54a5..2ecf5bce6 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -170,6 +170,14 @@
170#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ 170#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
171#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */ 171#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */
172 172
173/*
174 * This is a magic number in the kernel and not something that was picked
175 * arbitrarily. This value is returned whenever a uid that has no mapping in the
176 * user namespace is returned to userspace:
177 * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/highuid.h?h=v4.4#n40
178 */
179#define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */
180
173#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ 181#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
174#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ 182#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
175 183
diff --git a/libcutils/uevent.c b/libcutils/uevent.cpp
index f548dca2f..a84e5b000 100644
--- a/libcutils/uevent.c
+++ b/libcutils/uevent.cpp
@@ -17,7 +17,8 @@
17#include <cutils/uevent.h> 17#include <cutils/uevent.h>
18 18
19#include <errno.h> 19#include <errno.h>
20#include <stdbool.h> 20#include <stdint.h>
21#include <stdio.h>
21#include <string.h> 22#include <string.h>
22#include <strings.h> 23#include <strings.h>
23#include <sys/socket.h> 24#include <sys/socket.h>
@@ -26,11 +27,60 @@
26 27
27#include <linux/netlink.h> 28#include <linux/netlink.h>
28 29
30#include <fstream>
31
32#include <private/android_filesystem_config.h>
33
34namespace {
35
36// Returns the uid of root in the current user namespace.
37// Returns AID_OVERFLOWUID if the root user is not mapped in the current
38// namespace.
39// Returns 0 if the kernel is not user namespace-aware (for backwards
40// compatibility) or if AID_OVERFLOWUID could not be validated to match what the
41// kernel would return.
42uid_t GetRootUid() {
43 constexpr uid_t kParentRootUid = 0;
44
45 std::ifstream uid_map_file("/proc/self/uid_map");
46 if (!uid_map_file) {
47 // The kernel does not support user namespaces.
48 return kParentRootUid;
49 }
50
51 uid_t current_namespace_uid, parent_namespace_uid;
52 uint32_t length;
53 while (uid_map_file >> current_namespace_uid >> parent_namespace_uid >> length) {
54 // Since kParentRootUid is 0, it should be the first entry in the mapped
55 // range.
56 if (parent_namespace_uid != kParentRootUid || length < 1) continue;
57 return current_namespace_uid;
58 }
59
60 // Sanity check: verify that the overflow UID is the one to be returned by
61 // the kernel.
62 std::ifstream overflowuid_file("/proc/sys/kernel/overflowuid");
63 if (!overflowuid_file) {
64 // It's better to return 0 in case we cannot make sure that the overflow
65 // UID matches.
66 return kParentRootUid;
67 }
68 uid_t kernel_overflow_uid;
69 if (!(overflowuid_file >> kernel_overflow_uid) || kernel_overflow_uid != AID_OVERFLOWUID)
70 return kParentRootUid;
71
72 // root is unmapped, use the kernel "overflow" uid.
73 return AID_OVERFLOWUID;
74}
75
76} // namespace
77
78extern "C" {
79
29/** 80/**
30 * Like recv(), but checks that messages actually originate from the kernel. 81 * Like recv(), but checks that messages actually originate from the kernel.
31 */ 82 */
32ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) 83ssize_t uevent_kernel_multicast_recv(int socket, void* buffer, size_t length) {
33{
34 uid_t uid = -1; 84 uid_t uid = -1;
35 return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid); 85 return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid);
36} 86}
@@ -44,25 +94,19 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length)
44 * returns -1, sets errno to EIO, and sets "user" to the UID associated with the 94 * returns -1, sets errno to EIO, and sets "user" to the UID associated with the
45 * message. If the peer UID cannot be determined, "user" is set to -1." 95 * message. If the peer UID cannot be determined, "user" is set to -1."
46 */ 96 */
47ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid) 97ssize_t uevent_kernel_multicast_uid_recv(int socket, void* buffer, size_t length, uid_t* uid) {
48{
49 return uevent_kernel_recv(socket, buffer, length, true, uid); 98 return uevent_kernel_recv(socket, buffer, length, true, uid);
50} 99}
51 100
52ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require_group, uid_t *uid) 101ssize_t uevent_kernel_recv(int socket, void* buffer, size_t length, bool require_group, uid_t* uid) {
53{ 102 static const uid_t root_uid = GetRootUid();
54 struct iovec iov = { buffer, length }; 103 struct iovec iov = {buffer, length};
55 struct sockaddr_nl addr; 104 struct sockaddr_nl addr;
56 char control[CMSG_SPACE(sizeof(struct ucred))]; 105 char control[CMSG_SPACE(sizeof(struct ucred))];
57 struct msghdr hdr = { 106 struct msghdr hdr = {
58 &addr, 107 &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0,
59 sizeof(addr),
60 &iov,
61 1,
62 control,
63 sizeof(control),
64 0,
65 }; 108 };
109 struct ucred* cred;
66 110
67 *uid = -1; 111 *uid = -1;
68 ssize_t n = recvmsg(socket, &hdr, 0); 112 ssize_t n = recvmsg(socket, &hdr, 0);
@@ -70,15 +114,15 @@ ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require
70 return n; 114 return n;
71 } 115 }
72 116
73 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); 117 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
74 if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { 118 if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
75 /* ignoring netlink message with no sender credentials */ 119 /* ignoring netlink message with no sender credentials */
76 goto out; 120 goto out;
77 } 121 }
78 122
79 struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg); 123 cred = (struct ucred*)CMSG_DATA(cmsg);
80 *uid = cred->uid; 124 *uid = cred->uid;
81 if (cred->uid != 0) { 125 if (cred->uid != root_uid) {
82 /* ignoring netlink message from non-root user */ 126 /* ignoring netlink message from non-root user */
83 goto out; 127 goto out;
84 } 128 }
@@ -101,8 +145,7 @@ out:
101 return -1; 145 return -1;
102} 146}
103 147
104int uevent_open_socket(int buf_sz, bool passcred) 148int uevent_open_socket(int buf_sz, bool passcred) {
105{
106 struct sockaddr_nl addr; 149 struct sockaddr_nl addr;
107 int on = passcred; 150 int on = passcred;
108 int s; 151 int s;
@@ -113,8 +156,7 @@ int uevent_open_socket(int buf_sz, bool passcred)
113 addr.nl_groups = 0xffffffff; 156 addr.nl_groups = 0xffffffff;
114 157
115 s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT); 158 s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
116 if(s < 0) 159 if (s < 0) return -1;
117 return -1;
118 160
119 /* buf_sz should be less than net.core.rmem_max for this to succeed */ 161 /* buf_sz should be less than net.core.rmem_max for this to succeed */
120 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) { 162 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) {
@@ -124,10 +166,12 @@ int uevent_open_socket(int buf_sz, bool passcred)
124 166
125 setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); 167 setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
126 168
127 if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 169 if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
128 close(s); 170 close(s);
129 return -1; 171 return -1;
130 } 172 }
131 173
132 return s; 174 return s;
133} 175}
176
177} // extern "C"
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index c885c3f9b..40364fe40 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -48,8 +48,7 @@ cc_library {
48 srcs: [ 48 srcs: [
49 "ArmExidx.cpp", 49 "ArmExidx.cpp",
50 "DwarfCfa.cpp", 50 "DwarfCfa.cpp",
51 "DwarfDebugFrame.cpp", 51 "DwarfEhFrameWithHdr.cpp",
52 "DwarfEhFrame.cpp",
53 "DwarfMemory.cpp", 52 "DwarfMemory.cpp",
54 "DwarfOp.cpp", 53 "DwarfOp.cpp",
55 "DwarfSection.cpp", 54 "DwarfSection.cpp",
@@ -106,6 +105,7 @@ cc_test {
106 "tests/DwarfCfaTest.cpp", 105 "tests/DwarfCfaTest.cpp",
107 "tests/DwarfDebugFrameTest.cpp", 106 "tests/DwarfDebugFrameTest.cpp",
108 "tests/DwarfEhFrameTest.cpp", 107 "tests/DwarfEhFrameTest.cpp",
108 "tests/DwarfEhFrameWithHdrTest.cpp",
109 "tests/DwarfMemoryTest.cpp", 109 "tests/DwarfMemoryTest.cpp",
110 "tests/DwarfOpLogTest.cpp", 110 "tests/DwarfOpLogTest.cpp",
111 "tests/DwarfOpTest.cpp", 111 "tests/DwarfOpTest.cpp",
diff --git a/libunwindstack/DwarfDebugFrame.cpp b/libunwindstack/DwarfDebugFrame.cpp
deleted file mode 100644
index 57075962a..000000000
--- a/libunwindstack/DwarfDebugFrame.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18#include <stdlib.h>
19
20#include <algorithm>
21
22#include <unwindstack/DwarfStructs.h>
23#include <unwindstack/Memory.h>
24
25#include "DwarfDebugFrame.h"
26#include "DwarfEncoding.h"
27#include "DwarfError.h"
28
29namespace unwindstack {
30
31template <typename AddressType>
32bool DwarfDebugFrame<AddressType>::Init(uint64_t offset, uint64_t size) {
33 offset_ = offset;
34 end_offset_ = offset + size;
35
36 memory_.clear_func_offset();
37 memory_.clear_text_offset();
38 memory_.set_data_offset(offset);
39 memory_.set_cur_offset(offset);
40
41 return CreateSortedFdeList();
42}
43
44template <typename AddressType>
45bool DwarfDebugFrame<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
46 uint8_t version;
47 if (!memory_.ReadBytes(&version, 1)) {
48 last_error_ = DWARF_ERROR_MEMORY_INVALID;
49 return false;
50 }
51 // Read the augmentation string.
52 std::vector<char> aug_string;
53 char aug_value;
54 bool get_encoding = false;
55 do {
56 if (!memory_.ReadBytes(&aug_value, 1)) {
57 last_error_ = DWARF_ERROR_MEMORY_INVALID;
58 return false;
59 }
60 if (aug_value == 'R') {
61 get_encoding = true;
62 }
63 aug_string.push_back(aug_value);
64 } while (aug_value != '\0');
65
66 if (version == 4) {
67 // Skip the Address Size field.
68 memory_.set_cur_offset(memory_.cur_offset() + 1);
69
70 // Read the segment size.
71 if (!memory_.ReadBytes(segment_size, 1)) {
72 last_error_ = DWARF_ERROR_MEMORY_INVALID;
73 return false;
74 }
75 } else {
76 *segment_size = 0;
77 }
78
79 if (aug_string[0] != 'z' || !get_encoding) {
80 // No encoding
81 return true;
82 }
83
84 // Skip code alignment factor
85 uint8_t value;
86 do {
87 if (!memory_.ReadBytes(&value, 1)) {
88 last_error_ = DWARF_ERROR_MEMORY_INVALID;
89 return false;
90 }
91 } while (value & 0x80);
92
93 // Skip data alignment factor
94 do {
95 if (!memory_.ReadBytes(&value, 1)) {
96 last_error_ = DWARF_ERROR_MEMORY_INVALID;
97 return false;
98 }
99 } while (value & 0x80);
100
101 if (version == 1) {
102 // Skip return address register.
103 memory_.set_cur_offset(memory_.cur_offset() + 1);
104 } else {
105 // Skip return address register.
106 do {
107 if (!memory_.ReadBytes(&value, 1)) {
108 last_error_ = DWARF_ERROR_MEMORY_INVALID;
109 return false;
110 }
111 } while (value & 0x80);
112 }
113
114 // Skip the augmentation length.
115 do {
116 if (!memory_.ReadBytes(&value, 1)) {
117 last_error_ = DWARF_ERROR_MEMORY_INVALID;
118 return false;
119 }
120 } while (value & 0x80);
121
122 for (size_t i = 1; i < aug_string.size(); i++) {
123 if (aug_string[i] == 'R') {
124 if (!memory_.ReadBytes(encoding, 1)) {
125 last_error_ = DWARF_ERROR_MEMORY_INVALID;
126 return false;
127 }
128 // Got the encoding, that's all we are looking for.
129 return true;
130 } else if (aug_string[i] == 'L') {
131 memory_.set_cur_offset(memory_.cur_offset() + 1);
132 } else if (aug_string[i] == 'P') {
133 uint8_t encoding;
134 if (!memory_.ReadBytes(&encoding, 1)) {
135 last_error_ = DWARF_ERROR_MEMORY_INVALID;
136 return false;
137 }
138 uint64_t value;
139 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
140 last_error_ = DWARF_ERROR_MEMORY_INVALID;
141 return false;
142 }
143 }
144 }
145
146 // It should be impossible to get here.
147 abort();
148}
149
150template <typename AddressType>
151bool DwarfDebugFrame<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
152 uint8_t encoding) {
153 if (segment_size != 0) {
154 memory_.set_cur_offset(memory_.cur_offset() + 1);
155 }
156
157 uint64_t start;
158 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
159 last_error_ = DWARF_ERROR_MEMORY_INVALID;
160 return false;
161 }
162
163 uint64_t length;
164 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
165 last_error_ = DWARF_ERROR_MEMORY_INVALID;
166 return false;
167 }
168 if (length != 0) {
169 fdes_.emplace_back(entry_offset, start, length);
170 }
171
172 return true;
173}
174
175template <typename AddressType>
176bool DwarfDebugFrame<AddressType>::CreateSortedFdeList() {
177 memory_.set_cur_offset(offset_);
178
179 // Loop through all of the entries and read just enough to create
180 // a sorted list of pcs.
181 // This code assumes that first comes the cie, then the fdes that
182 // it applies to.
183 uint64_t cie_offset = 0;
184 uint8_t address_encoding;
185 uint8_t segment_size;
186 while (memory_.cur_offset() < end_offset_) {
187 uint64_t cur_entry_offset = memory_.cur_offset();
188
189 // Figure out the entry length and type.
190 uint32_t value32;
191 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
192 last_error_ = DWARF_ERROR_MEMORY_INVALID;
193 return false;
194 }
195
196 uint64_t next_entry_offset;
197 if (value32 == static_cast<uint32_t>(-1)) {
198 uint64_t value64;
199 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
200 last_error_ = DWARF_ERROR_MEMORY_INVALID;
201 return false;
202 }
203 next_entry_offset = memory_.cur_offset() + value64;
204
205 // Read the Cie Id of a Cie or the pointer of the Fde.
206 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
207 last_error_ = DWARF_ERROR_MEMORY_INVALID;
208 return false;
209 }
210
211 if (value64 == static_cast<uint64_t>(-1)) {
212 // Cie 64 bit
213 address_encoding = DW_EH_PE_sdata8;
214 if (!GetCieInfo(&segment_size, &address_encoding)) {
215 return false;
216 }
217 cie_offset = cur_entry_offset;
218 } else {
219 if (offset_ + value64 != cie_offset) {
220 // This means that this Fde is not following the Cie.
221 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
222 return false;
223 }
224
225 // Fde 64 bit
226 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
227 return false;
228 }
229 }
230 } else {
231 next_entry_offset = memory_.cur_offset() + value32;
232
233 // Read the Cie Id of a Cie or the pointer of the Fde.
234 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
235 last_error_ = DWARF_ERROR_MEMORY_INVALID;
236 return false;
237 }
238
239 if (value32 == static_cast<uint32_t>(-1)) {
240 // Cie 32 bit
241 address_encoding = DW_EH_PE_sdata4;
242 if (!GetCieInfo(&segment_size, &address_encoding)) {
243 return false;
244 }
245 cie_offset = cur_entry_offset;
246 } else {
247 if (offset_ + value32 != cie_offset) {
248 // This means that this Fde is not following the Cie.
249 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
250 return false;
251 }
252
253 // Fde 32 bit
254 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
255 return false;
256 }
257 }
258 }
259
260 if (next_entry_offset < memory_.cur_offset()) {
261 // This indicates some kind of corruption, or malformed section data.
262 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
263 return false;
264 }
265 memory_.set_cur_offset(next_entry_offset);
266 }
267
268 // Sort the entries.
269 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
270 if (a.start == b.start) return a.end < b.end;
271 return a.start < b.start;
272 });
273
274 fde_count_ = fdes_.size();
275
276 return true;
277}
278
279template <typename AddressType>
280bool DwarfDebugFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
281 if (fde_count_ == 0) {
282 return false;
283 }
284
285 size_t first = 0;
286 size_t last = fde_count_;
287 while (first < last) {
288 size_t current = (first + last) / 2;
289 const FdeInfo* info = &fdes_[current];
290 if (pc >= info->start && pc <= info->end) {
291 *fde_offset = info->offset;
292 return true;
293 }
294
295 if (pc < info->start) {
296 last = current;
297 } else {
298 first = current + 1;
299 }
300 }
301 return false;
302}
303
304template <typename AddressType>
305const DwarfFde* DwarfDebugFrame<AddressType>::GetFdeFromIndex(size_t index) {
306 if (index >= fdes_.size()) {
307 return nullptr;
308 }
309 return this->GetFdeFromOffset(fdes_[index].offset);
310}
311
312// Explicitly instantiate DwarfDebugFrame.
313template class DwarfDebugFrame<uint32_t>;
314template class DwarfDebugFrame<uint64_t>;
315
316} // namespace unwindstack
diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h
index 6a6178e6f..635cefdf2 100644
--- a/libunwindstack/DwarfDebugFrame.h
+++ b/libunwindstack/DwarfDebugFrame.h
@@ -28,51 +28,21 @@ namespace unwindstack {
28template <typename AddressType> 28template <typename AddressType>
29class DwarfDebugFrame : public DwarfSectionImpl<AddressType> { 29class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
30 public: 30 public:
31 // Add these so that the protected members of DwarfSectionImpl 31 DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {
32 // can be accessed without needing a this->. 32 this->cie32_value_ = static_cast<uint32_t>(-1);
33 using DwarfSectionImpl<AddressType>::memory_; 33 this->cie64_value_ = static_cast<uint64_t>(-1);
34 using DwarfSectionImpl<AddressType>::fde_count_; 34 }
35 using DwarfSectionImpl<AddressType>::last_error_;
36
37 struct FdeInfo {
38 FdeInfo(uint64_t offset, uint64_t start, uint64_t length)
39 : offset(offset), start(start), end(start + length) {}
40
41 uint64_t offset;
42 AddressType start;
43 AddressType end;
44 };
45
46 DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
47 virtual ~DwarfDebugFrame() = default; 35 virtual ~DwarfDebugFrame() = default;
48 36
49 bool Init(uint64_t offset, uint64_t size) override; 37 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
50 38 return this->entries_offset_ + pointer;
51 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; 39 }
52
53 const DwarfFde* GetFdeFromIndex(size_t index) override;
54
55 bool IsCie32(uint32_t value32) override { return value32 == static_cast<uint32_t>(-1); }
56
57 bool IsCie64(uint64_t value64) override { return value64 == static_cast<uint64_t>(-1); }
58 40
59 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return offset_ + pointer; } 41 uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
60 42 return this->entries_offset_ + pointer;
61 uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return offset_ + pointer; } 43 }
62 44
63 uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; } 45 uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; }
64
65 bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding);
66
67 bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding);
68
69 bool CreateSortedFdeList();
70
71 protected:
72 uint64_t offset_;
73 uint64_t end_offset_;
74
75 std::vector<FdeInfo> fdes_;
76}; 46};
77 47
78} // namespace unwindstack 48} // namespace unwindstack
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
index 4207b42f2..561d23a88 100644
--- a/libunwindstack/DwarfEhFrame.h
+++ b/libunwindstack/DwarfEhFrame.h
@@ -20,74 +20,30 @@
20#include <stdint.h> 20#include <stdint.h>
21 21
22#include <unwindstack/DwarfSection.h> 22#include <unwindstack/DwarfSection.h>
23#include <unwindstack/Memory.h>
23 24
24namespace unwindstack { 25namespace unwindstack {
25 26
26// Forward declarations.
27class Memory;
28
29template <typename AddressType> 27template <typename AddressType>
30class DwarfEhFrame : public DwarfSectionImpl<AddressType> { 28class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
31 public: 29 public:
32 // Add these so that the protected members of DwarfSectionImpl
33 // can be accessed without needing a this->.
34 using DwarfSectionImpl<AddressType>::memory_;
35 using DwarfSectionImpl<AddressType>::fde_count_;
36 using DwarfSectionImpl<AddressType>::last_error_;
37
38 struct FdeInfo {
39 AddressType pc;
40 uint64_t offset;
41 };
42
43 DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} 30 DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
44 virtual ~DwarfEhFrame() = default; 31 virtual ~DwarfEhFrame() = default;
45 32
46 bool Init(uint64_t offset, uint64_t size) override;
47
48 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
49
50 const DwarfFde* GetFdeFromIndex(size_t index) override;
51
52 bool IsCie32(uint32_t value32) override { return value32 == 0; }
53
54 bool IsCie64(uint64_t value64) override { return value64 == 0; }
55
56 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { 33 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
57 return memory_.cur_offset() - pointer - 4; 34 return this->memory_.cur_offset() - pointer - 4;
58 } 35 }
59 36
60 uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { 37 uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
61 return memory_.cur_offset() - pointer - 8; 38 return this->memory_.cur_offset() - pointer - 8;
62 } 39 }
63 40
64 uint64_t AdjustPcFromFde(uint64_t pc) override { 41 uint64_t AdjustPcFromFde(uint64_t pc) override {
65 // The eh_frame uses relative pcs. 42 // The eh_frame uses relative pcs.
66 return pc + memory_.cur_offset(); 43 return pc + this->memory_.cur_offset();
67 } 44 }
68
69 const FdeInfo* GetFdeInfoFromIndex(size_t index);
70
71 bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset);
72
73 bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries);
74
75 protected:
76 uint8_t version_;
77 uint8_t ptr_encoding_;
78 uint8_t table_encoding_;
79 size_t table_entry_size_;
80
81 uint64_t ptr_offset_;
82
83 uint64_t entries_offset_;
84 uint64_t entries_end_;
85 uint64_t entries_data_offset_;
86 uint64_t cur_entries_offset_ = 0;
87
88 std::unordered_map<uint64_t, FdeInfo> fde_info_;
89}; 45};
90 46
91} // namespace unwindstack 47} // namespace unwindstack
92 48
93#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H 49#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
diff --git a/libunwindstack/DwarfEhFrame.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index db8f558ff..0337dbaac 100644
--- a/libunwindstack/DwarfEhFrame.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -20,13 +20,13 @@
20#include <unwindstack/Memory.h> 20#include <unwindstack/Memory.h>
21 21
22#include "Check.h" 22#include "Check.h"
23#include "DwarfEhFrame.h" 23#include "DwarfEhFrameWithHdr.h"
24#include "DwarfError.h" 24#include "DwarfError.h"
25 25
26namespace unwindstack { 26namespace unwindstack {
27 27
28template <typename AddressType> 28template <typename AddressType>
29bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { 29bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) {
30 uint8_t data[4]; 30 uint8_t data[4];
31 31
32 memory_.clear_func_offset(); 32 memory_.clear_func_offset();
@@ -73,7 +73,7 @@ bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) {
73} 73}
74 74
75template <typename AddressType> 75template <typename AddressType>
76const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { 76const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) {
77 const FdeInfo* info = GetFdeInfoFromIndex(index); 77 const FdeInfo* info = GetFdeInfoFromIndex(index);
78 if (info == nullptr) { 78 if (info == nullptr) {
79 return nullptr; 79 return nullptr;
@@ -82,8 +82,8 @@ const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) {
82} 82}
83 83
84template <typename AddressType> 84template <typename AddressType>
85const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::GetFdeInfoFromIndex( 85const typename DwarfEhFrameWithHdr<AddressType>::FdeInfo*
86 size_t index) { 86DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
87 auto entry = fde_info_.find(index); 87 auto entry = fde_info_.find(index);
88 if (entry != fde_info_.end()) { 88 if (entry != fde_info_.end()) {
89 return &fde_info_[index]; 89 return &fde_info_[index];
@@ -105,8 +105,8 @@ const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::Ge
105} 105}
106 106
107template <typename AddressType> 107template <typename AddressType>
108bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, 108bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset,
109 uint64_t total_entries) { 109 uint64_t total_entries) {
110 CHECK(fde_count_ > 0); 110 CHECK(fde_count_ > 0);
111 CHECK(total_entries <= fde_count_); 111 CHECK(total_entries <= fde_count_);
112 112
@@ -115,6 +115,9 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of
115 while (first < last) { 115 while (first < last) {
116 size_t current = (first + last) / 2; 116 size_t current = (first + last) / 2;
117 const FdeInfo* info = GetFdeInfoFromIndex(current); 117 const FdeInfo* info = GetFdeInfoFromIndex(current);
118 if (info == nullptr) {
119 return false;
120 }
118 if (pc == info->pc) { 121 if (pc == info->pc) {
119 *fde_offset = info->offset; 122 *fde_offset = info->offset;
120 return true; 123 return true;
@@ -127,6 +130,9 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of
127 } 130 }
128 if (last != 0) { 131 if (last != 0) {
129 const FdeInfo* info = GetFdeInfoFromIndex(last - 1); 132 const FdeInfo* info = GetFdeInfoFromIndex(last - 1);
133 if (info == nullptr) {
134 return false;
135 }
130 *fde_offset = info->offset; 136 *fde_offset = info->offset;
131 return true; 137 return true;
132 } 138 }
@@ -134,7 +140,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of
134} 140}
135 141
136template <typename AddressType> 142template <typename AddressType>
137bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { 143bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) {
138 CHECK(fde_count_ != 0); 144 CHECK(fde_count_ != 0);
139 last_error_ = DWARF_ERROR_NONE; 145 last_error_ = DWARF_ERROR_NONE;
140 // We can do a binary search if the pc is in the range of the elements 146 // We can do a binary search if the pc is in the range of the elements
@@ -196,7 +202,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fd
196} 202}
197 203
198template <typename AddressType> 204template <typename AddressType>
199bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { 205bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
200 if (fde_count_ == 0) { 206 if (fde_count_ == 0) {
201 return false; 207 return false;
202 } 208 }
@@ -210,8 +216,8 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_of
210 } 216 }
211} 217}
212 218
213// Explicitly instantiate DwarfEhFrame. 219// Explicitly instantiate DwarfEhFrameWithHdr
214template class DwarfEhFrame<uint32_t>; 220template class DwarfEhFrameWithHdr<uint32_t>;
215template class DwarfEhFrame<uint64_t>; 221template class DwarfEhFrameWithHdr<uint64_t>;
216 222
217} // namespace unwindstack 223} // namespace unwindstack
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
new file mode 100644
index 000000000..357116620
--- /dev/null
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -0,0 +1,78 @@
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
18#define _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
19
20#include <stdint.h>
21
22#include <unordered_map>
23
24#include "DwarfEhFrame.h"
25
26namespace unwindstack {
27
28// Forward declarations.
29class Memory;
30
31template <typename AddressType>
32class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
33 public:
34 // Add these so that the protected members of DwarfSectionImpl
35 // can be accessed without needing a this->.
36 using DwarfSectionImpl<AddressType>::memory_;
37 using DwarfSectionImpl<AddressType>::fde_count_;
38 using DwarfSectionImpl<AddressType>::entries_offset_;
39 using DwarfSectionImpl<AddressType>::entries_end_;
40 using DwarfSectionImpl<AddressType>::last_error_;
41
42 struct FdeInfo {
43 AddressType pc;
44 uint64_t offset;
45 };
46
47 DwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrame<AddressType>(memory) {}
48 virtual ~DwarfEhFrameWithHdr() = default;
49
50 bool Init(uint64_t offset, uint64_t size) override;
51
52 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
53
54 const DwarfFde* GetFdeFromIndex(size_t index) override;
55
56 const FdeInfo* GetFdeInfoFromIndex(size_t index);
57
58 bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset);
59
60 bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries);
61
62 protected:
63 uint8_t version_;
64 uint8_t ptr_encoding_;
65 uint8_t table_encoding_;
66 size_t table_entry_size_;
67
68 uint64_t ptr_offset_;
69
70 uint64_t entries_data_offset_;
71 uint64_t cur_entries_offset_ = 0;
72
73 std::unordered_map<uint64_t, FdeInfo> fde_info_;
74};
75
76} // namespace unwindstack
77
78#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 91aef8045..805dcd34b 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -29,6 +29,9 @@
29#include "DwarfError.h" 29#include "DwarfError.h"
30#include "DwarfOp.h" 30#include "DwarfOp.h"
31 31
32#include "DwarfDebugFrame.h"
33#include "DwarfEhFrame.h"
34
32namespace unwindstack { 35namespace unwindstack {
33 36
34DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} 37DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {}
@@ -282,7 +285,7 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
282 last_error_ = DWARF_ERROR_MEMORY_INVALID; 285 last_error_ = DWARF_ERROR_MEMORY_INVALID;
283 return false; 286 return false;
284 } 287 }
285 if (!IsCie64(cie_id)) { 288 if (cie_id != cie64_value_) {
286 // This is not a Cie, something has gone horribly wrong. 289 // This is not a Cie, something has gone horribly wrong.
287 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 290 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
288 return false; 291 return false;
@@ -297,7 +300,7 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
297 last_error_ = DWARF_ERROR_MEMORY_INVALID; 300 last_error_ = DWARF_ERROR_MEMORY_INVALID;
298 return false; 301 return false;
299 } 302 }
300 if (!IsCie32(cie_id)) { 303 if (cie_id != cie32_value_) {
301 // This is not a Cie, something has gone horribly wrong. 304 // This is not a Cie, something has gone horribly wrong.
302 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 305 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
303 return false; 306 return false;
@@ -440,7 +443,7 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
440 last_error_ = DWARF_ERROR_MEMORY_INVALID; 443 last_error_ = DWARF_ERROR_MEMORY_INVALID;
441 return false; 444 return false;
442 } 445 }
443 if (IsCie64(value64)) { 446 if (value64 == cie64_value_) {
444 // This is a Cie, this means something has gone wrong. 447 // This is a Cie, this means something has gone wrong.
445 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 448 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
446 return false; 449 return false;
@@ -458,7 +461,7 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
458 last_error_ = DWARF_ERROR_MEMORY_INVALID; 461 last_error_ = DWARF_ERROR_MEMORY_INVALID;
459 return false; 462 return false;
460 } 463 }
461 if (IsCie32(value32)) { 464 if (value32 == cie32_value_) {
462 // This is a Cie, this means something has gone wrong. 465 // This is a Cie, this means something has gone wrong.
463 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 466 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
464 return false; 467 return false;
@@ -556,8 +559,301 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t lo
556 return true; 559 return true;
557} 560}
558 561
562template <typename AddressType>
563bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) {
564 entries_offset_ = offset;
565 entries_end_ = offset + size;
566
567 memory_.clear_func_offset();
568 memory_.clear_text_offset();
569 memory_.set_data_offset(offset);
570 memory_.set_cur_offset(offset);
571 memory_.set_pc_offset(offset);
572
573 return CreateSortedFdeList();
574}
575
576template <typename AddressType>
577bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
578 uint8_t version;
579 if (!memory_.ReadBytes(&version, 1)) {
580 last_error_ = DWARF_ERROR_MEMORY_INVALID;
581 return false;
582 }
583 // Read the augmentation string.
584 std::vector<char> aug_string;
585 char aug_value;
586 bool get_encoding = false;
587 do {
588 if (!memory_.ReadBytes(&aug_value, 1)) {
589 last_error_ = DWARF_ERROR_MEMORY_INVALID;
590 return false;
591 }
592 if (aug_value == 'R') {
593 get_encoding = true;
594 }
595 aug_string.push_back(aug_value);
596 } while (aug_value != '\0');
597
598 if (version == 4) {
599 // Skip the Address Size field.
600 memory_.set_cur_offset(memory_.cur_offset() + 1);
601
602 // Read the segment size.
603 if (!memory_.ReadBytes(segment_size, 1)) {
604 last_error_ = DWARF_ERROR_MEMORY_INVALID;
605 return false;
606 }
607 } else {
608 *segment_size = 0;
609 }
610
611 if (aug_string[0] != 'z' || !get_encoding) {
612 // No encoding
613 return true;
614 }
615
616 // Skip code alignment factor
617 uint8_t value;
618 do {
619 if (!memory_.ReadBytes(&value, 1)) {
620 last_error_ = DWARF_ERROR_MEMORY_INVALID;
621 return false;
622 }
623 } while (value & 0x80);
624
625 // Skip data alignment factor
626 do {
627 if (!memory_.ReadBytes(&value, 1)) {
628 last_error_ = DWARF_ERROR_MEMORY_INVALID;
629 return false;
630 }
631 } while (value & 0x80);
632
633 if (version == 1) {
634 // Skip return address register.
635 memory_.set_cur_offset(memory_.cur_offset() + 1);
636 } else {
637 // Skip return address register.
638 do {
639 if (!memory_.ReadBytes(&value, 1)) {
640 last_error_ = DWARF_ERROR_MEMORY_INVALID;
641 return false;
642 }
643 } while (value & 0x80);
644 }
645
646 // Skip the augmentation length.
647 do {
648 if (!memory_.ReadBytes(&value, 1)) {
649 last_error_ = DWARF_ERROR_MEMORY_INVALID;
650 return false;
651 }
652 } while (value & 0x80);
653
654 for (size_t i = 1; i < aug_string.size(); i++) {
655 if (aug_string[i] == 'R') {
656 if (!memory_.ReadBytes(encoding, 1)) {
657 last_error_ = DWARF_ERROR_MEMORY_INVALID;
658 return false;
659 }
660 // Got the encoding, that's all we are looking for.
661 return true;
662 } else if (aug_string[i] == 'L') {
663 memory_.set_cur_offset(memory_.cur_offset() + 1);
664 } else if (aug_string[i] == 'P') {
665 uint8_t encoding;
666 if (!memory_.ReadBytes(&encoding, 1)) {
667 last_error_ = DWARF_ERROR_MEMORY_INVALID;
668 return false;
669 }
670 uint64_t value;
671 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
672 last_error_ = DWARF_ERROR_MEMORY_INVALID;
673 return false;
674 }
675 }
676 }
677
678 // It should be impossible to get here.
679 abort();
680}
681
682template <typename AddressType>
683bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
684 uint8_t encoding) {
685 if (segment_size != 0) {
686 memory_.set_cur_offset(memory_.cur_offset() + 1);
687 }
688
689 uint64_t start;
690 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
691 last_error_ = DWARF_ERROR_MEMORY_INVALID;
692 return false;
693 }
694 start = AdjustPcFromFde(start);
695
696 uint64_t length;
697 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
698 last_error_ = DWARF_ERROR_MEMORY_INVALID;
699 return false;
700 }
701 if (length != 0) {
702 fdes_.emplace_back(entry_offset, start, length);
703 }
704
705 return true;
706}
707
708template <typename AddressType>
709bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
710 memory_.set_cur_offset(entries_offset_);
711
712 // Loop through all of the entries and read just enough to create
713 // a sorted list of pcs.
714 // This code assumes that first comes the cie, then the fdes that
715 // it applies to.
716 uint64_t cie_offset = 0;
717 uint8_t address_encoding;
718 uint8_t segment_size;
719 while (memory_.cur_offset() < entries_end_) {
720 uint64_t cur_entry_offset = memory_.cur_offset();
721
722 // Figure out the entry length and type.
723 uint32_t value32;
724 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
725 last_error_ = DWARF_ERROR_MEMORY_INVALID;
726 return false;
727 }
728
729 uint64_t next_entry_offset;
730 if (value32 == static_cast<uint32_t>(-1)) {
731 uint64_t value64;
732 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
733 last_error_ = DWARF_ERROR_MEMORY_INVALID;
734 return false;
735 }
736 next_entry_offset = memory_.cur_offset() + value64;
737
738 // Read the Cie Id of a Cie or the pointer of the Fde.
739 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
740 last_error_ = DWARF_ERROR_MEMORY_INVALID;
741 return false;
742 }
743
744 if (value64 == cie64_value_) {
745 // Cie 64 bit
746 address_encoding = DW_EH_PE_sdata8;
747 if (!GetCieInfo(&segment_size, &address_encoding)) {
748 return false;
749 }
750 cie_offset = cur_entry_offset;
751 } else {
752 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
753 if (last_cie_offset != cie_offset) {
754 // This means that this Fde is not following the Cie.
755 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
756 return false;
757 }
758
759 // Fde 64 bit
760 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
761 return false;
762 }
763 }
764 } else {
765 next_entry_offset = memory_.cur_offset() + value32;
766
767 // Read the Cie Id of a Cie or the pointer of the Fde.
768 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
769 last_error_ = DWARF_ERROR_MEMORY_INVALID;
770 return false;
771 }
772
773 if (value32 == cie32_value_) {
774 // Cie 32 bit
775 address_encoding = DW_EH_PE_sdata4;
776 if (!GetCieInfo(&segment_size, &address_encoding)) {
777 return false;
778 }
779 cie_offset = cur_entry_offset;
780 } else {
781 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
782 if (last_cie_offset != cie_offset) {
783 // This means that this Fde is not following the Cie.
784 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
785 return false;
786 }
787
788 // Fde 32 bit
789 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
790 return false;
791 }
792 }
793 }
794
795 if (next_entry_offset < memory_.cur_offset()) {
796 // This indicates some kind of corruption, or malformed section data.
797 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
798 return false;
799 }
800 memory_.set_cur_offset(next_entry_offset);
801 }
802
803 // Sort the entries.
804 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
805 if (a.start == b.start) return a.end < b.end;
806 return a.start < b.start;
807 });
808
809 fde_count_ = fdes_.size();
810
811 return true;
812}
813
814template <typename AddressType>
815bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
816 if (fde_count_ == 0) {
817 return false;
818 }
819
820 size_t first = 0;
821 size_t last = fde_count_;
822 while (first < last) {
823 size_t current = (first + last) / 2;
824 const FdeInfo* info = &fdes_[current];
825 if (pc >= info->start && pc <= info->end) {
826 *fde_offset = info->offset;
827 return true;
828 }
829
830 if (pc < info->start) {
831 last = current;
832 } else {
833 first = current + 1;
834 }
835 }
836 return false;
837}
838
839template <typename AddressType>
840const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
841 if (index >= fdes_.size()) {
842 return nullptr;
843 }
844 return this->GetFdeFromOffset(fdes_[index].offset);
845}
846
559// Explicitly instantiate DwarfSectionImpl 847// Explicitly instantiate DwarfSectionImpl
560template class DwarfSectionImpl<uint32_t>; 848template class DwarfSectionImpl<uint32_t>;
561template class DwarfSectionImpl<uint64_t>; 849template class DwarfSectionImpl<uint64_t>;
562 850
851// Explicitly instantiate DwarfDebugFrame
852template class DwarfDebugFrame<uint32_t>;
853template class DwarfDebugFrame<uint64_t>;
854
855// Explicitly instantiate DwarfEhFrame
856template class DwarfEhFrame<uint32_t>;
857template class DwarfEhFrame<uint64_t>;
858
563} // namespace unwindstack 859} // namespace unwindstack
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 20cc1b06c..d5d158f82 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -32,6 +32,7 @@
32 32
33#include "DwarfDebugFrame.h" 33#include "DwarfDebugFrame.h"
34#include "DwarfEhFrame.h" 34#include "DwarfEhFrame.h"
35#include "DwarfEhFrameWithHdr.h"
35#include "Symbols.h" 36#include "Symbols.h"
36 37
37namespace unwindstack { 38namespace unwindstack {
@@ -98,7 +99,17 @@ Memory* ElfInterface::CreateGnuDebugdataMemory() {
98 99
99template <typename AddressType> 100template <typename AddressType>
100void ElfInterface::InitHeadersWithTemplate() { 101void ElfInterface::InitHeadersWithTemplate() {
101 if (eh_frame_offset_ != 0) { 102 if (eh_frame_hdr_offset_ != 0) {
103 eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
104 if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) {
105 // Even if the eh_frame_offset_ is non-zero, do not bother
106 // trying to read that since something has gone wrong.
107 eh_frame_.reset(nullptr);
108 eh_frame_hdr_offset_ = 0;
109 eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
110 }
111 } else if (eh_frame_offset_ != 0) {
112 // If there is a eh_frame section without a eh_frame_hdr section.
102 eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); 113 eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
103 if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { 114 if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) {
104 eh_frame_.reset(nullptr); 115 eh_frame_.reset(nullptr);
@@ -181,11 +192,12 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
181 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 192 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
182 return false; 193 return false;
183 } 194 }
184 eh_frame_offset_ = phdr.p_offset; 195 // This is really the pointer to the .eh_frame_hdr section.
196 eh_frame_hdr_offset_ = phdr.p_offset;
185 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 197 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
186 return false; 198 return false;
187 } 199 }
188 eh_frame_size_ = phdr.p_memsz; 200 eh_frame_hdr_size_ = phdr.p_memsz;
189 break; 201 break;
190 202
191 case PT_DYNAMIC: 203 case PT_DYNAMIC:
@@ -271,6 +283,12 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
271 } else if (name == ".gnu_debugdata") { 283 } else if (name == ".gnu_debugdata") {
272 offset_ptr = &gnu_debugdata_offset_; 284 offset_ptr = &gnu_debugdata_offset_;
273 size_ptr = &gnu_debugdata_size_; 285 size_ptr = &gnu_debugdata_size_;
286 } else if (name == ".eh_frame") {
287 offset_ptr = &eh_frame_offset_;
288 size_ptr = &eh_frame_size_;
289 } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
290 offset_ptr = &eh_frame_hdr_offset_;
291 size_ptr = &eh_frame_hdr_size_;
274 } 292 }
275 if (offset_ptr != nullptr && 293 if (offset_ptr != nullptr &&
276 memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && 294 memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 1e843c359..10be6b48f 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -90,10 +90,6 @@ class DwarfSection {
90 90
91 virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0; 91 virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0;
92 92
93 virtual bool IsCie32(uint32_t value32) = 0;
94
95 virtual bool IsCie64(uint64_t value64) = 0;
96
97 virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0; 93 virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
98 94
99 virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0; 95 virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0;
@@ -106,6 +102,9 @@ class DwarfSection {
106 DwarfMemory memory_; 102 DwarfMemory memory_;
107 DwarfError last_error_; 103 DwarfError last_error_;
108 104
105 uint32_t cie32_value_ = 0;
106 uint64_t cie64_value_ = 0;
107
109 uint64_t fde_count_ = 0; 108 uint64_t fde_count_ = 0;
110 std::unordered_map<uint64_t, DwarfFde> fde_entries_; 109 std::unordered_map<uint64_t, DwarfFde> fde_entries_;
111 std::unordered_map<uint64_t, DwarfCie> cie_entries_; 110 std::unordered_map<uint64_t, DwarfCie> cie_entries_;
@@ -115,9 +114,24 @@ class DwarfSection {
115template <typename AddressType> 114template <typename AddressType>
116class DwarfSectionImpl : public DwarfSection { 115class DwarfSectionImpl : public DwarfSection {
117 public: 116 public:
117 struct FdeInfo {
118 FdeInfo(uint64_t offset, uint64_t start, uint64_t length)
119 : offset(offset), start(start), end(start + length) {}
120
121 uint64_t offset;
122 AddressType start;
123 AddressType end;
124 };
125
118 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {} 126 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
119 virtual ~DwarfSectionImpl() = default; 127 virtual ~DwarfSectionImpl() = default;
120 128
129 bool Init(uint64_t offset, uint64_t size) override;
130
131 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
132
133 const DwarfFde* GetFdeFromIndex(size_t index) override;
134
121 bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, 135 bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
122 Regs* regs, bool* finished) override; 136 Regs* regs, bool* finished) override;
123 137
@@ -134,6 +148,16 @@ class DwarfSectionImpl : public DwarfSection {
134 protected: 148 protected:
135 bool EvalExpression(const DwarfLocation& loc, uint8_t version, Memory* regular_memory, 149 bool EvalExpression(const DwarfLocation& loc, uint8_t version, Memory* regular_memory,
136 AddressType* value); 150 AddressType* value);
151
152 bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding);
153
154 bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding);
155
156 bool CreateSortedFdeList();
157
158 std::vector<FdeInfo> fdes_;
159 uint64_t entries_offset_;
160 uint64_t entries_end_;
137}; 161};
138 162
139} // namespace unwindstack 163} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index 319623d01..86e51b382 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -70,6 +70,8 @@ class ElfInterface {
70 70
71 uint64_t dynamic_offset() { return dynamic_offset_; } 71 uint64_t dynamic_offset() { return dynamic_offset_; }
72 uint64_t dynamic_size() { return dynamic_size_; } 72 uint64_t dynamic_size() { return dynamic_size_; }
73 uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
74 uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
73 uint64_t eh_frame_offset() { return eh_frame_offset_; } 75 uint64_t eh_frame_offset() { return eh_frame_offset_; }
74 uint64_t eh_frame_size() { return eh_frame_size_; } 76 uint64_t eh_frame_size() { return eh_frame_size_; }
75 uint64_t debug_frame_offset() { return debug_frame_offset_; } 77 uint64_t debug_frame_offset() { return debug_frame_offset_; }
@@ -112,6 +114,9 @@ class ElfInterface {
112 uint64_t dynamic_offset_ = 0; 114 uint64_t dynamic_offset_ = 0;
113 uint64_t dynamic_size_ = 0; 115 uint64_t dynamic_size_ = 0;
114 116
117 uint64_t eh_frame_hdr_offset_ = 0;
118 uint64_t eh_frame_hdr_size_ = 0;
119
115 uint64_t eh_frame_offset_ = 0; 120 uint64_t eh_frame_offset_ = 0;
116 uint64_t eh_frame_size_ = 0; 121 uint64_t eh_frame_size_ = 0;
117 122
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index 90baabedc..07204bcec 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -35,8 +35,8 @@ class MockDwarfDebugFrame : public DwarfDebugFrame<TypeParam> {
35 ~MockDwarfDebugFrame() = default; 35 ~MockDwarfDebugFrame() = default;
36 36
37 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } 37 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
38 void TestSetOffset(uint64_t offset) { this->offset_ = offset; } 38 void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; }
39 void TestSetEndOffset(uint64_t offset) { this->end_offset_ = offset; } 39 void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; }
40 void TestPushFdeInfo(const typename DwarfDebugFrame<TypeParam>::FdeInfo& info) { 40 void TestPushFdeInfo(const typename DwarfDebugFrame<TypeParam>::FdeInfo& info) {
41 this->fdes_.push_back(info); 41 this->fdes_.push_back(info);
42 } 42 }
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index 3dbabe185..53ee719d2 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -34,28 +34,19 @@ class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> {
34 MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {} 34 MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {}
35 ~MockDwarfEhFrame() = default; 35 ~MockDwarfEhFrame() = default;
36 36
37 void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
38 void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
39 void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; }
40 void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; }
41 void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; }
42 void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
43
44 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } 37 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
45 void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrame<TypeParam>::FdeInfo& info) { 38 void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; }
46 this->fde_info_[index] = info; 39 void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; }
40 void TestPushFdeInfo(const typename DwarfEhFrame<TypeParam>::FdeInfo& info) {
41 this->fdes_.push_back(info);
47 } 42 }
48 43
49 uint8_t TestGetVersion() { return this->version_; }
50 uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; }
51 uint64_t TestGetPtrOffset() { return this->ptr_offset_; }
52 uint8_t TestGetTableEncoding() { return this->table_encoding_; }
53 uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
54 uint64_t TestGetFdeCount() { return this->fde_count_; } 44 uint64_t TestGetFdeCount() { return this->fde_count_; }
55 uint64_t TestGetEntriesOffset() { return this->entries_offset_; } 45 uint8_t TestGetOffset() { return this->offset_; }
56 uint64_t TestGetEntriesEnd() { return this->entries_end_; } 46 uint8_t TestGetEndOffset() { return this->end_offset_; }
57 uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; } 47 void TestGetFdeInfo(size_t index, typename DwarfEhFrame<TypeParam>::FdeInfo* info) {
58 uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; } 48 *info = this->fdes_[index];
49 }
59}; 50};
60 51
61template <typename TypeParam> 52template <typename TypeParam>
@@ -76,248 +67,304 @@ TYPED_TEST_CASE_P(DwarfEhFrameTest);
76 67
77// NOTE: All test class variables need to be referenced as this->. 68// NOTE: All test class variables need to be referenced as this->.
78 69
79TYPED_TEST_P(DwarfEhFrameTest, Init) { 70TYPED_TEST_P(DwarfEhFrameTest, Init32) {
80 this->memory_.SetMemory( 71 // CIE 32 information.
81 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4}); 72 this->memory_.SetData32(0x5000, 0xfc);
82 this->memory_.SetData16(0x1004, 0x500); 73 this->memory_.SetData32(0x5004, 0);
83 this->memory_.SetData32(0x1006, 126); 74 this->memory_.SetData8(0x5008, 1);
84 75 this->memory_.SetData8(0x5009, '\0');
85 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100));
86 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
87 EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
88 EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
89 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
90 EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
91 EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
92 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
93 EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
94 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
95 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
96
97 // Verify an unexpected version will cause a fail.
98 this->memory_.SetData8(0x1000, 0);
99 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
100 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error());
101 this->memory_.SetData8(0x1000, 2);
102 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
103 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error());
104}
105 76
106TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_expect_cache_fail) { 77 // FDE 32 information.
107 this->eh_frame_->TestSetTableEntrySize(0x10); 78 this->memory_.SetData32(0x5100, 0xfc);
108 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 79 this->memory_.SetData32(0x5104, 0x104);
109 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); 80 this->memory_.SetData32(0x5108, 0x1500);
110 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); 81 this->memory_.SetData32(0x510c, 0x200);
111 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
112 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error());
113}
114 82
115TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_pcrel) { 83 this->memory_.SetData32(0x5200, 0xfc);
116 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4); 84 this->memory_.SetData32(0x5204, 0x204);
117 this->eh_frame_->TestSetEntriesOffset(0x1000); 85 this->memory_.SetData32(0x5208, 0x2500);
118 this->eh_frame_->TestSetEntriesDataOffset(0x3000); 86 this->memory_.SetData32(0x520c, 0x300);
119 this->eh_frame_->TestSetTableEntrySize(0x10);
120 87
121 this->memory_.SetData32(0x1040, 0x340); 88 // CIE 32 information.
122 this->memory_.SetData32(0x1044, 0x500); 89 this->memory_.SetData32(0x5300, 0xfc);
90 this->memory_.SetData32(0x5304, 0);
91 this->memory_.SetData8(0x5308, 1);
92 this->memory_.SetData8(0x5309, '\0');
123 93
124 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 94 // FDE 32 information.
125 ASSERT_TRUE(info != nullptr); 95 this->memory_.SetData32(0x5400, 0xfc);
126 EXPECT_EQ(0x1384U, info->pc); 96 this->memory_.SetData32(0x5404, 0x104);
127 EXPECT_EQ(0x1540U, info->offset); 97 this->memory_.SetData32(0x5408, 0x3500);
98 this->memory_.SetData32(0x540c, 0x400);
99
100 this->memory_.SetData32(0x5500, 0xfc);
101 this->memory_.SetData32(0x5504, 0x204);
102 this->memory_.SetData32(0x5508, 0x4500);
103 this->memory_.SetData32(0x550c, 0x500);
104
105 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600));
106 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
107
108 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
109
110 this->eh_frame_->TestGetFdeInfo(0, &info);
111 EXPECT_EQ(0x5100U, info.offset);
112 EXPECT_EQ(0x660cU, info.start);
113 EXPECT_EQ(0x680cU, info.end);
114
115 this->eh_frame_->TestGetFdeInfo(1, &info);
116 EXPECT_EQ(0x5200U, info.offset);
117 EXPECT_EQ(0x770cU, info.start);
118 EXPECT_EQ(0x7a0cU, info.end);
119
120 this->eh_frame_->TestGetFdeInfo(2, &info);
121 EXPECT_EQ(0x5400U, info.offset);
122 EXPECT_EQ(0x890cU, info.start);
123 EXPECT_EQ(0x8d0cU, info.end);
124
125 this->eh_frame_->TestGetFdeInfo(3, &info);
126 EXPECT_EQ(0x5500U, info.offset);
127 EXPECT_EQ(0x9a0cU, info.start);
128 EXPECT_EQ(0x9f0cU, info.end);
128} 129}
129 130
130TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_datarel) { 131TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) {
131 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4); 132 // CIE 32 information.
132 this->eh_frame_->TestSetEntriesOffset(0x1000); 133 this->memory_.SetData32(0x5000, 0xfc);
133 this->eh_frame_->TestSetEntriesDataOffset(0x3000); 134 this->memory_.SetData32(0x5004, 0);
134 this->eh_frame_->TestSetTableEntrySize(0x10); 135 this->memory_.SetData8(0x5008, 1);
136 this->memory_.SetData8(0x5009, '\0');
135 137
136 this->memory_.SetData32(0x1040, 0x340); 138 // FDE 32 information.
137 this->memory_.SetData32(0x1044, 0x500); 139 this->memory_.SetData32(0x5100, 0xfc);
140 this->memory_.SetData32(0x5104, 0x1000);
141 this->memory_.SetData32(0x5108, 0x1500);
142 this->memory_.SetData32(0x510c, 0x200);
138 143
139 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 144 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600));
140 ASSERT_TRUE(info != nullptr); 145 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error());
141 EXPECT_EQ(0x3344U, info->pc);
142 EXPECT_EQ(0x3500U, info->offset);
143} 146}
144 147
145TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_cached) { 148TYPED_TEST_P(DwarfEhFrameTest, Init64) {
146 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 149 // CIE 64 information.
147 this->eh_frame_->TestSetEntriesOffset(0x1000); 150 this->memory_.SetData32(0x5000, 0xffffffff);
148 this->eh_frame_->TestSetTableEntrySize(0x10); 151 this->memory_.SetData64(0x5004, 0xf4);
152 this->memory_.SetData64(0x500c, 0);
153 this->memory_.SetData8(0x5014, 1);
154 this->memory_.SetData8(0x5015, '\0');
155
156 // FDE 64 information.
157 this->memory_.SetData32(0x5100, 0xffffffff);
158 this->memory_.SetData64(0x5104, 0xf4);
159 this->memory_.SetData64(0x510c, 0x10c);
160 this->memory_.SetData64(0x5114, 0x1500);
161 this->memory_.SetData64(0x511c, 0x200);
162
163 this->memory_.SetData32(0x5200, 0xffffffff);
164 this->memory_.SetData64(0x5204, 0xf4);
165 this->memory_.SetData64(0x520c, 0x20c);
166 this->memory_.SetData64(0x5214, 0x2500);
167 this->memory_.SetData64(0x521c, 0x300);
149 168
150 this->memory_.SetData32(0x1040, 0x340); 169 // CIE 64 information.
151 this->memory_.SetData32(0x1044, 0x500); 170 this->memory_.SetData32(0x5300, 0xffffffff);
171 this->memory_.SetData64(0x5304, 0xf4);
172 this->memory_.SetData64(0x530c, 0);
173 this->memory_.SetData8(0x5314, 1);
174 this->memory_.SetData8(0x5315, '\0');
152 175
153 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 176 // FDE 64 information.
154 ASSERT_TRUE(info != nullptr); 177 this->memory_.SetData32(0x5400, 0xffffffff);
155 EXPECT_EQ(0x344U, info->pc); 178 this->memory_.SetData64(0x5404, 0xf4);
156 EXPECT_EQ(0x500U, info->offset); 179 this->memory_.SetData64(0x540c, 0x10c);
180 this->memory_.SetData64(0x5414, 0x3500);
181 this->memory_.SetData64(0x541c, 0x400);
182
183 this->memory_.SetData32(0x5500, 0xffffffff);
184 this->memory_.SetData64(0x5504, 0xf4);
185 this->memory_.SetData64(0x550c, 0x20c);
186 this->memory_.SetData64(0x5514, 0x4500);
187 this->memory_.SetData64(0x551c, 0x500);
188
189 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600));
190 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
191
192 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
193
194 this->eh_frame_->TestGetFdeInfo(0, &info);
195 EXPECT_EQ(0x5100U, info.offset);
196 EXPECT_EQ(0x661cU, info.start);
197 EXPECT_EQ(0x681cU, info.end);
198
199 this->eh_frame_->TestGetFdeInfo(1, &info);
200 EXPECT_EQ(0x5200U, info.offset);
201 EXPECT_EQ(0x771cU, info.start);
202 EXPECT_EQ(0x7a1cU, info.end);
203
204 this->eh_frame_->TestGetFdeInfo(2, &info);
205 EXPECT_EQ(0x5400U, info.offset);
206 EXPECT_EQ(0x891cU, info.start);
207 EXPECT_EQ(0x8d1cU, info.end);
208
209 this->eh_frame_->TestGetFdeInfo(3, &info);
210 EXPECT_EQ(0x5500U, info.offset);
211 EXPECT_EQ(0x9a1cU, info.start);
212 EXPECT_EQ(0x9f1cU, info.end);
213}
157 214
158 // Clear the memory so that this will fail if it doesn't read cached data. 215TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) {
159 this->memory_.Clear(); 216 // CIE 64 information.
217 this->memory_.SetData32(0x5000, 0xffffffff);
218 this->memory_.SetData64(0x5004, 0xf4);
219 this->memory_.SetData64(0x500c, 0);
220 this->memory_.SetData8(0x5014, 1);
221 this->memory_.SetData8(0x5015, '\0');
160 222
161 info = this->eh_frame_->GetFdeInfoFromIndex(2); 223 // FDE 64 information.
162 ASSERT_TRUE(info != nullptr); 224 this->memory_.SetData32(0x5100, 0xffffffff);
163 EXPECT_EQ(0x344U, info->pc); 225 this->memory_.SetData64(0x5104, 0xf4);
164 EXPECT_EQ(0x500U, info->offset); 226 this->memory_.SetData64(0x510c, 0x1000);
227 this->memory_.SetData64(0x5114, 0x1500);
228 this->memory_.SetData64(0x511c, 0x200);
229
230 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600));
231 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error());
165} 232}
166 233
167TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetBinary_verify) { 234TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
168 this->eh_frame_->TestSetTableEntrySize(0x10); 235 // CIE 32 information.
169 this->eh_frame_->TestSetFdeCount(10); 236 this->memory_.SetData32(0x5000, 0xfc);
237 this->memory_.SetData32(0x5004, 0);
238 this->memory_.SetData8(0x5008, 1);
239 // Augment string.
240 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'});
241 // Code alignment factor.
242 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00});
243 // Data alignment factor.
244 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
245 // Return address register
246 this->memory_.SetData8(0x5014, 0x84);
247 // Augmentation length
248 this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00});
249 // R data.
250 this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2);
170 251
171 typename DwarfEhFrame<TypeParam>::FdeInfo info; 252 // FDE 32 information.
172 for (size_t i = 0; i < 10; i++) { 253 this->memory_.SetData32(0x5100, 0xfc);
173 info.pc = 0x1000 * (i + 1); 254 this->memory_.SetData32(0x5104, 0x104);
255 this->memory_.SetData16(0x5108, 0x1500);
256 this->memory_.SetData16(0x510a, 0x200);
257
258 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200));
259 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
260
261 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
262 this->eh_frame_->TestGetFdeInfo(0, &info);
263 EXPECT_EQ(0x5100U, info.offset);
264 EXPECT_EQ(0x660aU, info.start);
265 EXPECT_EQ(0x680aU, info.end);
266}
267
268TYPED_TEST_P(DwarfEhFrameTest, Init_version4) {
269 // CIE 32 information.
270 this->memory_.SetData32(0x5000, 0xfc);
271 this->memory_.SetData32(0x5004, 0);
272 this->memory_.SetData8(0x5008, 4);
273 // Augment string.
274 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
275 // Address size.
276 this->memory_.SetData8(0x500e, 4);
277 // Segment size.
278 this->memory_.SetData8(0x500f, 0);
279 // Code alignment factor.
280 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00});
281 // Data alignment factor.
282 this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
283 // Return address register
284 this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10});
285 // Augmentation length
286 this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00});
287 // L data.
288 this->memory_.SetData8(0x501a, 0x10);
289 // P data.
290 this->memory_.SetData8(0x501b, DW_EH_PE_udata4);
291 this->memory_.SetData32(0x501c, 0x100);
292 // R data.
293 this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2);
294
295 // FDE 32 information.
296 this->memory_.SetData32(0x5100, 0xfc);
297 this->memory_.SetData32(0x5104, 0x104);
298 this->memory_.SetData16(0x5108, 0x1500);
299 this->memory_.SetData16(0x510a, 0x200);
300
301 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200));
302 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
303
304 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
305 this->eh_frame_->TestGetFdeInfo(0, &info);
306 EXPECT_EQ(0x5100U, info.offset);
307 EXPECT_EQ(0x660aU, info.start);
308 EXPECT_EQ(0x680aU, info.end);
309}
310
311TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
312 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
313 for (size_t i = 0; i < 9; i++) {
314 info.start = 0x1000 * (i + 1);
315 info.end = 0x1000 * (i + 2) - 0x10;
174 info.offset = 0x5000 + i * 0x20; 316 info.offset = 0x5000 + i * 0x20;
175 this->eh_frame_->TestSetFdeInfo(i, info); 317 this->eh_frame_->TestPushFdeInfo(info);
176 } 318 }
177 319
320 this->eh_frame_->TestSetFdeCount(0);
178 uint64_t fde_offset; 321 uint64_t fde_offset;
179 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); 322 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
180 // Not an error, just not found.
181 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 323 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
182 // Even number of elements. 324
183 for (size_t i = 0; i < 10; i++) { 325 this->eh_frame_->TestSetFdeCount(9);
326 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
327 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
328 // Odd number of elements.
329 for (size_t i = 0; i < 9; i++) {
184 TypeParam pc = 0x1000 * (i + 1); 330 TypeParam pc = 0x1000 * (i + 1);
185 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i; 331 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
186 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 332 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
187 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10)) << "Failed at index " 333 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
188 << i;
189 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 334 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
190 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10)) 335 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
191 << "Failed at index " << i; 336 << "Failed at index " << i;
192 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 337 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
338 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
339 << "Failed at index " << i;
340 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
193 } 341 }
194 // Odd number of elements. 342
195 for (size_t i = 0; i < 9; i++) { 343 // Even number of elements.
344 this->eh_frame_->TestSetFdeCount(10);
345 info.start = 0xa000;
346 info.end = 0xaff0;
347 info.offset = 0x5120;
348 this->eh_frame_->TestPushFdeInfo(info);
349
350 for (size_t i = 0; i < 10; i++) {
196 TypeParam pc = 0x1000 * (i + 1); 351 TypeParam pc = 0x1000 * (i + 1);
197 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i; 352 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
198 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 353 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
199 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9)) << "Failed at index " 354 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
200 << i;
201 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 355 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
202 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9)) 356 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
203 << "Failed at index " << i; 357 << "Failed at index " << i;
204 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 358 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
359 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
360 << "Failed at index " << i;
361 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
205 } 362 }
206} 363}
207 364
208TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential) {
209 this->eh_frame_->TestSetFdeCount(10);
210 this->eh_frame_->TestSetEntriesDataOffset(0x100);
211 this->eh_frame_->TestSetEntriesEnd(0x2000);
212 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
213
214 this->memory_.SetData32(0x1040, 0x340);
215 this->memory_.SetData32(0x1044, 0x500);
216
217 this->memory_.SetData32(0x1048, 0x440);
218 this->memory_.SetData32(0x104c, 0x600);
219
220 // Verify that if entries is zero, that it fails.
221 uint64_t fde_offset;
222 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
223 this->eh_frame_->TestSetCurEntriesOffset(0x1040);
224
225 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
226 EXPECT_EQ(0x500U, fde_offset);
227
228 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
229 EXPECT_EQ(0x600U, fde_offset);
230
231 // Expect that the data is cached so no more memory reads will occur.
232 this->memory_.Clear();
233 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
234 EXPECT_EQ(0x600U, fde_offset);
235}
236
237TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential_last_element) {
238 this->eh_frame_->TestSetFdeCount(2);
239 this->eh_frame_->TestSetEntriesDataOffset(0x100);
240 this->eh_frame_->TestSetEntriesEnd(0x2000);
241 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
242 this->eh_frame_->TestSetCurEntriesOffset(0x1040);
243
244 this->memory_.SetData32(0x1040, 0x340);
245 this->memory_.SetData32(0x1044, 0x500);
246
247 this->memory_.SetData32(0x1048, 0x440);
248 this->memory_.SetData32(0x104c, 0x600);
249
250 uint64_t fde_offset;
251 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
252 EXPECT_EQ(0x600U, fde_offset);
253}
254
255TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential_end_check) {
256 this->eh_frame_->TestSetFdeCount(2);
257 this->eh_frame_->TestSetEntriesDataOffset(0x100);
258 this->eh_frame_->TestSetEntriesEnd(0x1048);
259 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
260
261 this->memory_.SetData32(0x1040, 0x340);
262 this->memory_.SetData32(0x1044, 0x500);
263
264 this->memory_.SetData32(0x1048, 0x440);
265 this->memory_.SetData32(0x104c, 0x600);
266
267 uint64_t fde_offset;
268 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
269 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
270}
271
272TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_fail_fde_count) {
273 this->eh_frame_->TestSetFdeCount(0);
274
275 uint64_t fde_offset;
276 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
277 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
278}
279
280TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_binary_search) {
281 this->eh_frame_->TestSetTableEntrySize(16);
282 this->eh_frame_->TestSetFdeCount(10);
283
284 typename DwarfEhFrame<TypeParam>::FdeInfo info;
285 info.pc = 0x550;
286 info.offset = 0x10500;
287 this->eh_frame_->TestSetFdeInfo(5, info);
288 info.pc = 0x750;
289 info.offset = 0x10700;
290 this->eh_frame_->TestSetFdeInfo(7, info);
291 info.pc = 0x850;
292 info.offset = 0x10800;
293 this->eh_frame_->TestSetFdeInfo(8, info);
294
295 uint64_t fde_offset;
296 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset));
297 EXPECT_EQ(0x10700U, fde_offset);
298}
299
300TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_sequential_search) {
301 this->eh_frame_->TestSetFdeCount(10);
302 this->eh_frame_->TestSetTableEntrySize(0);
303
304 typename DwarfEhFrame<TypeParam>::FdeInfo info;
305 info.pc = 0x50;
306 info.offset = 0x10000;
307 this->eh_frame_->TestSetFdeInfo(0, info);
308 info.pc = 0x150;
309 info.offset = 0x10100;
310 this->eh_frame_->TestSetFdeInfo(1, info);
311 info.pc = 0x250;
312 info.offset = 0x10200;
313 this->eh_frame_->TestSetFdeInfo(2, info);
314
315 uint64_t fde_offset;
316 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset));
317 EXPECT_EQ(0x10100U, fde_offset);
318}
319
320TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) { 365TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) {
366 this->eh_frame_->TestSetOffset(0x4000);
367
321 // CIE 32 information. 368 // CIE 32 information.
322 this->memory_.SetData32(0xf000, 0x100); 369 this->memory_.SetData32(0xf000, 0x100);
323 this->memory_.SetData32(0xf004, 0); 370 this->memory_.SetData32(0xf004, 0);
@@ -358,6 +405,8 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) {
358} 405}
359 406
360TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) { 407TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
408 this->eh_frame_->TestSetOffset(0x2000);
409
361 // CIE 64 information. 410 // CIE 64 information.
362 this->memory_.SetData32(0x6000, 0xffffffff); 411 this->memory_.SetData32(0x6000, 0xffffffff);
363 this->memory_.SetData64(0x6004, 0x100); 412 this->memory_.SetData64(0x6004, 0x100);
@@ -399,25 +448,9 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
399 EXPECT_EQ(0x20U, fde->cie->return_address_register); 448 EXPECT_EQ(0x20U, fde->cie->return_address_register);
400} 449}
401 450
402TYPED_TEST_P(DwarfEhFrameTest, GetFdeFromPc_fde_not_found) { 451REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64,
403 this->eh_frame_->TestSetTableEntrySize(16); 452 Init64_fde_not_following_cie, Init_version1, Init_version4,
404 this->eh_frame_->TestSetFdeCount(1); 453 GetFdeOffsetFromPc, GetCieFde32, GetCieFde64);
405
406 typename DwarfEhFrame<TypeParam>::FdeInfo info;
407 info.pc = 0x550;
408 info.offset = 0x10500;
409 this->eh_frame_->TestSetFdeInfo(0, info);
410
411 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
412}
413
414REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init, GetFdeInfoFromIndex_expect_cache_fail,
415 GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel,
416 GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify,
417 GetFdeOffsetSequential, GetFdeOffsetSequential_last_element,
418 GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count,
419 GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search,
420 GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
421 454
422typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; 455typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
423INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); 456INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
new file mode 100644
index 000000000..1028ab9fe
--- /dev/null
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -0,0 +1,434 @@
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
22#include "DwarfEhFrameWithHdr.h"
23#include "DwarfEncoding.h"
24#include "DwarfError.h"
25
26#include "LogFake.h"
27#include "MemoryFake.h"
28
29namespace unwindstack {
30
31template <typename TypeParam>
32class MockDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> {
33 public:
34 MockDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {}
35 ~MockDwarfEhFrameWithHdr() = default;
36
37 void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
38 void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
39 void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; }
40 void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; }
41 void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; }
42 void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
43
44 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
45 void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo& info) {
46 this->fde_info_[index] = info;
47 }
48
49 uint8_t TestGetVersion() { return this->version_; }
50 uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; }
51 uint64_t TestGetPtrOffset() { return this->ptr_offset_; }
52 uint8_t TestGetTableEncoding() { return this->table_encoding_; }
53 uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
54 uint64_t TestGetFdeCount() { return this->fde_count_; }
55 uint64_t TestGetEntriesOffset() { return this->entries_offset_; }
56 uint64_t TestGetEntriesEnd() { return this->entries_end_; }
57 uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; }
58 uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; }
59};
60
61template <typename TypeParam>
62class DwarfEhFrameWithHdrTest : public ::testing::Test {
63 protected:
64 void SetUp() override {
65 memory_.Clear();
66 eh_frame_ = new MockDwarfEhFrameWithHdr<TypeParam>(&memory_);
67 ResetLogs();
68 }
69
70 void TearDown() override { delete eh_frame_; }
71
72 MemoryFake memory_;
73 MockDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr;
74};
75TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest);
76
77// NOTE: All test class variables need to be referenced as this->.
78
79TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) {
80 this->memory_.SetMemory(
81 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
82 this->memory_.SetData16(0x1004, 0x500);
83 this->memory_.SetData32(0x1006, 126);
84
85 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100));
86 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
87 EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
88 EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
89 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
90 EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
91 EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
92 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
93 EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
94 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
95 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
96
97 // Verify an unexpected version will cause a fail.
98 this->memory_.SetData8(0x1000, 0);
99 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
100 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error());
101 this->memory_.SetData8(0x1000, 2);
102 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
103 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error());
104}
105
106TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
107 this->eh_frame_->TestSetTableEntrySize(0x10);
108 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
109 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
110 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error());
111 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
112 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error());
113}
114
115TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
116 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4);
117 this->eh_frame_->TestSetEntriesOffset(0x1000);
118 this->eh_frame_->TestSetEntriesDataOffset(0x3000);
119 this->eh_frame_->TestSetTableEntrySize(0x10);
120
121 this->memory_.SetData32(0x1040, 0x340);
122 this->memory_.SetData32(0x1044, 0x500);
123
124 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
125 ASSERT_TRUE(info != nullptr);
126 EXPECT_EQ(0x1384U, info->pc);
127 EXPECT_EQ(0x1540U, info->offset);
128}
129
130TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) {
131 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4);
132 this->eh_frame_->TestSetEntriesOffset(0x1000);
133 this->eh_frame_->TestSetEntriesDataOffset(0x3000);
134 this->eh_frame_->TestSetTableEntrySize(0x10);
135
136 this->memory_.SetData32(0x1040, 0x340);
137 this->memory_.SetData32(0x1044, 0x500);
138
139 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
140 ASSERT_TRUE(info != nullptr);
141 EXPECT_EQ(0x3344U, info->pc);
142 EXPECT_EQ(0x3500U, info->offset);
143}
144
145TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) {
146 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
147 this->eh_frame_->TestSetEntriesOffset(0x1000);
148 this->eh_frame_->TestSetTableEntrySize(0x10);
149
150 this->memory_.SetData32(0x1040, 0x340);
151 this->memory_.SetData32(0x1044, 0x500);
152
153 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
154 ASSERT_TRUE(info != nullptr);
155 EXPECT_EQ(0x344U, info->pc);
156 EXPECT_EQ(0x500U, info->offset);
157
158 // Clear the memory so that this will fail if it doesn't read cached data.
159 this->memory_.Clear();
160
161 info = this->eh_frame_->GetFdeInfoFromIndex(2);
162 ASSERT_TRUE(info != nullptr);
163 EXPECT_EQ(0x344U, info->pc);
164 EXPECT_EQ(0x500U, info->offset);
165}
166
167TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) {
168 this->eh_frame_->TestSetTableEntrySize(0x10);
169 this->eh_frame_->TestSetFdeCount(10);
170
171 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
172 for (size_t i = 0; i < 10; i++) {
173 info.pc = 0x1000 * (i + 1);
174 info.offset = 0x5000 + i * 0x20;
175 this->eh_frame_->TestSetFdeInfo(i, info);
176 }
177
178 uint64_t fde_offset;
179 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10));
180 // Not an error, just not found.
181 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
182 // Even number of elements.
183 for (size_t i = 0; i < 10; i++) {
184 TypeParam pc = 0x1000 * (i + 1);
185 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i;
186 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
187 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10))
188 << "Failed at index " << i;
189 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
190 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10))
191 << "Failed at index " << i;
192 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
193 }
194 // Odd number of elements.
195 for (size_t i = 0; i < 9; i++) {
196 TypeParam pc = 0x1000 * (i + 1);
197 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i;
198 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
199 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9))
200 << "Failed at index " << i;
201 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
202 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9))
203 << "Failed at index " << i;
204 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
205 }
206}
207
208TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_index_fail) {
209 this->eh_frame_->TestSetTableEntrySize(0x10);
210 this->eh_frame_->TestSetFdeCount(10);
211
212 uint64_t fde_offset;
213 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x1000, &fde_offset, 10));
214}
215
216TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential) {
217 this->eh_frame_->TestSetFdeCount(10);
218 this->eh_frame_->TestSetEntriesDataOffset(0x100);
219 this->eh_frame_->TestSetEntriesEnd(0x2000);
220 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
221
222 this->memory_.SetData32(0x1040, 0x340);
223 this->memory_.SetData32(0x1044, 0x500);
224
225 this->memory_.SetData32(0x1048, 0x440);
226 this->memory_.SetData32(0x104c, 0x600);
227
228 // Verify that if entries is zero, that it fails.
229 uint64_t fde_offset;
230 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
231 this->eh_frame_->TestSetCurEntriesOffset(0x1040);
232
233 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
234 EXPECT_EQ(0x500U, fde_offset);
235
236 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
237 EXPECT_EQ(0x600U, fde_offset);
238
239 // Expect that the data is cached so no more memory reads will occur.
240 this->memory_.Clear();
241 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
242 EXPECT_EQ(0x600U, fde_offset);
243}
244
245TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_last_element) {
246 this->eh_frame_->TestSetFdeCount(2);
247 this->eh_frame_->TestSetEntriesDataOffset(0x100);
248 this->eh_frame_->TestSetEntriesEnd(0x2000);
249 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
250 this->eh_frame_->TestSetCurEntriesOffset(0x1040);
251
252 this->memory_.SetData32(0x1040, 0x340);
253 this->memory_.SetData32(0x1044, 0x500);
254
255 this->memory_.SetData32(0x1048, 0x440);
256 this->memory_.SetData32(0x104c, 0x600);
257
258 uint64_t fde_offset;
259 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
260 EXPECT_EQ(0x600U, fde_offset);
261}
262
263TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_end_check) {
264 this->eh_frame_->TestSetFdeCount(2);
265 this->eh_frame_->TestSetEntriesDataOffset(0x100);
266 this->eh_frame_->TestSetEntriesEnd(0x1048);
267 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
268
269 this->memory_.SetData32(0x1040, 0x340);
270 this->memory_.SetData32(0x1044, 0x500);
271
272 this->memory_.SetData32(0x1048, 0x440);
273 this->memory_.SetData32(0x104c, 0x600);
274
275 uint64_t fde_offset;
276 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
277 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
278}
279
280TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) {
281 this->eh_frame_->TestSetFdeCount(0);
282
283 uint64_t fde_offset;
284 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
285 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
286}
287
288TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) {
289 this->eh_frame_->TestSetTableEntrySize(16);
290 this->eh_frame_->TestSetFdeCount(10);
291
292 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
293 info.pc = 0x550;
294 info.offset = 0x10500;
295 this->eh_frame_->TestSetFdeInfo(5, info);
296 info.pc = 0x750;
297 info.offset = 0x10700;
298 this->eh_frame_->TestSetFdeInfo(7, info);
299 info.pc = 0x850;
300 info.offset = 0x10800;
301 this->eh_frame_->TestSetFdeInfo(8, info);
302
303 uint64_t fde_offset;
304 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset));
305 EXPECT_EQ(0x10700U, fde_offset);
306}
307
308TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_sequential_search) {
309 this->eh_frame_->TestSetFdeCount(10);
310 this->eh_frame_->TestSetTableEntrySize(0);
311
312 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
313 info.pc = 0x50;
314 info.offset = 0x10000;
315 this->eh_frame_->TestSetFdeInfo(0, info);
316 info.pc = 0x150;
317 info.offset = 0x10100;
318 this->eh_frame_->TestSetFdeInfo(1, info);
319 info.pc = 0x250;
320 info.offset = 0x10200;
321 this->eh_frame_->TestSetFdeInfo(2, info);
322
323 uint64_t fde_offset;
324 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset));
325 EXPECT_EQ(0x10100U, fde_offset);
326}
327
328TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) {
329 // CIE 32 information.
330 this->memory_.SetData32(0xf000, 0x100);
331 this->memory_.SetData32(0xf004, 0);
332 this->memory_.SetData8(0xf008, 0x1);
333 this->memory_.SetData8(0xf009, '\0');
334 this->memory_.SetData8(0xf00a, 4);
335 this->memory_.SetData8(0xf00b, 8);
336 this->memory_.SetData8(0xf00c, 0x20);
337
338 // FDE 32 information.
339 this->memory_.SetData32(0x14000, 0x20);
340 this->memory_.SetData32(0x14004, 0x5004);
341 this->memory_.SetData32(0x14008, 0x9000);
342 this->memory_.SetData32(0x1400c, 0x100);
343
344 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000);
345 ASSERT_TRUE(fde != nullptr);
346 EXPECT_EQ(0x14010U, fde->cfa_instructions_offset);
347 EXPECT_EQ(0x14024U, fde->cfa_instructions_end);
348 EXPECT_EQ(0x1d00cU, fde->pc_start);
349 EXPECT_EQ(0x1d10cU, fde->pc_end);
350 EXPECT_EQ(0xf000U, fde->cie_offset);
351 EXPECT_EQ(0U, fde->lsda_address);
352
353 ASSERT_TRUE(fde->cie != nullptr);
354 EXPECT_EQ(1U, fde->cie->version);
355 EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
356 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
357 EXPECT_EQ(0U, fde->cie->segment_size);
358 EXPECT_EQ(1U, fde->cie->augmentation_string.size());
359 EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
360 EXPECT_EQ(0U, fde->cie->personality_handler);
361 EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset);
362 EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end);
363 EXPECT_EQ(4U, fde->cie->code_alignment_factor);
364 EXPECT_EQ(8, fde->cie->data_alignment_factor);
365 EXPECT_EQ(0x20U, fde->cie->return_address_register);
366}
367
368TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) {
369 // CIE 64 information.
370 this->memory_.SetData32(0x6000, 0xffffffff);
371 this->memory_.SetData64(0x6004, 0x100);
372 this->memory_.SetData64(0x600c, 0);
373 this->memory_.SetData8(0x6014, 0x1);
374 this->memory_.SetData8(0x6015, '\0');
375 this->memory_.SetData8(0x6016, 4);
376 this->memory_.SetData8(0x6017, 8);
377 this->memory_.SetData8(0x6018, 0x20);
378
379 // FDE 64 information.
380 this->memory_.SetData32(0x8000, 0xffffffff);
381 this->memory_.SetData64(0x8004, 0x200);
382 this->memory_.SetData64(0x800c, 0x200c);
383 this->memory_.SetData64(0x8014, 0x5000);
384 this->memory_.SetData64(0x801c, 0x300);
385
386 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000);
387 ASSERT_TRUE(fde != nullptr);
388 EXPECT_EQ(0x8024U, fde->cfa_instructions_offset);
389 EXPECT_EQ(0x820cU, fde->cfa_instructions_end);
390 EXPECT_EQ(0xd01cU, fde->pc_start);
391 EXPECT_EQ(0xd31cU, fde->pc_end);
392 EXPECT_EQ(0x6000U, fde->cie_offset);
393 EXPECT_EQ(0U, fde->lsda_address);
394
395 ASSERT_TRUE(fde->cie != nullptr);
396 EXPECT_EQ(1U, fde->cie->version);
397 EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding);
398 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
399 EXPECT_EQ(0U, fde->cie->segment_size);
400 EXPECT_EQ(1U, fde->cie->augmentation_string.size());
401 EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
402 EXPECT_EQ(0U, fde->cie->personality_handler);
403 EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset);
404 EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end);
405 EXPECT_EQ(4U, fde->cie->code_alignment_factor);
406 EXPECT_EQ(8, fde->cie->data_alignment_factor);
407 EXPECT_EQ(0x20U, fde->cie->return_address_register);
408}
409
410TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) {
411 this->eh_frame_->TestSetTableEntrySize(16);
412 this->eh_frame_->TestSetFdeCount(1);
413
414 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
415 info.pc = 0x550;
416 info.offset = 0x10500;
417 this->eh_frame_->TestSetFdeInfo(0, info);
418
419 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
420}
421
422REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, GetFdeInfoFromIndex_expect_cache_fail,
423 GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel,
424 GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify,
425 GetFdeOffsetBinary_index_fail, GetFdeOffsetSequential,
426 GetFdeOffsetSequential_last_element, GetFdeOffsetSequential_end_check,
427 GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_binary_search,
428 GetFdeOffsetFromPc_sequential_search, GetCieFde32, GetCieFde64,
429 GetFdeFromPc_fde_not_found);
430
431typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes;
432INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes);
433
434} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 5b9f3ee19..d54b0bf59 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -42,16 +42,16 @@ class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
42 42
43 MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t)); 43 MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t));
44 44
45 MOCK_METHOD1(IsCie32, bool(uint32_t));
46
47 MOCK_METHOD1(IsCie64, bool(uint64_t));
48
49 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t)); 45 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
50 46
51 MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t)); 47 MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
52 48
53 MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t)); 49 MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
54 50
51 void TestSetCie32Value(uint32_t value32) { this->cie32_value_ = value32; }
52
53 void TestSetCie64Value(uint64_t value64) { this->cie64_value_ = value64; }
54
55 void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) { 55 void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) {
56 this->cie_entries_[offset] = cie; 56 this->cie_entries_[offset] = cie;
57 } 57 }
@@ -77,6 +77,8 @@ class DwarfSectionImplTest : public ::testing::Test {
77 memory_.Clear(); 77 memory_.Clear();
78 section_ = new MockDwarfSectionImpl<TypeParam>(&memory_); 78 section_ = new MockDwarfSectionImpl<TypeParam>(&memory_);
79 ResetLogs(); 79 ResetLogs();
80 section_->TestSetCie32Value(static_cast<uint32_t>(-1));
81 section_->TestSetCie64Value(static_cast<uint64_t>(-1));
80 } 82 }
81 83
82 void TearDown() override { delete section_; } 84 void TearDown() override { delete section_; }
@@ -448,8 +450,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
448 this->memory_.SetData8(0x500b, 8); 450 this->memory_.SetData8(0x500b, 8);
449 this->memory_.SetData8(0x500c, 0x20); 451 this->memory_.SetData8(0x500c, 0x20);
450 452
451 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
452
453 const DwarfCie* cie = this->section_->GetCie(0x5000); 453 const DwarfCie* cie = this->section_->GetCie(0x5000);
454 ASSERT_TRUE(cie != nullptr); 454 ASSERT_TRUE(cie != nullptr);
455 EXPECT_EQ(1U, cie->version); 455 EXPECT_EQ(1U, cie->version);
@@ -493,8 +493,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
493 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f}); 493 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
494 this->memory_.SetData8(0x5010, 0x20); 494 this->memory_.SetData8(0x5010, 0x20);
495 495
496 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
497
498 const DwarfCie* cie = this->section_->GetCie(0x5000); 496 const DwarfCie* cie = this->section_->GetCie(0x5000);
499 ASSERT_TRUE(cie != nullptr); 497 ASSERT_TRUE(cie != nullptr);
500 EXPECT_EQ(1U, cie->version); 498 EXPECT_EQ(1U, cie->version);
@@ -514,15 +512,13 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
514TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) { 512TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
515 this->memory_.SetData32(0x8000, 0xffffffff); 513 this->memory_.SetData32(0x8000, 0xffffffff);
516 this->memory_.SetData64(0x8004, 0x200); 514 this->memory_.SetData64(0x8004, 0x200);
517 this->memory_.SetData64(0x800c, 0xffffffff); 515 this->memory_.SetData64(0x800c, 0xffffffffffffffffULL);
518 this->memory_.SetData8(0x8014, 0x1); 516 this->memory_.SetData8(0x8014, 0x1);
519 this->memory_.SetData8(0x8015, '\0'); 517 this->memory_.SetData8(0x8015, '\0');
520 this->memory_.SetData8(0x8016, 4); 518 this->memory_.SetData8(0x8016, 4);
521 this->memory_.SetData8(0x8017, 8); 519 this->memory_.SetData8(0x8017, 8);
522 this->memory_.SetData8(0x8018, 0x20); 520 this->memory_.SetData8(0x8018, 0x20);
523 521
524 EXPECT_CALL(*this->section_, IsCie64(0xffffffff)).WillRepeatedly(::testing::Return(true));
525
526 const DwarfCie* cie = this->section_->GetCie(0x8000); 522 const DwarfCie* cie = this->section_->GetCie(0x8000);
527 ASSERT_TRUE(cie != nullptr); 523 ASSERT_TRUE(cie != nullptr);
528 EXPECT_EQ(1U, cie->version); 524 EXPECT_EQ(1U, cie->version);
@@ -557,8 +553,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
557 // R data. 553 // R data.
558 this->memory_.SetData8(0x5018, DW_EH_PE_udata2); 554 this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
559 555
560 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
561
562 const DwarfCie* cie = this->section_->GetCie(0x5000); 556 const DwarfCie* cie = this->section_->GetCie(0x5000);
563 ASSERT_TRUE(cie != nullptr); 557 ASSERT_TRUE(cie != nullptr);
564 EXPECT_EQ(1U, cie->version); 558 EXPECT_EQ(1U, cie->version);
@@ -588,8 +582,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
588 this->memory_.SetData8(0x500b, 8); 582 this->memory_.SetData8(0x500b, 8);
589 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03}); 583 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
590 584
591 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
592
593 const DwarfCie* cie = this->section_->GetCie(0x5000); 585 const DwarfCie* cie = this->section_->GetCie(0x5000);
594 ASSERT_TRUE(cie != nullptr); 586 ASSERT_TRUE(cie != nullptr);
595 EXPECT_EQ(3U, cie->version); 587 EXPECT_EQ(3U, cie->version);
@@ -617,8 +609,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
617 this->memory_.SetData8(0x500d, 8); 609 this->memory_.SetData8(0x500d, 8);
618 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03}); 610 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
619 611
620 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
621
622 const DwarfCie* cie = this->section_->GetCie(0x5000); 612 const DwarfCie* cie = this->section_->GetCie(0x5000);
623 ASSERT_TRUE(cie != nullptr); 613 ASSERT_TRUE(cie != nullptr);
624 EXPECT_EQ(4U, cie->version); 614 EXPECT_EQ(4U, cie->version);
@@ -649,7 +639,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
649 this->memory_.SetData32(0x4008, 0x5000); 639 this->memory_.SetData32(0x4008, 0x5000);
650 this->memory_.SetData32(0x400c, 0x100); 640 this->memory_.SetData32(0x400c, 0x100);
651 641
652 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
653 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); 642 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
654 DwarfCie cie{}; 643 DwarfCie cie{};
655 cie.fde_address_encoding = DW_EH_PE_udata4; 644 cie.fde_address_encoding = DW_EH_PE_udata4;
@@ -673,7 +662,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segme
673 this->memory_.SetData32(0x4018, 0x5000); 662 this->memory_.SetData32(0x4018, 0x5000);
674 this->memory_.SetData32(0x401c, 0x100); 663 this->memory_.SetData32(0x401c, 0x100);
675 664
676 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
677 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); 665 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
678 DwarfCie cie{}; 666 DwarfCie cie{};
679 cie.fde_address_encoding = DW_EH_PE_udata4; 667 cie.fde_address_encoding = DW_EH_PE_udata4;
@@ -700,7 +688,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
700 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01}); 688 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
701 this->memory_.SetData16(0x4012, 0x1234); 689 this->memory_.SetData16(0x4012, 0x1234);
702 690
703 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
704 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); 691 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
705 DwarfCie cie{}; 692 DwarfCie cie{};
706 cie.fde_address_encoding = DW_EH_PE_udata4; 693 cie.fde_address_encoding = DW_EH_PE_udata4;
@@ -727,7 +714,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
727 this->memory_.SetData32(0x4014, 0x5000); 714 this->memory_.SetData32(0x4014, 0x5000);
728 this->memory_.SetData32(0x4018, 0x100); 715 this->memory_.SetData32(0x4018, 0x100);
729 716
730 EXPECT_CALL(*this->section_, IsCie64(0x12345678)).WillOnce(::testing::Return(false));
731 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678)) 717 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
732 .WillOnce(::testing::Return(0x12345678)); 718 .WillOnce(::testing::Return(0x12345678));
733 DwarfCie cie{}; 719 DwarfCie cie{};
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 2752e99c2..e138c3acf 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -910,8 +910,32 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() {
910 memory_.SetMemory(offset, &shdr, sizeof(shdr)); 910 memory_.SetMemory(offset, &shdr, sizeof(shdr));
911 offset += ehdr.e_shentsize; 911 offset += ehdr.e_shentsize;
912 912
913 memset(&shdr, 0, sizeof(shdr));
914 shdr.sh_type = SHT_PROGBITS;
915 shdr.sh_link = 2;
916 shdr.sh_name = 0x300;
917 shdr.sh_addr = 0x7000;
918 shdr.sh_offset = 0x7000;
919 shdr.sh_entsize = 0x100;
920 shdr.sh_size = 0x800;
921 memory_.SetMemory(offset, &shdr, sizeof(shdr));
922 offset += ehdr.e_shentsize;
923
924 memset(&shdr, 0, sizeof(shdr));
925 shdr.sh_type = SHT_PROGBITS;
926 shdr.sh_link = 2;
927 shdr.sh_name = 0x400;
928 shdr.sh_addr = 0x6000;
929 shdr.sh_offset = 0xa000;
930 shdr.sh_entsize = 0x100;
931 shdr.sh_size = 0xf00;
932 memory_.SetMemory(offset, &shdr, sizeof(shdr));
933 offset += ehdr.e_shentsize;
934
913 memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame")); 935 memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
914 memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata")); 936 memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata"));
937 memory_.SetMemory(0xf300, ".eh_frame", sizeof(".eh_frame"));
938 memory_.SetMemory(0xf400, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
915 939
916 uint64_t load_bias = 0; 940 uint64_t load_bias = 0;
917 ASSERT_TRUE(elf->Init(&load_bias)); 941 ASSERT_TRUE(elf->Init(&load_bias));
@@ -920,6 +944,10 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() {
920 EXPECT_EQ(0x500U, elf->debug_frame_size()); 944 EXPECT_EQ(0x500U, elf->debug_frame_size());
921 EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset()); 945 EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset());
922 EXPECT_EQ(0x800U, elf->gnu_debugdata_size()); 946 EXPECT_EQ(0x800U, elf->gnu_debugdata_size());
947 EXPECT_EQ(0x7000U, elf->eh_frame_offset());
948 EXPECT_EQ(0x800U, elf->eh_frame_size());
949 EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset());
950 EXPECT_EQ(0xf00U, elf->eh_frame_hdr_size());
923} 951}
924 952
925TEST_F(ElfInterfaceTest, init_section_headers_offsets32) { 953TEST_F(ElfInterfaceTest, init_section_headers_offsets32) {
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
index 696e97817..d06cafc8e 100644
--- a/libvndksupport/linker.c
+++ b/libvndksupport/linker.c
@@ -23,24 +23,38 @@
23 23
24extern struct android_namespace_t* android_get_exported_namespace(const char*); 24extern struct android_namespace_t* android_get_exported_namespace(const char*);
25 25
26static const char* namespace_name = NULL;
27
28static struct android_namespace_t* get_vendor_namespace() {
29 const char* namespace_names[] = {"sphal", "default", NULL};
30 static struct android_namespace_t* vendor_namespace = NULL;
31 if (vendor_namespace == NULL) {
32 int name_idx = 0;
33 while (namespace_names[name_idx] != NULL) {
34 vendor_namespace = android_get_exported_namespace(namespace_names[name_idx]);
35 if (vendor_namespace != NULL) {
36 namespace_name = namespace_names[name_idx];
37 break;
38 }
39 name_idx++;
40 }
41 }
42 return vendor_namespace;
43}
44
26void* android_load_sphal_library(const char* name, int flag) { 45void* android_load_sphal_library(const char* name, int flag) {
27 struct android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal"); 46 struct android_namespace_t* vendor_namespace = get_vendor_namespace();
28 if (sphal_namespace != NULL) { 47 if (vendor_namespace != NULL) {
29 const android_dlextinfo dlextinfo = { 48 const android_dlextinfo dlextinfo = {
30 .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = sphal_namespace, 49 .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = vendor_namespace,
31 }; 50 };
32 void* handle = android_dlopen_ext(name, flag, &dlextinfo); 51 void* handle = android_dlopen_ext(name, flag, &dlextinfo);
33 if (!handle) { 52 if (!handle) {
34 ALOGE( 53 ALOGE("Could not load %s from %s namespace: %s.", name, namespace_name, dlerror());
35 "Could not load %s from sphal namespace: %s. ",
36 name, dlerror());
37 } 54 }
38 return handle; 55 return handle;
39 } else { 56 } else {
40 ALOGI( 57 ALOGD("Loading %s from current namespace instead of sphal namespace.", name);
41 "sphal namespace is not configured for this process. "
42 "Loading %s from the current namespace instead.",
43 name);
44 return dlopen(name, flag); 58 return dlopen(name, flag);
45 } 59 }
46} 60}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 749832530..43362fb5a 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -212,13 +212,19 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
212 if (log_id != LOG_ID_SECURITY) { 212 if (log_id != LOG_ID_SECURITY) {
213 int prio = ANDROID_LOG_INFO; 213 int prio = ANDROID_LOG_INFO;
214 const char* tag = nullptr; 214 const char* tag = nullptr;
215 size_t tag_len = 0;
215 if (log_id == LOG_ID_EVENTS) { 216 if (log_id == LOG_ID_EVENTS) {
216 tag = tagToName(elem->getTag()); 217 tag = tagToName(elem->getTag());
218 if (tag) {
219 tag_len = strlen(tag);
220 }
217 } else { 221 } else {
218 prio = *msg; 222 prio = *msg;
219 tag = msg + 1; 223 tag = msg + 1;
224 tag_len = strnlen(tag, len - 1);
220 } 225 }
221 if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { 226 if (!__android_log_is_loggable_len(prio, tag, tag_len,
227 ANDROID_LOG_VERBOSE)) {
222 // Log traffic received to total 228 // Log traffic received to total
223 wrlock(); 229 wrlock();
224 stats.addTotal(elem); 230 stats.addTotal(elem);
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index d2df68eef..fcf2cd8a1 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -43,9 +43,10 @@ bool LogListener::onDataAvailable(SocketClient* cli) {
43 name_set = true; 43 name_set = true;
44 } 44 }
45 45
46 // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
46 char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) + 47 char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) +
47 LOGGER_ENTRY_MAX_PAYLOAD]; 48 LOGGER_ENTRY_MAX_PAYLOAD + 1];
48 struct iovec iov = { buffer, sizeof(buffer) }; 49 struct iovec iov = { buffer, sizeof(buffer) - 1 };
49 50
50 alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))]; 51 alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
51 struct msghdr hdr = { 52 struct msghdr hdr = {
@@ -55,13 +56,16 @@ bool LogListener::onDataAvailable(SocketClient* cli) {
55 int socket = cli->getSocket(); 56 int socket = cli->getSocket();
56 57
57 // To clear the entire buffer is secure/safe, but this contributes to 1.68% 58 // To clear the entire buffer is secure/safe, but this contributes to 1.68%
58 // overhead under logging load. We are safe because we check counts. 59 // overhead under logging load. We are safe because we check counts, but
60 // still need to clear null terminator
59 // memset(buffer, 0, sizeof(buffer)); 61 // memset(buffer, 0, sizeof(buffer));
60 ssize_t n = recvmsg(socket, &hdr, 0); 62 ssize_t n = recvmsg(socket, &hdr, 0);
61 if (n <= (ssize_t)(sizeof(android_log_header_t))) { 63 if (n <= (ssize_t)(sizeof(android_log_header_t))) {
62 return false; 64 return false;
63 } 65 }
64 66
67 buffer[n] = 0;
68
65 struct ucred* cred = NULL; 69 struct ucred* cred = NULL;
66 70
67 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); 71 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);