blob: ec59ed9eae4bddfad14b9a08cebf5a5c88661362 [file] [log] [blame]
Armando Montanezfec572b2021-06-28 12:13:57 -07001// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
Armando Montanez5f10ff82021-08-13 13:47:39 -070014
15#define PW_LOG_LEVEL PW_THREAD_CONFIG_LOG_LEVEL
16
Armando Montanezfec572b2021-06-28 12:13:57 -070017#include "pw_thread/snapshot.h"
18
19#include <string_view>
20
21#include "pw_bytes/span.h"
22#include "pw_function/function.h"
23#include "pw_log/log.h"
24#include "pw_protobuf/encoder.h"
25#include "pw_status/status.h"
Armando Montanez5f10ff82021-08-13 13:47:39 -070026#include "pw_thread/config.h"
Armando Montanezfec572b2021-06-28 12:13:57 -070027#include "pw_thread_protos/thread.pwpb.h"
28
29namespace pw::thread {
30
31Status SnapshotStack(const StackContext& stack,
32 Thread::StreamEncoder& encoder,
33 ProcessThreadStackCallback& thread_stack_callback) {
34 // TODO(pwbug/422): Add support for ascending stacks.
35 encoder.WriteStackStartPointer(stack.stack_high_addr);
36 encoder.WriteStackEndPointer(stack.stack_low_addr);
37 encoder.WriteStackPointer(stack.stack_pointer);
J. Silva06f85692021-09-08 15:44:18 -070038 if (stack.stack_pointer_est_peak.has_value()) {
39 encoder.WriteStackPointerEstPeak(stack.stack_pointer_est_peak.value());
40 }
Armando Montaneze5a5f382021-08-09 15:50:26 -070041 PW_LOG_DEBUG("Active stack: 0x%08x-0x%08x (%ld bytes)",
42 stack.stack_high_addr,
43 stack.stack_pointer,
44 static_cast<long>(stack.stack_high_addr) -
45 static_cast<long>(stack.stack_pointer));
46 PW_LOG_DEBUG("Stack Limits: 0x%08x-0x%08x (%ld bytes)",
47 stack.stack_low_addr,
48 stack.stack_high_addr,
49 static_cast<long>(stack.stack_high_addr) -
50 static_cast<long>(stack.stack_low_addr));
Armando Montanezfec572b2021-06-28 12:13:57 -070051
52 if (stack.stack_pointer > stack.stack_high_addr) {
53 PW_LOG_ERROR("%s's stack underflowed by %lu bytes",
54 stack.thread_name.data(),
55 static_cast<long unsigned>(stack.stack_pointer -
56 stack.stack_high_addr));
57 return Status::OutOfRange();
58 }
59
60 // Log an error, but don't prevent the capture.
61 if (stack.stack_pointer < stack.stack_low_addr) {
62 PW_LOG_ERROR(
63 "%s's stack overflowed by %lu bytes",
64 stack.thread_name.data(),
65 static_cast<long unsigned>(stack.stack_low_addr - stack.stack_pointer));
66 }
67
68 return thread_stack_callback(
69 encoder,
70 ConstByteSpan(reinterpret_cast<const std::byte*>(stack.stack_pointer),
71 stack.stack_high_addr - stack.stack_pointer));
72}
73
74} // namespace pw::thread