Snap for 5472349 from 82866421b8b357b18c71e2b560c81c95ab925934 to qt-release

Change-Id: Id54a23ef636fb12b859ddd19285c0ce7930799f8
diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp
index c23da01..bc13a8c 100644
--- a/fastboot/fuzzy_fastboot/fixtures.cpp
+++ b/fastboot/fuzzy_fastboot/fixtures.cpp
@@ -59,7 +59,7 @@
 
 namespace fastboot {
 
-int FastBootTest::MatchFastboot(usb_ifc_info* info, const char* local_serial) {
+int FastBootTest::MatchFastboot(usb_ifc_info* info, const std::string& local_serial) {
     if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) {
         return -1;
     }
@@ -68,8 +68,8 @@
 
     // require matching serial number or device path if requested
     // at the command line with the -s option.
-    if (local_serial && (strcmp(local_serial, info->serial_number) != 0 &&
-                         strcmp(local_serial, info->device_path) != 0))
+    if (!local_serial.empty() && local_serial != info->serial_number &&
+        local_serial != info->device_path)
         return -1;
     return 0;
 }
@@ -113,7 +113,9 @@
         ASSERT_TRUE(UsbStillAvailible());  // The device disconnected
     }
 
-    const auto matcher = [](usb_ifc_info* info) -> int { return MatchFastboot(info, nullptr); };
+    const auto matcher = [](usb_ifc_info* info) -> int {
+        return MatchFastboot(info, device_serial);
+    };
     for (int i = 0; i < MAX_USB_TRIES && !transport; i++) {
         std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT));
         if (usb)
@@ -172,7 +174,9 @@
         ;
     printf("WAITING FOR DEVICE\n");
     // Need to wait for device
-    const auto matcher = [](usb_ifc_info* info) -> int { return MatchFastboot(info, nullptr); };
+    const auto matcher = [](usb_ifc_info* info) -> int {
+        return MatchFastboot(info, device_serial);
+    };
     while (!transport) {
         std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT));
         if (usb) {
@@ -238,6 +242,7 @@
 std::string FastBootTest::cb_scratch = "";
 std::string FastBootTest::initial_slot = "";
 int FastBootTest::serial_port = 0;
+std::string FastBootTest::device_serial = "";
 
 template <bool UNLOCKED>
 void ModeTest<UNLOCKED>::SetUp() {
diff --git a/fastboot/fuzzy_fastboot/fixtures.h b/fastboot/fuzzy_fastboot/fixtures.h
index 7c8d54d..c71c897 100644
--- a/fastboot/fuzzy_fastboot/fixtures.h
+++ b/fastboot/fuzzy_fastboot/fixtures.h
@@ -43,9 +43,10 @@
 class FastBootTest : public testing::Test {
   public:
     static int serial_port;
+    static std::string device_serial;
     static constexpr int MAX_USB_TRIES = 10;
 
-    static int MatchFastboot(usb_ifc_info* info, const char* local_serial = nullptr);
+    static int MatchFastboot(usb_ifc_info* info, const std::string& local_serial = "");
     bool UsbStillAvailible();
     bool UserSpaceFastboot();
     void ReconnectFastbootDevice();
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index a40bc27..ff918a7 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -162,7 +162,7 @@
 // Test that USB even works
 TEST(USBFunctionality, USBConnect) {
     const auto matcher = [](usb_ifc_info* info) -> int {
-        return FastBootTest::MatchFastboot(info, nullptr);
+        return FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial);
     };
     Transport* transport = nullptr;
     for (int i = 0; i < FastBootTest::MAX_USB_TRIES && !transport; i++) {
@@ -1738,10 +1738,14 @@
         fastboot::GenerateXmlTests(fastboot::config);
     }
 
+    if (args.find("serial") != args.end()) {
+        fastboot::FastBootTest::device_serial = args.at("serial");
+    }
+
     setbuf(stdout, NULL);  // no buffering
     printf("<Waiting for Device>\n");
     const auto matcher = [](usb_ifc_info* info) -> int {
-        return fastboot::FastBootTest::MatchFastboot(info, nullptr);
+        return fastboot::FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial);
     };
     Transport* transport = nullptr;
     while (!transport) {
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 6bec63c..71980d7 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -170,5 +170,7 @@
       return "Failed to unwind due to invalid unwind information";
     case BACKTRACE_UNWIND_ERROR_REPEATED_FRAME:
       return "Failed to unwind due to same sp/pc repeating";
+    case BACKTRACE_UNWIND_ERROR_INVALID_ELF:
+      return "Failed to unwind due to invalid elf";
   }
 }
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index f5f9b2a..36640cd 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -89,6 +89,10 @@
       case unwindstack::ERROR_REPEATED_FRAME:
         error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
         break;
+
+      case unwindstack::ERROR_INVALID_ELF:
+        error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF;
+        break;
     }
   }
 
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index 10e790b..404e7e8 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -64,6 +64,8 @@
   BACKTRACE_UNWIND_ERROR_UNWIND_INFO,
   // Unwind information stopped due to sp/pc repeating.
   BACKTRACE_UNWIND_ERROR_REPEATED_FRAME,
+  // Unwind information stopped due to invalid elf.
+  BACKTRACE_UNWIND_ERROR_INVALID_ELF,
 };
 
 struct BacktraceUnwindError {
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 4b93abb..3454913 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -160,7 +160,7 @@
   if (valid_) {
     return interface_->LastErrorCode();
   }
-  return ERROR_NONE;
+  return ERROR_INVALID_ELF;
 }
 
 uint64_t Elf::GetLastErrorAddress() {
@@ -170,22 +170,23 @@
   return 0;
 }
 
+// The relative pc expectd by this function is relative to the start of the elf.
+bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
+  if (!valid_) {
+    return false;
+  }
+  return regs->StepIfSignalHandler(rel_pc, this, process_memory);
+}
+
 // The relative pc is always relative to the start of the map from which it comes.
-bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
-               bool* finished) {
+bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) {
   if (!valid_) {
     return false;
   }
 
-  // The relative pc expectd by StepIfSignalHandler is relative to the start of the elf.
-  if (regs->StepIfSignalHandler(rel_pc, this, process_memory)) {
-    *finished = false;
-    return true;
-  }
-
   // Lock during the step which can update information in the object.
   std::lock_guard<std::mutex> guard(lock_);
-  return interface_->Step(adjusted_rel_pc, regs, process_memory, finished);
+  return interface_->Step(rel_pc, regs, process_memory, finished);
 }
 
 bool Elf::IsValidElf(Memory* memory) {
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp
index 5b2fadf..5d81200 100644
--- a/libunwindstack/LocalUnwinder.cpp
+++ b/libunwindstack/LocalUnwinder.cpp
@@ -111,6 +111,14 @@
       pc_adjustment = 0;
     }
     step_pc -= pc_adjustment;
+
+    bool finished = false;
+    if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) {
+      step_pc = rel_pc;
+    } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished)) {
+      finished = true;
+    }
+
     // Skip any locations that are within this library.
     if (num_frames != 0 || !ShouldSkipLibrary(map_info->name)) {
       // Add frame information.
@@ -124,22 +132,12 @@
       }
       num_frames++;
     }
-    if (!elf->valid()) {
-      break;
-    }
-    if (frame_info->size() == max_frames) {
-      break;
-    }
 
+    if (finished || frame_info->size() == max_frames ||
+        (cur_pc == regs->pc() && cur_sp == regs->sp())) {
+      break;
+    }
     adjust_pc = true;
-    bool finished;
-    if (!elf->Step(rel_pc, step_pc, regs.get(), process_memory_.get(), &finished) || finished) {
-      break;
-    }
-    // pc and sp are the same, terminate the unwind.
-    if (cur_pc == regs->pc() && cur_sp == regs->sp()) {
-      break;
-    }
   }
   return num_frames != 0;
 }
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 3f2e1c1..f3d2b5e 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -89,8 +89,8 @@
 #endif
 }
 
-void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
-                           uint64_t pc_adjustment) {
+FrameData* Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc,
+                                 uint64_t pc_adjustment) {
   size_t frame_num = frames_.size();
   frames_.resize(frame_num + 1);
   FrameData* frame = &frames_.at(frame_num);
@@ -100,7 +100,8 @@
   frame->pc = regs_->pc() - pc_adjustment;
 
   if (map_info == nullptr) {
-    return;
+    // Nothing else to update.
+    return nullptr;
   }
 
   if (resolve_names_) {
@@ -118,12 +119,7 @@
   frame->map_end = map_info->end;
   frame->map_flags = map_info->flags;
   frame->map_load_bias = elf->GetLoadBias();
-
-  if (!resolve_names_ ||
-      !elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) {
-    frame->function_name = "";
-    frame->function_offset = 0;
-  }
+  return frame;
 }
 
 static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore,
@@ -194,6 +190,7 @@
       }
     }
 
+    FrameData* frame = nullptr;
     if (map_info == nullptr || initial_map_names_to_skip == nullptr ||
         std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(),
                   basename(map_info->name.c_str())) == initial_map_names_to_skip->end()) {
@@ -210,23 +207,21 @@
         }
       }
 
-      FillInFrame(map_info, elf, rel_pc, step_pc, pc_adjustment);
+      frame = FillInFrame(map_info, elf, rel_pc, pc_adjustment);
 
       // Once a frame is added, stop skipping frames.
       initial_map_names_to_skip = nullptr;
     }
     adjust_pc = true;
 
-    bool stepped;
+    bool stepped = false;
     bool in_device_map = false;
-    if (map_info == nullptr) {
-      stepped = false;
-    } else {
+    bool finished = false;
+    if (map_info != nullptr) {
       if (map_info->flags & MAPS_FLAGS_DEVICE_MAP) {
         // Do not stop here, fall through in case we are
         // in the speculative unwind path and need to remove
         // some of the speculative frames.
-        stepped = false;
         in_device_map = true;
       } else {
         MapInfo* sp_info = maps_->Find(regs_->sp());
@@ -234,19 +229,37 @@
           // Do not stop here, fall through in case we are
           // in the speculative unwind path and need to remove
           // some of the speculative frames.
-          stepped = false;
           in_device_map = true;
         } else {
-          bool finished;
-          stepped = elf->Step(rel_pc, step_pc, regs_, process_memory_.get(), &finished);
-          elf->GetLastError(&last_error_);
-          if (stepped && finished) {
-            break;
+          if (elf->StepIfSignalHandler(rel_pc, regs_, process_memory_.get())) {
+            stepped = true;
+            if (frame != nullptr) {
+              // Need to adjust the relative pc because the signal handler
+              // pc should not be adjusted.
+              frame->rel_pc = rel_pc;
+              frame->pc += pc_adjustment;
+              step_pc = rel_pc;
+            }
+          } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished)) {
+            stepped = true;
           }
+          elf->GetLastError(&last_error_);
         }
       }
     }
 
+    if (frame != nullptr) {
+      if (!resolve_names_ ||
+          !elf->GetFunctionName(step_pc, &frame->function_name, &frame->function_offset)) {
+        frame->function_name = "";
+        frame->function_offset = 0;
+      }
+    }
+
+    if (finished) {
+      break;
+    }
+
     if (!stepped) {
       if (return_address_attempt) {
         // Only remove the speculative frame if there are more than two frames
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index ac94f10..56bf318 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -67,8 +67,9 @@
 
   uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
 
-  bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
-            bool* finished);
+  bool StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory);
+
+  bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
 
   ElfInterface* CreateInterfaceFromMemory(Memory* memory);
 
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
index 6ed0e0f..72ec454 100644
--- a/libunwindstack/include/unwindstack/Error.h
+++ b/libunwindstack/include/unwindstack/Error.h
@@ -29,6 +29,7 @@
   ERROR_INVALID_MAP,          // Unwind in an invalid map.
   ERROR_MAX_FRAMES_EXCEEDED,  // The number of frames exceed the total allowed.
   ERROR_REPEATED_FRAME,       // The last frame has the same pc/sp as the next.
+  ERROR_INVALID_ELF,          // Unwind in an invalid elf.
 };
 
 struct ErrorData {
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 8b01654..75be209 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -118,8 +118,7 @@
   Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
 
   void FillInDexFrame();
-  void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
-                   uint64_t pc_adjustment);
+  FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment);
 
   size_t max_frames_;
   Maps* maps_;
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 23c9cf8..c432d6d 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -132,8 +132,12 @@
   uint64_t func_offset;
   ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
 
+  ASSERT_FALSE(elf.StepIfSignalHandler(0, nullptr, nullptr));
+  EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode());
+
   bool finished;
-  ASSERT_FALSE(elf.Step(0, 0, nullptr, nullptr, &finished));
+  ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished));
+  EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode());
 }
 
 TEST_F(ElfTest, elf32_invalid_machine) {
@@ -295,9 +299,8 @@
   }
 
   elf.FakeSetValid(true);
-  bool finished;
-  ASSERT_TRUE(elf.Step(0x3000, 0x1000, &regs, &process_memory, &finished));
-  EXPECT_FALSE(finished);
+  ASSERT_TRUE(elf.StepIfSignalHandler(0x3000, &regs, &process_memory));
+  EXPECT_EQ(ERROR_NONE, elf.GetLastErrorCode());
   EXPECT_EQ(15U, regs.pc());
   EXPECT_EQ(13U, regs.sp());
 }
@@ -336,7 +339,7 @@
   EXPECT_CALL(*interface, Step(0x1000, &regs, &process_memory, &finished))
       .WillOnce(::testing::Return(true));
 
-  ASSERT_TRUE(elf.Step(0x1004, 0x1000, &regs, &process_memory, &finished));
+  ASSERT_TRUE(elf.Step(0x1000, &regs, &process_memory, &finished));
 }
 
 TEST_F(ElfTest, get_global_invalid_elf) {
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 02ba9c8..6c64c40 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1215,7 +1215,7 @@
       "  #02 pc 0032bff3  libunwindstack_test (SignalOuterFunction+2)\n"
       "  #03 pc 0032fed3  libunwindstack_test "
       "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n"
-      "  #04 pc 00026528  libc.so\n"
+      "  #04 pc 0002652c  libc.so (__restore)\n"
       "  #05 pc 00000000  <unknown>\n"
       "  #06 pc 0032c2d9  libunwindstack_test (InnerFunction+736)\n"
       "  #07 pc 0032cc4f  libunwindstack_test (MiddleFunction+42)\n"
@@ -1243,7 +1243,7 @@
   EXPECT_EQ(0xf43d2ce8U, unwinder.frames()[2].sp);
   EXPECT_EQ(0x2e59ed3U, unwinder.frames()[3].pc);
   EXPECT_EQ(0xf43d2cf0U, unwinder.frames()[3].sp);
-  EXPECT_EQ(0xf4136528U, unwinder.frames()[4].pc);
+  EXPECT_EQ(0xf413652cU, unwinder.frames()[4].pc);
   EXPECT_EQ(0xf43d2d10U, unwinder.frames()[4].sp);
   EXPECT_EQ(0U, unwinder.frames()[5].pc);
   EXPECT_EQ(0xffcc0ee0U, unwinder.frames()[5].sp);
@@ -1326,7 +1326,7 @@
       "  #00 pc 000000000014ccbc  linker64 (__dl_syscall+28)\n"
       "  #01 pc 000000000005426c  linker64 "
       "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
-      "  #02 pc 00000000000008bc  vdso.so\n"
+      "  #02 pc 00000000000008c0  vdso.so (__kernel_rt_sigreturn)\n"
       "  #03 pc 00000000000846f4  libc.so (abort+172)\n"
       "  #04 pc 0000000000084ad4  libc.so (__assert2+36)\n"
       "  #05 pc 000000000003d5b4  ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) "
@@ -1338,7 +1338,7 @@
   EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
   EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp);
-  EXPECT_EQ(0x7e82b018bcULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc);
   EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp);
   EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc);
   EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);
@@ -1366,7 +1366,7 @@
       "  #00 pc 000000000014ccbc  linker64 (__dl_syscall+28)\n"
       "  #01 pc 000000000005426c  linker64 "
       "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
-      "  #02 pc 00000000000008bc  vdso.so\n"
+      "  #02 pc 00000000000008c0  vdso.so (__kernel_rt_sigreturn)\n"
       "  #03 pc 00000000000846f4  libc.so (abort+172)\n"
       "  #04 pc 0000000000084ad4  libc.so (__assert2+36)\n"
       "  #05 pc 000000000003d5b4  ANGLEPrebuilt.apk (offset 0x21d5000)\n"
@@ -1377,7 +1377,7 @@
   EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
   EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp);
-  EXPECT_EQ(0x7e82b018bcULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc);
   EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp);
   EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc);
   EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);