LCOV - code coverage report
Current view: directory - src/trusted/gdb_rsp - abi.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 58 53 91.4 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <assert.h>
       8                 : 
       9                 : #include <map>
      10                 : #include <string>
      11                 : 
      12                 : #include "native_client/src/trusted/gdb_rsp/abi.h"
      13                 : #include "native_client/src/trusted/port/platform.h"
      14                 : 
      15                 : using port::IPlatform;
      16                 : 
      17                 : namespace gdb_rsp {
      18                 : 
      19                 : #define MINIDEF(x, name, purpose) { #name, sizeof(x), Abi::purpose, 0, 0 }
      20                 : #define BPDEF(x) { sizeof(x), x }
      21                 : 
      22                 : static Abi::RegDef RegsX86_64[] = {
      23                 :   MINIDEF(uint64_t, rax, GENERAL),
      24                 :   MINIDEF(uint64_t, rbx, GENERAL),
      25                 :   MINIDEF(uint64_t, rcx, GENERAL),
      26                 :   MINIDEF(uint64_t, rdx, GENERAL),
      27                 :   MINIDEF(uint64_t, rsi, GENERAL),
      28                 :   MINIDEF(uint64_t, rdi, GENERAL),
      29                 :   MINIDEF(uint64_t, rbp, GENERAL),
      30                 :   MINIDEF(uint64_t, rsp, GENERAL),
      31                 :   MINIDEF(uint64_t, r8, GENERAL),
      32                 :   MINIDEF(uint64_t, r9, GENERAL),
      33                 :   MINIDEF(uint64_t, r10, GENERAL),
      34                 :   MINIDEF(uint64_t, r11, GENERAL),
      35                 :   MINIDEF(uint64_t, r12, GENERAL),
      36                 :   MINIDEF(uint64_t, r13, GENERAL),
      37                 :   MINIDEF(uint64_t, r14, GENERAL),
      38                 :   MINIDEF(uint64_t, r15, GENERAL),
      39                 :   MINIDEF(uint64_t, rip, INST_PTR),
      40                 :   MINIDEF(uint32_t, eflags, FLAGS),
      41                 :   MINIDEF(uint32_t, cs, SEGMENT),
      42                 :   MINIDEF(uint32_t, ss, SEGMENT),
      43                 :   MINIDEF(uint32_t, ds, SEGMENT),
      44                 :   MINIDEF(uint32_t, es, SEGMENT),
      45                 :   MINIDEF(uint32_t, fs, SEGMENT),
      46                 :   MINIDEF(uint32_t, gs, SEGMENT),
      47                 : };
      48                 : 
      49                 : static Abi::RegDef RegsX86_32[] = {
      50                 :   MINIDEF(uint32_t, eax, GENERAL),
      51                 :   MINIDEF(uint32_t, ecx, GENERAL),
      52                 :   MINIDEF(uint32_t, edx, GENERAL),
      53                 :   MINIDEF(uint32_t, ebx, GENERAL),
      54                 :   MINIDEF(uint32_t, esp, GENERAL),
      55                 :   MINIDEF(uint32_t, ebp, GENERAL),
      56                 :   MINIDEF(uint32_t, esi, GENERAL),
      57                 :   MINIDEF(uint32_t, edi, GENERAL),
      58                 :   MINIDEF(uint32_t, eip, INST_PTR),
      59                 :   MINIDEF(uint32_t, eflags, FLAGS),
      60                 :   MINIDEF(uint32_t, cs, SEGMENT),
      61                 :   MINIDEF(uint32_t, ss, SEGMENT),
      62                 :   MINIDEF(uint32_t, ds, SEGMENT),
      63                 :   MINIDEF(uint32_t, es, SEGMENT),
      64                 :   MINIDEF(uint32_t, fs, SEGMENT),
      65                 :   MINIDEF(uint32_t, gs, SEGMENT),
      66                 : };
      67                 : 
      68                 : static Abi::RegDef RegsArm[] = {
      69                 :   MINIDEF(uint32_t, r0, GENERAL),
      70                 :   MINIDEF(uint32_t, r1, GENERAL),
      71                 :   MINIDEF(uint32_t, r2, GENERAL),
      72                 :   MINIDEF(uint32_t, r3, GENERAL),
      73                 :   MINIDEF(uint32_t, r4, GENERAL),
      74                 :   MINIDEF(uint32_t, r5, GENERAL),
      75                 :   MINIDEF(uint32_t, r6, GENERAL),
      76                 :   MINIDEF(uint32_t, r7, GENERAL),
      77                 :   MINIDEF(uint32_t, r8, GENERAL),
      78                 :   MINIDEF(uint32_t, r9, GENERAL),
      79                 :   MINIDEF(uint32_t, r10, GENERAL),
      80                 :   MINIDEF(uint32_t, r11, GENERAL),
      81                 :   MINIDEF(uint32_t, r12, GENERAL),
      82                 :   MINIDEF(uint32_t, sp, STACK_PTR),
      83                 :   MINIDEF(uint32_t, lr, LINK_PTR),
      84                 :   MINIDEF(uint32_t, pc, INST_PTR),
      85                 : };
      86                 : 
      87                 : /*
      88                 :  * TODO(mcgrathr): This is hlt rather than the canonical int3.  This is a
      89                 :  * workaround for http://code.google.com/p/nativeclient/issues/detail?id=1730.
      90                 :  * The only actual use of this is in the temporary breakpoint inserted
      91                 :  * implicitly at the entry point to catch startup.  The stub code doesn't
      92                 :  * really keep track of the fact that the trap is its own expected
      93                 :  * breakpoint hit, so it has no place that knows to adjust for it having
      94                 :  * it.  When the int3 trap hits, the PC is left after the int3 instruction,
      95                 :  * i.e. one byte past the place where the breakpoint was inserted.  (This
      96                 :  * is the hardware behavior, and at least Linux is known not to fiddle the
      97                 :  * register state left by the hardware.)  If we remove the breakpoint and
      98                 :  * resume without adjusting the PC back by one byte, then we are executing
      99                 :  * one byte ahead of where we should be.  That's either in the middle of an
     100                 :  * instruction, making it an invalid instruction, or skipping a one-byte
     101                 :  * instruction, breaking the computation by omitting the first instruction
     102                 :  * of the program.  Since hlt generates a fault-type exception rather than
     103                 :  * a trap-type, it will leave the PC at the beginning of the instruction.
     104                 :  * Since nobody cares what exception we actually got, this works around the
     105                 :  * problem.
     106                 :  */
     107                 : static uint8_t BPCodeX86[] = { 0xf4 };
     108                 : 
     109                 : static Abi::BPDef BPX86 = BPDEF(BPCodeX86);
     110                 : 
     111              15 : static AbiMap_t *GetAbis() {
     112              15 :   static AbiMap_t *_abis = new AbiMap_t();
     113              15 :   return _abis;
     114                 : }
     115                 : 
     116                 : // AbiInit & AbiIsAvailable
     117                 : //   This pair of functions work together as singleton to
     118                 : // ensure the module has been correctly initialized.  All
     119                 : // dependant functions should call AbiIsAvailable to ensure
     120                 : // the module is ready.
     121               1 : static bool AbiInit() {
     122               1 :   Abi::Register("i386", RegsX86_32, sizeof(RegsX86_32), &BPX86);
     123               1 :   Abi::Register("i386:x86-64", RegsX86_64, sizeof(RegsX86_64), &BPX86);
     124                 : 
     125                 :   // TODO(cbiffle) Figure out how to REALLY detect ARM, and define Breakpoint
     126               1 :   Abi::Register("iwmmxt", RegsArm, sizeof(RegsArm), NULL);
     127                 : 
     128               1 :   return true;
     129                 : }
     130                 : 
     131               7 : static bool AbiIsAvailable() {
     132               7 :   static bool initialized_ = AbiInit();
     133               7 :   return initialized_;
     134                 : }
     135                 : 
     136                 : 
     137                 : 
     138               3 : Abi::Abi() {}
     139               0 : Abi::~Abi() {}
     140                 : 
     141                 : void Abi::Register(const char *name, RegDef *regs,
     142               3 :                    uint32_t bytes, const BPDef *bp) {
     143               3 :   uint32_t offs = 0;
     144               3 :   const uint32_t cnt = bytes / sizeof(RegDef);
     145                 : 
     146                 :   // Build indexes and offsets
     147              59 :   for (uint32_t loop = 0; loop < cnt; loop++) {
     148              56 :     regs[loop].index_ = loop;
     149              56 :     regs[loop].offset_ = offs;
     150              56 :     offs += regs[loop].bytes_;
     151                 :   }
     152                 : 
     153               3 :   Abi *abi = new Abi;
     154                 : 
     155               3 :   abi->name_ = name;
     156               3 :   abi->regCnt_ = cnt;
     157               3 :   abi->regDefs_= regs;
     158               3 :   abi->ctxSize_ = offs;
     159               3 :   abi->bpDef_ = bp;
     160                 : 
     161               3 :   AbiMap_t *abis = GetAbis();
     162               3 :   (*abis)[name] = abi;
     163               3 : }
     164                 : 
     165               6 : const Abi* Abi::Find(const char *name) {
     166               6 :   if (!AbiIsAvailable()) {
     167               0 :     IPlatform::LogError("Failed to initalize ABIs.");
     168               0 :     return NULL;
     169                 :   }
     170                 : 
     171               6 :   AbiMap_t::const_iterator itr = GetAbis()->find(name);
     172               7 :   if (itr == GetAbis()->end()) return NULL;
     173                 : 
     174               5 :   return itr->second;
     175                 : }
     176                 : 
     177              93 : const Abi* Abi::Get() {
     178                 :   static const Abi* abi = NULL;
     179                 : 
     180              93 :   if ((NULL == abi) && AbiIsAvailable()) {
     181                 : #ifdef GDB_RSP_ABI_ARM
     182                 :     abi = Abi::Find("iwmmxt");
     183                 : #elif GDB_RSP_ABI_X86_64
     184                 :     abi = Abi::Find("i386:x86-64");
     185                 : #elif GDB_RSP_ABI_X86
     186               1 :     abi = Abi::Find("i386");
     187                 : #else
     188                 : #error "Unknown CPU architecture."
     189                 : #endif
     190                 :   }
     191                 : 
     192              93 :   return abi;
     193                 : }
     194                 : 
     195               6 : const char* Abi::GetName() const {
     196               6 :   return name_;
     197                 : }
     198                 : 
     199               1 : const Abi::BPDef *Abi::GetBreakpointDef() const {
     200               1 :   return bpDef_;
     201                 : }
     202                 : 
     203              12 : uint32_t Abi::GetContextSize() const {
     204              12 :   return ctxSize_;
     205                 : }
     206                 : 
     207             121 : uint32_t Abi::GetRegisterCount() const {
     208             121 :   return regCnt_;
     209                 : }
     210                 : 
     211             251 : const Abi::RegDef *Abi::GetRegisterDef(uint32_t index) const {
     212             251 :   if (index >= regCnt_) return NULL;
     213                 : 
     214             248 :   return &regDefs_[index];
     215                 : }
     216                 : 
     217               7 : const Abi::RegDef *Abi::GetRegisterType(RegType rtype, uint32_t nth) const {
     218               7 :   uint32_t typeNum = 0;
     219                 : 
     220                 :   // Scan for the "nth" register of rtype;
     221              46 :   for (uint32_t regNum = 0; regNum < regCnt_; regNum++) {
     222              46 :     if (rtype == regDefs_[regNum].type_) {
     223               7 :       if (typeNum == nth) return &regDefs_[regNum];
     224               0 :       typeNum++;
     225                 :     }
     226                 :   }
     227                 : 
     228                 :   // Otherwise we failed to find it
     229               0 :   return NULL;
     230                 : }
     231                 : 
     232                 : }  // namespace gdb_rsp

Generated by: LCOV version 1.7