1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdint.h> 18#include <sys/ptrace.h> 19#include <sys/uio.h> 20 21#include <vector> 22 23#include <unwindstack/Elf.h> 24#include <unwindstack/MapInfo.h> 25#include <unwindstack/Regs.h> 26#include <unwindstack/RegsArm.h> 27#include <unwindstack/RegsArm64.h> 28#include <unwindstack/RegsMips.h> 29#include <unwindstack/RegsMips64.h> 30#include <unwindstack/RegsX86.h> 31#include <unwindstack/RegsX86_64.h> 32#include <unwindstack/UserArm.h> 33#include <unwindstack/UserArm64.h> 34#include <unwindstack/UserMips.h> 35#include <unwindstack/UserMips64.h> 36#include <unwindstack/UserX86.h> 37#include <unwindstack/UserX86_64.h> 38 39namespace unwindstack { 40 41// The largest user structure. 42constexpr size_t MAX_USER_REGS_SIZE = sizeof(mips64_user_regs) + 10; 43 44// This function assumes that reg_data is already aligned to a 64 bit value. 45// If not this could crash with an unaligned access. 46Regs* Regs::RemoteGet(pid_t pid) { 47 // Make the buffer large enough to contain the largest registers type. 48 std::vector<uint64_t> buffer(MAX_USER_REGS_SIZE / sizeof(uint64_t)); 49 struct iovec io; 50 io.iov_base = buffer.data(); 51 io.iov_len = buffer.size() * sizeof(uint64_t); 52 53 if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, reinterpret_cast<void*>(&io)) == -1) { 54 return nullptr; 55 } 56 57 switch (io.iov_len) { 58 case sizeof(x86_user_regs): 59 return RegsX86::Read(buffer.data()); 60 case sizeof(x86_64_user_regs): 61 return RegsX86_64::Read(buffer.data()); 62 case sizeof(arm_user_regs): 63 return RegsArm::Read(buffer.data()); 64 case sizeof(arm64_user_regs): 65 return RegsArm64::Read(buffer.data()); 66 case sizeof(mips_user_regs): 67 return RegsMips::Read(buffer.data()); 68 case sizeof(mips64_user_regs): 69 return RegsMips64::Read(buffer.data()); 70 } 71 return nullptr; 72} 73 74Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) { 75 switch (arch) { 76 case ARCH_X86: 77 return RegsX86::CreateFromUcontext(ucontext); 78 case ARCH_X86_64: 79 return RegsX86_64::CreateFromUcontext(ucontext); 80 case ARCH_ARM: 81 return RegsArm::CreateFromUcontext(ucontext); 82 case ARCH_ARM64: 83 return RegsArm64::CreateFromUcontext(ucontext); 84 case ARCH_MIPS: 85 return RegsMips::CreateFromUcontext(ucontext); 86 case ARCH_MIPS64: 87 return RegsMips64::CreateFromUcontext(ucontext); 88 case ARCH_UNKNOWN: 89 default: 90 return nullptr; 91 } 92} 93 94ArchEnum Regs::CurrentArch() { 95#if defined(__arm__) 96 return ARCH_ARM; 97#elif defined(__aarch64__) 98 return ARCH_ARM64; 99#elif defined(__i386__) 100 return ARCH_X86; 101#elif defined(__x86_64__) 102 return ARCH_X86_64; 103#elif defined(__mips__) && !defined(__LP64__) 104 return ARCH_MIPS; 105#elif defined(__mips__) && defined(__LP64__) 106 return ARCH_MIPS64; 107#else 108 abort(); 109#endif 110} 111 112Regs* Regs::CreateFromLocal() { 113 Regs* regs; 114#if defined(__arm__) 115 regs = new RegsArm(); 116#elif defined(__aarch64__) 117 regs = new RegsArm64(); 118#elif defined(__i386__) 119 regs = new RegsX86(); 120#elif defined(__x86_64__) 121 regs = new RegsX86_64(); 122#elif defined(__mips__) && !defined(__LP64__) 123 regs = new RegsMips(); 124#elif defined(__mips__) && defined(__LP64__) 125 regs = new RegsMips64(); 126#else 127 abort(); 128#endif 129 return regs; 130} 131 132} // namespace unwindstack 133