| /* |
| * 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; |
| } |