diff options
Diffstat (limited to 'memory_replay/Action.cpp')
-rw-r--r-- | memory_replay/Action.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/memory_replay/Action.cpp b/memory_replay/Action.cpp new file mode 100644 index 00000000..3c97c438 --- /dev/null +++ b/memory_replay/Action.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <inttypes.h> +#include <malloc.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> + +#include <new> + +#include "Action.h" +#include "Threads.h" +#include "Pointers.h" + +class EndThreadAction : public Action { + public: + EndThreadAction() {} + + bool EndThread() override { return true; } + + void Execute(Pointers*) override {} +}; + +class AllocAction : public Action { + public: + AllocAction(uintptr_t key_pointer) : key_pointer_(key_pointer) {} + + protected: + uintptr_t key_pointer_ = 0; + size_t size_ = 0; +}; + +class MallocAction : public AllocAction { + public: + MallocAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) { + if (sscanf(line, "%zu", &size_) != 1) { + is_error_ = true; + } + } + + void Execute(Pointers* pointers) override { + void* memory = malloc(size_); + memset(memory, 1, size_); + pointers->Add(key_pointer_, memory); + } +}; + +class CallocAction : public AllocAction { + public: + CallocAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) { + if (sscanf(line, "%zu %zu", &n_elements_, &size_) != 2) { + is_error_ = true; + } + } + + void Execute(Pointers* pointers) override { + void* memory = calloc(n_elements_, size_); + memset(memory, 0, n_elements_ * size_); + pointers->Add(key_pointer_, memory); + } + + private: + size_t n_elements_ = 0; +}; + +class ReallocAction : public AllocAction { + public: + ReallocAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) { + if (sscanf(line, "%" SCNxPTR " %zu", &old_pointer_, &size_) != 2) { + is_error_ = true; + } + } + + bool DoesFree() override { return old_pointer_ != 0; } + + void Execute(Pointers* pointers) override { + void* old_memory = nullptr; + if (old_pointer_ != 0) { + old_memory = pointers->Remove(old_pointer_); + } + void* memory = realloc(old_memory, size_); + memset(memory, 1, size_); + pointers->Add(key_pointer_, memory); + } + + private: + uintptr_t old_pointer_ = 0; +}; + +class MemalignAction : public AllocAction { + public: + MemalignAction(uintptr_t key_pointer, const char* line) : AllocAction(key_pointer) { + if (sscanf(line, "%zu %zu", &align_, &size_) != 2) { + is_error_ = true; + } + } + + void Execute(Pointers* pointers) override { + void* memory = memalign(align_, size_); + memset(memory, 1, size_); + pointers->Add(key_pointer_, memory); + } + + private: + size_t align_ = 0; +}; + +class FreeAction : public AllocAction { + public: + FreeAction(uintptr_t key_pointer) : AllocAction(key_pointer) { + } + + bool DoesFree() override { return key_pointer_ != 0; } + + void Execute(Pointers* pointers) override { + if (key_pointer_) { + void* memory = pointers->Remove(key_pointer_); + free(memory); + } + } +}; + +size_t Action::MaxActionSize() { + size_t max = MAX(sizeof(EndThreadAction), sizeof(MallocAction)); + max = MAX(max, sizeof(CallocAction)); + max = MAX(max, sizeof(ReallocAction)); + max = MAX(max, sizeof(MemalignAction)); + return MAX(max, sizeof(FreeAction)); +} + +Action* Action::CreateAction(uintptr_t key_pointer, const char* type, + const char* line, void* action_memory) { + Action* action = nullptr; + if (strcmp(type, "malloc") == 0) { + action = new (action_memory) MallocAction(key_pointer, line); + } else if (strcmp(type, "free") == 0) { + action = new (action_memory) FreeAction(key_pointer); + } else if (strcmp(type, "calloc") == 0) { + action = new (action_memory) CallocAction(key_pointer, line); + } else if (strcmp(type, "realloc") == 0) { + action = new (action_memory) ReallocAction(key_pointer, line); + } else if (strcmp(type, "memalign") == 0) { + action = new (action_memory) MemalignAction(key_pointer, line); + } else if (strcmp(type, "thread_done") == 0) { + action = new (action_memory) EndThreadAction(); + } + + if (action == nullptr || action->IsError()) { + return nullptr; + } + return action; +} |