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 39 namespace unwindstack { 40 41 // The largest user structure. 42 constexpr 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. RemoteGet(pid_t pid)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 CreateFromUcontext(ArchEnum arch,void * ucontext)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 CurrentArch()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 CreateFromLocal()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