Refactor Config from a struct to a class.
This should make it easier to add new options, and to add options that
are complex. For example, I want to modify the behavior of
record_allocs_file so that it also enables record_allocs to a default
state.
Test: All unit tests pass.
Test: Enable the backtrace option and restart.
Change-Id: Idf5cdeed06ade3bc2c8ae39d228734bf65209b4f
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 3d46bf0..752d507 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -51,26 +51,26 @@
BacktraceData::BacktraceData(DebugData* debug_data, const Config& config, size_t* offset)
: OptionData(debug_data) {
- size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames;
+ size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames();
alloc_offset_ = *offset;
*offset += BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
}
bool BacktraceData::Initialize(const Config& config) {
- enabled_ = config.backtrace_enabled;
- if (config.backtrace_enable_on_signal) {
+ enabled_ = config.backtrace_enabled();
+ if (config.backtrace_enable_on_signal()) {
struct sigaction enable_act;
memset(&enable_act, 0, sizeof(enable_act));
enable_act.sa_sigaction = EnableToggle;
enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&enable_act.sa_mask);
- if (sigaction(config.backtrace_signal, &enable_act, nullptr) != 0) {
+ if (sigaction(config.backtrace_signal(), &enable_act, nullptr) != 0) {
error_log("Unable to set up backtrace signal enable function: %s", strerror(errno));
return false;
}
info_log("%s: Run: 'kill -%d %d' to enable backtracing.", getprogname(),
- config.backtrace_signal, getpid());
+ config.backtrace_signal(), getpid());
}
return true;
}
diff --git a/libc/malloc_debug/BacktraceData.h b/libc/malloc_debug/BacktraceData.h
index dbc3989..6dee505 100644
--- a/libc/malloc_debug/BacktraceData.h
+++ b/libc/malloc_debug/BacktraceData.h
@@ -36,7 +36,7 @@
#include "OptionData.h"
// Forward declarations.
-struct Config;
+class Config;
class BacktraceData : public OptionData {
public:
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index cb75bd6..df453a9 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
@@ -66,174 +67,227 @@
static constexpr size_t MAX_RECORD_ALLOCS = 50000000;
static constexpr const char DEFAULT_RECORD_ALLOCS_FILE[] = "/data/local/tmp/record_allocs.txt";
-struct Option {
- Option(std::string name, uint64_t option, bool combo_option = false, bool* config = nullptr)
- : name(name), option(option), combo_option(combo_option), config(config) {}
- virtual ~Option() = default;
+const std::unordered_map<std::string, Config::OptionInfo> Config::kOptions = {
+ {"guard",
+ {FRONT_GUARD | REAR_GUARD, &Config::SetGuard},
+ },
+ {"front_guard",
+ {FRONT_GUARD, &Config::SetFrontGuard},
+ },
+ {"rear_guard",
+ {REAR_GUARD, &Config::SetRearGuard},
+ },
- std::string name;
+ {"backtrace",
+ {BACKTRACE | TRACK_ALLOCS, &Config::SetBacktrace},
+ },
+ {"backtrace_enable_on_signal",
+ {BACKTRACE | TRACK_ALLOCS, &Config::SetBacktraceEnableOnSignal},
+ },
- uint64_t option;
- // If set to true, then all of the options following are set on until
- // the combo_option value is set to false.
- bool combo_option = false;
- bool* config;
+ {"fill",
+ {FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
+ },
+ {"fill_on_alloc",
+ {FILL_ON_ALLOC, &Config::SetFillOnAlloc},
+ },
+ {"fill_on_free",
+ {FILL_ON_FREE, &Config::SetFillOnFree},
+ },
- virtual bool ParseValue(const std::string& option_name, const std::string& value) const;
+ {"expand_alloc",
+ {EXPAND_ALLOC, &Config::SetExpandAlloc},
+ },
- virtual void SetDefault() const { }
+ {"free_track",
+ {FREE_TRACK | FILL_ON_FREE, &Config::SetFreeTrack},
+ },
+ {"free_track_backtrace_num_frames",
+ {0, &Config::SetFreeTrackBacktraceNumFrames},
+ },
+
+ {"leak_track",
+ {LEAK_TRACK | TRACK_ALLOCS, &Config::VerifyValueEmpty},
+ },
+
+ {"record_allocs",
+ {RECORD_ALLOCS, &Config::SetRecordAllocs},
+ },
+ {"record_allocs_file",
+ {0, &Config::SetRecordAllocsFile},
+ },
};
-bool Option::ParseValue(const std::string& option_name, const std::string& raw_value) const {
- if (!raw_value.empty()) {
- error_log("%s: value set for option '%s' which does not take a value",
- getprogname(), option_name.c_str());
- return false;
- }
- return true;
-}
-
-struct OptionString : public Option {
- OptionString(std::string name, uint64_t option, std::string default_value,
- std::string* value, bool combo_option = false,
- bool* config = nullptr)
- : Option(name, option, combo_option, config), default_value(default_value), value(value) {}
- virtual ~OptionString() = default;
-
- std::string default_value;
- std::string* value;
-
- bool ParseValue(const std::string& option_name, const std::string& value) const override;
-
- void SetDefault() const override { if (value) *value = default_value; }
-};
-
-bool OptionString::ParseValue(const std::string&, const std::string& raw_value) const {
- if (!raw_value.empty()) {
- *value = raw_value;
- }
- return true;
-}
-
-struct OptionSizeT : public Option {
- OptionSizeT(std::string name, size_t default_value, size_t min_value, size_t max_value,
- uint64_t option, size_t* value, bool combo_option = false, bool* config = nullptr)
- : Option(name, option, combo_option, config), default_value(default_value),
- min_value(min_value), max_value(max_value), value(value) {}
- virtual ~OptionSizeT() = default;
-
- size_t default_value;
- size_t min_value;
- size_t max_value;
-
- size_t* value;
-
- bool ParseValue(const std::string& option_name, const std::string& value) const override;
-
- void SetDefault() const override { if (value) *value = default_value; }
-};
-
-bool OptionSizeT::ParseValue(const std::string& option_name, const std::string& raw_value) const {
- if (raw_value.empty()) {
- // Value should have been set by the SetDefault() pass.
- return true;
- }
+bool Config::ParseValue(const std::string& option, const std::string& value,
+ size_t min_value, size_t max_value, size_t* parsed_value) const {
+ assert(!value.empty());
// Parse the value into a size_t value.
errno = 0;
char* end;
- long parsed_value = strtol(raw_value.c_str(), &end, 10);
+ long long_value = strtol(value.c_str(), &end, 10);
if (errno != 0) {
- error_log("%s: bad value for option '%s': %s", getprogname(), option_name.c_str(),
+ error_log("%s: bad value for option '%s': %s", getprogname(), option.c_str(),
strerror(errno));
return false;
}
- if (end == raw_value.c_str()) {
- error_log("%s: bad value for option '%s'", getprogname(), option_name.c_str());
+ if (end == value.c_str()) {
+ error_log("%s: bad value for option '%s'", getprogname(), option.c_str());
return false;
}
- if (static_cast<size_t>(end - raw_value.c_str()) != raw_value.size()) {
+ if (static_cast<size_t>(end - value.c_str()) != value.size()) {
error_log("%s: bad value for option '%s', non space found after option: %s",
- getprogname(), option_name.c_str(), end);
+ getprogname(), option.c_str(), end);
return false;
}
- if (parsed_value < 0) {
+ if (long_value < 0) {
error_log("%s: bad value for option '%s', value cannot be negative: %ld",
- getprogname(), option_name.c_str(), parsed_value);
+ getprogname(), option.c_str(), long_value);
return false;
}
- if (static_cast<size_t>(parsed_value) < min_value) {
+ if (static_cast<size_t>(long_value) < min_value) {
error_log("%s: bad value for option '%s', value must be >= %zu: %ld",
- getprogname(), option_name.c_str(), min_value, parsed_value);
+ getprogname(), option.c_str(), min_value, long_value);
return false;
}
- if (static_cast<size_t>(parsed_value) > max_value) {
+ if (static_cast<size_t>(long_value) > max_value) {
error_log("%s: bad value for option '%s', value must be <= %zu: %ld",
- getprogname(), option_name.c_str(), max_value, parsed_value);
+ getprogname(), option.c_str(), max_value, long_value);
return false;
}
- *value = static_cast<size_t>(parsed_value);
+ *parsed_value = static_cast<size_t>(long_value);
return true;
}
-class PropertyParser {
- public:
- explicit PropertyParser(const char* property) : cur_(property) {}
+bool Config::ParseValue(const std::string& option, const std::string& value, size_t default_value,
+ size_t min_value, size_t max_value, size_t* new_value) const {
+ if (value.empty()) {
+ *new_value = default_value;
+ return true;
+ }
+ return ParseValue(option, value, min_value, max_value, new_value);
+}
- bool Get(std::string* property, std::string* value);
+bool Config::SetGuard(const std::string& option, const std::string& value) {
+ if (value.empty()) {
+ // Set the defaults.
+ front_guard_bytes_ = DEFAULT_GUARD_BYTES;
+ rear_guard_bytes_ = DEFAULT_GUARD_BYTES;
+ return true;
+ }
- bool Done() { return done_; }
-
- void LogUsage();
-
- private:
- const char* cur_ = nullptr;
-
- bool done_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(PropertyParser);
-};
-
-bool PropertyParser::Get(std::string* property, std::string* value) {
- // Process each property name we can find.
- while (isspace(*cur_))
- ++cur_;
-
- if (*cur_ == '\0') {
- done_ = true;
+ if (!ParseValue(option, value, 1, MAX_GUARD_BYTES, &rear_guard_bytes_)) {
return false;
}
- const char* start = cur_;
- while (!isspace(*cur_) && *cur_ != '=' && *cur_ != '\0')
- ++cur_;
+ // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
+ // make sure that the header is aligned properly.
+ front_guard_bytes_ = BIONIC_ALIGN(rear_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
+ return true;
+}
- *property = std::string(start, cur_ - start);
+bool Config::SetFrontGuard(const std::string& option, const std::string& value) {
+ if (!ParseValue(option, value, DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, &front_guard_bytes_)) {
+ return false;
+ }
+ // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
+ // make sure that the header is aligned properly.
+ front_guard_bytes_ = BIONIC_ALIGN(front_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
+ return true;
+}
- // Skip any spaces after the name.
- while (isspace(*cur_))
- ++cur_;
+bool Config::SetRearGuard(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, &rear_guard_bytes_);
+}
- value->clear();
- if (*cur_ == '=') {
- ++cur_;
- // Skip the space after the equal.
- while (isspace(*cur_))
- ++cur_;
+bool Config::SetFill(const std::string& option, const std::string& value) {
+ if (value.empty()) {
+ // Set the defaults.
+ fill_on_alloc_bytes_ = SIZE_MAX;
+ fill_on_free_bytes_ = SIZE_MAX;
+ return true;
+ }
- start = cur_;
- while (!isspace(*cur_) && *cur_ != '\0')
- ++cur_;
+ if (!ParseValue(option, value, 1, SIZE_MAX, &fill_on_alloc_bytes_)) {
+ return false;
+ }
+ fill_on_free_bytes_ = fill_on_alloc_bytes_;
+ return true;
+}
- if (cur_ != start) {
- *value = std::string(start, cur_ - start);
- }
+bool Config::SetFillOnAlloc(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, SIZE_MAX, 1, SIZE_MAX, &fill_on_alloc_bytes_);
+}
+
+bool Config::SetFillOnFree(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, SIZE_MAX, 1, SIZE_MAX, &fill_on_free_bytes_);
+}
+
+bool Config::SetBacktrace(const std::string& option, const std::string& value) {
+ backtrace_enabled_ = true;
+ return ParseValue(option, value, DEFAULT_BACKTRACE_FRAMES, 1, MAX_BACKTRACE_FRAMES,
+ &backtrace_frames_);
+}
+
+bool Config::SetBacktraceEnableOnSignal(const std::string& option, const std::string& value) {
+ backtrace_enable_on_signal_ = true;
+ return ParseValue(option, value, DEFAULT_BACKTRACE_FRAMES, 1, MAX_BACKTRACE_FRAMES,
+ &backtrace_frames_);
+}
+
+bool Config::SetExpandAlloc(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, &expand_alloc_bytes_);
+}
+
+bool Config::SetFreeTrack(const std::string& option, const std::string& value) {
+ // This option enables fill on free, so set the bytes to the default value.
+ if (fill_on_free_bytes_ == 0) {
+ fill_on_free_bytes_ = SIZE_MAX;
+ }
+ if (free_track_backtrace_num_frames_ == 0) {
+ free_track_backtrace_num_frames_ = DEFAULT_BACKTRACE_FRAMES;
+ }
+
+ return ParseValue(option, value, DEFAULT_FREE_TRACK_ALLOCATIONS, 1, MAX_FREE_TRACK_ALLOCATIONS,
+ &free_track_allocations_);
+}
+
+bool Config::SetFreeTrackBacktraceNumFrames(const std::string& option, const std::string& value) {
+ return ParseValue(option, value, DEFAULT_BACKTRACE_FRAMES, 0, MAX_BACKTRACE_FRAMES,
+ &free_track_backtrace_num_frames_);
+}
+
+bool Config::SetRecordAllocs(const std::string& option, const std::string& value) {
+ if (record_allocs_file_.empty()) {
+ record_allocs_file_ = DEFAULT_RECORD_ALLOCS_FILE;
+ }
+ return ParseValue(option, value, DEFAULT_RECORD_ALLOCS, 1, MAX_RECORD_ALLOCS,
+ &record_allocs_num_entries_);
+}
+
+bool Config::SetRecordAllocsFile(const std::string&, const std::string& value) {
+ if (value.empty()) {
+ // Set the default.
+ record_allocs_file_ = DEFAULT_RECORD_ALLOCS_FILE;
+ return true;
+ }
+ record_allocs_file_ = value;
+ return true;
+}
+
+bool Config::VerifyValueEmpty(const std::string& option, const std::string& value) {
+ if (!value.empty()) {
+ // This is not valid.
+ error_log("%s: value set for option '%s' which does not take a value",
+ getprogname(), option.c_str());
+ return false;
}
return true;
}
-void PropertyParser::LogUsage() {
+
+void Config::LogUsage() const {
error_log("malloc debug options usage:");
error_log("");
error_log(" front_guard[=XX]");
@@ -325,155 +379,85 @@
error_log(" The default is %s.", DEFAULT_RECORD_ALLOCS_FILE);
}
-// This function is designed to be called once. A second call will not
-// reset all variables.
-bool Config::Set(const char* options_str) {
- // Initialize a few default values.
- fill_alloc_value = DEFAULT_FILL_ALLOC_VALUE;
- fill_free_value = DEFAULT_FILL_FREE_VALUE;
- front_guard_value = DEFAULT_FRONT_GUARD_VALUE;
- rear_guard_value = DEFAULT_REAR_GUARD_VALUE;
- backtrace_signal = SIGRTMAX - 19;
- record_allocs_signal = SIGRTMAX - 18;
- free_track_backtrace_num_frames = 0;
- record_allocs_file.clear();
+bool Config::GetOption(const char** options_str, std::string* option, std::string* value) {
+ const char* cur = *options_str;
+ // Process each property name we can find.
+ while (isspace(*cur))
+ ++cur;
- // Parse the options are of the format:
- // option_name or option_name=XX
-
- // Supported options:
- const OptionSizeT option_guard(
- "guard", DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, 0, nullptr, true);
- // Enable front guard. Value is the size of the guard.
- const OptionSizeT option_front_guard(
- "front_guard", DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, FRONT_GUARD,
- &this->front_guard_bytes, true);
- // Enable end guard. Value is the size of the guard.
- const OptionSizeT option_rear_guard(
- "rear_guard", DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, REAR_GUARD, &this->rear_guard_bytes,
- true);
-
- // Enable logging the backtrace on allocation. Value is the total
- // number of frames to log.
- const OptionSizeT option_backtrace(
- "backtrace", DEFAULT_BACKTRACE_FRAMES, 1, MAX_BACKTRACE_FRAMES, BACKTRACE | TRACK_ALLOCS,
- &this->backtrace_frames, false, &this->backtrace_enabled);
- // Enable gathering backtrace values on a signal.
- const OptionSizeT option_backtrace_enable_on_signal(
- "backtrace_enable_on_signal", DEFAULT_BACKTRACE_FRAMES, 1, MAX_BACKTRACE_FRAMES,
- BACKTRACE | TRACK_ALLOCS, &this->backtrace_frames, false, &this->backtrace_enable_on_signal);
-
- const OptionSizeT option_fill("fill", SIZE_MAX, 1, SIZE_MAX, 0, nullptr, true);
- // Fill the allocation with an arbitrary pattern on allocation.
- // Value is the number of bytes of the allocation to fill
- // (default entire allocation).
- const OptionSizeT option_fill_on_alloc(
- "fill_on_alloc", SIZE_MAX, 1, SIZE_MAX, FILL_ON_ALLOC, &this->fill_on_alloc_bytes, true);
- // Fill the allocation with an arbitrary pattern on free.
- // Value is the number of bytes of the allocation to fill
- // (default entire allocation).
- const OptionSizeT option_fill_on_free(
- "fill_on_free", SIZE_MAX, 1, SIZE_MAX, FILL_ON_FREE, &this->fill_on_free_bytes, true);
-
- // Expand the size of every alloc by this number bytes. Value is
- // the total number of bytes to expand every allocation by.
- const OptionSizeT option_expand_alloc(
- "expand_alloc", DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, EXPAND_ALLOC,
- &this->expand_alloc_bytes);
-
- // Keep track of the freed allocations and verify at a later date
- // that they have not been used. Turning this on, also turns on
- // fill on free.
- const OptionSizeT option_free_track(
- "free_track", DEFAULT_FREE_TRACK_ALLOCATIONS, 1, MAX_FREE_TRACK_ALLOCATIONS,
- FREE_TRACK | FILL_ON_FREE, &this->free_track_allocations);
- // Number of backtrace frames to keep when free_track is enabled. If this
- // value is set to zero, no backtrace will be kept.
- const OptionSizeT option_free_track_backtrace_num_frames(
- "free_track_backtrace_num_frames", DEFAULT_BACKTRACE_FRAMES, 0, MAX_BACKTRACE_FRAMES, 0,
- &this->free_track_backtrace_num_frames);
-
- // Enable printing leaked allocations.
- const Option option_leak_track("leak_track", LEAK_TRACK | TRACK_ALLOCS);
-
- const OptionSizeT option_record_allocs(
- "record_allocs", DEFAULT_RECORD_ALLOCS, 1, MAX_RECORD_ALLOCS, RECORD_ALLOCS,
- &this->record_allocs_num_entries);
- const OptionString option_record_allocs_file(
- "record_allocs_file", 0, DEFAULT_RECORD_ALLOCS_FILE, &this->record_allocs_file);
-
- const Option* option_list[] = {
- &option_guard, &option_front_guard, &option_rear_guard,
- &option_backtrace, &option_backtrace_enable_on_signal,
- &option_fill, &option_fill_on_alloc, &option_fill_on_free,
- &option_expand_alloc,
- &option_free_track, &option_free_track_backtrace_num_frames,
- &option_leak_track,
- &option_record_allocs, &option_record_allocs_file,
- };
-
- // Set defaults for all of the options.
- for (size_t i = 0; i < sizeof(option_list)/sizeof(Option*); i++) {
- option_list[i]->SetDefault();
+ if (*cur == '\0') {
+ *options_str = cur;
+ return false;
}
- // Process each property name we can find.
- PropertyParser parser(options_str);
- bool valid = true;
- std::string property;
- std::string value;
- while (valid && parser.Get(&property, &value)) {
- bool found = false;
- for (size_t i = 0; i < sizeof(option_list)/sizeof(Option*); i++) {
- if (property == option_list[i]->name) {
- if (option_list[i]->option == 0 && option_list[i]->combo_option) {
- const std::string* option_name = &option_list[i]->name;
- i++;
- for (; i < sizeof(option_list)/sizeof(Option*) && option_list[i]->combo_option; i++) {
- if (!option_list[i]->ParseValue(*option_name, value)) {
- valid = false;
- break;
- }
- if (option_list[i]->config) {
- *option_list[i]->config = true;
- }
- options |= option_list[i]->option;
- }
- if (!valid) {
- break;
- }
- } else {
- if (!option_list[i]->ParseValue(option_list[i]->name, value)) {
- valid = false;
- break;
- }
- if (option_list[i]->config) {
- *option_list[i]->config = true;
- }
- options |= option_list[i]->option;
- }
- found = true;
- break;
- }
+ const char* start = cur;
+ while (!isspace(*cur) && *cur != '=' && *cur != '\0')
+ ++cur;
+
+ *option = std::string(start, cur - start);
+
+ // Skip any spaces after the name.
+ while (isspace(*cur))
+ ++cur;
+
+ value->clear();
+ if (*cur == '=') {
+ ++cur;
+ // Skip the space after the equal.
+ while (isspace(*cur))
+ ++cur;
+
+ start = cur;
+ while (!isspace(*cur) && *cur != '\0')
+ ++cur;
+
+ if (cur != start) {
+ *value = std::string(start, cur - start);
}
- if (valid && !found) {
- error_log("%s: unknown option %s", getprogname(), property.c_str());
+ }
+ *options_str = cur;
+ return true;
+}
+
+bool Config::Init(const char* options_str) {
+ // Initialize a few default values.
+ fill_alloc_value_ = DEFAULT_FILL_ALLOC_VALUE;
+ fill_free_value_ = DEFAULT_FILL_FREE_VALUE;
+ front_guard_value_ = DEFAULT_FRONT_GUARD_VALUE;
+ rear_guard_value_ = DEFAULT_REAR_GUARD_VALUE;
+ backtrace_signal_ = SIGRTMAX - 19;
+ record_allocs_signal_ = SIGRTMAX - 18;
+ free_track_backtrace_num_frames_ = 0;
+ record_allocs_file_.clear();
+ fill_on_free_bytes_ = 0;
+ backtrace_enable_on_signal_ = false;
+ backtrace_enabled_ = false;
+
+ // Process each option name we can find.
+ std::string option;
+ std::string value;
+ bool valid = true;
+ while (GetOption(&options_str, &option, &value)) {
+ auto entry = kOptions.find(option);
+ if (entry == kOptions.end()) {
+ error_log("%s: unknown option %s", getprogname(), option.c_str());
valid = false;
break;
}
- }
- valid = valid && parser.Done();
-
- if (valid) {
- // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
- // make sure that the header is aligned properly.
- if (options & FRONT_GUARD) {
- front_guard_bytes = BIONIC_ALIGN(front_guard_bytes, MINIMUM_ALIGNMENT_BYTES);
+ const OptionInfo* info = &entry->second;
+ auto process_func = info->process_func;
+ if (process_func != nullptr && !(this->*process_func)(option, value)) {
+ valid = false;
+ break;
}
- } else {
- parser.LogUsage();
+ options_ |= info->option;
}
- return valid;
+ if (!valid || *options_str != '\0') {
+ LogUsage();
+ return false;
+ }
+
+ return true;
}
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index ca56dc8..d8a7069 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -32,6 +32,7 @@
#include <stdint.h>
#include <string>
+#include <unordered_map>
constexpr uint64_t FRONT_GUARD = 0x1;
constexpr uint64_t REAR_GUARD = 0x2;
@@ -55,34 +56,100 @@
// If one or more of these options is set, then a special header is needed.
constexpr uint64_t HEADER_OPTIONS = FRONT_GUARD | REAR_GUARD | BACKTRACE | FREE_TRACK | LEAK_TRACK;
-struct Config {
- bool Set(const char* str);
+class Config {
+ public:
+ bool Init(const char* options_str);
- size_t front_guard_bytes = 0;
- size_t rear_guard_bytes = 0;
+ void LogUsage() const;
- bool backtrace_enable_on_signal = false;
- int backtrace_signal = 0;
- bool backtrace_enabled = false;
- size_t backtrace_frames = 0;
+ uint64_t options() const { return options_; }
- size_t fill_on_alloc_bytes = 0;
- size_t fill_on_free_bytes = 0;
+ int backtrace_signal() const { return backtrace_signal_; }
+ size_t backtrace_frames() const { return backtrace_frames_; }
+ size_t backtrace_enabled() const { return backtrace_enabled_; }
+ size_t backtrace_enable_on_signal() const { return backtrace_enable_on_signal_; }
- size_t expand_alloc_bytes = 0;
+ size_t front_guard_bytes() const { return front_guard_bytes_; }
+ size_t rear_guard_bytes() const { return rear_guard_bytes_; }
+ uint8_t front_guard_value() const { return front_guard_value_; }
+ uint8_t rear_guard_value() const { return rear_guard_value_; }
- size_t free_track_allocations = 0;
- size_t free_track_backtrace_num_frames = 0;
+ size_t expand_alloc_bytes() const { return expand_alloc_bytes_; }
- int record_allocs_signal = 0;
- size_t record_allocs_num_entries = 0;
- std::string record_allocs_file;
+ size_t free_track_allocations() const { return free_track_allocations_; }
+ size_t free_track_backtrace_num_frames() const { return free_track_backtrace_num_frames_; }
- uint64_t options = 0;
- uint8_t fill_alloc_value;
- uint8_t fill_free_value;
- uint8_t front_guard_value;
- uint8_t rear_guard_value;
+ size_t fill_on_alloc_bytes() const { return fill_on_alloc_bytes_; }
+ size_t fill_on_free_bytes() const { return fill_on_free_bytes_; }
+ uint8_t fill_alloc_value() const { return fill_alloc_value_; }
+ uint8_t fill_free_value() const { return fill_free_value_; }
+
+ int record_allocs_signal() const { return record_allocs_signal_; }
+ size_t record_allocs_num_entries() const { return record_allocs_num_entries_; }
+ const std::string& record_allocs_file() const { return record_allocs_file_; }
+
+ private:
+ struct OptionInfo {
+ uint64_t option;
+ bool (Config::*process_func)(const std::string&, const std::string&);
+ };
+
+ bool ParseValue(const std::string& option, const std::string& value, size_t default_value,
+ size_t min_value, size_t max_value, size_t* new_value) const;
+
+ bool ParseValue(const std::string& option, const std::string& value, size_t min_value,
+ size_t max_value, size_t* parsed_value) const;
+
+ bool SetGuard(const std::string& option, const std::string& value);
+ bool SetFrontGuard(const std::string& option, const std::string& value);
+ bool SetRearGuard(const std::string& option, const std::string& value);
+
+ bool SetFill(const std::string& option, const std::string& value);
+ bool SetFillOnAlloc(const std::string& option, const std::string& value);
+ bool SetFillOnFree(const std::string& option, const std::string& value);
+
+ bool SetBacktrace(const std::string& option, const std::string& value);
+ bool SetBacktraceEnableOnSignal(const std::string& option, const std::string& value);
+
+ bool SetExpandAlloc(const std::string& option, const std::string& value);
+
+ bool SetFreeTrack(const std::string& option, const std::string& value);
+ bool SetFreeTrackBacktraceNumFrames(const std::string& option, const std::string& value);
+
+ bool SetRecordAllocs(const std::string& option, const std::string& value);
+ bool SetRecordAllocsFile(const std::string& option, const std::string& value);
+
+ bool VerifyValueEmpty(const std::string& option, const std::string& value);
+
+ static bool GetOption(const char** option_str, std::string* option, std::string* value);
+
+ const static std::unordered_map<std::string, OptionInfo> kOptions;
+
+ size_t front_guard_bytes_ = 0;
+ size_t rear_guard_bytes_ = 0;
+
+ bool backtrace_enable_on_signal_ = false;
+ int backtrace_signal_ = 0;
+ bool backtrace_enabled_ = false;
+ size_t backtrace_frames_ = 0;
+
+ size_t fill_on_alloc_bytes_ = 0;
+ size_t fill_on_free_bytes_ = 0;
+
+ size_t expand_alloc_bytes_ = 0;
+
+ size_t free_track_allocations_ = 0;
+ size_t free_track_backtrace_num_frames_ = 0;
+
+ int record_allocs_signal_ = 0;
+ size_t record_allocs_num_entries_ = 0;
+ std::string record_allocs_file_;
+
+ uint64_t options_ = 0;
+ uint8_t fill_alloc_value_;
+ uint8_t fill_free_value_;
+ uint8_t front_guard_value_;
+ uint8_t rear_guard_value_;
};
#endif // MALLOC_DEBUG_CONFIG_H
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index 339efdf..e9974d7 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -38,54 +38,54 @@
#include "TrackData.h"
bool DebugData::Initialize(const char* options) {
- if (!config_.Set(options)) {
+ if (!config_.Init(options)) {
return false;
}
// Check to see if the options that require a header are enabled.
- if (config_.options & HEADER_OPTIONS) {
+ if (config_.options() & HEADER_OPTIONS) {
need_header_ = true;
// Initialize all of the static header offsets.
pointer_offset_ = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
- if (config_.options & BACKTRACE) {
+ if (config_.options() & BACKTRACE) {
backtrace.reset(new BacktraceData(this, config_, &pointer_offset_));
if (!backtrace->Initialize(config_)) {
return false;
}
}
- if (config_.options & FRONT_GUARD) {
+ if (config_.options() & FRONT_GUARD) {
front_guard.reset(new FrontGuardData(this, config_, &pointer_offset_));
}
extra_bytes_ = pointer_offset_;
// Initialize all of the non-header data.
- if (config_.options & REAR_GUARD) {
+ if (config_.options() & REAR_GUARD) {
rear_guard.reset(new RearGuardData(this, config_));
- extra_bytes_ += config_.rear_guard_bytes;
+ extra_bytes_ += config_.rear_guard_bytes();
}
- if (config_.options & FREE_TRACK) {
+ if (config_.options() & FREE_TRACK) {
free_track.reset(new FreeTrackData(this, config_));
}
- if (config_.options & TRACK_ALLOCS) {
+ if (config_.options() & TRACK_ALLOCS) {
track.reset(new TrackData(this));
}
}
- if (config_.options & RECORD_ALLOCS) {
+ if (config_.options() & RECORD_ALLOCS) {
record.reset(new RecordData());
if (!record->Initialize(config_)) {
return false;
}
}
- if (config_.options & EXPAND_ALLOC) {
- extra_bytes_ += config_.expand_alloc_bytes;
+ if (config_.options() & EXPAND_ALLOC) {
+ extra_bytes_ += config_.expand_alloc_bytes();
}
return true;
}
diff --git a/libc/malloc_debug/FreeTrackData.cpp b/libc/malloc_debug/FreeTrackData.cpp
index 8e6502e..e8e7a67 100644
--- a/libc/malloc_debug/FreeTrackData.cpp
+++ b/libc/malloc_debug/FreeTrackData.cpp
@@ -37,15 +37,15 @@
#include "malloc_debug.h"
FreeTrackData::FreeTrackData(DebugData* debug, const Config& config)
- : OptionData(debug), backtrace_num_frames_(config.free_track_backtrace_num_frames) {
+ : OptionData(debug), backtrace_num_frames_(config.free_track_backtrace_num_frames()) {
cmp_mem_.resize(4096);
- memset(cmp_mem_.data(), config.fill_free_value, cmp_mem_.size());
+ memset(cmp_mem_.data(), config.fill_free_value(), cmp_mem_.size());
}
void FreeTrackData::LogFreeError(const Header* header, const uint8_t* pointer) {
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p USED AFTER FREE", pointer);
- uint8_t fill_free_value = debug_->config().fill_free_value;
+ uint8_t fill_free_value = debug_->config().fill_free_value();
for (size_t i = 0; i < header->usable_size; i++) {
if (pointer[i] != fill_free_value) {
error_log(" allocation[%zu] = 0x%02x (expected 0x%02x)", i, pointer[i], fill_free_value);
@@ -69,8 +69,8 @@
} else {
const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
size_t bytes = header->usable_size;
- bytes = (bytes < debug_->config().fill_on_free_bytes) ? bytes
- : debug_->config().fill_on_free_bytes;
+ bytes = (bytes < debug_->config().fill_on_free_bytes()) ? bytes
+ : debug_->config().fill_on_free_bytes();
while (bytes > 0) {
size_t bytes_to_cmp = (bytes < cmp_mem_.size()) ? bytes : cmp_mem_.size();
if (memcmp(memory, cmp_mem_.data(), bytes_to_cmp) != 0) {
@@ -92,7 +92,7 @@
void FreeTrackData::Add(const Header* header) {
pthread_mutex_lock(&mutex_);
- if (list_.size() == debug_->config().free_track_allocations) {
+ if (list_.size() == debug_->config().free_track_allocations()) {
const Header* old_header = list_.back();
VerifyAndFree(old_header);
list_.pop_back();
diff --git a/libc/malloc_debug/FreeTrackData.h b/libc/malloc_debug/FreeTrackData.h
index 21f845f..1758ef5 100644
--- a/libc/malloc_debug/FreeTrackData.h
+++ b/libc/malloc_debug/FreeTrackData.h
@@ -42,7 +42,7 @@
// Forward declarations.
struct BacktraceHeader;
-struct Config;
+class Config;
class DebugData;
struct Header;
diff --git a/libc/malloc_debug/GuardData.cpp b/libc/malloc_debug/GuardData.cpp
index e207b86..d6cef85 100644
--- a/libc/malloc_debug/GuardData.cpp
+++ b/libc/malloc_debug/GuardData.cpp
@@ -70,13 +70,13 @@
}
FrontGuardData::FrontGuardData(DebugData* debug_data, const Config& config, size_t* offset)
- : GuardData(debug_data, config.front_guard_value, config.front_guard_bytes) {
+ : GuardData(debug_data, config.front_guard_value(), config.front_guard_bytes()) {
// Create a buffer for fast comparisons of the front guard.
- cmp_mem_.resize(config.front_guard_bytes);
- memset(cmp_mem_.data(), config.front_guard_value, cmp_mem_.size());
+ cmp_mem_.resize(config.front_guard_bytes());
+ memset(cmp_mem_.data(), config.front_guard_value(), cmp_mem_.size());
// Assumes that front_bytes is a multiple of MINIMUM_ALIGNMENT_BYTES.
offset_ = *offset;
- *offset += config.front_guard_bytes;
+ *offset += config.front_guard_bytes();
}
bool FrontGuardData::Valid(const Header* header) {
@@ -88,7 +88,7 @@
}
RearGuardData::RearGuardData(DebugData* debug_data, const Config& config)
- : GuardData(debug_data, config.rear_guard_value, config.rear_guard_bytes) {
+ : GuardData(debug_data, config.rear_guard_value(), config.rear_guard_bytes()) {
}
bool RearGuardData::Valid(const Header* header) {
diff --git a/libc/malloc_debug/GuardData.h b/libc/malloc_debug/GuardData.h
index bfb3949..ddf6ce1 100644
--- a/libc/malloc_debug/GuardData.h
+++ b/libc/malloc_debug/GuardData.h
@@ -41,7 +41,7 @@
// Forward declarations.
class DebugData;
struct Header;
-struct Config;
+class Config;
class GuardData : public OptionData {
public:
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index c0f3486..5a68deb 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -185,20 +185,20 @@
dump_act.sa_sigaction = RecordDump;
dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&dump_act.sa_mask);
- if (sigaction(config.record_allocs_signal, &dump_act, nullptr) != 0) {
+ if (sigaction(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
error_log("Unable to set up record dump signal function: %s", strerror(errno));
return false;
}
pthread_setspecific(key_, nullptr);
info_log("%s: Run: 'kill -%d %d' to dump the allocation records.", getprogname(),
- config.record_allocs_signal, getpid());
+ config.record_allocs_signal(), getpid());
- num_entries_ = config.record_allocs_num_entries;
+ num_entries_ = config.record_allocs_num_entries();
entries_ = new const RecordEntry*[num_entries_];
cur_index_ = 0;
dump_ = false;
- dump_file_ = config.record_allocs_file;
+ dump_file_ = config.record_allocs_file();
return true;
}
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index 741afd5..6e19923 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -144,7 +144,7 @@
DISALLOW_COPY_AND_ASSIGN(MemalignEntry);
};
-struct Config;
+class Config;
class RecordData {
public:
diff --git a/libc/malloc_debug/TrackData.cpp b/libc/malloc_debug/TrackData.cpp
index d4064f8..7ce477c 100644
--- a/libc/malloc_debug/TrackData.cpp
+++ b/libc/malloc_debug/TrackData.cpp
@@ -92,7 +92,7 @@
for (const auto& header : list) {
error_log("+++ %s leaked block of size %zu at %p (leak %zu of %zu)", getprogname(),
header->real_size(), debug_->GetPointer(header), ++track_count, list.size());
- if (debug_->config().options & BACKTRACE) {
+ if (debug_->config().options() & BACKTRACE) {
BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
error_log("Backtrace at time of allocation:");
@@ -111,7 +111,7 @@
return;
}
- *backtrace_size = debug_->config().backtrace_frames;
+ *backtrace_size = debug_->config().backtrace_frames();
*info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size;
*info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, total_backtrace_allocs_));
if (*info == nullptr) {
diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h
index fcd8f2a..e4c8951 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -41,7 +41,7 @@
// Forward declarations.
struct Header;
-struct Config;
+class Config;
class DebugData;
class TrackData : public OptionData {
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index bb16faa..addb5d4 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -118,7 +118,7 @@
error_log(LOG_DIVIDER);
if (header->tag == DEBUG_FREE_TAG) {
error_log("+++ ALLOCATION %p USED AFTER FREE (%s)", pointer, name);
- if (g_debug->config().options & FREE_TRACK) {
+ if (g_debug->config().options() & FREE_TRACK) {
g_debug->free_track->LogBacktrace(header);
}
} else {
@@ -147,32 +147,32 @@
header->usable_size -= g_debug->pointer_offset() +
reinterpret_cast<uintptr_t>(header) - reinterpret_cast<uintptr_t>(orig_pointer);
- if (g_debug->config().options & FRONT_GUARD) {
+ if (g_debug->config().options() & FRONT_GUARD) {
uint8_t* guard = g_debug->GetFrontGuard(header);
- memset(guard, g_debug->config().front_guard_value, g_debug->config().front_guard_bytes);
+ memset(guard, g_debug->config().front_guard_value(), g_debug->config().front_guard_bytes());
}
- if (g_debug->config().options & REAR_GUARD) {
+ if (g_debug->config().options() & REAR_GUARD) {
uint8_t* guard = g_debug->GetRearGuard(header);
- memset(guard, g_debug->config().rear_guard_value, g_debug->config().rear_guard_bytes);
+ memset(guard, g_debug->config().rear_guard_value(), g_debug->config().rear_guard_bytes());
// If the rear guard is enabled, set the usable size to the exact size
// of the allocation.
header->usable_size = header->real_size();
}
bool backtrace_found = false;
- if (g_debug->config().options & BACKTRACE) {
+ if (g_debug->config().options() & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
if (g_debug->backtrace->enabled()) {
back_header->num_frames = backtrace_get(
- &back_header->frames[0], g_debug->config().backtrace_frames);
+ &back_header->frames[0], g_debug->config().backtrace_frames());
backtrace_found = back_header->num_frames > 0;
} else {
back_header->num_frames = 0;
}
}
- if (g_debug->config().options & TRACK_ALLOCS) {
+ if (g_debug->config().options() & TRACK_ALLOCS) {
g_debug->track->Add(header, backtrace_found);
}
@@ -215,11 +215,11 @@
return;
}
- if (g_debug->config().options & FREE_TRACK) {
+ if (g_debug->config().options() & FREE_TRACK) {
g_debug->free_track->VerifyAll();
}
- if (g_debug->config().options & LEAK_TRACK) {
+ if (g_debug->config().options() & LEAK_TRACK) {
g_debug->track->DisplayLeaks();
}
@@ -250,7 +250,7 @@
*total_memory = 0;
*backtrace_size = 0;
- if (!(g_debug->config().options & BACKTRACE)) {
+ if (!(g_debug->config().options() & BACKTRACE)) {
error_log("get_malloc_leak_info: Allocations not being tracked, to enable "
"set the option 'backtrace'.");
return;
@@ -315,11 +315,11 @@
pointer = g_dispatch->malloc(real_size);
}
- if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
+ if (pointer != nullptr && g_debug->config().options() & FILL_ON_ALLOC) {
size_t bytes = internal_malloc_usable_size(pointer);
- size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
+ size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
- memset(pointer, g_debug->config().fill_alloc_value, bytes);
+ memset(pointer, g_debug->config().fill_alloc_value(), bytes);
}
return pointer;
}
@@ -332,7 +332,7 @@
void* pointer = internal_malloc(size);
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new MallocEntry(pointer, size));
}
@@ -351,20 +351,20 @@
}
free_pointer = header->orig_pointer;
- if (g_debug->config().options & FRONT_GUARD) {
+ if (g_debug->config().options() & FRONT_GUARD) {
if (!g_debug->front_guard->Valid(header)) {
g_debug->front_guard->LogFailure(header);
}
}
- if (g_debug->config().options & REAR_GUARD) {
+ if (g_debug->config().options() & REAR_GUARD) {
if (!g_debug->rear_guard->Valid(header)) {
g_debug->rear_guard->LogFailure(header);
}
}
- if (g_debug->config().options & TRACK_ALLOCS) {
+ if (g_debug->config().options() & TRACK_ALLOCS) {
bool backtrace_found = false;
- if (g_debug->config().options & BACKTRACE) {
+ if (g_debug->config().options() & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
backtrace_found = back_header->num_frames > 0;
}
@@ -377,13 +377,13 @@
bytes = g_dispatch->malloc_usable_size(pointer);
}
- if (g_debug->config().options & FILL_ON_FREE) {
- size_t fill_bytes = g_debug->config().fill_on_free_bytes;
+ if (g_debug->config().options() & FILL_ON_FREE) {
+ size_t fill_bytes = g_debug->config().fill_on_free_bytes();
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
- memset(pointer, g_debug->config().fill_free_value, bytes);
+ memset(pointer, g_debug->config().fill_free_value(), bytes);
}
- if (g_debug->config().options & FREE_TRACK) {
+ if (g_debug->config().options() & FREE_TRACK) {
// Do not add the allocation until we are done modifying the pointer
// itself. This avoids a race if a lot of threads are all doing
// frees at the same time and we wind up trying to really free this
@@ -401,7 +401,7 @@
}
ScopedDisableDebugCalls disable;
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new FreeEntry(pointer));
}
@@ -466,14 +466,14 @@
pointer = g_dispatch->memalign(alignment, real_size);
}
- if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
+ if (pointer != nullptr && g_debug->config().options() & FILL_ON_ALLOC) {
size_t bytes = internal_malloc_usable_size(pointer);
- size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
+ size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
- memset(pointer, g_debug->config().fill_alloc_value, bytes);
+ memset(pointer, g_debug->config().fill_alloc_value(), bytes);
}
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
}
@@ -488,14 +488,14 @@
if (pointer == nullptr) {
pointer = internal_malloc(bytes);
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
}
return pointer;
}
if (bytes == 0) {
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
}
@@ -504,8 +504,8 @@
}
size_t real_size = bytes;
- if (g_debug->config().options & EXPAND_ALLOC) {
- real_size += g_debug->config().expand_alloc_bytes;
+ if (g_debug->config().options() & EXPAND_ALLOC) {
+ real_size += g_debug->config().expand_alloc_bytes();
if (real_size < bytes) {
// Overflow.
errno = ENOMEM;
@@ -539,12 +539,12 @@
if (*g_malloc_zygote_child) {
header->set_zygote();
}
- if (g_debug->config().options & REAR_GUARD) {
+ if (g_debug->config().options() & REAR_GUARD) {
// Don't bother allocating a smaller pointer in this case, simply
// change the header usable_size and reset the rear guard.
header->usable_size = header->real_size();
- memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value,
- g_debug->config().rear_guard_bytes);
+ memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value(),
+ g_debug->config().rear_guard_bytes());
}
// Do not bother recording, this is essentially a nop.
return pointer;
@@ -568,18 +568,18 @@
}
}
- if (g_debug->config().options & FILL_ON_ALLOC) {
+ if (g_debug->config().options() & FILL_ON_ALLOC) {
size_t bytes = internal_malloc_usable_size(new_pointer);
- if (bytes > g_debug->config().fill_on_alloc_bytes) {
- bytes = g_debug->config().fill_on_alloc_bytes;
+ if (bytes > g_debug->config().fill_on_alloc_bytes()) {
+ bytes = g_debug->config().fill_on_alloc_bytes();
}
if (bytes > prev_size) {
memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size),
- g_debug->config().fill_alloc_value, bytes - prev_size);
+ g_debug->config().fill_alloc_value(), bytes - prev_size);
}
}
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
}
@@ -629,7 +629,7 @@
} else {
pointer = g_dispatch->calloc(1, real_size);
}
- if (g_debug->config().options & RECORD_ALLOCS) {
+ if (g_debug->config().options() & RECORD_ALLOCS) {
g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
}
return pointer;
@@ -668,7 +668,7 @@
const void* pointer = reinterpret_cast<void*>(base);
if (g_debug->need_header()) {
const Header* header = reinterpret_cast<const Header*>(pointer);
- if (g_debug->config().options & TRACK_ALLOCS) {
+ if (g_debug->config().options() & TRACK_ALLOCS) {
if (g_debug->track->Contains(header)) {
// Return just the body of the allocation if we're sure the header exists
ctx->callback(reinterpret_cast<uintptr_t>(g_debug->GetPointer(header)),
@@ -704,7 +704,7 @@
if (g_debug->need_header()) {
Header* header;
- if (g_debug->config().options & TRACK_ALLOCS) {
+ if (g_debug->config().options() & TRACK_ALLOCS) {
header = g_debug->GetHeader(pointer);
if (!g_debug->track->Contains(header)) {
return 0;
@@ -715,7 +715,7 @@
if (header->tag != DEBUG_TAG) {
return 0;
}
- if (g_debug->config().options & BACKTRACE) {
+ if (g_debug->config().options() & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
if (frame_count > back_header->num_frames) {
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index f988124..77dc848 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -31,14 +31,11 @@
resetLogs();
}
- void TearDown() override {
- }
-
std::unique_ptr<Config> config;
bool InitConfig(const char* options) {
config.reset(new Config);
- return config->Set(options);
+ return config->Init(options);
}
};
@@ -201,8 +198,8 @@
TEST_F(MallocDebugConfigTest, space_before_equal) {
ASSERT_TRUE(InitConfig("backtrace =10")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(10U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(10U, config->backtrace_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -210,8 +207,8 @@
TEST_F(MallocDebugConfigTest, space_after_equal) {
ASSERT_TRUE(InitConfig("backtrace= 10")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(10U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(10U, config->backtrace_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -219,8 +216,8 @@
TEST_F(MallocDebugConfigTest, extra_space) {
ASSERT_TRUE(InitConfig(" backtrace=64 ")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(64U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(64U, config->backtrace_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -228,9 +225,9 @@
TEST_F(MallocDebugConfigTest, multiple_options) {
ASSERT_TRUE(InitConfig(" backtrace=64 front_guard=48")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS | FRONT_GUARD, config->options);
- ASSERT_EQ(64U, config->backtrace_frames);
- ASSERT_EQ(48U, config->front_guard_bytes);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS | FRONT_GUARD, config->options());
+ ASSERT_EQ(64U, config->backtrace_frames());
+ ASSERT_EQ(48U, config->front_guard_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -238,24 +235,24 @@
TEST_F(MallocDebugConfigTest, front_guard) {
ASSERT_TRUE(InitConfig("front_guard=48")) << getFakeLogPrint();
- ASSERT_EQ(FRONT_GUARD, config->options);
- ASSERT_EQ(48U, config->front_guard_bytes);
+ ASSERT_EQ(FRONT_GUARD, config->options());
+ ASSERT_EQ(48U, config->front_guard_bytes());
ASSERT_TRUE(InitConfig("front_guard")) << getFakeLogPrint();
- ASSERT_EQ(FRONT_GUARD, config->options);
- ASSERT_EQ(32U, config->front_guard_bytes);
+ ASSERT_EQ(FRONT_GUARD, config->options());
+ ASSERT_EQ(32U, config->front_guard_bytes());
ASSERT_TRUE(InitConfig("front_guard=39")) << getFakeLogPrint();
- ASSERT_EQ(FRONT_GUARD, config->options);
+ ASSERT_EQ(FRONT_GUARD, config->options());
#if defined(__LP64__)
- ASSERT_EQ(48U, config->front_guard_bytes);
+ ASSERT_EQ(48U, config->front_guard_bytes());
#else
- ASSERT_EQ(40U, config->front_guard_bytes);
+ ASSERT_EQ(40U, config->front_guard_bytes());
#endif
ASSERT_TRUE(InitConfig("front_guard=41")) << getFakeLogPrint();
- ASSERT_EQ(FRONT_GUARD, config->options);
- ASSERT_EQ(48U, config->front_guard_bytes);
+ ASSERT_EQ(FRONT_GUARD, config->options());
+ ASSERT_EQ(48U, config->front_guard_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -263,12 +260,12 @@
TEST_F(MallocDebugConfigTest, rear_guard) {
ASSERT_TRUE(InitConfig("rear_guard=50")) << getFakeLogPrint();
- ASSERT_EQ(REAR_GUARD, config->options);
- ASSERT_EQ(50U, config->rear_guard_bytes);
+ ASSERT_EQ(REAR_GUARD, config->options());
+ ASSERT_EQ(50U, config->rear_guard_bytes());
ASSERT_TRUE(InitConfig("rear_guard")) << getFakeLogPrint();
- ASSERT_EQ(REAR_GUARD, config->options);
- ASSERT_EQ(32U, config->rear_guard_bytes);
+ ASSERT_EQ(REAR_GUARD, config->options());
+ ASSERT_EQ(32U, config->rear_guard_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -276,14 +273,14 @@
TEST_F(MallocDebugConfigTest, guard) {
ASSERT_TRUE(InitConfig("guard=32")) << getFakeLogPrint();
- ASSERT_EQ(FRONT_GUARD | REAR_GUARD, config->options);
- ASSERT_EQ(32U, config->front_guard_bytes);
- ASSERT_EQ(32U, config->rear_guard_bytes);
+ ASSERT_EQ(FRONT_GUARD | REAR_GUARD, config->options());
+ ASSERT_EQ(32U, config->front_guard_bytes());
+ ASSERT_EQ(32U, config->rear_guard_bytes());
ASSERT_TRUE(InitConfig("guard")) << getFakeLogPrint();
- ASSERT_EQ(FRONT_GUARD | REAR_GUARD, config->options);
- ASSERT_EQ(32U, config->front_guard_bytes);
- ASSERT_EQ(32U, config->rear_guard_bytes);
+ ASSERT_EQ(FRONT_GUARD | REAR_GUARD, config->options());
+ ASSERT_EQ(32U, config->front_guard_bytes());
+ ASSERT_EQ(32U, config->rear_guard_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -291,12 +288,16 @@
TEST_F(MallocDebugConfigTest, backtrace) {
ASSERT_TRUE(InitConfig("backtrace=64")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(64U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(64U, config->backtrace_frames());
+ ASSERT_TRUE(config->backtrace_enabled());
+ ASSERT_FALSE(config->backtrace_enable_on_signal());
ASSERT_TRUE(InitConfig("backtrace")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(16U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(16U, config->backtrace_frames());
+ ASSERT_TRUE(config->backtrace_enabled());
+ ASSERT_FALSE(config->backtrace_enable_on_signal());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -304,12 +305,50 @@
TEST_F(MallocDebugConfigTest, backtrace_enable_on_signal) {
ASSERT_TRUE(InitConfig("backtrace_enable_on_signal=64")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(64U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(64U, config->backtrace_frames());
+ ASSERT_FALSE(config->backtrace_enabled());
+ ASSERT_TRUE(config->backtrace_enable_on_signal());
ASSERT_TRUE(InitConfig("backtrace_enable_on_signal")) << getFakeLogPrint();
- ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options);
- ASSERT_EQ(16U, config->backtrace_frames);
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(16U, config->backtrace_frames());
+ ASSERT_FALSE(config->backtrace_enabled());
+ ASSERT_TRUE(config->backtrace_enable_on_signal());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_enable_on_signal_init) {
+ ASSERT_TRUE(InitConfig("backtrace_enable_on_signal=64")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(64U, config->backtrace_frames());
+ ASSERT_FALSE(config->backtrace_enabled());
+ ASSERT_TRUE(config->backtrace_enable_on_signal());
+
+ ASSERT_TRUE(InitConfig("backtrace")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(16U, config->backtrace_frames());
+ ASSERT_TRUE(config->backtrace_enabled());
+ ASSERT_FALSE(config->backtrace_enable_on_signal());
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_enable_and_backtrace) {
+ ASSERT_TRUE(InitConfig("backtrace_enable_on_signal backtrace")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(16U, config->backtrace_frames());
+ ASSERT_TRUE(config->backtrace_enabled());
+ ASSERT_TRUE(config->backtrace_enable_on_signal());
+
+ ASSERT_TRUE(InitConfig("backtrace backtrace_enable_on_signal")) << getFakeLogPrint();
+ ASSERT_EQ(BACKTRACE | TRACK_ALLOCS, config->options());
+ ASSERT_EQ(16U, config->backtrace_frames());
+ ASSERT_TRUE(config->backtrace_enabled());
+ ASSERT_TRUE(config->backtrace_enable_on_signal());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -317,12 +356,12 @@
TEST_F(MallocDebugConfigTest, fill_on_alloc) {
ASSERT_TRUE(InitConfig("fill_on_alloc=64")) << getFakeLogPrint();
- ASSERT_EQ(FILL_ON_ALLOC, config->options);
- ASSERT_EQ(64U, config->fill_on_alloc_bytes);
+ ASSERT_EQ(FILL_ON_ALLOC, config->options());
+ ASSERT_EQ(64U, config->fill_on_alloc_bytes());
ASSERT_TRUE(InitConfig("fill_on_alloc")) << getFakeLogPrint();
- ASSERT_EQ(FILL_ON_ALLOC, config->options);
- ASSERT_EQ(SIZE_MAX, config->fill_on_alloc_bytes);
+ ASSERT_EQ(FILL_ON_ALLOC, config->options());
+ ASSERT_EQ(SIZE_MAX, config->fill_on_alloc_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -330,12 +369,12 @@
TEST_F(MallocDebugConfigTest, fill_on_free) {
ASSERT_TRUE(InitConfig("fill_on_free=64")) << getFakeLogPrint();
- ASSERT_EQ(FILL_ON_FREE, config->options);
- ASSERT_EQ(64U, config->fill_on_free_bytes);
+ ASSERT_EQ(FILL_ON_FREE, config->options());
+ ASSERT_EQ(64U, config->fill_on_free_bytes());
ASSERT_TRUE(InitConfig("fill_on_free")) << getFakeLogPrint();
- ASSERT_EQ(FILL_ON_FREE, config->options);
- ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes);
+ ASSERT_EQ(FILL_ON_FREE, config->options());
+ ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -343,14 +382,14 @@
TEST_F(MallocDebugConfigTest, fill) {
ASSERT_TRUE(InitConfig("fill=64")) << getFakeLogPrint();
- ASSERT_EQ(FILL_ON_ALLOC | FILL_ON_FREE, config->options);
- ASSERT_EQ(64U, config->fill_on_alloc_bytes);
- ASSERT_EQ(64U, config->fill_on_free_bytes);
+ ASSERT_EQ(FILL_ON_ALLOC | FILL_ON_FREE, config->options());
+ ASSERT_EQ(64U, config->fill_on_alloc_bytes());
+ ASSERT_EQ(64U, config->fill_on_free_bytes());
ASSERT_TRUE(InitConfig("fill")) << getFakeLogPrint();
- ASSERT_EQ(FILL_ON_ALLOC | FILL_ON_FREE, config->options);
- ASSERT_EQ(SIZE_MAX, config->fill_on_alloc_bytes);
- ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes);
+ ASSERT_EQ(FILL_ON_ALLOC | FILL_ON_FREE, config->options());
+ ASSERT_EQ(SIZE_MAX, config->fill_on_alloc_bytes());
+ ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -358,12 +397,12 @@
TEST_F(MallocDebugConfigTest, expand_alloc) {
ASSERT_TRUE(InitConfig("expand_alloc=1234")) << getFakeLogPrint();
- ASSERT_EQ(EXPAND_ALLOC, config->options);
- ASSERT_EQ(1234U, config->expand_alloc_bytes);
+ ASSERT_EQ(EXPAND_ALLOC, config->options());
+ ASSERT_EQ(1234U, config->expand_alloc_bytes());
ASSERT_TRUE(InitConfig("expand_alloc")) << getFakeLogPrint();
- ASSERT_EQ(EXPAND_ALLOC, config->options);
- ASSERT_EQ(16U, config->expand_alloc_bytes);
+ ASSERT_EQ(EXPAND_ALLOC, config->options());
+ ASSERT_EQ(16U, config->expand_alloc_bytes());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -371,16 +410,16 @@
TEST_F(MallocDebugConfigTest, free_track) {
ASSERT_TRUE(InitConfig("free_track=1234")) << getFakeLogPrint();
- ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options);
- ASSERT_EQ(1234U, config->free_track_allocations);
- ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes);
- ASSERT_EQ(16U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(1234U, config->free_track_allocations());
+ ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
ASSERT_TRUE(InitConfig("free_track")) << getFakeLogPrint();
- ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options);
- ASSERT_EQ(100U, config->free_track_allocations);
- ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes);
- ASSERT_EQ(16U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(100U, config->free_track_allocations());
+ ASSERT_EQ(SIZE_MAX, config->fill_on_free_bytes());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -388,16 +427,23 @@
TEST_F(MallocDebugConfigTest, free_track_and_fill_on_free) {
ASSERT_TRUE(InitConfig("free_track=1234 fill_on_free=32")) << getFakeLogPrint();
- ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options);
- ASSERT_EQ(1234U, config->free_track_allocations);
- ASSERT_EQ(32U, config->fill_on_free_bytes);
- ASSERT_EQ(16U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(1234U, config->free_track_allocations());
+ ASSERT_EQ(32U, config->fill_on_free_bytes());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
ASSERT_TRUE(InitConfig("free_track fill_on_free=60")) << getFakeLogPrint();
- ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options);
- ASSERT_EQ(100U, config->free_track_allocations);
- ASSERT_EQ(60U, config->fill_on_free_bytes);
- ASSERT_EQ(16U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(100U, config->free_track_allocations());
+ ASSERT_EQ(60U, config->fill_on_free_bytes());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
+
+ // Now reverse the arguments.
+ ASSERT_TRUE(InitConfig("fill_on_free=32 free_track=1234")) << getFakeLogPrint();
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(1234U, config->free_track_allocations());
+ ASSERT_EQ(32U, config->fill_on_free_bytes());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -406,12 +452,12 @@
TEST_F(MallocDebugConfigTest, free_track_backtrace_num_frames) {
ASSERT_TRUE(InitConfig("free_track_backtrace_num_frames=123")) << getFakeLogPrint();
- ASSERT_EQ(0U, config->options);
- ASSERT_EQ(123U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(0U, config->options());
+ ASSERT_EQ(123U, config->free_track_backtrace_num_frames());
ASSERT_TRUE(InitConfig("free_track_backtrace_num_frames")) << getFakeLogPrint();
- ASSERT_EQ(0U, config->options);
- ASSERT_EQ(16U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(0U, config->options());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -420,8 +466,8 @@
TEST_F(MallocDebugConfigTest, free_track_backtrace_num_frames_zero) {
ASSERT_TRUE(InitConfig("free_track_backtrace_num_frames=0")) << getFakeLogPrint();
- ASSERT_EQ(0U, config->options);
- ASSERT_EQ(0U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(0U, config->options());
+ ASSERT_EQ(0U, config->free_track_backtrace_num_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -429,12 +475,12 @@
TEST_F(MallocDebugConfigTest, free_track_backtrace_num_frames_and_free_track) {
ASSERT_TRUE(InitConfig("free_track free_track_backtrace_num_frames=123")) << getFakeLogPrint();
- ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options);
- ASSERT_EQ(123U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(123U, config->free_track_backtrace_num_frames());
ASSERT_TRUE(InitConfig("free_track free_track_backtrace_num_frames")) << getFakeLogPrint();
- ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options);
- ASSERT_EQ(16U, config->free_track_backtrace_num_frames);
+ ASSERT_EQ(FREE_TRACK | FILL_ON_FREE, config->options());
+ ASSERT_EQ(16U, config->free_track_backtrace_num_frames());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -442,7 +488,7 @@
TEST_F(MallocDebugConfigTest, leak_track) {
ASSERT_TRUE(InitConfig("leak_track")) << getFakeLogPrint();
- ASSERT_EQ(LEAK_TRACK | TRACK_ALLOCS, config->options);
+ ASSERT_EQ(LEAK_TRACK | TRACK_ALLOCS, config->options());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -460,14 +506,14 @@
TEST_F(MallocDebugConfigTest, record_allocs) {
ASSERT_TRUE(InitConfig("record_allocs=1234")) << getFakeLogPrint();
- ASSERT_EQ(RECORD_ALLOCS, config->options);
- ASSERT_EQ(1234U, config->record_allocs_num_entries);
- ASSERT_STREQ("/data/local/tmp/record_allocs.txt", config->record_allocs_file.c_str());
+ ASSERT_EQ(RECORD_ALLOCS, config->options());
+ ASSERT_EQ(1234U, config->record_allocs_num_entries());
+ ASSERT_STREQ("/data/local/tmp/record_allocs.txt", config->record_allocs_file().c_str());
ASSERT_TRUE(InitConfig("record_allocs")) << getFakeLogPrint();
- ASSERT_EQ(RECORD_ALLOCS, config->options);
- ASSERT_EQ(8000000U, config->record_allocs_num_entries);
- ASSERT_STREQ("/data/local/tmp/record_allocs.txt", config->record_allocs_file.c_str());
+ ASSERT_EQ(RECORD_ALLOCS, config->options());
+ ASSERT_EQ(8000000U, config->record_allocs_num_entries());
+ ASSERT_STREQ("/data/local/tmp/record_allocs.txt", config->record_allocs_file().c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -475,10 +521,10 @@
TEST_F(MallocDebugConfigTest, record_allocs_file) {
ASSERT_TRUE(InitConfig("record_allocs=1234 record_allocs_file=/fake/file")) << getFakeLogPrint();
- ASSERT_STREQ("/fake/file", config->record_allocs_file.c_str());
+ ASSERT_STREQ("/fake/file", config->record_allocs_file().c_str());
ASSERT_TRUE(InitConfig("record_allocs_file")) << getFakeLogPrint();
- ASSERT_STREQ("/data/local/tmp/record_allocs.txt", config->record_allocs_file.c_str());
+ ASSERT_STREQ("/data/local/tmp/record_allocs.txt", config->record_allocs_file().c_str());
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());