diff options
51 files changed, 1647 insertions, 946 deletions
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp index 1c94298da..3c2758276 100644 --- a/adb/daemon/main.cpp +++ b/adb/daemon/main.cpp @@ -233,8 +233,8 @@ int main(int argc, char** argv) { adb_device_banner = optarg; break; case 'v': - printf("Android Debug Bridge Daemon version %d.%d.%d (%s)\n", ADB_VERSION_MAJOR, - ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_VERSION); + printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR, + ADB_VERSION_MINOR, ADB_SERVER_VERSION); return 0; default: // getopt already prints "adbd: invalid option -- %c" for us. 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 import time import unittest -import mock - import adb - def requires_root(func): def wrapper(self, *args): if self.device.get_prop('ro.debuggable') != '1': @@ -76,59 +73,6 @@ def requires_non_root(func): return wrapper -class GetDeviceTest(unittest.TestCase): - def setUp(self): - self.android_serial = os.getenv('ANDROID_SERIAL') - if 'ANDROID_SERIAL' in os.environ: - del os.environ['ANDROID_SERIAL'] - - def tearDown(self): - if self.android_serial is not None: - os.environ['ANDROID_SERIAL'] = self.android_serial - else: - if 'ANDROID_SERIAL' in os.environ: - del os.environ['ANDROID_SERIAL'] - - @mock.patch('adb.device.get_devices') - def test_explicit(self, mock_get_devices): - mock_get_devices.return_value = ['foo', 'bar'] - device = adb.get_device('foo') - self.assertEqual(device.serial, 'foo') - - @mock.patch('adb.device.get_devices') - def test_from_env(self, mock_get_devices): - mock_get_devices.return_value = ['foo', 'bar'] - os.environ['ANDROID_SERIAL'] = 'foo' - device = adb.get_device() - self.assertEqual(device.serial, 'foo') - - @mock.patch('adb.device.get_devices') - def test_arg_beats_env(self, mock_get_devices): - mock_get_devices.return_value = ['foo', 'bar'] - os.environ['ANDROID_SERIAL'] = 'bar' - device = adb.get_device('foo') - self.assertEqual(device.serial, 'foo') - - @mock.patch('adb.device.get_devices') - def test_no_such_device(self, mock_get_devices): - mock_get_devices.return_value = ['foo', 'bar'] - self.assertRaises(adb.DeviceNotFoundError, adb.get_device, ['baz']) - - os.environ['ANDROID_SERIAL'] = 'baz' - self.assertRaises(adb.DeviceNotFoundError, adb.get_device) - - @mock.patch('adb.device.get_devices') - def test_unique_device(self, mock_get_devices): - mock_get_devices.return_value = ['foo'] - device = adb.get_device() - self.assertEqual(device.serial, 'foo') - - @mock.patch('adb.device.get_devices') - def test_no_unique_device(self, mock_get_devices): - mock_get_devices.return_value = ['foo', 'bar'] - self.assertRaises(adb.NoUniqueDeviceError, adb.get_device) - - class DeviceTest(unittest.TestCase): def setUp(self): self.device = adb.get_device() diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 45e768dbc..8d0c98bb0 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -16,6 +16,7 @@ #include <err.h> #include <fcntl.h> +#include <stdlib.h> #include <sys/capability.h> #include <sys/prctl.h> #include <sys/ptrace.h> @@ -298,6 +299,26 @@ TEST_F(CrasherTest, smoke) { ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)"); } +TEST_F(CrasherTest, LD_PRELOAD) { + int intercept_result; + unique_fd output_fd; + StartProcess([]() { + setenv("LD_PRELOAD", "nonexistent.so", 1); + *reinterpret_cast<volatile char*>(0xdead) = '1'; + }); + + StartIntercept(&output_fd); + FinishCrasher(); + AssertDeath(SIGSEGV); + FinishIntercept(&intercept_result); + + ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; + + std::string result; + ConsumeFd(std::move(output_fd), &result); + ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)"); +} + TEST_F(CrasherTest, abort) { int intercept_result; unique_fd output_fd; diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp index d41dc67be..d6b6d58d8 100644 --- a/debuggerd/handler/debuggerd_handler.cpp +++ b/debuggerd/handler/debuggerd_handler.cpp @@ -330,8 +330,8 @@ static int debuggerd_dispatch_pseudothread(void* arg) { async_safe_format_buffer(debuggerd_dump_type, sizeof(debuggerd_dump_type), "%d", get_dump_type(thread_info)); - execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, main_tid, pseudothread_tid, debuggerd_dump_type, - nullptr); + execle(CRASH_DUMP_PATH, CRASH_DUMP_NAME, main_tid, pseudothread_tid, debuggerd_dump_type, + nullptr, nullptr); fatal_errno("exec failed"); } else { diff --git a/fastboot/Android.mk b/fastboot/Android.mk index dd8bad9aa..bc8800296 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -58,7 +58,6 @@ LOCAL_C_INCLUDES_windows := development/host/windows/usb/api LOCAL_STATIC_LIBRARIES := \ libziparchive \ - libext4_utils \ libsparse \ libutils \ liblog \ diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index c3b1bfb2e..40c18e002 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -1354,7 +1354,7 @@ static std::string fb_fix_numeric_var(std::string var) { static unsigned fb_get_flash_block_size(Transport* transport, std::string name) { std::string sizeString; - if (!fb_getvar(transport, name.c_str(), &sizeString)) { + if (!fb_getvar(transport, name.c_str(), &sizeString) || sizeString.empty()) { /* This device does not report flash block sizes, so return 0 */ return 0; } @@ -1365,9 +1365,8 @@ static unsigned fb_get_flash_block_size(Transport* transport, std::string name) fprintf(stderr, "Couldn't parse %s '%s'.\n", name.c_str(), sizeString.c_str()); return 0; } - if (size < 4096 || (size & (size - 1)) != 0) { - fprintf(stderr, "Invalid %s %u: must be a power of 2 and at least 4096.\n", - name.c_str(), size); + if ((size & (size - 1)) != 0) { + fprintf(stderr, "Invalid %s %u: must be a power of 2.\n", name.c_str(), size); return 0; } return size; diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp index 709f061bd..2d77dd6eb 100644 --- a/fastboot/fs.cpp +++ b/fastboot/fs.cpp @@ -23,7 +23,6 @@ #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> -#include <ext4_utils/make_ext4fs.h> #include <sparse/sparse.h> using android::base::StringPrintf; @@ -120,6 +119,8 @@ static int generate_ext4_image(const char* fileName, long long partSize, int raid_stripe_width = eraseBlkSize / block_size; // stride should be the max of 8kb and logical block size if (logicalBlkSize != 0 && logicalBlkSize < 8192) raid_stride = 8192 / block_size; + // stripe width should be >= stride + if (raid_stripe_width < raid_stride) raid_stripe_width = raid_stride; ext_attr += StringPrintf(",stride=%d,stripe-width=%d", raid_stride, raid_stripe_width); } mke2fs_args.push_back("-E"); diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index d17c211d0..3a3883902 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp @@ -44,13 +44,13 @@ #include "UnwindStackMap.h" bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, - std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) { - std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"}; + std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, + std::vector<std::string>* skip_names) { UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map); auto process_memory = stack_map->process_memory(); unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(), regs, stack_map->process_memory()); - unwinder.Unwind(&skip_names, &stack_map->GetSuffixesToIgnore()); + unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore()); if (num_ignore_frames >= unwinder.NumFrames()) { frames->resize(0); @@ -104,7 +104,8 @@ bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* } error_ = BACKTRACE_UNWIND_NO_ERROR; - return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames); + std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"}; + return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names); } UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map) @@ -124,5 +125,5 @@ bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) { } error_ = BACKTRACE_UNWIND_NO_ERROR; - return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames); + return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr); } diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h index 73a58b5ee..e07353346 100644 --- a/libbacktrace/include/backtrace/Backtrace.h +++ b/libbacktrace/include/backtrace/Backtrace.h @@ -109,7 +109,8 @@ public: virtual bool Unwind(size_t num_ignore_frames, ucontext_t* context = NULL) = 0; static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, - std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames); + std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, + std::vector<std::string>* skip_names); // Get the function name and offset into the function given the pc. // If the string is empty, then no valid function name was found, diff --git a/libcutils/Android.bp b/libcutils/Android.bp index cfe8d2931..faaad0c20 100644 --- a/libcutils/Android.bp +++ b/libcutils/Android.bp @@ -112,25 +112,34 @@ cc_library { "properties.cpp", "qtaguid.c", "trace-dev.c", - "uevent.c", + "uevent.cpp", ], - sanitize: { - misc_undefined: ["integer"], - }, }, android_arm: { srcs: ["arch-arm/memset32.S"], + sanitize: { + misc_undefined: ["integer"], + }, }, android_arm64: { srcs: ["arch-arm64/android_memset.S"], + sanitize: { + misc_undefined: ["integer"], + }, }, android_mips: { srcs: ["arch-mips/android_memset.c"], + sanitize: { + misc_undefined: ["integer"], + }, }, android_mips64: { srcs: ["arch-mips/android_memset.c"], + sanitize: { + misc_undefined: ["integer"], + }, }, android_x86: { @@ -138,6 +147,12 @@ cc_library { "arch-x86/android_memset16.S", "arch-x86/android_memset32.S", ], + // TODO: This is to work around b/29412086. + // Remove once __mulodi4 is available and move the "sanitize" block + // to the android target. + sanitize: { + misc_undefined: [], + }, }, android_x86_64: { @@ -145,6 +160,9 @@ cc_library { "arch-x86_64/android_memset16.S", "arch-x86_64/android_memset32.S", ], + sanitize: { + misc_undefined: ["integer"], + }, }, }, 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 @@ #define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ #define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */ +/* + * This is a magic number in the kernel and not something that was picked + * arbitrarily. This value is returned whenever a uid that has no mapping in the + * user namespace is returned to userspace: + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/highuid.h?h=v4.4#n40 + */ +#define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */ + #define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ #define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ 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 @@ #include <cutils/uevent.h> #include <errno.h> -#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> #include <string.h> #include <strings.h> #include <sys/socket.h> @@ -26,11 +27,60 @@ #include <linux/netlink.h> +#include <fstream> + +#include <private/android_filesystem_config.h> + +namespace { + +// Returns the uid of root in the current user namespace. +// Returns AID_OVERFLOWUID if the root user is not mapped in the current +// namespace. +// Returns 0 if the kernel is not user namespace-aware (for backwards +// compatibility) or if AID_OVERFLOWUID could not be validated to match what the +// kernel would return. +uid_t GetRootUid() { + constexpr uid_t kParentRootUid = 0; + + std::ifstream uid_map_file("/proc/self/uid_map"); + if (!uid_map_file) { + // The kernel does not support user namespaces. + return kParentRootUid; + } + + uid_t current_namespace_uid, parent_namespace_uid; + uint32_t length; + while (uid_map_file >> current_namespace_uid >> parent_namespace_uid >> length) { + // Since kParentRootUid is 0, it should be the first entry in the mapped + // range. + if (parent_namespace_uid != kParentRootUid || length < 1) continue; + return current_namespace_uid; + } + + // Sanity check: verify that the overflow UID is the one to be returned by + // the kernel. + std::ifstream overflowuid_file("/proc/sys/kernel/overflowuid"); + if (!overflowuid_file) { + // It's better to return 0 in case we cannot make sure that the overflow + // UID matches. + return kParentRootUid; + } + uid_t kernel_overflow_uid; + if (!(overflowuid_file >> kernel_overflow_uid) || kernel_overflow_uid != AID_OVERFLOWUID) + return kParentRootUid; + + // root is unmapped, use the kernel "overflow" uid. + return AID_OVERFLOWUID; +} + +} // namespace + +extern "C" { + /** * Like recv(), but checks that messages actually originate from the kernel. */ -ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) -{ +ssize_t uevent_kernel_multicast_recv(int socket, void* buffer, size_t length) { uid_t uid = -1; return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid); } @@ -44,25 +94,19 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) * returns -1, sets errno to EIO, and sets "user" to the UID associated with the * message. If the peer UID cannot be determined, "user" is set to -1." */ -ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid) -{ +ssize_t uevent_kernel_multicast_uid_recv(int socket, void* buffer, size_t length, uid_t* uid) { return uevent_kernel_recv(socket, buffer, length, true, uid); } -ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require_group, uid_t *uid) -{ - struct iovec iov = { buffer, length }; +ssize_t uevent_kernel_recv(int socket, void* buffer, size_t length, bool require_group, uid_t* uid) { + static const uid_t root_uid = GetRootUid(); + struct iovec iov = {buffer, length}; struct sockaddr_nl addr; char control[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr hdr = { - &addr, - sizeof(addr), - &iov, - 1, - control, - sizeof(control), - 0, + &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0, }; + struct ucred* cred; *uid = -1; 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 return n; } - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); + struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { /* ignoring netlink message with no sender credentials */ goto out; } - struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg); + cred = (struct ucred*)CMSG_DATA(cmsg); *uid = cred->uid; - if (cred->uid != 0) { + if (cred->uid != root_uid) { /* ignoring netlink message from non-root user */ goto out; } @@ -101,8 +145,7 @@ out: return -1; } -int uevent_open_socket(int buf_sz, bool passcred) -{ +int uevent_open_socket(int buf_sz, bool passcred) { struct sockaddr_nl addr; int on = passcred; int s; @@ -113,8 +156,7 @@ int uevent_open_socket(int buf_sz, bool passcred) addr.nl_groups = 0xffffffff; s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT); - if(s < 0) - return -1; + if (s < 0) return -1; /* buf_sz should be less than net.core.rmem_max for this to succeed */ 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) setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { close(s); return -1; } return s; } + +} // extern "C" diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk index 55891db99..c7306cd5e 100644 --- a/libpixelflinger/Android.mk +++ b/libpixelflinger/Android.mk @@ -25,6 +25,8 @@ PIXELFLINGER_SRC_FILES:= \ buffer.cpp PIXELFLINGER_CFLAGS := -fstrict-aliasing -fomit-frame-pointer +PIXELFLINGER_CFLAGS += -Wall -Werror +PIXELFLINGER_CFLAGS += -Wno-unused-function PIXELFLINGER_SRC_FILES_arm := \ codeflinger/ARMAssembler.cpp \ diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp index bff87bbac..aebc129bf 100644 --- a/libpixelflinger/codeflinger/Arm64Assembler.cpp +++ b/libpixelflinger/codeflinger/Arm64Assembler.cpp @@ -151,11 +151,11 @@ namespace android { -static const char* shift_codes[] = +static __unused const char* shift_codes[] = { "LSL", "LSR", "ASR", "ROR" }; -static const char *cc_codes[] = +static __unused const char *cc_codes[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", @@ -984,7 +984,7 @@ uint32_t ArmToArm64Assembler::reg_post(int /*Rm*/) // A64 instructions // ---------------------------------------------------------------------------- -static const char * dataTransferOpName[] = +static __unused const char * dataTransferOpName[] = { "LDR","LDRB","LDRH","STR","STRB","STRH" }; diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp index 91fbd53cf..04e285d1b 100644 --- a/libpixelflinger/codeflinger/GGLAssembler.cpp +++ b/libpixelflinger/codeflinger/GGLAssembler.cpp @@ -94,8 +94,6 @@ int GGLAssembler::scanline(const needs_t& needs, context_t const* c) int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c) { - int64_t duration = ggl_system_time(); - mBlendFactorCached = 0; mBlending = 0; mMasking = 0; @@ -353,7 +351,6 @@ void GGLAssembler::build_scanline_prolog( fragment_parts_t& parts, const needs_t& needs) { Scratch scratches(registerFile()); - int Rctx = mBuilderContext.Rctx; // compute count comment("compute ct (# of pixels to process)"); diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.cpp b/libpixelflinger/codeflinger/MIPS64Assembler.cpp index d5e4cea89..d6d215679 100644 --- a/libpixelflinger/codeflinger/MIPS64Assembler.cpp +++ b/libpixelflinger/codeflinger/MIPS64Assembler.cpp @@ -39,6 +39,7 @@ #include "mips64_disassem.h" #define NOT_IMPLEMENTED() LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__) +#define __unused __attribute__((__unused__)) // ---------------------------------------------------------------------------- @@ -146,7 +147,7 @@ void ArmToMips64Assembler::prolog() mMips->MOVE(R_v0, R_a0); // move context * passed in a0 to v0 (arm r0) } -void ArmToMips64Assembler::epilog(uint32_t touched) +void ArmToMips64Assembler::epilog(uint32_t touched __unused) { mArmPC[mInum++] = pc(); // save starting PC for this instr @@ -205,7 +206,7 @@ int ArmToMips64Assembler::buildImmediate( // shifters... -bool ArmToMips64Assembler::isValidImmediate(uint32_t immediate) +bool ArmToMips64Assembler::isValidImmediate(uint32_t immediate __unused) { // for MIPS, any 32-bit immediate is OK return true; @@ -225,13 +226,14 @@ uint32_t ArmToMips64Assembler::reg_imm(int Rm, int type, uint32_t shift) return AMODE_REG_IMM; } -uint32_t ArmToMips64Assembler::reg_rrx(int Rm) +uint32_t ArmToMips64Assembler::reg_rrx(int Rm __unused) { // reg_rrx mode is not used in the GLLAssember code at this time return AMODE_UNSUPPORTED; } -uint32_t ArmToMips64Assembler::reg_reg(int Rm, int type, int Rs) +uint32_t ArmToMips64Assembler::reg_reg(int Rm __unused, int type __unused, + int Rs __unused) { // reg_reg mode is not used in the GLLAssember code at this time return AMODE_UNSUPPORTED; @@ -272,14 +274,15 @@ uint32_t ArmToMips64Assembler::reg_scale_pre(int Rm, int type, return AMODE_REG_SCALE_PRE; } -uint32_t ArmToMips64Assembler::reg_scale_post(int Rm, int type, uint32_t shift) +uint32_t ArmToMips64Assembler::reg_scale_post(int Rm __unused, int type __unused, + uint32_t shift __unused) { LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n"); return AMODE_UNSUPPORTED; } // LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0) -uint32_t ArmToMips64Assembler::immed8_pre(int32_t immed8, int W) +uint32_t ArmToMips64Assembler::immed8_pre(int32_t immed8, int W __unused) { LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n"); @@ -305,7 +308,7 @@ uint32_t ArmToMips64Assembler::reg_pre(int Rm, int W) return AMODE_REG_PRE; } -uint32_t ArmToMips64Assembler::reg_post(int Rm) +uint32_t ArmToMips64Assembler::reg_post(int Rm __unused) { LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n"); return AMODE_UNSUPPORTED; @@ -320,12 +323,6 @@ uint32_t ArmToMips64Assembler::reg_post(int Rm) #pragma mark Data Processing... #endif - -static const char * const dpOpNames[] = { - "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC", - "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN" -}; - // check if the operand registers from a previous CMP or S-bit instruction // would be overwritten by this instruction. If so, move the value to a // safe register. @@ -594,7 +591,7 @@ void ArmToMips64Assembler::dataProcessing(int opcode, int cc, #endif // multiply, accumulate -void ArmToMips64Assembler::MLA(int cc, int s, +void ArmToMips64Assembler::MLA(int cc __unused, int s, int Rd, int Rm, int Rs, int Rn) { //ALOGW("MLA"); @@ -608,7 +605,7 @@ void ArmToMips64Assembler::MLA(int cc, int s, } } -void ArmToMips64Assembler::MUL(int cc, int s, +void ArmToMips64Assembler::MUL(int cc __unused, int s, int Rd, int Rm, int Rs) { mArmPC[mInum++] = pc(); mMips->MUL(Rd, Rm, Rs); @@ -618,7 +615,7 @@ void ArmToMips64Assembler::MUL(int cc, int s, } } -void ArmToMips64Assembler::UMULL(int cc, int s, +void ArmToMips64Assembler::UMULL(int cc __unused, int s, int RdLo, int RdHi, int Rm, int Rs) { mArmPC[mInum++] = pc(); mMips->MUH(RdHi, Rm, Rs); @@ -631,8 +628,8 @@ void ArmToMips64Assembler::UMULL(int cc, int s, } } -void ArmToMips64Assembler::UMUAL(int cc, int s, - int RdLo, int RdHi, int Rm, int Rs) { +void ArmToMips64Assembler::UMUAL(int cc __unused, int s, + int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi, "UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs); // *mPC++ = (cc<<28) | (1<<23) | (1<<21) | (s<<20) | @@ -647,8 +644,8 @@ void ArmToMips64Assembler::UMUAL(int cc, int s, } } -void ArmToMips64Assembler::SMULL(int cc, int s, - int RdLo, int RdHi, int Rm, int Rs) { +void ArmToMips64Assembler::SMULL(int cc __unused, int s, + int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi, "SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs); // *mPC++ = (cc<<28) | (1<<23) | (1<<22) | (s<<20) | @@ -662,8 +659,8 @@ void ArmToMips64Assembler::SMULL(int cc, int s, LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n"); } } -void ArmToMips64Assembler::SMUAL(int cc, int s, - int RdLo, int RdHi, int Rm, int Rs) { +void ArmToMips64Assembler::SMUAL(int cc __unused, int s, + int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi, "SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs); // *mPC++ = (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (s<<20) | @@ -717,26 +714,26 @@ void ArmToMips64Assembler::B(int cc, const char* label) } } -void ArmToMips64Assembler::BL(int cc, const char* label) +void ArmToMips64Assembler::BL(int cc __unused, const char* label __unused) { LOG_ALWAYS_FATAL("branch-and-link not supported yet\n"); mArmPC[mInum++] = pc(); } // no use for Branches with integer PC, but they're in the Interface class .... -void ArmToMips64Assembler::B(int cc, uint32_t* to_pc) +void ArmToMips64Assembler::B(int cc __unused, uint32_t* to_pc __unused) { LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); mArmPC[mInum++] = pc(); } -void ArmToMips64Assembler::BL(int cc, uint32_t* to_pc) +void ArmToMips64Assembler::BL(int cc __unused, uint32_t* to_pc __unused) { LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); mArmPC[mInum++] = pc(); } -void ArmToMips64Assembler::BX(int cc, int Rn) +void ArmToMips64Assembler::BX(int cc __unused, int Rn __unused) { LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); mArmPC[mInum++] = pc(); @@ -750,7 +747,7 @@ void ArmToMips64Assembler::BX(int cc, int Rn) #endif // data transfer... -void ArmToMips64Assembler::LDR(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::LDR(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -784,7 +781,7 @@ void ArmToMips64Assembler::LDR(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMips64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::LDRB(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -813,7 +810,7 @@ void ArmToMips64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t offset) } -void ArmToMips64Assembler::STR(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::STR(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -849,7 +846,7 @@ void ArmToMips64Assembler::STR(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMips64Assembler::STRB(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::STRB(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -877,7 +874,7 @@ void ArmToMips64Assembler::STRB(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMips64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::LDRH(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed8_pre(0) @@ -905,21 +902,23 @@ void ArmToMips64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMips64Assembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::LDRSB(int cc __unused, int Rd __unused, + int Rn __unused, uint32_t offset __unused) { mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::LDRSH(int cc __unused, int Rd __unused, + int Rn __unused, uint32_t offset __unused) { mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::STRH(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMips64Assembler::STRH(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed8_pre(0) @@ -955,8 +954,8 @@ void ArmToMips64Assembler::STRH(int cc, int Rd, int Rn, uint32_t offset) #endif // block data transfer... -void ArmToMips64Assembler::LDM(int cc, int dir, - int Rn, int W, uint32_t reg_list) +void ArmToMips64Assembler::LDM(int cc __unused, int dir __unused, + int Rn __unused, int W __unused, uint32_t reg_list __unused) { // ED FD EA FA IB IA DB DA // const uint8_t P[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; // const uint8_t U[8] = { 1, 1, 0, 0, 1, 1, 0, 0 }; @@ -967,8 +966,8 @@ void ArmToMips64Assembler::LDM(int cc, int dir, NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::STM(int cc, int dir, - int Rn, int W, uint32_t reg_list) +void ArmToMips64Assembler::STM(int cc __unused, int dir __unused, + int Rn __unused, int W __unused, uint32_t reg_list __unused) { // FA EA FD ED IB IA DB DA // const uint8_t P[8] = { 0, 1, 0, 1, 1, 0, 1, 0 }; // const uint8_t U[8] = { 0, 0, 1, 1, 1, 1, 0, 0 }; @@ -987,21 +986,23 @@ void ArmToMips64Assembler::STM(int cc, int dir, #endif // special... -void ArmToMips64Assembler::SWP(int cc, int Rn, int Rd, int Rm) { +void ArmToMips64Assembler::SWP(int cc __unused, int Rn __unused, + int Rd __unused, int Rm __unused) { // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::SWPB(int cc, int Rn, int Rd, int Rm) { +void ArmToMips64Assembler::SWPB(int cc __unused, int Rn __unused, + int Rd __unused, int Rm __unused) { // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::SWI(int cc, uint32_t comment) { +void ArmToMips64Assembler::SWI(int cc __unused, uint32_t comment __unused) { // *mPC++ = (cc<<28) | (0xF<<24) | comment; mArmPC[mInum++] = pc(); mMips->NOP2(); @@ -1015,7 +1016,7 @@ void ArmToMips64Assembler::SWI(int cc, uint32_t comment) { #endif // DSP instructions... -void ArmToMips64Assembler::PLD(int Rn, uint32_t offset) { +void ArmToMips64Assembler::PLD(int Rn __unused, uint32_t offset) { LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))), "PLD only P=1, W=0"); // *mPC++ = 0xF550F000 | (Rn<<16) | offset; @@ -1024,13 +1025,14 @@ void ArmToMips64Assembler::PLD(int Rn, uint32_t offset) { NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::CLZ(int cc, int Rd, int Rm) +void ArmToMips64Assembler::CLZ(int cc __unused, int Rd, int Rm) { mArmPC[mInum++] = pc(); mMips->CLZ(Rd, Rm); } -void ArmToMips64Assembler::QADD(int cc, int Rd, int Rm, int Rn) +void ArmToMips64Assembler::QADD(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1038,7 +1040,8 @@ void ArmToMips64Assembler::QADD(int cc, int Rd, int Rm, int Rn) NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::QDADD(int cc, int Rd, int Rm, int Rn) +void ArmToMips64Assembler::QDADD(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1046,7 +1049,8 @@ void ArmToMips64Assembler::QDADD(int cc, int Rd, int Rm, int Rn) NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::QSUB(int cc, int Rd, int Rm, int Rn) +void ArmToMips64Assembler::QSUB(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1054,7 +1058,8 @@ void ArmToMips64Assembler::QSUB(int cc, int Rd, int Rm, int Rn) NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::QDSUB(int cc, int Rd, int Rm, int Rn) +void ArmToMips64Assembler::QDSUB(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1063,7 +1068,7 @@ void ArmToMips64Assembler::QDSUB(int cc, int Rd, int Rm, int Rn) } // 16 x 16 signed multiply (like SMLAxx without the accumulate) -void ArmToMips64Assembler::SMUL(int cc, int xy, +void ArmToMips64Assembler::SMUL(int cc __unused, int xy, int Rd, int Rm, int Rs) { mArmPC[mInum++] = pc(); @@ -1092,7 +1097,7 @@ void ArmToMips64Assembler::SMUL(int cc, int xy, } // signed 32b x 16b multiple, save top 32-bits of 48-bit result -void ArmToMips64Assembler::SMULW(int cc, int y, +void ArmToMips64Assembler::SMULW(int cc __unused, int y, int Rd, int Rm, int Rs) { mArmPC[mInum++] = pc(); @@ -1111,7 +1116,7 @@ void ArmToMips64Assembler::SMULW(int cc, int y, } // 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn -void ArmToMips64Assembler::SMLA(int cc, int xy, +void ArmToMips64Assembler::SMLA(int cc __unused, int xy, int Rd, int Rm, int Rs, int Rn) { mArmPC[mInum++] = pc(); @@ -1141,8 +1146,9 @@ void ArmToMips64Assembler::SMLA(int cc, int xy, mMips->ADDU(Rd, R_at, Rn); } -void ArmToMips64Assembler::SMLAL(int cc, int xy, - int RdHi, int RdLo, int Rs, int Rm) +void ArmToMips64Assembler::SMLAL(int cc __unused, int xy __unused, + int RdHi __unused, int RdLo __unused, + int Rs __unused, int Rm __unused) { // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm; mArmPC[mInum++] = pc(); @@ -1150,8 +1156,9 @@ void ArmToMips64Assembler::SMLAL(int cc, int xy, NOT_IMPLEMENTED(); } -void ArmToMips64Assembler::SMLAW(int cc, int y, - int Rd, int Rm, int Rs, int Rn) +void ArmToMips64Assembler::SMLAW(int cc __unused, int y __unused, + int Rd __unused, int Rm __unused, + int Rs __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm; mArmPC[mInum++] = pc(); @@ -1160,7 +1167,7 @@ void ArmToMips64Assembler::SMLAW(int cc, int y, } // used by ARMv6 version of GGLAssembler::filter32 -void ArmToMips64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate) +void ArmToMips64Assembler::UXTB16(int cc __unused, int Rd, int Rm, int rotate) { mArmPC[mInum++] = pc(); @@ -1173,7 +1180,8 @@ void ArmToMips64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate) mMips->AND(Rd, R_at2, R_at); } -void ArmToMips64Assembler::UBFX(int cc, int Rd, int Rn, int lsb, int width) +void ArmToMips64Assembler::UBFX(int cc __unused, int Rd __unused, int Rn __unused, + int lsb __unused, int width __unused) { /* Placeholder for UBFX */ mArmPC[mInum++] = pc(); @@ -1202,7 +1210,8 @@ void ArmToMips64Assembler::ADDR_SUB(int cc, dataProcessing(opSUB64, cc, s, Rd, Rn, Op2); } -void ArmToMips64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset) { +void ArmToMips64Assembler::ADDR_LDR(int cc __unused, int Rd, + int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) if (offset > AMODE_UNSUPPORTED) offset = 0; @@ -1235,7 +1244,8 @@ void ArmToMips64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset) { } } -void ArmToMips64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t offset) { +void ArmToMips64Assembler::ADDR_STR(int cc __unused, int Rd, + int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) if (offset > AMODE_UNSUPPORTED) offset = 0; @@ -1290,14 +1300,12 @@ void ArmToMips64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t offset) { */ MIPS64Assembler::MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent) - : mParent(parent), - MIPSAssembler::MIPSAssembler(assembly, NULL) + : MIPSAssembler::MIPSAssembler(assembly, NULL), mParent(parent) { } MIPS64Assembler::MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent) - : mParent(parent), - MIPSAssembler::MIPSAssembler(assembly) + : MIPSAssembler::MIPSAssembler(assembly), mParent(parent) { } @@ -1319,7 +1327,7 @@ void MIPS64Assembler::reset() } -void MIPS64Assembler::disassemble(const char* name) +void MIPS64Assembler::disassemble(const char* name __unused) { char di_buf[140]; @@ -1334,11 +1342,6 @@ void MIPS64Assembler::disassemble(const char* name) } } - // iArm is an index to Arm instructions 1...n for this assembly sequence - // mArmPC[iArm] holds the value of the Mips-PC for the first MIPS - // instruction corresponding to that Arm instruction number - - int iArm = 0; size_t count = pc()-base(); uint32_t* mipsPC = base(); diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp index 865a5683c..039a72504 100644 --- a/libpixelflinger/codeflinger/MIPSAssembler.cpp +++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp @@ -51,6 +51,7 @@ #include <stdio.h> #include <stdlib.h> +#include <inttypes.h> #include <cutils/properties.h> #include <log/log.h> @@ -60,6 +61,8 @@ #include "MIPSAssembler.h" #include "mips_disassem.h" +#define __unused __attribute__((__unused__)) + // Choose MIPS arch variant following gcc flags #if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 #define mips32r2 1 @@ -167,7 +170,7 @@ void ArmToMipsAssembler::prolog() mMips->MOVE(R_v0, R_a0); // move context * passed in a0 to v0 (arm r0) } -void ArmToMipsAssembler::epilog(uint32_t touched) +void ArmToMipsAssembler::epilog(uint32_t touched __unused) { mArmPC[mInum++] = pc(); // save starting PC for this instr @@ -213,7 +216,7 @@ int ArmToMipsAssembler::buildImmediate( // shifters... -bool ArmToMipsAssembler::isValidImmediate(uint32_t immediate) +bool ArmToMipsAssembler::isValidImmediate(uint32_t immediate __unused) { // for MIPS, any 32-bit immediate is OK return true; @@ -234,13 +237,14 @@ uint32_t ArmToMipsAssembler::reg_imm(int Rm, int type, uint32_t shift) return AMODE_REG_IMM; } -uint32_t ArmToMipsAssembler::reg_rrx(int Rm) +uint32_t ArmToMipsAssembler::reg_rrx(int Rm __unused) { // reg_rrx mode is not used in the GLLAssember code at this time return AMODE_UNSUPPORTED; } -uint32_t ArmToMipsAssembler::reg_reg(int Rm, int type, int Rs) +uint32_t ArmToMipsAssembler::reg_reg(int Rm __unused, int type __unused, + int Rs __unused) { // reg_reg mode is not used in the GLLAssember code at this time return AMODE_UNSUPPORTED; @@ -281,14 +285,15 @@ uint32_t ArmToMipsAssembler::reg_scale_pre(int Rm, int type, return AMODE_REG_SCALE_PRE; } -uint32_t ArmToMipsAssembler::reg_scale_post(int Rm, int type, uint32_t shift) +uint32_t ArmToMipsAssembler::reg_scale_post(int Rm __unused, int type __unused, + uint32_t shift __unused) { LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n"); return AMODE_UNSUPPORTED; } // LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0) -uint32_t ArmToMipsAssembler::immed8_pre(int32_t immed8, int W) +uint32_t ArmToMipsAssembler::immed8_pre(int32_t immed8, int W __unused) { // uint32_t offset = abs(immed8); @@ -318,7 +323,7 @@ uint32_t ArmToMipsAssembler::reg_pre(int Rm, int W) return AMODE_REG_PRE; } -uint32_t ArmToMipsAssembler::reg_post(int Rm) +uint32_t ArmToMipsAssembler::reg_post(int Rm __unused) { LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n"); return AMODE_UNSUPPORTED; @@ -333,12 +338,6 @@ uint32_t ArmToMipsAssembler::reg_post(int Rm) #pragma mark Data Processing... #endif - -static const char * const dpOpNames[] = { - "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC", - "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN" -}; - // check if the operand registers from a previous CMP or S-bit instruction // would be overwritten by this instruction. If so, move the value to a // safe register. @@ -605,7 +604,7 @@ void ArmToMipsAssembler::dataProcessing(int opcode, int cc, #endif // multiply, accumulate -void ArmToMipsAssembler::MLA(int cc, int s, +void ArmToMipsAssembler::MLA(int cc __unused, int s, int Rd, int Rm, int Rs, int Rn) { mArmPC[mInum++] = pc(); // save starting PC for this instr @@ -618,7 +617,7 @@ void ArmToMipsAssembler::MLA(int cc, int s, } } -void ArmToMipsAssembler::MUL(int cc, int s, +void ArmToMipsAssembler::MUL(int cc __unused, int s, int Rd, int Rm, int Rs) { mArmPC[mInum++] = pc(); mMips->MUL(Rd, Rm, Rs); @@ -628,7 +627,7 @@ void ArmToMipsAssembler::MUL(int cc, int s, } } -void ArmToMipsAssembler::UMULL(int cc, int s, +void ArmToMipsAssembler::UMULL(int cc __unused, int s, int RdLo, int RdHi, int Rm, int Rs) { mArmPC[mInum++] = pc(); mMips->MULT(Rm, Rs); @@ -641,8 +640,8 @@ void ArmToMipsAssembler::UMULL(int cc, int s, } } -void ArmToMipsAssembler::UMUAL(int cc, int s, - int RdLo, int RdHi, int Rm, int Rs) { +void ArmToMipsAssembler::UMUAL(int cc __unused, int s, + int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi, "UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs); // *mPC++ = (cc<<28) | (1<<23) | (1<<21) | (s<<20) | @@ -657,8 +656,8 @@ void ArmToMipsAssembler::UMUAL(int cc, int s, } } -void ArmToMipsAssembler::SMULL(int cc, int s, - int RdLo, int RdHi, int Rm, int Rs) { +void ArmToMipsAssembler::SMULL(int cc __unused, int s, + int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi, "SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs); // *mPC++ = (cc<<28) | (1<<23) | (1<<22) | (s<<20) | @@ -672,8 +671,8 @@ void ArmToMipsAssembler::SMULL(int cc, int s, LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n"); } } -void ArmToMipsAssembler::SMUAL(int cc, int s, - int RdLo, int RdHi, int Rm, int Rs) { +void ArmToMipsAssembler::SMUAL(int cc __unused, int s, + int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi, "SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs); // *mPC++ = (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (s<<20) | @@ -727,26 +726,26 @@ void ArmToMipsAssembler::B(int cc, const char* label) } } -void ArmToMipsAssembler::BL(int cc, const char* label) +void ArmToMipsAssembler::BL(int cc __unused, const char* label __unused) { LOG_ALWAYS_FATAL("branch-and-link not supported yet\n"); mArmPC[mInum++] = pc(); } // no use for Branches with integer PC, but they're in the Interface class .... -void ArmToMipsAssembler::B(int cc, uint32_t* to_pc) +void ArmToMipsAssembler::B(int cc __unused, uint32_t* to_pc __unused) { LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); mArmPC[mInum++] = pc(); } -void ArmToMipsAssembler::BL(int cc, uint32_t* to_pc) +void ArmToMipsAssembler::BL(int cc __unused, uint32_t* to_pc __unused) { LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); mArmPC[mInum++] = pc(); } -void ArmToMipsAssembler::BX(int cc, int Rn) +void ArmToMipsAssembler::BX(int cc __unused, int Rn __unused) { LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); mArmPC[mInum++] = pc(); @@ -760,7 +759,7 @@ void ArmToMipsAssembler::BX(int cc, int Rn) #endif // data transfer... -void ArmToMipsAssembler::LDR(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::LDR(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -794,7 +793,7 @@ void ArmToMipsAssembler::LDR(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMipsAssembler::LDRB(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::LDRB(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -823,7 +822,7 @@ void ArmToMipsAssembler::LDRB(int cc, int Rd, int Rn, uint32_t offset) } -void ArmToMipsAssembler::STR(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::STR(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -859,7 +858,7 @@ void ArmToMipsAssembler::STR(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMipsAssembler::STRB(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::STRB(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed12_pre(0) @@ -887,7 +886,7 @@ void ArmToMipsAssembler::STRB(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMipsAssembler::LDRH(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::LDRH(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed8_pre(0) @@ -915,21 +914,23 @@ void ArmToMipsAssembler::LDRH(int cc, int Rd, int Rn, uint32_t offset) } } -void ArmToMipsAssembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::LDRSB(int cc __unused, int Rd __unused, + int Rn __unused, uint32_t offset __unused) { mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::LDRSH(int cc __unused, int Rd __unused, + int Rn __unused, uint32_t offset __unused) { mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::STRH(int cc, int Rd, int Rn, uint32_t offset) +void ArmToMipsAssembler::STRH(int cc __unused, int Rd, int Rn, uint32_t offset) { mArmPC[mInum++] = pc(); // work-around for ARM default address mode of immed8_pre(0) @@ -965,8 +966,8 @@ void ArmToMipsAssembler::STRH(int cc, int Rd, int Rn, uint32_t offset) #endif // block data transfer... -void ArmToMipsAssembler::LDM(int cc, int dir, - int Rn, int W, uint32_t reg_list) +void ArmToMipsAssembler::LDM(int cc __unused, int dir __unused, + int Rn __unused, int W __unused, uint32_t reg_list __unused) { // ED FD EA FA IB IA DB DA // const uint8_t P[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; // const uint8_t U[8] = { 1, 1, 0, 0, 1, 1, 0, 0 }; @@ -977,8 +978,8 @@ void ArmToMipsAssembler::LDM(int cc, int dir, NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::STM(int cc, int dir, - int Rn, int W, uint32_t reg_list) +void ArmToMipsAssembler::STM(int cc __unused, int dir __unused, + int Rn __unused, int W __unused, uint32_t reg_list __unused) { // FA EA FD ED IB IA DB DA // const uint8_t P[8] = { 0, 1, 0, 1, 1, 0, 1, 0 }; // const uint8_t U[8] = { 0, 0, 1, 1, 1, 1, 0, 0 }; @@ -997,21 +998,23 @@ void ArmToMipsAssembler::STM(int cc, int dir, #endif // special... -void ArmToMipsAssembler::SWP(int cc, int Rn, int Rd, int Rm) { +void ArmToMipsAssembler::SWP(int cc __unused, int Rn __unused, + int Rd __unused, int Rm __unused) { // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::SWPB(int cc, int Rn, int Rd, int Rm) { +void ArmToMipsAssembler::SWPB(int cc __unused, int Rn __unused, + int Rd __unused, int Rm __unused) { // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; mArmPC[mInum++] = pc(); mMips->NOP2(); NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::SWI(int cc, uint32_t comment) { +void ArmToMipsAssembler::SWI(int cc __unused, uint32_t comment __unused) { // *mPC++ = (cc<<28) | (0xF<<24) | comment; mArmPC[mInum++] = pc(); mMips->NOP2(); @@ -1025,7 +1028,7 @@ void ArmToMipsAssembler::SWI(int cc, uint32_t comment) { #endif // DSP instructions... -void ArmToMipsAssembler::PLD(int Rn, uint32_t offset) { +void ArmToMipsAssembler::PLD(int Rn __unused, uint32_t offset) { LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))), "PLD only P=1, W=0"); // *mPC++ = 0xF550F000 | (Rn<<16) | offset; @@ -1034,13 +1037,14 @@ void ArmToMipsAssembler::PLD(int Rn, uint32_t offset) { NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::CLZ(int cc, int Rd, int Rm) +void ArmToMipsAssembler::CLZ(int cc __unused, int Rd, int Rm) { mArmPC[mInum++] = pc(); mMips->CLZ(Rd, Rm); } -void ArmToMipsAssembler::QADD(int cc, int Rd, int Rm, int Rn) +void ArmToMipsAssembler::QADD(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1048,7 +1052,8 @@ void ArmToMipsAssembler::QADD(int cc, int Rd, int Rm, int Rn) NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::QDADD(int cc, int Rd, int Rm, int Rn) +void ArmToMipsAssembler::QDADD(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1056,7 +1061,8 @@ void ArmToMipsAssembler::QDADD(int cc, int Rd, int Rm, int Rn) NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::QSUB(int cc, int Rd, int Rm, int Rn) +void ArmToMipsAssembler::QSUB(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1064,7 +1070,8 @@ void ArmToMipsAssembler::QSUB(int cc, int Rd, int Rm, int Rn) NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::QDSUB(int cc, int Rd, int Rm, int Rn) +void ArmToMipsAssembler::QDSUB(int cc __unused, int Rd __unused, + int Rm __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm; mArmPC[mInum++] = pc(); @@ -1073,7 +1080,7 @@ void ArmToMipsAssembler::QDSUB(int cc, int Rd, int Rm, int Rn) } // 16 x 16 signed multiply (like SMLAxx without the accumulate) -void ArmToMipsAssembler::SMUL(int cc, int xy, +void ArmToMipsAssembler::SMUL(int cc __unused, int xy, int Rd, int Rm, int Rs) { mArmPC[mInum++] = pc(); @@ -1112,7 +1119,7 @@ void ArmToMipsAssembler::SMUL(int cc, int xy, } // signed 32b x 16b multiple, save top 32-bits of 48-bit result -void ArmToMipsAssembler::SMULW(int cc, int y, +void ArmToMipsAssembler::SMULW(int cc __unused, int y, int Rd, int Rm, int Rs) { mArmPC[mInum++] = pc(); @@ -1132,7 +1139,7 @@ void ArmToMipsAssembler::SMULW(int cc, int y, } // 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn -void ArmToMipsAssembler::SMLA(int cc, int xy, +void ArmToMipsAssembler::SMLA(int cc __unused, int xy, int Rd, int Rm, int Rs, int Rn) { mArmPC[mInum++] = pc(); @@ -1172,8 +1179,9 @@ void ArmToMipsAssembler::SMLA(int cc, int xy, mMips->ADDU(Rd, R_at, Rn); } -void ArmToMipsAssembler::SMLAL(int cc, int xy, - int RdHi, int RdLo, int Rs, int Rm) +void ArmToMipsAssembler::SMLAL(int cc __unused, int xy __unused, + int RdHi __unused, int RdLo __unused, + int Rs __unused, int Rm __unused) { // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm; mArmPC[mInum++] = pc(); @@ -1181,8 +1189,9 @@ void ArmToMipsAssembler::SMLAL(int cc, int xy, NOT_IMPLEMENTED(); } -void ArmToMipsAssembler::SMLAW(int cc, int y, - int Rd, int Rm, int Rs, int Rn) +void ArmToMipsAssembler::SMLAW(int cc __unused, int y __unused, + int Rd __unused, int Rm __unused, + int Rs __unused, int Rn __unused) { // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm; mArmPC[mInum++] = pc(); @@ -1191,7 +1200,7 @@ void ArmToMipsAssembler::SMLAW(int cc, int y, } // used by ARMv6 version of GGLAssembler::filter32 -void ArmToMipsAssembler::UXTB16(int cc, int Rd, int Rm, int rotate) +void ArmToMipsAssembler::UXTB16(int cc __unused, int Rd, int Rm, int rotate) { mArmPC[mInum++] = pc(); @@ -1202,7 +1211,9 @@ void ArmToMipsAssembler::UXTB16(int cc, int Rd, int Rm, int rotate) mMips->AND(Rd, Rm, 0x00FF00FF); } -void ArmToMipsAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width) +void ArmToMipsAssembler::UBFX(int cc __unused, int Rd __unused, + int Rn __unused, int lsb __unused, + int width __unused) { /* Placeholder for UBFX */ mArmPC[mInum++] = pc(); @@ -1339,11 +1350,6 @@ void MIPSAssembler::disassemble(const char* name) } } - // iArm is an index to Arm instructions 1...n for this assembly sequence - // mArmPC[iArm] holds the value of the Mips-PC for the first MIPS - // instruction corresponding to that Arm instruction number - - int iArm = 0; size_t count = pc()-base(); uint32_t* mipsPC = base(); while (count--) { @@ -1359,7 +1365,7 @@ void MIPSAssembler::disassemble(const char* name) ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt); string_detab(di_buf); string_pad(di_buf, 30); - ALOGW("%08x: %08x %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf); + ALOGW("0x%p: %08x %s", mipsPC, uint32_t(*mipsPC), di_buf); mipsPC++; } } @@ -1381,7 +1387,7 @@ void MIPSAssembler::prolog() // empty - done in ArmToMipsAssembler } -void MIPSAssembler::epilog(uint32_t touched) +void MIPSAssembler::epilog(uint32_t touched __unused) { // empty - done in ArmToMipsAssembler } @@ -1403,7 +1409,7 @@ int MIPSAssembler::generate(const char* name) // the instruction & data caches are flushed by CodeCache const int64_t duration = ggl_system_time() - mDuration; - const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n"; + const char * const format = "generated %s (%d ins) at [%p:%p] in %" PRId64 " ns\n"; ALOGI(format, name, int(pc()-base()), base(), pc(), duration); char value[PROPERTY_VALUE_MAX]; @@ -1864,7 +1870,7 @@ void MIPSAssembler::BEQZ(int Rs, const char* label) BEQ(Rs, R_zero, label); } -void MIPSAssembler::BNEZ(int Rs, const char* label) +void MIPSAssembler::BNEZ(int Rs __unused, const char* label) { BNE(R_at, R_zero, label); } diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp index da21e1d97..4db0a4948 100644 --- a/libpixelflinger/codeflinger/load_store.cpp +++ b/libpixelflinger/codeflinger/load_store.cpp @@ -232,7 +232,6 @@ void GGLAssembler::expand(integer_t& dst, const integer_t& src, int dbits) void GGLAssembler::downshift( pixel_t& d, int component, component_t s, const reg_t& dither) { - const needs_t& needs = mBuilderContext.needs; Scratch scratches(registerFile()); int sh = s.h; diff --git a/libpixelflinger/codeflinger/mips64_disassem.c b/libpixelflinger/codeflinger/mips64_disassem.c index 1856e5c0e..852829984 100644 --- a/libpixelflinger/codeflinger/mips64_disassem.c +++ b/libpixelflinger/codeflinger/mips64_disassem.c @@ -45,6 +45,8 @@ #include "mips_opcode.h" +#define __unused __attribute__((__unused__)) + static char *sprintf_buffer; static int sprintf_buf_len; @@ -114,7 +116,7 @@ static char * alt_arm_reg_name[32] = { // hacked names for comparison with ARM "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" }; -static char ** reg_name = &mips_reg_name[0]; +static char * const * reg_name = &mips_reg_name[0]; static const char * const c0_opname[64] = { "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07", @@ -147,7 +149,7 @@ db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format); * 'loc' may in fact contain a breakpoint instruction. */ static db_addr_t -db_disasm_insn(int insn, db_addr_t loc, bool altfmt) +db_disasm_insn(int insn, db_addr_t loc, bool altfmt __unused) { bool bdslot = false; InstFmt i; diff --git a/libpixelflinger/codeflinger/mips_disassem.c b/libpixelflinger/codeflinger/mips_disassem.c index 83a9740ed..1fe680675 100644 --- a/libpixelflinger/codeflinger/mips_disassem.c +++ b/libpixelflinger/codeflinger/mips_disassem.c @@ -57,6 +57,7 @@ // #include <ddb/db_extern.h> // #include <ddb/db_sym.h> +#define __unused __attribute__((__unused__)) static char *sprintf_buffer; static int sprintf_buf_len; @@ -183,7 +184,7 @@ db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format); * 'loc' may in fact contain a breakpoint instruction. */ static db_addr_t -db_disasm_insn(int insn, db_addr_t loc, bool altfmt) +db_disasm_insn(int insn, db_addr_t loc, bool altfmt __unused) { bool bdslot = false; InstFmt i; diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp index 4c357af83..e6997bd4b 100644 --- a/libpixelflinger/codeflinger/texturing.cpp +++ b/libpixelflinger/codeflinger/texturing.cpp @@ -41,7 +41,6 @@ namespace android { void GGLAssembler::init_iterated_color(fragment_parts_t& parts, const reg_t& x) { context_t const* c = mBuilderContext.c; - const needs_t& needs = mBuilderContext.needs; if (mSmooth) { // NOTE: we could take this case in the mDithering + !mSmooth case, @@ -324,9 +323,7 @@ void GGLAssembler::init_textures( tex_coord_t* coords, const reg_t& x, const reg_t& y) { - context_t const* c = mBuilderContext.c; const needs_t& needs = mBuilderContext.needs; - int Rctx = mBuilderContext.Rctx; int Rx = x.reg; int Ry = y.reg; @@ -402,10 +399,6 @@ void GGLAssembler::init_textures( void GGLAssembler::build_textures( fragment_parts_t& parts, Scratch& regs) { - context_t const* c = mBuilderContext.c; - const needs_t& needs = mBuilderContext.needs; - int Rctx = mBuilderContext.Rctx; - // We don't have a way to spill registers automatically // spill depth and AA regs, when we know we may have to. // build the spill list... @@ -434,7 +427,6 @@ void GGLAssembler::build_textures( fragment_parts_t& parts, Spill spill(registerFile(), *this, spill_list); - const bool multiTexture = mTextureMachine.activeUnits > 1; for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { const texture_unit_t& tmu = mTextureMachine.tmu[i]; if (tmu.format_idx == 0) @@ -442,7 +434,7 @@ void GGLAssembler::build_textures( fragment_parts_t& parts, pointer_t& txPtr = parts.coords[i].ptr; pixel_t& texel = parts.texel[i]; - + // repeat... if ((tmu.swrap == GGL_NEEDS_WRAP_11) && (tmu.twrap == GGL_NEEDS_WRAP_11)) @@ -656,7 +648,6 @@ void GGLAssembler::build_textures( fragment_parts_t& parts, void GGLAssembler::build_iterate_texture_coordinates( const fragment_parts_t& parts) { - const bool multiTexture = mTextureMachine.activeUnits > 1; for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { const texture_unit_t& tmu = mTextureMachine.tmu[i]; if (tmu.format_idx == 0) diff --git a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h index 17b85dd58..51e9e2695 100644 --- a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h +++ b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h @@ -497,7 +497,6 @@ inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) { GGLfixed result; - int rshift; asm("smull %x[result], %w[x], %w[y] \n" "lsr %x[result], %x[result], %x[shift] \n" diff --git a/libpixelflinger/raster.cpp b/libpixelflinger/raster.cpp index 26d8e4571..e95c2c8ab 100644 --- a/libpixelflinger/raster.cpp +++ b/libpixelflinger/raster.cpp @@ -153,7 +153,6 @@ GGLint gglBitBlit(GGLContext* con, int tmu, GGLint crop[4], GGLint where[4]) GGLint h = where[3]; // exclsively enable this tmu - const GGLSurface& cbSurface = c->state.buffers.color.s; c->procs.activeTexture(c, tmu); c->procs.disable(c, GGL_W_LERP); diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp index c6cf5bffe..4cc23c773 100644 --- a/libpixelflinger/scanline.cpp +++ b/libpixelflinger/scanline.cpp @@ -2144,7 +2144,6 @@ void scanline_t32cb16(context_t* c) const int32_t u = (c->state.texture[0].shade.is0>>16) + x; const int32_t v = (c->state.texture[0].shade.it0>>16) + y; uint32_t *src = reinterpret_cast<uint32_t*>(tex->data)+(u+(tex->stride*v)); - int sR, sG, sB; uint32_t s, d; if (ct==1 || uintptr_t(dst)&2) { diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.mk b/libpixelflinger/tests/arch-arm64/assembler/Android.mk index bd0f24b3e..db5dc4df9 100644 --- a/libpixelflinger/tests/arch-arm64/assembler/Android.mk +++ b/libpixelflinger/tests/arch-arm64/assembler/Android.mk @@ -14,6 +14,8 @@ LOCAL_C_INCLUDES := \ LOCAL_MODULE:= test-pixelflinger-arm64-assembler-test +LOCAL_CFLAGS := -Wall -Werror + LOCAL_MODULE_TAGS := tests LOCAL_MULTILIB := 64 diff --git a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk index 3368eb017..3096232b8 100644 --- a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk +++ b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk @@ -11,6 +11,8 @@ LOCAL_C_INCLUDES := LOCAL_MODULE:= test-pixelflinger-arm64-col32cb16blend +LOCAL_CFLAGS := -Wall -Werror + LOCAL_MODULE_TAGS := tests LOCAL_MULTILIB := 64 diff --git a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk index d8f7e699f..78f12af9d 100644 --- a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk +++ b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk @@ -9,6 +9,8 @@ LOCAL_SHARED_LIBRARIES := LOCAL_MODULE:= test-pixelflinger-arm64-disassembler-test +LOCAL_CFLAGS := -Wall -Werror + LOCAL_MODULE_TAGS := tests LOCAL_MULTILIB := 64 diff --git a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk index 8e5ec5e01..664347f50 100644 --- a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk +++ b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk @@ -11,6 +11,8 @@ LOCAL_C_INCLUDES := LOCAL_MODULE:= test-pixelflinger-arm64-t32cb16blend +LOCAL_CFLAGS := -Wall -Werror + LOCAL_MODULE_TAGS := tests LOCAL_MULTILIB := 64 diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk index 2f9ca2f9a..72d71efd3 100644 --- a/libpixelflinger/tests/codegen/Android.mk +++ b/libpixelflinger/tests/codegen/Android.mk @@ -13,6 +13,8 @@ LOCAL_C_INCLUDES := \ LOCAL_MODULE:= test-opengl-codegen +LOCAL_CFLAGS:= -Wall -Werror + LOCAL_MODULE_TAGS := tests include $(BUILD_NATIVE_TEST) diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp index efa6d87bf..dce4ed72c 100644 --- a/libpixelflinger/tests/codegen/codegen.cpp +++ b/libpixelflinger/tests/codegen/codegen.cpp @@ -40,9 +40,9 @@ public: const AssemblyKey<needs_t>& key() const { return mKey; } }; +#if ANDROID_ARM_CODEGEN static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1) { -#if ANDROID_ARM_CODEGEN GGLContext* c; gglInit(&c); needs_t needs; @@ -73,10 +73,12 @@ static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1) printf("error %08x (%s)\n", err, strerror(-err)); } gglUninit(c); +} #else +static void ggl_test_codegen(uint32_t, uint32_t, uint32_t, uint32_t) { printf("This test runs only on ARM, Arm64 or MIPS\n"); -#endif } +#endif int main(int argc, char** argv) { diff --git a/libpixelflinger/tests/gglmul/Android.mk b/libpixelflinger/tests/gglmul/Android.mk index 75bd39ef5..67f358fc5 100644 --- a/libpixelflinger/tests/gglmul/Android.mk +++ b/libpixelflinger/tests/gglmul/Android.mk @@ -11,6 +11,8 @@ LOCAL_C_INCLUDES := \ LOCAL_MODULE:= test-pixelflinger-gglmul +LOCAL_CFLAGS:= -Wall -Werror + LOCAL_MODULE_TAGS := tests include $(BUILD_NATIVE_TEST) diff --git a/libpixelflinger/trap.cpp b/libpixelflinger/trap.cpp index 234bfdde1..06ad2373c 100644 --- a/libpixelflinger/trap.cpp +++ b/libpixelflinger/trap.cpp @@ -349,7 +349,6 @@ void linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord static void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width) { - GGL_CONTEXT(c, con); GGLcoord v[4][2]; v[0][0] = v0[0]; v[0][1] = v0[1]; v[1][0] = v1[0]; v[1][1] = v1[1]; @@ -377,7 +376,6 @@ static void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord wi static void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width) { - GGL_CONTEXT(c, con); GGLcoord v[4][2]; v[0][0] = v0[0]; v[0][1] = v0[1]; v[1][0] = v1[0]; v[1][1] = v1[1]; 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 { srcs: [ "ArmExidx.cpp", "DwarfCfa.cpp", - "DwarfDebugFrame.cpp", - "DwarfEhFrame.cpp", + "DwarfEhFrameWithHdr.cpp", "DwarfMemory.cpp", "DwarfOp.cpp", "DwarfSection.cpp", @@ -106,6 +105,7 @@ cc_test { "tests/DwarfCfaTest.cpp", "tests/DwarfDebugFrameTest.cpp", "tests/DwarfEhFrameTest.cpp", + "tests/DwarfEhFrameWithHdrTest.cpp", "tests/DwarfMemoryTest.cpp", "tests/DwarfOpLogTest.cpp", "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 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <stdlib.h> - -#include <algorithm> - -#include <unwindstack/DwarfStructs.h> -#include <unwindstack/Memory.h> - -#include "DwarfDebugFrame.h" -#include "DwarfEncoding.h" -#include "DwarfError.h" - -namespace unwindstack { - -template <typename AddressType> -bool DwarfDebugFrame<AddressType>::Init(uint64_t offset, uint64_t size) { - offset_ = offset; - end_offset_ = offset + size; - - memory_.clear_func_offset(); - memory_.clear_text_offset(); - memory_.set_data_offset(offset); - memory_.set_cur_offset(offset); - - return CreateSortedFdeList(); -} - -template <typename AddressType> -bool DwarfDebugFrame<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { - uint8_t version; - if (!memory_.ReadBytes(&version, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - // Read the augmentation string. - std::vector<char> aug_string; - char aug_value; - bool get_encoding = false; - do { - if (!memory_.ReadBytes(&aug_value, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - if (aug_value == 'R') { - get_encoding = true; - } - aug_string.push_back(aug_value); - } while (aug_value != '\0'); - - if (version == 4) { - // Skip the Address Size field. - memory_.set_cur_offset(memory_.cur_offset() + 1); - - // Read the segment size. - if (!memory_.ReadBytes(segment_size, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - } else { - *segment_size = 0; - } - - if (aug_string[0] != 'z' || !get_encoding) { - // No encoding - return true; - } - - // Skip code alignment factor - uint8_t value; - do { - if (!memory_.ReadBytes(&value, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - } while (value & 0x80); - - // Skip data alignment factor - do { - if (!memory_.ReadBytes(&value, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - } while (value & 0x80); - - if (version == 1) { - // Skip return address register. - memory_.set_cur_offset(memory_.cur_offset() + 1); - } else { - // Skip return address register. - do { - if (!memory_.ReadBytes(&value, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - } while (value & 0x80); - } - - // Skip the augmentation length. - do { - if (!memory_.ReadBytes(&value, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - } while (value & 0x80); - - for (size_t i = 1; i < aug_string.size(); i++) { - if (aug_string[i] == 'R') { - if (!memory_.ReadBytes(encoding, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - // Got the encoding, that's all we are looking for. - return true; - } else if (aug_string[i] == 'L') { - memory_.set_cur_offset(memory_.cur_offset() + 1); - } else if (aug_string[i] == 'P') { - uint8_t encoding; - if (!memory_.ReadBytes(&encoding, 1)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - uint64_t value; - if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - } - } - - // It should be impossible to get here. - abort(); -} - -template <typename AddressType> -bool DwarfDebugFrame<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, - uint8_t encoding) { - if (segment_size != 0) { - memory_.set_cur_offset(memory_.cur_offset() + 1); - } - - uint64_t start; - if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - - uint64_t length; - if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - if (length != 0) { - fdes_.emplace_back(entry_offset, start, length); - } - - return true; -} - -template <typename AddressType> -bool DwarfDebugFrame<AddressType>::CreateSortedFdeList() { - memory_.set_cur_offset(offset_); - - // Loop through all of the entries and read just enough to create - // a sorted list of pcs. - // This code assumes that first comes the cie, then the fdes that - // it applies to. - uint64_t cie_offset = 0; - uint8_t address_encoding; - uint8_t segment_size; - while (memory_.cur_offset() < end_offset_) { - uint64_t cur_entry_offset = memory_.cur_offset(); - - // Figure out the entry length and type. - uint32_t value32; - if (!memory_.ReadBytes(&value32, sizeof(value32))) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - - uint64_t next_entry_offset; - if (value32 == static_cast<uint32_t>(-1)) { - uint64_t value64; - if (!memory_.ReadBytes(&value64, sizeof(value64))) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - next_entry_offset = memory_.cur_offset() + value64; - - // Read the Cie Id of a Cie or the pointer of the Fde. - if (!memory_.ReadBytes(&value64, sizeof(value64))) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - - if (value64 == static_cast<uint64_t>(-1)) { - // Cie 64 bit - address_encoding = DW_EH_PE_sdata8; - if (!GetCieInfo(&segment_size, &address_encoding)) { - return false; - } - cie_offset = cur_entry_offset; - } else { - if (offset_ + value64 != cie_offset) { - // This means that this Fde is not following the Cie. - last_error_ = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - // Fde 64 bit - if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { - return false; - } - } - } else { - next_entry_offset = memory_.cur_offset() + value32; - - // Read the Cie Id of a Cie or the pointer of the Fde. - if (!memory_.ReadBytes(&value32, sizeof(value32))) { - last_error_ = DWARF_ERROR_MEMORY_INVALID; - return false; - } - - if (value32 == static_cast<uint32_t>(-1)) { - // Cie 32 bit - address_encoding = DW_EH_PE_sdata4; - if (!GetCieInfo(&segment_size, &address_encoding)) { - return false; - } - cie_offset = cur_entry_offset; - } else { - if (offset_ + value32 != cie_offset) { - // This means that this Fde is not following the Cie. - last_error_ = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - // Fde 32 bit - if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { - return false; - } - } - } - - if (next_entry_offset < memory_.cur_offset()) { - // This indicates some kind of corruption, or malformed section data. - last_error_ = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - memory_.set_cur_offset(next_entry_offset); - } - - // Sort the entries. - std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) { - if (a.start == b.start) return a.end < b.end; - return a.start < b.start; - }); - - fde_count_ = fdes_.size(); - - return true; -} - -template <typename AddressType> -bool DwarfDebugFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { - if (fde_count_ == 0) { - return false; - } - - size_t first = 0; - size_t last = fde_count_; - while (first < last) { - size_t current = (first + last) / 2; - const FdeInfo* info = &fdes_[current]; - if (pc >= info->start && pc <= info->end) { - *fde_offset = info->offset; - return true; - } - - if (pc < info->start) { - last = current; - } else { - first = current + 1; - } - } - return false; -} - -template <typename AddressType> -const DwarfFde* DwarfDebugFrame<AddressType>::GetFdeFromIndex(size_t index) { - if (index >= fdes_.size()) { - return nullptr; - } - return this->GetFdeFromOffset(fdes_[index].offset); -} - -// Explicitly instantiate DwarfDebugFrame. -template class DwarfDebugFrame<uint32_t>; -template class DwarfDebugFrame<uint64_t>; - -} // 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 { template <typename AddressType> class DwarfDebugFrame : public DwarfSectionImpl<AddressType> { public: - // Add these so that the protected members of DwarfSectionImpl - // can be accessed without needing a this->. - using DwarfSectionImpl<AddressType>::memory_; - using DwarfSectionImpl<AddressType>::fde_count_; - using DwarfSectionImpl<AddressType>::last_error_; - - struct FdeInfo { - FdeInfo(uint64_t offset, uint64_t start, uint64_t length) - : offset(offset), start(start), end(start + length) {} - - uint64_t offset; - AddressType start; - AddressType end; - }; - - DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} + DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) { + this->cie32_value_ = static_cast<uint32_t>(-1); + this->cie64_value_ = static_cast<uint64_t>(-1); + } virtual ~DwarfDebugFrame() = default; - bool Init(uint64_t offset, uint64_t size) override; - - bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; - - const DwarfFde* GetFdeFromIndex(size_t index) override; - - bool IsCie32(uint32_t value32) override { return value32 == static_cast<uint32_t>(-1); } - - bool IsCie64(uint64_t value64) override { return value64 == static_cast<uint64_t>(-1); } + uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { + return this->entries_offset_ + pointer; + } - uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return offset_ + pointer; } - - uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return offset_ + pointer; } + uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { + return this->entries_offset_ + pointer; + } uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; } - - bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding); - - bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding); - - bool CreateSortedFdeList(); - - protected: - uint64_t offset_; - uint64_t end_offset_; - - std::vector<FdeInfo> fdes_; }; } // 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 @@ #include <stdint.h> #include <unwindstack/DwarfSection.h> +#include <unwindstack/Memory.h> namespace unwindstack { -// Forward declarations. -class Memory; - template <typename AddressType> class DwarfEhFrame : public DwarfSectionImpl<AddressType> { public: - // Add these so that the protected members of DwarfSectionImpl - // can be accessed without needing a this->. - using DwarfSectionImpl<AddressType>::memory_; - using DwarfSectionImpl<AddressType>::fde_count_; - using DwarfSectionImpl<AddressType>::last_error_; - - struct FdeInfo { - AddressType pc; - uint64_t offset; - }; - DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} virtual ~DwarfEhFrame() = default; - bool Init(uint64_t offset, uint64_t size) override; - - bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; - - const DwarfFde* GetFdeFromIndex(size_t index) override; - - bool IsCie32(uint32_t value32) override { return value32 == 0; } - - bool IsCie64(uint64_t value64) override { return value64 == 0; } - uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { - return memory_.cur_offset() - pointer - 4; + return this->memory_.cur_offset() - pointer - 4; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { - return memory_.cur_offset() - pointer - 8; + return this->memory_.cur_offset() - pointer - 8; } uint64_t AdjustPcFromFde(uint64_t pc) override { // The eh_frame uses relative pcs. - return pc + memory_.cur_offset(); + return pc + this->memory_.cur_offset(); } - - const FdeInfo* GetFdeInfoFromIndex(size_t index); - - bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset); - - bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries); - - protected: - uint8_t version_; - uint8_t ptr_encoding_; - uint8_t table_encoding_; - size_t table_entry_size_; - - uint64_t ptr_offset_; - - uint64_t entries_offset_; - uint64_t entries_end_; - uint64_t entries_data_offset_; - uint64_t cur_entries_offset_ = 0; - - std::unordered_map<uint64_t, FdeInfo> fde_info_; }; } // namespace unwindstack -#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H +#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 @@ #include <unwindstack/Memory.h> #include "Check.h" -#include "DwarfEhFrame.h" +#include "DwarfEhFrameWithHdr.h" #include "DwarfError.h" namespace unwindstack { template <typename AddressType> -bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { +bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) { uint8_t data[4]; memory_.clear_func_offset(); @@ -73,7 +73,7 @@ bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { } template <typename AddressType> -const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { +const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) { const FdeInfo* info = GetFdeInfoFromIndex(index); if (info == nullptr) { return nullptr; @@ -82,8 +82,8 @@ const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { } template <typename AddressType> -const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::GetFdeInfoFromIndex( - size_t index) { +const typename DwarfEhFrameWithHdr<AddressType>::FdeInfo* +DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) { auto entry = fde_info_.find(index); if (entry != fde_info_.end()) { return &fde_info_[index]; @@ -105,8 +105,8 @@ const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::Ge } template <typename AddressType> -bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, - uint64_t total_entries) { +bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, + uint64_t total_entries) { CHECK(fde_count_ > 0); CHECK(total_entries <= fde_count_); @@ -115,6 +115,9 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of while (first < last) { size_t current = (first + last) / 2; const FdeInfo* info = GetFdeInfoFromIndex(current); + if (info == nullptr) { + return false; + } if (pc == info->pc) { *fde_offset = info->offset; return true; @@ -127,6 +130,9 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of } if (last != 0) { const FdeInfo* info = GetFdeInfoFromIndex(last - 1); + if (info == nullptr) { + return false; + } *fde_offset = info->offset; return true; } @@ -134,7 +140,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of } template <typename AddressType> -bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { +bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { CHECK(fde_count_ != 0); last_error_ = DWARF_ERROR_NONE; // 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 } template <typename AddressType> -bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { +bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } @@ -210,8 +216,8 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_of } } -// Explicitly instantiate DwarfEhFrame. -template class DwarfEhFrame<uint32_t>; -template class DwarfEhFrame<uint64_t>; +// Explicitly instantiate DwarfEhFrameWithHdr +template class DwarfEhFrameWithHdr<uint32_t>; +template class DwarfEhFrameWithHdr<uint64_t>; } // 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 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H +#define _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H + +#include <stdint.h> + +#include <unordered_map> + +#include "DwarfEhFrame.h" + +namespace unwindstack { + +// Forward declarations. +class Memory; + +template <typename AddressType> +class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> { + public: + // Add these so that the protected members of DwarfSectionImpl + // can be accessed without needing a this->. + using DwarfSectionImpl<AddressType>::memory_; + using DwarfSectionImpl<AddressType>::fde_count_; + using DwarfSectionImpl<AddressType>::entries_offset_; + using DwarfSectionImpl<AddressType>::entries_end_; + using DwarfSectionImpl<AddressType>::last_error_; + + struct FdeInfo { + AddressType pc; + uint64_t offset; + }; + + DwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrame<AddressType>(memory) {} + virtual ~DwarfEhFrameWithHdr() = default; + + bool Init(uint64_t offset, uint64_t size) override; + + bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; + + const DwarfFde* GetFdeFromIndex(size_t index) override; + + const FdeInfo* GetFdeInfoFromIndex(size_t index); + + bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset); + + bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries); + + protected: + uint8_t version_; + uint8_t ptr_encoding_; + uint8_t table_encoding_; + size_t table_entry_size_; + + uint64_t ptr_offset_; + + uint64_t entries_data_offset_; + uint64_t cur_entries_offset_ = 0; + + std::unordered_map<uint64_t, FdeInfo> fde_info_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp index 22921684a..805dcd34b 100644 --- a/libunwindstack/DwarfSection.cpp +++ b/libunwindstack/DwarfSection.cpp @@ -29,6 +29,9 @@ #include "DwarfError.h" #include "DwarfOp.h" +#include "DwarfDebugFrame.h" +#include "DwarfEhFrame.h" + namespace unwindstack { DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} @@ -39,6 +42,10 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { return nullptr; } const DwarfFde* fde = GetFdeFromOffset(fde_offset); + if (fde == nullptr) { + return nullptr; + } + // Guaranteed pc >= pc_start, need to check pc in the fde range. if (pc < fde->pc_end) { return fde; @@ -278,7 +285,7 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } - if (!IsCie64(cie_id)) { + if (cie_id != cie64_value_) { // This is not a Cie, something has gone horribly wrong. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; @@ -293,7 +300,7 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } - if (!IsCie32(cie_id)) { + if (cie_id != cie32_value_) { // This is not a Cie, something has gone horribly wrong. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; @@ -436,7 +443,7 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } - if (IsCie64(value64)) { + if (value64 == cie64_value_) { // This is a Cie, this means something has gone wrong. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; @@ -454,7 +461,7 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } - if (IsCie32(value32)) { + if (value32 == cie32_value_) { // This is a Cie, this means something has gone wrong. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; @@ -552,8 +559,301 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t lo return true; } +template <typename AddressType> +bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) { + entries_offset_ = offset; + entries_end_ = offset + size; + + memory_.clear_func_offset(); + memory_.clear_text_offset(); + memory_.set_data_offset(offset); + memory_.set_cur_offset(offset); + memory_.set_pc_offset(offset); + + return CreateSortedFdeList(); +} + +template <typename AddressType> +bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { + uint8_t version; + if (!memory_.ReadBytes(&version, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + // Read the augmentation string. + std::vector<char> aug_string; + char aug_value; + bool get_encoding = false; + do { + if (!memory_.ReadBytes(&aug_value, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + if (aug_value == 'R') { + get_encoding = true; + } + aug_string.push_back(aug_value); + } while (aug_value != '\0'); + + if (version == 4) { + // Skip the Address Size field. + memory_.set_cur_offset(memory_.cur_offset() + 1); + + // Read the segment size. + if (!memory_.ReadBytes(segment_size, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + } else { + *segment_size = 0; + } + + if (aug_string[0] != 'z' || !get_encoding) { + // No encoding + return true; + } + + // Skip code alignment factor + uint8_t value; + do { + if (!memory_.ReadBytes(&value, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + } while (value & 0x80); + + // Skip data alignment factor + do { + if (!memory_.ReadBytes(&value, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + } while (value & 0x80); + + if (version == 1) { + // Skip return address register. + memory_.set_cur_offset(memory_.cur_offset() + 1); + } else { + // Skip return address register. + do { + if (!memory_.ReadBytes(&value, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + } while (value & 0x80); + } + + // Skip the augmentation length. + do { + if (!memory_.ReadBytes(&value, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + } while (value & 0x80); + + for (size_t i = 1; i < aug_string.size(); i++) { + if (aug_string[i] == 'R') { + if (!memory_.ReadBytes(encoding, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + // Got the encoding, that's all we are looking for. + return true; + } else if (aug_string[i] == 'L') { + memory_.set_cur_offset(memory_.cur_offset() + 1); + } else if (aug_string[i] == 'P') { + uint8_t encoding; + if (!memory_.ReadBytes(&encoding, 1)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + uint64_t value; + if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + } + } + + // It should be impossible to get here. + abort(); +} + +template <typename AddressType> +bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, + uint8_t encoding) { + if (segment_size != 0) { + memory_.set_cur_offset(memory_.cur_offset() + 1); + } + + uint64_t start; + if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + start = AdjustPcFromFde(start); + + uint64_t length; + if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + if (length != 0) { + fdes_.emplace_back(entry_offset, start, length); + } + + return true; +} + +template <typename AddressType> +bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() { + memory_.set_cur_offset(entries_offset_); + + // Loop through all of the entries and read just enough to create + // a sorted list of pcs. + // This code assumes that first comes the cie, then the fdes that + // it applies to. + uint64_t cie_offset = 0; + uint8_t address_encoding; + uint8_t segment_size; + while (memory_.cur_offset() < entries_end_) { + uint64_t cur_entry_offset = memory_.cur_offset(); + + // Figure out the entry length and type. + uint32_t value32; + if (!memory_.ReadBytes(&value32, sizeof(value32))) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + + uint64_t next_entry_offset; + if (value32 == static_cast<uint32_t>(-1)) { + uint64_t value64; + if (!memory_.ReadBytes(&value64, sizeof(value64))) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + next_entry_offset = memory_.cur_offset() + value64; + + // Read the Cie Id of a Cie or the pointer of the Fde. + if (!memory_.ReadBytes(&value64, sizeof(value64))) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + + if (value64 == cie64_value_) { + // Cie 64 bit + address_encoding = DW_EH_PE_sdata8; + if (!GetCieInfo(&segment_size, &address_encoding)) { + return false; + } + cie_offset = cur_entry_offset; + } else { + uint64_t last_cie_offset = GetCieOffsetFromFde64(value64); + if (last_cie_offset != cie_offset) { + // This means that this Fde is not following the Cie. + last_error_ = DWARF_ERROR_ILLEGAL_VALUE; + return false; + } + + // Fde 64 bit + if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { + return false; + } + } + } else { + next_entry_offset = memory_.cur_offset() + value32; + + // Read the Cie Id of a Cie or the pointer of the Fde. + if (!memory_.ReadBytes(&value32, sizeof(value32))) { + last_error_ = DWARF_ERROR_MEMORY_INVALID; + return false; + } + + if (value32 == cie32_value_) { + // Cie 32 bit + address_encoding = DW_EH_PE_sdata4; + if (!GetCieInfo(&segment_size, &address_encoding)) { + return false; + } + cie_offset = cur_entry_offset; + } else { + uint64_t last_cie_offset = GetCieOffsetFromFde32(value32); + if (last_cie_offset != cie_offset) { + // This means that this Fde is not following the Cie. + last_error_ = DWARF_ERROR_ILLEGAL_VALUE; + return false; + } + + // Fde 32 bit + if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { + return false; + } + } + } + + if (next_entry_offset < memory_.cur_offset()) { + // This indicates some kind of corruption, or malformed section data. + last_error_ = DWARF_ERROR_ILLEGAL_VALUE; + return false; + } + memory_.set_cur_offset(next_entry_offset); + } + + // Sort the entries. + std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) { + if (a.start == b.start) return a.end < b.end; + return a.start < b.start; + }); + + fde_count_ = fdes_.size(); + + return true; +} + +template <typename AddressType> +bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { + if (fde_count_ == 0) { + return false; + } + + size_t first = 0; + size_t last = fde_count_; + while (first < last) { + size_t current = (first + last) / 2; + const FdeInfo* info = &fdes_[current]; + if (pc >= info->start && pc <= info->end) { + *fde_offset = info->offset; + return true; + } + + if (pc < info->start) { + last = current; + } else { + first = current + 1; + } + } + return false; +} + +template <typename AddressType> +const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) { + if (index >= fdes_.size()) { + return nullptr; + } + return this->GetFdeFromOffset(fdes_[index].offset); +} + // Explicitly instantiate DwarfSectionImpl template class DwarfSectionImpl<uint32_t>; template class DwarfSectionImpl<uint64_t>; +// Explicitly instantiate DwarfDebugFrame +template class DwarfDebugFrame<uint32_t>; +template class DwarfDebugFrame<uint64_t>; + +// Explicitly instantiate DwarfEhFrame +template class DwarfEhFrame<uint32_t>; +template class DwarfEhFrame<uint64_t>; + } // 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 @@ #include "DwarfDebugFrame.h" #include "DwarfEhFrame.h" +#include "DwarfEhFrameWithHdr.h" #include "Symbols.h" namespace unwindstack { @@ -98,7 +99,17 @@ Memory* ElfInterface::CreateGnuDebugdataMemory() { template <typename AddressType> void ElfInterface::InitHeadersWithTemplate() { - if (eh_frame_offset_ != 0) { + if (eh_frame_hdr_offset_ != 0) { + eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_)); + if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) { + // Even if the eh_frame_offset_ is non-zero, do not bother + // trying to read that since something has gone wrong. + eh_frame_.reset(nullptr); + eh_frame_hdr_offset_ = 0; + eh_frame_hdr_size_ = static_cast<uint64_t>(-1); + } + } else if (eh_frame_offset_ != 0) { + // If there is a eh_frame section without a eh_frame_hdr section. eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { eh_frame_.reset(nullptr); @@ -181,11 +192,12 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { return false; } - eh_frame_offset_ = phdr.p_offset; + // This is really the pointer to the .eh_frame_hdr section. + eh_frame_hdr_offset_ = phdr.p_offset; if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { return false; } - eh_frame_size_ = phdr.p_memsz; + eh_frame_hdr_size_ = phdr.p_memsz; break; case PT_DYNAMIC: @@ -271,6 +283,12 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { } else if (name == ".gnu_debugdata") { offset_ptr = &gnu_debugdata_offset_; size_ptr = &gnu_debugdata_size_; + } else if (name == ".eh_frame") { + offset_ptr = &eh_frame_offset_; + size_ptr = &eh_frame_size_; + } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") { + offset_ptr = &eh_frame_hdr_offset_; + size_ptr = &eh_frame_hdr_size_; } if (offset_ptr != nullptr && 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 { virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0; - virtual bool IsCie32(uint32_t value32) = 0; - - virtual bool IsCie64(uint64_t value64) = 0; - virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0; virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0; @@ -106,6 +102,9 @@ class DwarfSection { DwarfMemory memory_; DwarfError last_error_; + uint32_t cie32_value_ = 0; + uint64_t cie64_value_ = 0; + uint64_t fde_count_ = 0; std::unordered_map<uint64_t, DwarfFde> fde_entries_; std::unordered_map<uint64_t, DwarfCie> cie_entries_; @@ -115,9 +114,24 @@ class DwarfSection { template <typename AddressType> class DwarfSectionImpl : public DwarfSection { public: + struct FdeInfo { + FdeInfo(uint64_t offset, uint64_t start, uint64_t length) + : offset(offset), start(start), end(start + length) {} + + uint64_t offset; + AddressType start; + AddressType end; + }; + DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {} virtual ~DwarfSectionImpl() = default; + bool Init(uint64_t offset, uint64_t size) override; + + bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; + + const DwarfFde* GetFdeFromIndex(size_t index) override; + bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, Regs* regs, bool* finished) override; @@ -134,6 +148,16 @@ class DwarfSectionImpl : public DwarfSection { protected: bool EvalExpression(const DwarfLocation& loc, uint8_t version, Memory* regular_memory, AddressType* value); + + bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding); + + bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding); + + bool CreateSortedFdeList(); + + std::vector<FdeInfo> fdes_; + uint64_t entries_offset_; + uint64_t entries_end_; }; } // 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 { uint64_t dynamic_offset() { return dynamic_offset_; } uint64_t dynamic_size() { return dynamic_size_; } + uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; } + uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; } uint64_t eh_frame_offset() { return eh_frame_offset_; } uint64_t eh_frame_size() { return eh_frame_size_; } uint64_t debug_frame_offset() { return debug_frame_offset_; } @@ -112,6 +114,9 @@ class ElfInterface { uint64_t dynamic_offset_ = 0; uint64_t dynamic_size_ = 0; + uint64_t eh_frame_hdr_offset_ = 0; + uint64_t eh_frame_hdr_size_ = 0; + uint64_t eh_frame_offset_ = 0; uint64_t eh_frame_size_ = 0; 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> { ~MockDwarfDebugFrame() = default; void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } - void TestSetOffset(uint64_t offset) { this->offset_ = offset; } - void TestSetEndOffset(uint64_t offset) { this->end_offset_ = offset; } + void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; } + void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; } void TestPushFdeInfo(const typename DwarfDebugFrame<TypeParam>::FdeInfo& info) { this->fdes_.push_back(info); } diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp index 21114da8c..53ee719d2 100644 --- a/libunwindstack/tests/DwarfEhFrameTest.cpp +++ b/libunwindstack/tests/DwarfEhFrameTest.cpp @@ -34,28 +34,19 @@ class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> { MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {} ~MockDwarfEhFrame() = default; - void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; } - void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; } - void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; } - void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; } - void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; } - void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; } - void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } - void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrame<TypeParam>::FdeInfo& info) { - this->fde_info_[index] = info; + void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; } + void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; } + void TestPushFdeInfo(const typename DwarfEhFrame<TypeParam>::FdeInfo& info) { + this->fdes_.push_back(info); } - uint8_t TestGetVersion() { return this->version_; } - uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; } - uint64_t TestGetPtrOffset() { return this->ptr_offset_; } - uint8_t TestGetTableEncoding() { return this->table_encoding_; } - uint64_t TestGetTableEntrySize() { return this->table_entry_size_; } uint64_t TestGetFdeCount() { return this->fde_count_; } - uint64_t TestGetEntriesOffset() { return this->entries_offset_; } - uint64_t TestGetEntriesEnd() { return this->entries_end_; } - uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; } - uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; } + uint8_t TestGetOffset() { return this->offset_; } + uint8_t TestGetEndOffset() { return this->end_offset_; } + void TestGetFdeInfo(size_t index, typename DwarfEhFrame<TypeParam>::FdeInfo* info) { + *info = this->fdes_[index]; + } }; template <typename TypeParam> @@ -76,248 +67,304 @@ TYPED_TEST_CASE_P(DwarfEhFrameTest); // NOTE: All test class variables need to be referenced as this->. -TYPED_TEST_P(DwarfEhFrameTest, Init) { - this->memory_.SetMemory( - 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 126); - - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100)); - EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); - EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding()); - EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding()); - EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize()); - EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount()); - EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset()); - EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset()); - EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd()); - EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset()); - EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset()); - - // Verify an unexpected version will cause a fail. - this->memory_.SetData8(0x1000, 0); - ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); - ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error()); - this->memory_.SetData8(0x1000, 2); - ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); - ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error()); -} +TYPED_TEST_P(DwarfEhFrameTest, Init32) { + // CIE 32 information. + this->memory_.SetData32(0x5000, 0xfc); + this->memory_.SetData32(0x5004, 0); + this->memory_.SetData8(0x5008, 1); + this->memory_.SetData8(0x5009, '\0'); -TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_expect_cache_fail) { - this->eh_frame_->TestSetTableEntrySize(0x10); - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); - ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); -} + // FDE 32 information. + this->memory_.SetData32(0x5100, 0xfc); + this->memory_.SetData32(0x5104, 0x104); + this->memory_.SetData32(0x5108, 0x1500); + this->memory_.SetData32(0x510c, 0x200); -TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_pcrel) { - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4); - this->eh_frame_->TestSetEntriesOffset(0x1000); - this->eh_frame_->TestSetEntriesDataOffset(0x3000); - this->eh_frame_->TestSetTableEntrySize(0x10); + this->memory_.SetData32(0x5200, 0xfc); + this->memory_.SetData32(0x5204, 0x204); + this->memory_.SetData32(0x5208, 0x2500); + this->memory_.SetData32(0x520c, 0x300); - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); + // CIE 32 information. + this->memory_.SetData32(0x5300, 0xfc); + this->memory_.SetData32(0x5304, 0); + this->memory_.SetData8(0x5308, 1); + this->memory_.SetData8(0x5309, '\0'); - auto info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x1384U, info->pc); - EXPECT_EQ(0x1540U, info->offset); + // FDE 32 information. + this->memory_.SetData32(0x5400, 0xfc); + this->memory_.SetData32(0x5404, 0x104); + this->memory_.SetData32(0x5408, 0x3500); + this->memory_.SetData32(0x540c, 0x400); + + this->memory_.SetData32(0x5500, 0xfc); + this->memory_.SetData32(0x5504, 0x204); + this->memory_.SetData32(0x5508, 0x4500); + this->memory_.SetData32(0x550c, 0x500); + + ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600)); + ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount()); + + typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); + + this->eh_frame_->TestGetFdeInfo(0, &info); + EXPECT_EQ(0x5100U, info.offset); + EXPECT_EQ(0x660cU, info.start); + EXPECT_EQ(0x680cU, info.end); + + this->eh_frame_->TestGetFdeInfo(1, &info); + EXPECT_EQ(0x5200U, info.offset); + EXPECT_EQ(0x770cU, info.start); + EXPECT_EQ(0x7a0cU, info.end); + + this->eh_frame_->TestGetFdeInfo(2, &info); + EXPECT_EQ(0x5400U, info.offset); + EXPECT_EQ(0x890cU, info.start); + EXPECT_EQ(0x8d0cU, info.end); + + this->eh_frame_->TestGetFdeInfo(3, &info); + EXPECT_EQ(0x5500U, info.offset); + EXPECT_EQ(0x9a0cU, info.start); + EXPECT_EQ(0x9f0cU, info.end); } -TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_datarel) { - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4); - this->eh_frame_->TestSetEntriesOffset(0x1000); - this->eh_frame_->TestSetEntriesDataOffset(0x3000); - this->eh_frame_->TestSetTableEntrySize(0x10); +TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) { + // CIE 32 information. + this->memory_.SetData32(0x5000, 0xfc); + this->memory_.SetData32(0x5004, 0); + this->memory_.SetData8(0x5008, 1); + this->memory_.SetData8(0x5009, '\0'); - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); + // FDE 32 information. + this->memory_.SetData32(0x5100, 0xfc); + this->memory_.SetData32(0x5104, 0x1000); + this->memory_.SetData32(0x5108, 0x1500); + this->memory_.SetData32(0x510c, 0x200); - auto info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x3344U, info->pc); - EXPECT_EQ(0x3500U, info->offset); + ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); + ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error()); } -TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_cached) { - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - this->eh_frame_->TestSetEntriesOffset(0x1000); - this->eh_frame_->TestSetTableEntrySize(0x10); +TYPED_TEST_P(DwarfEhFrameTest, Init64) { + // CIE 64 information. + this->memory_.SetData32(0x5000, 0xffffffff); + this->memory_.SetData64(0x5004, 0xf4); + this->memory_.SetData64(0x500c, 0); + this->memory_.SetData8(0x5014, 1); + this->memory_.SetData8(0x5015, '\0'); - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); + // FDE 64 information. + this->memory_.SetData32(0x5100, 0xffffffff); + this->memory_.SetData64(0x5104, 0xf4); + this->memory_.SetData64(0x510c, 0x10c); + this->memory_.SetData64(0x5114, 0x1500); + this->memory_.SetData64(0x511c, 0x200); + + this->memory_.SetData32(0x5200, 0xffffffff); + this->memory_.SetData64(0x5204, 0xf4); + this->memory_.SetData64(0x520c, 0x20c); + this->memory_.SetData64(0x5214, 0x2500); + this->memory_.SetData64(0x521c, 0x300); - auto info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x344U, info->pc); - EXPECT_EQ(0x500U, info->offset); + // CIE 64 information. + this->memory_.SetData32(0x5300, 0xffffffff); + this->memory_.SetData64(0x5304, 0xf4); + this->memory_.SetData64(0x530c, 0); + this->memory_.SetData8(0x5314, 1); + this->memory_.SetData8(0x5315, '\0'); + + // FDE 64 information. + this->memory_.SetData32(0x5400, 0xffffffff); + this->memory_.SetData64(0x5404, 0xf4); + this->memory_.SetData64(0x540c, 0x10c); + this->memory_.SetData64(0x5414, 0x3500); + this->memory_.SetData64(0x541c, 0x400); + + this->memory_.SetData32(0x5500, 0xffffffff); + this->memory_.SetData64(0x5504, 0xf4); + this->memory_.SetData64(0x550c, 0x20c); + this->memory_.SetData64(0x5514, 0x4500); + this->memory_.SetData64(0x551c, 0x500); + + ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600)); + ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount()); + + typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); + + this->eh_frame_->TestGetFdeInfo(0, &info); + EXPECT_EQ(0x5100U, info.offset); + EXPECT_EQ(0x661cU, info.start); + EXPECT_EQ(0x681cU, info.end); + + this->eh_frame_->TestGetFdeInfo(1, &info); + EXPECT_EQ(0x5200U, info.offset); + EXPECT_EQ(0x771cU, info.start); + EXPECT_EQ(0x7a1cU, info.end); + + this->eh_frame_->TestGetFdeInfo(2, &info); + EXPECT_EQ(0x5400U, info.offset); + EXPECT_EQ(0x891cU, info.start); + EXPECT_EQ(0x8d1cU, info.end); + + this->eh_frame_->TestGetFdeInfo(3, &info); + EXPECT_EQ(0x5500U, info.offset); + EXPECT_EQ(0x9a1cU, info.start); + EXPECT_EQ(0x9f1cU, info.end); +} - // Clear the memory so that this will fail if it doesn't read cached data. - this->memory_.Clear(); +TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) { + // CIE 64 information. + this->memory_.SetData32(0x5000, 0xffffffff); + this->memory_.SetData64(0x5004, 0xf4); + this->memory_.SetData64(0x500c, 0); + this->memory_.SetData8(0x5014, 1); + this->memory_.SetData8(0x5015, '\0'); - info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x344U, info->pc); - EXPECT_EQ(0x500U, info->offset); + // FDE 64 information. + this->memory_.SetData32(0x5100, 0xffffffff); + this->memory_.SetData64(0x5104, 0xf4); + this->memory_.SetData64(0x510c, 0x1000); + this->memory_.SetData64(0x5114, 0x1500); + this->memory_.SetData64(0x511c, 0x200); + + ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); + ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error()); } -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetBinary_verify) { - this->eh_frame_->TestSetTableEntrySize(0x10); - this->eh_frame_->TestSetFdeCount(10); +TYPED_TEST_P(DwarfEhFrameTest, Init_version1) { + // CIE 32 information. + this->memory_.SetData32(0x5000, 0xfc); + this->memory_.SetData32(0x5004, 0); + this->memory_.SetData8(0x5008, 1); + // Augment string. + this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'}); + // Code alignment factor. + this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00}); + // Data alignment factor. + this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00}); + // Return address register + this->memory_.SetData8(0x5014, 0x84); + // Augmentation length + this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00}); + // R data. + this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2); - typename DwarfEhFrame<TypeParam>::FdeInfo info; - for (size_t i = 0; i < 10; i++) { - info.pc = 0x1000 * (i + 1); + // FDE 32 information. + this->memory_.SetData32(0x5100, 0xfc); + this->memory_.SetData32(0x5104, 0x104); + this->memory_.SetData16(0x5108, 0x1500); + this->memory_.SetData16(0x510a, 0x200); + + ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200)); + ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount()); + + typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); + this->eh_frame_->TestGetFdeInfo(0, &info); + EXPECT_EQ(0x5100U, info.offset); + EXPECT_EQ(0x660aU, info.start); + EXPECT_EQ(0x680aU, info.end); +} + +TYPED_TEST_P(DwarfEhFrameTest, Init_version4) { + // CIE 32 information. + this->memory_.SetData32(0x5000, 0xfc); + this->memory_.SetData32(0x5004, 0); + this->memory_.SetData8(0x5008, 4); + // Augment string. + this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'}); + // Address size. + this->memory_.SetData8(0x500e, 4); + // Segment size. + this->memory_.SetData8(0x500f, 0); + // Code alignment factor. + this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00}); + // Data alignment factor. + this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00}); + // Return address register + this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10}); + // Augmentation length + this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00}); + // L data. + this->memory_.SetData8(0x501a, 0x10); + // P data. + this->memory_.SetData8(0x501b, DW_EH_PE_udata4); + this->memory_.SetData32(0x501c, 0x100); + // R data. + this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2); + + // FDE 32 information. + this->memory_.SetData32(0x5100, 0xfc); + this->memory_.SetData32(0x5104, 0x104); + this->memory_.SetData16(0x5108, 0x1500); + this->memory_.SetData16(0x510a, 0x200); + + ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200)); + ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount()); + + typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); + this->eh_frame_->TestGetFdeInfo(0, &info); + EXPECT_EQ(0x5100U, info.offset); + EXPECT_EQ(0x660aU, info.start); + EXPECT_EQ(0x680aU, info.end); +} + +TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) { + typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); + for (size_t i = 0; i < 9; i++) { + info.start = 0x1000 * (i + 1); + info.end = 0x1000 * (i + 2) - 0x10; info.offset = 0x5000 + i * 0x20; - this->eh_frame_->TestSetFdeInfo(i, info); + this->eh_frame_->TestPushFdeInfo(info); } + this->eh_frame_->TestSetFdeCount(0); uint64_t fde_offset; - EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); - // Not an error, just not found. + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); - // Even number of elements. - for (size_t i = 0; i < 10; i++) { + + this->eh_frame_->TestSetFdeCount(9); + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); + ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); + // Odd number of elements. + for (size_t i = 0; i < 9; i++) { TypeParam pc = 0x1000 * (i + 1); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10)) << "Failed at index " - << i; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10)) + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset)) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) + << "Failed at index " << i; + ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); } - // Odd number of elements. - for (size_t i = 0; i < 9; i++) { + + // Even number of elements. + this->eh_frame_->TestSetFdeCount(10); + info.start = 0xa000; + info.end = 0xaff0; + info.offset = 0x5120; + this->eh_frame_->TestPushFdeInfo(info); + + for (size_t i = 0; i < 10; i++) { TypeParam pc = 0x1000 * (i + 1); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9)) << "Failed at index " - << i; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9)) + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset)) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) + << "Failed at index " << i; + ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); } } -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential) { - this->eh_frame_->TestSetFdeCount(10); - this->eh_frame_->TestSetEntriesDataOffset(0x100); - this->eh_frame_->TestSetEntriesEnd(0x2000); - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); - - this->memory_.SetData32(0x1048, 0x440); - this->memory_.SetData32(0x104c, 0x600); - - // Verify that if entries is zero, that it fails. - uint64_t fde_offset; - ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); - this->eh_frame_->TestSetCurEntriesOffset(0x1040); - - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); - EXPECT_EQ(0x500U, fde_offset); - - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); - EXPECT_EQ(0x600U, fde_offset); - - // Expect that the data is cached so no more memory reads will occur. - this->memory_.Clear(); - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); - EXPECT_EQ(0x600U, fde_offset); -} - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential_last_element) { - this->eh_frame_->TestSetFdeCount(2); - this->eh_frame_->TestSetEntriesDataOffset(0x100); - this->eh_frame_->TestSetEntriesEnd(0x2000); - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - this->eh_frame_->TestSetCurEntriesOffset(0x1040); - - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); - - this->memory_.SetData32(0x1048, 0x440); - this->memory_.SetData32(0x104c, 0x600); - - uint64_t fde_offset; - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); - EXPECT_EQ(0x600U, fde_offset); -} - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential_end_check) { - this->eh_frame_->TestSetFdeCount(2); - this->eh_frame_->TestSetEntriesDataOffset(0x100); - this->eh_frame_->TestSetEntriesEnd(0x1048); - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); - - this->memory_.SetData32(0x1048, 0x440); - this->memory_.SetData32(0x104c, 0x600); - - uint64_t fde_offset; - ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); - ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); -} - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_fail_fde_count) { - this->eh_frame_->TestSetFdeCount(0); - - uint64_t fde_offset; - ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); - ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); -} - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_binary_search) { - this->eh_frame_->TestSetTableEntrySize(16); - this->eh_frame_->TestSetFdeCount(10); - - typename DwarfEhFrame<TypeParam>::FdeInfo info; - info.pc = 0x550; - info.offset = 0x10500; - this->eh_frame_->TestSetFdeInfo(5, info); - info.pc = 0x750; - info.offset = 0x10700; - this->eh_frame_->TestSetFdeInfo(7, info); - info.pc = 0x850; - info.offset = 0x10800; - this->eh_frame_->TestSetFdeInfo(8, info); - - uint64_t fde_offset; - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset)); - EXPECT_EQ(0x10700U, fde_offset); -} - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_sequential_search) { - this->eh_frame_->TestSetFdeCount(10); - this->eh_frame_->TestSetTableEntrySize(0); - - typename DwarfEhFrame<TypeParam>::FdeInfo info; - info.pc = 0x50; - info.offset = 0x10000; - this->eh_frame_->TestSetFdeInfo(0, info); - info.pc = 0x150; - info.offset = 0x10100; - this->eh_frame_->TestSetFdeInfo(1, info); - info.pc = 0x250; - info.offset = 0x10200; - this->eh_frame_->TestSetFdeInfo(2, info); - - uint64_t fde_offset; - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset)); - EXPECT_EQ(0x10100U, fde_offset); -} - TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) { + this->eh_frame_->TestSetOffset(0x4000); + // CIE 32 information. this->memory_.SetData32(0xf000, 0x100); this->memory_.SetData32(0xf004, 0); @@ -358,6 +405,8 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) { } TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) { + this->eh_frame_->TestSetOffset(0x2000); + // CIE 64 information. this->memory_.SetData32(0x6000, 0xffffffff); this->memory_.SetData64(0x6004, 0x100); @@ -399,13 +448,9 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) { EXPECT_EQ(0x20U, fde->cie->return_address_register); } -REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init, GetFdeInfoFromIndex_expect_cache_fail, - GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel, - GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify, - GetFdeOffsetSequential, GetFdeOffsetSequential_last_element, - GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count, - GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search, - GetCieFde32, GetCieFde64); +REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64, + Init64_fde_not_following_cie, Init_version1, Init_version4, + GetFdeOffsetFromPc, GetCieFde32, GetCieFde64); typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; INSTANTIATE_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 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "DwarfEhFrameWithHdr.h" +#include "DwarfEncoding.h" +#include "DwarfError.h" + +#include "LogFake.h" +#include "MemoryFake.h" + +namespace unwindstack { + +template <typename TypeParam> +class MockDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> { + public: + MockDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {} + ~MockDwarfEhFrameWithHdr() = default; + + void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; } + void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; } + void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; } + void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; } + void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; } + void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; } + + void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } + void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo& info) { + this->fde_info_[index] = info; + } + + uint8_t TestGetVersion() { return this->version_; } + uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; } + uint64_t TestGetPtrOffset() { return this->ptr_offset_; } + uint8_t TestGetTableEncoding() { return this->table_encoding_; } + uint64_t TestGetTableEntrySize() { return this->table_entry_size_; } + uint64_t TestGetFdeCount() { return this->fde_count_; } + uint64_t TestGetEntriesOffset() { return this->entries_offset_; } + uint64_t TestGetEntriesEnd() { return this->entries_end_; } + uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; } + uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; } +}; + +template <typename TypeParam> +class DwarfEhFrameWithHdrTest : public ::testing::Test { + protected: + void SetUp() override { + memory_.Clear(); + eh_frame_ = new MockDwarfEhFrameWithHdr<TypeParam>(&memory_); + ResetLogs(); + } + + void TearDown() override { delete eh_frame_; } + + MemoryFake memory_; + MockDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr; +}; +TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest); + +// NOTE: All test class variables need to be referenced as this->. + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) { + this->memory_.SetMemory( + 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4}); + this->memory_.SetData16(0x1004, 0x500); + this->memory_.SetData32(0x1006, 126); + + ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100)); + EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); + EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding()); + EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding()); + EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize()); + EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount()); + EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset()); + EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset()); + EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd()); + EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset()); + EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset()); + + // Verify an unexpected version will cause a fail. + this->memory_.SetData8(0x1000, 0); + ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); + ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error()); + this->memory_.SetData8(0x1000, 2); + ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); + ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error()); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { + this->eh_frame_->TestSetTableEntrySize(0x10); + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); + ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); + ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); + ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); + ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) { + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4); + this->eh_frame_->TestSetEntriesOffset(0x1000); + this->eh_frame_->TestSetEntriesDataOffset(0x3000); + this->eh_frame_->TestSetTableEntrySize(0x10); + + this->memory_.SetData32(0x1040, 0x340); + this->memory_.SetData32(0x1044, 0x500); + + auto info = this->eh_frame_->GetFdeInfoFromIndex(2); + ASSERT_TRUE(info != nullptr); + EXPECT_EQ(0x1384U, info->pc); + EXPECT_EQ(0x1540U, info->offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) { + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4); + this->eh_frame_->TestSetEntriesOffset(0x1000); + this->eh_frame_->TestSetEntriesDataOffset(0x3000); + this->eh_frame_->TestSetTableEntrySize(0x10); + + this->memory_.SetData32(0x1040, 0x340); + this->memory_.SetData32(0x1044, 0x500); + + auto info = this->eh_frame_->GetFdeInfoFromIndex(2); + ASSERT_TRUE(info != nullptr); + EXPECT_EQ(0x3344U, info->pc); + EXPECT_EQ(0x3500U, info->offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) { + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); + this->eh_frame_->TestSetEntriesOffset(0x1000); + this->eh_frame_->TestSetTableEntrySize(0x10); + + this->memory_.SetData32(0x1040, 0x340); + this->memory_.SetData32(0x1044, 0x500); + + auto info = this->eh_frame_->GetFdeInfoFromIndex(2); + ASSERT_TRUE(info != nullptr); + EXPECT_EQ(0x344U, info->pc); + EXPECT_EQ(0x500U, info->offset); + + // Clear the memory so that this will fail if it doesn't read cached data. + this->memory_.Clear(); + + info = this->eh_frame_->GetFdeInfoFromIndex(2); + ASSERT_TRUE(info != nullptr); + EXPECT_EQ(0x344U, info->pc); + EXPECT_EQ(0x500U, info->offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) { + this->eh_frame_->TestSetTableEntrySize(0x10); + this->eh_frame_->TestSetFdeCount(10); + + typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; + for (size_t i = 0; i < 10; i++) { + info.pc = 0x1000 * (i + 1); + info.offset = 0x5000 + i * 0x20; + this->eh_frame_->TestSetFdeInfo(i, info); + } + + uint64_t fde_offset; + EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); + // Not an error, just not found. + ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); + // Even number of elements. + for (size_t i = 0; i < 10; i++) { + TypeParam pc = 0x1000 * (i + 1); + EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i; + EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10)) + << "Failed at index " << i; + EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10)) + << "Failed at index " << i; + EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + } + // Odd number of elements. + for (size_t i = 0; i < 9; i++) { + TypeParam pc = 0x1000 * (i + 1); + EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i; + EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9)) + << "Failed at index " << i; + EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9)) + << "Failed at index " << i; + EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; + } +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_index_fail) { + this->eh_frame_->TestSetTableEntrySize(0x10); + this->eh_frame_->TestSetFdeCount(10); + + uint64_t fde_offset; + EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x1000, &fde_offset, 10)); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential) { + this->eh_frame_->TestSetFdeCount(10); + this->eh_frame_->TestSetEntriesDataOffset(0x100); + this->eh_frame_->TestSetEntriesEnd(0x2000); + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); + + this->memory_.SetData32(0x1040, 0x340); + this->memory_.SetData32(0x1044, 0x500); + + this->memory_.SetData32(0x1048, 0x440); + this->memory_.SetData32(0x104c, 0x600); + + // Verify that if entries is zero, that it fails. + uint64_t fde_offset; + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); + this->eh_frame_->TestSetCurEntriesOffset(0x1040); + + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); + EXPECT_EQ(0x500U, fde_offset); + + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); + EXPECT_EQ(0x600U, fde_offset); + + // Expect that the data is cached so no more memory reads will occur. + this->memory_.Clear(); + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); + EXPECT_EQ(0x600U, fde_offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_last_element) { + this->eh_frame_->TestSetFdeCount(2); + this->eh_frame_->TestSetEntriesDataOffset(0x100); + this->eh_frame_->TestSetEntriesEnd(0x2000); + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); + this->eh_frame_->TestSetCurEntriesOffset(0x1040); + + this->memory_.SetData32(0x1040, 0x340); + this->memory_.SetData32(0x1044, 0x500); + + this->memory_.SetData32(0x1048, 0x440); + this->memory_.SetData32(0x104c, 0x600); + + uint64_t fde_offset; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); + EXPECT_EQ(0x600U, fde_offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_end_check) { + this->eh_frame_->TestSetFdeCount(2); + this->eh_frame_->TestSetEntriesDataOffset(0x100); + this->eh_frame_->TestSetEntriesEnd(0x1048); + this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); + + this->memory_.SetData32(0x1040, 0x340); + this->memory_.SetData32(0x1044, 0x500); + + this->memory_.SetData32(0x1048, 0x440); + this->memory_.SetData32(0x104c, 0x600); + + uint64_t fde_offset; + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); + ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { + this->eh_frame_->TestSetFdeCount(0); + + uint64_t fde_offset; + ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); + ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) { + this->eh_frame_->TestSetTableEntrySize(16); + this->eh_frame_->TestSetFdeCount(10); + + typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; + info.pc = 0x550; + info.offset = 0x10500; + this->eh_frame_->TestSetFdeInfo(5, info); + info.pc = 0x750; + info.offset = 0x10700; + this->eh_frame_->TestSetFdeInfo(7, info); + info.pc = 0x850; + info.offset = 0x10800; + this->eh_frame_->TestSetFdeInfo(8, info); + + uint64_t fde_offset; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset)); + EXPECT_EQ(0x10700U, fde_offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_sequential_search) { + this->eh_frame_->TestSetFdeCount(10); + this->eh_frame_->TestSetTableEntrySize(0); + + typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; + info.pc = 0x50; + info.offset = 0x10000; + this->eh_frame_->TestSetFdeInfo(0, info); + info.pc = 0x150; + info.offset = 0x10100; + this->eh_frame_->TestSetFdeInfo(1, info); + info.pc = 0x250; + info.offset = 0x10200; + this->eh_frame_->TestSetFdeInfo(2, info); + + uint64_t fde_offset; + ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset)); + EXPECT_EQ(0x10100U, fde_offset); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) { + // CIE 32 information. + this->memory_.SetData32(0xf000, 0x100); + this->memory_.SetData32(0xf004, 0); + this->memory_.SetData8(0xf008, 0x1); + this->memory_.SetData8(0xf009, '\0'); + this->memory_.SetData8(0xf00a, 4); + this->memory_.SetData8(0xf00b, 8); + this->memory_.SetData8(0xf00c, 0x20); + + // FDE 32 information. + this->memory_.SetData32(0x14000, 0x20); + this->memory_.SetData32(0x14004, 0x5004); + this->memory_.SetData32(0x14008, 0x9000); + this->memory_.SetData32(0x1400c, 0x100); + + const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000); + ASSERT_TRUE(fde != nullptr); + EXPECT_EQ(0x14010U, fde->cfa_instructions_offset); + EXPECT_EQ(0x14024U, fde->cfa_instructions_end); + EXPECT_EQ(0x1d00cU, fde->pc_start); + EXPECT_EQ(0x1d10cU, fde->pc_end); + EXPECT_EQ(0xf000U, fde->cie_offset); + EXPECT_EQ(0U, fde->lsda_address); + + ASSERT_TRUE(fde->cie != nullptr); + EXPECT_EQ(1U, fde->cie->version); + EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding); + EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); + EXPECT_EQ(0U, fde->cie->segment_size); + EXPECT_EQ(1U, fde->cie->augmentation_string.size()); + EXPECT_EQ('\0', fde->cie->augmentation_string[0]); + EXPECT_EQ(0U, fde->cie->personality_handler); + EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset); + EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end); + EXPECT_EQ(4U, fde->cie->code_alignment_factor); + EXPECT_EQ(8, fde->cie->data_alignment_factor); + EXPECT_EQ(0x20U, fde->cie->return_address_register); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) { + // CIE 64 information. + this->memory_.SetData32(0x6000, 0xffffffff); + this->memory_.SetData64(0x6004, 0x100); + this->memory_.SetData64(0x600c, 0); + this->memory_.SetData8(0x6014, 0x1); + this->memory_.SetData8(0x6015, '\0'); + this->memory_.SetData8(0x6016, 4); + this->memory_.SetData8(0x6017, 8); + this->memory_.SetData8(0x6018, 0x20); + + // FDE 64 information. + this->memory_.SetData32(0x8000, 0xffffffff); + this->memory_.SetData64(0x8004, 0x200); + this->memory_.SetData64(0x800c, 0x200c); + this->memory_.SetData64(0x8014, 0x5000); + this->memory_.SetData64(0x801c, 0x300); + + const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000); + ASSERT_TRUE(fde != nullptr); + EXPECT_EQ(0x8024U, fde->cfa_instructions_offset); + EXPECT_EQ(0x820cU, fde->cfa_instructions_end); + EXPECT_EQ(0xd01cU, fde->pc_start); + EXPECT_EQ(0xd31cU, fde->pc_end); + EXPECT_EQ(0x6000U, fde->cie_offset); + EXPECT_EQ(0U, fde->lsda_address); + + ASSERT_TRUE(fde->cie != nullptr); + EXPECT_EQ(1U, fde->cie->version); + EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding); + EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); + EXPECT_EQ(0U, fde->cie->segment_size); + EXPECT_EQ(1U, fde->cie->augmentation_string.size()); + EXPECT_EQ('\0', fde->cie->augmentation_string[0]); + EXPECT_EQ(0U, fde->cie->personality_handler); + EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset); + EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end); + EXPECT_EQ(4U, fde->cie->code_alignment_factor); + EXPECT_EQ(8, fde->cie->data_alignment_factor); + EXPECT_EQ(0x20U, fde->cie->return_address_register); +} + +TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) { + this->eh_frame_->TestSetTableEntrySize(16); + this->eh_frame_->TestSetFdeCount(1); + + typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; + info.pc = 0x550; + info.offset = 0x10500; + this->eh_frame_->TestSetFdeInfo(0, info); + + ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800)); +} + +REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, GetFdeInfoFromIndex_expect_cache_fail, + GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel, + GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify, + GetFdeOffsetBinary_index_fail, GetFdeOffsetSequential, + GetFdeOffsetSequential_last_element, GetFdeOffsetSequential_end_check, + GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_binary_search, + GetFdeOffsetFromPc_sequential_search, GetCieFde32, GetCieFde64, + GetFdeFromPc_fde_not_found); + +typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; +INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes); + +} // 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> { MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t)); - MOCK_METHOD1(IsCie32, bool(uint32_t)); - - MOCK_METHOD1(IsCie64, bool(uint64_t)); - MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t)); MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t)); MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t)); + void TestSetCie32Value(uint32_t value32) { this->cie32_value_ = value32; } + + void TestSetCie64Value(uint64_t value64) { this->cie64_value_ = value64; } + void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) { this->cie_entries_[offset] = cie; } @@ -77,6 +77,8 @@ class DwarfSectionImplTest : public ::testing::Test { memory_.Clear(); section_ = new MockDwarfSectionImpl<TypeParam>(&memory_); ResetLogs(); + section_->TestSetCie32Value(static_cast<uint32_t>(-1)); + section_->TestSetCie64Value(static_cast<uint64_t>(-1)); } void TearDown() override { delete section_; } @@ -448,8 +450,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) { this->memory_.SetData8(0x500b, 8); this->memory_.SetData8(0x500c, 0x20); - EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); - const DwarfCie* cie = this->section_->GetCie(0x5000); ASSERT_TRUE(cie != nullptr); EXPECT_EQ(1U, cie->version); @@ -493,8 +493,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) { this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f}); this->memory_.SetData8(0x5010, 0x20); - EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); - const DwarfCie* cie = this->section_->GetCie(0x5000); ASSERT_TRUE(cie != nullptr); EXPECT_EQ(1U, cie->version); @@ -514,15 +512,13 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) { TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) { this->memory_.SetData32(0x8000, 0xffffffff); this->memory_.SetData64(0x8004, 0x200); - this->memory_.SetData64(0x800c, 0xffffffff); + this->memory_.SetData64(0x800c, 0xffffffffffffffffULL); this->memory_.SetData8(0x8014, 0x1); this->memory_.SetData8(0x8015, '\0'); this->memory_.SetData8(0x8016, 4); this->memory_.SetData8(0x8017, 8); this->memory_.SetData8(0x8018, 0x20); - EXPECT_CALL(*this->section_, IsCie64(0xffffffff)).WillRepeatedly(::testing::Return(true)); - const DwarfCie* cie = this->section_->GetCie(0x8000); ASSERT_TRUE(cie != nullptr); EXPECT_EQ(1U, cie->version); @@ -557,8 +553,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) { // R data. this->memory_.SetData8(0x5018, DW_EH_PE_udata2); - EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); - const DwarfCie* cie = this->section_->GetCie(0x5000); ASSERT_TRUE(cie != nullptr); EXPECT_EQ(1U, cie->version); @@ -588,8 +582,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) { this->memory_.SetData8(0x500b, 8); this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03}); - EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); - const DwarfCie* cie = this->section_->GetCie(0x5000); ASSERT_TRUE(cie != nullptr); EXPECT_EQ(3U, cie->version); @@ -617,8 +609,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) { this->memory_.SetData8(0x500d, 8); this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03}); - EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); - const DwarfCie* cie = this->section_->GetCie(0x5000); ASSERT_TRUE(cie != nullptr); EXPECT_EQ(4U, cie->version); @@ -649,7 +639,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) { this->memory_.SetData32(0x4008, 0x5000); this->memory_.SetData32(0x400c, 0x100); - EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false)); EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); DwarfCie cie{}; cie.fde_address_encoding = DW_EH_PE_udata4; @@ -673,7 +662,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segme this->memory_.SetData32(0x4018, 0x5000); this->memory_.SetData32(0x401c, 0x100); - EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false)); EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); DwarfCie cie{}; cie.fde_address_encoding = DW_EH_PE_udata4; @@ -700,7 +688,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) { this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01}); this->memory_.SetData16(0x4012, 0x1234); - EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false)); EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); DwarfCie cie{}; cie.fde_address_encoding = DW_EH_PE_udata4; @@ -727,7 +714,6 @@ TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) { this->memory_.SetData32(0x4014, 0x5000); this->memory_.SetData32(0x4018, 0x100); - EXPECT_CALL(*this->section_, IsCie64(0x12345678)).WillOnce(::testing::Return(false)); EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678)) .WillOnce(::testing::Return(0x12345678)); 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() { memory_.SetMemory(offset, &shdr, sizeof(shdr)); offset += ehdr.e_shentsize; + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x300; + shdr.sh_addr = 0x7000; + shdr.sh_offset = 0x7000; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0x800; + memory_.SetMemory(offset, &shdr, sizeof(shdr)); + offset += ehdr.e_shentsize; + + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x400; + shdr.sh_addr = 0x6000; + shdr.sh_offset = 0xa000; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0xf00; + memory_.SetMemory(offset, &shdr, sizeof(shdr)); + offset += ehdr.e_shentsize; + memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame")); memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata")); + memory_.SetMemory(0xf300, ".eh_frame", sizeof(".eh_frame")); + memory_.SetMemory(0xf400, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); @@ -920,6 +944,10 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() { EXPECT_EQ(0x500U, elf->debug_frame_size()); EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset()); EXPECT_EQ(0x800U, elf->gnu_debugdata_size()); + EXPECT_EQ(0x7000U, elf->eh_frame_offset()); + EXPECT_EQ(0x800U, elf->eh_frame_size()); + EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset()); + EXPECT_EQ(0xf00U, elf->eh_frame_hdr_size()); } TEST_F(ElfInterfaceTest, init_section_headers_offsets32) { 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, if (log_id != LOG_ID_SECURITY) { int prio = ANDROID_LOG_INFO; const char* tag = nullptr; + size_t tag_len = 0; if (log_id == LOG_ID_EVENTS) { tag = tagToName(elem->getTag()); + if (tag) { + tag_len = strlen(tag); + } } else { prio = *msg; tag = msg + 1; + tag_len = strnlen(tag, len - 1); } - if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { + if (!__android_log_is_loggable_len(prio, tag, tag_len, + ANDROID_LOG_VERBOSE)) { // Log traffic received to total wrlock(); 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) { name_set = true; } + // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) + - LOGGER_ENTRY_MAX_PAYLOAD]; - struct iovec iov = { buffer, sizeof(buffer) }; + LOGGER_ENTRY_MAX_PAYLOAD + 1]; + struct iovec iov = { buffer, sizeof(buffer) - 1 }; alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr hdr = { @@ -55,13 +56,16 @@ bool LogListener::onDataAvailable(SocketClient* cli) { int socket = cli->getSocket(); // To clear the entire buffer is secure/safe, but this contributes to 1.68% - // overhead under logging load. We are safe because we check counts. + // overhead under logging load. We are safe because we check counts, but + // still need to clear null terminator // memset(buffer, 0, sizeof(buffer)); ssize_t n = recvmsg(socket, &hdr, 0); if (n <= (ssize_t)(sizeof(android_log_header_t))) { return false; } + buffer[n] = 0; + struct ucred* cred = NULL; struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); diff --git a/toolbox/Android.mk b/toolbox/Android.mk index 94029d8d2..c4795a73a 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -59,3 +59,12 @@ $(INPUT_H_LABELS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/generate-input. $(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H) $(INPUT_H_LABELS_H): $(transform-generated-source) + +# We only want 'r' on userdebug and eng builds. +include $(CLEAR_VARS) +LOCAL_SRC_FILES := r.c +LOCAL_CFLAGS += $(common_cflags) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/ +LOCAL_MODULE := r +LOCAL_MODULE_TAGS := debug +include $(BUILD_EXECUTABLE) diff --git a/toolbox/r.c b/toolbox/r.c new file mode 100644 index 000000000..b96cdb279 --- /dev/null +++ b/toolbox/r.c @@ -0,0 +1,102 @@ +#include <fcntl.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> + +#if __LP64__ +#define strtoptr strtoull +#else +#define strtoptr strtoul +#endif + +static int usage() +{ + fprintf(stderr,"r [-b|-s] <address> [<value>]\n"); + return -1; +} + +int main(int argc, char *argv[]) +{ + if(argc < 2) return usage(); + + int width = 4; + if(!strcmp(argv[1], "-b")) { + width = 1; + argc--; + argv++; + } else if(!strcmp(argv[1], "-s")) { + width = 2; + argc--; + argv++; + } + + if(argc < 2) return usage(); + uintptr_t addr = strtoptr(argv[1], 0, 16); + + uintptr_t endaddr = 0; + char* end = strchr(argv[1], '-'); + if (end) + endaddr = strtoptr(end + 1, 0, 16); + + if (!endaddr) + endaddr = addr + width - 1; + + if (endaddr <= addr) { + fprintf(stderr, "end address <= start address\n"); + return -1; + } + + bool set = false; + uint32_t value = 0; + if(argc > 2) { + set = true; + value = strtoul(argv[2], 0, 16); + } + + int fd = open("/dev/mem", O_RDWR | O_SYNC); + if(fd < 0) { + fprintf(stderr,"cannot open /dev/mem\n"); + return -1; + } + + off64_t mmap_start = addr & ~(PAGE_SIZE - 1); + size_t mmap_size = endaddr - mmap_start + 1; + mmap_size = (mmap_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + void* page = mmap64(0, mmap_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, mmap_start); + + if(page == MAP_FAILED){ + fprintf(stderr,"cannot mmap region\n"); + return -1; + } + + while (addr <= endaddr) { + switch(width){ + case 4: { + uint32_t* x = (uint32_t*) (((uintptr_t) page) + (addr & 4095)); + if(set) *x = value; + fprintf(stderr,"%08"PRIxPTR": %08x\n", addr, *x); + break; + } + case 2: { + uint16_t* x = (uint16_t*) (((uintptr_t) page) + (addr & 4095)); + if(set) *x = value; + fprintf(stderr,"%08"PRIxPTR": %04x\n", addr, *x); + break; + } + case 1: { + uint8_t* x = (uint8_t*) (((uintptr_t) page) + (addr & 4095)); + if(set) *x = value; + fprintf(stderr,"%08"PRIxPTR": %02x\n", addr, *x); + break; + } + } + addr += width; + } + return 0; +} |