Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b22451f1 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Always set the sp reg to the cfa for DWARF."

parents e8d1b75c 11e96fe4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -188,6 +188,7 @@ cc_test {
    data: [
        "tests/files/elf32.xz",
        "tests/files/elf64.xz",
        "tests/files/offline/art_quick_osr_stub_arm/*",
        "tests/files/offline/bad_eh_frame_hdr_arm64/*",
        "tests/files/offline/debug_frame_first_x86/*",
        "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
+1 −10
Original line number Diff line number Diff line
@@ -190,8 +190,6 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
  // Always set the dex pc to zero when evaluating.
  cur_regs->set_dex_pc(0);

  AddressType prev_cfa = regs->sp();

  EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
                                  .cie = cie,
                                  .regular_memory = regular_memory,
@@ -204,14 +202,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
        last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
        return false;
      }
      // If the stack pointer register is the CFA, and the stack
      // pointer register does not have any associated location
      // information, use the current cfa value.
      if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
        eval_info.cfa = prev_cfa;
      } else {
      eval_info.cfa = (*cur_regs)[loc->values[0]];
      }
      eval_info.cfa += loc->values[1];
      break;
    case DWARF_LOCATION_VAL_EXPRESSION: {
+2 −6
Original line number Diff line number Diff line
@@ -127,13 +127,9 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Mem
  if (arm.ExtractEntryData(entry_offset) && arm.Eval()) {
    // If the pc was not set, then use the LR registers for the PC.
    if (!arm.pc_set()) {
      regs_arm->set_pc((*regs_arm)[ARM_REG_LR]);
      (*regs_arm)[ARM_REG_PC] = regs_arm->pc();
    } else {
      regs_arm->set_pc((*regs_arm)[ARM_REG_PC]);
      (*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR];
    }
    regs_arm->set_sp(arm.cfa());
    (*regs_arm)[ARM_REG_SP] = regs_arm->sp();
    (*regs_arm)[ARM_REG_SP] = arm.cfa();
    return_value = true;

    // If the pc was set to zero, consider this the final frame.
+29 −19
Original line number Diff line number Diff line
@@ -28,13 +28,28 @@

namespace unwindstack {

RegsArm::RegsArm()
    : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
RegsArm::RegsArm() : RegsImpl<uint32_t>(ARM_REG_LAST, Location(LOCATION_REGISTER, ARM_REG_LR)) {}

ArchEnum RegsArm::Arch() {
  return ARCH_ARM;
}

uint64_t RegsArm::pc() {
  return regs_[ARM_REG_PC];
}

uint64_t RegsArm::sp() {
  return regs_[ARM_REG_SP];
}

void RegsArm::set_pc(uint64_t pc) {
  regs_[ARM_REG_PC] = pc;
}

void RegsArm::set_sp(uint64_t sp) {
  regs_[ARM_REG_SP] = sp;
}

uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  uint64_t load_bias = elf->GetLoadBias();
  if (rel_pc < load_bias) {
@@ -56,17 +71,13 @@ uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  return 4;
}

void RegsArm::SetFromRaw() {
  set_pc(regs_[ARM_REG_PC]);
  set_sp(regs_[ARM_REG_SP]);
}

bool RegsArm::SetPcFromReturnAddress(Memory*) {
  if (pc() == regs_[ARM_REG_LR]) {
  uint32_t lr = regs_[ARM_REG_LR];
  if (regs_[ARM_REG_PC] == lr) {
    return false;
  }

  set_pc(regs_[ARM_REG_LR]);
  regs_[ARM_REG_PC] = lr;
  return true;
}

@@ -94,7 +105,6 @@ Regs* RegsArm::Read(void* remote_data) {

  RegsArm* regs = new RegsArm();
  memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
  regs->SetFromRaw();
  return regs;
}

@@ -103,7 +113,6 @@ Regs* RegsArm::CreateFromUcontext(void* ucontext) {

  RegsArm* regs = new RegsArm();
  memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
  regs->SetFromRaw();
  return regs;
}

@@ -118,6 +127,7 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem

  uint64_t offset = 0;
  if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
    uint64_t sp = regs_[ARM_REG_SP];
    // non-RT sigreturn call.
    // __restore:
    //
@@ -131,17 +141,18 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
    // Form 3 (thumb):
    // 0x77 0x27              movs r7, #77
    // 0x00 0xdf              svc 0
    if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
    if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
      return false;
    }
    if (data == 0x5ac3c35a) {
      // SP + uc_mcontext offset + r0 offset.
      offset = sp() + 0x14 + 0xc;
      offset = sp + 0x14 + 0xc;
    } else {
      // SP + r0 offset
      offset = sp() + 0xc;
      offset = sp + 0xc;
    }
  } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
    uint64_t sp = regs_[ARM_REG_SP];
    // RT sigreturn call.
    // __restore_rt:
    //
@@ -155,15 +166,15 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
    // Form 3 (thumb):
    // 0xad 0x27              movs r7, #ad
    // 0x00 0xdf              svc 0
    if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
    if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
      return false;
    }
    if (data == sp() + 8) {
    if (data == sp + 8) {
      // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
      offset = sp() + 8 + 0x80 + 0x14 + 0xc;
      offset = sp + 8 + 0x80 + 0x14 + 0xc;
    } else {
      // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
      offset = sp() + 0x80 + 0x14 + 0xc;
      offset = sp + 0x80 + 0x14 + 0xc;
    }
  }
  if (offset == 0) {
@@ -173,7 +184,6 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
  if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
    return false;
  }
  SetFromRaw();
  return true;
}

+21 −13
Original line number Diff line number Diff line
@@ -29,12 +29,28 @@
namespace unwindstack {

RegsArm64::RegsArm64()
    : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
    : RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}

ArchEnum RegsArm64::Arch() {
  return ARCH_ARM64;
}

uint64_t RegsArm64::pc() {
  return regs_[ARM64_REG_PC];
}

uint64_t RegsArm64::sp() {
  return regs_[ARM64_REG_SP];
}

void RegsArm64::set_pc(uint64_t pc) {
  regs_[ARM64_REG_PC] = pc;
}

void RegsArm64::set_sp(uint64_t sp) {
  regs_[ARM64_REG_SP] = sp;
}

uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid() || rel_pc < 4) {
    return 0;
@@ -42,17 +58,13 @@ uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  return 4;
}

void RegsArm64::SetFromRaw() {
  set_pc(regs_[ARM64_REG_PC]);
  set_sp(regs_[ARM64_REG_SP]);
}

bool RegsArm64::SetPcFromReturnAddress(Memory*) {
  if (pc() == regs_[ARM64_REG_LR]) {
  uint64_t lr = regs_[ARM64_REG_LR];
  if (regs_[ARM64_REG_PC] == lr) {
    return false;
  }

  set_pc(regs_[ARM64_REG_LR]);
  regs_[ARM64_REG_PC] = lr;
  return true;
}

@@ -100,7 +112,6 @@ Regs* RegsArm64::Read(void* remote_data) {
  uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
  reg_data[ARM64_REG_PC] = user->pc;
  reg_data[ARM64_REG_SP] = user->sp;
  regs->SetFromRaw();
  return regs;
}

@@ -109,7 +120,6 @@ Regs* RegsArm64::CreateFromUcontext(void* ucontext) {

  RegsArm64* regs = new RegsArm64();
  memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
  regs->SetFromRaw();
  return regs;
}

@@ -131,12 +141,10 @@ bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_m
  }

  // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
  if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
  if (!process_memory->ReadFully(regs_[ARM64_REG_SP] + 0x80 + 0xb0 + 0x08, regs_.data(),
                                 sizeof(uint64_t) * ARM64_REG_LAST)) {
    return false;
  }

  SetFromRaw();
  return true;
}

Loading